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:
Peter Maydell 2016-03-04 11:46:32 +00:00
commit 3c0f12df65
55 changed files with 1059 additions and 426 deletions

View file

@ -111,7 +111,7 @@ static void clipper_init(MachineState *machine)
}
size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
NULL, &palcode_entry, &palcode_low, &palcode_high,
0, EM_ALPHA, 0);
0, EM_ALPHA, 0, 0);
if (size < 0) {
error_report("could not load palcode '%s'", palcode_filename);
exit(1);
@ -131,7 +131,7 @@ static void clipper_init(MachineState *machine)
size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
NULL, &kernel_entry, &kernel_low, &kernel_high,
0, EM_ALPHA, 0);
0, EM_ALPHA, 0, 0);
if (size < 0) {
error_report("could not load kernel '%s'", kernel_filename);
exit(1);

View file

@ -211,7 +211,7 @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
if (kernel_filename) {
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) {
image_size = load_image_targphys(kernel_filename, 0, mem_size);
lowaddr = 0;

View file

@ -518,9 +518,34 @@ static void do_cpu_reset(void *opaque)
cpu_reset(cs);
if (info) {
if (!info->is_linux) {
int i;
/* Jump to the entry point. */
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) {
env->thumb = info->entry & 1;
entry &= 0xfffffffe;
@ -638,6 +663,62 @@ static int do_arm_linux_init(Object *obj, void *opaque)
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)
{
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;
int elf_machine;
hwaddr entry, kernel_load_offset;
int big_endian;
static const ARMInsnFixup *primary_loader;
ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
notifier, notifier);
@ -733,12 +813,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
if (info->nb_cpus == 0)
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
* kernel is uncompressed it will not clobber the initrd. However
* 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);
/* Assume that raw images are linux kernels, and ELF images are not. */
kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
&elf_low_addr, &elf_high_addr, big_endian,
elf_machine, 1);
kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
&elf_high_addr, elf_machine);
if (kernel_size > 0 && have_dtb(info)) {
/* 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.

View file

@ -73,6 +73,7 @@ typedef struct VirtBoardInfo {
uint32_t clock_phandle;
uint32_t gic_phandle;
uint32_t v2m_phandle;
bool using_psci;
} VirtBoardInfo;
typedef struct {
@ -95,6 +96,23 @@ typedef struct {
#define VIRT_MACHINE_CLASS(klass) \
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.
* 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.
@ -127,10 +145,11 @@ static const MemMapEntry a15memmap[] = {
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
[VIRT_SECURE_MEM] = { 0x0e000000, 0x01000000 },
[VIRT_PCIE_MMIO] = { 0x10000000, 0x2eff0000 },
[VIRT_PCIE_PIO] = { 0x3eff0000, 0x00010000 },
[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 */
[VIRT_PCIE_MMIO_HIGH] = { 0x8000000000ULL, 0x8000000000ULL },
};
@ -230,6 +249,10 @@ static void fdt_add_psci_node(const VirtBoardInfo *vbi)
void *fdt = vbi->fdt;
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
if (!vbi->using_psci) {
return;
}
qemu_fdt_add_subnode(fdt, "/psci");
if (armcpu->psci_version == 2) {
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",
armcpu->dtb_compatible);
if (vbi->smp_cpus > 1) {
if (vbi->using_psci && vbi->smp_cpus > 1) {
qemu_fdt_setprop_string(vbi->fdt, nodename,
"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,
hwaddr flashsize)
hwaddr flashsize, const char *file,
MemoryRegion *sysmem)
{
/* Create and map a single flash device. We use the same
* parameters as the flash devices on the Versatile Express board.
*/
DriveInfo *dinfo = drive_get_next(IF_PFLASH);
DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
const uint64_t sectorlength = 256 * 1024;
if (dinfo) {
@ -704,19 +729,10 @@ static void create_one_flash(const char *name, hwaddr flashbase,
qdev_prop_set_string(dev, "name", name);
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)
{
/* 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) {
if (file) {
char *fn;
int image_size;
@ -726,30 +742,73 @@ static void create_flash(const VirtBoardInfo *vbi)
"but you cannot use both options at once");
exit(1);
}
fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, file);
if (!fn) {
error_report("Could not find ROM image '%s'", bios_name);
error_report("Could not find ROM image '%s'", file);
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);
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);
}
}
}
create_one_flash("virt.flash0", flashbase, flashsize);
create_one_flash("virt.flash1", flashbase + flashsize, flashsize);
static void create_flash(const VirtBoardInfo *vbi,
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;
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, 2, flashsize,
2, flashbase + flashsize, 2, flashsize);
qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4);
g_free(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);
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,
2, flashbase + flashsize, 2, flashsize);
qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4);
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)
@ -960,6 +1019,27 @@ static void create_platform_bus(VirtBoardInfo *vbi, qemu_irq *pic)
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)
{
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);
VirtGuestInfo *guest_info = &guest_info_state->info;
char **cpustr;
bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
if (!cpu_model) {
cpu_model = "cortex-a15";
@ -1047,6 +1128,15 @@ static void machvirt_init(MachineState *machine)
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
* many redistributors we can fit into the memory map.
*/
@ -1066,7 +1156,7 @@ static void machvirt_init(MachineState *machine)
vbi->smp_cpus = smp_cpus;
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);
}
@ -1114,12 +1204,15 @@ static void machvirt_init(MachineState *machine)
object_property_set_bool(cpuobj, false, "has_el3", NULL);
}
object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_HVC, "psci-conduit",
NULL);
if (vbi->using_psci) {
object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_HVC,
"psci-conduit", NULL);
/* Secondary CPUs start in PSCI powered-down state */
if (n > 0) {
object_property_set_bool(cpuobj, true, "start-powered-off", NULL);
/* Secondary CPUs start in PSCI powered-down state */
if (n > 0) {
object_property_set_bool(cpuobj, true,
"start-powered-off", NULL);
}
}
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
@ -1145,13 +1238,14 @@ static void machvirt_init(MachineState *machine)
machine->ram_size);
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_uart(vbi, pic, VIRT_UART, sysmem);
if (vms->secure) {
create_secure_ram(vbi, 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.loader_start = vbi->memmap[VIRT_MEM].base;
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);
/*

View file

@ -147,6 +147,28 @@ int load_image_targphys(const char *filename,
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,
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 */
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
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;
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);
if (e_ident[EI_CLASS] == ELFCLASS64) {
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 {
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:
@ -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,
hwaddr addr, int32_t bootindex,
bool option_rom)
bool option_rom, MemoryRegion *mr)
{
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
Rom *rom;
@ -818,7 +898,12 @@ int rom_add_file(const char *file, const char *fw_dir,
fw_cfg_add_file(fw_cfg, fw_file_name, data, rom->romsize);
} else {
snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr);
if (mr) {
rom->mr = mr;
snprintf(devpath, sizeof(devpath), "/rom@%s", file);
} else {
snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr);
}
}
add_boot_device_path(bootindex, NULL, devpath);
@ -892,12 +977,12 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize,
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)
{
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)

