target-arm queue:
* Correct handling of writes to CPSR from gdbstub in user mode
  * virt: lift maximum RAM limit to 255GB
  * sdhci: implement reset
  * virt: if booting in Secure mode, provide secure-only RAM, make first
    flash device secure-only, and assume the EL3 boot rom will handle PSCI
  * bcm2835: use explicit endianness accessors rather than ldl/stl_phys
  * support big-endian in system mode for ARM
  * implement SETEND instruction
  * arm_gic: implement the GICv2 GICC_DIR register
  * fix SRS bug: only trap from S-EL1 to EL3 if specified mode is Mon
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJW2XPNAAoJEDwlJe0UNgze3qgQAJI5tMud+PtKDF3B7hihlKAe
 Ffwn+OO/Pl3U7O2IcKw4qqRbze88e4rFHWtsPmKhId8iwvQ1xQ/bXUDE39F4zVFT
 p0Xp0hHpvM2DzUuuX1Y5wmypUAAuSdFe+6BiHa1AY93qzdTbx/5kmzJ2B0ML38pW
 c/igiOQZSQ3piKhHm6LvYNv5APMKq11+8qGlBqNootoUplnhEvEEgiqtiqat1KPI
 7fBzObFGu0OnMaD83yAUYS4+/dSke7Wxl2IW+sAkVZM0mylY8GmxdLFw1nnUh3UW
 HNCbKzaC3v2GwbtD7Ewc9ubD2vN6leSyYfzVJYWyCkT8awQdZp0f+3kIKlWg30uc
 VStrFNtzqhd5B/jJkynR7i2uJ7kXEcRdZi/FXF8jo+9RuxI6iJ0agVk5/rzznShz
 jscr2oIIw90lybDm7TQsWDXjpxo3khUBMYvGQ0iZ+IDHSbj2FGLB1W/V06Lxm4xM
 NU4FjHCXB2H501WAaglo6JKXMWLXhE1TprJwh4g9KYYSjsFNSxPw9fOOiecysZ2e
 FEJ8MbACV8IlGtG1AeNjM3ml2JMvKlBq/zifKYzXim8pAcgHgxSAaRMNGIUdN7DO
 I4lAHmqqOLLRaERzGQjemBOVvXpDHPqlocfzo9awqAouz3K3tv1NKRaRatd4P4kw
 opE0lOV70ecHMcjelg12
 =6cP7
 -----END PGP SIGNATURE-----
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20160304' into staging
target-arm queue:
 * Correct handling of writes to CPSR from gdbstub in user mode
 * virt: lift maximum RAM limit to 255GB
 * sdhci: implement reset
 * virt: if booting in Secure mode, provide secure-only RAM, make first
   flash device secure-only, and assume the EL3 boot rom will handle PSCI
 * bcm2835: use explicit endianness accessors rather than ldl/stl_phys
 * support big-endian in system mode for ARM
 * implement SETEND instruction
 * arm_gic: implement the GICv2 GICC_DIR register
 * fix SRS bug: only trap from S-EL1 to EL3 if specified mode is Mon
# gpg: Signature made Fri 04 Mar 2016 11:38:53 GMT using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
* remotes/pmaydell/tags/pull-target-arm-20160304: (30 commits)
  target-arm: Only trap SRS from S-EL1 if specified mode is MON
  hw/intc/arm_gic.c: Implement GICv2 GICC_DIR
  arm: boot: Support big-endian elfs
  loader: Add data swap option to load-elf
  loader: load_elf(): Add doc comment
  loader: add API to load elf header
  target-arm: implement BE32 mode in system emulation
  target-arm: implement setend
  target-arm: introduce tbflag for endianness
  target-arm: a64: Add endianness support
  target-arm: introduce disas flag for endianness
  target-arm: pass DisasContext to gen_aa32_ld*/st*
  target-arm: implement SCTLR.EE
  linux-user: arm: handle CPSR.E correctly in strex emulation
  linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode
  arm: cpu: handle BE32 user-mode as BE
  target-arm: cpu: Move cpu_is_big_endian to header
  target-arm: implement SCTLR.B, drop bswap_code
  linux-user: arm: pass env to get_user_code_*
  linux-user: arm: fix coding style for some linux-user signal functions
  ...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
			
			
