diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2019-05-28 12:25:20 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-05-28 12:25:20 +0100 |
commit | 4a1d38c44089f4e7bbbc924a830f30ca0119a7dd (patch) | |
tree | 995221cc5913acbb7b05e1d36872d2a044efacca | |
parent | 4bade28288b12a6268d2e1fc2e4fa1f77ccb1d89 (diff) | |
parent | c47c336e870585307f1e2371ea85a6256a05022e (diff) | |
download | qemu-4a1d38c44089f4e7bbbc924a830f30ca0119a7dd.zip qemu-4a1d38c44089f4e7bbbc924a830f30ca0119a7dd.tar.gz qemu-4a1d38c44089f4e7bbbc924a830f30ca0119a7dd.tar.bz2 |
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>
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | linux-user/syscall.c | 24 | ||||
-rw-r--r-- | target/mips/cpu.h | 209 | ||||
-rw-r--r-- | target/mips/helper.c | 13 | ||||
-rw-r--r-- | target/mips/helper.h | 16 | ||||
-rw-r--r-- | target/mips/msa_helper.c | 191 | ||||
-rw-r--r-- | target/mips/op_helper.c | 388 | ||||
-rw-r--r-- | target/mips/translate.c | 59 | ||||
-rw-r--r-- | tests/acceptance/linux_ssh_mips_malta.py | 230 | ||||
-rw-r--r-- | tests/requirements.txt | 1 |
10 files changed, 922 insertions, 210 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 3cacd75..8c34d5c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -934,6 +934,7 @@ M: Aurelien Jarno <aurelien@aurel32.net> R: Aleksandar Rikalo <arikalo@wavecomp.com> S: Maintained F: hw/mips/mips_malta.c +F: tests/acceptance/linux_ssh_mips_malta.py Mipssim M: Aleksandar Markovic <amarkovic@wavecomp.com> diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5521258..5e29e67 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -763,14 +763,7 @@ safe_syscall2(int, nanosleep, const struct timespec *, req, safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags, const struct timespec *, req, struct timespec *, rem) #endif -#ifdef __NR_msgsnd -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 +#if !defined(__NR_msgsnd) || !defined(__NR_msgrcv) || !defined(__NR_semtimedop) /* This host kernel architecture uses a single ipc syscall; fake up * wrappers for the sub-operations to hide this implementation detail. * 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, 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) { 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) { 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, const struct timespec *timeout) { diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 1f41cf6..06a8ed4 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -22,10 +22,10 @@ typedef struct CPUMIPSTLBContext CPUMIPSTLBContext; typedef union wr_t wr_t; union wr_t { - int8_t b[MSA_WRLEN/8]; - int16_t h[MSA_WRLEN/16]; - int32_t w[MSA_WRLEN/32]; - int64_t d[MSA_WRLEN/64]; + int8_t b[MSA_WRLEN / 8]; + int16_t h[MSA_WRLEN / 16]; + int32_t w[MSA_WRLEN / 32]; + int64_t d[MSA_WRLEN / 64]; }; typedef union fpr_t fpr_t; @@ -37,7 +37,8 @@ union fpr_t { /* FPU/MSA register mapping is not tested on big-endian hosts. */ 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 */ #if defined(HOST_WORDS_BIGENDIAN) @@ -71,16 +72,29 @@ struct CPUMIPSFPUContext { #define FCR31_FS 24 #define FCR31_ABS2008 19 #define FCR31_NAN2008 18 -#define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (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 SET_FP_COND(num, env) do { ((env).fcr31) |= \ + ((num) ? (1 << ((num) + 24)) : \ + (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_ENABLE(reg) (((reg) >> 7) & 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_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 SET_FP_CAUSE(reg, v) do { (reg) = ((reg) & ~(0x3f << 12)) | \ + ((v & 0x3f) << 12); \ + } 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_UNDERFLOW 2 #define FP_OVERFLOW 4 @@ -95,25 +109,25 @@ struct CPUMIPSFPUContext { typedef struct CPUMIPSMVPContext CPUMIPSMVPContext; struct CPUMIPSMVPContext { int32_t CP0_MVPControl; -#define CP0MVPCo_CPA 3 -#define CP0MVPCo_STLB 2 -#define CP0MVPCo_VPC 1 -#define CP0MVPCo_EVP 0 +#define CP0MVPCo_CPA 3 +#define CP0MVPCo_STLB 2 +#define CP0MVPCo_VPC 1 +#define CP0MVPCo_EVP 0 int32_t CP0_MVPConf0; -#define CP0MVPC0_M 31 -#define CP0MVPC0_TLBS 29 -#define CP0MVPC0_GS 28 -#define CP0MVPC0_PCP 27 -#define CP0MVPC0_PTLBE 16 -#define CP0MVPC0_TCA 15 -#define CP0MVPC0_PVPE 10 -#define CP0MVPC0_PTC 0 +#define CP0MVPC0_M 31 +#define CP0MVPC0_TLBS 29 +#define CP0MVPC0_GS 28 +#define CP0MVPC0_PCP 27 +#define CP0MVPC0_PTLBE 16 +#define CP0MVPC0_TCA 15 +#define CP0MVPC0_PVPE 10 +#define CP0MVPC0_PTC 0 int32_t CP0_MVPConf1; -#define CP0MVPC1_CIM 31 -#define CP0MVPC1_CIF 30 -#define CP0MVPC1_PCX 20 -#define CP0MVPC1_PCP2 10 -#define CP0MVPC1_PCP1 0 +#define CP0MVPC1_CIM 31 +#define CP0MVPC1_CIF 30 +#define CP0MVPC1_PCX 20 +#define CP0MVPC1_PCP2 10 +#define CP0MVPC1_PCP1 0 }; typedef struct mips_def_t mips_def_t; @@ -481,44 +495,44 @@ struct CPUMIPSState { */ int32_t CP0_Random; int32_t CP0_VPEControl; -#define CP0VPECo_YSI 21 -#define CP0VPECo_GSI 20 -#define CP0VPECo_EXCPT 16 -#define CP0VPECo_TE 15 -#define CP0VPECo_TargTC 0 +#define CP0VPECo_YSI 21 +#define CP0VPECo_GSI 20 +#define CP0VPECo_EXCPT 16 +#define CP0VPECo_TE 15 +#define CP0VPECo_TargTC 0 int32_t CP0_VPEConf0; -#define CP0VPEC0_M 31 -#define CP0VPEC0_XTC 21 -#define CP0VPEC0_TCS 19 -#define CP0VPEC0_SCS 18 -#define CP0VPEC0_DSC 17 -#define CP0VPEC0_ICS 16 -#define CP0VPEC0_MVP 1 -#define CP0VPEC0_VPA 0 +#define CP0VPEC0_M 31 +#define CP0VPEC0_XTC 21 +#define CP0VPEC0_TCS 19 +#define CP0VPEC0_SCS 18 +#define CP0VPEC0_DSC 17 +#define CP0VPEC0_ICS 16 +#define CP0VPEC0_MVP 1 +#define CP0VPEC0_VPA 0 int32_t CP0_VPEConf1; -#define CP0VPEC1_NCX 20 -#define CP0VPEC1_NCP2 10 -#define CP0VPEC1_NCP1 0 +#define CP0VPEC1_NCX 20 +#define CP0VPEC1_NCP2 10 +#define CP0VPEC1_NCP1 0 target_ulong CP0_YQMask; target_ulong CP0_VPESchedule; target_ulong CP0_VPEScheFBack; int32_t CP0_VPEOpt; -#define CP0VPEOpt_IWX7 15 -#define CP0VPEOpt_IWX6 14 -#define CP0VPEOpt_IWX5 13 -#define CP0VPEOpt_IWX4 12 -#define CP0VPEOpt_IWX3 11 -#define CP0VPEOpt_IWX2 10 -#define CP0VPEOpt_IWX1 9 -#define CP0VPEOpt_IWX0 8 -#define CP0VPEOpt_DWX7 7 -#define CP0VPEOpt_DWX6 6 -#define CP0VPEOpt_DWX5 5 -#define CP0VPEOpt_DWX4 4 -#define CP0VPEOpt_DWX3 3 -#define CP0VPEOpt_DWX2 2 -#define CP0VPEOpt_DWX1 1 -#define CP0VPEOpt_DWX0 0 +#define CP0VPEOpt_IWX7 15 +#define CP0VPEOpt_IWX6 14 +#define CP0VPEOpt_IWX5 13 +#define CP0VPEOpt_IWX4 12 +#define CP0VPEOpt_IWX3 11 +#define CP0VPEOpt_IWX2 10 +#define CP0VPEOpt_IWX1 9 +#define CP0VPEOpt_IWX0 8 +#define CP0VPEOpt_DWX7 7 +#define CP0VPEOpt_DWX6 6 +#define CP0VPEOpt_DWX5 5 +#define CP0VPEOpt_DWX4 4 +#define CP0VPEOpt_DWX3 3 +#define CP0VPEOpt_DWX2 2 +#define CP0VPEOpt_DWX1 1 +#define CP0VPEOpt_DWX0 0 /* * CP0 Register 2 */ @@ -625,33 +639,33 @@ struct CPUMIPSState { #define CP0PC_PSN 0 /* 5..0 */ int32_t CP0_SRSConf0_rw_bitmask; int32_t CP0_SRSConf0; -#define CP0SRSC0_M 31 -#define CP0SRSC0_SRS3 20 -#define CP0SRSC0_SRS2 10 -#define CP0SRSC0_SRS1 0 +#define CP0SRSC0_M 31 +#define CP0SRSC0_SRS3 20 +#define CP0SRSC0_SRS2 10 +#define CP0SRSC0_SRS1 0 int32_t CP0_SRSConf1_rw_bitmask; int32_t CP0_SRSConf1; -#define CP0SRSC1_M 31 -#define CP0SRSC1_SRS6 20 -#define CP0SRSC1_SRS5 10 -#define CP0SRSC1_SRS4 0 +#define CP0SRSC1_M 31 +#define CP0SRSC1_SRS6 20 +#define CP0SRSC1_SRS5 10 +#define CP0SRSC1_SRS4 0 int32_t CP0_SRSConf2_rw_bitmask; int32_t CP0_SRSConf2; -#define CP0SRSC2_M 31 -#define CP0SRSC2_SRS9 20 -#define CP0SRSC2_SRS8 10 -#define CP0SRSC2_SRS7 0 +#define CP0SRSC2_M 31 +#define CP0SRSC2_SRS9 20 +#define CP0SRSC2_SRS8 10 +#define CP0SRSC2_SRS7 0 int32_t CP0_SRSConf3_rw_bitmask; int32_t CP0_SRSConf3; -#define CP0SRSC3_M 31 -#define CP0SRSC3_SRS12 20 -#define CP0SRSC3_SRS11 10 -#define CP0SRSC3_SRS10 0 +#define CP0SRSC3_M 31 +#define CP0SRSC3_SRS12 20 +#define CP0SRSC3_SRS11 10 +#define CP0SRSC3_SRS10 0 int32_t CP0_SRSConf4_rw_bitmask; int32_t CP0_SRSConf4; -#define CP0SRSC4_SRS15 20 -#define CP0SRSC4_SRS14 10 -#define CP0SRSC4_SRS13 0 +#define CP0SRSC4_SRS15 20 +#define CP0SRSC4_SRS14 10 +#define CP0SRSC4_SRS13 0 /* * CP0 Register 7 */ @@ -963,9 +977,11 @@ struct CPUMIPSState { /* TMASK defines different execution modes */ #define MIPS_HFLAG_TMASK 0x1F5807FF #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 bits as the value of mmu_idx. */ + /* + * 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 bits as the value of mmu_idx. + */ #define MIPS_HFLAG_KSU 0x00003 /* kernel/supervisor/user mode mask */ #define MIPS_HFLAG_UM 0x00002 /* user 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_FPU 0x00020 /* 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 - and RSQRT.D. */ + /* + * True if the MIPS IV COP1X instructions can be used. This also + * 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_RE 0x00100 /* Reversed endianness */ #define MIPS_HFLAG_AWRAP 0x00200 /* 32-bit compatibility address wrapping */ #define MIPS_HFLAG_M16 0x00400 /* MIPS16 mode flag */ #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 * 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_B 0x00800 /* Unconditional 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 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_MODE1_SUFFIX _super #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); } #include "exec/cpu-all.h" -/* Memory access type : +/* + * Memory access type : * may be needed for precise access rights control and precise exceptions. */ enum { @@ -1182,7 +1205,7 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level); void itc_reconfigure(struct MIPSITUState *tag); /* 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) { diff --git a/target/mips/helper.c b/target/mips/helper.c index 9799f2e..68e44df 100644 --- a/target/mips/helper.c +++ b/target/mips/helper.c @@ -43,7 +43,7 @@ int no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type) { *physical = address; - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return TLBRET_MATCH; } @@ -61,7 +61,7 @@ int fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, else *physical = address; - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return TLBRET_MATCH; } @@ -101,6 +101,9 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, *prot = PAGE_READ; if (n ? tlb->D1 : tlb->D0) *prot |= PAGE_WRITE; + if (!(n ? tlb->XI1 : tlb->XI0)) { + *prot |= PAGE_EXEC; + } return TLBRET_MATCH; } return TLBRET_DIRTY; @@ -182,7 +185,7 @@ static int get_seg_physical_address(CPUMIPSState *env, hwaddr *physical, } else { /* The segment is unmapped */ *physical = physical_base | (real_address & segmask); - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return TLBRET_MATCH; } } @@ -907,7 +910,7 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } if (ret == TLBRET_MATCH) { 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); return true; } @@ -927,7 +930,7 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, access_type, mips_access_type, mmu_idx); if (ret == TLBRET_MATCH) { 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); return true; } diff --git a/target/mips/helper.h b/target/mips/helper.h index a6d687e..2863f60 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -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_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_3(msa_ctcmsa, void, env, tl, 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_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_ftrunc_s_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32) diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index c74e3cd..ee1b1fa 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -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) { 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) { uint64_t u_arg1 = UNSIGNED(arg1, 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) @@ -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) { 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) { uint64_t u_arg1 = UNSIGNED(arg1, 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) \ @@ -1248,78 +1249,152 @@ void helper_msa_splati_df(CPUMIPSState *env, uint32_t df, uint32_t wd, msa_splat_df(df, pwd, pws, n); } -void helper_msa_copy_s_df(CPUMIPSState *env, uint32_t df, uint32_t rd, - uint32_t ws, uint32_t n) +void helper_msa_copy_s_b(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) { - n %= DF_ELEMENTS(df); + 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] = (int8_t)env->active_fpu.fpr[ws].wr.b[n]; +} - switch (df) { - case DF_BYTE: - env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n]; - break; - 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; +void helper_msa_copy_s_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 - default: - assert(0); + env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n]; +} + +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_u_df(CPUMIPSState *env, uint32_t df, uint32_t rd, - uint32_t ws, uint32_t n) +void helper_msa_copy_s_d(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) { - n %= DF_ELEMENTS(df); + n %= 2; + env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n]; +} - switch (df) { - case DF_BYTE: - env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n]; - break; - 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; +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 - default: - assert(0); + 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_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +void helper_msa_insert_b(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 %= 16; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 8) { + n = 8 - n - 1; + } else { + n = 24 - n - 1; + } +#endif + pwd->b[n] = (int8_t)rs; +} - switch (df) { - case DF_BYTE: - pwd->b[n] = (int8_t)rs; - break; - case DF_HALF: - 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); +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, diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 6d86912..3918027 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -4356,31 +4356,179 @@ FOP_CONDN_S(sne, (float32_lt(fst1, fst0, &env->active_fpu.fp_status) #define MEMOP_IDX(DF) #endif -#define MSA_LD_DF(DF, TYPE, LD_INSN, ...) \ -void helper_msa_ld_ ## TYPE(CPUMIPSState *env, uint32_t wd, \ - target_ulong addr) \ -{ \ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ - wr_t wx; \ - int i; \ - MEMOP_IDX(DF) \ - for (i = 0; i < DF_ELEMENTS(DF); i++) { \ - wx.TYPE[i] = LD_INSN(env, addr + (i << DF), ##__VA_ARGS__); \ - } \ - memcpy(pwd, &wx, sizeof(wr_t)); \ +void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_BYTE) +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); + pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); + 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()); + 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(HOST_WORDS_BIGENDIAN) + pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC()); + pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), 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 + pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC()); + pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC()); + pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC()); + 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 +#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) -MSA_LD_DF(DF_BYTE, b, helper_ret_ldub_mmu, oi, GETPC()) -MSA_LD_DF(DF_HALF, h, helper_ret_lduw_mmu, oi, GETPC()) -MSA_LD_DF(DF_WORD, w, helper_ret_ldul_mmu, oi, GETPC()) -MSA_LD_DF(DF_DOUBLE, d, helper_ret_ldq_mmu, oi, GETPC()) +#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 -MSA_LD_DF(DF_BYTE, b, cpu_ldub_data) -MSA_LD_DF(DF_HALF, h, cpu_lduw_data) -MSA_LD_DF(DF_WORD, w, cpu_ldl_data) -MSA_LD_DF(DF_DOUBLE, d, cpu_ldq_data) + 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) \ ((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN/8 - 1) >= TARGET_PAGE_SIZE) @@ -4402,31 +4550,191 @@ static inline void ensure_writable_pages(CPUMIPSState *env, #endif } -#define MSA_ST_DF(DF, TYPE, ST_INSN, ...) \ -void helper_msa_st_ ## TYPE(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); \ - int i; \ - MEMOP_IDX(DF) \ - ensure_writable_pages(env, addr, mmu_idx, GETPC()); \ - for (i = 0; i < DF_ELEMENTS(DF); i++) { \ - ST_INSN(env, addr + (i << DF), pwd->TYPE[i], ##__VA_ARGS__); \ - } \ +void helper_msa_st_b(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_BYTE) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + 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(HOST_WORDS_BIGENDIAN) + helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], 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 + helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC()); + 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 +#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) -MSA_ST_DF(DF_BYTE, b, helper_ret_stb_mmu, oi, GETPC()) -MSA_ST_DF(DF_HALF, h, helper_ret_stw_mmu, oi, GETPC()) -MSA_ST_DF(DF_WORD, w, helper_ret_stl_mmu, oi, GETPC()) -MSA_ST_DF(DF_DOUBLE, d, helper_ret_stq_mmu, oi, GETPC()) +#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 -MSA_ST_DF(DF_BYTE, b, cpu_stb_data) -MSA_ST_DF(DF_HALF, h, cpu_stw_data) -MSA_ST_DF(DF_WORD, w, cpu_stl_data) -MSA_ST_DF(DF_DOUBLE, d, cpu_stq_data) + 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) { diff --git a/target/mips/translate.c b/target/mips/translate.c index f96c0d0..dd706ad 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -28297,20 +28297,73 @@ static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df, generate_exception_end(ctx, EXCP_RI); break; } + if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) && + (df == DF_WORD)) { + generate_exception_end(ctx, EXCP_RI); + break; + } #endif switch (MASK_MSA_ELM(ctx->opcode)) { case OPC_COPY_S_df: 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; case OPC_COPY_U_df: 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; 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; diff --git a/tests/acceptance/linux_ssh_mips_malta.py b/tests/acceptance/linux_ssh_mips_malta.py new file mode 100644 index 0000000..aafb0c3 --- /dev/null +++ b/tests/acceptance/linux_ssh_mips_malta.py @@ -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') diff --git a/tests/requirements.txt b/tests/requirements.txt index 002ded6..3ae0e29 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -2,3 +2,4 @@ # in the tests/venv Python virtual environment. For more info, # refer to: https://pip.pypa.io/en/stable/user_guide/#id1 avocado-framework==68.0 +paramiko |