View file

@ -109,7 +109,7 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
/* Memory map (addresses are offsets from PERIPHBASE):
* 0x0000-0x0fff -- reserved
* 0x1000-0x1fff -- GIC Distributor
* 0x2000-0x2fff -- GIC CPU interface
* 0x2000-0x3fff -- GIC CPU interface
* 0x4000-0x4fff -- GIC virtual interface control (not modelled)
* 0x5000-0x5fff -- GIC virtual interface control (not modelled)
* 0x6000-0x7fff -- GIC virtual CPU interface (not modelled)

View file

@ -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
devboard SDK. */
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;
if (image_size < 0) {
/* Takes a kimage from the axis devboard SDK. */

View file

@ -196,7 +196,8 @@ int load_multiboot(FWCfgState *fw_cfg,
}
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) {
fprintf(stderr, "Error while loading elf kernel\n");
exit(1);

View file

@ -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)
{
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_CLEAR_ACTIVE(irq, cm);
/* 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_update(s);
}
@ -1210,6 +1249,10 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
s->nsapr[regno][cpu] = value;
break;
}
case 0x1000:
/* GICC_DIR */
gic_deactivate_irq(s, cpu, value & 0x3ff, attrs);
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"gic_cpu_write: Bad offset %x\n", (int)offset);

View file

@ -121,7 +121,7 @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
* neither it can use KVM.
*/
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]);
}
}

View file

@ -143,7 +143,7 @@ static void lm32_evr_init(MachineState *machine)
int kernel_size;
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;
if (kernel_size < 0) {
@ -245,7 +245,7 @@ static void lm32_uclinux_init(MachineState *machine)
int kernel_size;
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;
if (kernel_size < 0) {

View file

@ -177,7 +177,7 @@ milkymist_init(MachineState *machine)
/* Boots a kernel elf binary. */
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;
if (kernel_size < 0) {

View file

@ -73,7 +73,7 @@ static void an5206_init(MachineState *machine)
}
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;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,

View file

@ -50,7 +50,7 @@ static void dummy_m68k_init(MachineState *machine)
/* Load kernel. */
if (kernel_filename) {
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;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,

View file

@ -276,7 +276,7 @@ static void mcf5208evb_init(MachineState *machine)
}
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;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,

View file

@ -142,12 +142,12 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
/* Boots a kernel elf binary. */
kernel_size = load_elf(kernel_filename, NULL, NULL,
&entry, &low, &high,
big_endian, EM_MICROBLAZE, 0);
big_endian, EM_MICROBLAZE, 0, 0);
base32 = entry;
if (base32 == 0xc0000000) {
kernel_size = load_elf(kernel_filename, translate_kernel_address,
NULL, &entry, NULL, NULL,
big_endian, EM_MICROBLAZE, 0);
big_endian, EM_MICROBLAZE, 0, 0);
}
/* Always boot into physical ram. */
boot_info.bootstrap_pc = (uint32_t)entry;

View file

@ -117,7 +117,7 @@ static int64_t load_kernel (CPUMIPSState *env)
if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
(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",
loaderparams.kernel_filename);
exit(1);

View file

@ -796,7 +796,7 @@ static int64_t load_kernel (void)
if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
(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",
loaderparams.kernel_filename);
exit(1);

View file

@ -70,7 +70,7 @@ static int64_t load_kernel(void)
kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
NULL, (uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, big_endian,
EM_MIPS, 1);
EM_MIPS, 1, 0);
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry;

View file

@ -88,7 +88,7 @@ static int64_t load_kernel(void)
kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
NULL, (uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, big_endian,
EM_MIPS, 1);
EM_MIPS, 1, 0);
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry;

View file

