mirror of https://github.com/xemu-project/xemu.git
target-arm queue:
* Support EL0 v7m msr/mrs for CONFIG_USER_ONLY * Relax r13 restriction for ldrex/strex for v8.0 * Do not reject rt == rt2 for strexd * net/cadence_gem: Set PHY autonegotiation restart status * ssi: xilinx_spips: Skip spi bus update for a few register writes * pl031: Expose RTCICR as proper WC register -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAl3T7nsZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3uMOD/4xK9KDvUyCxwJkEziskodk 3d9JHrG3YWhpCzUpO01DmqYS6Hy32HYctoSYGoF3eWVYBoA+axqUtiVmcskYOx2F BIhBtTW3Svq8I5xP9jYOTS/wTUcHUJ+mWkl1aMDPRD7VJ2TJDUqD8ncFHg0aJI1S USFMj8D9bZiyGb5E+JI26LwKmvJO4G+upDyysL7Tmf5n3eTp6W1wdjrriAjFZeq4 +nMg9Qk3X5hpM3o86acGr3wnLyw3ECMAq932bpcjjRJyHaaYFuz8hF/gQaKohUAB KCD7zv/sEu0i4XlzS69J3milFWAl32qF9wCrbWLgb4WMDWVnB4EKKmo5tk92jIK+ CmddGgJHeyaR2UB6Fczk8khCWB5NpdnECi/7bcVfTBf/ceelrDWUebNztZbKR4UH UYpk1GPYbsFTsZyFj0x+b3PcRVDYKgPKrgsHNU3pAZDNwqRXh+R1SBApcQWy7ZDR wMTX1Sw92MoigiQS0phqDeUe0saToS3lkNchuFOOW224FsEwk0OpkvXi0c54Wn87 ao4ScCyxMJkE7lDH0GWpz9w3f8co/+B20X1HwpaCkkm2MvkV4stjuej8O80mtLqE kK5CirW9kOjkzhy47L7muAwZlciUlA9p+ZdVTwfTwWSb5aYUuIfHQV5Bz+Pq4uHu 215+GvJhFCtdcstDu8l+Qg== =9Prn -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20191119' into staging target-arm queue: * Support EL0 v7m msr/mrs for CONFIG_USER_ONLY * Relax r13 restriction for ldrex/strex for v8.0 * Do not reject rt == rt2 for strexd * net/cadence_gem: Set PHY autonegotiation restart status * ssi: xilinx_spips: Skip spi bus update for a few register writes * pl031: Expose RTCICR as proper WC register # gpg: Signature made Tue 19 Nov 2019 13:30:35 GMT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20191119: target/arm: Support EL0 v7m msr/mrs for CONFIG_USER_ONLY target/arm: Relax r13 restriction for ldrex/strex for v8.0 target/arm: Do not reject rt == rt2 for strexd net/cadence_gem: Set PHY autonegotiation restart status ssi: xilinx_spips: Skip spi bus update for a few register writes target/arm: Merge arm_cpu_vq_map_next_smaller into sole caller pl031: Expose RTCICR as proper WC register Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
9263dec8ef
|
@ -271,9 +271,10 @@
|
|||
#define PHY_REG_EXT_PHYSPCFC_ST 27
|
||||
#define PHY_REG_CABLE_DIAG 28
|
||||
|
||||
#define PHY_REG_CONTROL_RST 0x8000
|
||||
#define PHY_REG_CONTROL_LOOP 0x4000
|
||||
#define PHY_REG_CONTROL_ANEG 0x1000
|
||||
#define PHY_REG_CONTROL_RST 0x8000
|
||||
#define PHY_REG_CONTROL_LOOP 0x4000
|
||||
#define PHY_REG_CONTROL_ANEG 0x1000
|
||||
#define PHY_REG_CONTROL_ANRESTART 0x0200
|
||||
|
||||
#define PHY_REG_STATUS_LINK 0x0004
|
||||
#define PHY_REG_STATUS_ANEGCMPL 0x0020
|
||||
|
@ -1345,7 +1346,7 @@ static void gem_phy_write(CadenceGEMState *s, unsigned reg_num, uint16_t val)
|
|||
}
|
||||
if (val & PHY_REG_CONTROL_ANEG) {
|
||||
/* Complete autonegotiation immediately */
|
||||
val &= ~PHY_REG_CONTROL_ANEG;
|
||||
val &= ~(PHY_REG_CONTROL_ANEG | PHY_REG_CONTROL_ANRESTART);
|
||||
s->phy_regs[PHY_REG_STATUS] |= PHY_REG_STATUS_ANEGCMPL;
|
||||
}
|
||||
if (val & PHY_REG_CONTROL_LOOP) {
|
||||
|
|
|
@ -149,11 +149,7 @@ static void pl031_write(void * opaque, hwaddr offset,
|
|||
pl031_update(s);
|
||||
break;
|
||||
case RTC_ICR:
|
||||
/* The PL031 documentation (DDI0224B) states that the interrupt is
|
||||
cleared when bit 0 of the written value is set. However the
|
||||
arm926e documentation (DDI0287B) states that the interrupt is
|
||||
cleared when any value is written. */
|
||||
s->is = 0;
|
||||
s->is &= ~value;
|
||||
pl031_update(s);
|
||||
break;
|
||||
case RTC_CR:
|
||||
|
|
|
@ -109,6 +109,7 @@
|
|||
#define R_GPIO (0x30 / 4)
|
||||
#define R_LPBK_DLY_ADJ (0x38 / 4)
|
||||
#define R_LPBK_DLY_ADJ_RESET (0x33)
|
||||
#define R_IOU_TAPDLY_BYPASS (0x3C / 4)
|
||||
#define R_TXD1 (0x80 / 4)
|
||||
#define R_TXD2 (0x84 / 4)
|
||||
#define R_TXD3 (0x88 / 4)
|
||||
|
@ -139,6 +140,8 @@
|
|||
#define R_LQSPI_STS (0xA4 / 4)
|
||||
#define LQSPI_STS_WR_RECVD (1 << 1)
|
||||
|
||||
#define R_DUMMY_CYCLE_EN (0xC8 / 4)
|
||||
#define R_ECO (0xF8 / 4)
|
||||
#define R_MOD_ID (0xFC / 4)
|
||||
|
||||
#define R_GQSPI_SELECT (0x144 / 4)
|
||||
|
@ -970,6 +973,7 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
|
|||
{
|
||||
int mask = ~0;
|
||||
XilinxSPIPS *s = opaque;
|
||||
bool try_flush = true;
|
||||
|
||||
DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr, (unsigned)value);
|
||||
addr >>= 2;
|
||||
|
@ -1019,13 +1023,23 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
|
|||
tx_data_bytes(&s->tx_fifo, (uint32_t)value, 3,
|
||||
s->regs[R_CONFIG] & R_CONFIG_ENDIAN);
|
||||
goto no_reg_update;
|
||||
/* Skip SPI bus update for below registers writes */
|
||||
case R_GPIO:
|
||||
case R_LPBK_DLY_ADJ:
|
||||
case R_IOU_TAPDLY_BYPASS:
|
||||
case R_DUMMY_CYCLE_EN:
|
||||
case R_ECO:
|
||||
try_flush = false;
|
||||
break;
|
||||
}
|
||||
s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask);
|
||||
no_reg_update:
|
||||
xilinx_spips_update_cs_lines(s);
|
||||
xilinx_spips_check_flush(s);
|
||||
xilinx_spips_update_cs_lines(s);
|
||||
xilinx_spips_update_ixr(s);
|
||||
if (try_flush) {
|
||||
xilinx_spips_update_cs_lines(s);
|
||||
xilinx_spips_check_flush(s);
|
||||
xilinx_spips_update_cs_lines(s);
|
||||
xilinx_spips_update_ixr(s);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps spips_ops = {
|
||||
|
|
|
@ -185,12 +185,9 @@ typedef struct {
|
|||
#ifdef TARGET_AARCH64
|
||||
# define ARM_MAX_VQ 16
|
||||
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
|
||||
uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq);
|
||||
#else
|
||||
# define ARM_MAX_VQ 1
|
||||
static inline void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { }
|
||||
static inline uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq)
|
||||
{ return 0; }
|
||||
#endif
|
||||
|
||||
typedef struct ARMVectorReg {
|
||||
|
@ -1317,6 +1314,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
|
|||
if (mask & XPSR_GE) {
|
||||
env->GE = (val & XPSR_GE) >> 16;
|
||||
}
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (mask & XPSR_T) {
|
||||
env->thumb = ((val & XPSR_T) != 0);
|
||||
}
|
||||
|
@ -1332,6 +1330,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
|
|||
/* Note that this only happens on exception exit */
|
||||
write_v7m_exception(env, val & XPSR_EXCP);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define HCR_VM (1ULL << 0)
|
||||
|
|
|
@ -458,21 +458,6 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
|
|||
cpu->sve_max_vq = max_vq;
|
||||
}
|
||||
|
||||
uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq)
|
||||
{
|
||||
uint32_t bitnum;
|
||||
|
||||
/*
|
||||
* We allow vq == ARM_MAX_VQ + 1 to be input because the caller may want
|
||||
* to find the maximum vq enabled, which may be ARM_MAX_VQ, but this
|
||||
* function always returns the next smaller than the input.
|
||||
*/
|
||||
assert(vq && vq <= ARM_MAX_VQ + 1);
|
||||
|
||||
bitnum = find_last_bit(cpu->sve_vq_map, vq - 1);
|
||||
return bitnum == vq - 1 ? 0 : bitnum + 1;
|
||||
}
|
||||
|
||||
static void cpu_max_get_sve_max_vq(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
|
|
|
@ -5363,9 +5363,14 @@ int sve_exception_el(CPUARMState *env, int el)
|
|||
|
||||
static uint32_t sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len)
|
||||
{
|
||||
uint32_t start_vq = (start_len & 0xf) + 1;
|
||||
uint32_t end_len;
|
||||
|
||||
return arm_cpu_vq_map_next_smaller(cpu, start_vq + 1) - 1;
|
||||
end_len = start_len &= 0xf;
|
||||
if (!test_bit(start_len, cpu->sve_vq_map)) {
|
||||
end_len = find_last_bit(cpu->sve_vq_map, start_len);
|
||||
assert(end_len < start_len);
|
||||
}
|
||||
return end_len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -33,22 +33,82 @@
|
|||
#include "exec/cpu_ldst.h"
|
||||
#endif
|
||||
|
||||
static void v7m_msr_xpsr(CPUARMState *env, uint32_t mask,
|
||||
uint32_t reg, uint32_t val)
|
||||
{
|
||||
/* Only APSR is actually writable */
|
||||
if (!(reg & 4)) {
|
||||
uint32_t apsrmask = 0;
|
||||
|
||||
if (mask & 8) {
|
||||
apsrmask |= XPSR_NZCV | XPSR_Q;
|
||||
}
|
||||
if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
|
||||
apsrmask |= XPSR_GE;
|
||||
}
|
||||
xpsr_write(env, val, apsrmask);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t v7m_mrs_xpsr(CPUARMState *env, uint32_t reg, unsigned el)
|
||||
{
|
||||
uint32_t mask = 0;
|
||||
|
||||
if ((reg & 1) && el) {
|
||||
mask |= XPSR_EXCP; /* IPSR (unpriv. reads as zero) */
|
||||
}
|
||||
if (!(reg & 4)) {
|
||||
mask |= XPSR_NZCV | XPSR_Q; /* APSR */
|
||||
if (arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
|
||||
mask |= XPSR_GE;
|
||||
}
|
||||
}
|
||||
/* EPSR reads as zero */
|
||||
return xpsr_read(env) & mask;
|
||||
}
|
||||
|
||||
static uint32_t v7m_mrs_control(CPUARMState *env, uint32_t secure)
|
||||
{
|
||||
uint32_t value = env->v7m.control[secure];
|
||||
|
||||
if (!secure) {
|
||||
/* SFPA is RAZ/WI from NS; FPCA is stored in the M_REG_S bank */
|
||||
value |= env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
|
||||
/* These should probably raise undefined insn exceptions. */
|
||||
void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
|
||||
void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
uint32_t mask = extract32(maskreg, 8, 4);
|
||||
uint32_t reg = extract32(maskreg, 0, 8);
|
||||
|
||||
cpu_abort(CPU(cpu), "v7m_msr %d\n", reg);
|
||||
switch (reg) {
|
||||
case 0 ... 7: /* xPSR sub-fields */
|
||||
v7m_msr_xpsr(env, mask, reg, val);
|
||||
break;
|
||||
case 20: /* CONTROL */
|
||||
/* There are no sub-fields that are actually writable from EL0. */
|
||||
break;
|
||||
default:
|
||||
/* Unprivileged writes to other registers are ignored */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
|
||||
cpu_abort(CPU(cpu), "v7m_mrs %d\n", reg);
|
||||
return 0;
|
||||
switch (reg) {
|
||||
case 0 ... 7: /* xPSR sub-fields */
|
||||
return v7m_mrs_xpsr(env, reg, 0);
|
||||
case 20: /* CONTROL */
|
||||
return v7m_mrs_control(env, 0);
|
||||
default:
|
||||
/* Unprivileged reads others as zero. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
|
||||
|
@ -2196,35 +2256,14 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
|
|||
|
||||
uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
|
||||
{
|
||||
uint32_t mask;
|
||||
unsigned el = arm_current_el(env);
|
||||
|
||||
/* First handle registers which unprivileged can read */
|
||||
|
||||
switch (reg) {
|
||||
case 0 ... 7: /* xPSR sub-fields */
|
||||
mask = 0;
|
||||
if ((reg & 1) && el) {
|
||||
mask |= XPSR_EXCP; /* IPSR (unpriv. reads as zero) */
|
||||
}
|
||||
if (!(reg & 4)) {
|
||||
mask |= XPSR_NZCV | XPSR_Q; /* APSR */
|
||||
if (arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
|
||||
mask |= XPSR_GE;
|
||||
}
|
||||
}
|
||||
/* EPSR reads as zero */
|
||||
return xpsr_read(env) & mask;
|
||||
break;
|
||||
return v7m_mrs_xpsr(env, reg, el);
|
||||
case 20: /* CONTROL */
|
||||
{
|
||||
uint32_t value = env->v7m.control[env->v7m.secure];
|
||||
if (!env->v7m.secure) {
|
||||
/* SFPA is RAZ/WI from NS; FPCA is stored in the M_REG_S bank */
|
||||
value |= env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return v7m_mrs_control(env, env->v7m.secure);
|
||||
case 0x94: /* CONTROL_NS */
|
||||
/*
|
||||
* We have to handle this here because unprivileged Secure code
|
||||
|
@ -2454,18 +2493,7 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
|
|||
|
||||
switch (reg) {
|
||||
case 0 ... 7: /* xPSR sub-fields */
|
||||
/* only APSR is actually writable */
|
||||
if (!(reg & 4)) {
|
||||
uint32_t apsrmask = 0;
|
||||
|
||||
if (mask & 8) {
|
||||
apsrmask |= XPSR_NZCV | XPSR_Q;
|
||||
}
|
||||
if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
|
||||
apsrmask |= XPSR_GE;
|
||||
}
|
||||
xpsr_write(env, val, apsrmask);
|
||||
}
|
||||
v7m_msr_xpsr(env, mask, reg, val);
|
||||
break;
|
||||
case 8: /* MSP */
|
||||
if (v7m_using_psp(env)) {
|
||||
|
|
|
@ -8927,15 +8927,17 @@ static bool trans_SWPB(DisasContext *s, arg_SWP *a)
|
|||
static bool op_strex(DisasContext *s, arg_STREX *a, MemOp mop, bool rel)
|
||||
{
|
||||
TCGv_i32 addr;
|
||||
/* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
|
||||
bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
|
||||
|
||||
/* We UNDEF for these UNPREDICTABLE cases. */
|
||||
if (a->rd == 15 || a->rn == 15 || a->rt == 15
|
||||
|| a->rd == a->rn || a->rd == a->rt
|
||||
|| (s->thumb && (a->rd == 13 || a->rt == 13))
|
||||
|| (!v8a && s->thumb && (a->rd == 13 || a->rt == 13))
|
||||
|| (mop == MO_64
|
||||
&& (a->rt2 == 15
|
||||
|| a->rd == a->rt2 || a->rt == a->rt2
|
||||
|| (s->thumb && a->rt2 == 13)))) {
|
||||
|| a->rd == a->rt2
|
||||
|| (!v8a && s->thumb && a->rt2 == 13)))) {
|
||||
unallocated_encoding(s);
|
||||
return true;
|
||||
}
|
||||
|
@ -9084,13 +9086,15 @@ static bool trans_STLH(DisasContext *s, arg_STL *a)
|
|||
static bool op_ldrex(DisasContext *s, arg_LDREX *a, MemOp mop, bool acq)
|
||||
{
|
||||
TCGv_i32 addr;
|
||||
/* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
|
||||
bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
|
||||
|
||||
/* We UNDEF for these UNPREDICTABLE cases. */
|
||||
if (a->rn == 15 || a->rt == 15
|
||||
|| (s->thumb && a->rt == 13)
|
||||
|| (!v8a && s->thumb && a->rt == 13)
|
||||
|| (mop == MO_64
|
||||
&& (a->rt2 == 15 || a->rt == a->rt2
|
||||
|| (s->thumb && a->rt2 == 13)))) {
|
||||
|| (!v8a && s->thumb && a->rt2 == 13)))) {
|
||||
unallocated_encoding(s);
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue