Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180116' into staging

target-arm queue:
 * SDHCI: cleanups and minor bug fixes
 * target/arm: minor refactor preparatory to fp16 support
 * omap_ssd, ssi-sd, pl181, milkymist-memcard: reset the SD
   card on controller reset (fixes migration failures)
 * target/arm: Handle page table walk load failures correctly
 * hw/arm/virt: Add virt-2.12 machine type
 * get_phys_addr_pmsav7: Support AP=0b111 for v7M
 * hw/intc/armv7m: Support byte and halfword accesses to CFSR

# gpg: Signature made Tue 16 Jan 2018 13:33:31 GMT
# gpg:                using RSA key 0x3C2525ED14360CDE
# 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>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20180116: (24 commits)
  sdhci: add a 'dma' property to the sysbus devices
  sdhci: fix the PCI device, using the PCI address space for DMA
  sdhci: Implement write method of ACMD12ERRSTS register
  sdhci: fix CAPAB/MAXCURR registers, both are 64bit and read-only
  sdhci: rename the SDHC_CAPAB register
  sdhci: move MASK_TRNMOD with other SDHC_TRN* defines in "sd-internal.h"
  sdhci: convert the DPRINT() calls into trace events
  sdhci: use qemu_log_mask(UNIMP) instead of fprintf()
  sdhci: refactor common sysbus/pci unrealize() into sdhci_common_unrealize()
  sdhci: refactor common sysbus/pci realize() into sdhci_common_realize()
  sdhci: refactor common sysbus/pci class_init() into sdhci_common_class_init()
  sdhci: use DEFINE_SDHCI_COMMON_PROPERTIES() for common sysbus/pci properties
  sdhci: remove dead code
  sdhci: clean up includes
  target/arm: Add fp16 support to vfp_expand_imm
  target/arm: Split out vfp_expand_imm
  hw/sd/omap_mmc: Reset SD card on controller reset
  hw/sd/ssi-sd: Reset SD card on controller reset
  hw/sd/milkymist-memcard: Reset SD card on controller reset
  hw/sd/pl181: Reset SD card on controller reset
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2018-01-16 14:18:20 +00:00
14 changed files with 363 additions and 168 deletions
+18 -3
View File
@@ -1618,7 +1618,7 @@ static void machvirt_machine_init(void)
}
type_init(machvirt_machine_init);
static void virt_2_11_instance_init(Object *obj)
static void virt_2_12_instance_init(Object *obj)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
@@ -1678,10 +1678,25 @@ static void virt_2_11_instance_init(Object *obj)
vms->irqmap = a15irqmap;
}
static void virt_machine_2_11_options(MachineClass *mc)
static void virt_machine_2_12_options(MachineClass *mc)
{
}
DEFINE_VIRT_MACHINE_AS_LATEST(2, 11)
DEFINE_VIRT_MACHINE_AS_LATEST(2, 12)
#define VIRT_COMPAT_2_11 \
HW_COMPAT_2_11
static void virt_2_11_instance_init(Object *obj)
{
virt_2_12_instance_init(obj);
}
static void virt_machine_2_11_options(MachineClass *mc)
{
virt_machine_2_12_options(mc);
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_11);
}
DEFINE_VIRT_MACHINE(2, 11)
#define VIRT_COMPAT_2_10 \
HW_COMPAT_2_10
+22 -16
View File
@@ -896,13 +896,6 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
val |= (1 << 8);
}
return val;
case 0xd28: /* Configurable Fault Status. */
/* The BFSR bits [15:8] are shared between security states
* and we store them in the NS copy
*/
val = cpu->env.v7m.cfsr[attrs.secure];
val |= cpu->env.v7m.cfsr[M_REG_NS] & R_V7M_CFSR_BFSR_MASK;
return val;
case 0xd2c: /* Hard Fault Status. */
return cpu->env.v7m.hfsr;
case 0xd30: /* Debug Fault Status. */
@@ -1280,15 +1273,6 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
s->vectors[ARMV7M_EXCP_DEBUG].active = (value & (1 << 8)) != 0;
nvic_irq_update(s);
break;
case 0xd28: /* Configurable Fault Status. */
cpu->env.v7m.cfsr[attrs.secure] &= ~value; /* W1C */
if (attrs.secure) {
/* The BFSR bits [15:8] are shared between security states
* and we store them in the NS copy.
*/
cpu->env.v7m.cfsr[M_REG_NS] &= ~(value & R_V7M_CFSR_BFSR_MASK);
}
break;
case 0xd2c: /* Hard Fault Status. */
cpu->env.v7m.hfsr &= ~value; /* W1C */
break;
@@ -1667,6 +1651,14 @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
val = deposit32(val, i * 8, 8, get_prio(s, hdlidx, sbank));
}
break;
case 0xd28 ... 0xd2b: /* Configurable Fault Status (CFSR) */
/* The BFSR bits [15:8] are shared between security states
* and we store them in the NS copy
*/
val = s->cpu->env.v7m.cfsr[attrs.secure];
val |= s->cpu->env.v7m.cfsr[M_REG_NS] & R_V7M_CFSR_BFSR_MASK;
val = extract32(val, (offset - 0xd28) * 8, size * 8);
break;
case 0xfe0 ... 0xfff: /* ID. */
if (offset & 3) {
val = 0;
@@ -1765,6 +1757,20 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
}
nvic_irq_update(s);
return MEMTX_OK;
case 0xd28 ... 0xd2b: /* Configurable Fault Status (CFSR) */
/* All bits are W1C, so construct 32 bit value with 0s in
* the parts not written by the access size
*/
value <<= ((offset - 0xd28) * 8);
s->cpu->env.v7m.cfsr[attrs.secure] &= ~value;
if (attrs.secure) {
/* The BFSR bits [15:8] are shared between security states
* and we store them in the NS copy.
*/
s->cpu->env.v7m.cfsr[M_REG_NS] &= ~(value & R_V7M_CFSR_BFSR_MASK);
}
return MEMTX_OK;
}
if (size == 4) {
nvic_writel(s, offset, value, attrs);
+4
View File
@@ -248,6 +248,10 @@ static void milkymist_memcard_reset(DeviceState *d)
for (i = 0; i < R_MAX; i++) {
s->regs[i] = 0;
}
/* Since we're still using the legacy SD API the card is not plugged
* into any bus, and we must reset it manually.
*/
device_reset(DEVICE(s->card));
}
static int milkymist_memcard_init(SysBusDevice *dev)
+10 -4
View File
@@ -305,6 +305,12 @@ void omap_mmc_reset(struct omap_mmc_s *host)
host->cdet_enable = 0;
qemu_set_irq(host->coverswitch, host->cdet_state);
host->clkdiv = 0;
/* Since we're still using the legacy SD API the card is not plugged
* into any bus, and we must reset it manually. When omap_mmc is
* QOMified this must move into the QOM reset function.
*/
device_reset(DEVICE(host->card));
}
static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
@@ -587,8 +593,6 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base,
s->lines = 1; /* TODO: needs to be settable per-board */
s->rev = 1;
omap_mmc_reset(s);
memory_region_init_io(&s->iomem, NULL, &omap_mmc_ops, s, "omap.mmc", 0x800);
memory_region_add_subregion(sysmem, base, &s->iomem);
@@ -598,6 +602,8 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base,
exit(1);
}
omap_mmc_reset(s);
return s;
}
@@ -613,8 +619,6 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
s->lines = 4;
s->rev = 2;
omap_mmc_reset(s);
memory_region_init_io(&s->iomem, NULL, &omap_mmc_ops, s, "omap.mmc",
omap_l4_region_size(ta, 0));
omap_l4_attach(ta, 0, &s->iomem);
@@ -628,6 +632,8 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
s->cdet = qemu_allocate_irq(omap_mmc_cover_cb, s, 0);
sd_set_cb(s->card, NULL, s->cdet);
omap_mmc_reset(s);
return s;
}
+4
View File
@@ -480,6 +480,10 @@ static void pl181_reset(DeviceState *d)
/* We can assume our GPIO outputs have been wired up now */
sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]);
/* Since we're still using the legacy SD API the card is not plugged
* into any bus, and we must reset it manually.
*/
device_reset(DEVICE(s->card));
}
static void pl181_init(Object *obj)
+2 -5
View File
@@ -24,8 +24,6 @@
#ifndef SDHCI_INTERNAL_H
#define SDHCI_INTERNAL_H
#include "hw/sd/sdhci.h"
/* R/W SDMA System Address register 0x0 */
#define SDHC_SYSAD 0x00
@@ -45,6 +43,7 @@
#define SDHC_TRNS_ACMD12 0x0004
#define SDHC_TRNS_READ 0x0010
#define SDHC_TRNS_MULTI 0x0020
#define SDHC_TRNMOD_MASK 0x0037
/* R/W Command Register 0x0 */
#define SDHC_CMDREG 0x0E
@@ -175,7 +174,7 @@
#define SDHC_ACMD12ERRSTS 0x3C
/* HWInit Capabilities Register 0x05E80080 */
#define SDHC_CAPAREG 0x40
#define SDHC_CAPAB 0x40
#define SDHC_CAN_DO_DMA 0x00400000
#define SDHC_CAN_DO_ADMA2 0x00080000
#define SDHC_CAN_DO_ADMA1 0x00100000
@@ -227,6 +226,4 @@ enum {
sdhc_gap_write = 2 /* SDHC stopped at block gap during write operation */
};
extern const VMStateDescription sdhci_vmstate;
#endif
+161 -105
View File
File diff suppressed because it is too large Load Diff
+23 -2
View File
@@ -50,6 +50,9 @@ typedef struct {
SDState *sd;
} ssi_sd_state;
#define TYPE_SSI_SD "ssi-sd"
#define SSI_SD(obj) OBJECT_CHECK(ssi_sd_state, (obj), TYPE_SSI_SD)
/* State word bits. */
#define SSI_SDR_LOCKED 0x0001
#define SSI_SDR_WP_ERASE 0x0002
@@ -241,7 +244,6 @@ static void ssi_sd_realize(SSISlave *d, Error **errp)
ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d);
DriveInfo *dinfo;
s->mode = SSI_SD_CMD;
/* FIXME use a qdev drive property instead of drive_get_next() */
dinfo = drive_get_next(IF_SD);
s->sd = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, true);
@@ -251,6 +253,24 @@ static void ssi_sd_realize(SSISlave *d, Error **errp)
}
}
static void ssi_sd_reset(DeviceState *dev)
{
ssi_sd_state *s = SSI_SD(dev);
s->mode = SSI_SD_CMD;
s->cmd = 0;
memset(s->cmdarg, 0, sizeof(s->cmdarg));
memset(s->response, 0, sizeof(s->response));
s->arglen = 0;
s->response_pos = 0;
s->stopping = 0;
/* Since we're still using the legacy SD API the card is not plugged
* into any bus, and we must reset it manually.
*/
device_reset(DEVICE(s->sd));
}
static void ssi_sd_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -260,10 +280,11 @@ static void ssi_sd_class_init(ObjectClass *klass, void *data)
k->transfer = ssi_sd_transfer;
k->cs_polarity = SSI_CS_LOW;
dc->vmsd = &vmstate_ssi_sd;
dc->reset = ssi_sd_reset;
}
static const TypeInfo ssi_sd_info = {
.name = "ssi-sd",
.name = TYPE_SSI_SD,
.parent = TYPE_SSI_SLAVE,
.instance_size = sizeof(ssi_sd_state),
.class_init = ssi_sd_class_init,
+14
View File
@@ -1,5 +1,19 @@
# See docs/devel/tracing.txt for syntax documentation.
# hw/sd/sdhci.c
sdhci_set_inserted(const char *level) "card state changed: %s"
sdhci_send_command(uint8_t cmd, uint32_t arg) "CMD%02u ARG[0x%08x]"
sdhci_error(const char *msg) "%s"
sdhci_response4(uint32_t r0) "RSPREG[31..0]=0x%08x"
sdhci_response16(uint32_t r3, uint32_t r2, uint32_t r1, uint32_t r0) "RSPREG[127..96]=0x%08x, RSPREG[95..64]=0x%08x, RSPREG[63..32]=0x%08x, RSPREG[31..0]=0x%08x"
sdhci_end_transfer(uint8_t cmd, uint32_t arg) "Automatically issue CMD%02u 0x%08x"
sdhci_adma(const char *desc, uint32_t sysad) "%s: admasysaddr=0x%" PRIx32
sdhci_adma_loop(uint64_t addr, uint16_t length, uint8_t attr) "addr=0x%08" PRIx64 ", len=%d, attr=0x%x"
sdhci_adma_transfer_completed(void) ""
sdhci_access(const char *access, unsigned int size, uint64_t offset, const char *dir, uint64_t val, uint64_t val2) "%s%u: addr[0x%04" PRIx64 "] %s 0x%08" PRIx64 " (%" PRIu64 ")"
sdhci_read_dataport(uint16_t data_count) "all %u bytes of data have been read from input buffer"
sdhci_write_dataport(uint16_t data_count) "write buffer filled with %u bytes of data"
# hw/sd/milkymist-memcard.c
milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
+13 -6
View File
@@ -26,26 +26,29 @@
#define SDHCI_H
#include "qemu-common.h"
#include "hw/block/block.h"
#include "hw/pci/pci.h"
#include "hw/sysbus.h"
#include "hw/sd/sd.h"
/* SD/MMC host controller state */
typedef struct SDHCIState {
/*< private >*/
union {
PCIDevice pcidev;
SysBusDevice busdev;
};
/*< public >*/
SDBus sdbus;
MemoryRegion iomem;
AddressSpace *dma_as;
MemoryRegion *dma_mr;
QEMUTimer *insert_timer; /* timer for 'changing' sd card. */
QEMUTimer *transfer_timer;
qemu_irq eject_cb;
qemu_irq ro_cb;
qemu_irq irq;
/* Registers cleared on reset */
uint32_t sdmasysad; /* SDMA System Address register */
uint16_t blksize; /* Host DMA Buff Boundary and Transfer BlkSize Reg */
uint16_t blkcnt; /* Blocks count for current transfer */
@@ -70,19 +73,23 @@ typedef struct SDHCIState {
uint16_t acmd12errsts; /* Auto CMD12 error status register */
uint64_t admasysaddr; /* ADMA System Address Register */
uint32_t capareg; /* Capabilities Register */
uint32_t maxcurr; /* Maximum Current Capabilities Register */
/* Read-only registers */
uint64_t capareg; /* Capabilities Register */
uint64_t maxcurr; /* Maximum Current Capabilities Register */
uint8_t *fifo_buffer; /* SD host i/o FIFO buffer */
uint32_t buf_maxsz;
uint16_t data_count; /* current element in FIFO buffer */
uint8_t stopped_state;/* Current SDHC state */
bool pending_insert_quirk;/* Quirk for Raspberry Pi card insert int */
bool pending_insert_state;
/* Buffer Data Port Register - virtual access point to R and W buffers */
/* Software Reset Register - always reads as 0 */
/* Force Event Auto CMD12 Error Interrupt Reg - write only */
/* Force Event Error Interrupt Register- write only */
/* RO Host Controller Version Register always reads as 0x2401 */
/* Configurable properties */
bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
} SDHCIState;
#define TYPE_PCI_SDHCI "sdhci-pci"
+48 -5
View File
@@ -8305,6 +8305,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_S2NS, &s2pa,
&txattrs, &s2prot, &s2size, fi, NULL);
if (ret) {
assert(fi->type != ARMFault_None);
fi->s2addr = addr;
fi->stage2 = true;
fi->s1ptw = true;
@@ -8328,7 +8329,9 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
MemTxAttrs attrs = {};
MemTxResult result = MEMTX_OK;
AddressSpace *as;
uint32_t data;
attrs.secure = is_secure;
as = arm_addressspace(cs, attrs);
@@ -8337,10 +8340,16 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
return 0;
}
if (regime_translation_big_endian(env, mmu_idx)) {
return address_space_ldl_be(as, addr, attrs, NULL);
data = address_space_ldl_be(as, addr, attrs, &result);
} else {
return address_space_ldl_le(as, addr, attrs, NULL);
data = address_space_ldl_le(as, addr, attrs, &result);
}
if (result == MEMTX_OK) {
return data;
}
fi->type = ARMFault_SyncExternalOnWalk;
fi->ea = arm_extabort_type(result);
return 0;
}
static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
@@ -8349,7 +8358,9 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
MemTxAttrs attrs = {};
MemTxResult result = MEMTX_OK;
AddressSpace *as;
uint32_t data;
attrs.secure = is_secure;
as = arm_addressspace(cs, attrs);
@@ -8358,10 +8369,16 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
return 0;
}
if (regime_translation_big_endian(env, mmu_idx)) {
return address_space_ldq_be(as, addr, attrs, NULL);
data = address_space_ldq_be(as, addr, attrs, &result);
} else {
return address_space_ldq_le(as, addr, attrs, NULL);
data = address_space_ldq_le(as, addr, attrs, &result);
}
if (result == MEMTX_OK) {
return data;
}
fi->type = ARMFault_SyncExternalOnWalk;
fi->ea = arm_extabort_type(result);
return 0;
}
static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
@@ -8390,6 +8407,9 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
}
desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
mmu_idx, fi);
if (fi->type != ARMFault_None) {
goto do_fault;
}
type = (desc & 3);
domain = (desc >> 5) & 0x0f;
if (regime_el(env, mmu_idx) == 1) {
@@ -8426,6 +8446,9 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
}
desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
mmu_idx, fi);
if (fi->type != ARMFault_None) {
goto do_fault;
}
switch (desc & 3) {
case 0: /* Page translation fault. */
fi->type = ARMFault_Translation;
@@ -8508,6 +8531,9 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
}
desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
mmu_idx, fi);
if (fi->type != ARMFault_None) {
goto do_fault;
}
type = (desc & 3);
if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
/* Section translation fault, or attempt to use the encoding
@@ -8559,6 +8585,9 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
mmu_idx, fi);
if (fi->type != ARMFault_None) {
goto do_fault;
}
ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
switch (desc & 3) {
case 0: /* Page translation fault. */
@@ -8964,7 +8993,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
descaddr &= ~7ULL;
nstable = extract32(tableattrs, 4, 1);
descriptor = arm_ldq_ptw(cs, descaddr, !nstable, mmu_idx, fi);
if (fi->s1ptw) {
if (fi->type != ARMFault_None) {
goto do_fault;
}
@@ -9272,6 +9301,13 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
case 6:
*prot |= PAGE_READ | PAGE_EXEC;
break;
case 7:
/* for v7M, same as 6; for R profile a reserved value */
if (arm_feature(env, ARM_FEATURE_M)) {
*prot |= PAGE_READ | PAGE_EXEC;
break;
}
/* fall through */
default:
qemu_log_mask(LOG_GUEST_ERROR,
"DRACR[%d]: Bad value for AP bits: 0x%"
@@ -9290,6 +9326,13 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
case 6:
*prot |= PAGE_READ | PAGE_EXEC;
break;
case 7:
/* for v7M, same as 6; for R profile a reserved value */
if (arm_feature(env, ARM_FEATURE_M)) {
*prot |= PAGE_READ | PAGE_EXEC;
break;
}
/* fall through */
default:
qemu_log_mask(LOG_GUEST_ERROR,
"DRACR[%d]: Bad value for AP bits: 0x%"
+10
View File
@@ -687,6 +687,16 @@ static inline uint32_t arm_fi_to_lfsc(ARMMMUFaultInfo *fi)
return fsc;
}
static inline bool arm_extabort_type(MemTxResult result)
{
/* The EA bit in syndromes and fault status registers is an
* IMPDEF classification of external aborts. ARM implementations
* usually use this to indicate AXI bus Decode error (0) or
* Slave error (1); in QEMU we follow that.
*/
return result != MEMTX_DECODE_ERROR;
}
/* Do a page table walk and add page to TLB if possible */
bool arm_tlb_fill(CPUState *cpu, vaddr address,
MMUAccessType access_type, int mmu_idx,
+1 -6
View File
@@ -220,12 +220,7 @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
/* now we have a real cpu fault */
cpu_restore_state(cs, retaddr);
/* The EA bit in syndromes and fault status registers is an
* IMPDEF classification of external aborts. ARM implementations
* usually use this to indicate AXI bus Decode error (0) or
* Slave error (1); in QEMU we follow that.
*/
fi.ea = (response != MEMTX_DECODE_ERROR);
fi.ea = arm_extabort_type(response);
fi.type = ARMFault_SyncExternal;
deliver_fault(cpu, addr, access_type, mmu_idx, &fi);
}
+33 -16
View File
@@ -4985,6 +4985,38 @@ static void disas_fp_3src(DisasContext *s, uint32_t insn)
}
}
/* The imm8 encodes the sign bit, enough bits to represent an exponent in
* the range 01....1xx to 10....0xx, and the most significant 4 bits of
* the mantissa; see VFPExpandImm() in the v8 ARM ARM.
*/
static uint64_t vfp_expand_imm(int size, uint8_t imm8)
{
uint64_t imm;
switch (size) {
case MO_64:
imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
(extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
extract32(imm8, 0, 6);
imm <<= 48;
break;
case MO_32:
imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
(extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
(extract32(imm8, 0, 6) << 3);
imm <<= 16;
break;
case MO_16:
imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
(extract32(imm8, 6, 1) ? 0x3000 : 0x4000) |
(extract32(imm8, 0, 6) << 6);
break;
default:
g_assert_not_reached();
}
return imm;
}
/* Floating point immediate
* 31 30 29 28 24 23 22 21 20 13 12 10 9 5 4 0
* +---+---+---+-----------+------+---+------------+-------+------+------+
@@ -5008,22 +5040,7 @@ static void disas_fp_imm(DisasContext *s, uint32_t insn)
return;
}
/* The imm8 encodes the sign bit, enough bits to represent
* an exponent in the range 01....1xx to 10....0xx,
* and the most significant 4 bits of the mantissa; see
* VFPExpandImm() in the v8 ARM ARM.
*/
if (is_double) {
imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
(extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
extract32(imm8, 0, 6);
imm <<= 48;
} else {
imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
(extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
(extract32(imm8, 0, 6) << 3);
imm <<= 16;
}
imm = vfp_expand_imm(MO_32 + is_double, imm8);
tcg_res = tcg_const_i64(imm);
write_fp_dreg(s, rd, tcg_res);