@ -98,7 +98,7 @@ static void bcm2835_mbox_update(BCM2835MboxState *s)
*/
for (n = 0; n < MBOX_CHAN_COUNT; n++) {
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 */
mbox_push(&s->mbox[0], value);
}
@ -207,12 +207,12 @@ static void bcm2835_mbox_write(void *opaque, hwaddr offset,
ch = value & 0xf;
if (ch < MBOX_CHAN_COUNT) {
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 */
mbox_push(&s->mbox[1], value);
} else {
/* Push it directly to the child device */
stl_phys(&s->mbox_as, childaddr, value);
stl_le_phys(&s->mbox_as, childaddr, value);
}
} else {
/* Invalid channel number */

View file

@ -22,20 +22,20 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t 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 */
value = s->addr + 8;
while (value + 8 <= s->addr + tot_len) {
tag = ldl_phys(&s->dma_as, value);
bufsize = ldl_phys(&s->dma_as, value + 4);
tag = ldl_le_phys(&s->dma_as, value);
bufsize = ldl_le_phys(&s->dma_as, value + 4);
/* @(value + 8) : Request/response indicator */
resplen = 0;
switch (tag) {
case 0x00000000: /* End tag */
break;
case 0x00000001: /* Get firmware revision */
stl_phys(&s->dma_as, value + 12, 346337);
stl_le_phys(&s->dma_as, value + 12, 346337);
resplen = 4;
break;
case 0x00010001: /* Get board model */
@ -44,7 +44,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
resplen = 4;
break;
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;
break;
case 0x00010003: /* Get board MAC address */
@ -58,24 +58,24 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
break;
case 0x00010005: /* Get ARM memory */
/* base */
stl_phys(&s->dma_as, value + 12, 0);
stl_le_phys(&s->dma_as, value + 12, 0);
/* size */
stl_phys(&s->dma_as, value + 16, s->ram_size);
stl_le_phys(&s->dma_as, value + 16, s->ram_size);
resplen = 8;
break;
case 0x00028001: /* Set power state */
/* Assume that whatever device they asked for exists,
* and we'll just claim we set it to the desired state
*/
tmp = ldl_phys(&s->dma_as, value + 16);
stl_phys(&s->dma_as, value + 16, (tmp & 1));
tmp = ldl_le_phys(&s->dma_as, value + 16);
stl_le_phys(&s->dma_as, value + 16, (tmp & 1));
resplen = 8;
break;
/* Clocks */
case 0x00030001: /* Get clock state */
stl_phys(&s->dma_as, value + 16, 0x1);
stl_le_phys(&s->dma_as, value + 16, 0x1);
resplen = 8;
break;
@ -88,15 +88,15 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
case 0x00030002: /* Get clock rate */
case 0x00030004: /* Get max 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 */
stl_phys(&s->dma_as, value + 16, 50000000);
stl_le_phys(&s->dma_as, value + 16, 50000000);
break;
case 2: /* UART */
stl_phys(&s->dma_as, value + 16, 3000000);
stl_le_phys(&s->dma_as, value + 16, 3000000);
break;
default:
stl_phys(&s->dma_as, value + 16, 700000000);
stl_le_phys(&s->dma_as, value + 16, 700000000);
break;
}
resplen = 8;
@ -113,19 +113,19 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
/* Temperature */
case 0x00030006: /* Get temperature */
stl_phys(&s->dma_as, value + 16, 25000);
stl_le_phys(&s->dma_as, value + 16, 25000);
resplen = 8;
break;
case 0x0003000A: /* Get max temperature */
stl_phys(&s->dma_as, value + 16, 99000);
stl_le_phys(&s->dma_as, value + 16, 99000);
resplen = 8;
break;
case 0x00060001: /* Get DMA channels */
/* channels 2-5 */
stl_phys(&s->dma_as, value + 12, 0x003C);
stl_le_phys(&s->dma_as, value + 12, 0x003C);
resplen = 4;
break;
@ -143,12 +143,12 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
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;
}
/* 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,

View file

@ -54,7 +54,8 @@ static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params)
ram_addr_t initrd_offset;
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) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",

View file

@ -69,7 +69,8 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
if (kernel_filename && !qtest_enabled()) {
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;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename,

View file

@ -313,7 +313,7 @@ static void raven_realize(PCIDevice *d, Error **errp)
if (filename) {
if (s->elf_machine != EM_NONE) {
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) {
bios_size = get_image_size(filename);

View file

@ -1017,7 +1017,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
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) {
/*
* Hrm. No ELF image? Try a uImage, maybe someone is giving us an

View file

@ -221,7 +221,7 @@ static void ppc_core99_init(MachineState *machine)
/* Load OpenBIOS (ELF) */
if (filename) {
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);
} else {
@ -244,7 +244,8 @@ static void ppc_core99_init(MachineState *machine)
kernel_base = KERNEL_LOAD_ADDR;
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)
kernel_size = load_aout(kernel_filename, kernel_base,
ram_size - kernel_base, bswap_needed,

View file

@ -149,7 +149,7 @@ static void ppc_heathrow_init(MachineState *machine)
/* Load OpenBIOS (ELF) */
if (filename) {
bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
1, PPC_ELF_MACHINE, 0);
1, PPC_ELF_MACHINE, 0, 0);
g_free(filename);
} else {
bios_size = -1;
@ -170,7 +170,8 @@ static void ppc_heathrow_init(MachineState *machine)
#endif
kernel_base = KERNEL_LOAD_ADDR;
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)
kernel_size = load_aout(kernel_filename, kernel_base,
ram_size - kernel_base, bswap_needed,

View file

@ -256,7 +256,8 @@ static void bamboo_init(MachineState *machine)
NULL, NULL);
if (success < 0) {
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;
loadaddr = elf_lowaddr;
}

View file

@ -1942,11 +1942,13 @@ static void ppc_spapr_init(MachineState *machine)
uint64_t lowaddr = 0;
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) {
kernel_size = load_elf(kernel_filename,
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;
}
if (kernel_size < 0) {

View file

@ -258,7 +258,8 @@ static void virtex_init(MachineState *machine)
/* Boots a kernel elf binary. */
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;
if (kernel_size < 0) {

View file

@ -101,7 +101,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
bios_size = load_elf(bios_filename, bios_translate_addr, &fwbase,
&ipl->bios_start_addr, NULL, NULL, 1,
EM_S390, 0);
EM_S390, 0, 0);
if (bios_size > 0) {
/* Adjust ELF start address to final location */
ipl->bios_start_addr += fwbase;
@ -124,7 +124,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
if (ipl->kernel) {
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) {
kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
}

View file

@ -449,7 +449,7 @@ static void sd_reset(DeviceState *dev)
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)

View file

@ -207,6 +207,21 @@ static void sdhci_reset(SDHCIState *s)
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_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);
dc->vmsd = &sdhci_vmstate;
dc->props = sdhci_pci_properties;
dc->reset = sdhci_poweron_reset;
}
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",
SDHC_REGISTERS_MAP_SIZE);
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)
@ -1345,6 +1357,7 @@ static void sdhci_sysbus_class_init(ObjectClass *klass, void *data)
dc->vmsd = &sdhci_vmstate;
dc->props = sdhci_sysbus_properties;
dc->realize = sdhci_sysbus_realize;
dc->reset = sdhci_poweron_reset;
}
static const TypeInfo sdhci_sysbus_info = {

View file

@ -194,7 +194,7 @@ static void leon3_generic_hw_init(MachineState *machine)
uint64_t entry;
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) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);

View file

@ -279,7 +279,7 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename,
bswap_needed = 0;
#endif
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)
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
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);
if (filename) {
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) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
}

View file

@ -187,7 +187,7 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename,
bswap_needed = 0;
#endif
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) {
*kernel_addr = 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);
if (filename) {
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) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
}

View file