This commit is contained in:
		
						commit
						3c0f12df65
					
				@ -111,7 +111,7 @@ static void clipper_init(MachineState *machine)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
 | 
					    size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
 | 
				
			||||||
                    NULL, &palcode_entry, &palcode_low, &palcode_high,
 | 
					                    NULL, &palcode_entry, &palcode_low, &palcode_high,
 | 
				
			||||||
                    0, EM_ALPHA, 0);
 | 
					                    0, EM_ALPHA, 0, 0);
 | 
				
			||||||
    if (size < 0) {
 | 
					    if (size < 0) {
 | 
				
			||||||
        error_report("could not load palcode '%s'", palcode_filename);
 | 
					        error_report("could not load palcode '%s'", palcode_filename);
 | 
				
			||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
@ -131,7 +131,7 @@ static void clipper_init(MachineState *machine)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
 | 
					        size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
 | 
				
			||||||
                        NULL, &kernel_entry, &kernel_low, &kernel_high,
 | 
					                        NULL, &kernel_entry, &kernel_low, &kernel_high,
 | 
				
			||||||
                        0, EM_ALPHA, 0);
 | 
					                        0, EM_ALPHA, 0, 0);
 | 
				
			||||||
        if (size < 0) {
 | 
					        if (size < 0) {
 | 
				
			||||||
            error_report("could not load kernel '%s'", kernel_filename);
 | 
					            error_report("could not load kernel '%s'", kernel_filename);
 | 
				
			||||||
            exit(1);
 | 
					            exit(1);
 | 
				
			||||||
 | 
				
			|||||||
@ -211,7 +211,7 @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (kernel_filename) {
 | 
					    if (kernel_filename) {
 | 
				
			||||||
        image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
 | 
					        image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
 | 
				
			||||||
                              NULL, big_endian, EM_ARM, 1);
 | 
					                              NULL, big_endian, EM_ARM, 1, 0);
 | 
				
			||||||
        if (image_size < 0) {
 | 
					        if (image_size < 0) {
 | 
				
			||||||
            image_size = load_image_targphys(kernel_filename, 0, mem_size);
 | 
					            image_size = load_image_targphys(kernel_filename, 0, mem_size);
 | 
				
			||||||
            lowaddr = 0;
 | 
					            lowaddr = 0;
 | 
				
			||||||
 | 
				
			|||||||
@ -518,9 +518,34 @@ static void do_cpu_reset(void *opaque)
 | 
				
			|||||||
    cpu_reset(cs);
 | 
					    cpu_reset(cs);
 | 
				
			||||||
    if (info) {
 | 
					    if (info) {
 | 
				
			||||||
        if (!info->is_linux) {
 | 
					        if (!info->is_linux) {
 | 
				
			||||||
 | 
					            int i;
 | 
				
			||||||
            /* Jump to the entry point.  */
 | 
					            /* Jump to the entry point.  */
 | 
				
			||||||
            uint64_t entry = info->entry;
 | 
					            uint64_t entry = info->entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            switch (info->endianness) {
 | 
				
			||||||
 | 
					            case ARM_ENDIANNESS_LE:
 | 
				
			||||||
 | 
					                env->cp15.sctlr_el[1] &= ~SCTLR_E0E;
 | 
				
			||||||
 | 
					                for (i = 1; i < 4; ++i) {
 | 
				
			||||||
 | 
					                    env->cp15.sctlr_el[i] &= ~SCTLR_EE;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                env->uncached_cpsr &= ~CPSR_E;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case ARM_ENDIANNESS_BE8:
 | 
				
			||||||
 | 
					                env->cp15.sctlr_el[1] |= SCTLR_E0E;
 | 
				
			||||||
 | 
					                for (i = 1; i < 4; ++i) {
 | 
				
			||||||
 | 
					                    env->cp15.sctlr_el[i] |= SCTLR_EE;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                env->uncached_cpsr |= CPSR_E;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case ARM_ENDIANNESS_BE32:
 | 
				
			||||||
 | 
					                env->cp15.sctlr_el[1] |= SCTLR_B;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case ARM_ENDIANNESS_UNKNOWN:
 | 
				
			||||||
 | 
					                break; /* Board's decision */
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                g_assert_not_reached();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!env->aarch64) {
 | 
					            if (!env->aarch64) {
 | 
				
			||||||
                env->thumb = info->entry & 1;
 | 
					                env->thumb = info->entry & 1;
 | 
				
			||||||
                entry &= 0xfffffffe;
 | 
					                entry &= 0xfffffffe;
 | 
				
			||||||
@ -638,6 +663,62 @@ static int do_arm_linux_init(Object *obj, void *opaque)
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
 | 
				
			||||||
 | 
					                             uint64_t *lowaddr, uint64_t *highaddr,
 | 
				
			||||||
 | 
					                             int elf_machine)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    bool elf_is64;
 | 
				
			||||||
 | 
					    union {
 | 
				
			||||||
 | 
					        Elf32_Ehdr h32;
 | 
				
			||||||
 | 
					        Elf64_Ehdr h64;
 | 
				
			||||||
 | 
					    } elf_header;
 | 
				
			||||||
 | 
					    int data_swab = 0;
 | 
				
			||||||
 | 
					    bool big_endian;
 | 
				
			||||||
 | 
					    uint64_t ret = -1;
 | 
				
			||||||
 | 
					    Error *err = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    load_elf_hdr(info->kernel_filename, &elf_header, &elf_is64, &err);
 | 
				
			||||||
 | 
					    if (err) {
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (elf_is64) {
 | 
				
			||||||
 | 
					        big_endian = elf_header.h64.e_ident[EI_DATA] == ELFDATA2MSB;
 | 
				
			||||||
 | 
					        info->endianness = big_endian ? ARM_ENDIANNESS_BE8
 | 
				
			||||||
 | 
					                                      : ARM_ENDIANNESS_LE;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        big_endian = elf_header.h32.e_ident[EI_DATA] == ELFDATA2MSB;
 | 
				
			||||||
 | 
					        if (big_endian) {
 | 
				
			||||||
 | 
					            if (bswap32(elf_header.h32.e_flags) & EF_ARM_BE8) {
 | 
				
			||||||
 | 
					                info->endianness = ARM_ENDIANNESS_BE8;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                info->endianness = ARM_ENDIANNESS_BE32;
 | 
				
			||||||
 | 
					                /* In BE32, the CPU has a different view of the per-byte
 | 
				
			||||||
 | 
					                 * address map than the rest of the system. BE32 ELF files
 | 
				
			||||||
 | 
					                 * are organised such that they can be programmed through
 | 
				
			||||||
 | 
					                 * the CPU's per-word byte-reversed view of the world. QEMU
 | 
				
			||||||
 | 
					                 * however loads ELF files independently of the CPU. So
 | 
				
			||||||
 | 
					                 * tell the ELF loader to byte reverse the data for us.
 | 
				
			||||||
 | 
					                 */
 | 
				
			||||||
 | 
					                data_swab = 2;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            info->endianness = ARM_ENDIANNESS_LE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = load_elf(info->kernel_filename, NULL, NULL,
 | 
				
			||||||
 | 
					                   pentry, lowaddr, highaddr, big_endian, elf_machine,
 | 
				
			||||||
 | 
					                   1, data_swab);
 | 
				
			||||||
 | 
					    if (ret <= 0) {
 | 
				
			||||||
 | 
					        /* The header loaded but the image didn't */
 | 
				
			||||||
 | 
					        exit(1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void arm_load_kernel_notify(Notifier *notifier, void *data)
 | 
					static void arm_load_kernel_notify(Notifier *notifier, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CPUState *cs;
 | 
					    CPUState *cs;
 | 
				
			||||||
@ -647,7 +728,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
 | 
				
			|||||||
    uint64_t elf_entry, elf_low_addr, elf_high_addr;
 | 
					    uint64_t elf_entry, elf_low_addr, elf_high_addr;
 | 
				
			||||||
    int elf_machine;
 | 
					    int elf_machine;
 | 
				
			||||||
    hwaddr entry, kernel_load_offset;
 | 
					    hwaddr entry, kernel_load_offset;
 | 
				
			||||||
    int big_endian;
 | 
					 | 
				
			||||||
    static const ARMInsnFixup *primary_loader;
 | 
					    static const ARMInsnFixup *primary_loader;
 | 
				
			||||||
    ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
 | 
					    ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
 | 
				
			||||||
                                         notifier, notifier);
 | 
					                                         notifier, notifier);
 | 
				
			||||||
@ -733,12 +813,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
 | 
				
			|||||||
    if (info->nb_cpus == 0)
 | 
					    if (info->nb_cpus == 0)
 | 
				
			||||||
        info->nb_cpus = 1;
 | 
					        info->nb_cpus = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef TARGET_WORDS_BIGENDIAN
 | 
					 | 
				
			||||||
    big_endian = 1;
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
    big_endian = 0;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* We want to put the initrd far enough into RAM that when the
 | 
					    /* We want to put the initrd far enough into RAM that when the
 | 
				
			||||||
     * kernel is uncompressed it will not clobber the initrd. However
 | 
					     * kernel is uncompressed it will not clobber the initrd. However
 | 
				
			||||||
     * on boards without much RAM we must ensure that we still leave
 | 
					     * on boards without much RAM we must ensure that we still leave
 | 
				
			||||||
@ -753,9 +827,8 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
 | 
				
			|||||||
        MIN(info->ram_size / 2, 128 * 1024 * 1024);
 | 
					        MIN(info->ram_size / 2, 128 * 1024 * 1024);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Assume that raw images are linux kernels, and ELF images are not.  */
 | 
					    /* Assume that raw images are linux kernels, and ELF images are not.  */
 | 
				
			||||||
    kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
 | 
					    kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
 | 
				
			||||||
                           &elf_low_addr, &elf_high_addr, big_endian,
 | 
					                               &elf_high_addr, elf_machine);
 | 
				
			||||||
                           elf_machine, 1);
 | 
					 | 
				
			||||||
    if (kernel_size > 0 && have_dtb(info)) {
 | 
					    if (kernel_size > 0 && have_dtb(info)) {
 | 
				
			||||||
        /* If there is still some room left at the base of RAM, try and put
 | 
					        /* If there is still some room left at the base of RAM, try and put
 | 
				
			||||||
         * the DTB there like we do for images loaded with -bios or -pflash.
 | 
					         * the DTB there like we do for images loaded with -bios or -pflash.
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										148
									
								
								hw/arm/virt.c
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								hw/arm/virt.c
									
									
									
									
									
								
							@ -73,6 +73,7 @@ typedef struct VirtBoardInfo {
 | 
				
			|||||||
    uint32_t clock_phandle;
 | 
					    uint32_t clock_phandle;
 | 
				
			||||||
    uint32_t gic_phandle;
 | 
					    uint32_t gic_phandle;
 | 
				
			||||||
    uint32_t v2m_phandle;
 | 
					    uint32_t v2m_phandle;
 | 
				
			||||||
 | 
					    bool using_psci;
 | 
				
			||||||
} VirtBoardInfo;
 | 
					} VirtBoardInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
@ -95,6 +96,23 @@ typedef struct {
 | 
				
			|||||||
#define VIRT_MACHINE_CLASS(klass) \
 | 
					#define VIRT_MACHINE_CLASS(klass) \
 | 
				
			||||||
    OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE)
 | 
					    OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* RAM limit in GB. Since VIRT_MEM starts at the 1GB mark, this means
 | 
				
			||||||
 | 
					 * RAM can go up to the 256GB mark, leaving 256GB of the physical
 | 
				
			||||||
 | 
					 * address space unallocated and free for future use between 256G and 512G.
 | 
				
			||||||
 | 
					 * If we need to provide more RAM to VMs in the future then we need to:
 | 
				
			||||||
 | 
					 *  * allocate a second bank of RAM starting at 2TB and working up
 | 
				
			||||||
 | 
					 *  * fix the DT and ACPI table generation code in QEMU to correctly
 | 
				
			||||||
 | 
					 *    report two split lumps of RAM to the guest
 | 
				
			||||||
 | 
					 *  * fix KVM in the host kernel to allow guests with >40 bit address spaces
 | 
				
			||||||
 | 
					 * (We don't want to fill all the way up to 512GB with RAM because
 | 
				
			||||||
 | 
					 * we might want it for non-RAM purposes later. Conversely it seems
 | 
				
			||||||
 | 
					 * reasonable to assume that anybody configuring a VM with a quarter
 | 
				
			||||||
 | 
					 * of a terabyte of RAM will be doing it on a host with more than a
 | 
				
			||||||
 | 
					 * terabyte of physical address space.)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define RAMLIMIT_GB 255
 | 
				
			||||||
 | 
					#define RAMLIMIT_BYTES (RAMLIMIT_GB * 1024ULL * 1024 * 1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Addresses and sizes of our components.
 | 
					/* Addresses and sizes of our components.
 | 
				
			||||||
 * 0..128MB is space for a flash device so we can run bootrom code such as UEFI.
 | 
					 * 0..128MB is space for a flash device so we can run bootrom code such as UEFI.
 | 
				
			||||||
 * 128MB..256MB is used for miscellaneous device I/O.
 | 
					 * 128MB..256MB is used for miscellaneous device I/O.
 | 
				
			||||||
@ -127,10 +145,11 @@ static const MemMapEntry a15memmap[] = {
 | 
				
			|||||||
    [VIRT_MMIO] =               { 0x0a000000, 0x00000200 },
 | 
					    [VIRT_MMIO] =               { 0x0a000000, 0x00000200 },
 | 
				
			||||||
    /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
 | 
					    /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
 | 
				
			||||||
    [VIRT_PLATFORM_BUS] =       { 0x0c000000, 0x02000000 },
 | 
					    [VIRT_PLATFORM_BUS] =       { 0x0c000000, 0x02000000 },
 | 
				
			||||||
 | 
					    [VIRT_SECURE_MEM] =         { 0x0e000000, 0x01000000 },
 | 
				
			||||||
    [VIRT_PCIE_MMIO] =          { 0x10000000, 0x2eff0000 },
 | 
					    [VIRT_PCIE_MMIO] =          { 0x10000000, 0x2eff0000 },
 | 
				
			||||||
    [VIRT_PCIE_PIO] =           { 0x3eff0000, 0x00010000 },
 | 
					    [VIRT_PCIE_PIO] =           { 0x3eff0000, 0x00010000 },
 | 
				
			||||||
    [VIRT_PCIE_ECAM] =          { 0x3f000000, 0x01000000 },
 | 
					    [VIRT_PCIE_ECAM] =          { 0x3f000000, 0x01000000 },
 | 
				
			||||||
    [VIRT_MEM] =                { 0x40000000, 30ULL * 1024 * 1024 * 1024 },
 | 
					    [VIRT_MEM] =                { 0x40000000, RAMLIMIT_BYTES },
 | 
				
			||||||
    /* Second PCIe window, 512GB wide at the 512GB boundary */
 | 
					    /* Second PCIe window, 512GB wide at the 512GB boundary */
 | 
				
			||||||
    [VIRT_PCIE_MMIO_HIGH] =   { 0x8000000000ULL, 0x8000000000ULL },
 | 
					    [VIRT_PCIE_MMIO_HIGH] =   { 0x8000000000ULL, 0x8000000000ULL },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -230,6 +249,10 @@ static void fdt_add_psci_node(const VirtBoardInfo *vbi)
 | 
				
			|||||||
    void *fdt = vbi->fdt;
 | 
					    void *fdt = vbi->fdt;
 | 
				
			||||||
    ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
 | 
					    ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!vbi->using_psci) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_fdt_add_subnode(fdt, "/psci");
 | 
					    qemu_fdt_add_subnode(fdt, "/psci");
 | 
				
			||||||
    if (armcpu->psci_version == 2) {
 | 
					    if (armcpu->psci_version == 2) {
 | 
				
			||||||
        const char comp[] = "arm,psci-0.2\0arm,psci";
 | 
					        const char comp[] = "arm,psci-0.2\0arm,psci";
 | 
				
			||||||
@ -341,7 +364,7 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
 | 
				
			|||||||
        qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible",
 | 
					        qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible",
 | 
				
			||||||
                                    armcpu->dtb_compatible);
 | 
					                                    armcpu->dtb_compatible);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (vbi->smp_cpus > 1) {
 | 
					        if (vbi->using_psci && vbi->smp_cpus > 1) {
 | 
				
			||||||
            qemu_fdt_setprop_string(vbi->fdt, nodename,
 | 
					            qemu_fdt_setprop_string(vbi->fdt, nodename,
 | 
				
			||||||
                                        "enable-method", "psci");
 | 
					                                        "enable-method", "psci");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -678,13 +701,15 @@ static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void create_one_flash(const char *name, hwaddr flashbase,
 | 
					static void create_one_flash(const char *name, hwaddr flashbase,
 | 
				
			||||||
                             hwaddr flashsize)
 | 
					                             hwaddr flashsize, const char *file,
 | 
				
			||||||
 | 
					                             MemoryRegion *sysmem)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* Create and map a single flash device. We use the same
 | 
					    /* Create and map a single flash device. We use the same
 | 
				
			||||||
     * parameters as the flash devices on the Versatile Express board.
 | 
					     * parameters as the flash devices on the Versatile Express board.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    DriveInfo *dinfo = drive_get_next(IF_PFLASH);
 | 
					    DriveInfo *dinfo = drive_get_next(IF_PFLASH);
 | 
				
			||||||
    DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
 | 
					    DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
 | 
				
			||||||
 | 
					    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 | 
				
			||||||
    const uint64_t sectorlength = 256 * 1024;
 | 
					    const uint64_t sectorlength = 256 * 1024;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (dinfo) {
 | 
					    if (dinfo) {
 | 
				
			||||||
@ -704,19 +729,10 @@ static void create_one_flash(const char *name, hwaddr flashbase,
 | 
				
			|||||||
    qdev_prop_set_string(dev, "name", name);
 | 
					    qdev_prop_set_string(dev, "name", name);
 | 
				
			||||||
    qdev_init_nofail(dev);
 | 
					    qdev_init_nofail(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, flashbase);
 | 
					    memory_region_add_subregion(sysmem, flashbase,
 | 
				
			||||||
}
 | 
					                                sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void create_flash(const VirtBoardInfo *vbi)
 | 
					    if (file) {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /* Create two flash devices to fill the VIRT_FLASH space in the memmap.
 | 
					 | 
				
			||||||
     * Any file passed via -bios goes in the first of these.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    hwaddr flashsize = vbi->memmap[VIRT_FLASH].size / 2;
 | 
					 | 
				
			||||||
    hwaddr flashbase = vbi->memmap[VIRT_FLASH].base;
 | 
					 | 
				
			||||||
    char *nodename;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (bios_name) {
 | 
					 | 
				
			||||||
        char *fn;
 | 
					        char *fn;
 | 
				
			||||||
        int image_size;
 | 
					        int image_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -726,22 +742,43 @@ static void create_flash(const VirtBoardInfo *vbi)
 | 
				
			|||||||
                         "but you cannot use both options at once");
 | 
					                         "but you cannot use both options at once");
 | 
				
			||||||
            exit(1);
 | 
					            exit(1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 | 
					        fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, file);
 | 
				
			||||||
        if (!fn) {
 | 
					        if (!fn) {
 | 
				
			||||||
            error_report("Could not find ROM image '%s'", bios_name);
 | 
					            error_report("Could not find ROM image '%s'", file);
 | 
				
			||||||
            exit(1);
 | 
					            exit(1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        image_size = load_image_targphys(fn, flashbase, flashsize);
 | 
					        image_size = load_image_mr(fn, sysbus_mmio_get_region(sbd, 0));
 | 
				
			||||||
        g_free(fn);
 | 
					        g_free(fn);
 | 
				
			||||||
        if (image_size < 0) {
 | 
					        if (image_size < 0) {
 | 
				
			||||||
            error_report("Could not load ROM image '%s'", bios_name);
 | 
					            error_report("Could not load ROM image '%s'", file);
 | 
				
			||||||
            exit(1);
 | 
					            exit(1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    create_one_flash("virt.flash0", flashbase, flashsize);
 | 
					static void create_flash(const VirtBoardInfo *vbi,
 | 
				
			||||||
    create_one_flash("virt.flash1", flashbase + flashsize, flashsize);
 | 
					                         MemoryRegion *sysmem,
 | 
				
			||||||
 | 
					                         MemoryRegion *secure_sysmem)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Create two flash devices to fill the VIRT_FLASH space in the memmap.
 | 
				
			||||||
 | 
					     * Any file passed via -bios goes in the first of these.
 | 
				
			||||||
 | 
					     * sysmem is the system memory space. secure_sysmem is the secure view
 | 
				
			||||||
 | 
					     * of the system, and the first flash device should be made visible only
 | 
				
			||||||
 | 
					     * there. The second flash device is visible to both secure and nonsecure.
 | 
				
			||||||
 | 
					     * If sysmem == secure_sysmem this means there is no separate Secure
 | 
				
			||||||
 | 
					     * address space and both flash devices are generally visible.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    hwaddr flashsize = vbi->memmap[VIRT_FLASH].size / 2;
 | 
				
			||||||
 | 
					    hwaddr flashbase = vbi->memmap[VIRT_FLASH].base;
 | 
				
			||||||
 | 
					    char *nodename;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    create_one_flash("virt.flash0", flashbase, flashsize,
 | 
				
			||||||
 | 
					                     bios_name, secure_sysmem);
 | 
				
			||||||
 | 
					    create_one_flash("virt.flash1", flashbase + flashsize, flashsize,
 | 
				
			||||||
 | 
					                     NULL, sysmem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (sysmem == secure_sysmem) {
 | 
				
			||||||
 | 
					        /* Report both flash devices as a single node in the DT */
 | 
				
			||||||
        nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
 | 
					        nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
 | 
				
			||||||
        qemu_fdt_add_subnode(vbi->fdt, nodename);
 | 
					        qemu_fdt_add_subnode(vbi->fdt, nodename);
 | 
				
			||||||
        qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash");
 | 
					        qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash");
 | 
				
			||||||
@ -750,6 +787,28 @@ static void create_flash(const VirtBoardInfo *vbi)
 | 
				
			|||||||
                                     2, flashbase + flashsize, 2, flashsize);
 | 
					                                     2, flashbase + flashsize, 2, flashsize);
 | 
				
			||||||
        qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4);
 | 
					        qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4);
 | 
				
			||||||
        g_free(nodename);
 | 
					        g_free(nodename);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        /* Report the devices as separate nodes so we can mark one as
 | 
				
			||||||
 | 
					         * only visible to the secure world.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        nodename = g_strdup_printf("/secflash@%" PRIx64, flashbase);
 | 
				
			||||||
 | 
					        qemu_fdt_add_subnode(vbi->fdt, nodename);
 | 
				
			||||||
 | 
					        qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash");
 | 
				
			||||||
 | 
					        qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
 | 
				
			||||||
 | 
					                                     2, flashbase, 2, flashsize);
 | 
				
			||||||
 | 
					        qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4);
 | 
				
			||||||
 | 
					        qemu_fdt_setprop_string(vbi->fdt, nodename, "status", "disabled");
 | 
				
			||||||
 | 
					        qemu_fdt_setprop_string(vbi->fdt, nodename, "secure-status", "okay");
 | 
				
			||||||
 | 
					        g_free(nodename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
 | 
				
			||||||
 | 
					        qemu_fdt_add_subnode(vbi->fdt, nodename);
 | 
				
			||||||
 | 
					        qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash");
 | 
				
			||||||
 | 
					        qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
 | 
				
			||||||
 | 
					                                     2, flashbase + flashsize, 2, flashsize);
 | 
				
			||||||
 | 
					        qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4);
 | 
				
			||||||
 | 
					        g_free(nodename);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void create_fw_cfg(const VirtBoardInfo *vbi, AddressSpace *as)
 | 
					static void create_fw_cfg(const VirtBoardInfo *vbi, AddressSpace *as)
 | 
				
			||||||
@ -960,6 +1019,27 @@ static void create_platform_bus(VirtBoardInfo *vbi, qemu_irq *pic)
 | 
				
			|||||||
                                sysbus_mmio_get_region(s, 0));
 | 
					                                sysbus_mmio_get_region(s, 0));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void create_secure_ram(VirtBoardInfo *vbi, MemoryRegion *secure_sysmem)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    MemoryRegion *secram = g_new(MemoryRegion, 1);
 | 
				
			||||||
 | 
					    char *nodename;
 | 
				
			||||||
 | 
					    hwaddr base = vbi->memmap[VIRT_SECURE_MEM].base;
 | 
				
			||||||
 | 
					    hwaddr size = vbi->memmap[VIRT_SECURE_MEM].size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memory_region_init_ram(secram, NULL, "virt.secure-ram", size, &error_fatal);
 | 
				
			||||||
 | 
					    vmstate_register_ram_global(secram);
 | 
				
			||||||
 | 
					    memory_region_add_subregion(secure_sysmem, base, secram);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    nodename = g_strdup_printf("/secram@%" PRIx64, base);
 | 
				
			||||||
 | 
					    qemu_fdt_add_subnode(vbi->fdt, nodename);
 | 
				
			||||||
 | 
					    qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "memory");
 | 
				
			||||||
 | 
					    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", 2, base, 2, size);
 | 
				
			||||||
 | 
					    qemu_fdt_setprop_string(vbi->fdt, nodename, "status", "disabled");
 | 
				
			||||||
 | 
					    qemu_fdt_setprop_string(vbi->fdt, nodename, "secure-status", "okay");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_free(nodename);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
 | 
					static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const VirtBoardInfo *board = (const VirtBoardInfo *)binfo;
 | 
					    const VirtBoardInfo *board = (const VirtBoardInfo *)binfo;
 | 
				
			||||||
@ -1020,6 +1100,7 @@ static void machvirt_init(MachineState *machine)
 | 
				
			|||||||
    VirtGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
 | 
					    VirtGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
 | 
				
			||||||
    VirtGuestInfo *guest_info = &guest_info_state->info;
 | 
					    VirtGuestInfo *guest_info = &guest_info_state->info;
 | 
				
			||||||
    char **cpustr;
 | 
					    char **cpustr;
 | 
				
			||||||
 | 
					    bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!cpu_model) {
 | 
					    if (!cpu_model) {
 | 
				
			||||||
        cpu_model = "cortex-a15";
 | 
					        cpu_model = "cortex-a15";
 | 
				
			||||||
@ -1047,6 +1128,15 @@ static void machvirt_init(MachineState *machine)
 | 
				
			|||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* If we have an EL3 boot ROM then the assumption is that it will
 | 
				
			||||||
 | 
					     * implement PSCI itself, so disable QEMU's internal implementation
 | 
				
			||||||
 | 
					     * so it doesn't get in the way. Instead of starting secondary
 | 
				
			||||||
 | 
					     * CPUs in PSCI powerdown state we will start them all running and
 | 
				
			||||||
 | 
					     * let the boot ROM sort them out.
 | 
				
			||||||
 | 
					     * The usual case is that we do use QEMU's PSCI implementation.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    vbi->using_psci = !(vms->secure && firmware_loaded);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* The maximum number of CPUs depends on the GIC version, or on how
 | 
					    /* The maximum number of CPUs depends on the GIC version, or on how
 | 
				
			||||||
     * many redistributors we can fit into the memory map.
 | 
					     * many redistributors we can fit into the memory map.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -1066,7 +1156,7 @@ static void machvirt_init(MachineState *machine)
 | 
				
			|||||||
    vbi->smp_cpus = smp_cpus;
 | 
					    vbi->smp_cpus = smp_cpus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (machine->ram_size > vbi->memmap[VIRT_MEM].size) {
 | 
					    if (machine->ram_size > vbi->memmap[VIRT_MEM].size) {
 | 
				
			||||||
        error_report("mach-virt: cannot model more than 30GB RAM");
 | 
					        error_report("mach-virt: cannot model more than %dGB RAM", RAMLIMIT_GB);
 | 
				
			||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1114,12 +1204,15 @@ static void machvirt_init(MachineState *machine)
 | 
				
			|||||||
            object_property_set_bool(cpuobj, false, "has_el3", NULL);
 | 
					            object_property_set_bool(cpuobj, false, "has_el3", NULL);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_HVC, "psci-conduit",
 | 
					        if (vbi->using_psci) {
 | 
				
			||||||
                                NULL);
 | 
					            object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_HVC,
 | 
				
			||||||
 | 
					                                    "psci-conduit", NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* Secondary CPUs start in PSCI powered-down state */
 | 
					            /* Secondary CPUs start in PSCI powered-down state */
 | 
				
			||||||
            if (n > 0) {
 | 
					            if (n > 0) {
 | 
				
			||||||
            object_property_set_bool(cpuobj, true, "start-powered-off", NULL);
 | 
					                object_property_set_bool(cpuobj, true,
 | 
				
			||||||
 | 
					                                         "start-powered-off", NULL);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (object_property_find(cpuobj, "reset-cbar", NULL)) {
 | 
					        if (object_property_find(cpuobj, "reset-cbar", NULL)) {
 | 
				
			||||||
@ -1145,13 +1238,14 @@ static void machvirt_init(MachineState *machine)
 | 
				
			|||||||
                                         machine->ram_size);
 | 
					                                         machine->ram_size);
 | 
				
			||||||
    memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram);
 | 
					    memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    create_flash(vbi);
 | 
					    create_flash(vbi, sysmem, secure_sysmem ? secure_sysmem : sysmem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    create_gic(vbi, pic, gic_version, vms->secure);
 | 
					    create_gic(vbi, pic, gic_version, vms->secure);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    create_uart(vbi, pic, VIRT_UART, sysmem);
 | 
					    create_uart(vbi, pic, VIRT_UART, sysmem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (vms->secure) {
 | 
					    if (vms->secure) {
 | 
				
			||||||
 | 
					        create_secure_ram(vbi, secure_sysmem);
 | 
				
			||||||
        create_uart(vbi, pic, VIRT_SECURE_UART, secure_sysmem);
 | 
					        create_uart(vbi, pic, VIRT_SECURE_UART, secure_sysmem);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1187,7 +1281,7 @@ static void machvirt_init(MachineState *machine)
 | 
				
			|||||||
    vbi->bootinfo.board_id = -1;
 | 
					    vbi->bootinfo.board_id = -1;
 | 
				
			||||||
    vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base;
 | 
					    vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base;
 | 
				
			||||||
    vbi->bootinfo.get_dtb = machvirt_dtb;
 | 
					    vbi->bootinfo.get_dtb = machvirt_dtb;
 | 
				
			||||||
    vbi->bootinfo.firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
 | 
					    vbi->bootinfo.firmware_loaded = firmware_loaded;
 | 
				
			||||||
    arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo);
 | 
					    arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
 | 
				
			|||||||
@ -147,6 +147,28 @@ int load_image_targphys(const char *filename,
 | 
				
			|||||||
    return size;
 | 
					    return size;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int load_image_mr(const char *filename, MemoryRegion *mr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!memory_access_is_direct(mr, false)) {
 | 
				
			||||||
 | 
					        /* Can only load an image into RAM or ROM */
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size = get_image_size(filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (size > memory_region_size(mr)) {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (size > 0) {
 | 
				
			||||||
 | 
					        if (rom_add_file_mr(filename, mr, -1) < 0) {
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pstrcpy_targphys(const char *name, hwaddr dest, int buf_size,
 | 
					void pstrcpy_targphys(const char *name, hwaddr dest, int buf_size,
 | 
				
			||||||
                      const char *source)
 | 
					                      const char *source)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -332,10 +354,66 @@ const char *load_elf_strerror(int error)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int fd;
 | 
				
			||||||
 | 
					    uint8_t e_ident_local[EI_NIDENT];
 | 
				
			||||||
 | 
					    uint8_t *e_ident;
 | 
				
			||||||
 | 
					    size_t hdr_size, off;
 | 
				
			||||||
 | 
					    bool is64l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!hdr) {
 | 
				
			||||||
 | 
					        hdr = e_ident_local;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    e_ident = hdr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fd = open(filename, O_RDONLY | O_BINARY);
 | 
				
			||||||
 | 
					    if (fd < 0) {
 | 
				
			||||||
 | 
					        error_setg_errno(errp, errno, "Failed to open file: %s", filename);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (read(fd, hdr, EI_NIDENT) != EI_NIDENT) {
 | 
				
			||||||
 | 
					        error_setg_errno(errp, errno, "Failed to read file: %s", filename);
 | 
				
			||||||
 | 
					        goto fail;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (e_ident[0] != ELFMAG0 ||
 | 
				
			||||||
 | 
					        e_ident[1] != ELFMAG1 ||
 | 
				
			||||||
 | 
					        e_ident[2] != ELFMAG2 ||
 | 
				
			||||||
 | 
					        e_ident[3] != ELFMAG3) {
 | 
				
			||||||
 | 
					        error_setg(errp, "Bad ELF magic");
 | 
				
			||||||
 | 
					        goto fail;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    is64l = e_ident[EI_CLASS] == ELFCLASS64;
 | 
				
			||||||
 | 
					    hdr_size = is64l ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr);
 | 
				
			||||||
 | 
					    if (is64) {
 | 
				
			||||||
 | 
					        *is64 = is64l;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    off = EI_NIDENT;
 | 
				
			||||||
 | 
					    while (hdr != e_ident_local && off < hdr_size) {
 | 
				
			||||||
 | 
					        size_t br = read(fd, hdr + off, hdr_size - off);
 | 
				
			||||||
 | 
					        switch (br) {
 | 
				
			||||||
 | 
					        case 0:
 | 
				
			||||||
 | 
					            error_setg(errp, "File too short: %s", filename);
 | 
				
			||||||
 | 
					            goto fail;
 | 
				
			||||||
 | 
					        case -1:
 | 
				
			||||||
 | 
					            error_setg_errno(errp, errno, "Failed to read file: %s",
 | 
				
			||||||
 | 
					                             filename);
 | 
				
			||||||
 | 
					            goto fail;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        off += br;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fail:
 | 
				
			||||||
 | 
					    close(fd);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* return < 0 if error, otherwise the number of bytes loaded in memory */
 | 
					/* return < 0 if error, otherwise the number of bytes loaded in memory */
 | 
				
			||||||
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
					int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
				
			||||||
             void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
 | 
					             void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
 | 
				
			||||||
             uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb)
 | 
					             uint64_t *highaddr, int big_endian, int elf_machine,
 | 
				
			||||||
 | 
					             int clear_lsb, int data_swab)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
 | 
					    int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
 | 
				
			||||||
    uint8_t e_ident[EI_NIDENT];
 | 
					    uint8_t e_ident[EI_NIDENT];
 | 
				
			||||||
@ -374,10 +452,12 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
				
			|||||||
    lseek(fd, 0, SEEK_SET);
 | 
					    lseek(fd, 0, SEEK_SET);
 | 
				
			||||||
    if (e_ident[EI_CLASS] == ELFCLASS64) {
 | 
					    if (e_ident[EI_CLASS] == ELFCLASS64) {
 | 
				
			||||||
        ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
 | 
					        ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
 | 
				
			||||||
                         pentry, lowaddr, highaddr, elf_machine, clear_lsb);
 | 
					                         pentry, lowaddr, highaddr, elf_machine, clear_lsb,
 | 
				
			||||||
 | 
					                         data_swab);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
 | 
					        ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
 | 
				
			||||||
                         pentry, lowaddr, highaddr, elf_machine, clear_lsb);
 | 
					                         pentry, lowaddr, highaddr, elf_machine, clear_lsb,
 | 
				
			||||||
 | 
					                         data_swab);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 fail:
 | 
					 fail:
 | 
				
			||||||
@ -751,7 +831,7 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char *name)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int rom_add_file(const char *file, const char *fw_dir,
 | 
					int rom_add_file(const char *file, const char *fw_dir,
 | 
				
			||||||
                 hwaddr addr, int32_t bootindex,
 | 
					                 hwaddr addr, int32_t bootindex,
 | 
				
			||||||
                 bool option_rom)
 | 
					                 bool option_rom, MemoryRegion *mr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
 | 
					    MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
 | 
				
			||||||
    Rom *rom;
 | 
					    Rom *rom;
 | 
				
			||||||
@ -817,9 +897,14 @@ int rom_add_file(const char *file, const char *fw_dir,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fw_cfg_add_file(fw_cfg, fw_file_name, data, rom->romsize);
 | 
					        fw_cfg_add_file(fw_cfg, fw_file_name, data, rom->romsize);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        if (mr) {
 | 
				
			||||||
 | 
					            rom->mr = mr;
 | 
				
			||||||
 | 
					            snprintf(devpath, sizeof(devpath), "/rom@%s", file);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr);
 | 
					            snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    add_boot_device_path(bootindex, NULL, devpath);
 | 
					    add_boot_device_path(bootindex, NULL, devpath);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
@ -892,12 +977,12 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int rom_add_vga(const char *file)
 | 
					int rom_add_vga(const char *file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return rom_add_file(file, "vgaroms", 0, -1, true);
 | 
					    return rom_add_file(file, "vgaroms", 0, -1, true, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int rom_add_option(const char *file, int32_t bootindex)
 | 
					int rom_add_option(const char *file, int32_t bootindex)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return rom_add_file(file, "genroms", 0, bootindex, true);
 | 
					    return rom_add_file(file, "genroms", 0, bootindex, true, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void rom_reset(void *unused)
 | 
					static void rom_reset(void *unused)
 | 
				
			||||||
 | 
				
			|||||||
@ -109,7 +109,7 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
    /* Memory map (addresses are offsets from PERIPHBASE):
 | 
					    /* Memory map (addresses are offsets from PERIPHBASE):
 | 
				
			||||||
     *  0x0000-0x0fff -- reserved
 | 
					     *  0x0000-0x0fff -- reserved
 | 
				
			||||||
     *  0x1000-0x1fff -- GIC Distributor
 | 
					     *  0x1000-0x1fff -- GIC Distributor
 | 
				
			||||||
     *  0x2000-0x2fff -- GIC CPU interface
 | 
					     *  0x2000-0x3fff -- GIC CPU interface
 | 
				
			||||||
     *  0x4000-0x4fff -- GIC virtual interface control (not modelled)
 | 
					     *  0x4000-0x4fff -- GIC virtual interface control (not modelled)
 | 
				
			||||||
     *  0x5000-0x5fff -- GIC virtual interface control (not modelled)
 | 
					     *  0x5000-0x5fff -- GIC virtual interface control (not modelled)
 | 
				
			||||||
     *  0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
 | 
					     *  0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
 | 
				
			||||||
 | 
				
			|||||||
@ -73,7 +73,7 @@ void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
 | 
				
			|||||||
    /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis 
 | 
					    /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis 
 | 
				
			||||||
       devboard SDK.  */
 | 
					       devboard SDK.  */
 | 
				
			||||||
    image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
 | 
					    image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
 | 
				
			||||||
                          &entry, NULL, &high, 0, EM_CRIS, 0);
 | 
					                          &entry, NULL, &high, 0, EM_CRIS, 0, 0);
 | 
				
			||||||
    li->entry = entry;
 | 
					    li->entry = entry;
 | 
				
			||||||
    if (image_size < 0) {
 | 
					    if (image_size < 0) {
 | 
				
			||||||
        /* Takes a kimage from the axis devboard SDK.  */
 | 
					        /* Takes a kimage from the axis devboard SDK.  */
 | 
				
			||||||
 | 
				
			|||||||
@ -196,7 +196,8 @@ int load_multiboot(FWCfgState *fw_cfg,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
 | 
					        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
 | 
				
			||||||
                               &elf_low, &elf_high, 0, I386_ELF_MACHINE, 0);
 | 
					                               &elf_low, &elf_high, 0, I386_ELF_MACHINE,
 | 
				
			||||||
 | 
					                               0, 0);
 | 
				
			||||||
        if (kernel_size < 0) {
 | 
					        if (kernel_size < 0) {
 | 
				
			||||||
            fprintf(stderr, "Error while loading elf kernel\n");
 | 
					            fprintf(stderr, "Error while loading elf kernel\n");
 | 
				
			||||||
            exit(1);
 | 
					            exit(1);
 | 
				
			||||||
 | 
				
			|||||||
@ -500,6 +500,41 @@ static uint8_t gic_get_running_priority(GICState *s, int cpu, MemTxAttrs attrs)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Return true if we should split priority drop and interrupt deactivation,
 | 
				
			||||||
 | 
					 * ie whether the relevant EOIMode bit is set.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static bool gic_eoi_split(GICState *s, int cpu, MemTxAttrs attrs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (s->revision != 2) {
 | 
				
			||||||
 | 
					        /* Before GICv2 prio-drop and deactivate are not separable */
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (s->security_extn && !attrs.secure) {
 | 
				
			||||||
 | 
					        return s->cpu_ctlr[cpu] & GICC_CTLR_EOIMODE_NS;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return s->cpu_ctlr[cpu] & GICC_CTLR_EOIMODE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gic_deactivate_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int cm = 1 << cpu;
 | 
				
			||||||
 | 
					    int group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!gic_eoi_split(s, cpu, attrs)) {
 | 
				
			||||||
 | 
					        /* This is UNPREDICTABLE; we choose to ignore it */
 | 
				
			||||||
 | 
					        qemu_log_mask(LOG_GUEST_ERROR,
 | 
				
			||||||
 | 
					                      "gic_deactivate_irq: GICC_DIR write when EOIMode clear");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (s->security_extn && !attrs.secure && !group) {
 | 
				
			||||||
 | 
					        DPRINTF("Non-secure DI for Group0 interrupt %d ignored\n", irq);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GIC_CLEAR_ACTIVE(irq, cm);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
 | 
					void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int cm = 1 << cpu;
 | 
					    int cm = 1 << cpu;
 | 
				
			||||||
@ -544,7 +579,11 @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gic_drop_prio(s, cpu, group);
 | 
					    gic_drop_prio(s, cpu, group);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* In GICv2 the guest can choose to split priority-drop and deactivate */
 | 
				
			||||||
 | 
					    if (!gic_eoi_split(s, cpu, attrs)) {
 | 
				
			||||||
        GIC_CLEAR_ACTIVE(irq, cm);
 | 
					        GIC_CLEAR_ACTIVE(irq, cm);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    gic_update(s);
 | 
					    gic_update(s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1210,6 +1249,10 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
 | 
				
			|||||||
        s->nsapr[regno][cpu] = value;
 | 
					        s->nsapr[regno][cpu] = value;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    case 0x1000:
 | 
				
			||||||
 | 
					        /* GICC_DIR */
 | 
				
			||||||
 | 
					        gic_deactivate_irq(s, cpu, value & 0x3ff, attrs);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        qemu_log_mask(LOG_GUEST_ERROR,
 | 
					        qemu_log_mask(LOG_GUEST_ERROR,
 | 
				
			||||||
                      "gic_cpu_write: Bad offset %x\n", (int)offset);
 | 
					                      "gic_cpu_write: Bad offset %x\n", (int)offset);
 | 
				
			||||||
 | 
				
			|||||||
@ -121,7 +121,7 @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
 | 
				
			|||||||
         * neither it can use KVM.
 | 
					         * neither it can use KVM.
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
 | 
					        memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
 | 
				
			||||||
                              s, "gic_cpu", s->revision == 2 ? 0x1000 : 0x100);
 | 
					                              s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100);
 | 
				
			||||||
        sysbus_init_mmio(sbd, &s->cpuiomem[0]);
 | 
					        sysbus_init_mmio(sbd, &s->cpuiomem[0]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -143,7 +143,7 @@ static void lm32_evr_init(MachineState *machine)
 | 
				
			|||||||
        int kernel_size;
 | 
					        int kernel_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
 | 
					        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
 | 
				
			||||||
                               1, EM_LATTICEMICO32, 0);
 | 
					                               1, EM_LATTICEMICO32, 0, 0);
 | 
				
			||||||
        reset_info->bootstrap_pc = entry;
 | 
					        reset_info->bootstrap_pc = entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (kernel_size < 0) {
 | 
					        if (kernel_size < 0) {
 | 
				
			||||||
@ -245,7 +245,7 @@ static void lm32_uclinux_init(MachineState *machine)
 | 
				
			|||||||
        int kernel_size;
 | 
					        int kernel_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
 | 
					        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
 | 
				
			||||||
                               1, EM_LATTICEMICO32, 0);
 | 
					                               1, EM_LATTICEMICO32, 0, 0);
 | 
				
			||||||
        reset_info->bootstrap_pc = entry;
 | 
					        reset_info->bootstrap_pc = entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (kernel_size < 0) {
 | 
					        if (kernel_size < 0) {
 | 
				
			||||||
 | 
				
			|||||||
@ -177,7 +177,7 @@ milkymist_init(MachineState *machine)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        /* Boots a kernel elf binary.  */
 | 
					        /* Boots a kernel elf binary.  */
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
 | 
					        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
 | 
				
			||||||
                               1, EM_LATTICEMICO32, 0);
 | 
					                               1, EM_LATTICEMICO32, 0, 0);
 | 
				
			||||||
        reset_info->bootstrap_pc = entry;
 | 
					        reset_info->bootstrap_pc = entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (kernel_size < 0) {
 | 
					        if (kernel_size < 0) {
 | 
				
			||||||
 | 
				
			|||||||
@ -73,7 +73,7 @@ static void an5206_init(MachineState *machine)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
 | 
					    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
 | 
				
			||||||
                           NULL, NULL, 1, EM_68K, 0);
 | 
					                           NULL, NULL, 1, EM_68K, 0, 0);
 | 
				
			||||||
    entry = elf_entry;
 | 
					    entry = elf_entry;
 | 
				
			||||||
    if (kernel_size < 0) {
 | 
					    if (kernel_size < 0) {
 | 
				
			||||||
        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
 | 
					        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
 | 
				
			||||||
 | 
				
			|||||||
@ -50,7 +50,7 @@ static void dummy_m68k_init(MachineState *machine)
 | 
				
			|||||||
    /* Load kernel.  */
 | 
					    /* Load kernel.  */
 | 
				
			||||||
    if (kernel_filename) {
 | 
					    if (kernel_filename) {
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
 | 
					        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
 | 
				
			||||||
                               NULL, NULL, 1, EM_68K, 0);
 | 
					                               NULL, NULL, 1, EM_68K, 0, 0);
 | 
				
			||||||
        entry = elf_entry;
 | 
					        entry = elf_entry;
 | 
				
			||||||
        if (kernel_size < 0) {
 | 
					        if (kernel_size < 0) {
 | 
				
			||||||
            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
 | 
					            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
 | 
				
			||||||
 | 
				
			|||||||
@ -276,7 +276,7 @@ static void mcf5208evb_init(MachineState *machine)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
 | 
					    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
 | 
				
			||||||
                           NULL, NULL, 1, EM_68K, 0);
 | 
					                           NULL, NULL, 1, EM_68K, 0, 0);
 | 
				
			||||||
    entry = elf_entry;
 | 
					    entry = elf_entry;
 | 
				
			||||||
    if (kernel_size < 0) {
 | 
					    if (kernel_size < 0) {
 | 
				
			||||||
        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
 | 
					        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
 | 
				
			||||||
 | 
				
			|||||||
@ -142,12 +142,12 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
 | 
				
			|||||||
        /* Boots a kernel elf binary.  */
 | 
					        /* Boots a kernel elf binary.  */
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, NULL, NULL,
 | 
					        kernel_size = load_elf(kernel_filename, NULL, NULL,
 | 
				
			||||||
                               &entry, &low, &high,
 | 
					                               &entry, &low, &high,
 | 
				
			||||||
                               big_endian, EM_MICROBLAZE, 0);
 | 
					                               big_endian, EM_MICROBLAZE, 0, 0);
 | 
				
			||||||
        base32 = entry;
 | 
					        base32 = entry;
 | 
				
			||||||
        if (base32 == 0xc0000000) {
 | 
					        if (base32 == 0xc0000000) {
 | 
				
			||||||
            kernel_size = load_elf(kernel_filename, translate_kernel_address,
 | 
					            kernel_size = load_elf(kernel_filename, translate_kernel_address,
 | 
				
			||||||
                                   NULL, &entry, NULL, NULL,
 | 
					                                   NULL, &entry, NULL, NULL,
 | 
				
			||||||
                                   big_endian, EM_MICROBLAZE, 0);
 | 
					                                   big_endian, EM_MICROBLAZE, 0, 0);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        /* Always boot into physical ram.  */
 | 
					        /* Always boot into physical ram.  */
 | 
				
			||||||
        boot_info.bootstrap_pc = (uint32_t)entry;
 | 
					        boot_info.bootstrap_pc = (uint32_t)entry;
 | 
				
			||||||
 | 
				
			|||||||
@ -117,7 +117,7 @@ static int64_t load_kernel (CPUMIPSState *env)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
 | 
					    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
 | 
				
			||||||
                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
 | 
					                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
 | 
				
			||||||
                 (uint64_t *)&kernel_high, 0, EM_MIPS, 1) < 0) {
 | 
					                 (uint64_t *)&kernel_high, 0, EM_MIPS, 1, 0) < 0) {
 | 
				
			||||||
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
 | 
					        fprintf(stderr, "qemu: could not load kernel '%s'\n",
 | 
				
			||||||
                loaderparams.kernel_filename);
 | 
					                loaderparams.kernel_filename);
 | 
				
			||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
 | 
				
			|||||||
@ -796,7 +796,7 @@ static int64_t load_kernel (void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
 | 
					    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
 | 
				
			||||||
                 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
 | 
					                 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
 | 
				
			||||||
                 big_endian, EM_MIPS, 1) < 0) {
 | 
					                 big_endian, EM_MIPS, 1, 0) < 0) {
 | 
				
			||||||
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
 | 
					        fprintf(stderr, "qemu: could not load kernel '%s'\n",
 | 
				
			||||||
                loaderparams.kernel_filename);
 | 
					                loaderparams.kernel_filename);
 | 
				
			||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
 | 
				
			|||||||
@ -70,7 +70,7 @@ static int64_t load_kernel(void)
 | 
				
			|||||||
    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
 | 
					    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
 | 
				
			||||||
                           NULL, (uint64_t *)&entry, NULL,
 | 
					                           NULL, (uint64_t *)&entry, NULL,
 | 
				
			||||||
                           (uint64_t *)&kernel_high, big_endian,
 | 
					                           (uint64_t *)&kernel_high, big_endian,
 | 
				
			||||||
                           EM_MIPS, 1);
 | 
					                           EM_MIPS, 1, 0);
 | 
				
			||||||
    if (kernel_size >= 0) {
 | 
					    if (kernel_size >= 0) {
 | 
				
			||||||
        if ((entry & ~0x7fffffffULL) == 0x80000000)
 | 
					        if ((entry & ~0x7fffffffULL) == 0x80000000)
 | 
				
			||||||
            entry = (int32_t)entry;
 | 
					            entry = (int32_t)entry;
 | 
				
			||||||
 | 
				
			|||||||
@ -88,7 +88,7 @@ static int64_t load_kernel(void)
 | 
				
			|||||||
    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
 | 
					    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
 | 
				
			||||||
                           NULL, (uint64_t *)&entry, NULL,
 | 
					                           NULL, (uint64_t *)&entry, NULL,
 | 
				
			||||||
                           (uint64_t *)&kernel_high, big_endian,
 | 
					                           (uint64_t *)&kernel_high, big_endian,
 | 
				
			||||||
                           EM_MIPS, 1);
 | 
					                           EM_MIPS, 1, 0);
 | 
				
			||||||
    if (kernel_size >= 0) {
 | 
					    if (kernel_size >= 0) {
 | 
				
			||||||
        if ((entry & ~0x7fffffffULL) == 0x80000000)
 | 
					        if ((entry & ~0x7fffffffULL) == 0x80000000)
 | 
				
			||||||
            entry = (int32_t)entry;
 | 
					            entry = (int32_t)entry;
 | 
				
			||||||
 | 
				
			|||||||
@ -98,7 +98,7 @@ static void bcm2835_mbox_update(BCM2835MboxState *s)
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    for (n = 0; n < MBOX_CHAN_COUNT; n++) {
 | 
					    for (n = 0; n < MBOX_CHAN_COUNT; n++) {
 | 
				
			||||||
        while (s->available[n] && !(s->mbox[0].status & ARM_MS_FULL)) {
 | 
					        while (s->available[n] && !(s->mbox[0].status & ARM_MS_FULL)) {
 | 
				
			||||||
            value = ldl_phys(&s->mbox_as, n << MBOX_AS_CHAN_SHIFT);
 | 
					            value = ldl_le_phys(&s->mbox_as, n << MBOX_AS_CHAN_SHIFT);
 | 
				
			||||||
            assert(value != MBOX_INVALID_DATA); /* Pending interrupt but no data */
 | 
					            assert(value != MBOX_INVALID_DATA); /* Pending interrupt but no data */
 | 
				
			||||||
            mbox_push(&s->mbox[0], value);
 | 
					            mbox_push(&s->mbox[0], value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -207,12 +207,12 @@ static void bcm2835_mbox_write(void *opaque, hwaddr offset,
 | 
				
			|||||||
            ch = value & 0xf;
 | 
					            ch = value & 0xf;
 | 
				
			||||||
            if (ch < MBOX_CHAN_COUNT) {
 | 
					            if (ch < MBOX_CHAN_COUNT) {
 | 
				
			||||||
                childaddr = ch << MBOX_AS_CHAN_SHIFT;
 | 
					                childaddr = ch << MBOX_AS_CHAN_SHIFT;
 | 
				
			||||||
                if (ldl_phys(&s->mbox_as, childaddr + MBOX_AS_PENDING)) {
 | 
					                if (ldl_le_phys(&s->mbox_as, childaddr + MBOX_AS_PENDING)) {
 | 
				
			||||||
                    /* Child busy, push delayed. Push it in the arm->vc mbox */
 | 
					                    /* Child busy, push delayed. Push it in the arm->vc mbox */
 | 
				
			||||||
                    mbox_push(&s->mbox[1], value);
 | 
					                    mbox_push(&s->mbox[1], value);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    /* Push it directly to the child device */
 | 
					                    /* Push it directly to the child device */
 | 
				
			||||||
                    stl_phys(&s->mbox_as, childaddr, value);
 | 
					                    stl_le_phys(&s->mbox_as, childaddr, value);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                /* Invalid channel number */
 | 
					                /* Invalid channel number */
 | 
				
			||||||
 | 
				
			|||||||
@ -22,20 +22,20 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    s->addr = value;
 | 
					    s->addr = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tot_len = ldl_phys(&s->dma_as, value);
 | 
					    tot_len = ldl_le_phys(&s->dma_as, value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* @(addr + 4) : Buffer response code */
 | 
					    /* @(addr + 4) : Buffer response code */
 | 
				
			||||||
    value = s->addr + 8;
 | 
					    value = s->addr + 8;
 | 
				
			||||||
    while (value + 8 <= s->addr + tot_len) {
 | 
					    while (value + 8 <= s->addr + tot_len) {
 | 
				
			||||||
        tag = ldl_phys(&s->dma_as, value);
 | 
					        tag = ldl_le_phys(&s->dma_as, value);
 | 
				
			||||||
        bufsize = ldl_phys(&s->dma_as, value + 4);
 | 
					        bufsize = ldl_le_phys(&s->dma_as, value + 4);
 | 
				
			||||||
        /* @(value + 8) : Request/response indicator */
 | 
					        /* @(value + 8) : Request/response indicator */
 | 
				
			||||||
        resplen = 0;
 | 
					        resplen = 0;
 | 
				
			||||||
        switch (tag) {
 | 
					        switch (tag) {
 | 
				
			||||||
        case 0x00000000: /* End tag */
 | 
					        case 0x00000000: /* End tag */
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 0x00000001: /* Get firmware revision */
 | 
					        case 0x00000001: /* Get firmware revision */
 | 
				
			||||||
            stl_phys(&s->dma_as, value + 12, 346337);
 | 
					            stl_le_phys(&s->dma_as, value + 12, 346337);
 | 
				
			||||||
            resplen = 4;
 | 
					            resplen = 4;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 0x00010001: /* Get board model */
 | 
					        case 0x00010001: /* Get board model */
 | 
				
			||||||
@ -44,7 +44,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 | 
				
			|||||||
            resplen = 4;
 | 
					            resplen = 4;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 0x00010002: /* Get board revision */
 | 
					        case 0x00010002: /* Get board revision */
 | 
				
			||||||
            stl_phys(&s->dma_as, value + 12, s->board_rev);
 | 
					            stl_le_phys(&s->dma_as, value + 12, s->board_rev);
 | 
				
			||||||
            resplen = 4;
 | 
					            resplen = 4;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 0x00010003: /* Get board MAC address */
 | 
					        case 0x00010003: /* Get board MAC address */
 | 
				
			||||||
@ -58,24 +58,24 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 0x00010005: /* Get ARM memory */
 | 
					        case 0x00010005: /* Get ARM memory */
 | 
				
			||||||
            /* base */
 | 
					            /* base */
 | 
				
			||||||
            stl_phys(&s->dma_as, value + 12, 0);
 | 
					            stl_le_phys(&s->dma_as, value + 12, 0);
 | 
				
			||||||
            /* size */
 | 
					            /* size */
 | 
				
			||||||
            stl_phys(&s->dma_as, value + 16, s->ram_size);
 | 
					            stl_le_phys(&s->dma_as, value + 16, s->ram_size);
 | 
				
			||||||
            resplen = 8;
 | 
					            resplen = 8;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 0x00028001: /* Set power state */
 | 
					        case 0x00028001: /* Set power state */
 | 
				
			||||||
            /* Assume that whatever device they asked for exists,
 | 
					            /* Assume that whatever device they asked for exists,
 | 
				
			||||||
             * and we'll just claim we set it to the desired state
 | 
					             * and we'll just claim we set it to the desired state
 | 
				
			||||||
             */
 | 
					             */
 | 
				
			||||||
            tmp = ldl_phys(&s->dma_as, value + 16);
 | 
					            tmp = ldl_le_phys(&s->dma_as, value + 16);
 | 
				
			||||||
            stl_phys(&s->dma_as, value + 16, (tmp & 1));
 | 
					            stl_le_phys(&s->dma_as, value + 16, (tmp & 1));
 | 
				
			||||||
            resplen = 8;
 | 
					            resplen = 8;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Clocks */
 | 
					        /* Clocks */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case 0x00030001: /* Get clock state */
 | 
					        case 0x00030001: /* Get clock state */
 | 
				
			||||||
            stl_phys(&s->dma_as, value + 16, 0x1);
 | 
					            stl_le_phys(&s->dma_as, value + 16, 0x1);
 | 
				
			||||||
            resplen = 8;
 | 
					            resplen = 8;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -88,15 +88,15 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 | 
				
			|||||||
        case 0x00030002: /* Get clock rate */
 | 
					        case 0x00030002: /* Get clock rate */
 | 
				
			||||||
        case 0x00030004: /* Get max clock rate */
 | 
					        case 0x00030004: /* Get max clock rate */
 | 
				
			||||||
        case 0x00030007: /* Get min clock rate */
 | 
					        case 0x00030007: /* Get min clock rate */
 | 
				
			||||||
            switch (ldl_phys(&s->dma_as, value + 12)) {
 | 
					            switch (ldl_le_phys(&s->dma_as, value + 12)) {
 | 
				
			||||||
            case 1: /* EMMC */
 | 
					            case 1: /* EMMC */
 | 
				
			||||||
                stl_phys(&s->dma_as, value + 16, 50000000);
 | 
					                stl_le_phys(&s->dma_as, value + 16, 50000000);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case 2: /* UART */
 | 
					            case 2: /* UART */
 | 
				
			||||||
                stl_phys(&s->dma_as, value + 16, 3000000);
 | 
					                stl_le_phys(&s->dma_as, value + 16, 3000000);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                stl_phys(&s->dma_as, value + 16, 700000000);
 | 
					                stl_le_phys(&s->dma_as, value + 16, 700000000);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            resplen = 8;
 | 
					            resplen = 8;
 | 
				
			||||||
@ -113,19 +113,19 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 | 
				
			|||||||
        /* Temperature */
 | 
					        /* Temperature */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case 0x00030006: /* Get temperature */
 | 
					        case 0x00030006: /* Get temperature */
 | 
				
			||||||
            stl_phys(&s->dma_as, value + 16, 25000);
 | 
					            stl_le_phys(&s->dma_as, value + 16, 25000);
 | 
				
			||||||
            resplen = 8;
 | 
					            resplen = 8;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case 0x0003000A: /* Get max temperature */
 | 
					        case 0x0003000A: /* Get max temperature */
 | 
				
			||||||
            stl_phys(&s->dma_as, value + 16, 99000);
 | 
					            stl_le_phys(&s->dma_as, value + 16, 99000);
 | 
				
			||||||
            resplen = 8;
 | 
					            resplen = 8;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case 0x00060001: /* Get DMA channels */
 | 
					        case 0x00060001: /* Get DMA channels */
 | 
				
			||||||
            /* channels 2-5 */
 | 
					            /* channels 2-5 */
 | 
				
			||||||
            stl_phys(&s->dma_as, value + 12, 0x003C);
 | 
					            stl_le_phys(&s->dma_as, value + 12, 0x003C);
 | 
				
			||||||
            resplen = 4;
 | 
					            resplen = 4;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -143,12 +143,12 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        stl_phys(&s->dma_as, value + 8, (1 << 31) | resplen);
 | 
					        stl_le_phys(&s->dma_as, value + 8, (1 << 31) | resplen);
 | 
				
			||||||
        value += bufsize + 12;
 | 
					        value += bufsize + 12;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Buffer response code */
 | 
					    /* Buffer response code */
 | 
				
			||||||
    stl_phys(&s->dma_as, s->addr + 4, (1 << 31));
 | 
					    stl_le_phys(&s->dma_as, s->addr + 4, (1 << 31));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint64_t bcm2835_property_read(void *opaque, hwaddr offset,
 | 
					static uint64_t bcm2835_property_read(void *opaque, hwaddr offset,
 | 
				
			||||||
 | 
				
			|||||||
@ -54,7 +54,8 @@ static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params)
 | 
				
			|||||||
    ram_addr_t initrd_offset;
 | 
					    ram_addr_t initrd_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    kernel_size = load_elf(loader_params->kernel_filename,  NULL, NULL,
 | 
					    kernel_size = load_elf(loader_params->kernel_filename,  NULL, NULL,
 | 
				
			||||||
                           &entry, &kernel_low, &kernel_high, 1, EM_MOXIE, 0);
 | 
					                           &entry, &kernel_low, &kernel_high, 1, EM_MOXIE,
 | 
				
			||||||
 | 
					                           0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (kernel_size <= 0) {
 | 
					    if (kernel_size <= 0) {
 | 
				
			||||||
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
 | 
					        fprintf(stderr, "qemu: could not load kernel '%s'\n",
 | 
				
			||||||
 | 
				
			|||||||
@ -69,7 +69,8 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (kernel_filename && !qtest_enabled()) {
 | 
					    if (kernel_filename && !qtest_enabled()) {
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, NULL, NULL,
 | 
					        kernel_size = load_elf(kernel_filename, NULL, NULL,
 | 
				
			||||||
                               &elf_entry, NULL, NULL, 1, EM_OPENRISC, 1);
 | 
					                               &elf_entry, NULL, NULL, 1, EM_OPENRISC,
 | 
				
			||||||
 | 
					                               1, 0);
 | 
				
			||||||
        entry = elf_entry;
 | 
					        entry = elf_entry;
 | 
				
			||||||
        if (kernel_size < 0) {
 | 
					        if (kernel_size < 0) {
 | 
				
			||||||
            kernel_size = load_uimage(kernel_filename,
 | 
					            kernel_size = load_uimage(kernel_filename,
 | 
				
			||||||
 | 
				
			|||||||
@ -313,7 +313,7 @@ static void raven_realize(PCIDevice *d, Error **errp)
 | 
				
			|||||||
        if (filename) {
 | 
					        if (filename) {
 | 
				
			||||||
            if (s->elf_machine != EM_NONE) {
 | 
					            if (s->elf_machine != EM_NONE) {
 | 
				
			||||||
                bios_size = load_elf(filename, NULL, NULL, NULL,
 | 
					                bios_size = load_elf(filename, NULL, NULL, NULL,
 | 
				
			||||||
                                     NULL, NULL, 1, s->elf_machine, 0);
 | 
					                                     NULL, NULL, 1, s->elf_machine, 0, 0);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (bios_size < 0) {
 | 
					            if (bios_size < 0) {
 | 
				
			||||||
                bios_size = get_image_size(filename);
 | 
					                bios_size = get_image_size(filename);
 | 
				
			||||||
 | 
				
			|||||||
@ -1017,7 +1017,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
 | 
				
			|||||||
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 | 
					    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bios_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL,
 | 
					    bios_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL,
 | 
				
			||||||
                         1, PPC_ELF_MACHINE, 0);
 | 
					                         1, PPC_ELF_MACHINE, 0, 0);
 | 
				
			||||||
    if (bios_size < 0) {
 | 
					    if (bios_size < 0) {
 | 
				
			||||||
        /*
 | 
					        /*
 | 
				
			||||||
         * Hrm. No ELF image? Try a uImage, maybe someone is giving us an
 | 
					         * Hrm. No ELF image? Try a uImage, maybe someone is giving us an
 | 
				
			||||||
 | 
				
			|||||||
@ -221,7 +221,7 @@ static void ppc_core99_init(MachineState *machine)
 | 
				
			|||||||
    /* Load OpenBIOS (ELF) */
 | 
					    /* Load OpenBIOS (ELF) */
 | 
				
			||||||
    if (filename) {
 | 
					    if (filename) {
 | 
				
			||||||
        bios_size = load_elf(filename, NULL, NULL, NULL,
 | 
					        bios_size = load_elf(filename, NULL, NULL, NULL,
 | 
				
			||||||
                             NULL, NULL, 1, PPC_ELF_MACHINE, 0);
 | 
					                             NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        g_free(filename);
 | 
					        g_free(filename);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@ -244,7 +244,8 @@ static void ppc_core99_init(MachineState *machine)
 | 
				
			|||||||
        kernel_base = KERNEL_LOAD_ADDR;
 | 
					        kernel_base = KERNEL_LOAD_ADDR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
 | 
					        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
 | 
				
			||||||
                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0);
 | 
					                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
 | 
				
			||||||
 | 
					                               0, 0);
 | 
				
			||||||
        if (kernel_size < 0)
 | 
					        if (kernel_size < 0)
 | 
				
			||||||
            kernel_size = load_aout(kernel_filename, kernel_base,
 | 
					            kernel_size = load_aout(kernel_filename, kernel_base,
 | 
				
			||||||
                                    ram_size - kernel_base, bswap_needed,
 | 
					                                    ram_size - kernel_base, bswap_needed,
 | 
				
			||||||
 | 
				
			|||||||
@ -149,7 +149,7 @@ static void ppc_heathrow_init(MachineState *machine)
 | 
				
			|||||||
    /* Load OpenBIOS (ELF) */
 | 
					    /* Load OpenBIOS (ELF) */
 | 
				
			||||||
    if (filename) {
 | 
					    if (filename) {
 | 
				
			||||||
        bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
 | 
					        bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
 | 
				
			||||||
                             1, PPC_ELF_MACHINE, 0);
 | 
					                             1, PPC_ELF_MACHINE, 0, 0);
 | 
				
			||||||
        g_free(filename);
 | 
					        g_free(filename);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        bios_size = -1;
 | 
					        bios_size = -1;
 | 
				
			||||||
@ -170,7 +170,8 @@ static void ppc_heathrow_init(MachineState *machine)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
        kernel_base = KERNEL_LOAD_ADDR;
 | 
					        kernel_base = KERNEL_LOAD_ADDR;
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
 | 
					        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
 | 
				
			||||||
                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0);
 | 
					                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
 | 
				
			||||||
 | 
					                               0, 0);
 | 
				
			||||||
        if (kernel_size < 0)
 | 
					        if (kernel_size < 0)
 | 
				
			||||||
            kernel_size = load_aout(kernel_filename, kernel_base,
 | 
					            kernel_size = load_aout(kernel_filename, kernel_base,
 | 
				
			||||||
                                    ram_size - kernel_base, bswap_needed,
 | 
					                                    ram_size - kernel_base, bswap_needed,
 | 
				
			||||||
 | 
				
			|||||||
@ -256,7 +256,8 @@ static void bamboo_init(MachineState *machine)
 | 
				
			|||||||
                              NULL, NULL);
 | 
					                              NULL, NULL);
 | 
				
			||||||
        if (success < 0) {
 | 
					        if (success < 0) {
 | 
				
			||||||
            success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
 | 
					            success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
 | 
				
			||||||
                               &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0);
 | 
					                               &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE,
 | 
				
			||||||
 | 
					                               0, 0);
 | 
				
			||||||
            entry = elf_entry;
 | 
					            entry = elf_entry;
 | 
				
			||||||
            loadaddr = elf_lowaddr;
 | 
					            loadaddr = elf_lowaddr;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -1942,11 +1942,13 @@ static void ppc_spapr_init(MachineState *machine)
 | 
				
			|||||||
        uint64_t lowaddr = 0;
 | 
					        uint64_t lowaddr = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
 | 
					        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
 | 
				
			||||||
                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0);
 | 
					                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
 | 
				
			||||||
 | 
					                               0, 0);
 | 
				
			||||||
        if (kernel_size == ELF_LOAD_WRONG_ENDIAN) {
 | 
					        if (kernel_size == ELF_LOAD_WRONG_ENDIAN) {
 | 
				
			||||||
            kernel_size = load_elf(kernel_filename,
 | 
					            kernel_size = load_elf(kernel_filename,
 | 
				
			||||||
                                   translate_kernel_address, NULL,
 | 
					                                   translate_kernel_address, NULL,
 | 
				
			||||||
                                   NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE, 0);
 | 
					                                   NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE,
 | 
				
			||||||
 | 
					                                   0, 0);
 | 
				
			||||||
            kernel_le = kernel_size > 0;
 | 
					            kernel_le = kernel_size > 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (kernel_size < 0) {
 | 
					        if (kernel_size < 0) {
 | 
				
			||||||
 | 
				
			|||||||
@ -258,7 +258,8 @@ static void virtex_init(MachineState *machine)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        /* Boots a kernel elf binary.  */
 | 
					        /* Boots a kernel elf binary.  */
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, NULL, NULL,
 | 
					        kernel_size = load_elf(kernel_filename, NULL, NULL,
 | 
				
			||||||
                               &entry, &low, &high, 1, PPC_ELF_MACHINE, 0);
 | 
					                               &entry, &low, &high, 1, PPC_ELF_MACHINE,
 | 
				
			||||||
 | 
					                               0, 0);
 | 
				
			||||||
        boot_info.bootstrap_pc = entry & 0x00ffffff;
 | 
					        boot_info.bootstrap_pc = entry & 0x00ffffff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (kernel_size < 0) {
 | 
					        if (kernel_size < 0) {
 | 
				
			||||||
 | 
				
			|||||||
@ -101,7 +101,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        bios_size = load_elf(bios_filename, bios_translate_addr, &fwbase,
 | 
					        bios_size = load_elf(bios_filename, bios_translate_addr, &fwbase,
 | 
				
			||||||
                             &ipl->bios_start_addr, NULL, NULL, 1,
 | 
					                             &ipl->bios_start_addr, NULL, NULL, 1,
 | 
				
			||||||
                             EM_S390, 0);
 | 
					                             EM_S390, 0, 0);
 | 
				
			||||||
        if (bios_size > 0) {
 | 
					        if (bios_size > 0) {
 | 
				
			||||||
            /* Adjust ELF start address to final location */
 | 
					            /* Adjust ELF start address to final location */
 | 
				
			||||||
            ipl->bios_start_addr += fwbase;
 | 
					            ipl->bios_start_addr += fwbase;
 | 
				
			||||||
@ -124,7 +124,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (ipl->kernel) {
 | 
					    if (ipl->kernel) {
 | 
				
			||||||
        kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL,
 | 
					        kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL,
 | 
				
			||||||
                               NULL, 1, EM_S390, 0);
 | 
					                               NULL, 1, EM_S390, 0, 0);
 | 
				
			||||||
        if (kernel_size < 0) {
 | 
					        if (kernel_size < 0) {
 | 
				
			||||||
            kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
 | 
					            kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -449,7 +449,7 @@ static void sd_reset(DeviceState *dev)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static bool sd_get_inserted(SDState *sd)
 | 
					static bool sd_get_inserted(SDState *sd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return blk_is_inserted(sd->blk);
 | 
					    return sd->blk && blk_is_inserted(sd->blk);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool sd_get_readonly(SDState *sd)
 | 
					static bool sd_get_readonly(SDState *sd)
 | 
				
			||||||
 | 
				
			|||||||
@ -207,6 +207,21 @@ static void sdhci_reset(SDHCIState *s)
 | 
				
			|||||||
    s->pending_insert_state = false;
 | 
					    s->pending_insert_state = false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void sdhci_poweron_reset(DeviceState *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* QOM (ie power-on) reset. This is identical to reset
 | 
				
			||||||
 | 
					     * commanded via device register apart from handling of the
 | 
				
			||||||
 | 
					     * 'pending insert on powerup' quirk.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    SDHCIState *s = (SDHCIState *)dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sdhci_reset(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (s->pending_insert_quirk) {
 | 
				
			||||||
 | 
					        s->pending_insert_state = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sdhci_data_transfer(void *opaque);
 | 
					static void sdhci_data_transfer(void *opaque);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sdhci_send_command(SDHCIState *s)
 | 
					static void sdhci_send_command(SDHCIState *s)
 | 
				
			||||||
@ -1290,6 +1305,7 @@ static void sdhci_pci_class_init(ObjectClass *klass, void *data)
 | 
				
			|||||||
    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 | 
					    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 | 
				
			||||||
    dc->vmsd = &sdhci_vmstate;
 | 
					    dc->vmsd = &sdhci_vmstate;
 | 
				
			||||||
    dc->props = sdhci_pci_properties;
 | 
					    dc->props = sdhci_pci_properties;
 | 
				
			||||||
 | 
					    dc->reset = sdhci_poweron_reset;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const TypeInfo sdhci_pci_info = {
 | 
					static const TypeInfo sdhci_pci_info = {
 | 
				
			||||||
@ -1332,10 +1348,6 @@ static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp)
 | 
				
			|||||||
    memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci",
 | 
					    memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci",
 | 
				
			||||||
            SDHC_REGISTERS_MAP_SIZE);
 | 
					            SDHC_REGISTERS_MAP_SIZE);
 | 
				
			||||||
    sysbus_init_mmio(sbd, &s->iomem);
 | 
					    sysbus_init_mmio(sbd, &s->iomem);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (s->pending_insert_quirk) {
 | 
					 | 
				
			||||||
        s->pending_insert_state = true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sdhci_sysbus_class_init(ObjectClass *klass, void *data)
 | 
					static void sdhci_sysbus_class_init(ObjectClass *klass, void *data)
 | 
				
			||||||
@ -1345,6 +1357,7 @@ static void sdhci_sysbus_class_init(ObjectClass *klass, void *data)
 | 
				
			|||||||
    dc->vmsd = &sdhci_vmstate;
 | 
					    dc->vmsd = &sdhci_vmstate;
 | 
				
			||||||
    dc->props = sdhci_sysbus_properties;
 | 
					    dc->props = sdhci_sysbus_properties;
 | 
				
			||||||
    dc->realize = sdhci_sysbus_realize;
 | 
					    dc->realize = sdhci_sysbus_realize;
 | 
				
			||||||
 | 
					    dc->reset = sdhci_poweron_reset;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const TypeInfo sdhci_sysbus_info = {
 | 
					static const TypeInfo sdhci_sysbus_info = {
 | 
				
			||||||
 | 
				
			|||||||
@ -194,7 +194,7 @@ static void leon3_generic_hw_init(MachineState *machine)
 | 
				
			|||||||
        uint64_t entry;
 | 
					        uint64_t entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
 | 
					        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
 | 
				
			||||||
                               1 /* big endian */, EM_SPARC, 0);
 | 
					                               1 /* big endian */, EM_SPARC, 0, 0);
 | 
				
			||||||
        if (kernel_size < 0) {
 | 
					        if (kernel_size < 0) {
 | 
				
			||||||
            fprintf(stderr, "qemu: could not load kernel '%s'\n",
 | 
					            fprintf(stderr, "qemu: could not load kernel '%s'\n",
 | 
				
			||||||
                    kernel_filename);
 | 
					                    kernel_filename);
 | 
				
			||||||
 | 
				
			|||||||
@ -279,7 +279,7 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename,
 | 
				
			|||||||
        bswap_needed = 0;
 | 
					        bswap_needed = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
 | 
					        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
 | 
				
			||||||
                               NULL, NULL, NULL, 1, EM_SPARC, 0);
 | 
					                               NULL, NULL, NULL, 1, EM_SPARC, 0, 0);
 | 
				
			||||||
        if (kernel_size < 0)
 | 
					        if (kernel_size < 0)
 | 
				
			||||||
            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
 | 
					            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
 | 
				
			||||||
                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
 | 
					                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
 | 
				
			||||||
@ -723,7 +723,7 @@ static void prom_init(hwaddr addr, const char *bios_name)
 | 
				
			|||||||
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 | 
					    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 | 
				
			||||||
    if (filename) {
 | 
					    if (filename) {
 | 
				
			||||||
        ret = load_elf(filename, translate_prom_address, &addr, NULL,
 | 
					        ret = load_elf(filename, translate_prom_address, &addr, NULL,
 | 
				
			||||||
                       NULL, NULL, 1, EM_SPARC, 0);
 | 
					                       NULL, NULL, 1, EM_SPARC, 0, 0);
 | 
				
			||||||
        if (ret < 0 || ret > PROM_SIZE_MAX) {
 | 
					        if (ret < 0 || ret > PROM_SIZE_MAX) {
 | 
				
			||||||
            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
 | 
					            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -187,7 +187,7 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename,
 | 
				
			|||||||
        bswap_needed = 0;
 | 
					        bswap_needed = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry,
 | 
					        kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry,
 | 
				
			||||||
                               kernel_addr, &kernel_top, 1, EM_SPARCV9, 0);
 | 
					                               kernel_addr, &kernel_top, 1, EM_SPARCV9, 0, 0);
 | 
				
			||||||
        if (kernel_size < 0) {
 | 
					        if (kernel_size < 0) {
 | 
				
			||||||
            *kernel_addr = KERNEL_LOAD_ADDR;
 | 
					            *kernel_addr = KERNEL_LOAD_ADDR;
 | 
				
			||||||
            *kernel_entry = KERNEL_LOAD_ADDR;
 | 
					            *kernel_entry = KERNEL_LOAD_ADDR;
 | 
				
			||||||
@ -633,7 +633,7 @@ static void prom_init(hwaddr addr, const char *bios_name)
 | 
				
			|||||||
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 | 
					    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 | 
				
			||||||
    if (filename) {
 | 
					    if (filename) {
 | 
				
			||||||
        ret = load_elf(filename, translate_prom_address, &addr,
 | 
					        ret = load_elf(filename, translate_prom_address, &addr,
 | 
				
			||||||
                       NULL, NULL, NULL, 1, EM_SPARCV9, 0);
 | 
					                       NULL, NULL, NULL, 1, EM_SPARCV9, 0, 0);
 | 
				
			||||||
        if (ret < 0 || ret > PROM_SIZE_MAX) {
 | 
					        if (ret < 0 || ret > PROM_SIZE_MAX) {
 | 
				
			||||||
            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
 | 
					            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -45,7 +45,7 @@ static void tricore_load_kernel(CPUTriCoreState *env)
 | 
				
			|||||||
    kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL,
 | 
					    kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL,
 | 
				
			||||||
                           NULL, (uint64_t *)&entry, NULL,
 | 
					                           NULL, (uint64_t *)&entry, NULL,
 | 
				
			||||||
                           NULL, 0,
 | 
					                           NULL, 0,
 | 
				
			||||||
                           EM_TRICORE, 1);
 | 
					                           EM_TRICORE, 1, 0);
 | 
				
			||||||
    if (kernel_size <= 0) {
 | 
					    if (kernel_size <= 0) {
 | 
				
			||||||
        error_report("qemu: no kernel file '%s'",
 | 
					        error_report("qemu: no kernel file '%s'",
 | 
				
			||||||
                tricoretb_binfo.kernel_filename);
 | 
					                tricoretb_binfo.kernel_filename);
 | 
				
			||||||
 | 
				
			|||||||
@ -94,10 +94,10 @@ static void xtensa_sim_init(MachineState *machine)
 | 
				
			|||||||
        uint64_t elf_lowaddr;
 | 
					        uint64_t elf_lowaddr;
 | 
				
			||||||
#ifdef TARGET_WORDS_BIGENDIAN
 | 
					#ifdef TARGET_WORDS_BIGENDIAN
 | 
				
			||||||
        int success = load_elf(kernel_filename, translate_phys_addr, cpu,
 | 
					        int success = load_elf(kernel_filename, translate_phys_addr, cpu,
 | 
				
			||||||
                &elf_entry, &elf_lowaddr, NULL, 1, EM_XTENSA, 0);
 | 
					                &elf_entry, &elf_lowaddr, NULL, 1, EM_XTENSA, 0, 0);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
        int success = load_elf(kernel_filename, translate_phys_addr, cpu,
 | 
					        int success = load_elf(kernel_filename, translate_phys_addr, cpu,
 | 
				
			||||||
                &elf_entry, &elf_lowaddr, NULL, 0, EM_XTENSA, 0);
 | 
					                &elf_entry, &elf_lowaddr, NULL, 0, EM_XTENSA, 0, 0);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        if (success > 0) {
 | 
					        if (success > 0) {
 | 
				
			||||||
            env->pc = elf_entry;
 | 
					            env->pc = elf_entry;
 | 
				
			||||||
 | 
				
			|||||||
@ -355,7 +355,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
 | 
				
			|||||||
        uint64_t elf_entry;
 | 
					        uint64_t elf_entry;
 | 
				
			||||||
        uint64_t elf_lowaddr;
 | 
					        uint64_t elf_lowaddr;
 | 
				
			||||||
        int success = load_elf(kernel_filename, translate_phys_addr, cpu,
 | 
					        int success = load_elf(kernel_filename, translate_phys_addr, cpu,
 | 
				
			||||||
                &elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0);
 | 
					                &elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0, 0);
 | 
				
			||||||
        if (success > 0) {
 | 
					        if (success > 0) {
 | 
				
			||||||
            entry_point = elf_entry;
 | 
					            entry_point = elf_entry;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,13 @@
 | 
				
			|||||||
#include "qemu/notify.h"
 | 
					#include "qemu/notify.h"
 | 
				
			||||||
#include "cpu.h"
 | 
					#include "cpu.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum {
 | 
				
			||||||
 | 
					    ARM_ENDIANNESS_UNKNOWN = 0,
 | 
				
			||||||
 | 
					    ARM_ENDIANNESS_LE,
 | 
				
			||||||
 | 
					    ARM_ENDIANNESS_BE8,
 | 
				
			||||||
 | 
					    ARM_ENDIANNESS_BE32,
 | 
				
			||||||
 | 
					} arm_endianness;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* armv7m.c */
 | 
					/* armv7m.c */
 | 
				
			||||||
DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
 | 
					DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
 | 
				
			||||||
                      const char *kernel_filename, const char *cpu_model);
 | 
					                      const char *kernel_filename, const char *cpu_model);
 | 
				
			||||||
@ -103,6 +110,8 @@ struct arm_boot_info {
 | 
				
			|||||||
     * changing to non-secure state if implementing a non-secure boot
 | 
					     * changing to non-secure state if implementing a non-secure boot
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    bool secure_board_setup;
 | 
					    bool secure_board_setup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    arm_endianness endianness;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
				
			|||||||
@ -61,6 +61,7 @@ enum {
 | 
				
			|||||||
    VIRT_PCIE_MMIO_HIGH,
 | 
					    VIRT_PCIE_MMIO_HIGH,
 | 
				
			||||||
    VIRT_GPIO,
 | 
					    VIRT_GPIO,
 | 
				
			||||||
    VIRT_SECURE_UART,
 | 
					    VIRT_SECURE_UART,
 | 
				
			||||||
 | 
					    VIRT_SECURE_MEM,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct MemMapEntry {
 | 
					typedef struct MemMapEntry {
 | 
				
			||||||
 | 
				
			|||||||
@ -263,7 +263,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
 | 
				
			|||||||
                              void *translate_opaque,
 | 
					                              void *translate_opaque,
 | 
				
			||||||
                              int must_swab, uint64_t *pentry,
 | 
					                              int must_swab, uint64_t *pentry,
 | 
				
			||||||
                              uint64_t *lowaddr, uint64_t *highaddr,
 | 
					                              uint64_t *lowaddr, uint64_t *highaddr,
 | 
				
			||||||
                              int elf_machine, int clear_lsb)
 | 
					                              int elf_machine, int clear_lsb, int data_swab)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct elfhdr ehdr;
 | 
					    struct elfhdr ehdr;
 | 
				
			||||||
    struct elf_phdr *phdr = NULL, *ph;
 | 
					    struct elf_phdr *phdr = NULL, *ph;
 | 
				
			||||||
@ -366,6 +366,26 @@ static int glue(load_elf, SZ)(const char *name, int fd,
 | 
				
			|||||||
                addr = ph->p_paddr;
 | 
					                addr = ph->p_paddr;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (data_swab) {
 | 
				
			||||||
 | 
					                int j;
 | 
				
			||||||
 | 
					                for (j = 0; j < file_size; j += (1 << data_swab)) {
 | 
				
			||||||
 | 
					                    uint8_t *dp = data + j;
 | 
				
			||||||
 | 
					                    switch (data_swab) {
 | 
				
			||||||
 | 
					                    case (1):
 | 
				
			||||||
 | 
					                        *(uint16_t *)dp = bswap16(*(uint16_t *)dp);
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    case (2):
 | 
				
			||||||
 | 
					                        *(uint32_t *)dp = bswap32(*(uint32_t *)dp);
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    case (3):
 | 
				
			||||||
 | 
					                        *(uint64_t *)dp = bswap64(*(uint64_t *)dp);
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    default:
 | 
				
			||||||
 | 
					                        g_assert_not_reached();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* the entry pointer in the ELF header is a virtual
 | 
					            /* the entry pointer in the ELF header is a virtual
 | 
				
			||||||
             * address, if the text segments paddr and vaddr differ
 | 
					             * address, if the text segments paddr and vaddr differ
 | 
				
			||||||
             * we need to adjust the entry */
 | 
					             * we need to adjust the entry */
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,18 @@ int load_image(const char *filename, uint8_t *addr); /* deprecated */
 | 
				
			|||||||
ssize_t load_image_size(const char *filename, void *addr, size_t size);
 | 
					ssize_t load_image_size(const char *filename, void *addr, size_t size);
 | 
				
			||||||
int load_image_targphys(const char *filename, hwaddr,
 | 
					int load_image_targphys(const char *filename, hwaddr,
 | 
				
			||||||
                        uint64_t max_sz);
 | 
					                        uint64_t max_sz);
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * load_image_mr: load an image into a memory region
 | 
				
			||||||
 | 
					 * @filename: Path to the image file
 | 
				
			||||||
 | 
					 * @mr: Memory Region to load into
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Load the specified file into the memory region.
 | 
				
			||||||
 | 
					 * The file loaded is registered as a ROM, so its contents will be
 | 
				
			||||||
 | 
					 * reinstated whenever the system is reset.
 | 
				
			||||||
 | 
					 * If the file is larger than the memory region's size the call will fail.
 | 
				
			||||||
 | 
					 * Returns -1 on failure, or the size of the file.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int load_image_mr(const char *filename, MemoryRegion *mr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This is the limit on the maximum uncompressed image size that
 | 
					/* This is the limit on the maximum uncompressed image size that
 | 
				
			||||||
 * load_image_gzipped_buffer() and load_image_gzipped() will read. It prevents
 | 
					 * load_image_gzipped_buffer() and load_image_gzipped() will read. It prevents
 | 
				
			||||||
@ -32,10 +44,49 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
 | 
				
			|||||||
#define ELF_LOAD_WRONG_ARCH   -3
 | 
					#define ELF_LOAD_WRONG_ARCH   -3
 | 
				
			||||||
#define ELF_LOAD_WRONG_ENDIAN -4
 | 
					#define ELF_LOAD_WRONG_ENDIAN -4
 | 
				
			||||||
const char *load_elf_strerror(int error);
 | 
					const char *load_elf_strerror(int error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** load_elf:
 | 
				
			||||||
 | 
					 * @filename: Path of ELF file
 | 
				
			||||||
 | 
					 * @translate_fn: optional function to translate load addresses
 | 
				
			||||||
 | 
					 * @translate_opaque: opaque data passed to @translate_fn
 | 
				
			||||||
 | 
					 * @pentry: Populated with program entry point. Ignored if NULL.
 | 
				
			||||||
 | 
					 * @lowaddr: Populated with lowest loaded address. Ignored if NULL.
 | 
				
			||||||
 | 
					 * @highaddr: Populated with highest loaded address. Ignored if NULL.
 | 
				
			||||||
 | 
					 * @bigendian: Expected ELF endianness. 0 for LE otherwise BE
 | 
				
			||||||
 | 
					 * @elf_machine: Expected ELF machine type
 | 
				
			||||||
 | 
					 * @clear_lsb: Set to mask off LSB of addresses (Some architectures use
 | 
				
			||||||
 | 
					 *             this for non-address data)
 | 
				
			||||||
 | 
					 * @data_swab: Set to order of byte swapping for data. 0 for no swap, 1
 | 
				
			||||||
 | 
					 *             for swapping bytes within halfwords, 2 for bytes within
 | 
				
			||||||
 | 
					 *             words and 3 for within doublewords.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Load an ELF file's contents to the emulated system's address space.
 | 
				
			||||||
 | 
					 * Clients may optionally specify a callback to perform address
 | 
				
			||||||
 | 
					 * translations. @pentry, @lowaddr and @highaddr are optional pointers
 | 
				
			||||||
 | 
					 * which will be populated with various load information. @bigendian and
 | 
				
			||||||
 | 
					 * @elf_machine give the expected endianness and machine for the ELF the
 | 
				
			||||||
 | 
					 * load will fail if the target ELF does not match. Some architectures
 | 
				
			||||||
 | 
					 * have some architecture-specific behaviours that come into effect when
 | 
				
			||||||
 | 
					 * their particular values for @elf_machine are set.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
					int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
 | 
				
			||||||
             void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
 | 
					             void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
 | 
				
			||||||
             uint64_t *highaddr, int big_endian, int elf_machine,
 | 
					             uint64_t *highaddr, int big_endian, int elf_machine,
 | 
				
			||||||
             int clear_lsb);
 | 
					             int clear_lsb, int data_swab);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** load_elf_hdr:
 | 
				
			||||||
 | 
					 * @filename: Path of ELF file
 | 
				
			||||||
 | 
					 * @hdr: Buffer to populate with header data. Header data will not be
 | 
				
			||||||
 | 
					 * filled if set to NULL.
 | 
				
			||||||
 | 
					 * @is64: Set to true if the ELF is 64bit. Ignored if set to NULL
 | 
				
			||||||
 | 
					 * @errp: Populated with an error in failure cases
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Inspect an ELF file's header. Read its full header contents into a
 | 
				
			||||||
 | 
					 * buffer and/or determine if the ELF is 64bit.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int load_aout(const char *filename, hwaddr addr, int max_sz,
 | 
					int load_aout(const char *filename, hwaddr addr, int max_sz,
 | 
				
			||||||
              int bswap_needed, hwaddr target_page_size);
 | 
					              int bswap_needed, hwaddr target_page_size);
 | 
				
			||||||
int load_uimage(const char *filename, hwaddr *ep,
 | 
					int load_uimage(const char *filename, hwaddr *ep,
 | 
				
			||||||
@ -67,7 +118,7 @@ extern bool rom_file_has_mr;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int rom_add_file(const char *file, const char *fw_dir,
 | 
					int rom_add_file(const char *file, const char *fw_dir,
 | 
				
			||||||
                 hwaddr addr, int32_t bootindex,
 | 
					                 hwaddr addr, int32_t bootindex,
 | 
				
			||||||
                 bool option_rom);
 | 
					                 bool option_rom, MemoryRegion *mr);
 | 
				
			||||||
MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
 | 
					MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
 | 
				
			||||||
                           size_t max_len, hwaddr addr,
 | 
					                           size_t max_len, hwaddr addr,
 | 
				
			||||||
                           const char *fw_file_name,
 | 
					                           const char *fw_file_name,
 | 
				
			||||||
@ -82,9 +133,11 @@ void *rom_ptr(hwaddr addr);
 | 
				
			|||||||
void hmp_info_roms(Monitor *mon, const QDict *qdict);
 | 
					void hmp_info_roms(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define rom_add_file_fixed(_f, _a, _i)          \
 | 
					#define rom_add_file_fixed(_f, _a, _i)          \
 | 
				
			||||||
    rom_add_file(_f, NULL, _a, _i, false)
 | 
					    rom_add_file(_f, NULL, _a, _i, false, NULL)
 | 
				
			||||||
#define rom_add_blob_fixed(_f, _b, _l, _a)      \
 | 
					#define rom_add_blob_fixed(_f, _b, _l, _a)      \
 | 
				
			||||||
    rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL)
 | 
					    rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL)
 | 
				
			||||||
 | 
					#define rom_add_file_mr(_f, _mr, _i)            \
 | 
				
			||||||
 | 
					    rom_add_file(_f, NULL, 0, _i, false, mr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PC_ROM_MIN_VGA     0xc0000
 | 
					#define PC_ROM_MIN_VGA     0xc0000
 | 
				
			||||||
#define PC_ROM_MIN_OPTION  0xc8000
 | 
					#define PC_ROM_MIN_OPTION  0xc8000
 | 
				
			||||||
 | 
				
			|||||||
@ -435,22 +435,54 @@ void cpu_loop(CPUX86State *env)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#ifdef TARGET_ARM
 | 
					#ifdef TARGET_ARM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define get_user_code_u32(x, gaddr, doswap)             \
 | 
					#define get_user_code_u32(x, gaddr, env)                \
 | 
				
			||||||
    ({ abi_long __r = get_user_u32((x), (gaddr));       \
 | 
					    ({ abi_long __r = get_user_u32((x), (gaddr));       \
 | 
				
			||||||
        if (!__r && (doswap)) {                         \
 | 
					        if (!__r && bswap_code(arm_sctlr_b(env))) {     \
 | 
				
			||||||
            (x) = bswap32(x);                           \
 | 
					            (x) = bswap32(x);                           \
 | 
				
			||||||
        }                                               \
 | 
					        }                                               \
 | 
				
			||||||
        __r;                                            \
 | 
					        __r;                                            \
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define get_user_code_u16(x, gaddr, doswap)             \
 | 
					#define get_user_code_u16(x, gaddr, env)                \
 | 
				
			||||||
    ({ abi_long __r = get_user_u16((x), (gaddr));       \
 | 
					    ({ abi_long __r = get_user_u16((x), (gaddr));       \
 | 
				
			||||||
        if (!__r && (doswap)) {                         \
 | 
					        if (!__r && bswap_code(arm_sctlr_b(env))) {     \
 | 
				
			||||||
            (x) = bswap16(x);                           \
 | 
					            (x) = bswap16(x);                           \
 | 
				
			||||||
        }                                               \
 | 
					        }                                               \
 | 
				
			||||||
        __r;                                            \
 | 
					        __r;                                            \
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define get_user_data_u32(x, gaddr, env)                \
 | 
				
			||||||
 | 
					    ({ abi_long __r = get_user_u32((x), (gaddr));       \
 | 
				
			||||||
 | 
					        if (!__r && arm_cpu_bswap_data(env)) {          \
 | 
				
			||||||
 | 
					            (x) = bswap32(x);                           \
 | 
				
			||||||
 | 
					        }                                               \
 | 
				
			||||||
 | 
					        __r;                                            \
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define get_user_data_u16(x, gaddr, env)                \
 | 
				
			||||||
 | 
					    ({ abi_long __r = get_user_u16((x), (gaddr));       \
 | 
				
			||||||
 | 
					        if (!__r && arm_cpu_bswap_data(env)) {          \
 | 
				
			||||||
 | 
					            (x) = bswap16(x);                           \
 | 
				
			||||||
 | 
					        }                                               \
 | 
				
			||||||
 | 
					        __r;                                            \
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define put_user_data_u32(x, gaddr, env)                \
 | 
				
			||||||
 | 
					    ({ typeof(x) __x = (x);                             \
 | 
				
			||||||
 | 
					        if (arm_cpu_bswap_data(env)) {                  \
 | 
				
			||||||
 | 
					            __x = bswap32(__x);                         \
 | 
				
			||||||
 | 
					        }                                               \
 | 
				
			||||||
 | 
					        put_user_u32(__x, (gaddr));                     \
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define put_user_data_u16(x, gaddr, env)                \
 | 
				
			||||||
 | 
					    ({ typeof(x) __x = (x);                             \
 | 
				
			||||||
 | 
					        if (arm_cpu_bswap_data(env)) {                  \
 | 
				
			||||||
 | 
					            __x = bswap16(__x);                         \
 | 
				
			||||||
 | 
					        }                                               \
 | 
				
			||||||
 | 
					        put_user_u16(__x, (gaddr));                     \
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef TARGET_ABI32
 | 
					#ifdef TARGET_ABI32
 | 
				
			||||||
/* Commpage handling -- there is no commpage for AArch64 */
 | 
					/* Commpage handling -- there is no commpage for AArch64 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -610,11 +642,11 @@ static int do_strex(CPUARMState *env)
 | 
				
			|||||||
        segv = get_user_u8(val, addr);
 | 
					        segv = get_user_u8(val, addr);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 1:
 | 
					    case 1:
 | 
				
			||||||
        segv = get_user_u16(val, addr);
 | 
					        segv = get_user_data_u16(val, addr, env);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 2:
 | 
					    case 2:
 | 
				
			||||||
    case 3:
 | 
					    case 3:
 | 
				
			||||||
        segv = get_user_u32(val, addr);
 | 
					        segv = get_user_data_u32(val, addr, env);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        abort();
 | 
					        abort();
 | 
				
			||||||
@ -625,13 +657,17 @@ static int do_strex(CPUARMState *env)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    if (size == 3) {
 | 
					    if (size == 3) {
 | 
				
			||||||
        uint32_t valhi;
 | 
					        uint32_t valhi;
 | 
				
			||||||
        segv = get_user_u32(valhi, addr + 4);
 | 
					        segv = get_user_data_u32(valhi, addr + 4, env);
 | 
				
			||||||
        if (segv) {
 | 
					        if (segv) {
 | 
				
			||||||
            env->exception.vaddress = addr + 4;
 | 
					            env->exception.vaddress = addr + 4;
 | 
				
			||||||
            goto done;
 | 
					            goto done;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (arm_cpu_bswap_data(env)) {
 | 
				
			||||||
 | 
					            val = deposit64((uint64_t)valhi, 32, 32, val);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
            val = deposit64(val, 32, 32, valhi);
 | 
					            val = deposit64(val, 32, 32, valhi);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (val != env->exclusive_val) {
 | 
					    if (val != env->exclusive_val) {
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -642,11 +678,11 @@ static int do_strex(CPUARMState *env)
 | 
				
			|||||||
        segv = put_user_u8(val, addr);
 | 
					        segv = put_user_u8(val, addr);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 1:
 | 
					    case 1:
 | 
				
			||||||
        segv = put_user_u16(val, addr);
 | 
					        segv = put_user_data_u16(val, addr, env);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 2:
 | 
					    case 2:
 | 
				
			||||||
    case 3:
 | 
					    case 3:
 | 
				
			||||||
        segv = put_user_u32(val, addr);
 | 
					        segv = put_user_data_u32(val, addr, env);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (segv) {
 | 
					    if (segv) {
 | 
				
			||||||
@ -655,7 +691,7 @@ static int do_strex(CPUARMState *env)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    if (size == 3) {
 | 
					    if (size == 3) {
 | 
				
			||||||
        val = env->regs[(env->exclusive_info >> 12) & 0xf];
 | 
					        val = env->regs[(env->exclusive_info >> 12) & 0xf];
 | 
				
			||||||
        segv = put_user_u32(val, addr + 4);
 | 
					        segv = put_user_data_u32(val, addr + 4, env);
 | 
				
			||||||
        if (segv) {
 | 
					        if (segv) {
 | 
				
			||||||
            env->exception.vaddress = addr + 4;
 | 
					            env->exception.vaddress = addr + 4;
 | 
				
			||||||
            goto done;
 | 
					            goto done;
 | 
				
			||||||
@ -692,7 +728,7 @@ void cpu_loop(CPUARMState *env)
 | 
				
			|||||||
                /* we handle the FPU emulation here, as Linux */
 | 
					                /* we handle the FPU emulation here, as Linux */
 | 
				
			||||||
                /* we get the opcode */
 | 
					                /* we get the opcode */
 | 
				
			||||||
                /* FIXME - what to do if get_user() fails? */
 | 
					                /* FIXME - what to do if get_user() fails? */
 | 
				
			||||||
                get_user_code_u32(opcode, env->regs[15], env->bswap_code);
 | 
					                get_user_code_u32(opcode, env->regs[15], env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                rc = EmulateAll(opcode, &ts->fpa, env);
 | 
					                rc = EmulateAll(opcode, &ts->fpa, env);
 | 
				
			||||||
                if (rc == 0) { /* illegal instruction */
 | 
					                if (rc == 0) { /* illegal instruction */
 | 
				
			||||||
@ -762,25 +798,23 @@ void cpu_loop(CPUARMState *env)
 | 
				
			|||||||
                if (trapnr == EXCP_BKPT) {
 | 
					                if (trapnr == EXCP_BKPT) {
 | 
				
			||||||
                    if (env->thumb) {
 | 
					                    if (env->thumb) {
 | 
				
			||||||
                        /* FIXME - what to do if get_user() fails? */
 | 
					                        /* FIXME - what to do if get_user() fails? */
 | 
				
			||||||
                        get_user_code_u16(insn, env->regs[15], env->bswap_code);
 | 
					                        get_user_code_u16(insn, env->regs[15], env);
 | 
				
			||||||
                        n = insn & 0xff;
 | 
					                        n = insn & 0xff;
 | 
				
			||||||
                        env->regs[15] += 2;
 | 
					                        env->regs[15] += 2;
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        /* FIXME - what to do if get_user() fails? */
 | 
					                        /* FIXME - what to do if get_user() fails? */
 | 
				
			||||||
                        get_user_code_u32(insn, env->regs[15], env->bswap_code);
 | 
					                        get_user_code_u32(insn, env->regs[15], env);
 | 
				
			||||||
                        n = (insn & 0xf) | ((insn >> 4) & 0xff0);
 | 
					                        n = (insn & 0xf) | ((insn >> 4) & 0xff0);
 | 
				
			||||||
                        env->regs[15] += 4;
 | 
					                        env->regs[15] += 4;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    if (env->thumb) {
 | 
					                    if (env->thumb) {
 | 
				
			||||||
                        /* FIXME - what to do if get_user() fails? */
 | 
					                        /* FIXME - what to do if get_user() fails? */
 | 
				
			||||||
                        get_user_code_u16(insn, env->regs[15] - 2,
 | 
					                        get_user_code_u16(insn, env->regs[15] - 2, env);
 | 
				
			||||||
                                          env->bswap_code);
 | 
					 | 
				
			||||||
                        n = insn & 0xff;
 | 
					                        n = insn & 0xff;
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        /* FIXME - what to do if get_user() fails? */
 | 
					                        /* FIXME - what to do if get_user() fails? */
 | 
				
			||||||
                        get_user_code_u32(insn, env->regs[15] - 4,
 | 
					                        get_user_code_u32(insn, env->regs[15] - 4, env);
 | 
				
			||||||
                                          env->bswap_code);
 | 
					 | 
				
			||||||
                        n = insn & 0xffffff;
 | 
					                        n = insn & 0xffffff;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -4451,11 +4485,16 @@ int main(int argc, char **argv, char **envp)
 | 
				
			|||||||
        for(i = 0; i < 16; i++) {
 | 
					        for(i = 0; i < 16; i++) {
 | 
				
			||||||
            env->regs[i] = regs->uregs[i];
 | 
					            env->regs[i] = regs->uregs[i];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					#ifdef TARGET_WORDS_BIGENDIAN
 | 
				
			||||||
        /* Enable BE8.  */
 | 
					        /* Enable BE8.  */
 | 
				
			||||||
        if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
 | 
					        if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
 | 
				
			||||||
            && (info->elf_flags & EF_ARM_BE8)) {
 | 
					            && (info->elf_flags & EF_ARM_BE8)) {
 | 
				
			||||||
            env->bswap_code = 1;
 | 
					            env->uncached_cpsr |= CPSR_E;
 | 
				
			||||||
 | 
					            env->cp15.sctlr_el[1] |= SCTLR_E0E;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            env->cp15.sctlr_el[1] |= SCTLR_B;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#elif defined(TARGET_UNICORE32)
 | 
					#elif defined(TARGET_UNICORE32)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -1570,8 +1570,9 @@ get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
 | 
				
			|||||||
    /*
 | 
					    /*
 | 
				
			||||||
     * This is the X/Open sanctioned signal stack switching.
 | 
					     * This is the X/Open sanctioned signal stack switching.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
	if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
 | 
					    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
 | 
				
			||||||
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
 | 
					        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
     * ATPCS B01 mandates 8-byte alignment
 | 
					     * ATPCS B01 mandates 8-byte alignment
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -1599,8 +1600,9 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
 | 
				
			|||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        unsigned int idx = thumb;
 | 
					        unsigned int idx = thumb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (ka->sa_flags & TARGET_SA_SIGINFO)
 | 
					        if (ka->sa_flags & TARGET_SA_SIGINFO) {
 | 
				
			||||||
            idx += 2;
 | 
					            idx += 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        __put_user(retcodes[idx], rc);
 | 
					        __put_user(retcodes[idx], rc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,10 +25,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Load an instruction and return it in the standard little-endian order */
 | 
					/* Load an instruction and return it in the standard little-endian order */
 | 
				
			||||||
static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
 | 
					static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
 | 
				
			||||||
                                    bool do_swap)
 | 
					                                    bool sctlr_b)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t insn = cpu_ldl_code(env, addr);
 | 
					    uint32_t insn = cpu_ldl_code(env, addr);
 | 
				
			||||||
    if (do_swap) {
 | 
					    if (bswap_code(sctlr_b)) {
 | 
				
			||||||
        return bswap32(insn);
 | 
					        return bswap32(insn);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return insn;
 | 
					    return insn;
 | 
				
			||||||
@ -36,10 +36,10 @@ static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Ditto, for a halfword (Thumb) instruction */
 | 
					/* Ditto, for a halfword (Thumb) instruction */
 | 
				
			||||||
static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
 | 
					static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
 | 
				
			||||||
                                     bool do_swap)
 | 
					                                     bool sctlr_b)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint16_t insn = cpu_lduw_code(env, addr);
 | 
					    uint16_t insn = cpu_lduw_code(env, addr);
 | 
				
			||||||
    if (do_swap) {
 | 
					    if (bswap_code(sctlr_b)) {
 | 
				
			||||||
        return bswap16(insn);
 | 
					        return bswap16(insn);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return insn;
 | 
					    return insn;
 | 
				
			||||||
 | 
				
			|||||||
@ -369,26 +369,13 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool arm_cpu_is_big_endian(CPUState *cs)
 | 
					static bool arm_cpu_virtio_is_big_endian(CPUState *cs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ARMCPU *cpu = ARM_CPU(cs);
 | 
					    ARMCPU *cpu = ARM_CPU(cs);
 | 
				
			||||||
    CPUARMState *env = &cpu->env;
 | 
					    CPUARMState *env = &cpu->env;
 | 
				
			||||||
    int cur_el;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cpu_synchronize_state(cs);
 | 
					    cpu_synchronize_state(cs);
 | 
				
			||||||
 | 
					    return arm_cpu_data_is_big_endian(env);
 | 
				
			||||||
    /* In 32bit guest endianness is determined by looking at CPSR's E bit */
 | 
					 | 
				
			||||||
    if (!is_a64(env)) {
 | 
					 | 
				
			||||||
        return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cur_el = arm_current_el(env);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (cur_el == 0) {
 | 
					 | 
				
			||||||
        return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -427,7 +414,7 @@ static void arm_disas_set_info(CPUState *cpu, disassemble_info *info)
 | 
				
			|||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        info->print_insn = print_insn_arm;
 | 
					        info->print_insn = print_insn_arm;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (env->bswap_code) {
 | 
					    if (bswap_code(arm_sctlr_b(env))) {
 | 
				
			||||||
#ifdef TARGET_WORDS_BIGENDIAN
 | 
					#ifdef TARGET_WORDS_BIGENDIAN
 | 
				
			||||||
        info->endian = BFD_ENDIAN_LITTLE;
 | 
					        info->endian = BFD_ENDIAN_LITTLE;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
@ -1476,7 +1463,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
 | 
				
			|||||||
    cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug;
 | 
					    cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug;
 | 
				
			||||||
    cc->asidx_from_attrs = arm_asidx_from_attrs;
 | 
					    cc->asidx_from_attrs = arm_asidx_from_attrs;
 | 
				
			||||||
    cc->vmsd = &vmstate_arm_cpu;
 | 
					    cc->vmsd = &vmstate_arm_cpu;
 | 
				
			||||||
    cc->virtio_is_big_endian = arm_cpu_is_big_endian;
 | 
					    cc->virtio_is_big_endian = arm_cpu_virtio_is_big_endian;
 | 
				
			||||||
    cc->write_elf64_note = arm_cpu_write_elf64_note;
 | 
					    cc->write_elf64_note = arm_cpu_write_elf64_note;
 | 
				
			||||||
    cc->write_elf32_note = arm_cpu_write_elf32_note;
 | 
					    cc->write_elf32_note = arm_cpu_write_elf32_note;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -478,9 +478,6 @@ typedef struct CPUARMState {
 | 
				
			|||||||
        uint32_t cregs[16];
 | 
					        uint32_t cregs[16];
 | 
				
			||||||
    } iwmmxt;
 | 
					    } iwmmxt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* For mixed endian mode.  */
 | 
					 | 
				
			||||||
    bool bswap_code;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(CONFIG_USER_ONLY)
 | 
					#if defined(CONFIG_USER_ONLY)
 | 
				
			||||||
    /* For usermode syscall translation.  */
 | 
					    /* For usermode syscall translation.  */
 | 
				
			||||||
    int eabi;
 | 
					    int eabi;
 | 
				
			||||||
@ -1898,6 +1895,53 @@ static inline bool arm_singlestep_active(CPUARMState *env)
 | 
				
			|||||||
        && arm_generate_debug_exceptions(env);
 | 
					        && arm_generate_debug_exceptions(env);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool arm_sctlr_b(CPUARMState *env)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return
 | 
				
			||||||
 | 
					        /* We need not implement SCTLR.ITD in user-mode emulation, so
 | 
				
			||||||
 | 
					         * let linux-user ignore the fact that it conflicts with SCTLR_B.
 | 
				
			||||||
 | 
					         * This lets people run BE32 binaries with "-cpu any".
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					#ifndef CONFIG_USER_ONLY
 | 
				
			||||||
 | 
					        !arm_feature(env, ARM_FEATURE_V7) &&
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        (env->cp15.sctlr_el[1] & SCTLR_B) != 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Return true if the processor is in big-endian mode. */
 | 
				
			||||||
 | 
					static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int cur_el;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* In 32bit endianness is determined by looking at CPSR's E bit */
 | 
				
			||||||
 | 
					    if (!is_a64(env)) {
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					#ifdef CONFIG_USER_ONLY
 | 
				
			||||||
 | 
					            /* In system mode, BE32 is modelled in line with the
 | 
				
			||||||
 | 
					             * architecture (as word-invariant big-endianness), where loads
 | 
				
			||||||
 | 
					             * and stores are done little endian but from addresses which
 | 
				
			||||||
 | 
					             * are adjusted by XORing with the appropriate constant. So the
 | 
				
			||||||
 | 
					             * endianness to use for the raw data access is not affected by
 | 
				
			||||||
 | 
					             * SCTLR.B.
 | 
				
			||||||
 | 
					             * In user mode, however, we model BE32 as byte-invariant
 | 
				
			||||||
 | 
					             * big-endianness (because user-only code cannot tell the
 | 
				
			||||||
 | 
					             * difference), and so we need to use a data access endianness
 | 
				
			||||||
 | 
					             * that depends on SCTLR.B.
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            arm_sctlr_b(env) ||
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					                ((env->uncached_cpsr & CPSR_E) ? 1 : 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cur_el = arm_current_el(env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (cur_el == 0) {
 | 
				
			||||||
 | 
					        return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "exec/cpu-all.h"
 | 
					#include "exec/cpu-all.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Bit usage in the TB flags field: bit 31 indicates whether we are
 | 
					/* Bit usage in the TB flags field: bit 31 indicates whether we are
 | 
				
			||||||
@ -1928,8 +1972,8 @@ static inline bool arm_singlestep_active(CPUARMState *env)
 | 
				
			|||||||
#define ARM_TBFLAG_VFPEN_MASK       (1 << ARM_TBFLAG_VFPEN_SHIFT)
 | 
					#define ARM_TBFLAG_VFPEN_MASK       (1 << ARM_TBFLAG_VFPEN_SHIFT)
 | 
				
			||||||
#define ARM_TBFLAG_CONDEXEC_SHIFT   8
 | 
					#define ARM_TBFLAG_CONDEXEC_SHIFT   8
 | 
				
			||||||
#define ARM_TBFLAG_CONDEXEC_MASK    (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
 | 
					#define ARM_TBFLAG_CONDEXEC_MASK    (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
 | 
				
			||||||
#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
 | 
					#define ARM_TBFLAG_SCTLR_B_SHIFT    16
 | 
				
			||||||
#define ARM_TBFLAG_BSWAP_CODE_MASK  (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
 | 
					#define ARM_TBFLAG_SCTLR_B_MASK     (1 << ARM_TBFLAG_SCTLR_B_SHIFT)
 | 
				
			||||||
/* We store the bottom two bits of the CPAR as TB flags and handle
 | 
					/* We store the bottom two bits of the CPAR as TB flags and handle
 | 
				
			||||||
 * checks on the other bits at runtime
 | 
					 * checks on the other bits at runtime
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -1941,6 +1985,8 @@ static inline bool arm_singlestep_active(CPUARMState *env)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
#define ARM_TBFLAG_NS_SHIFT         19
 | 
					#define ARM_TBFLAG_NS_SHIFT         19
 | 
				
			||||||
#define ARM_TBFLAG_NS_MASK          (1 << ARM_TBFLAG_NS_SHIFT)
 | 
					#define ARM_TBFLAG_NS_MASK          (1 << ARM_TBFLAG_NS_SHIFT)
 | 
				
			||||||
 | 
					#define ARM_TBFLAG_BE_DATA_SHIFT    20
 | 
				
			||||||
 | 
					#define ARM_TBFLAG_BE_DATA_MASK     (1 << ARM_TBFLAG_BE_DATA_SHIFT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Bit usage when in AArch64 state: currently we have no A64 specific bits */
 | 
					/* Bit usage when in AArch64 state: currently we have no A64 specific bits */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1965,12 +2011,34 @@ static inline bool arm_singlestep_active(CPUARMState *env)
 | 
				
			|||||||
    (((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT)
 | 
					    (((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT)
 | 
				
			||||||
#define ARM_TBFLAG_CONDEXEC(F) \
 | 
					#define ARM_TBFLAG_CONDEXEC(F) \
 | 
				
			||||||
    (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
 | 
					    (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
 | 
				
			||||||
#define ARM_TBFLAG_BSWAP_CODE(F) \
 | 
					#define ARM_TBFLAG_SCTLR_B(F) \
 | 
				
			||||||
    (((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
 | 
					    (((F) & ARM_TBFLAG_SCTLR_B_MASK) >> ARM_TBFLAG_SCTLR_B_SHIFT)
 | 
				
			||||||
#define ARM_TBFLAG_XSCALE_CPAR(F) \
 | 
					#define ARM_TBFLAG_XSCALE_CPAR(F) \
 | 
				
			||||||
    (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
 | 
					    (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
 | 
				
			||||||
#define ARM_TBFLAG_NS(F) \
 | 
					#define ARM_TBFLAG_NS(F) \
 | 
				
			||||||
    (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
 | 
					    (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
 | 
				
			||||||
 | 
					#define ARM_TBFLAG_BE_DATA(F) \
 | 
				
			||||||
 | 
					    (((F) & ARM_TBFLAG_BE_DATA_MASK) >> ARM_TBFLAG_BE_DATA_SHIFT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool bswap_code(bool sctlr_b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifdef CONFIG_USER_ONLY
 | 
				
			||||||
 | 
					    /* BE8 (SCTLR.B = 0, TARGET_WORDS_BIGENDIAN = 1) is mixed endian.
 | 
				
			||||||
 | 
					     * The invalid combination SCTLR.B=1/CPSR.E=1/TARGET_WORDS_BIGENDIAN=0
 | 
				
			||||||
 | 
					     * would also end up as a mixed-endian mode with BE code, LE data.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    return
 | 
				
			||||||
 | 
					#ifdef TARGET_WORDS_BIGENDIAN
 | 
				
			||||||
 | 
					        1 ^
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        sctlr_b;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    /* All code access in ARM is little endian, and there are no loaders
 | 
				
			||||||
 | 
					     * doing swaps that need to be reversed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Return the exception level to which FP-disabled exceptions should
 | 
					/* Return the exception level to which FP-disabled exceptions should
 | 
				
			||||||
 * be taken, or 0 if FP is enabled.
 | 
					 * be taken, or 0 if FP is enabled.
 | 
				
			||||||
@ -2037,6 +2105,17 @@ static inline int fp_exception_el(CPUARMState *env)
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_USER_ONLY
 | 
				
			||||||
 | 
					static inline bool arm_cpu_bswap_data(CPUARMState *env)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return
 | 
				
			||||||
 | 
					#ifdef TARGET_WORDS_BIGENDIAN
 | 
				
			||||||
 | 
					       1 ^
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					       arm_cpu_data_is_big_endian(env);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
 | 
					static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
 | 
				
			||||||
                                        target_ulong *cs_base, int *flags)
 | 
					                                        target_ulong *cs_base, int *flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -2049,7 +2128,7 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
 | 
				
			|||||||
            | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
 | 
					            | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
 | 
				
			||||||
            | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
 | 
					            | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
 | 
				
			||||||
            | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
 | 
					            | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
 | 
				
			||||||
            | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
 | 
					            | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
 | 
				
			||||||
        if (!(access_secure_reg(env))) {
 | 
					        if (!(access_secure_reg(env))) {
 | 
				
			||||||
            *flags |= ARM_TBFLAG_NS_MASK;
 | 
					            *flags |= ARM_TBFLAG_NS_MASK;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -2081,6 +2160,9 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (arm_cpu_data_is_big_endian(env)) {
 | 
				
			||||||
 | 
					        *flags |= ARM_TBFLAG_BE_DATA_MASK;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
 | 
					    *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *cs_base = 0;
 | 
					    *cs_base = 0;
 | 
				
			||||||
 | 
				
			|||||||
@ -5490,9 +5490,16 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
 | 
				
			|||||||
    env->daif |= val & CPSR_AIF & mask;
 | 
					    env->daif |= val & CPSR_AIF & mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (write_type != CPSRWriteRaw &&
 | 
					    if (write_type != CPSRWriteRaw &&
 | 
				
			||||||
        (env->uncached_cpsr & CPSR_M) != CPSR_USER &&
 | 
					 | 
				
			||||||
        ((env->uncached_cpsr ^ val) & mask & CPSR_M)) {
 | 
					        ((env->uncached_cpsr ^ val) & mask & CPSR_M)) {
 | 
				
			||||||
        if (bad_mode_switch(env, val & CPSR_M, write_type)) {
 | 
					        if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR) {
 | 
				
			||||||
 | 
					            /* Note that we can only get here in USR mode if this is a
 | 
				
			||||||
 | 
					             * gdb stub write; for this case we follow the architectural
 | 
				
			||||||
 | 
					             * behaviour for guest writes in USR mode of ignoring an attempt
 | 
				
			||||||
 | 
					             * to switch mode. (Those are caught by translate.c for writes
 | 
				
			||||||
 | 
					             * triggered by guest instructions.)
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            mask &= ~CPSR_M;
 | 
				
			||||||
 | 
					        } else if (bad_mode_switch(env, val & CPSR_M, write_type)) {
 | 
				
			||||||
            /* Attempt to switch to an invalid mode: this is UNPREDICTABLE in
 | 
					            /* Attempt to switch to an invalid mode: this is UNPREDICTABLE in
 | 
				
			||||||
             * v7, and has defined behaviour in v8:
 | 
					             * v7, and has defined behaviour in v8:
 | 
				
			||||||
             *  + leave CPSR.M untouched
 | 
					             *  + leave CPSR.M untouched
 | 
				
			||||||
@ -5841,7 +5848,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
 | 
				
			|||||||
    case EXCP_BKPT:
 | 
					    case EXCP_BKPT:
 | 
				
			||||||
        if (semihosting_enabled()) {
 | 
					        if (semihosting_enabled()) {
 | 
				
			||||||
            int nr;
 | 
					            int nr;
 | 
				
			||||||
            nr = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
 | 
					            nr = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env)) & 0xff;
 | 
				
			||||||
            if (nr == 0xab) {
 | 
					            if (nr == 0xab) {
 | 
				
			||||||
                env->regs[15] += 2;
 | 
					                env->regs[15] += 2;
 | 
				
			||||||
                qemu_log_mask(CPU_LOG_INT,
 | 
					                qemu_log_mask(CPU_LOG_INT,
 | 
				
			||||||
@ -6234,6 +6241,11 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
 | 
				
			|||||||
    env->condexec_bits = 0;
 | 
					    env->condexec_bits = 0;
 | 
				
			||||||
    /* Switch to the new mode, and to the correct instruction set.  */
 | 
					    /* Switch to the new mode, and to the correct instruction set.  */
 | 
				
			||||||
    env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
 | 
					    env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
 | 
				
			||||||
 | 
					    /* Set new mode endianness */
 | 
				
			||||||
 | 
					    env->uncached_cpsr &= ~CPSR_E;
 | 
				
			||||||
 | 
					    if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
 | 
				
			||||||
 | 
					        env->uncached_cpsr |= ~CPSR_E;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    env->daif |= mask;
 | 
					    env->daif |= mask;
 | 
				
			||||||
    /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
 | 
					    /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
 | 
				
			||||||
     * and we should just guard the thumb mode on V4 */
 | 
					     * and we should just guard the thumb mode on V4 */
 | 
				
			||||||
@ -6379,13 +6391,13 @@ static inline bool check_for_semihosting(CPUState *cs)
 | 
				
			|||||||
        case EXCP_SWI:
 | 
					        case EXCP_SWI:
 | 
				
			||||||
            /* Check for semihosting interrupt.  */
 | 
					            /* Check for semihosting interrupt.  */
 | 
				
			||||||
            if (env->thumb) {
 | 
					            if (env->thumb) {
 | 
				
			||||||
                imm = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code)
 | 
					                imm = arm_lduw_code(env, env->regs[15] - 2, arm_sctlr_b(env))
 | 
				
			||||||
                    & 0xff;
 | 
					                    & 0xff;
 | 
				
			||||||
                if (imm == 0xab) {
 | 
					                if (imm == 0xab) {
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                imm = arm_ldl_code(env, env->regs[15] - 4, env->bswap_code)
 | 
					                imm = arm_ldl_code(env, env->regs[15] - 4, arm_sctlr_b(env))
 | 
				
			||||||
                    & 0xffffff;
 | 
					                    & 0xffffff;
 | 
				
			||||||
                if (imm == 0x123456) {
 | 
					                if (imm == 0x123456) {
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
@ -6395,7 +6407,7 @@ static inline bool check_for_semihosting(CPUState *cs)
 | 
				
			|||||||
        case EXCP_BKPT:
 | 
					        case EXCP_BKPT:
 | 
				
			||||||
            /* See if this is a semihosting syscall.  */
 | 
					            /* See if this is a semihosting syscall.  */
 | 
				
			||||||
            if (env->thumb) {
 | 
					            if (env->thumb) {
 | 
				
			||||||
                imm = arm_lduw_code(env, env->regs[15], env->bswap_code)
 | 
					                imm = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env))
 | 
				
			||||||
                    & 0xff;
 | 
					                    & 0xff;
 | 
				
			||||||
                if (imm == 0xab) {
 | 
					                if (imm == 0xab) {
 | 
				
			||||||
                    env->regs[15] += 2;
 | 
					                    env->regs[15] += 2;
 | 
				
			||||||
@ -6520,6 +6532,12 @@ static inline bool regime_translation_disabled(CPUARMState *env,
 | 
				
			|||||||
    return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
 | 
					    return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool regime_translation_big_endian(CPUARMState *env,
 | 
				
			||||||
 | 
					                                                 ARMMMUIdx mmu_idx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Return the TCR controlling this translation regime */
 | 
					/* Return the TCR controlling this translation regime */
 | 
				
			||||||
static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
 | 
					static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -6842,7 +6860,11 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
 | 
				
			|||||||
    if (fi->s1ptw) {
 | 
					    if (fi->s1ptw) {
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return address_space_ldl(as, addr, attrs, NULL);
 | 
					    if (regime_translation_big_endian(env, mmu_idx)) {
 | 
				
			||||||
 | 
					        return address_space_ldl_be(as, addr, attrs, NULL);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return address_space_ldl_le(as, addr, attrs, NULL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
 | 
					static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
 | 
				
			||||||
@ -6860,7 +6882,11 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
 | 
				
			|||||||
    if (fi->s1ptw) {
 | 
					    if (fi->s1ptw) {
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return address_space_ldq(as, addr, attrs, NULL);
 | 
					    if (regime_translation_big_endian(env, mmu_idx)) {
 | 
				
			||||||
 | 
					        return address_space_ldq_be(as, addr, attrs, NULL);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return address_space_ldq_le(as, addr, attrs, NULL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
 | 
					static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
 | 
				
			||||||
 | 
				
			|||||||
@ -48,6 +48,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
 | 
				
			|||||||
                   i32, i32, i32, i32)
 | 
					                   i32, i32, i32, i32)
 | 
				
			||||||
DEF_HELPER_2(exception_internal, void, env, i32)
 | 
					DEF_HELPER_2(exception_internal, void, env, i32)
 | 
				
			||||||
DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
 | 
					DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
 | 
				
			||||||
 | 
					DEF_HELPER_1(setend, void, env)
 | 
				
			||||||
DEF_HELPER_1(wfi, void, env)
 | 
					DEF_HELPER_1(wfi, void, env)
 | 
				
			||||||
DEF_HELPER_1(wfe, void, env)
 | 
					DEF_HELPER_1(wfe, void, env)
 | 
				
			||||||
DEF_HELPER_1(yield, void, env)
 | 
					DEF_HELPER_1(yield, void, env)
 | 
				
			||||||
 | 
				
			|||||||
@ -296,6 +296,11 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
 | 
				
			|||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HELPER(setend)(CPUARMState *env)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    env->uncached_cpsr ^= CPSR_E;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
 | 
					/* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
 | 
				
			||||||
 * The function returns the target EL (1-3) if the instruction is to be trapped;
 | 
					 * The function returns the target EL (1-3) if the instruction is to be trapped;
 | 
				
			||||||
 * otherwise it returns 0 indicating it is not trapped.
 | 
					 * otherwise it returns 0 indicating it is not trapped.
 | 
				
			||||||
 | 
				
			|||||||
@ -723,7 +723,7 @@ static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 source,
 | 
				
			|||||||
                             TCGv_i64 tcg_addr, int size, int memidx)
 | 
					                             TCGv_i64 tcg_addr, int size, int memidx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    g_assert(size <= 3);
 | 
					    g_assert(size <= 3);
 | 
				
			||||||
    tcg_gen_qemu_st_i64(source, tcg_addr, memidx, MO_TE + size);
 | 
					    tcg_gen_qemu_st_i64(source, tcg_addr, memidx, s->be_data + size);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void do_gpr_st(DisasContext *s, TCGv_i64 source,
 | 
					static void do_gpr_st(DisasContext *s, TCGv_i64 source,
 | 
				
			||||||
@ -738,7 +738,7 @@ static void do_gpr_st(DisasContext *s, TCGv_i64 source,
 | 
				
			|||||||
static void do_gpr_ld_memidx(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
 | 
					static void do_gpr_ld_memidx(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
 | 
				
			||||||
                             int size, bool is_signed, bool extend, int memidx)
 | 
					                             int size, bool is_signed, bool extend, int memidx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    TCGMemOp memop = MO_TE + size;
 | 
					    TCGMemOp memop = s->be_data + size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_assert(size <= 3);
 | 
					    g_assert(size <= 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -770,13 +770,18 @@ static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
 | 
				
			|||||||
    TCGv_i64 tmp = tcg_temp_new_i64();
 | 
					    TCGv_i64 tmp = tcg_temp_new_i64();
 | 
				
			||||||
    tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
 | 
					    tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
 | 
				
			||||||
    if (size < 4) {
 | 
					    if (size < 4) {
 | 
				
			||||||
        tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
 | 
					        tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s),
 | 
				
			||||||
 | 
					                            s->be_data + size);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
 | 
					        bool be = s->be_data == MO_BE;
 | 
				
			||||||
        TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
 | 
					        TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
 | 
				
			||||||
        tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
 | 
					
 | 
				
			||||||
        tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
 | 
					 | 
				
			||||||
        tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
 | 
					        tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
 | 
				
			||||||
        tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
 | 
					        tcg_gen_qemu_st_i64(tmp, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
 | 
				
			||||||
 | 
					                            s->be_data | MO_Q);
 | 
				
			||||||
 | 
					        tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
 | 
				
			||||||
 | 
					        tcg_gen_qemu_st_i64(tmp, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
 | 
				
			||||||
 | 
					                            s->be_data | MO_Q);
 | 
				
			||||||
        tcg_temp_free_i64(tcg_hiaddr);
 | 
					        tcg_temp_free_i64(tcg_hiaddr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -793,17 +798,21 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
 | 
				
			|||||||
    TCGv_i64 tmphi;
 | 
					    TCGv_i64 tmphi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (size < 4) {
 | 
					    if (size < 4) {
 | 
				
			||||||
        TCGMemOp memop = MO_TE + size;
 | 
					        TCGMemOp memop = s->be_data + size;
 | 
				
			||||||
        tmphi = tcg_const_i64(0);
 | 
					        tmphi = tcg_const_i64(0);
 | 
				
			||||||
        tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
 | 
					        tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
 | 
					        bool be = s->be_data == MO_BE;
 | 
				
			||||||
        TCGv_i64 tcg_hiaddr;
 | 
					        TCGv_i64 tcg_hiaddr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tmphi = tcg_temp_new_i64();
 | 
					        tmphi = tcg_temp_new_i64();
 | 
				
			||||||
        tcg_hiaddr = tcg_temp_new_i64();
 | 
					        tcg_hiaddr = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), MO_TEQ);
 | 
					 | 
				
			||||||
        tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
 | 
					        tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
 | 
				
			||||||
        tcg_gen_qemu_ld_i64(tmphi, tcg_hiaddr, get_mem_index(s), MO_TEQ);
 | 
					        tcg_gen_qemu_ld_i64(tmplo, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
 | 
				
			||||||
 | 
					                            s->be_data | MO_Q);
 | 
				
			||||||
 | 
					        tcg_gen_qemu_ld_i64(tmphi, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
 | 
				
			||||||
 | 
					                            s->be_data | MO_Q);
 | 
				
			||||||
        tcg_temp_free_i64(tcg_hiaddr);
 | 
					        tcg_temp_free_i64(tcg_hiaddr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -942,7 +951,7 @@ static void clear_vec_high(DisasContext *s, int rd)
 | 
				
			|||||||
static void do_vec_st(DisasContext *s, int srcidx, int element,
 | 
					static void do_vec_st(DisasContext *s, int srcidx, int element,
 | 
				
			||||||
                      TCGv_i64 tcg_addr, int size)
 | 
					                      TCGv_i64 tcg_addr, int size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    TCGMemOp memop = MO_TE + size;
 | 
					    TCGMemOp memop = s->be_data + size;
 | 
				
			||||||
    TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 | 
					    TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    read_vec_element(s, tcg_tmp, srcidx, element, size);
 | 
					    read_vec_element(s, tcg_tmp, srcidx, element, size);
 | 
				
			||||||
@ -955,7 +964,7 @@ static void do_vec_st(DisasContext *s, int srcidx, int element,
 | 
				
			|||||||
static void do_vec_ld(DisasContext *s, int destidx, int element,
 | 
					static void do_vec_ld(DisasContext *s, int destidx, int element,
 | 
				
			||||||
                      TCGv_i64 tcg_addr, int size)
 | 
					                      TCGv_i64 tcg_addr, int size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    TCGMemOp memop = MO_TE + size;
 | 
					    TCGMemOp memop = s->be_data + size;
 | 
				
			||||||
    TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 | 
					    TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
 | 
					    tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
 | 
				
			||||||
@ -1702,7 +1711,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
 | 
				
			|||||||
                               TCGv_i64 addr, int size, bool is_pair)
 | 
					                               TCGv_i64 addr, int size, bool is_pair)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    TCGv_i64 tmp = tcg_temp_new_i64();
 | 
					    TCGv_i64 tmp = tcg_temp_new_i64();
 | 
				
			||||||
    TCGMemOp memop = MO_TE + size;
 | 
					    TCGMemOp memop = s->be_data + size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_assert(size <= 3);
 | 
					    g_assert(size <= 3);
 | 
				
			||||||
    tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), memop);
 | 
					    tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), memop);
 | 
				
			||||||
@ -1764,7 +1773,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
 | 
				
			|||||||
    tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
 | 
					    tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tmp = tcg_temp_new_i64();
 | 
					    tmp = tcg_temp_new_i64();
 | 
				
			||||||
    tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), MO_TE + size);
 | 
					    tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), s->be_data + size);
 | 
				
			||||||
    tcg_gen_brcond_i64(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
 | 
					    tcg_gen_brcond_i64(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
 | 
				
			||||||
    tcg_temp_free_i64(tmp);
 | 
					    tcg_temp_free_i64(tmp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1773,7 +1782,8 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
 | 
				
			|||||||
        TCGv_i64 tmphi = tcg_temp_new_i64();
 | 
					        TCGv_i64 tmphi = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tcg_gen_addi_i64(addrhi, addr, 1 << size);
 | 
					        tcg_gen_addi_i64(addrhi, addr, 1 << size);
 | 
				
			||||||
        tcg_gen_qemu_ld_i64(tmphi, addrhi, get_mem_index(s), MO_TE + size);
 | 
					        tcg_gen_qemu_ld_i64(tmphi, addrhi, get_mem_index(s),
 | 
				
			||||||
 | 
					                            s->be_data + size);
 | 
				
			||||||
        tcg_gen_brcond_i64(TCG_COND_NE, tmphi, cpu_exclusive_high, fail_label);
 | 
					        tcg_gen_brcond_i64(TCG_COND_NE, tmphi, cpu_exclusive_high, fail_label);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tcg_temp_free_i64(tmphi);
 | 
					        tcg_temp_free_i64(tmphi);
 | 
				
			||||||
@ -1781,13 +1791,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* We seem to still have the exclusive monitor, so do the store */
 | 
					    /* We seem to still have the exclusive monitor, so do the store */
 | 
				
			||||||
    tcg_gen_qemu_st_i64(cpu_reg(s, rt), addr, get_mem_index(s), MO_TE + size);
 | 
					    tcg_gen_qemu_st_i64(cpu_reg(s, rt), addr, get_mem_index(s),
 | 
				
			||||||
 | 
					                        s->be_data + size);
 | 
				
			||||||
    if (is_pair) {
 | 
					    if (is_pair) {
 | 
				
			||||||
        TCGv_i64 addrhi = tcg_temp_new_i64();
 | 
					        TCGv_i64 addrhi = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tcg_gen_addi_i64(addrhi, addr, 1 << size);
 | 
					        tcg_gen_addi_i64(addrhi, addr, 1 << size);
 | 
				
			||||||
        tcg_gen_qemu_st_i64(cpu_reg(s, rt2), addrhi,
 | 
					        tcg_gen_qemu_st_i64(cpu_reg(s, rt2), addrhi,
 | 
				
			||||||
                            get_mem_index(s), MO_TE + size);
 | 
					                            get_mem_index(s), s->be_data + size);
 | 
				
			||||||
        tcg_temp_free_i64(addrhi);
 | 
					        tcg_temp_free_i64(addrhi);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2602,7 +2613,7 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
            TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 | 
					            TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
 | 
					            tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
 | 
				
			||||||
                                get_mem_index(s), MO_TE + scale);
 | 
					                                get_mem_index(s), s->be_data + scale);
 | 
				
			||||||
            switch (scale) {
 | 
					            switch (scale) {
 | 
				
			||||||
            case 0:
 | 
					            case 0:
 | 
				
			||||||
                mulconst = 0x0101010101010101ULL;
 | 
					                mulconst = 0x0101010101010101ULL;
 | 
				
			||||||
@ -2632,9 +2643,9 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            /* Load/store one element per register */
 | 
					            /* Load/store one element per register */
 | 
				
			||||||
            if (is_load) {
 | 
					            if (is_load) {
 | 
				
			||||||
                do_vec_ld(s, rt, index, tcg_addr, MO_TE + scale);
 | 
					                do_vec_ld(s, rt, index, tcg_addr, s->be_data + scale);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                do_vec_st(s, rt, index, tcg_addr, MO_TE + scale);
 | 
					                do_vec_st(s, rt, index, tcg_addr, s->be_data + scale);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
 | 
					        tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
 | 
				
			||||||
@ -10966,7 +10977,7 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t insn;
 | 
					    uint32_t insn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    insn = arm_ldl_code(env, s->pc, s->bswap_code);
 | 
					    insn = arm_ldl_code(env, s->pc, s->sctlr_b);
 | 
				
			||||||
    s->insn = insn;
 | 
					    s->insn = insn;
 | 
				
			||||||
    s->pc += 4;
 | 
					    s->pc += 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -11031,7 +11042,8 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
 | 
				
			|||||||
    dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
 | 
					    dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
 | 
				
			||||||
                               !arm_el_is_aa64(env, 3);
 | 
					                               !arm_el_is_aa64(env, 3);
 | 
				
			||||||
    dc->thumb = 0;
 | 
					    dc->thumb = 0;
 | 
				
			||||||
    dc->bswap_code = 0;
 | 
					    dc->sctlr_b = 0;
 | 
				
			||||||
 | 
					    dc->be_data = ARM_TBFLAG_BE_DATA(tb->flags) ? MO_BE : MO_LE;
 | 
				
			||||||
    dc->condexec_mask = 0;
 | 
					    dc->condexec_mask = 0;
 | 
				
			||||||
    dc->condexec_cond = 0;
 | 
					    dc->condexec_cond = 0;
 | 
				
			||||||
    dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
 | 
					    dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
 | 
				
			||||||
@ -11217,7 +11229,7 @@ done_generating:
 | 
				
			|||||||
        qemu_log("----------------\n");
 | 
					        qemu_log("----------------\n");
 | 
				
			||||||
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
 | 
					        qemu_log("IN: %s\n", lookup_symbol(pc_start));
 | 
				
			||||||
        log_target_disas(cs, pc_start, dc->pc - pc_start,
 | 
					        log_target_disas(cs, pc_start, dc->pc - pc_start,
 | 
				
			||||||
                         4 | (dc->bswap_code << 1));
 | 
					                         4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
 | 
				
			||||||
        qemu_log("\n");
 | 
					        qemu_log("\n");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -911,6 +911,12 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_USER_ONLY
 | 
				
			||||||
 | 
					#define IS_USER_ONLY 1
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define IS_USER_ONLY 0
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Abstractions of "generate code to do a guest load/store for
 | 
					/* Abstractions of "generate code to do a guest load/store for
 | 
				
			||||||
 * AArch32", where a vaddr is always 32 bits (and is zero
 | 
					 * AArch32", where a vaddr is always 32 bits (and is zero
 | 
				
			||||||
 * extended if we're a 64 bit core) and  data is also
 | 
					 * extended if we're a 64 bit core) and  data is also
 | 
				
			||||||
@ -920,77 +926,143 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
#if TARGET_LONG_BITS == 32
 | 
					#if TARGET_LONG_BITS == 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DO_GEN_LD(SUFF, OPC)                                             \
 | 
					#define DO_GEN_LD(SUFF, OPC, BE32_XOR)                                   \
 | 
				
			||||||
static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
 | 
					static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,      \
 | 
				
			||||||
 | 
					                                     TCGv_i32 addr, int index)           \
 | 
				
			||||||
{                                                                        \
 | 
					{                                                                        \
 | 
				
			||||||
    tcg_gen_qemu_ld_i32(val, addr, index, (OPC));                        \
 | 
					    TCGMemOp opc = (OPC) | s->be_data;                                   \
 | 
				
			||||||
 | 
					    /* Not needed for user-mode BE32, where we use MO_BE instead.  */    \
 | 
				
			||||||
 | 
					    if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) {                       \
 | 
				
			||||||
 | 
					        TCGv addr_be = tcg_temp_new();                                   \
 | 
				
			||||||
 | 
					        tcg_gen_xori_i32(addr_be, addr, BE32_XOR);                       \
 | 
				
			||||||
 | 
					        tcg_gen_qemu_ld_i32(val, addr_be, index, opc);                   \
 | 
				
			||||||
 | 
					        tcg_temp_free(addr_be);                                          \
 | 
				
			||||||
 | 
					        return;                                                          \
 | 
				
			||||||
 | 
					    }                                                                    \
 | 
				
			||||||
 | 
					    tcg_gen_qemu_ld_i32(val, addr, index, opc);                          \
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DO_GEN_ST(SUFF, OPC)                                             \
 | 
					#define DO_GEN_ST(SUFF, OPC, BE32_XOR)                                   \
 | 
				
			||||||
static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
 | 
					static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,      \
 | 
				
			||||||
 | 
					                                     TCGv_i32 addr, int index)           \
 | 
				
			||||||
{                                                                        \
 | 
					{                                                                        \
 | 
				
			||||||
    tcg_gen_qemu_st_i32(val, addr, index, (OPC));                        \
 | 
					    TCGMemOp opc = (OPC) | s->be_data;                                   \
 | 
				
			||||||
 | 
					    /* Not needed for user-mode BE32, where we use MO_BE instead.  */    \
 | 
				
			||||||
 | 
					    if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) {                       \
 | 
				
			||||||
 | 
					        TCGv addr_be = tcg_temp_new();                                   \
 | 
				
			||||||
 | 
					        tcg_gen_xori_i32(addr_be, addr, BE32_XOR);                       \
 | 
				
			||||||
 | 
					        tcg_gen_qemu_st_i32(val, addr_be, index, opc);                   \
 | 
				
			||||||
 | 
					        tcg_temp_free(addr_be);                                          \
 | 
				
			||||||
 | 
					        return;                                                          \
 | 
				
			||||||
 | 
					    }                                                                    \
 | 
				
			||||||
 | 
					    tcg_gen_qemu_st_i32(val, addr, index, opc);                          \
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
 | 
					static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
 | 
				
			||||||
 | 
					                                 TCGv_i32 addr, int index)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
 | 
					    TCGMemOp opc = MO_Q | s->be_data;
 | 
				
			||||||
 | 
					    tcg_gen_qemu_ld_i64(val, addr, index, opc);
 | 
				
			||||||
 | 
					    /* Not needed for user-mode BE32, where we use MO_BE instead.  */
 | 
				
			||||||
 | 
					    if (!IS_USER_ONLY && s->sctlr_b) {
 | 
				
			||||||
 | 
					        tcg_gen_rotri_i64(val, val, 32);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
 | 
					static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
 | 
				
			||||||
 | 
					                                 TCGv_i32 addr, int index)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
 | 
					    TCGMemOp opc = MO_Q | s->be_data;
 | 
				
			||||||
 | 
					    /* Not needed for user-mode BE32, where we use MO_BE instead.  */
 | 
				
			||||||
 | 
					    if (!IS_USER_ONLY && s->sctlr_b) {
 | 
				
			||||||
 | 
					        TCGv_i64 tmp = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					        tcg_gen_rotri_i64(tmp, val, 32);
 | 
				
			||||||
 | 
					        tcg_gen_qemu_st_i64(tmp, addr, index, opc);
 | 
				
			||||||
 | 
					        tcg_temp_free_i64(tmp);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    tcg_gen_qemu_st_i64(val, addr, index, opc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DO_GEN_LD(SUFF, OPC)                                             \
 | 
					#define DO_GEN_LD(SUFF, OPC, BE32_XOR)                                   \
 | 
				
			||||||
static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
 | 
					static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,      \
 | 
				
			||||||
 | 
					                                     TCGv_i32 addr, int index)           \
 | 
				
			||||||
{                                                                        \
 | 
					{                                                                        \
 | 
				
			||||||
 | 
					    TCGMemOp opc = (OPC) | s->be_data;                                   \
 | 
				
			||||||
    TCGv addr64 = tcg_temp_new();                                        \
 | 
					    TCGv addr64 = tcg_temp_new();                                        \
 | 
				
			||||||
    tcg_gen_extu_i32_i64(addr64, addr);                                  \
 | 
					    tcg_gen_extu_i32_i64(addr64, addr);                                  \
 | 
				
			||||||
    tcg_gen_qemu_ld_i32(val, addr64, index, OPC);                        \
 | 
					    /* Not needed for user-mode BE32, where we use MO_BE instead.  */    \
 | 
				
			||||||
 | 
					    if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) {                       \
 | 
				
			||||||
 | 
					        tcg_gen_xori_i64(addr64, addr64, BE32_XOR);                      \
 | 
				
			||||||
 | 
					    }                                                                    \
 | 
				
			||||||
 | 
					    tcg_gen_qemu_ld_i32(val, addr64, index, opc);                        \
 | 
				
			||||||
    tcg_temp_free(addr64);                                               \
 | 
					    tcg_temp_free(addr64);                                               \
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DO_GEN_ST(SUFF, OPC)                                             \
 | 
					#define DO_GEN_ST(SUFF, OPC, BE32_XOR)                                   \
 | 
				
			||||||
static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
 | 
					static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,      \
 | 
				
			||||||
 | 
					                                     TCGv_i32 addr, int index)           \
 | 
				
			||||||
{                                                                        \
 | 
					{                                                                        \
 | 
				
			||||||
 | 
					    TCGMemOp opc = (OPC) | s->be_data;                                   \
 | 
				
			||||||
    TCGv addr64 = tcg_temp_new();                                        \
 | 
					    TCGv addr64 = tcg_temp_new();                                        \
 | 
				
			||||||
    tcg_gen_extu_i32_i64(addr64, addr);                                  \
 | 
					    tcg_gen_extu_i32_i64(addr64, addr);                                  \
 | 
				
			||||||
    tcg_gen_qemu_st_i32(val, addr64, index, OPC);                        \
 | 
					    /* Not needed for user-mode BE32, where we use MO_BE instead.  */    \
 | 
				
			||||||
 | 
					    if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) {                       \
 | 
				
			||||||
 | 
					        tcg_gen_xori_i64(addr64, addr64, BE32_XOR);                      \
 | 
				
			||||||
 | 
					    }                                                                    \
 | 
				
			||||||
 | 
					    tcg_gen_qemu_st_i32(val, addr64, index, opc);                        \
 | 
				
			||||||
    tcg_temp_free(addr64);                                               \
 | 
					    tcg_temp_free(addr64);                                               \
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
 | 
					static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
 | 
				
			||||||
 | 
					                                 TCGv_i32 addr, int index)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    TCGMemOp opc = MO_Q | s->be_data;
 | 
				
			||||||
    TCGv addr64 = tcg_temp_new();
 | 
					    TCGv addr64 = tcg_temp_new();
 | 
				
			||||||
    tcg_gen_extu_i32_i64(addr64, addr);
 | 
					    tcg_gen_extu_i32_i64(addr64, addr);
 | 
				
			||||||
    tcg_gen_qemu_ld_i64(val, addr64, index, MO_TEQ);
 | 
					    tcg_gen_qemu_ld_i64(val, addr64, index, opc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Not needed for user-mode BE32, where we use MO_BE instead.  */
 | 
				
			||||||
 | 
					    if (!IS_USER_ONLY && s->sctlr_b) {
 | 
				
			||||||
 | 
					        tcg_gen_rotri_i64(val, val, 32);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    tcg_temp_free(addr64);
 | 
					    tcg_temp_free(addr64);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
 | 
					static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
 | 
				
			||||||
 | 
					                                 TCGv_i32 addr, int index)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    TCGMemOp opc = MO_Q | s->be_data;
 | 
				
			||||||
    TCGv addr64 = tcg_temp_new();
 | 
					    TCGv addr64 = tcg_temp_new();
 | 
				
			||||||
    tcg_gen_extu_i32_i64(addr64, addr);
 | 
					    tcg_gen_extu_i32_i64(addr64, addr);
 | 
				
			||||||
    tcg_gen_qemu_st_i64(val, addr64, index, MO_TEQ);
 | 
					
 | 
				
			||||||
 | 
					    /* Not needed for user-mode BE32, where we use MO_BE instead.  */
 | 
				
			||||||
 | 
					    if (!IS_USER_ONLY && s->sctlr_b) {
 | 
				
			||||||
 | 
					        TCGv tmp = tcg_temp_new();
 | 
				
			||||||
 | 
					        tcg_gen_rotri_i64(tmp, val, 32);
 | 
				
			||||||
 | 
					        tcg_gen_qemu_st_i64(tmp, addr64, index, opc);
 | 
				
			||||||
 | 
					        tcg_temp_free(tmp);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        tcg_gen_qemu_st_i64(val, addr64, index, opc);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    tcg_temp_free(addr64);
 | 
					    tcg_temp_free(addr64);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DO_GEN_LD(8s, MO_SB)
 | 
					DO_GEN_LD(8s, MO_SB, 3)
 | 
				
			||||||
DO_GEN_LD(8u, MO_UB)
 | 
					DO_GEN_LD(8u, MO_UB, 3)
 | 
				
			||||||
DO_GEN_LD(16s, MO_TESW)
 | 
					DO_GEN_LD(16s, MO_SW, 2)
 | 
				
			||||||
DO_GEN_LD(16u, MO_TEUW)
 | 
					DO_GEN_LD(16u, MO_UW, 2)
 | 
				
			||||||
DO_GEN_LD(32u, MO_TEUL)
 | 
					DO_GEN_LD(32u, MO_UL, 0)
 | 
				
			||||||
/* 'a' variants include an alignment check */
 | 
					/* 'a' variants include an alignment check */
 | 
				
			||||||
DO_GEN_LD(16ua, MO_TEUW | MO_ALIGN)
 | 
					DO_GEN_LD(16ua, MO_UW | MO_ALIGN, 2)
 | 
				
			||||||
DO_GEN_LD(32ua, MO_TEUL | MO_ALIGN)
 | 
					DO_GEN_LD(32ua, MO_UL | MO_ALIGN, 0)
 | 
				
			||||||
DO_GEN_ST(8, MO_UB)
 | 
					DO_GEN_ST(8, MO_UB, 3)
 | 
				
			||||||
DO_GEN_ST(16, MO_TEUW)
 | 
					DO_GEN_ST(16, MO_UW, 2)
 | 
				
			||||||
DO_GEN_ST(32, MO_TEUL)
 | 
					DO_GEN_ST(32, MO_UL, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
 | 
					static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -1285,18 +1357,18 @@ VFP_GEN_FIX(ulto, )
 | 
				
			|||||||
static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
 | 
					static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (dp) {
 | 
					    if (dp) {
 | 
				
			||||||
        gen_aa32_ld64(cpu_F0d, addr, get_mem_index(s));
 | 
					        gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        gen_aa32_ld32u(cpu_F0s, addr, get_mem_index(s));
 | 
					        gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
 | 
					static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (dp) {
 | 
					    if (dp) {
 | 
				
			||||||
        gen_aa32_st64(cpu_F0d, addr, get_mem_index(s));
 | 
					        gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        gen_aa32_st32(cpu_F0s, addr, get_mem_index(s));
 | 
					        gen_aa32_st32(s, cpu_F0s, addr, get_mem_index(s));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1632,24 +1704,24 @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
        if (insn & ARM_CP_RW_BIT) {
 | 
					        if (insn & ARM_CP_RW_BIT) {
 | 
				
			||||||
            if ((insn >> 28) == 0xf) {			/* WLDRW wCx */
 | 
					            if ((insn >> 28) == 0xf) {			/* WLDRW wCx */
 | 
				
			||||||
                tmp = tcg_temp_new_i32();
 | 
					                tmp = tcg_temp_new_i32();
 | 
				
			||||||
                gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                iwmmxt_store_creg(wrd, tmp);
 | 
					                iwmmxt_store_creg(wrd, tmp);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                i = 1;
 | 
					                i = 1;
 | 
				
			||||||
                if (insn & (1 << 8)) {
 | 
					                if (insn & (1 << 8)) {
 | 
				
			||||||
                    if (insn & (1 << 22)) {		/* WLDRD */
 | 
					                    if (insn & (1 << 22)) {		/* WLDRD */
 | 
				
			||||||
                        gen_aa32_ld64(cpu_M0, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
 | 
				
			||||||
                        i = 0;
 | 
					                        i = 0;
 | 
				
			||||||
                    } else {				/* WLDRW wRd */
 | 
					                    } else {				/* WLDRW wRd */
 | 
				
			||||||
                        tmp = tcg_temp_new_i32();
 | 
					                        tmp = tcg_temp_new_i32();
 | 
				
			||||||
                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    tmp = tcg_temp_new_i32();
 | 
					                    tmp = tcg_temp_new_i32();
 | 
				
			||||||
                    if (insn & (1 << 22)) {		/* WLDRH */
 | 
					                    if (insn & (1 << 22)) {		/* WLDRH */
 | 
				
			||||||
                        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    } else {				/* WLDRB */
 | 
					                    } else {				/* WLDRB */
 | 
				
			||||||
                        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (i) {
 | 
					                if (i) {
 | 
				
			||||||
@ -1661,24 +1733,24 @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if ((insn >> 28) == 0xf) {			/* WSTRW wCx */
 | 
					            if ((insn >> 28) == 0xf) {			/* WSTRW wCx */
 | 
				
			||||||
                tmp = iwmmxt_load_creg(wrd);
 | 
					                tmp = iwmmxt_load_creg(wrd);
 | 
				
			||||||
                gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                gen_op_iwmmxt_movq_M0_wRn(wrd);
 | 
					                gen_op_iwmmxt_movq_M0_wRn(wrd);
 | 
				
			||||||
                tmp = tcg_temp_new_i32();
 | 
					                tmp = tcg_temp_new_i32();
 | 
				
			||||||
                if (insn & (1 << 8)) {
 | 
					                if (insn & (1 << 8)) {
 | 
				
			||||||
                    if (insn & (1 << 22)) {		/* WSTRD */
 | 
					                    if (insn & (1 << 22)) {		/* WSTRD */
 | 
				
			||||||
                        gen_aa32_st64(cpu_M0, addr, get_mem_index(s));
 | 
					                        gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
 | 
				
			||||||
                    } else {				/* WSTRW wRd */
 | 
					                    } else {				/* WSTRW wRd */
 | 
				
			||||||
                        tcg_gen_extrl_i64_i32(tmp, cpu_M0);
 | 
					                        tcg_gen_extrl_i64_i32(tmp, cpu_M0);
 | 
				
			||||||
                        gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    if (insn & (1 << 22)) {		/* WSTRH */
 | 
					                    if (insn & (1 << 22)) {		/* WSTRH */
 | 
				
			||||||
                        tcg_gen_extrl_i64_i32(tmp, cpu_M0);
 | 
					                        tcg_gen_extrl_i64_i32(tmp, cpu_M0);
 | 
				
			||||||
                        gen_aa32_st16(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_st16(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    } else {				/* WSTRB */
 | 
					                    } else {				/* WSTRB */
 | 
				
			||||||
                        tcg_gen_extrl_i64_i32(tmp, cpu_M0);
 | 
					                        tcg_gen_extrl_i64_i32(tmp, cpu_M0);
 | 
				
			||||||
                        gen_aa32_st8(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_st8(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -2743,15 +2815,15 @@ static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
 | 
				
			|||||||
    TCGv_i32 tmp = tcg_temp_new_i32();
 | 
					    TCGv_i32 tmp = tcg_temp_new_i32();
 | 
				
			||||||
    switch (size) {
 | 
					    switch (size) {
 | 
				
			||||||
    case 0:
 | 
					    case 0:
 | 
				
			||||||
        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        gen_neon_dup_u8(tmp, 0);
 | 
					        gen_neon_dup_u8(tmp, 0);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 1:
 | 
					    case 1:
 | 
				
			||||||
        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        gen_neon_dup_low16(tmp);
 | 
					        gen_neon_dup_low16(tmp);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 2:
 | 
					    case 2:
 | 
				
			||||||
        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    default: /* Avoid compiler warnings.  */
 | 
					    default: /* Avoid compiler warnings.  */
 | 
				
			||||||
        abort();
 | 
					        abort();
 | 
				
			||||||
@ -4449,11 +4521,11 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
            if (size == 3) {
 | 
					            if (size == 3) {
 | 
				
			||||||
                tmp64 = tcg_temp_new_i64();
 | 
					                tmp64 = tcg_temp_new_i64();
 | 
				
			||||||
                if (load) {
 | 
					                if (load) {
 | 
				
			||||||
                    gen_aa32_ld64(tmp64, addr, get_mem_index(s));
 | 
					                    gen_aa32_ld64(s, tmp64, addr, get_mem_index(s));
 | 
				
			||||||
                    neon_store_reg64(tmp64, rd);
 | 
					                    neon_store_reg64(tmp64, rd);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    neon_load_reg64(tmp64, rd);
 | 
					                    neon_load_reg64(tmp64, rd);
 | 
				
			||||||
                    gen_aa32_st64(tmp64, addr, get_mem_index(s));
 | 
					                    gen_aa32_st64(s, tmp64, addr, get_mem_index(s));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                tcg_temp_free_i64(tmp64);
 | 
					                tcg_temp_free_i64(tmp64);
 | 
				
			||||||
                tcg_gen_addi_i32(addr, addr, stride);
 | 
					                tcg_gen_addi_i32(addr, addr, stride);
 | 
				
			||||||
@ -4462,21 +4534,21 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
                    if (size == 2) {
 | 
					                    if (size == 2) {
 | 
				
			||||||
                        if (load) {
 | 
					                        if (load) {
 | 
				
			||||||
                            tmp = tcg_temp_new_i32();
 | 
					                            tmp = tcg_temp_new_i32();
 | 
				
			||||||
                            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                            neon_store_reg(rd, pass, tmp);
 | 
					                            neon_store_reg(rd, pass, tmp);
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            tmp = neon_load_reg(rd, pass);
 | 
					                            tmp = neon_load_reg(rd, pass);
 | 
				
			||||||
                            gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                            tcg_temp_free_i32(tmp);
 | 
					                            tcg_temp_free_i32(tmp);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        tcg_gen_addi_i32(addr, addr, stride);
 | 
					                        tcg_gen_addi_i32(addr, addr, stride);
 | 
				
			||||||
                    } else if (size == 1) {
 | 
					                    } else if (size == 1) {
 | 
				
			||||||
                        if (load) {
 | 
					                        if (load) {
 | 
				
			||||||
                            tmp = tcg_temp_new_i32();
 | 
					                            tmp = tcg_temp_new_i32();
 | 
				
			||||||
                            gen_aa32_ld16u(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                            tcg_gen_addi_i32(addr, addr, stride);
 | 
					                            tcg_gen_addi_i32(addr, addr, stride);
 | 
				
			||||||
                            tmp2 = tcg_temp_new_i32();
 | 
					                            tmp2 = tcg_temp_new_i32();
 | 
				
			||||||
                            gen_aa32_ld16u(tmp2, addr, get_mem_index(s));
 | 
					                            gen_aa32_ld16u(s, tmp2, addr, get_mem_index(s));
 | 
				
			||||||
                            tcg_gen_addi_i32(addr, addr, stride);
 | 
					                            tcg_gen_addi_i32(addr, addr, stride);
 | 
				
			||||||
                            tcg_gen_shli_i32(tmp2, tmp2, 16);
 | 
					                            tcg_gen_shli_i32(tmp2, tmp2, 16);
 | 
				
			||||||
                            tcg_gen_or_i32(tmp, tmp, tmp2);
 | 
					                            tcg_gen_or_i32(tmp, tmp, tmp2);
 | 
				
			||||||
@ -4486,10 +4558,10 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
                            tmp = neon_load_reg(rd, pass);
 | 
					                            tmp = neon_load_reg(rd, pass);
 | 
				
			||||||
                            tmp2 = tcg_temp_new_i32();
 | 
					                            tmp2 = tcg_temp_new_i32();
 | 
				
			||||||
                            tcg_gen_shri_i32(tmp2, tmp, 16);
 | 
					                            tcg_gen_shri_i32(tmp2, tmp, 16);
 | 
				
			||||||
                            gen_aa32_st16(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                            tcg_temp_free_i32(tmp);
 | 
					                            tcg_temp_free_i32(tmp);
 | 
				
			||||||
                            tcg_gen_addi_i32(addr, addr, stride);
 | 
					                            tcg_gen_addi_i32(addr, addr, stride);
 | 
				
			||||||
                            gen_aa32_st16(tmp2, addr, get_mem_index(s));
 | 
					                            gen_aa32_st16(s, tmp2, addr, get_mem_index(s));
 | 
				
			||||||
                            tcg_temp_free_i32(tmp2);
 | 
					                            tcg_temp_free_i32(tmp2);
 | 
				
			||||||
                            tcg_gen_addi_i32(addr, addr, stride);
 | 
					                            tcg_gen_addi_i32(addr, addr, stride);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
@ -4498,7 +4570,7 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
                            TCGV_UNUSED_I32(tmp2);
 | 
					                            TCGV_UNUSED_I32(tmp2);
 | 
				
			||||||
                            for (n = 0; n < 4; n++) {
 | 
					                            for (n = 0; n < 4; n++) {
 | 
				
			||||||
                                tmp = tcg_temp_new_i32();
 | 
					                                tmp = tcg_temp_new_i32();
 | 
				
			||||||
                                gen_aa32_ld8u(tmp, addr, get_mem_index(s));
 | 
					                                gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                                tcg_gen_addi_i32(addr, addr, stride);
 | 
					                                tcg_gen_addi_i32(addr, addr, stride);
 | 
				
			||||||
                                if (n == 0) {
 | 
					                                if (n == 0) {
 | 
				
			||||||
                                    tmp2 = tmp;
 | 
					                                    tmp2 = tmp;
 | 
				
			||||||
@ -4518,7 +4590,7 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
                                } else {
 | 
					                                } else {
 | 
				
			||||||
                                    tcg_gen_shri_i32(tmp, tmp2, n * 8);
 | 
					                                    tcg_gen_shri_i32(tmp, tmp2, n * 8);
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                                gen_aa32_st8(tmp, addr, get_mem_index(s));
 | 
					                                gen_aa32_st8(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                                tcg_temp_free_i32(tmp);
 | 
					                                tcg_temp_free_i32(tmp);
 | 
				
			||||||
                                tcg_gen_addi_i32(addr, addr, stride);
 | 
					                                tcg_gen_addi_i32(addr, addr, stride);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
@ -4642,13 +4714,13 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
                    tmp = tcg_temp_new_i32();
 | 
					                    tmp = tcg_temp_new_i32();
 | 
				
			||||||
                    switch (size) {
 | 
					                    switch (size) {
 | 
				
			||||||
                    case 0:
 | 
					                    case 0:
 | 
				
			||||||
                        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 1:
 | 
					                    case 1:
 | 
				
			||||||
                        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 2:
 | 
					                    case 2:
 | 
				
			||||||
                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    default: /* Avoid compiler warnings.  */
 | 
					                    default: /* Avoid compiler warnings.  */
 | 
				
			||||||
                        abort();
 | 
					                        abort();
 | 
				
			||||||
@ -4666,13 +4738,13 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
                        tcg_gen_shri_i32(tmp, tmp, shift);
 | 
					                        tcg_gen_shri_i32(tmp, tmp, shift);
 | 
				
			||||||
                    switch (size) {
 | 
					                    switch (size) {
 | 
				
			||||||
                    case 0:
 | 
					                    case 0:
 | 
				
			||||||
                        gen_aa32_st8(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_st8(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 1:
 | 
					                    case 1:
 | 
				
			||||||
                        gen_aa32_st16(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_st16(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 2:
 | 
					                    case 2:
 | 
				
			||||||
                        gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    tcg_temp_free_i32(tmp);
 | 
					                    tcg_temp_free_i32(tmp);
 | 
				
			||||||
@ -7435,14 +7507,14 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    switch (size) {
 | 
					    switch (size) {
 | 
				
			||||||
    case 0:
 | 
					    case 0:
 | 
				
			||||||
        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 1:
 | 
					    case 1:
 | 
				
			||||||
        gen_aa32_ld16ua(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_ld16ua(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 2:
 | 
					    case 2:
 | 
				
			||||||
    case 3:
 | 
					    case 3:
 | 
				
			||||||
        gen_aa32_ld32ua(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_ld32ua(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        abort();
 | 
					        abort();
 | 
				
			||||||
@ -7453,7 +7525,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
 | 
				
			|||||||
        TCGv_i32 tmp3 = tcg_temp_new_i32();
 | 
					        TCGv_i32 tmp3 = tcg_temp_new_i32();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tcg_gen_addi_i32(tmp2, addr, 4);
 | 
					        tcg_gen_addi_i32(tmp2, addr, 4);
 | 
				
			||||||
        gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
 | 
					        gen_aa32_ld32u(s, tmp3, tmp2, get_mem_index(s));
 | 
				
			||||||
        tcg_temp_free_i32(tmp2);
 | 
					        tcg_temp_free_i32(tmp2);
 | 
				
			||||||
        tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
 | 
					        tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
 | 
				
			||||||
        store_reg(s, rt2, tmp3);
 | 
					        store_reg(s, rt2, tmp3);
 | 
				
			||||||
@ -7504,14 +7576,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
 | 
				
			|||||||
    tmp = tcg_temp_new_i32();
 | 
					    tmp = tcg_temp_new_i32();
 | 
				
			||||||
    switch (size) {
 | 
					    switch (size) {
 | 
				
			||||||
    case 0:
 | 
					    case 0:
 | 
				
			||||||
        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 1:
 | 
					    case 1:
 | 
				
			||||||
        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 2:
 | 
					    case 2:
 | 
				
			||||||
    case 3:
 | 
					    case 3:
 | 
				
			||||||
        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        abort();
 | 
					        abort();
 | 
				
			||||||
@ -7522,7 +7594,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
 | 
				
			|||||||
        TCGv_i32 tmp2 = tcg_temp_new_i32();
 | 
					        TCGv_i32 tmp2 = tcg_temp_new_i32();
 | 
				
			||||||
        TCGv_i32 tmp3 = tcg_temp_new_i32();
 | 
					        TCGv_i32 tmp3 = tcg_temp_new_i32();
 | 
				
			||||||
        tcg_gen_addi_i32(tmp2, addr, 4);
 | 
					        tcg_gen_addi_i32(tmp2, addr, 4);
 | 
				
			||||||
        gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
 | 
					        gen_aa32_ld32u(s, tmp3, tmp2, get_mem_index(s));
 | 
				
			||||||
        tcg_temp_free_i32(tmp2);
 | 
					        tcg_temp_free_i32(tmp2);
 | 
				
			||||||
        tcg_gen_concat_i32_i64(val64, tmp, tmp3);
 | 
					        tcg_gen_concat_i32_i64(val64, tmp, tmp3);
 | 
				
			||||||
        tcg_temp_free_i32(tmp3);
 | 
					        tcg_temp_free_i32(tmp3);
 | 
				
			||||||
@ -7537,14 +7609,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
 | 
				
			|||||||
    tmp = load_reg(s, rt);
 | 
					    tmp = load_reg(s, rt);
 | 
				
			||||||
    switch (size) {
 | 
					    switch (size) {
 | 
				
			||||||
    case 0:
 | 
					    case 0:
 | 
				
			||||||
        gen_aa32_st8(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_st8(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 1:
 | 
					    case 1:
 | 
				
			||||||
        gen_aa32_st16(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_st16(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 2:
 | 
					    case 2:
 | 
				
			||||||
    case 3:
 | 
					    case 3:
 | 
				
			||||||
        gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        abort();
 | 
					        abort();
 | 
				
			||||||
@ -7553,7 +7625,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
 | 
				
			|||||||
    if (size == 3) {
 | 
					    if (size == 3) {
 | 
				
			||||||
        tcg_gen_addi_i32(addr, addr, 4);
 | 
					        tcg_gen_addi_i32(addr, addr, 4);
 | 
				
			||||||
        tmp = load_reg(s, rt2);
 | 
					        tmp = load_reg(s, rt2);
 | 
				
			||||||
        gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
        tcg_temp_free_i32(tmp);
 | 
					        tcg_temp_free_i32(tmp);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    tcg_gen_movi_i32(cpu_R[rd], 0);
 | 
					    tcg_gen_movi_i32(cpu_R[rd], 0);
 | 
				
			||||||
@ -7583,6 +7655,7 @@ static void gen_srs(DisasContext *s,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* SRS is:
 | 
					    /* SRS is:
 | 
				
			||||||
     * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
 | 
					     * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
 | 
				
			||||||
 | 
					     *   and specified mode is monitor mode
 | 
				
			||||||
     * - UNDEFINED in Hyp mode
 | 
					     * - UNDEFINED in Hyp mode
 | 
				
			||||||
     * - UNPREDICTABLE in User or System mode
 | 
					     * - UNPREDICTABLE in User or System mode
 | 
				
			||||||
     * - UNPREDICTABLE if the specified mode is:
 | 
					     * - UNPREDICTABLE if the specified mode is:
 | 
				
			||||||
@ -7592,7 +7665,7 @@ static void gen_srs(DisasContext *s,
 | 
				
			|||||||
     * -- Monitor, if we are Non-secure
 | 
					     * -- Monitor, if we are Non-secure
 | 
				
			||||||
     * For the UNPREDICTABLE cases we choose to UNDEF.
 | 
					     * For the UNPREDICTABLE cases we choose to UNDEF.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    if (s->current_el == 1 && !s->ns) {
 | 
					    if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
 | 
				
			||||||
        gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
 | 
					        gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -7659,11 +7732,11 @@ static void gen_srs(DisasContext *s,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    tcg_gen_addi_i32(addr, addr, offset);
 | 
					    tcg_gen_addi_i32(addr, addr, offset);
 | 
				
			||||||
    tmp = load_reg(s, 14);
 | 
					    tmp = load_reg(s, 14);
 | 
				
			||||||
    gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
    tcg_temp_free_i32(tmp);
 | 
					    tcg_temp_free_i32(tmp);
 | 
				
			||||||
    tmp = load_cpu_field(spsr);
 | 
					    tmp = load_cpu_field(spsr);
 | 
				
			||||||
    tcg_gen_addi_i32(addr, addr, 4);
 | 
					    tcg_gen_addi_i32(addr, addr, 4);
 | 
				
			||||||
    gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
    tcg_temp_free_i32(tmp);
 | 
					    tcg_temp_free_i32(tmp);
 | 
				
			||||||
    if (writeback) {
 | 
					    if (writeback) {
 | 
				
			||||||
        switch (amode) {
 | 
					        switch (amode) {
 | 
				
			||||||
@ -7770,10 +7843,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
 | 
				
			|||||||
        if ((insn & 0x0ffffdff) == 0x01010000) {
 | 
					        if ((insn & 0x0ffffdff) == 0x01010000) {
 | 
				
			||||||
            ARCH(6);
 | 
					            ARCH(6);
 | 
				
			||||||
            /* setend */
 | 
					            /* setend */
 | 
				
			||||||
            if (((insn >> 9) & 1) != s->bswap_code) {
 | 
					            if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
 | 
				
			||||||
                /* Dynamic endianness switching not implemented. */
 | 
					                gen_helper_setend(cpu_env);
 | 
				
			||||||
                qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
 | 
					                s->is_jmp = DISAS_UPDATE;
 | 
				
			||||||
                goto illegal_op;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        } else if ((insn & 0x0fffff00) == 0x057ff000) {
 | 
					        } else if ((insn & 0x0fffff00) == 0x057ff000) {
 | 
				
			||||||
@ -7822,10 +7894,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
 | 
				
			|||||||
                tcg_gen_addi_i32(addr, addr, offset);
 | 
					                tcg_gen_addi_i32(addr, addr, offset);
 | 
				
			||||||
            /* Load PC into tmp and CPSR into tmp2.  */
 | 
					            /* Load PC into tmp and CPSR into tmp2.  */
 | 
				
			||||||
            tmp = tcg_temp_new_i32();
 | 
					            tmp = tcg_temp_new_i32();
 | 
				
			||||||
            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            tcg_gen_addi_i32(addr, addr, 4);
 | 
					            tcg_gen_addi_i32(addr, addr, 4);
 | 
				
			||||||
            tmp2 = tcg_temp_new_i32();
 | 
					            tmp2 = tcg_temp_new_i32();
 | 
				
			||||||
            gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
 | 
					            gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
 | 
				
			||||||
            if (insn & (1 << 21)) {
 | 
					            if (insn & (1 << 21)) {
 | 
				
			||||||
                /* Base writeback.  */
 | 
					                /* Base writeback.  */
 | 
				
			||||||
                switch (i) {
 | 
					                switch (i) {
 | 
				
			||||||
@ -8441,13 +8513,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
 | 
				
			|||||||
                                tmp = tcg_temp_new_i32();
 | 
					                                tmp = tcg_temp_new_i32();
 | 
				
			||||||
                                switch (op1) {
 | 
					                                switch (op1) {
 | 
				
			||||||
                                case 0: /* lda */
 | 
					                                case 0: /* lda */
 | 
				
			||||||
                                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                                    gen_aa32_ld32u(s, tmp, addr,
 | 
				
			||||||
 | 
					                                                   get_mem_index(s));
 | 
				
			||||||
                                    break;
 | 
					                                    break;
 | 
				
			||||||
                                case 2: /* ldab */
 | 
					                                case 2: /* ldab */
 | 
				
			||||||
                                    gen_aa32_ld8u(tmp, addr, get_mem_index(s));
 | 
					                                    gen_aa32_ld8u(s, tmp, addr,
 | 
				
			||||||
 | 
					                                                  get_mem_index(s));
 | 
				
			||||||
                                    break;
 | 
					                                    break;
 | 
				
			||||||
                                case 3: /* ldah */
 | 
					                                case 3: /* ldah */
 | 
				
			||||||
                                    gen_aa32_ld16u(tmp, addr, get_mem_index(s));
 | 
					                                    gen_aa32_ld16u(s, tmp, addr,
 | 
				
			||||||
 | 
					                                                   get_mem_index(s));
 | 
				
			||||||
                                    break;
 | 
					                                    break;
 | 
				
			||||||
                                default:
 | 
					                                default:
 | 
				
			||||||
                                    abort();
 | 
					                                    abort();
 | 
				
			||||||
@ -8458,13 +8533,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
 | 
				
			|||||||
                                tmp = load_reg(s, rm);
 | 
					                                tmp = load_reg(s, rm);
 | 
				
			||||||
                                switch (op1) {
 | 
					                                switch (op1) {
 | 
				
			||||||
                                case 0: /* stl */
 | 
					                                case 0: /* stl */
 | 
				
			||||||
                                    gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                                    gen_aa32_st32(s, tmp, addr,
 | 
				
			||||||
 | 
					                                                  get_mem_index(s));
 | 
				
			||||||
                                    break;
 | 
					                                    break;
 | 
				
			||||||
                                case 2: /* stlb */
 | 
					                                case 2: /* stlb */
 | 
				
			||||||
                                    gen_aa32_st8(tmp, addr, get_mem_index(s));
 | 
					                                    gen_aa32_st8(s, tmp, addr,
 | 
				
			||||||
 | 
					                                                 get_mem_index(s));
 | 
				
			||||||
                                    break;
 | 
					                                    break;
 | 
				
			||||||
                                case 3: /* stlh */
 | 
					                                case 3: /* stlh */
 | 
				
			||||||
                                    gen_aa32_st16(tmp, addr, get_mem_index(s));
 | 
					                                    gen_aa32_st16(s, tmp, addr,
 | 
				
			||||||
 | 
					                                                  get_mem_index(s));
 | 
				
			||||||
                                    break;
 | 
					                                    break;
 | 
				
			||||||
                                default:
 | 
					                                default:
 | 
				
			||||||
                                    abort();
 | 
					                                    abort();
 | 
				
			||||||
@ -8519,11 +8597,11 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
 | 
				
			|||||||
                        tmp = load_reg(s, rm);
 | 
					                        tmp = load_reg(s, rm);
 | 
				
			||||||
                        tmp2 = tcg_temp_new_i32();
 | 
					                        tmp2 = tcg_temp_new_i32();
 | 
				
			||||||
                        if (insn & (1 << 22)) {
 | 
					                        if (insn & (1 << 22)) {
 | 
				
			||||||
                            gen_aa32_ld8u(tmp2, addr, get_mem_index(s));
 | 
					                            gen_aa32_ld8u(s, tmp2, addr, get_mem_index(s));
 | 
				
			||||||
                            gen_aa32_st8(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
 | 
					                            gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
 | 
				
			||||||
                            gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        tcg_temp_free_i32(tmp);
 | 
					                        tcg_temp_free_i32(tmp);
 | 
				
			||||||
                        tcg_temp_free_i32(addr);
 | 
					                        tcg_temp_free_i32(addr);
 | 
				
			||||||
@ -8558,20 +8636,20 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
 | 
				
			|||||||
                    if (!load) {
 | 
					                    if (!load) {
 | 
				
			||||||
                        /* store */
 | 
					                        /* store */
 | 
				
			||||||
                        tmp = load_reg(s, rd);
 | 
					                        tmp = load_reg(s, rd);
 | 
				
			||||||
                        gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        tcg_temp_free_i32(tmp);
 | 
					                        tcg_temp_free_i32(tmp);
 | 
				
			||||||
                        tcg_gen_addi_i32(addr, addr, 4);
 | 
					                        tcg_gen_addi_i32(addr, addr, 4);
 | 
				
			||||||
                        tmp = load_reg(s, rd + 1);
 | 
					                        tmp = load_reg(s, rd + 1);
 | 
				
			||||||
                        gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        tcg_temp_free_i32(tmp);
 | 
					                        tcg_temp_free_i32(tmp);
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        /* load */
 | 
					                        /* load */
 | 
				
			||||||
                        tmp = tcg_temp_new_i32();
 | 
					                        tmp = tcg_temp_new_i32();
 | 
				
			||||||
                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        store_reg(s, rd, tmp);
 | 
					                        store_reg(s, rd, tmp);
 | 
				
			||||||
                        tcg_gen_addi_i32(addr, addr, 4);
 | 
					                        tcg_gen_addi_i32(addr, addr, 4);
 | 
				
			||||||
                        tmp = tcg_temp_new_i32();
 | 
					                        tmp = tcg_temp_new_i32();
 | 
				
			||||||
                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        rd++;
 | 
					                        rd++;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    address_offset = -4;
 | 
					                    address_offset = -4;
 | 
				
			||||||
@ -8580,20 +8658,20 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
 | 
				
			|||||||
                    tmp = tcg_temp_new_i32();
 | 
					                    tmp = tcg_temp_new_i32();
 | 
				
			||||||
                    switch (sh) {
 | 
					                    switch (sh) {
 | 
				
			||||||
                    case 1:
 | 
					                    case 1:
 | 
				
			||||||
                        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 2:
 | 
					                    case 2:
 | 
				
			||||||
                        gen_aa32_ld8s(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    default:
 | 
					                    default:
 | 
				
			||||||
                    case 3:
 | 
					                    case 3:
 | 
				
			||||||
                        gen_aa32_ld16s(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    /* store */
 | 
					                    /* store */
 | 
				
			||||||
                    tmp = load_reg(s, rd);
 | 
					                    tmp = load_reg(s, rd);
 | 
				
			||||||
                    gen_aa32_st16(tmp, addr, get_mem_index(s));
 | 
					                    gen_aa32_st16(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    tcg_temp_free_i32(tmp);
 | 
					                    tcg_temp_free_i32(tmp);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                /* Perform base writeback before the loaded value to
 | 
					                /* Perform base writeback before the loaded value to
 | 
				
			||||||
@ -8946,17 +9024,17 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
 | 
				
			|||||||
                /* load */
 | 
					                /* load */
 | 
				
			||||||
                tmp = tcg_temp_new_i32();
 | 
					                tmp = tcg_temp_new_i32();
 | 
				
			||||||
                if (insn & (1 << 22)) {
 | 
					                if (insn & (1 << 22)) {
 | 
				
			||||||
                    gen_aa32_ld8u(tmp, tmp2, i);
 | 
					                    gen_aa32_ld8u(s, tmp, tmp2, i);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    gen_aa32_ld32u(tmp, tmp2, i);
 | 
					                    gen_aa32_ld32u(s, tmp, tmp2, i);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                /* store */
 | 
					                /* store */
 | 
				
			||||||
                tmp = load_reg(s, rd);
 | 
					                tmp = load_reg(s, rd);
 | 
				
			||||||
                if (insn & (1 << 22)) {
 | 
					                if (insn & (1 << 22)) {
 | 
				
			||||||
                    gen_aa32_st8(tmp, tmp2, i);
 | 
					                    gen_aa32_st8(s, tmp, tmp2, i);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    gen_aa32_st32(tmp, tmp2, i);
 | 
					                    gen_aa32_st32(s, tmp, tmp2, i);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                tcg_temp_free_i32(tmp);
 | 
					                tcg_temp_free_i32(tmp);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -9029,7 +9107,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
 | 
				
			|||||||
                        if (is_load) {
 | 
					                        if (is_load) {
 | 
				
			||||||
                            /* load */
 | 
					                            /* load */
 | 
				
			||||||
                            tmp = tcg_temp_new_i32();
 | 
					                            tmp = tcg_temp_new_i32();
 | 
				
			||||||
                            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                            if (user) {
 | 
					                            if (user) {
 | 
				
			||||||
                                tmp2 = tcg_const_i32(i);
 | 
					                                tmp2 = tcg_const_i32(i);
 | 
				
			||||||
                                gen_helper_set_user_reg(cpu_env, tmp2, tmp);
 | 
					                                gen_helper_set_user_reg(cpu_env, tmp2, tmp);
 | 
				
			||||||
@ -9056,7 +9134,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
 | 
				
			|||||||
                            } else {
 | 
					                            } else {
 | 
				
			||||||
                                tmp = load_reg(s, i);
 | 
					                                tmp = load_reg(s, i);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                            tcg_temp_free_i32(tmp);
 | 
					                            tcg_temp_free_i32(tmp);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        j++;
 | 
					                        j++;
 | 
				
			||||||
@ -9286,7 +9364,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
 | 
				
			|||||||
        /* Fall through to 32-bit decode.  */
 | 
					        /* Fall through to 32-bit decode.  */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    insn = arm_lduw_code(env, s->pc, s->bswap_code);
 | 
					    insn = arm_lduw_code(env, s->pc, s->sctlr_b);
 | 
				
			||||||
    s->pc += 2;
 | 
					    s->pc += 2;
 | 
				
			||||||
    insn |= (uint32_t)insn_hw1 << 16;
 | 
					    insn |= (uint32_t)insn_hw1 << 16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -9323,20 +9401,20 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
 | 
				
			|||||||
                if (insn & (1 << 20)) {
 | 
					                if (insn & (1 << 20)) {
 | 
				
			||||||
                    /* ldrd */
 | 
					                    /* ldrd */
 | 
				
			||||||
                    tmp = tcg_temp_new_i32();
 | 
					                    tmp = tcg_temp_new_i32();
 | 
				
			||||||
                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    store_reg(s, rs, tmp);
 | 
					                    store_reg(s, rs, tmp);
 | 
				
			||||||
                    tcg_gen_addi_i32(addr, addr, 4);
 | 
					                    tcg_gen_addi_i32(addr, addr, 4);
 | 
				
			||||||
                    tmp = tcg_temp_new_i32();
 | 
					                    tmp = tcg_temp_new_i32();
 | 
				
			||||||
                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    store_reg(s, rd, tmp);
 | 
					                    store_reg(s, rd, tmp);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    /* strd */
 | 
					                    /* strd */
 | 
				
			||||||
                    tmp = load_reg(s, rs);
 | 
					                    tmp = load_reg(s, rs);
 | 
				
			||||||
                    gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    tcg_temp_free_i32(tmp);
 | 
					                    tcg_temp_free_i32(tmp);
 | 
				
			||||||
                    tcg_gen_addi_i32(addr, addr, 4);
 | 
					                    tcg_gen_addi_i32(addr, addr, 4);
 | 
				
			||||||
                    tmp = load_reg(s, rd);
 | 
					                    tmp = load_reg(s, rd);
 | 
				
			||||||
                    gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    tcg_temp_free_i32(tmp);
 | 
					                    tcg_temp_free_i32(tmp);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (insn & (1 << 21)) {
 | 
					                if (insn & (1 << 21)) {
 | 
				
			||||||
@ -9374,11 +9452,11 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
 | 
				
			|||||||
                    tcg_gen_add_i32(addr, addr, tmp);
 | 
					                    tcg_gen_add_i32(addr, addr, tmp);
 | 
				
			||||||
                    tcg_temp_free_i32(tmp);
 | 
					                    tcg_temp_free_i32(tmp);
 | 
				
			||||||
                    tmp = tcg_temp_new_i32();
 | 
					                    tmp = tcg_temp_new_i32();
 | 
				
			||||||
                    gen_aa32_ld16u(tmp, addr, get_mem_index(s));
 | 
					                    gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                } else { /* tbb */
 | 
					                } else { /* tbb */
 | 
				
			||||||
                    tcg_temp_free_i32(tmp);
 | 
					                    tcg_temp_free_i32(tmp);
 | 
				
			||||||
                    tmp = tcg_temp_new_i32();
 | 
					                    tmp = tcg_temp_new_i32();
 | 
				
			||||||
                    gen_aa32_ld8u(tmp, addr, get_mem_index(s));
 | 
					                    gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                tcg_temp_free_i32(addr);
 | 
					                tcg_temp_free_i32(addr);
 | 
				
			||||||
                tcg_gen_shli_i32(tmp, tmp, 1);
 | 
					                tcg_gen_shli_i32(tmp, tmp, 1);
 | 
				
			||||||
@ -9415,13 +9493,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
 | 
				
			|||||||
                        tmp = tcg_temp_new_i32();
 | 
					                        tmp = tcg_temp_new_i32();
 | 
				
			||||||
                        switch (op) {
 | 
					                        switch (op) {
 | 
				
			||||||
                        case 0: /* ldab */
 | 
					                        case 0: /* ldab */
 | 
				
			||||||
                            gen_aa32_ld8u(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
                        case 1: /* ldah */
 | 
					                        case 1: /* ldah */
 | 
				
			||||||
                            gen_aa32_ld16u(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
                        case 2: /* lda */
 | 
					                        case 2: /* lda */
 | 
				
			||||||
                            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
                        default:
 | 
					                        default:
 | 
				
			||||||
                            abort();
 | 
					                            abort();
 | 
				
			||||||
@ -9431,13 +9509,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
 | 
				
			|||||||
                        tmp = load_reg(s, rs);
 | 
					                        tmp = load_reg(s, rs);
 | 
				
			||||||
                        switch (op) {
 | 
					                        switch (op) {
 | 
				
			||||||
                        case 0: /* stlb */
 | 
					                        case 0: /* stlb */
 | 
				
			||||||
                            gen_aa32_st8(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
                        case 1: /* stlh */
 | 
					                        case 1: /* stlh */
 | 
				
			||||||
                            gen_aa32_st16(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
                        case 2: /* stl */
 | 
					                        case 2: /* stl */
 | 
				
			||||||
                            gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
                        default:
 | 
					                        default:
 | 
				
			||||||
                            abort();
 | 
					                            abort();
 | 
				
			||||||
@ -9465,10 +9543,10 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
 | 
				
			|||||||
                        tcg_gen_addi_i32(addr, addr, -8);
 | 
					                        tcg_gen_addi_i32(addr, addr, -8);
 | 
				
			||||||
                    /* Load PC into tmp and CPSR into tmp2.  */
 | 
					                    /* Load PC into tmp and CPSR into tmp2.  */
 | 
				
			||||||
                    tmp = tcg_temp_new_i32();
 | 
					                    tmp = tcg_temp_new_i32();
 | 
				
			||||||
                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    tcg_gen_addi_i32(addr, addr, 4);
 | 
					                    tcg_gen_addi_i32(addr, addr, 4);
 | 
				
			||||||
                    tmp2 = tcg_temp_new_i32();
 | 
					                    tmp2 = tcg_temp_new_i32();
 | 
				
			||||||
                    gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
 | 
					                    gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
 | 
				
			||||||
                    if (insn & (1 << 21)) {
 | 
					                    if (insn & (1 << 21)) {
 | 
				
			||||||
                        /* Base writeback.  */
 | 
					                        /* Base writeback.  */
 | 
				
			||||||
                        if (insn & (1 << 24)) {
 | 
					                        if (insn & (1 << 24)) {
 | 
				
			||||||
@ -9507,7 +9585,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
 | 
				
			|||||||
                    if (insn & (1 << 20)) {
 | 
					                    if (insn & (1 << 20)) {
 | 
				
			||||||
                        /* Load.  */
 | 
					                        /* Load.  */
 | 
				
			||||||
                        tmp = tcg_temp_new_i32();
 | 
					                        tmp = tcg_temp_new_i32();
 | 
				
			||||||
                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        if (i == 15) {
 | 
					                        if (i == 15) {
 | 
				
			||||||
                            gen_bx(s, tmp);
 | 
					                            gen_bx(s, tmp);
 | 
				
			||||||
                        } else if (i == rn) {
 | 
					                        } else if (i == rn) {
 | 
				
			||||||
@ -9519,7 +9597,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
 | 
				
			|||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        /* Store.  */
 | 
					                        /* Store.  */
 | 
				
			||||||
                        tmp = load_reg(s, i);
 | 
					                        tmp = load_reg(s, i);
 | 
				
			||||||
                        gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        tcg_temp_free_i32(tmp);
 | 
					                        tcg_temp_free_i32(tmp);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    tcg_gen_addi_i32(addr, addr, 4);
 | 
					                    tcg_gen_addi_i32(addr, addr, 4);
 | 
				
			||||||
@ -10449,19 +10527,19 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
 | 
				
			|||||||
            tmp = tcg_temp_new_i32();
 | 
					            tmp = tcg_temp_new_i32();
 | 
				
			||||||
            switch (op) {
 | 
					            switch (op) {
 | 
				
			||||||
            case 0:
 | 
					            case 0:
 | 
				
			||||||
                gen_aa32_ld8u(tmp, addr, memidx);
 | 
					                gen_aa32_ld8u(s, tmp, addr, memidx);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case 4:
 | 
					            case 4:
 | 
				
			||||||
                gen_aa32_ld8s(tmp, addr, memidx);
 | 
					                gen_aa32_ld8s(s, tmp, addr, memidx);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case 1:
 | 
					            case 1:
 | 
				
			||||||
                gen_aa32_ld16u(tmp, addr, memidx);
 | 
					                gen_aa32_ld16u(s, tmp, addr, memidx);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case 5:
 | 
					            case 5:
 | 
				
			||||||
                gen_aa32_ld16s(tmp, addr, memidx);
 | 
					                gen_aa32_ld16s(s, tmp, addr, memidx);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case 2:
 | 
					            case 2:
 | 
				
			||||||
                gen_aa32_ld32u(tmp, addr, memidx);
 | 
					                gen_aa32_ld32u(s, tmp, addr, memidx);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                tcg_temp_free_i32(tmp);
 | 
					                tcg_temp_free_i32(tmp);
 | 
				
			||||||
@ -10478,13 +10556,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
 | 
				
			|||||||
            tmp = load_reg(s, rs);
 | 
					            tmp = load_reg(s, rs);
 | 
				
			||||||
            switch (op) {
 | 
					            switch (op) {
 | 
				
			||||||
            case 0:
 | 
					            case 0:
 | 
				
			||||||
                gen_aa32_st8(tmp, addr, memidx);
 | 
					                gen_aa32_st8(s, tmp, addr, memidx);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case 1:
 | 
					            case 1:
 | 
				
			||||||
                gen_aa32_st16(tmp, addr, memidx);
 | 
					                gen_aa32_st16(s, tmp, addr, memidx);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case 2:
 | 
					            case 2:
 | 
				
			||||||
                gen_aa32_st32(tmp, addr, memidx);
 | 
					                gen_aa32_st32(s, tmp, addr, memidx);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                tcg_temp_free_i32(tmp);
 | 
					                tcg_temp_free_i32(tmp);
 | 
				
			||||||
@ -10528,7 +10606,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    insn = arm_lduw_code(env, s->pc, s->bswap_code);
 | 
					    insn = arm_lduw_code(env, s->pc, s->sctlr_b);
 | 
				
			||||||
    s->pc += 2;
 | 
					    s->pc += 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (insn >> 12) {
 | 
					    switch (insn >> 12) {
 | 
				
			||||||
@ -10621,7 +10699,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
            addr = tcg_temp_new_i32();
 | 
					            addr = tcg_temp_new_i32();
 | 
				
			||||||
            tcg_gen_movi_i32(addr, val);
 | 
					            tcg_gen_movi_i32(addr, val);
 | 
				
			||||||
            tmp = tcg_temp_new_i32();
 | 
					            tmp = tcg_temp_new_i32();
 | 
				
			||||||
            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            tcg_temp_free_i32(addr);
 | 
					            tcg_temp_free_i32(addr);
 | 
				
			||||||
            store_reg(s, rd, tmp);
 | 
					            store_reg(s, rd, tmp);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@ -10824,28 +10902,28 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        switch (op) {
 | 
					        switch (op) {
 | 
				
			||||||
        case 0: /* str */
 | 
					        case 0: /* str */
 | 
				
			||||||
            gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 1: /* strh */
 | 
					        case 1: /* strh */
 | 
				
			||||||
            gen_aa32_st16(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 2: /* strb */
 | 
					        case 2: /* strb */
 | 
				
			||||||
            gen_aa32_st8(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 3: /* ldrsb */
 | 
					        case 3: /* ldrsb */
 | 
				
			||||||
            gen_aa32_ld8s(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 4: /* ldr */
 | 
					        case 4: /* ldr */
 | 
				
			||||||
            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 5: /* ldrh */
 | 
					        case 5: /* ldrh */
 | 
				
			||||||
            gen_aa32_ld16u(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 6: /* ldrb */
 | 
					        case 6: /* ldrb */
 | 
				
			||||||
            gen_aa32_ld8u(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 7: /* ldrsh */
 | 
					        case 7: /* ldrsh */
 | 
				
			||||||
            gen_aa32_ld16s(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (op >= 3) { /* load */
 | 
					        if (op >= 3) { /* load */
 | 
				
			||||||
@ -10867,12 +10945,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
        if (insn & (1 << 11)) {
 | 
					        if (insn & (1 << 11)) {
 | 
				
			||||||
            /* load */
 | 
					            /* load */
 | 
				
			||||||
            tmp = tcg_temp_new_i32();
 | 
					            tmp = tcg_temp_new_i32();
 | 
				
			||||||
            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            store_reg(s, rd, tmp);
 | 
					            store_reg(s, rd, tmp);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            /* store */
 | 
					            /* store */
 | 
				
			||||||
            tmp = load_reg(s, rd);
 | 
					            tmp = load_reg(s, rd);
 | 
				
			||||||
            gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            tcg_temp_free_i32(tmp);
 | 
					            tcg_temp_free_i32(tmp);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        tcg_temp_free_i32(addr);
 | 
					        tcg_temp_free_i32(addr);
 | 
				
			||||||
@ -10889,12 +10967,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
        if (insn & (1 << 11)) {
 | 
					        if (insn & (1 << 11)) {
 | 
				
			||||||
            /* load */
 | 
					            /* load */
 | 
				
			||||||
            tmp = tcg_temp_new_i32();
 | 
					            tmp = tcg_temp_new_i32();
 | 
				
			||||||
            gen_aa32_ld8u(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            store_reg(s, rd, tmp);
 | 
					            store_reg(s, rd, tmp);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            /* store */
 | 
					            /* store */
 | 
				
			||||||
            tmp = load_reg(s, rd);
 | 
					            tmp = load_reg(s, rd);
 | 
				
			||||||
            gen_aa32_st8(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            tcg_temp_free_i32(tmp);
 | 
					            tcg_temp_free_i32(tmp);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        tcg_temp_free_i32(addr);
 | 
					        tcg_temp_free_i32(addr);
 | 
				
			||||||
@ -10911,12 +10989,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
        if (insn & (1 << 11)) {
 | 
					        if (insn & (1 << 11)) {
 | 
				
			||||||
            /* load */
 | 
					            /* load */
 | 
				
			||||||
            tmp = tcg_temp_new_i32();
 | 
					            tmp = tcg_temp_new_i32();
 | 
				
			||||||
            gen_aa32_ld16u(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            store_reg(s, rd, tmp);
 | 
					            store_reg(s, rd, tmp);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            /* store */
 | 
					            /* store */
 | 
				
			||||||
            tmp = load_reg(s, rd);
 | 
					            tmp = load_reg(s, rd);
 | 
				
			||||||
            gen_aa32_st16(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            tcg_temp_free_i32(tmp);
 | 
					            tcg_temp_free_i32(tmp);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        tcg_temp_free_i32(addr);
 | 
					        tcg_temp_free_i32(addr);
 | 
				
			||||||
@ -10932,12 +11010,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
        if (insn & (1 << 11)) {
 | 
					        if (insn & (1 << 11)) {
 | 
				
			||||||
            /* load */
 | 
					            /* load */
 | 
				
			||||||
            tmp = tcg_temp_new_i32();
 | 
					            tmp = tcg_temp_new_i32();
 | 
				
			||||||
            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            store_reg(s, rd, tmp);
 | 
					            store_reg(s, rd, tmp);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            /* store */
 | 
					            /* store */
 | 
				
			||||||
            tmp = load_reg(s, rd);
 | 
					            tmp = load_reg(s, rd);
 | 
				
			||||||
            gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
            tcg_temp_free_i32(tmp);
 | 
					            tcg_temp_free_i32(tmp);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        tcg_temp_free_i32(addr);
 | 
					        tcg_temp_free_i32(addr);
 | 
				
			||||||
@ -11005,12 +11083,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
                    if (insn & (1 << 11)) {
 | 
					                    if (insn & (1 << 11)) {
 | 
				
			||||||
                        /* pop */
 | 
					                        /* pop */
 | 
				
			||||||
                        tmp = tcg_temp_new_i32();
 | 
					                        tmp = tcg_temp_new_i32();
 | 
				
			||||||
                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        store_reg(s, i, tmp);
 | 
					                        store_reg(s, i, tmp);
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        /* push */
 | 
					                        /* push */
 | 
				
			||||||
                        tmp = load_reg(s, i);
 | 
					                        tmp = load_reg(s, i);
 | 
				
			||||||
                        gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                        tcg_temp_free_i32(tmp);
 | 
					                        tcg_temp_free_i32(tmp);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    /* advance to the next address.  */
 | 
					                    /* advance to the next address.  */
 | 
				
			||||||
@ -11022,13 +11100,13 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
                if (insn & (1 << 11)) {
 | 
					                if (insn & (1 << 11)) {
 | 
				
			||||||
                    /* pop pc */
 | 
					                    /* pop pc */
 | 
				
			||||||
                    tmp = tcg_temp_new_i32();
 | 
					                    tmp = tcg_temp_new_i32();
 | 
				
			||||||
                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    /* don't set the pc until the rest of the instruction
 | 
					                    /* don't set the pc until the rest of the instruction
 | 
				
			||||||
                       has completed */
 | 
					                       has completed */
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    /* push lr */
 | 
					                    /* push lr */
 | 
				
			||||||
                    tmp = load_reg(s, 14);
 | 
					                    tmp = load_reg(s, 14);
 | 
				
			||||||
                    gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    tcg_temp_free_i32(tmp);
 | 
					                    tcg_temp_free_i32(tmp);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                tcg_gen_addi_i32(addr, addr, 4);
 | 
					                tcg_gen_addi_i32(addr, addr, 4);
 | 
				
			||||||
@ -11099,10 +11177,9 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
            case 2:
 | 
					            case 2:
 | 
				
			||||||
                /* setend */
 | 
					                /* setend */
 | 
				
			||||||
                ARCH(6);
 | 
					                ARCH(6);
 | 
				
			||||||
                if (((insn >> 3) & 1) != s->bswap_code) {
 | 
					                if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
 | 
				
			||||||
                    /* Dynamic endianness switching not implemented. */
 | 
					                    gen_helper_setend(cpu_env);
 | 
				
			||||||
                    qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
 | 
					                    s->is_jmp = DISAS_UPDATE;
 | 
				
			||||||
                    goto illegal_op;
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case 3:
 | 
					            case 3:
 | 
				
			||||||
@ -11158,7 +11235,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
                if (insn & (1 << 11)) {
 | 
					                if (insn & (1 << 11)) {
 | 
				
			||||||
                    /* load */
 | 
					                    /* load */
 | 
				
			||||||
                    tmp = tcg_temp_new_i32();
 | 
					                    tmp = tcg_temp_new_i32();
 | 
				
			||||||
                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
 | 
					                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    if (i == rn) {
 | 
					                    if (i == rn) {
 | 
				
			||||||
                        loaded_var = tmp;
 | 
					                        loaded_var = tmp;
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
@ -11167,7 +11244,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    /* store */
 | 
					                    /* store */
 | 
				
			||||||
                    tmp = load_reg(s, i);
 | 
					                    tmp = load_reg(s, i);
 | 
				
			||||||
                    gen_aa32_st32(tmp, addr, get_mem_index(s));
 | 
					                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
 | 
				
			||||||
                    tcg_temp_free_i32(tmp);
 | 
					                    tcg_temp_free_i32(tmp);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                /* advance to the next address */
 | 
					                /* advance to the next address */
 | 
				
			||||||
@ -11253,7 +11330,7 @@ static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* This must be a Thumb insn */
 | 
					    /* This must be a Thumb insn */
 | 
				
			||||||
    insn = arm_lduw_code(env, s->pc, s->bswap_code);
 | 
					    insn = arm_lduw_code(env, s->pc, s->sctlr_b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((insn >> 11) >= 0x1d) {
 | 
					    if ((insn >> 11) >= 0x1d) {
 | 
				
			||||||
        /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
 | 
					        /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
 | 
				
			||||||
@ -11307,7 +11384,8 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
 | 
				
			|||||||
    dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
 | 
					    dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
 | 
				
			||||||
                               !arm_el_is_aa64(env, 3);
 | 
					                               !arm_el_is_aa64(env, 3);
 | 
				
			||||||
    dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
 | 
					    dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
 | 
				
			||||||
    dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
 | 
					    dc->sctlr_b = ARM_TBFLAG_SCTLR_B(tb->flags);
 | 
				
			||||||
 | 
					    dc->be_data = ARM_TBFLAG_BE_DATA(tb->flags) ? MO_BE : MO_LE;
 | 
				
			||||||
    dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
 | 
					    dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
 | 
				
			||||||
    dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
 | 
					    dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
 | 
				
			||||||
    dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
 | 
					    dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
 | 
				
			||||||
@ -11487,7 +11565,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            unsigned int insn = arm_ldl_code(env, dc->pc, dc->bswap_code);
 | 
					            unsigned int insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
 | 
				
			||||||
            dc->pc += 4;
 | 
					            dc->pc += 4;
 | 
				
			||||||
            disas_arm_insn(dc, insn);
 | 
					            disas_arm_insn(dc, insn);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -11644,7 +11722,7 @@ done_generating:
 | 
				
			|||||||
        qemu_log("----------------\n");
 | 
					        qemu_log("----------------\n");
 | 
				
			||||||
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
 | 
					        qemu_log("IN: %s\n", lookup_symbol(pc_start));
 | 
				
			||||||
        log_target_disas(cs, pc_start, dc->pc - pc_start,
 | 
					        log_target_disas(cs, pc_start, dc->pc - pc_start,
 | 
				
			||||||
                         dc->thumb | (dc->bswap_code << 1));
 | 
					                         dc->thumb | (dc->sctlr_b << 1));
 | 
				
			||||||
        qemu_log("\n");
 | 
					        qemu_log("\n");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,8 @@ typedef struct DisasContext {
 | 
				
			|||||||
    struct TranslationBlock *tb;
 | 
					    struct TranslationBlock *tb;
 | 
				
			||||||
    int singlestep_enabled;
 | 
					    int singlestep_enabled;
 | 
				
			||||||
    int thumb;
 | 
					    int thumb;
 | 
				
			||||||
    int bswap_code;
 | 
					    int sctlr_b;
 | 
				
			||||||
 | 
					    TCGMemOp be_data;
 | 
				
			||||||
#if !defined(CONFIG_USER_ONLY)
 | 
					#if !defined(CONFIG_USER_ONLY)
 | 
				
			||||||
    int user;
 | 
					    int user;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user