mirror of https://github.com/xemu-project/xemu.git
MIPS queue for May 19th, 2019 - v3
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJc6rmrAAoJENSXKoln91pleiIH/iII48dveAe846j+leRJzvq0 xwykZ+uc1gM8vwHjJmQL2iz8BSx9irYg68jNgZNw+0/7pOqKVkyDt7T9CMpNIgI/ xsbaX3ta90Rhw6Cnw9h99SsWJAg2Oq4Phv7yCIgDMoNmph/caZyd/95ThmmQ2MXr BDOehxODcDyJAO3KIMODccuD6R0ofM2JKXUk2S5s7v1FjYm5fxfzOcx8P4P4lGP3 AB/k+iVMaEaZJWDHhPXte/5tF9aW8s39CUoe0BE/Cqje3ehLEY/6XxMamXiaWf/G 2taLvJ6lZ1T5nRmcTCBFfO4Sk3BEBeGlqF72nIlzeCJCe9SvISfwEhsHNkfsqiE= =hSSg -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-may-19-2019-v3' into staging MIPS queue for May 19th, 2019 - v3 # gpg: Signature made Sun 26 May 2019 17:07:07 BST # gpg: using RSA key D4972A8967F75A65 # gpg: Good signature from "Aleksandar Markovic <amarkovic@wavecomp.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 8526 FBF1 5DA3 811F 4A01 DD75 D497 2A89 67F7 5A65 * remotes/amarkovic/tags/mips-queue-may-19-2019-v3: BootLinuxSshTest: Test some userspace commands on Malta target/mips: realign comments to fix checkpatch warnings target/mips: add or remove space to fix checkpatch errors linux-user: fix __NR_semtimedop undeclared error mips: Decide to map PAGE_EXEC in map_address target/mips: Refactor and fix INSERT.<B|H|W|D> instructions target/mips: Refactor and fix COPY_U.<B|H|W> instructions target/mips: Refactor and fix COPY_S.<B|H|W|D> instructions target/mips: Fix MSA instructions ST.<B|H|W|D> on big endian host target/mips: Fix MSA instructions LD.<B|H|W|D> on big endian host target/mips: Make the results of MOD_<U|S>.<B|H|W|D> the same as on hardware target/mips: Make the results of DIV_<U|S>.<B|H|W|D> the same as on hardware Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
4a1d38c440
|
@ -934,6 +934,7 @@ M: Aurelien Jarno <aurelien@aurel32.net>
|
||||||
R: Aleksandar Rikalo <arikalo@wavecomp.com>
|
R: Aleksandar Rikalo <arikalo@wavecomp.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: hw/mips/mips_malta.c
|
F: hw/mips/mips_malta.c
|
||||||
|
F: tests/acceptance/linux_ssh_mips_malta.py
|
||||||
|
|
||||||
Mipssim
|
Mipssim
|
||||||
M: Aleksandar Markovic <amarkovic@wavecomp.com>
|
M: Aleksandar Markovic <amarkovic@wavecomp.com>
|
||||||
|
|
|
@ -763,14 +763,7 @@ safe_syscall2(int, nanosleep, const struct timespec *, req,
|
||||||
safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
|
safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
|
||||||
const struct timespec *, req, struct timespec *, rem)
|
const struct timespec *, req, struct timespec *, rem)
|
||||||
#endif
|
#endif
|
||||||
#ifdef __NR_msgsnd
|
#if !defined(__NR_msgsnd) || !defined(__NR_msgrcv) || !defined(__NR_semtimedop)
|
||||||
safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
|
|
||||||
int, flags)
|
|
||||||
safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
|
|
||||||
long, msgtype, int, flags)
|
|
||||||
safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
|
|
||||||
unsigned, nsops, const struct timespec *, timeout)
|
|
||||||
#else
|
|
||||||
/* This host kernel architecture uses a single ipc syscall; fake up
|
/* This host kernel architecture uses a single ipc syscall; fake up
|
||||||
* wrappers for the sub-operations to hide this implementation detail.
|
* wrappers for the sub-operations to hide this implementation detail.
|
||||||
* Annoyingly we can't include linux/ipc.h to get the constant definitions
|
* Annoyingly we can't include linux/ipc.h to get the constant definitions
|
||||||
|
@ -785,14 +778,29 @@ safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
|
||||||
|
|
||||||
safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
|
safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
|
||||||
void *, ptr, long, fifth)
|
void *, ptr, long, fifth)
|
||||||
|
#endif
|
||||||
|
#ifdef __NR_msgsnd
|
||||||
|
safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
|
||||||
|
int, flags)
|
||||||
|
#else
|
||||||
static int safe_msgsnd(int msgid, const void *msgp, size_t sz, int flags)
|
static int safe_msgsnd(int msgid, const void *msgp, size_t sz, int flags)
|
||||||
{
|
{
|
||||||
return safe_ipc(Q_IPCCALL(0, Q_MSGSND), msgid, sz, flags, (void *)msgp, 0);
|
return safe_ipc(Q_IPCCALL(0, Q_MSGSND), msgid, sz, flags, (void *)msgp, 0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __NR_msgrcv
|
||||||
|
safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
|
||||||
|
long, msgtype, int, flags)
|
||||||
|
#else
|
||||||
static int safe_msgrcv(int msgid, void *msgp, size_t sz, long type, int flags)
|
static int safe_msgrcv(int msgid, void *msgp, size_t sz, long type, int flags)
|
||||||
{
|
{
|
||||||
return safe_ipc(Q_IPCCALL(1, Q_MSGRCV), msgid, sz, flags, msgp, type);
|
return safe_ipc(Q_IPCCALL(1, Q_MSGRCV), msgid, sz, flags, msgp, type);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __NR_semtimedop
|
||||||
|
safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
|
||||||
|
unsigned, nsops, const struct timespec *, timeout)
|
||||||
|
#else
|
||||||
static int safe_semtimedop(int semid, struct sembuf *tsops, unsigned nsops,
|
static int safe_semtimedop(int semid, struct sembuf *tsops, unsigned nsops,
|
||||||
const struct timespec *timeout)
|
const struct timespec *timeout)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,10 +22,10 @@ typedef struct CPUMIPSTLBContext CPUMIPSTLBContext;
|
||||||
|
|
||||||
typedef union wr_t wr_t;
|
typedef union wr_t wr_t;
|
||||||
union wr_t {
|
union wr_t {
|
||||||
int8_t b[MSA_WRLEN/8];
|
int8_t b[MSA_WRLEN / 8];
|
||||||
int16_t h[MSA_WRLEN/16];
|
int16_t h[MSA_WRLEN / 16];
|
||||||
int32_t w[MSA_WRLEN/32];
|
int32_t w[MSA_WRLEN / 32];
|
||||||
int64_t d[MSA_WRLEN/64];
|
int64_t d[MSA_WRLEN / 64];
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef union fpr_t fpr_t;
|
typedef union fpr_t fpr_t;
|
||||||
|
@ -37,7 +37,8 @@ union fpr_t {
|
||||||
/* FPU/MSA register mapping is not tested on big-endian hosts. */
|
/* FPU/MSA register mapping is not tested on big-endian hosts. */
|
||||||
wr_t wr; /* vector data */
|
wr_t wr; /* vector data */
|
||||||
};
|
};
|
||||||
/* define FP_ENDIAN_IDX to access the same location
|
/*
|
||||||
|
*define FP_ENDIAN_IDX to access the same location
|
||||||
* in the fpr_t union regardless of the host endianness
|
* in the fpr_t union regardless of the host endianness
|
||||||
*/
|
*/
|
||||||
#if defined(HOST_WORDS_BIGENDIAN)
|
#if defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
@ -71,16 +72,29 @@ struct CPUMIPSFPUContext {
|
||||||
#define FCR31_FS 24
|
#define FCR31_FS 24
|
||||||
#define FCR31_ABS2008 19
|
#define FCR31_ABS2008 19
|
||||||
#define FCR31_NAN2008 18
|
#define FCR31_NAN2008 18
|
||||||
#define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
|
#define SET_FP_COND(num, env) do { ((env).fcr31) |= \
|
||||||
#define CLEAR_FP_COND(num,env) do { ((env).fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
|
((num) ? (1 << ((num) + 24)) : \
|
||||||
#define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1))
|
(1 << 23)); \
|
||||||
|
} while (0)
|
||||||
|
#define CLEAR_FP_COND(num, env) do { ((env).fcr31) &= \
|
||||||
|
~((num) ? (1 << ((num) + 24)) : \
|
||||||
|
(1 << 23)); \
|
||||||
|
} while (0)
|
||||||
|
#define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | \
|
||||||
|
(((env).fcr31 >> 23) & 0x1))
|
||||||
#define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f)
|
#define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f)
|
||||||
#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)
|
#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)
|
||||||
#define GET_FP_FLAGS(reg) (((reg) >> 2) & 0x1f)
|
#define GET_FP_FLAGS(reg) (((reg) >> 2) & 0x1f)
|
||||||
#define SET_FP_CAUSE(reg,v) do { (reg) = ((reg) & ~(0x3f << 12)) | ((v & 0x3f) << 12); } while(0)
|
#define SET_FP_CAUSE(reg, v) do { (reg) = ((reg) & ~(0x3f << 12)) | \
|
||||||
#define SET_FP_ENABLE(reg,v) do { (reg) = ((reg) & ~(0x1f << 7)) | ((v & 0x1f) << 7); } while(0)
|
((v & 0x3f) << 12); \
|
||||||
#define SET_FP_FLAGS(reg,v) do { (reg) = ((reg) & ~(0x1f << 2)) | ((v & 0x1f) << 2); } while(0)
|
} while (0)
|
||||||
#define UPDATE_FP_FLAGS(reg,v) do { (reg) |= ((v & 0x1f) << 2); } while(0)
|
#define SET_FP_ENABLE(reg, v) do { (reg) = ((reg) & ~(0x1f << 7)) | \
|
||||||
|
((v & 0x1f) << 7); \
|
||||||
|
} while (0)
|
||||||
|
#define SET_FP_FLAGS(reg, v) do { (reg) = ((reg) & ~(0x1f << 2)) | \
|
||||||
|
((v & 0x1f) << 2); \
|
||||||
|
} while (0)
|
||||||
|
#define UPDATE_FP_FLAGS(reg, v) do { (reg) |= ((v & 0x1f) << 2); } while (0)
|
||||||
#define FP_INEXACT 1
|
#define FP_INEXACT 1
|
||||||
#define FP_UNDERFLOW 2
|
#define FP_UNDERFLOW 2
|
||||||
#define FP_OVERFLOW 4
|
#define FP_OVERFLOW 4
|
||||||
|
@ -95,25 +109,25 @@ struct CPUMIPSFPUContext {
|
||||||
typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
|
typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
|
||||||
struct CPUMIPSMVPContext {
|
struct CPUMIPSMVPContext {
|
||||||
int32_t CP0_MVPControl;
|
int32_t CP0_MVPControl;
|
||||||
#define CP0MVPCo_CPA 3
|
#define CP0MVPCo_CPA 3
|
||||||
#define CP0MVPCo_STLB 2
|
#define CP0MVPCo_STLB 2
|
||||||
#define CP0MVPCo_VPC 1
|
#define CP0MVPCo_VPC 1
|
||||||
#define CP0MVPCo_EVP 0
|
#define CP0MVPCo_EVP 0
|
||||||
int32_t CP0_MVPConf0;
|
int32_t CP0_MVPConf0;
|
||||||
#define CP0MVPC0_M 31
|
#define CP0MVPC0_M 31
|
||||||
#define CP0MVPC0_TLBS 29
|
#define CP0MVPC0_TLBS 29
|
||||||
#define CP0MVPC0_GS 28
|
#define CP0MVPC0_GS 28
|
||||||
#define CP0MVPC0_PCP 27
|
#define CP0MVPC0_PCP 27
|
||||||
#define CP0MVPC0_PTLBE 16
|
#define CP0MVPC0_PTLBE 16
|
||||||
#define CP0MVPC0_TCA 15
|
#define CP0MVPC0_TCA 15
|
||||||
#define CP0MVPC0_PVPE 10
|
#define CP0MVPC0_PVPE 10
|
||||||
#define CP0MVPC0_PTC 0
|
#define CP0MVPC0_PTC 0
|
||||||
int32_t CP0_MVPConf1;
|
int32_t CP0_MVPConf1;
|
||||||
#define CP0MVPC1_CIM 31
|
#define CP0MVPC1_CIM 31
|
||||||
#define CP0MVPC1_CIF 30
|
#define CP0MVPC1_CIF 30
|
||||||
#define CP0MVPC1_PCX 20
|
#define CP0MVPC1_PCX 20
|
||||||
#define CP0MVPC1_PCP2 10
|
#define CP0MVPC1_PCP2 10
|
||||||
#define CP0MVPC1_PCP1 0
|
#define CP0MVPC1_PCP1 0
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct mips_def_t mips_def_t;
|
typedef struct mips_def_t mips_def_t;
|
||||||
|
@ -481,44 +495,44 @@ struct CPUMIPSState {
|
||||||
*/
|
*/
|
||||||
int32_t CP0_Random;
|
int32_t CP0_Random;
|
||||||
int32_t CP0_VPEControl;
|
int32_t CP0_VPEControl;
|
||||||
#define CP0VPECo_YSI 21
|
#define CP0VPECo_YSI 21
|
||||||
#define CP0VPECo_GSI 20
|
#define CP0VPECo_GSI 20
|
||||||
#define CP0VPECo_EXCPT 16
|
#define CP0VPECo_EXCPT 16
|
||||||
#define CP0VPECo_TE 15
|
#define CP0VPECo_TE 15
|
||||||
#define CP0VPECo_TargTC 0
|
#define CP0VPECo_TargTC 0
|
||||||
int32_t CP0_VPEConf0;
|
int32_t CP0_VPEConf0;
|
||||||
#define CP0VPEC0_M 31
|
#define CP0VPEC0_M 31
|
||||||
#define CP0VPEC0_XTC 21
|
#define CP0VPEC0_XTC 21
|
||||||
#define CP0VPEC0_TCS 19
|
#define CP0VPEC0_TCS 19
|
||||||
#define CP0VPEC0_SCS 18
|
#define CP0VPEC0_SCS 18
|
||||||
#define CP0VPEC0_DSC 17
|
#define CP0VPEC0_DSC 17
|
||||||
#define CP0VPEC0_ICS 16
|
#define CP0VPEC0_ICS 16
|
||||||
#define CP0VPEC0_MVP 1
|
#define CP0VPEC0_MVP 1
|
||||||
#define CP0VPEC0_VPA 0
|
#define CP0VPEC0_VPA 0
|
||||||
int32_t CP0_VPEConf1;
|
int32_t CP0_VPEConf1;
|
||||||
#define CP0VPEC1_NCX 20
|
#define CP0VPEC1_NCX 20
|
||||||
#define CP0VPEC1_NCP2 10
|
#define CP0VPEC1_NCP2 10
|
||||||
#define CP0VPEC1_NCP1 0
|
#define CP0VPEC1_NCP1 0
|
||||||
target_ulong CP0_YQMask;
|
target_ulong CP0_YQMask;
|
||||||
target_ulong CP0_VPESchedule;
|
target_ulong CP0_VPESchedule;
|
||||||
target_ulong CP0_VPEScheFBack;
|
target_ulong CP0_VPEScheFBack;
|
||||||
int32_t CP0_VPEOpt;
|
int32_t CP0_VPEOpt;
|
||||||
#define CP0VPEOpt_IWX7 15
|
#define CP0VPEOpt_IWX7 15
|
||||||
#define CP0VPEOpt_IWX6 14
|
#define CP0VPEOpt_IWX6 14
|
||||||
#define CP0VPEOpt_IWX5 13
|
#define CP0VPEOpt_IWX5 13
|
||||||
#define CP0VPEOpt_IWX4 12
|
#define CP0VPEOpt_IWX4 12
|
||||||
#define CP0VPEOpt_IWX3 11
|
#define CP0VPEOpt_IWX3 11
|
||||||
#define CP0VPEOpt_IWX2 10
|
#define CP0VPEOpt_IWX2 10
|
||||||
#define CP0VPEOpt_IWX1 9
|
#define CP0VPEOpt_IWX1 9
|
||||||
#define CP0VPEOpt_IWX0 8
|
#define CP0VPEOpt_IWX0 8
|
||||||
#define CP0VPEOpt_DWX7 7
|
#define CP0VPEOpt_DWX7 7
|
||||||
#define CP0VPEOpt_DWX6 6
|
#define CP0VPEOpt_DWX6 6
|
||||||
#define CP0VPEOpt_DWX5 5
|
#define CP0VPEOpt_DWX5 5
|
||||||
#define CP0VPEOpt_DWX4 4
|
#define CP0VPEOpt_DWX4 4
|
||||||
#define CP0VPEOpt_DWX3 3
|
#define CP0VPEOpt_DWX3 3
|
||||||
#define CP0VPEOpt_DWX2 2
|
#define CP0VPEOpt_DWX2 2
|
||||||
#define CP0VPEOpt_DWX1 1
|
#define CP0VPEOpt_DWX1 1
|
||||||
#define CP0VPEOpt_DWX0 0
|
#define CP0VPEOpt_DWX0 0
|
||||||
/*
|
/*
|
||||||
* CP0 Register 2
|
* CP0 Register 2
|
||||||
*/
|
*/
|
||||||
|
@ -625,33 +639,33 @@ struct CPUMIPSState {
|
||||||
#define CP0PC_PSN 0 /* 5..0 */
|
#define CP0PC_PSN 0 /* 5..0 */
|
||||||
int32_t CP0_SRSConf0_rw_bitmask;
|
int32_t CP0_SRSConf0_rw_bitmask;
|
||||||
int32_t CP0_SRSConf0;
|
int32_t CP0_SRSConf0;
|
||||||
#define CP0SRSC0_M 31
|
#define CP0SRSC0_M 31
|
||||||
#define CP0SRSC0_SRS3 20
|
#define CP0SRSC0_SRS3 20
|
||||||
#define CP0SRSC0_SRS2 10
|
#define CP0SRSC0_SRS2 10
|
||||||
#define CP0SRSC0_SRS1 0
|
#define CP0SRSC0_SRS1 0
|
||||||
int32_t CP0_SRSConf1_rw_bitmask;
|
int32_t CP0_SRSConf1_rw_bitmask;
|
||||||
int32_t CP0_SRSConf1;
|
int32_t CP0_SRSConf1;
|
||||||
#define CP0SRSC1_M 31
|
#define CP0SRSC1_M 31
|
||||||
#define CP0SRSC1_SRS6 20
|
#define CP0SRSC1_SRS6 20
|
||||||
#define CP0SRSC1_SRS5 10
|
#define CP0SRSC1_SRS5 10
|
||||||
#define CP0SRSC1_SRS4 0
|
#define CP0SRSC1_SRS4 0
|
||||||
int32_t CP0_SRSConf2_rw_bitmask;
|
int32_t CP0_SRSConf2_rw_bitmask;
|
||||||
int32_t CP0_SRSConf2;
|
int32_t CP0_SRSConf2;
|
||||||
#define CP0SRSC2_M 31
|
#define CP0SRSC2_M 31
|
||||||
#define CP0SRSC2_SRS9 20
|
#define CP0SRSC2_SRS9 20
|
||||||
#define CP0SRSC2_SRS8 10
|
#define CP0SRSC2_SRS8 10
|
||||||
#define CP0SRSC2_SRS7 0
|
#define CP0SRSC2_SRS7 0
|
||||||
int32_t CP0_SRSConf3_rw_bitmask;
|
int32_t CP0_SRSConf3_rw_bitmask;
|
||||||
int32_t CP0_SRSConf3;
|
int32_t CP0_SRSConf3;
|
||||||
#define CP0SRSC3_M 31
|
#define CP0SRSC3_M 31
|
||||||
#define CP0SRSC3_SRS12 20
|
#define CP0SRSC3_SRS12 20
|
||||||
#define CP0SRSC3_SRS11 10
|
#define CP0SRSC3_SRS11 10
|
||||||
#define CP0SRSC3_SRS10 0
|
#define CP0SRSC3_SRS10 0
|
||||||
int32_t CP0_SRSConf4_rw_bitmask;
|
int32_t CP0_SRSConf4_rw_bitmask;
|
||||||
int32_t CP0_SRSConf4;
|
int32_t CP0_SRSConf4;
|
||||||
#define CP0SRSC4_SRS15 20
|
#define CP0SRSC4_SRS15 20
|
||||||
#define CP0SRSC4_SRS14 10
|
#define CP0SRSC4_SRS14 10
|
||||||
#define CP0SRSC4_SRS13 0
|
#define CP0SRSC4_SRS13 0
|
||||||
/*
|
/*
|
||||||
* CP0 Register 7
|
* CP0 Register 7
|
||||||
*/
|
*/
|
||||||
|
@ -963,9 +977,11 @@ struct CPUMIPSState {
|
||||||
/* TMASK defines different execution modes */
|
/* TMASK defines different execution modes */
|
||||||
#define MIPS_HFLAG_TMASK 0x1F5807FF
|
#define MIPS_HFLAG_TMASK 0x1F5807FF
|
||||||
#define MIPS_HFLAG_MODE 0x00007 /* execution modes */
|
#define MIPS_HFLAG_MODE 0x00007 /* execution modes */
|
||||||
/* The KSU flags must be the lowest bits in hflags. The flag order
|
/*
|
||||||
must be the same as defined for CP0 Status. This allows to use
|
* The KSU flags must be the lowest bits in hflags. The flag order
|
||||||
the bits as the value of mmu_idx. */
|
* must be the same as defined for CP0 Status. This allows to use
|
||||||
|
* the bits as the value of mmu_idx.
|
||||||
|
*/
|
||||||
#define MIPS_HFLAG_KSU 0x00003 /* kernel/supervisor/user mode mask */
|
#define MIPS_HFLAG_KSU 0x00003 /* kernel/supervisor/user mode mask */
|
||||||
#define MIPS_HFLAG_UM 0x00002 /* user mode flag */
|
#define MIPS_HFLAG_UM 0x00002 /* user mode flag */
|
||||||
#define MIPS_HFLAG_SM 0x00001 /* supervisor mode flag */
|
#define MIPS_HFLAG_SM 0x00001 /* supervisor mode flag */
|
||||||
|
@ -975,18 +991,22 @@ struct CPUMIPSState {
|
||||||
#define MIPS_HFLAG_CP0 0x00010 /* CP0 enabled */
|
#define MIPS_HFLAG_CP0 0x00010 /* CP0 enabled */
|
||||||
#define MIPS_HFLAG_FPU 0x00020 /* FPU enabled */
|
#define MIPS_HFLAG_FPU 0x00020 /* FPU enabled */
|
||||||
#define MIPS_HFLAG_F64 0x00040 /* 64-bit FPU enabled */
|
#define MIPS_HFLAG_F64 0x00040 /* 64-bit FPU enabled */
|
||||||
/* True if the MIPS IV COP1X instructions can be used. This also
|
/*
|
||||||
controls the non-COP1X instructions RECIP.S, RECIP.D, RSQRT.S
|
* True if the MIPS IV COP1X instructions can be used. This also
|
||||||
and RSQRT.D. */
|
* controls the non-COP1X instructions RECIP.S, RECIP.D, RSQRT.S
|
||||||
|
* and RSQRT.D.
|
||||||
|
*/
|
||||||
#define MIPS_HFLAG_COP1X 0x00080 /* COP1X instructions enabled */
|
#define MIPS_HFLAG_COP1X 0x00080 /* COP1X instructions enabled */
|
||||||
#define MIPS_HFLAG_RE 0x00100 /* Reversed endianness */
|
#define MIPS_HFLAG_RE 0x00100 /* Reversed endianness */
|
||||||
#define MIPS_HFLAG_AWRAP 0x00200 /* 32-bit compatibility address wrapping */
|
#define MIPS_HFLAG_AWRAP 0x00200 /* 32-bit compatibility address wrapping */
|
||||||
#define MIPS_HFLAG_M16 0x00400 /* MIPS16 mode flag */
|
#define MIPS_HFLAG_M16 0x00400 /* MIPS16 mode flag */
|
||||||
#define MIPS_HFLAG_M16_SHIFT 10
|
#define MIPS_HFLAG_M16_SHIFT 10
|
||||||
/* If translation is interrupted between the branch instruction and
|
/*
|
||||||
|
* If translation is interrupted between the branch instruction and
|
||||||
* the delay slot, record what type of branch it is so that we can
|
* the delay slot, record what type of branch it is so that we can
|
||||||
* resume translation properly. It might be possible to reduce
|
* resume translation properly. It might be possible to reduce
|
||||||
* this from three bits to two. */
|
* this from three bits to two.
|
||||||
|
*/
|
||||||
#define MIPS_HFLAG_BMASK_BASE 0x803800
|
#define MIPS_HFLAG_BMASK_BASE 0x803800
|
||||||
#define MIPS_HFLAG_B 0x00800 /* Unconditional branch */
|
#define MIPS_HFLAG_B 0x00800 /* Unconditional branch */
|
||||||
#define MIPS_HFLAG_BC 0x01000 /* Conditional branch */
|
#define MIPS_HFLAG_BC 0x01000 /* Conditional branch */
|
||||||
|
@ -1073,8 +1093,10 @@ void mips_cpu_list(void);
|
||||||
extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
|
extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
|
||||||
extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
|
extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
|
||||||
|
|
||||||
/* MMU modes definitions. We carefully match the indices with our
|
/*
|
||||||
hflags layout. */
|
* MMU modes definitions. We carefully match the indices with our
|
||||||
|
* hflags layout.
|
||||||
|
*/
|
||||||
#define MMU_MODE0_SUFFIX _kernel
|
#define MMU_MODE0_SUFFIX _kernel
|
||||||
#define MMU_MODE1_SUFFIX _super
|
#define MMU_MODE1_SUFFIX _super
|
||||||
#define MMU_MODE2_SUFFIX _user
|
#define MMU_MODE2_SUFFIX _user
|
||||||
|
@ -1090,14 +1112,15 @@ static inline int hflags_mmu_index(uint32_t hflags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int cpu_mmu_index (CPUMIPSState *env, bool ifetch)
|
static inline int cpu_mmu_index(CPUMIPSState *env, bool ifetch)
|
||||||
{
|
{
|
||||||
return hflags_mmu_index(env->hflags);
|
return hflags_mmu_index(env->hflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "exec/cpu-all.h"
|
#include "exec/cpu-all.h"
|
||||||
|
|
||||||
/* Memory access type :
|
/*
|
||||||
|
* Memory access type :
|
||||||
* may be needed for precise access rights control and precise exceptions.
|
* may be needed for precise access rights control and precise exceptions.
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
|
@ -1182,7 +1205,7 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level);
|
||||||
void itc_reconfigure(struct MIPSITUState *tag);
|
void itc_reconfigure(struct MIPSITUState *tag);
|
||||||
|
|
||||||
/* helper.c */
|
/* helper.c */
|
||||||
target_ulong exception_resume_pc (CPUMIPSState *env);
|
target_ulong exception_resume_pc(CPUMIPSState *env);
|
||||||
|
|
||||||
static inline void restore_snan_bit_mode(CPUMIPSState *env)
|
static inline void restore_snan_bit_mode(CPUMIPSState *env)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,7 +43,7 @@ int no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
|
||||||
target_ulong address, int rw, int access_type)
|
target_ulong address, int rw, int access_type)
|
||||||
{
|
{
|
||||||
*physical = address;
|
*physical = address;
|
||||||
*prot = PAGE_READ | PAGE_WRITE;
|
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||||
return TLBRET_MATCH;
|
return TLBRET_MATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ int fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
|
||||||
else
|
else
|
||||||
*physical = address;
|
*physical = address;
|
||||||
|
|
||||||
*prot = PAGE_READ | PAGE_WRITE;
|
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||||
return TLBRET_MATCH;
|
return TLBRET_MATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +101,9 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
|
||||||
*prot = PAGE_READ;
|
*prot = PAGE_READ;
|
||||||
if (n ? tlb->D1 : tlb->D0)
|
if (n ? tlb->D1 : tlb->D0)
|
||||||
*prot |= PAGE_WRITE;
|
*prot |= PAGE_WRITE;
|
||||||
|
if (!(n ? tlb->XI1 : tlb->XI0)) {
|
||||||
|
*prot |= PAGE_EXEC;
|
||||||
|
}
|
||||||
return TLBRET_MATCH;
|
return TLBRET_MATCH;
|
||||||
}
|
}
|
||||||
return TLBRET_DIRTY;
|
return TLBRET_DIRTY;
|
||||||
|
@ -182,7 +185,7 @@ static int get_seg_physical_address(CPUMIPSState *env, hwaddr *physical,
|
||||||
} else {
|
} else {
|
||||||
/* The segment is unmapped */
|
/* The segment is unmapped */
|
||||||
*physical = physical_base | (real_address & segmask);
|
*physical = physical_base | (real_address & segmask);
|
||||||
*prot = PAGE_READ | PAGE_WRITE;
|
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||||
return TLBRET_MATCH;
|
return TLBRET_MATCH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -907,7 +910,7 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||||
}
|
}
|
||||||
if (ret == TLBRET_MATCH) {
|
if (ret == TLBRET_MATCH) {
|
||||||
tlb_set_page(cs, address & TARGET_PAGE_MASK,
|
tlb_set_page(cs, address & TARGET_PAGE_MASK,
|
||||||
physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
|
physical & TARGET_PAGE_MASK, prot,
|
||||||
mmu_idx, TARGET_PAGE_SIZE);
|
mmu_idx, TARGET_PAGE_SIZE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -927,7 +930,7 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||||
access_type, mips_access_type, mmu_idx);
|
access_type, mips_access_type, mmu_idx);
|
||||||
if (ret == TLBRET_MATCH) {
|
if (ret == TLBRET_MATCH) {
|
||||||
tlb_set_page(cs, address & TARGET_PAGE_MASK,
|
tlb_set_page(cs, address & TARGET_PAGE_MASK,
|
||||||
physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
|
physical & TARGET_PAGE_MASK, prot,
|
||||||
mmu_idx, TARGET_PAGE_SIZE);
|
mmu_idx, TARGET_PAGE_SIZE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -876,9 +876,7 @@ DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32)
|
||||||
|
|
||||||
DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32)
|
DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32)
|
||||||
DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32)
|
DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32)
|
||||||
DEF_HELPER_5(msa_copy_s_df, void, env, i32, i32, i32, i32)
|
|
||||||
DEF_HELPER_5(msa_copy_u_df, void, env, i32, i32, i32, i32)
|
|
||||||
DEF_HELPER_5(msa_insert_df, void, env, i32, i32, i32, i32)
|
|
||||||
DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32)
|
DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32)
|
||||||
DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32)
|
DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32)
|
||||||
DEF_HELPER_2(msa_cfcmsa, tl, env, i32)
|
DEF_HELPER_2(msa_cfcmsa, tl, env, i32)
|
||||||
|
@ -938,6 +936,18 @@ DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32)
|
||||||
DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32)
|
DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32)
|
||||||
DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32)
|
DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32)
|
||||||
|
|
||||||
|
DEF_HELPER_4(msa_copy_s_b, void, env, i32, i32, i32)
|
||||||
|
DEF_HELPER_4(msa_copy_s_h, void, env, i32, i32, i32)
|
||||||
|
DEF_HELPER_4(msa_copy_s_w, void, env, i32, i32, i32)
|
||||||
|
DEF_HELPER_4(msa_copy_s_d, void, env, i32, i32, i32)
|
||||||
|
DEF_HELPER_4(msa_copy_u_b, void, env, i32, i32, i32)
|
||||||
|
DEF_HELPER_4(msa_copy_u_h, void, env, i32, i32, i32)
|
||||||
|
DEF_HELPER_4(msa_copy_u_w, void, env, i32, i32, i32)
|
||||||
|
DEF_HELPER_4(msa_insert_b, void, env, i32, i32, i32)
|
||||||
|
DEF_HELPER_4(msa_insert_h, void, env, i32, i32, i32)
|
||||||
|
DEF_HELPER_4(msa_insert_w, void, env, i32, i32, i32)
|
||||||
|
DEF_HELPER_4(msa_insert_d, void, env, i32, i32, i32)
|
||||||
|
|
||||||
DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32)
|
DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32)
|
||||||
DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32)
|
DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32)
|
||||||
DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32)
|
DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32)
|
||||||
|
|
|
@ -641,14 +641,15 @@ static inline int64_t msa_div_s_df(uint32_t df, int64_t arg1, int64_t arg2)
|
||||||
if (arg1 == DF_MIN_INT(df) && arg2 == -1) {
|
if (arg1 == DF_MIN_INT(df) && arg2 == -1) {
|
||||||
return DF_MIN_INT(df);
|
return DF_MIN_INT(df);
|
||||||
}
|
}
|
||||||
return arg2 ? arg1 / arg2 : 0;
|
return arg2 ? arg1 / arg2
|
||||||
|
: arg1 >= 0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int64_t msa_div_u_df(uint32_t df, int64_t arg1, int64_t arg2)
|
static inline int64_t msa_div_u_df(uint32_t df, int64_t arg1, int64_t arg2)
|
||||||
{
|
{
|
||||||
uint64_t u_arg1 = UNSIGNED(arg1, df);
|
uint64_t u_arg1 = UNSIGNED(arg1, df);
|
||||||
uint64_t u_arg2 = UNSIGNED(arg2, df);
|
uint64_t u_arg2 = UNSIGNED(arg2, df);
|
||||||
return u_arg2 ? u_arg1 / u_arg2 : 0;
|
return arg2 ? u_arg1 / u_arg2 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2)
|
static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2)
|
||||||
|
@ -656,14 +657,14 @@ static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2)
|
||||||
if (arg1 == DF_MIN_INT(df) && arg2 == -1) {
|
if (arg1 == DF_MIN_INT(df) && arg2 == -1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return arg2 ? arg1 % arg2 : 0;
|
return arg2 ? arg1 % arg2 : arg1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int64_t msa_mod_u_df(uint32_t df, int64_t arg1, int64_t arg2)
|
static inline int64_t msa_mod_u_df(uint32_t df, int64_t arg1, int64_t arg2)
|
||||||
{
|
{
|
||||||
uint64_t u_arg1 = UNSIGNED(arg1, df);
|
uint64_t u_arg1 = UNSIGNED(arg1, df);
|
||||||
uint64_t u_arg2 = UNSIGNED(arg2, df);
|
uint64_t u_arg2 = UNSIGNED(arg2, df);
|
||||||
return u_arg2 ? u_arg1 % u_arg2 : 0;
|
return u_arg2 ? u_arg1 % u_arg2 : u_arg1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SIGNED_EVEN(a, df) \
|
#define SIGNED_EVEN(a, df) \
|
||||||
|
@ -1248,78 +1249,152 @@ void helper_msa_splati_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||||
msa_splat_df(df, pwd, pws, n);
|
msa_splat_df(df, pwd, pws, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_msa_copy_s_df(CPUMIPSState *env, uint32_t df, uint32_t rd,
|
void helper_msa_copy_s_b(CPUMIPSState *env, uint32_t rd,
|
||||||
uint32_t ws, uint32_t n)
|
uint32_t ws, uint32_t n)
|
||||||
{
|
{
|
||||||
n %= DF_ELEMENTS(df);
|
n %= 16;
|
||||||
|
#if defined(HOST_WORDS_BIGENDIAN)
|
||||||
switch (df) {
|
if (n < 8) {
|
||||||
case DF_BYTE:
|
n = 8 - n - 1;
|
||||||
env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n];
|
} else {
|
||||||
break;
|
n = 24 - n - 1;
|
||||||
case DF_HALF:
|
|
||||||
env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n];
|
|
||||||
break;
|
|
||||||
case DF_WORD:
|
|
||||||
env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n];
|
|
||||||
break;
|
|
||||||
#ifdef TARGET_MIPS64
|
|
||||||
case DF_DOUBLE:
|
|
||||||
env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n];
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_msa_copy_u_df(CPUMIPSState *env, uint32_t df, uint32_t rd,
|
void helper_msa_copy_s_h(CPUMIPSState *env, uint32_t rd,
|
||||||
uint32_t ws, uint32_t n)
|
uint32_t ws, uint32_t n)
|
||||||
{
|
{
|
||||||
n %= DF_ELEMENTS(df);
|
n %= 8;
|
||||||
|
#if defined(HOST_WORDS_BIGENDIAN)
|
||||||
switch (df) {
|
if (n < 4) {
|
||||||
case DF_BYTE:
|
n = 4 - n - 1;
|
||||||
env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n];
|
} else {
|
||||||
break;
|
n = 12 - n - 1;
|
||||||
case DF_HALF:
|
|
||||||
env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n];
|
|
||||||
break;
|
|
||||||
case DF_WORD:
|
|
||||||
env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n];
|
|
||||||
break;
|
|
||||||
#ifdef TARGET_MIPS64
|
|
||||||
case DF_DOUBLE:
|
|
||||||
env->active_tc.gpr[rd] = (uint64_t)env->active_fpu.fpr[ws].wr.d[n];
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_msa_insert_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
void helper_msa_copy_s_w(CPUMIPSState *env, uint32_t rd,
|
||||||
|
uint32_t ws, uint32_t n)
|
||||||
|
{
|
||||||
|
n %= 4;
|
||||||
|
#if defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
if (n < 2) {
|
||||||
|
n = 2 - n - 1;
|
||||||
|
} else {
|
||||||
|
n = 6 - n - 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_copy_s_d(CPUMIPSState *env, uint32_t rd,
|
||||||
|
uint32_t ws, uint32_t n)
|
||||||
|
{
|
||||||
|
n %= 2;
|
||||||
|
env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_copy_u_b(CPUMIPSState *env, uint32_t rd,
|
||||||
|
uint32_t ws, uint32_t n)
|
||||||
|
{
|
||||||
|
n %= 16;
|
||||||
|
#if defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
if (n < 8) {
|
||||||
|
n = 8 - n - 1;
|
||||||
|
} else {
|
||||||
|
n = 24 - n - 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_copy_u_h(CPUMIPSState *env, uint32_t rd,
|
||||||
|
uint32_t ws, uint32_t n)
|
||||||
|
{
|
||||||
|
n %= 8;
|
||||||
|
#if defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
if (n < 4) {
|
||||||
|
n = 4 - n - 1;
|
||||||
|
} else {
|
||||||
|
n = 12 - n - 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_copy_u_w(CPUMIPSState *env, uint32_t rd,
|
||||||
|
uint32_t ws, uint32_t n)
|
||||||
|
{
|
||||||
|
n %= 4;
|
||||||
|
#if defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
if (n < 2) {
|
||||||
|
n = 2 - n - 1;
|
||||||
|
} else {
|
||||||
|
n = 6 - n - 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_insert_b(CPUMIPSState *env, uint32_t wd,
|
||||||
uint32_t rs_num, uint32_t n)
|
uint32_t rs_num, uint32_t n)
|
||||||
{
|
{
|
||||||
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
target_ulong rs = env->active_tc.gpr[rs_num];
|
target_ulong rs = env->active_tc.gpr[rs_num];
|
||||||
|
n %= 16;
|
||||||
switch (df) {
|
#if defined(HOST_WORDS_BIGENDIAN)
|
||||||
case DF_BYTE:
|
if (n < 8) {
|
||||||
pwd->b[n] = (int8_t)rs;
|
n = 8 - n - 1;
|
||||||
break;
|
} else {
|
||||||
case DF_HALF:
|
n = 24 - n - 1;
|
||||||
pwd->h[n] = (int16_t)rs;
|
|
||||||
break;
|
|
||||||
case DF_WORD:
|
|
||||||
pwd->w[n] = (int32_t)rs;
|
|
||||||
break;
|
|
||||||
case DF_DOUBLE:
|
|
||||||
pwd->d[n] = (int64_t)rs;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
pwd->b[n] = (int8_t)rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_insert_h(CPUMIPSState *env, uint32_t wd,
|
||||||
|
uint32_t rs_num, uint32_t n)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
target_ulong rs = env->active_tc.gpr[rs_num];
|
||||||
|
n %= 8;
|
||||||
|
#if defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
if (n < 4) {
|
||||||
|
n = 4 - n - 1;
|
||||||
|
} else {
|
||||||
|
n = 12 - n - 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
pwd->h[n] = (int16_t)rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_insert_w(CPUMIPSState *env, uint32_t wd,
|
||||||
|
uint32_t rs_num, uint32_t n)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
target_ulong rs = env->active_tc.gpr[rs_num];
|
||||||
|
n %= 4;
|
||||||
|
#if defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
if (n < 2) {
|
||||||
|
n = 2 - n - 1;
|
||||||
|
} else {
|
||||||
|
n = 6 - n - 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
pwd->w[n] = (int32_t)rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_insert_d(CPUMIPSState *env, uint32_t wd,
|
||||||
|
uint32_t rs_num, uint32_t n)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
target_ulong rs = env->active_tc.gpr[rs_num];
|
||||||
|
n %= 2;
|
||||||
|
pwd->d[n] = (int64_t)rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_msa_insve_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
void helper_msa_insve_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||||
|
|
|
@ -4356,31 +4356,179 @@ FOP_CONDN_S(sne, (float32_lt(fst1, fst0, &env->active_fpu.fp_status)
|
||||||
#define MEMOP_IDX(DF)
|
#define MEMOP_IDX(DF)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MSA_LD_DF(DF, TYPE, LD_INSN, ...) \
|
void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
|
||||||
void helper_msa_ld_ ## TYPE(CPUMIPSState *env, uint32_t wd, \
|
target_ulong addr)
|
||||||
target_ulong addr) \
|
{
|
||||||
{ \
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
|
MEMOP_IDX(DF_BYTE)
|
||||||
wr_t wx; \
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
int i; \
|
#if !defined(HOST_WORDS_BIGENDIAN)
|
||||||
MEMOP_IDX(DF) \
|
pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
|
||||||
for (i = 0; i < DF_ELEMENTS(DF); i++) { \
|
pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
|
||||||
wx.TYPE[i] = LD_INSN(env, addr + (i << DF), ##__VA_ARGS__); \
|
pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
|
||||||
} \
|
pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
|
||||||
memcpy(pwd, &wx, sizeof(wr_t)); \
|
pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
|
||||||
|
#else
|
||||||
|
pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
|
||||||
|
pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if !defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
|
||||||
|
pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
|
||||||
|
pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
|
||||||
|
pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
|
||||||
|
pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
|
||||||
|
pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
|
||||||
|
pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
|
||||||
|
pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
|
||||||
|
pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
|
||||||
|
pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
|
||||||
|
pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
|
||||||
|
pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
|
||||||
|
pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
|
||||||
|
pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
|
||||||
|
pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
|
||||||
|
pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
|
||||||
|
#else
|
||||||
|
pwd->b[0] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
|
||||||
|
pwd->b[1] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
|
||||||
|
pwd->b[2] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
|
||||||
|
pwd->b[3] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
|
||||||
|
pwd->b[4] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
|
||||||
|
pwd->b[5] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
|
||||||
|
pwd->b[6] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
|
||||||
|
pwd->b[7] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
|
||||||
|
pwd->b[8] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
|
||||||
|
pwd->b[9] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
|
||||||
|
pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
|
||||||
|
pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
|
||||||
|
pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
|
||||||
|
pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
|
||||||
|
pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
|
||||||
|
pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
|
||||||
|
target_ulong addr)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
MEMOP_IDX(DF_HALF)
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
MSA_LD_DF(DF_BYTE, b, helper_ret_ldub_mmu, oi, GETPC())
|
#if !defined(HOST_WORDS_BIGENDIAN)
|
||||||
MSA_LD_DF(DF_HALF, h, helper_ret_lduw_mmu, oi, GETPC())
|
pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
|
||||||
MSA_LD_DF(DF_WORD, w, helper_ret_ldul_mmu, oi, GETPC())
|
pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
|
||||||
MSA_LD_DF(DF_DOUBLE, d, helper_ret_ldq_mmu, oi, GETPC())
|
pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
|
||||||
|
pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
|
||||||
|
pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
|
||||||
|
pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
|
||||||
|
pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
|
||||||
|
pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
|
||||||
#else
|
#else
|
||||||
MSA_LD_DF(DF_BYTE, b, cpu_ldub_data)
|
pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
|
||||||
MSA_LD_DF(DF_HALF, h, cpu_lduw_data)
|
pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
|
||||||
MSA_LD_DF(DF_WORD, w, cpu_ldl_data)
|
pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
|
||||||
MSA_LD_DF(DF_DOUBLE, d, cpu_ldq_data)
|
pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
|
||||||
|
pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
|
||||||
|
pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
|
||||||
|
pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
|
||||||
|
pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
#if !defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF));
|
||||||
|
pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF));
|
||||||
|
pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF));
|
||||||
|
pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF));
|
||||||
|
pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF));
|
||||||
|
pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF));
|
||||||
|
pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF));
|
||||||
|
pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF));
|
||||||
|
#else
|
||||||
|
pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF));
|
||||||
|
pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF));
|
||||||
|
pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF));
|
||||||
|
pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF));
|
||||||
|
pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF));
|
||||||
|
pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF));
|
||||||
|
pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF));
|
||||||
|
pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd,
|
||||||
|
target_ulong addr)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
MEMOP_IDX(DF_WORD)
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
#if !defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
|
||||||
|
pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
|
||||||
|
pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
|
||||||
|
pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
|
||||||
|
#else
|
||||||
|
pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
|
||||||
|
pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
|
||||||
|
pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
|
||||||
|
pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if !defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD));
|
||||||
|
pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD));
|
||||||
|
pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD));
|
||||||
|
pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD));
|
||||||
|
#else
|
||||||
|
pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD));
|
||||||
|
pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD));
|
||||||
|
pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD));
|
||||||
|
pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd,
|
||||||
|
target_ulong addr)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
MEMOP_IDX(DF_DOUBLE)
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC());
|
||||||
|
pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC());
|
||||||
|
#else
|
||||||
|
pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE));
|
||||||
|
pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#define MSA_PAGESPAN(x) \
|
#define MSA_PAGESPAN(x) \
|
||||||
((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN/8 - 1) >= TARGET_PAGE_SIZE)
|
((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN/8 - 1) >= TARGET_PAGE_SIZE)
|
||||||
|
@ -4402,31 +4550,191 @@ static inline void ensure_writable_pages(CPUMIPSState *env,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MSA_ST_DF(DF, TYPE, ST_INSN, ...) \
|
void helper_msa_st_b(CPUMIPSState *env, uint32_t wd,
|
||||||
void helper_msa_st_ ## TYPE(CPUMIPSState *env, uint32_t wd, \
|
target_ulong addr)
|
||||||
target_ulong addr) \
|
{
|
||||||
{ \
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \
|
int mmu_idx = cpu_mmu_index(env, false);
|
||||||
int mmu_idx = cpu_mmu_index(env, false); \
|
|
||||||
int i; \
|
MEMOP_IDX(DF_BYTE)
|
||||||
MEMOP_IDX(DF) \
|
ensure_writable_pages(env, addr, mmu_idx, GETPC());
|
||||||
ensure_writable_pages(env, addr, mmu_idx, GETPC()); \
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
for (i = 0; i < DF_ELEMENTS(DF); i++) { \
|
#if !defined(HOST_WORDS_BIGENDIAN)
|
||||||
ST_INSN(env, addr + (i << DF), pwd->TYPE[i], ##__VA_ARGS__); \
|
helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[0], oi, GETPC());
|
||||||
} \
|
helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[1], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[2], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[3], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[4], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[5], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[6], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[7], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[8], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[9], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC());
|
||||||
|
#else
|
||||||
|
helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[0], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[1], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[2], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[3], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[4], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[5], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[6], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[7], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[14], oi, GETPC());
|
||||||
|
helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[15], oi, GETPC());
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if !defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[0]);
|
||||||
|
cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[1]);
|
||||||
|
cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[2]);
|
||||||
|
cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[3]);
|
||||||
|
cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[4]);
|
||||||
|
cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[5]);
|
||||||
|
cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[6]);
|
||||||
|
cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[7]);
|
||||||
|
cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[8]);
|
||||||
|
cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[9]);
|
||||||
|
cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]);
|
||||||
|
cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]);
|
||||||
|
cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]);
|
||||||
|
cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]);
|
||||||
|
cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]);
|
||||||
|
cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]);
|
||||||
|
#else
|
||||||
|
cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[0]);
|
||||||
|
cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[1]);
|
||||||
|
cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[2]);
|
||||||
|
cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[3]);
|
||||||
|
cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[4]);
|
||||||
|
cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[5]);
|
||||||
|
cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[6]);
|
||||||
|
cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[7]);
|
||||||
|
cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]);
|
||||||
|
cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]);
|
||||||
|
cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]);
|
||||||
|
cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]);
|
||||||
|
cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]);
|
||||||
|
cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]);
|
||||||
|
cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[14]);
|
||||||
|
cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[15]);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
|
||||||
|
target_ulong addr)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
int mmu_idx = cpu_mmu_index(env, false);
|
||||||
|
|
||||||
|
MEMOP_IDX(DF_HALF)
|
||||||
|
ensure_writable_pages(env, addr, mmu_idx, GETPC());
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
MSA_ST_DF(DF_BYTE, b, helper_ret_stb_mmu, oi, GETPC())
|
#if !defined(HOST_WORDS_BIGENDIAN)
|
||||||
MSA_ST_DF(DF_HALF, h, helper_ret_stw_mmu, oi, GETPC())
|
helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC());
|
||||||
MSA_ST_DF(DF_WORD, w, helper_ret_stl_mmu, oi, GETPC())
|
helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC());
|
||||||
MSA_ST_DF(DF_DOUBLE, d, helper_ret_stq_mmu, oi, GETPC())
|
helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC());
|
||||||
|
helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC());
|
||||||
|
helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC());
|
||||||
|
helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC());
|
||||||
|
helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC());
|
||||||
|
helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC());
|
||||||
#else
|
#else
|
||||||
MSA_ST_DF(DF_BYTE, b, cpu_stb_data)
|
helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC());
|
||||||
MSA_ST_DF(DF_HALF, h, cpu_stw_data)
|
helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC());
|
||||||
MSA_ST_DF(DF_WORD, w, cpu_stl_data)
|
helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC());
|
||||||
MSA_ST_DF(DF_DOUBLE, d, cpu_stq_data)
|
helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC());
|
||||||
|
helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC());
|
||||||
|
helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC());
|
||||||
|
helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC());
|
||||||
|
helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC());
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
#if !defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]);
|
||||||
|
cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]);
|
||||||
|
cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]);
|
||||||
|
cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]);
|
||||||
|
cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]);
|
||||||
|
cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]);
|
||||||
|
cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]);
|
||||||
|
cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]);
|
||||||
|
#else
|
||||||
|
cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]);
|
||||||
|
cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]);
|
||||||
|
cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]);
|
||||||
|
cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]);
|
||||||
|
cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]);
|
||||||
|
cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]);
|
||||||
|
cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]);
|
||||||
|
cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
|
||||||
|
target_ulong addr)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
int mmu_idx = cpu_mmu_index(env, false);
|
||||||
|
|
||||||
|
MEMOP_IDX(DF_WORD)
|
||||||
|
ensure_writable_pages(env, addr, mmu_idx, GETPC());
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
#if !defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
helper_ret_stl_mmu(env, addr + (0 << DF_WORD), oi, GETPC(), pwd->w[0]);
|
||||||
|
helper_ret_stl_mmu(env, addr + (1 << DF_WORD), oi, GETPC(), pwd->w[1]);
|
||||||
|
helper_ret_stl_mmu(env, addr + (2 << DF_WORD), oi, GETPC(), pwd->w[2]);
|
||||||
|
helper_ret_stl_mmu(env, addr + (3 << DF_WORD), oi, GETPC(), pwd->w[3]);
|
||||||
|
#else
|
||||||
|
helper_ret_stl_mmu(env, addr + (1 << DF_WORD), oi, GETPC(), pwd->w[0]);
|
||||||
|
helper_ret_stl_mmu(env, addr + (0 << DF_WORD), oi, GETPC(), pwd->w[1]);
|
||||||
|
helper_ret_stl_mmu(env, addr + (3 << DF_WORD), oi, GETPC(), pwd->w[2]);
|
||||||
|
helper_ret_stl_mmu(env, addr + (2 << DF_WORD), oi, GETPC(), pwd->w[3]);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if !defined(HOST_WORDS_BIGENDIAN)
|
||||||
|
cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[0]);
|
||||||
|
cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[1]);
|
||||||
|
cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[2]);
|
||||||
|
cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[3]);
|
||||||
|
#else
|
||||||
|
cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[0]);
|
||||||
|
cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[1]);
|
||||||
|
cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[2]);
|
||||||
|
cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[3]);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper_msa_st_d(CPUMIPSState *env, uint32_t wd,
|
||||||
|
target_ulong addr)
|
||||||
|
{
|
||||||
|
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
|
||||||
|
int mmu_idx = cpu_mmu_index(env, false);
|
||||||
|
|
||||||
|
MEMOP_IDX(DF_DOUBLE)
|
||||||
|
ensure_writable_pages(env, addr, mmu_idx, GETPC());
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
helper_ret_stq_mmu(env, addr + (0 << DF_DOUBLE), pwd->d[0], oi, GETPC());
|
||||||
|
helper_ret_stq_mmu(env, addr + (1 << DF_DOUBLE), pwd->d[1], oi, GETPC());
|
||||||
|
#else
|
||||||
|
cpu_stq_data(env, addr + (0 << DF_DOUBLE), pwd->d[0]);
|
||||||
|
cpu_stq_data(env, addr + (1 << DF_DOUBLE), pwd->d[1]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op)
|
void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28297,20 +28297,73 @@ static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
|
||||||
generate_exception_end(ctx, EXCP_RI);
|
generate_exception_end(ctx, EXCP_RI);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
|
||||||
|
(df == DF_WORD)) {
|
||||||
|
generate_exception_end(ctx, EXCP_RI);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
switch (MASK_MSA_ELM(ctx->opcode)) {
|
switch (MASK_MSA_ELM(ctx->opcode)) {
|
||||||
case OPC_COPY_S_df:
|
case OPC_COPY_S_df:
|
||||||
if (likely(wd != 0)) {
|
if (likely(wd != 0)) {
|
||||||
gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
|
switch (df) {
|
||||||
|
case DF_BYTE:
|
||||||
|
gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
case DF_HALF:
|
||||||
|
gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
case DF_WORD:
|
||||||
|
gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
#if defined(TARGET_MIPS64)
|
||||||
|
case DF_DOUBLE:
|
||||||
|
gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPC_COPY_U_df:
|
case OPC_COPY_U_df:
|
||||||
if (likely(wd != 0)) {
|
if (likely(wd != 0)) {
|
||||||
gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
|
switch (df) {
|
||||||
|
case DF_BYTE:
|
||||||
|
gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
case DF_HALF:
|
||||||
|
gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
#if defined(TARGET_MIPS64)
|
||||||
|
case DF_WORD:
|
||||||
|
gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPC_INSERT_df:
|
case OPC_INSERT_df:
|
||||||
gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
|
switch (df) {
|
||||||
|
case DF_BYTE:
|
||||||
|
gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
case DF_HALF:
|
||||||
|
gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
case DF_WORD:
|
||||||
|
gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
#if defined(TARGET_MIPS64)
|
||||||
|
case DF_DOUBLE:
|
||||||
|
gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
# Functional test that boots a VM and run commands via a SSH session
|
||||||
|
#
|
||||||
|
# Copyright (c) Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||||
|
#
|
||||||
|
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||||
|
# later. See the COPYING file in the top-level directory.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import base64
|
||||||
|
import logging
|
||||||
|
import paramiko
|
||||||
|
import time
|
||||||
|
|
||||||
|
from avocado import skipIf
|
||||||
|
from avocado_qemu import Test
|
||||||
|
from avocado.utils import process
|
||||||
|
from avocado.utils import archive
|
||||||
|
|
||||||
|
|
||||||
|
class LinuxSSH(Test):
|
||||||
|
|
||||||
|
timeout = 150 # Not for 'configure --enable-debug --enable-debug-tcg'
|
||||||
|
|
||||||
|
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 '
|
||||||
|
VM_IP = '127.0.0.1'
|
||||||
|
|
||||||
|
IMAGE_INFO = {
|
||||||
|
'be': {
|
||||||
|
'image_url': 'https://people.debian.org/~aurel32/qemu/mips/'
|
||||||
|
'debian_wheezy_mips_standard.qcow2',
|
||||||
|
'image_hash': '8987a63270df67345b2135a6b7a4885a35e392d5',
|
||||||
|
'rsa_hostkey': b'AAAAB3NzaC1yc2EAAAADAQABAAABAQCca1VitiyLAdQOld'
|
||||||
|
b'zT43IOEVJZ0wHD78GJi8wDAjMiYWUzNSSn0rXGQsINHuH5'
|
||||||
|
b'IlF+kBZsHinb/FtKCAyS9a8uCHhQI4SuB4QhAb0+39MlUw'
|
||||||
|
b'Mm0CLkctgM2eUUZ6MQMQvDlqnue6CCkxN62EZYbaxmby7j'
|
||||||
|
b'CQa1125o1HRKBvdGm2zrJWxXAfA+f1v6jHLyE8Jnu83eQ+'
|
||||||
|
b'BFY25G+Vzx1PVc3zQBwJ8r0NGTRqy2//oWQP0h+bMsgeFe'
|
||||||
|
b'KH/J3RJM22vg6+I4JAdBFcxnK+l781h1FuRxOn4O/Xslbg'
|
||||||
|
b'go6WtB4V4TOsw2E/KfxI5IZ/icxF+swVcnvF46Hf3uQc/0'
|
||||||
|
b'BBqb',
|
||||||
|
},
|
||||||
|
'le': {
|
||||||
|
'image_url': 'https://people.debian.org/~aurel32/qemu/mipsel/'
|
||||||
|
'debian_wheezy_mipsel_standard.qcow2',
|
||||||
|
'image_hash': '7866764d9de3ef536ffca24c9fb9f04ffdb45802',
|
||||||
|
'rsa_hostkey': b'AAAAB3NzaC1yc2EAAAADAQABAAABAQClXJlBT71HL5yKvv'
|
||||||
|
b'gfC7jmxSWx5zSBCzET6CLZczwAafSIs7YKfNOy/dQTxhuk'
|
||||||
|
b'yIGFUugZFoF3E9PzdhunuyvyTd56MPoNIqFbb5rGokwU5I'
|
||||||
|
b'TOx3dBHZR0mClypL6MVrwe0bsiIb8GhF1zioNwcsaAZnAi'
|
||||||
|
b'KfXStVDtXvn/kLLq+xLABYt48CC5KYWoFaCoICskLAY+qo'
|
||||||
|
b'L+LWyAnQisj4jAH8VSaSKIImFpfkHWEXPhHcC4ZBlDKtnH'
|
||||||
|
b'po9vhfCHgnfW3Pzrqmk8BI4HysqPFVmJWkJGlGUL+sGeg3'
|
||||||
|
b'ZZolAYuDXGuBrw8ooPJq2v2dOH+z6dyD2q/ypmAbyPqj5C'
|
||||||
|
b'rc8H',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def wait_for_console_pattern(self, success_message,
|
||||||
|
failure_message='Oops'):
|
||||||
|
console = self.vm.console_socket.makefile()
|
||||||
|
console_logger = logging.getLogger('console')
|
||||||
|
while True:
|
||||||
|
msg = console.readline()
|
||||||
|
console_logger.debug(msg.strip())
|
||||||
|
if success_message in msg:
|
||||||
|
break
|
||||||
|
if failure_message in msg:
|
||||||
|
fail = 'Failure message found in console: %s' % failure_message
|
||||||
|
self.fail(fail)
|
||||||
|
|
||||||
|
def get_portfwd(self):
|
||||||
|
res = self.vm.command('human-monitor-command',
|
||||||
|
command_line='info usernet')
|
||||||
|
line = res.split('\r\n')[2]
|
||||||
|
port = re.split(r'.*TCP.HOST_FORWARD.*127\.0\.0\.1 (\d+)\s+10\..*',
|
||||||
|
line)[1]
|
||||||
|
self.log.debug("sshd listening on port:" + port)
|
||||||
|
return port
|
||||||
|
|
||||||
|
def ssh_connect(self, username, password, rsa_hostkey_b64=None):
|
||||||
|
self.ssh_logger = logging.getLogger('ssh')
|
||||||
|
self.ssh_username = username
|
||||||
|
self.ssh_ps1 = '# ' if username is 'root' else '$ '
|
||||||
|
self.ssh_client = paramiko.SSHClient()
|
||||||
|
port = self.get_portfwd()
|
||||||
|
if rsa_hostkey_b64:
|
||||||
|
rsa_hostkey_bin = base64.b64decode(rsa_hostkey_b64)
|
||||||
|
rsa_hostkey = paramiko.RSAKey(data = rsa_hostkey_bin)
|
||||||
|
ipport = '[%s]:%s' % (self.VM_IP, port)
|
||||||
|
self.ssh_logger.debug('ipport ' + ipport)
|
||||||
|
self.ssh_client.get_host_keys().add(ipport, 'ssh-rsa', rsa_hostkey)
|
||||||
|
for i in range(10):
|
||||||
|
try:
|
||||||
|
self.ssh_client.connect(self.VM_IP, int(port),
|
||||||
|
username, password, banner_timeout=90)
|
||||||
|
self.ssh_logger.info("Entering interactive session.")
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
time.sleep(4)
|
||||||
|
pass
|
||||||
|
self.fail("sshd timeout")
|
||||||
|
|
||||||
|
def ssh_disconnect_vm(self):
|
||||||
|
self.ssh_client.close()
|
||||||
|
|
||||||
|
def ssh_command(self, command, is_root=True):
|
||||||
|
self.ssh_logger.info(self.ssh_ps1 + command)
|
||||||
|
stdin, stdout, stderr = self.ssh_client.exec_command(command)
|
||||||
|
stdout_lines = [line.strip('\n') for line in stdout]
|
||||||
|
for line in stdout_lines:
|
||||||
|
self.ssh_logger.info(line)
|
||||||
|
stderr_lines = [line.strip('\n') for line in stderr]
|
||||||
|
for line in stderr_lines:
|
||||||
|
self.ssh_logger.warning(line)
|
||||||
|
return stdout_lines, stderr_lines
|
||||||
|
|
||||||
|
def boot_debian_wheezy_image_and_ssh_login(self, endianess, kernel_path):
|
||||||
|
image_url = self.IMAGE_INFO[endianess]['image_url']
|
||||||
|
image_hash = self.IMAGE_INFO[endianess]['image_hash']
|
||||||
|
image_path = self.fetch_asset(image_url, asset_hash=image_hash)
|
||||||
|
rsa_hostkey_b64 = self.IMAGE_INFO[endianess]['rsa_hostkey']
|
||||||
|
|
||||||
|
self.vm.set_machine('malta')
|
||||||
|
self.vm.set_console()
|
||||||
|
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE
|
||||||
|
+ 'console=ttyS0 root=/dev/sda1')
|
||||||
|
self.vm.add_args('-no-reboot',
|
||||||
|
'-kernel', kernel_path,
|
||||||
|
'-append', kernel_command_line,
|
||||||
|
'-hda', image_path,
|
||||||
|
'-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22',
|
||||||
|
'-device', 'pcnet,netdev=vnet')
|
||||||
|
self.vm.launch()
|
||||||
|
|
||||||
|
self.log.info('VM launched, waiting for sshd')
|
||||||
|
console_pattern = 'Starting OpenBSD Secure Shell server: sshd'
|
||||||
|
self.wait_for_console_pattern(console_pattern)
|
||||||
|
self.log.info('sshd ready')
|
||||||
|
|
||||||
|
self.ssh_connect('root', 'root', rsa_hostkey_b64=rsa_hostkey_b64)
|
||||||
|
|
||||||
|
def shutdown_via_ssh(self):
|
||||||
|
self.ssh_command('poweroff')
|
||||||
|
self.ssh_disconnect_vm()
|
||||||
|
self.wait_for_console_pattern('Power down')
|
||||||
|
|
||||||
|
def run_common_commands(self):
|
||||||
|
stdout, stderr = self.ssh_command('lspci -d 11ab:4620')
|
||||||
|
self.assertIn(True, ["GT-64120" in line for line in stdout])
|
||||||
|
|
||||||
|
stdout, stderr = self.ssh_command('cat /sys/bus/i2c/devices/i2c-0/name')
|
||||||
|
self.assertIn(True, ["SMBus PIIX4 adapter" in line
|
||||||
|
for line in stdout])
|
||||||
|
|
||||||
|
stdout, stderr = self.ssh_command('cat /proc/mtd')
|
||||||
|
self.assertIn(True, ["YAMON" in line
|
||||||
|
for line in stdout])
|
||||||
|
|
||||||
|
# Empty 'Board Config'
|
||||||
|
stdout, stderr = self.ssh_command('md5sum /dev/mtd2ro')
|
||||||
|
self.assertIn(True, ["0dfbe8aa4c20b52e1b8bf3cb6cbdf193" in line
|
||||||
|
for line in stdout])
|
||||||
|
|
||||||
|
def do_test_mips_malta(self, endianess, kernel_path, uname_m):
|
||||||
|
self.boot_debian_wheezy_image_and_ssh_login(endianess, kernel_path)
|
||||||
|
|
||||||
|
stdout, stderr = self.ssh_command('uname -a')
|
||||||
|
self.assertIn(True, [uname_m + " GNU/Linux" in line for line in stdout])
|
||||||
|
|
||||||
|
self.run_common_commands()
|
||||||
|
self.shutdown_via_ssh()
|
||||||
|
|
||||||
|
@skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI')
|
||||||
|
def test_mips_malta32eb_kernel3_2_0(self):
|
||||||
|
"""
|
||||||
|
:avocado: tags=arch:mips
|
||||||
|
:avocado: tags=machine:malta
|
||||||
|
:avocado: tags=endian:big
|
||||||
|
:avocado: tags=device:pcnet32
|
||||||
|
"""
|
||||||
|
kernel_url = ('https://people.debian.org/~aurel32/qemu/mips/'
|
||||||
|
'vmlinux-3.2.0-4-4kc-malta')
|
||||||
|
kernel_hash = '592e384a4edc16dade52a6cd5c785c637bcbc9ad'
|
||||||
|
kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
|
||||||
|
|
||||||
|
self.do_test_mips_malta('be', kernel_path, 'mips')
|
||||||
|
|
||||||
|
@skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI')
|
||||||
|
def test_mips_malta32el_kernel3_2_0(self):
|
||||||
|
"""
|
||||||
|
:avocado: tags=arch:mipsel
|
||||||
|
:avocado: tags=machine:malta
|
||||||
|
:avocado: tags=endian:little
|
||||||
|
:avocado: tags=device:pcnet32
|
||||||
|
"""
|
||||||
|
kernel_url = ('https://people.debian.org/~aurel32/qemu/mipsel/'
|
||||||
|
'vmlinux-3.2.0-4-4kc-malta')
|
||||||
|
kernel_hash = 'a66bea5a8adaa2cb3d36a1d4e0ccdb01be8f6c2a'
|
||||||
|
kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
|
||||||
|
|
||||||
|
self.do_test_mips_malta('le', kernel_path, 'mips')
|
||||||
|
|
||||||
|
@skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI')
|
||||||
|
def test_mips_malta64eb_kernel3_2_0(self):
|
||||||
|
"""
|
||||||
|
:avocado: tags=arch:mips64
|
||||||
|
:avocado: tags=machine:malta
|
||||||
|
:avocado: tags=endian:big
|
||||||
|
:avocado: tags=device:pcnet32
|
||||||
|
"""
|
||||||
|
kernel_url = ('https://people.debian.org/~aurel32/qemu/mips/'
|
||||||
|
'vmlinux-3.2.0-4-5kc-malta')
|
||||||
|
kernel_hash = 'db6eea7de35d36c77d8c165b6bcb222e16eb91db'
|
||||||
|
kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
|
||||||
|
self.do_test_mips_malta('be', kernel_path, 'mips64')
|
||||||
|
|
||||||
|
@skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI')
|
||||||
|
def test_mips_malta64el_kernel3_2_0(self):
|
||||||
|
"""
|
||||||
|
:avocado: tags=arch:mips64el
|
||||||
|
:avocado: tags=machine:malta
|
||||||
|
:avocado: tags=endian:little
|
||||||
|
:avocado: tags=device:pcnet32
|
||||||
|
"""
|
||||||
|
kernel_url = ('https://people.debian.org/~aurel32/qemu/mipsel/'
|
||||||
|
'vmlinux-3.2.0-4-5kc-malta')
|
||||||
|
kernel_hash = '6a7f77245acf231415a0e8b725d91ed2f3487794'
|
||||||
|
kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
|
||||||
|
self.do_test_mips_malta('le', kernel_path, 'mips64')
|
|
@ -2,3 +2,4 @@
|
||||||
# in the tests/venv Python virtual environment. For more info,
|
# in the tests/venv Python virtual environment. For more info,
|
||||||
# refer to: https://pip.pypa.io/en/stable/user_guide/#id1
|
# refer to: https://pip.pypa.io/en/stable/user_guide/#id1
|
||||||
avocado-framework==68.0
|
avocado-framework==68.0
|
||||||
|
paramiko
|
||||||
|
|
Loading…
Reference in New Issue