@ -45,7 +45,7 @@ static void tricore_load_kernel(CPUTriCoreState *env)
kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL,
NULL, (uint64_t *)&entry, NULL,
NULL, 0,
EM_TRICORE, 1);
EM_TRICORE, 1, 0);
if (kernel_size <= 0) {
error_report("qemu: no kernel file '%s'",
tricoretb_binfo.kernel_filename);

View file

@ -94,10 +94,10 @@ static void xtensa_sim_init(MachineState *machine)
uint64_t elf_lowaddr;
#ifdef TARGET_WORDS_BIGENDIAN
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
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
if (success > 0) {
env->pc = elf_entry;

View file

@ -355,7 +355,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
uint64_t elf_entry;
uint64_t elf_lowaddr;
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) {
entry_point = elf_entry;
} else {

View file

@ -16,6 +16,13 @@
#include "qemu/notify.h"
#include "cpu.h"
typedef enum {
ARM_ENDIANNESS_UNKNOWN = 0,
ARM_ENDIANNESS_LE,
ARM_ENDIANNESS_BE8,
ARM_ENDIANNESS_BE32,
} arm_endianness;
/* armv7m.c */
DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
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
*/
bool secure_board_setup;
arm_endianness endianness;
};
/**

View file

@ -61,6 +61,7 @@ enum {
VIRT_PCIE_MMIO_HIGH,
VIRT_GPIO,
VIRT_SECURE_UART,
VIRT_SECURE_MEM,
};
typedef struct MemMapEntry {

View file

@ -263,7 +263,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
void *translate_opaque,
int must_swab, uint64_t *pentry,
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 elf_phdr *phdr = NULL, *ph;
@ -366,6 +366,26 @@ static int glue(load_elf, SZ)(const char *name, int fd,
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
* address, if the text segments paddr and vaddr differ
* we need to adjust the entry */

View file

@ -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);
int load_image_targphys(const char *filename, hwaddr,
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
* 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_ENDIAN -4
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),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
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 bswap_needed, hwaddr target_page_size);
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,
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,
size_t max_len, hwaddr addr,
const char *fw_file_name,
@ -82,9 +133,11 @@ void *rom_ptr(hwaddr addr);
void hmp_info_roms(Monitor *mon, const QDict *qdict);
#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) \
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_OPTION 0xc8000

View file

@ -435,22 +435,54 @@ void cpu_loop(CPUX86State *env)
#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)); \
if (!__r && (doswap)) { \
if (!__r && bswap_code(arm_sctlr_b(env))) { \
(x) = bswap32(x); \
} \
__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)); \
if (!__r && (doswap)) { \
if (!__r && bswap_code(arm_sctlr_b(env))) { \
(x) = bswap16(x); \
} \
__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
/* Commpage handling -- there is no commpage for AArch64 */
@ -610,11 +642,11 @@ static int do_strex(CPUARMState *env)
segv = get_user_u8(val, addr);
break;
case 1:
segv = get_user_u16(val, addr);
segv = get_user_data_u16(val, addr, env);
break;
case 2:
case 3:
segv = get_user_u32(val, addr);
segv = get_user_data_u32(val, addr, env);
break;
default:
abort();
@ -625,12 +657,16 @@ static int do_strex(CPUARMState *env)
}
if (size == 3) {
uint32_t valhi;
segv = get_user_u32(valhi, addr + 4);
segv = get_user_data_u32(valhi, addr + 4, env);
if (segv) {
env->exception.vaddress = addr + 4;
goto done;
}
val = deposit64(val, 32, 32, valhi);
if (arm_cpu_bswap_data(env)) {
val = deposit64((uint64_t)valhi, 32, 32, val);
} else {
val = deposit64(val, 32, 32, valhi);
}
}
if (val != env->exclusive_val) {
goto fail;
@ -642,11 +678,11 @@ static int do_strex(CPUARMState *env)
segv = put_user_u8(val, addr);
break;
case 1:
segv = put_user_u16(val, addr);
segv = put_user_data_u16(val, addr, env);
break;
case 2:
case 3:
segv = put_user_u32(val, addr);
segv = put_user_data_u32(val, addr, env);
break;
}
if (segv) {
@ -655,7 +691,7 @@ static int do_strex(CPUARMState *env)
}
if (size == 3) {
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) {
env->exception.vaddress = addr + 4;
goto done;
@ -692,7 +728,7 @@ void cpu_loop(CPUARMState *env)
/* we handle the FPU emulation here, as Linux */
/* we get the opcode */
/* 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);
if (rc == 0) { /* illegal instruction */
@ -762,25 +798,23 @@ void cpu_loop(CPUARMState *env)
if (trapnr == EXCP_BKPT) {
if (env->thumb) {
/* 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;
env->regs[15] += 2;
} else {
/* 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);
env->regs[15] += 4;
}
} else {
if (env->thumb) {
/* FIXME - what to do if get_user() fails? */
get_user_code_u16(insn, env->regs[15] - 2,
env->bswap_code);
get_user_code_u16(insn, env->regs[15] - 2, env);
n = insn & 0xff;
} else {
/* FIXME - what to do if get_user() fails? */
get_user_code_u32(insn, env->regs[15] - 4,
env->bswap_code);
get_user_code_u32(insn, env->regs[15] - 4, env);
n = insn & 0xffffff;
}
}
@ -4451,11 +4485,16 @@ int main(int argc, char **argv, char **envp)
for(i = 0; i < 16; i++) {
env->regs[i] = regs->uregs[i];
}
#ifdef TARGET_WORDS_BIGENDIAN
/* Enable BE8. */
if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
&& (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)
{

View file

@ -1536,82 +1536,84 @@ static void
setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
CPUARMState *env, abi_ulong mask)
{
__put_user(env->regs[0], &sc->arm_r0);
__put_user(env->regs[1], &sc->arm_r1);
__put_user(env->regs[2], &sc->arm_r2);
__put_user(env->regs[3], &sc->arm_r3);
__put_user(env->regs[4], &sc->arm_r4);
__put_user(env->regs[5], &sc->arm_r5);
__put_user(env->regs[6], &sc->arm_r6);
__put_user(env->regs[7], &sc->arm_r7);
__put_user(env->regs[8], &sc->arm_r8);
__put_user(env->regs[9], &sc->arm_r9);
__put_user(env->regs[10], &sc->arm_r10);
__put_user(env->regs[11], &sc->arm_fp);
__put_user(env->regs[12], &sc->arm_ip);
__put_user(env->regs[13], &sc->arm_sp);
__put_user(env->regs[14], &sc->arm_lr);
__put_user(env->regs[15], &sc->arm_pc);
__put_user(env->regs[0], &sc->arm_r0);
__put_user(env->regs[1], &sc->arm_r1);
__put_user(env->regs[2], &sc->arm_r2);
__put_user(env->regs[3], &sc->arm_r3);
__put_user(env->regs[4], &sc->arm_r4);
__put_user(env->regs[5], &sc->arm_r5);
__put_user(env->regs[6], &sc->arm_r6);
__put_user(env->regs[7], &sc->arm_r7);
__put_user(env->regs[8], &sc->arm_r8);
__put_user(env->regs[9], &sc->arm_r9);
__put_user(env->regs[10], &sc->arm_r10);
__put_user(env->regs[11], &sc->arm_fp);
__put_user(env->regs[12], &sc->arm_ip);
__put_user(env->regs[13], &sc->arm_sp);
__put_user(env->regs[14], &sc->arm_lr);
__put_user(env->regs[15], &sc->arm_pc);
#ifdef TARGET_CONFIG_CPU_32
__put_user(cpsr_read(env), &sc->arm_cpsr);
__put_user(cpsr_read(env), &sc->arm_cpsr);
#endif
__put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
__put_user(/* current->thread.error_code */ 0, &sc->error_code);
__put_user(/* current->thread.address */ 0, &sc->fault_address);
__put_user(mask, &sc->oldmask);
__put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
__put_user(/* current->thread.error_code */ 0, &sc->error_code);
__put_user(/* current->thread.address */ 0, &sc->fault_address);
__put_user(mask, &sc->oldmask);
}
static inline abi_ulong
get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
{
unsigned long sp = regs->regs[13];
unsigned long sp = regs->regs[13];
/*
* This is the X/Open sanctioned signal stack switching.
*/
if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
/*
* ATPCS B01 mandates 8-byte alignment
*/
return (sp - framesize) & ~7;
/*
* This is the X/Open sanctioned signal stack switching.
*/
if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
}
/*
* ATPCS B01 mandates 8-byte alignment
*/
return (sp - framesize) & ~7;
}
static void
setup_return(CPUARMState *env, struct target_sigaction *ka,
abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
{
abi_ulong handler = ka->_sa_handler;
abi_ulong retcode;
int thumb = handler & 1;
uint32_t cpsr = cpsr_read(env);
abi_ulong handler = ka->_sa_handler;
abi_ulong retcode;
int thumb = handler & 1;
uint32_t cpsr = cpsr_read(env);
cpsr &= ~CPSR_IT;
if (thumb) {
cpsr |= CPSR_T;
} else {
cpsr &= ~CPSR_T;
}
cpsr &= ~CPSR_IT;
if (thumb) {
cpsr |= CPSR_T;
} else {
cpsr &= ~CPSR_T;
}
if (ka->sa_flags & TARGET_SA_RESTORER) {
retcode = ka->sa_restorer;
} else {
unsigned int idx = thumb;
if (ka->sa_flags & TARGET_SA_RESTORER) {
retcode = ka->sa_restorer;
} else {
unsigned int idx = thumb;
if (ka->sa_flags & TARGET_SA_SIGINFO)
idx += 2;
if (ka->sa_flags & TARGET_SA_SIGINFO) {
idx += 2;
}
__put_user(retcodes[idx], rc);
retcode = rc_addr + thumb;
}
retcode = rc_addr + thumb;
}
env->regs[0] = usig;
env->regs[13] = frame_addr;
env->regs[14] = retcode;
env->regs[15] = handler & (thumb ? ~1 : ~3);
cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
env->regs[0] = usig;
env->regs[13] = frame_addr;
env->regs[14] = retcode;
env->regs[15] = handler & (thumb ? ~1 : ~3);
cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
}
static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)

View file

@ -25,10 +25,10 @@
/* Load an instruction and return it in the standard little-endian order */
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);
if (do_swap) {
if (bswap_code(sctlr_b)) {
return bswap32(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 */
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);
if (do_swap) {
if (bswap_code(sctlr_b)) {
return bswap16(insn);
}
return insn;

View file

@ -369,26 +369,13 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
#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);
CPUARMState *env = &cpu->env;
int cur_el;
cpu_synchronize_state(cs);
/* 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;
return arm_cpu_data_is_big_endian(env);
}
#endif
@ -427,7 +414,7 @@ static void arm_disas_set_info(CPUState *cpu, disassemble_info *info)
} else {
info->print_insn = print_insn_arm;
}
if (env->bswap_code) {
if (bswap_code(arm_sctlr_b(env))) {
#ifdef TARGET_WORDS_BIGENDIAN
info->endian = BFD_ENDIAN_LITTLE;
#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->asidx_from_attrs = arm_asidx_from_attrs;
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_elf32_note = arm_cpu_write_elf32_note;
#endif

View file

@ -478,9 +478,6 @@ typedef struct CPUARMState {
uint32_t cregs[16];
} iwmmxt;
/* For mixed endian mode. */
bool bswap_code;
#if defined(CONFIG_USER_ONLY)
/* For usermode syscall translation. */
int eabi;
@ -1898,6 +1895,53 @@ static inline bool arm_singlestep_active(CPUARMState *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"
/* 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_CONDEXEC_SHIFT 8
#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
#define ARM_TBFLAG_SCTLR_B_SHIFT 16
#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
* 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_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 */
@ -1965,12 +2011,34 @@ static inline bool arm_singlestep_active(CPUARMState *env)
(((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT)
#define ARM_TBFLAG_CONDEXEC(F) \
(((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
#define ARM_TBFLAG_BSWAP_CODE(F) \
(((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
#define ARM_TBFLAG_SCTLR_B(F) \
(((F) & ARM_TBFLAG_SCTLR_B_MASK) >> ARM_TBFLAG_SCTLR_B_SHIFT)
#define ARM_TBFLAG_XSCALE_CPAR(F) \
(((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
#define ARM_TBFLAG_NS(F) \
(((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
* be taken, or 0 if FP is enabled.
@ -2037,6 +2105,17 @@ static inline int fp_exception_el(CPUARMState *env)
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,
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_stride << ARM_TBFLAG_VECSTRIDE_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))) {
*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;
*cs_base = 0;

View file

@ -5490,9 +5490,16 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
env->daif |= val & CPSR_AIF & mask;
if (write_type != CPSRWriteRaw &&
(env->uncached_cpsr & CPSR_M) != CPSR_USER &&
((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
* v7, and has defined behaviour in v8:
* + leave CPSR.M untouched
@ -5841,7 +5848,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
case EXCP_BKPT:
if (semihosting_enabled()) {
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) {
env->regs[15] += 2;
qemu_log_mask(CPU_LOG_INT,
@ -6234,6 +6241,11 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
env->condexec_bits = 0;
/* Switch to the new mode, and to the correct instruction set. */
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;
/* 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 */
@ -6379,13 +6391,13 @@ static inline bool check_for_semihosting(CPUState *cs)
case EXCP_SWI:
/* Check for semihosting interrupt. */
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;
if (imm == 0xab) {
break;
}
} 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;
if (imm == 0x123456) {
break;
@ -6395,7 +6407,7 @@ static inline bool check_for_semihosting(CPUState *cs)
case EXCP_BKPT:
/* See if this is a semihosting syscall. */
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;
if (imm == 0xab) {
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;
}
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 */
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) {
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,
@ -6860,7 +6882,11 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
if (fi->s1ptw) {
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,

View file

@ -48,6 +48,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
DEF_HELPER_2(exception_internal, void, env, 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(wfe, void, env)
DEF_HELPER_1(yield, void, env)

View file

@ -296,6 +296,11 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
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.
* The function returns the target EL (1-3) if the instruction is to be trapped;
* otherwise it returns 0 indicating it is not trapped.

View file

@ -723,7 +723,7 @@ static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 source,
TCGv_i64 tcg_addr, int size, int memidx)
{
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,
@ -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,
int size, bool is_signed, bool extend, int memidx)
{
TCGMemOp memop = MO_TE + size;
TCGMemOp memop = s->be_data + size;
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();
tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
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 {
bool be = s->be_data == MO_BE;
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_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);
}
@ -793,17 +798,21 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
TCGv_i64 tmphi;
if (size < 4) {
TCGMemOp memop = MO_TE + size;
TCGMemOp memop = s->be_data + size;
tmphi = tcg_const_i64(0);
tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
} else {
bool be = s->be_data == MO_BE;
TCGv_i64 tcg_hiaddr;
tmphi = 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_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);
}
@ -942,7 +951,7 @@ static void clear_vec_high(DisasContext *s, int rd)
static void do_vec_st(DisasContext *s, int srcidx, int element,
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();
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,
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();
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 tmp = tcg_temp_new_i64();
TCGMemOp memop = MO_TE + size;
TCGMemOp memop = s->be_data + size;
g_assert(size <= 3);
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);
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_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();
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_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 */
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) {
TCGv_i64 addrhi = tcg_temp_new_i64();
tcg_gen_addi_i64(addrhi, addr, 1 << size);
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);
}
@ -2602,7 +2613,7 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
TCGv_i64 tcg_tmp = tcg_temp_new_i64();
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) {
case 0:
mulconst = 0x0101010101010101ULL;
@ -2632,9 +2643,9 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
} else {
/* Load/store one element per register */
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 {
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);
@ -10966,7 +10977,7 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
{
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->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) &&
!arm_el_is_aa64(env, 3);
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_cond = 0;
dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
@ -11217,7 +11229,7 @@ done_generating:
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(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");
}
#endif

View file

@ -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
* AArch32", where a vaddr is always 32 bits (and is zero
* 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
#define DO_GEN_LD(SUFF, OPC) \
static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
#define DO_GEN_LD(SUFF, OPC, BE32_XOR) \
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) \
static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
#define DO_GEN_ST(SUFF, OPC, BE32_XOR) \
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
#define DO_GEN_LD(SUFF, OPC) \
static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
#define DO_GEN_LD(SUFF, OPC, BE32_XOR) \
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(); \
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); \
}
#define DO_GEN_ST(SUFF, OPC) \
static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
#define DO_GEN_ST(SUFF, OPC, BE32_XOR) \
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(); \
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); \
}
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();
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);
}
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();
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);
}
#endif
DO_GEN_LD(8s, MO_SB)
DO_GEN_LD(8u, MO_UB)
DO_GEN_LD(16s, MO_TESW)
DO_GEN_LD(16u, MO_TEUW)
DO_GEN_LD(32u, MO_TEUL)
DO_GEN_LD(8s, MO_SB, 3)
DO_GEN_LD(8u, MO_UB, 3)
DO_GEN_LD(16s, MO_SW, 2)
DO_GEN_LD(16u, MO_UW, 2)
DO_GEN_LD(32u, MO_UL, 0)
/* 'a' variants include an alignment check */
DO_GEN_LD(16ua, MO_TEUW | MO_ALIGN)
DO_GEN_LD(32ua, MO_TEUL | MO_ALIGN)
DO_GEN_ST(8, MO_UB)
DO_GEN_ST(16, MO_TEUW)
DO_GEN_ST(32, MO_TEUL)
DO_GEN_LD(16ua, MO_UW | MO_ALIGN, 2)
DO_GEN_LD(32ua, MO_UL | MO_ALIGN, 0)
DO_GEN_ST(8, MO_UB, 3)
DO_GEN_ST(16, MO_UW, 2)
DO_GEN_ST(32, MO_UL, 0)
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)
{
if (dp) {
gen_aa32_ld64(cpu_F0d, addr, get_mem_index(s));
gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
} 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)
{
if (dp) {
gen_aa32_st64(cpu_F0d, addr, get_mem_index(s));
gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
} 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 >> 28) == 0xf) { /* WLDRW wCx */
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);
} else {
i = 1;
if (insn & (1 << 8)) {
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;
} else { /* WLDRW wRd */
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 {
tmp = tcg_temp_new_i32();
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 */
gen_aa32_ld8u(tmp, addr, get_mem_index(s));
gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
}
}
if (i) {
@ -1661,24 +1733,24 @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
} else {
if ((insn >> 28) == 0xf) { /* WSTRW wCx */
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 {
gen_op_iwmmxt_movq_M0_wRn(wrd);
tmp = tcg_temp_new_i32();
if (insn & (1 << 8)) {
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 */
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 {
if (insn & (1 << 22)) { /* WSTRH */
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 */
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();
switch (size) {
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);
break;
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);
break;
case 2:
gen_aa32_ld32u(tmp, addr, get_mem_index(s));
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
break;
default: /* Avoid compiler warnings. */
abort();
@ -4449,11 +4521,11 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
if (size == 3) {
tmp64 = tcg_temp_new_i64();
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);
} else {
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_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 (load) {
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);
} else {
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_gen_addi_i32(addr, addr, stride);
} else if (size == 1) {
if (load) {
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);
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_shli_i32(tmp2, tmp2, 16);
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);
tmp2 = tcg_temp_new_i32();
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_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_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);
for (n = 0; n < 4; n++) {
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);
if (n == 0) {
tmp2 = tmp;
@ -4518,7 +4590,7 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
} else {
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_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();
switch (size) {
case 0:
gen_aa32_ld8u(tmp, addr, get_mem_index(s));
gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
break;
case 1:
gen_aa32_ld16u(tmp, addr, get_mem_index(s));
gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
break;
case 2:
gen_aa32_ld32u(tmp, addr, get_mem_index(s));
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
break;
default: /* Avoid compiler warnings. */
abort();
@ -4666,13 +4738,13 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
tcg_gen_shri_i32(tmp, tmp, shift);
switch (size) {
case 0:
gen_aa32_st8(tmp, addr, get_mem_index(s));
gen_aa32_st8(s, tmp, addr, get_mem_index(s));
break;
case 1:
gen_aa32_st16(tmp, addr, get_mem_index(s));
gen_aa32_st16(s, tmp, addr, get_mem_index(s));
break;
case 2:
gen_aa32_st32(tmp, addr, get_mem_index(s));
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
break;
}
tcg_temp_free_i32(tmp);
@ -7435,14 +7507,14 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
switch (size) {
case 0:
gen_aa32_ld8u(tmp, addr, get_mem_index(s));
gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
break;
case 1:
gen_aa32_ld16ua(tmp, addr, get_mem_index(s));
gen_aa32_ld16ua(s, tmp, addr, get_mem_index(s));
break;
case 2:
case 3:
gen_aa32_ld32ua(tmp, addr, get_mem_index(s));
gen_aa32_ld32ua(s, tmp, addr, get_mem_index(s));
break;
default:
abort();
@ -7453,7 +7525,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
TCGv_i32 tmp3 = tcg_temp_new_i32();
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_gen_concat_i32_i64(cpu_exclusive_val, tmp, 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();
switch (size) {
case 0:
gen_aa32_ld8u(tmp, addr, get_mem_index(s));
gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
break;
case 1:
gen_aa32_ld16u(tmp, addr, get_mem_index(s));
gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
break;
case 2:
case 3:
gen_aa32_ld32u(tmp, addr, get_mem_index(s));
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
break;
default:
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 tmp3 = tcg_temp_new_i32();
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_gen_concat_i32_i64(val64, tmp, 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);
switch (size) {
case 0:
gen_aa32_st8(tmp, addr, get_mem_index(s));
gen_aa32_st8(s, tmp, addr, get_mem_index(s));
break;
case 1:
gen_aa32_st16(tmp, addr, get_mem_index(s));
gen_aa32_st16(s, tmp, addr, get_mem_index(s));
break;
case 2:
case 3:
gen_aa32_st32(tmp, addr, get_mem_index(s));
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
break;
default:
abort();
@ -7553,7 +7625,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
if (size == 3) {
tcg_gen_addi_i32(addr, addr, 4);
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_gen_movi_i32(cpu_R[rd], 0);
@ -7583,6 +7655,7 @@ static void gen_srs(DisasContext *s,
/* SRS is:
* - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
* and specified mode is monitor mode
* - UNDEFINED in Hyp mode
* - UNPREDICTABLE in User or System mode
* - UNPREDICTABLE if the specified mode is:
@ -7592,7 +7665,7 @@ static void gen_srs(DisasContext *s,
* -- Monitor, if we are Non-secure
* 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);
return;
}
@ -7659,11 +7732,11 @@ static void gen_srs(DisasContext *s,
}
tcg_gen_addi_i32(addr, addr, offset);
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);
tmp = load_cpu_field(spsr);
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);
if (writeback) {
switch (amode) {
@ -7770,10 +7843,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
if ((insn & 0x0ffffdff) == 0x01010000) {
ARCH(6);
/* setend */
if (((insn >> 9) & 1) != s->bswap_code) {
/* Dynamic endianness switching not implemented. */
qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
goto illegal_op;
if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
gen_helper_setend(cpu_env);
s->is_jmp = DISAS_UPDATE;
}
return;
} 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);
/* Load PC into tmp and CPSR into tmp2. */
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);
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)) {
/* Base writeback. */
switch (i) {
@ -8441,13 +8513,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
tmp = tcg_temp_new_i32();
switch (op1) {
case 0: /* lda */
gen_aa32_ld32u(tmp, addr, get_mem_index(s));
gen_aa32_ld32u(s, tmp, addr,
get_mem_index(s));
break;
case 2: /* ldab */
gen_aa32_ld8u(tmp, addr, get_mem_index(s));
gen_aa32_ld8u(s, tmp, addr,
get_mem_index(s));
break;
case 3: /* ldah */
gen_aa32_ld16u(tmp, addr, get_mem_index(s));
gen_aa32_ld16u(s, tmp, addr,
get_mem_index(s));
break;
default:
abort();
@ -8458,13 +8533,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
tmp = load_reg(s, rm);
switch (op1) {
case 0: /* stl */
gen_aa32_st32(tmp, addr, get_mem_index(s));
gen_aa32_st32(s, tmp, addr,
get_mem_index(s));
break;
case 2: /* stlb */
gen_aa32_st8(tmp, addr, get_mem_index(s));
gen_aa32_st8(s, tmp, addr,
get_mem_index(s));
break;
case 3: /* stlh */
gen_aa32_st16(tmp, addr, get_mem_index(s));
gen_aa32_st16(s, tmp, addr,
get_mem_index(s));
break;
default:
abort();
@ -8519,11 +8597,11 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
tmp = load_reg(s, rm);
tmp2 = tcg_temp_new_i32();
if (insn & (1 << 22)) {
gen_aa32_ld8u(tmp2, addr, get_mem_index(s));
gen_aa32_st8(tmp, addr, get_mem_index(s));
gen_aa32_ld8u(s, tmp2, addr, get_mem_index(s));
gen_aa32_st8(s, tmp, addr, get_mem_index(s));
} else {
gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
gen_aa32_st32(tmp, addr, get_mem_index(s));
gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
}
tcg_temp_free_i32(tmp);
tcg_temp_free_i32(addr);
@ -8558,20 +8636,20 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
if (!load) {
/* store */
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_gen_addi_i32(addr, addr, 4);
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);
} else {
/* load */
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);
tcg_gen_addi_i32(addr, addr, 4);
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++;
}
address_offset = -4;
@ -8580,20 +8658,20 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
tmp = tcg_temp_new_i32();
switch (sh) {
case 1:
gen_aa32_ld16u(tmp, addr, get_mem_index(s));
gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
break;
case 2:
gen_aa32_ld8s(tmp, addr, get_mem_index(s));
gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
break;
default:
case 3:
gen_aa32_ld16s(tmp, addr, get_mem_index(s));
gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
break;
}
} else {
/* store */
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);
}
/* Perform base writeback before the loaded value to
@ -8946,17 +9024,17 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
/* load */
tmp = tcg_temp_new_i32();
if (insn & (1 << 22)) {
gen_aa32_ld8u(tmp, tmp2, i);
gen_aa32_ld8u(s, tmp, tmp2, i);
} else {
gen_aa32_ld32u(tmp, tmp2, i);
gen_aa32_ld32u(s, tmp, tmp2, i);
}
} else {
/* store */
tmp = load_reg(s, rd);
if (insn & (1 << 22)) {
gen_aa32_st8(tmp, tmp2, i);
gen_aa32_st8(s, tmp, tmp2, i);
} else {
gen_aa32_st32(tmp, tmp2, i);
gen_aa32_st32(s, tmp, tmp2, i);
}
tcg_temp_free_i32(tmp);
}
@ -9029,7 +9107,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
if (is_load) {
/* load */
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) {
tmp2 = tcg_const_i32(i);
gen_helper_set_user_reg(cpu_env, tmp2, tmp);
@ -9056,7 +9134,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
} else {
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);
}
j++;
@ -9286,7 +9364,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
/* 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;
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)) {
/* ldrd */
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);
tcg_gen_addi_i32(addr, addr, 4);
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);
} else {
/* strd */
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_gen_addi_i32(addr, addr, 4);
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);
}
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_temp_free_i32(tmp);
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 */
tcg_temp_free_i32(tmp);
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_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();
switch (op) {
case 0: /* ldab */
gen_aa32_ld8u(tmp, addr, get_mem_index(s));
gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
break;
case 1: /* ldah */
gen_aa32_ld16u(tmp, addr, get_mem_index(s));
gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
break;
case 2: /* lda */
gen_aa32_ld32u(tmp, addr, get_mem_index(s));
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
break;
default:
abort();
@ -9431,13 +9509,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
tmp = load_reg(s, rs);
switch (op) {
case 0: /* stlb */
gen_aa32_st8(tmp, addr, get_mem_index(s));
gen_aa32_st8(s, tmp, addr, get_mem_index(s));
break;
case 1: /* stlh */
gen_aa32_st16(tmp, addr, get_mem_index(s));
gen_aa32_st16(s, tmp, addr, get_mem_index(s));
break;
case 2: /* stl */
gen_aa32_st32(tmp, addr, get_mem_index(s));
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
break;
default:
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);
/* Load PC into tmp and CPSR into tmp2. */
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);
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)) {
/* Base writeback. */
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)) {
/* Load. */
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) {
gen_bx(s, tmp);
} else if (i == rn) {
@ -9519,7 +9597,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
} else {
/* Store. */
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_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();
switch (op) {
case 0:
gen_aa32_ld8u(tmp, addr, memidx);
gen_aa32_ld8u(s, tmp, addr, memidx);
break;
case 4:
gen_aa32_ld8s(tmp, addr, memidx);
gen_aa32_ld8s(s, tmp, addr, memidx);
break;
case 1:
gen_aa32_ld16u(tmp, addr, memidx);
gen_aa32_ld16u(s, tmp, addr, memidx);
break;
case 5:
gen_aa32_ld16s(tmp, addr, memidx);
gen_aa32_ld16s(s, tmp, addr, memidx);
break;
case 2:
gen_aa32_ld32u(tmp, addr, memidx);
gen_aa32_ld32u(s, tmp, addr, memidx);
break;
default:
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);
switch (op) {
case 0:
gen_aa32_st8(tmp, addr, memidx);
gen_aa32_st8(s, tmp, addr, memidx);
break;
case 1:
gen_aa32_st16(tmp, addr, memidx);
gen_aa32_st16(s, tmp, addr, memidx);
break;
case 2:
gen_aa32_st32(tmp, addr, memidx);
gen_aa32_st32(s, tmp, addr, memidx);
break;
default:
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;
switch (insn >> 12) {
@ -10621,7 +10699,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
addr = tcg_temp_new_i32();
tcg_gen_movi_i32(addr, val);
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);
store_reg(s, rd, tmp);
break;
@ -10824,28 +10902,28 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
switch (op) {
case 0: /* str */
gen_aa32_st32(tmp, addr, get_mem_index(s));
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
break;
case 1: /* strh */
gen_aa32_st16(tmp, addr, get_mem_index(s));
gen_aa32_st16(s, tmp, addr, get_mem_index(s));
break;
case 2: /* strb */
gen_aa32_st8(tmp, addr, get_mem_index(s));
gen_aa32_st8(s, tmp, addr, get_mem_index(s));
break;
case 3: /* ldrsb */
gen_aa32_ld8s(tmp, addr, get_mem_index(s));
gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
break;
case 4: /* ldr */
gen_aa32_ld32u(tmp, addr, get_mem_index(s));
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
break;
case 5: /* ldrh */
gen_aa32_ld16u(tmp, addr, get_mem_index(s));
gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
break;
case 6: /* ldrb */
gen_aa32_ld8u(tmp, addr, get_mem_index(s));
gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
break;
case 7: /* ldrsh */
gen_aa32_ld16s(tmp, addr, get_mem_index(s));
gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
break;
}
if (op >= 3) { /* load */
@ -10867,12 +10945,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* load */
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);
} else {
/* store */
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(addr);
@ -10889,12 +10967,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* load */
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);
} else {
/* store */
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(addr);
@ -10911,12 +10989,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* load */
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);
} else {
/* store */
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(addr);
@ -10932,12 +11010,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* load */
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);
} else {
/* store */
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(addr);
@ -11005,12 +11083,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* pop */
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);
} else {
/* push */
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);
}
/* advance to the next address. */
@ -11022,13 +11100,13 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* pop pc */
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
has completed */
} else {
/* push lr */
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_gen_addi_i32(addr, addr, 4);
@ -11099,10 +11177,9 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
case 2:
/* setend */
ARCH(6);
if (((insn >> 3) & 1) != s->bswap_code) {
/* Dynamic endianness switching not implemented. */
qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
goto illegal_op;
if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
gen_helper_setend(cpu_env);
s->is_jmp = DISAS_UPDATE;
}
break;
case 3:
@ -11158,7 +11235,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* load */
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) {
loaded_var = tmp;
} else {
@ -11167,7 +11244,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
} else {
/* store */
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);
}
/* advance to the next address */
@ -11253,7 +11330,7 @@ static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
}
/* 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) {
/* 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) &&
!arm_el_is_aa64(env, 3);
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_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
@ -11487,7 +11565,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
}
}
} 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;
disas_arm_insn(dc, insn);
}
@ -11644,7 +11722,7 @@ done_generating:
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(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");
}
#endif

View file

@ -16,7 +16,8 @@ typedef struct DisasContext {
struct TranslationBlock *tb;
int singlestep_enabled;
int thumb;
int bswap_code;
int sctlr_b;
TCGMemOp be_data;
#if !defined(CONFIG_USER_ONLY)
int user;
#endif