mirror of https://github.com/xemu-project/xemu.git
MIPS queue for October 2018, part 4
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJb1yMkAAoJENSXKoln91plSrUIAIp8e63jdI/YX8gIp0iEVZmJ +QDAfgTRc3/zvIFYie4A4mEnEj6c8iwmrvINalxQ+tZDtNcMLU8zI+0bz2YxwgiT 1YbVrhNPJxqx65YOqwEAQ/vjlCC3iVtTP6s6eKpR5MZRBLUWrkuEub6gDWpKxrK0 lfSRXS8Bj2gAOzefxeLIcFhBcV/z8hlRe7wxGpSjmPcJ36G3Bv28nyV+LbfmCsTb QekIrEUtxlSqNJbb1apZHP1754mKURc43KoH6ZdXWXQWj2RedARltIfVxbprR0bK huYwwSSl1fD7ltvJW1gXGYKdRABUbvTMeRsheA7YwGXlIjeQLOAnkwc8ZwQkidU= =A7R3 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-october-2018-part-4' into staging MIPS queue for October 2018, part 4 # gpg: Signature made Mon 29 Oct 2018 15:11:32 GMT # gpg: using RSA key D4972A8967F75A65 # gpg: Good signature from "Aleksandar Markovic <amarkovic@wavecomp.com>" # 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-october-2018-part-4: (27 commits) linux-user: Add prctl() PR_SET_FP_MODE and PR_GET_FP_MODE implementations linux-user: Determine the desired FPU mode from MIPS.abiflags linux-user: Read and set FP ABI value from MIPS abiflags linux-user: Extract MIPS abiflags from ELF file linux-user: Extend image_info struct with MIPS fp_abi and interp_fp_abi fields elf: Define MIPS_ABI_FP_UNKNOWN macro target/mips: Amend MXU ASE overview note target/mips: Move MXU_EN check one level higher target/mips: Add emulation of MXU instructions S32LDD and S32LDDR target/mips: Add emulation of MXU instructions Q8MUL and Q8MULSU target/mips: Add emulation of MXU instruction D16MAC target/mips: Add emulation of MXU instruction D16MUL target/mips: Add emulation of MXU instruction S8LDD target/mips: Move MUL, S32M2I, S32I2M handling out of main MXU switch target/mips: Add emulation of MXU instructions S32I2M and S32M2I target/mips: Add emulation of non-MXU MULL within MXU decoding engine target/mips: Add bit encoding for MXU operand getting pattern 'optn3' target/mips: Add bit encoding for MXU operand getting pattern 'optn2' target/mips: Add bit encoding for MXU execute add/sub pattern 'eptn2' target/mips: Add bit encoding for MXU accumulate add/sub 2-bit pattern 'aptn2' ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
0bbba1665c
|
@ -87,6 +87,8 @@ typedef int64_t Elf64_Sxword;
|
|||
#define EF_MIPS_MACH_LS3A 0x00a20000 /* ST Microelectronics Loongson 3A */
|
||||
#define EF_MIPS_MACH 0x00ff0000 /* EF_MIPS_MACH_xxx selection mask */
|
||||
|
||||
#define MIPS_ABI_FP_UNKNOWN (-1) /* Unknown FP ABI (internal) */
|
||||
|
||||
#define MIPS_ABI_FP_ANY 0x0 /* FP ABI doesn't matter */
|
||||
#define MIPS_ABI_FP_DOUBLE 0x1 /* -mdouble-float */
|
||||
#define MIPS_ABI_FP_SINGLE 0x2 /* -msingle-float */
|
||||
|
|
|
@ -1517,11 +1517,25 @@ static void bswap_sym(struct elf_sym *sym)
|
|||
bswaptls(&sym->st_size);
|
||||
bswap16s(&sym->st_shndx);
|
||||
}
|
||||
|
||||
#ifdef TARGET_MIPS
|
||||
static void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags)
|
||||
{
|
||||
bswap16s(&abiflags->version);
|
||||
bswap32s(&abiflags->ases);
|
||||
bswap32s(&abiflags->isa_ext);
|
||||
bswap32s(&abiflags->flags1);
|
||||
bswap32s(&abiflags->flags2);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
static inline void bswap_ehdr(struct elfhdr *ehdr) { }
|
||||
static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
|
||||
static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
|
||||
static inline void bswap_sym(struct elf_sym *sym) { }
|
||||
#ifdef TARGET_MIPS
|
||||
static inline void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) { }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_ELF_CORE_DUMP
|
||||
|
@ -2364,6 +2378,26 @@ static void load_elf_image(const char *image_name, int image_fd,
|
|||
goto exit_errmsg;
|
||||
}
|
||||
*pinterp_name = interp_name;
|
||||
#ifdef TARGET_MIPS
|
||||
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
|
||||
Mips_elf_abiflags_v0 abiflags;
|
||||
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
|
||||
errmsg = "Invalid PT_MIPS_ABIFLAGS entry";
|
||||
goto exit_errmsg;
|
||||
}
|
||||
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
|
||||
memcpy(&abiflags, bprm_buf + eppnt->p_offset,
|
||||
sizeof(Mips_elf_abiflags_v0));
|
||||
} else {
|
||||
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
|
||||
eppnt->p_offset);
|
||||
if (retval != sizeof(Mips_elf_abiflags_v0)) {
|
||||
goto exit_perror;
|
||||
}
|
||||
}
|
||||
bswap_mips_abiflags(&abiflags);
|
||||
info->fp_abi = abiflags.fp_abi;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2675,6 +2709,9 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
|
|||
target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
}
|
||||
#ifdef TARGET_MIPS
|
||||
info->interp_fp_abi = interp_info.fp_abi;
|
||||
#endif
|
||||
}
|
||||
|
||||
bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
|
||||
|
|
|
@ -740,6 +740,34 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
|
|||
struct image_info *info = ts->info;
|
||||
int i;
|
||||
|
||||
struct mode_req {
|
||||
bool single;
|
||||
bool soft;
|
||||
bool fr1;
|
||||
bool frdefault;
|
||||
bool fre;
|
||||
};
|
||||
|
||||
static const struct mode_req fpu_reqs[] = {
|
||||
[MIPS_ABI_FP_ANY] = { true, true, true, true, true },
|
||||
[MIPS_ABI_FP_DOUBLE] = { false, false, false, true, true },
|
||||
[MIPS_ABI_FP_SINGLE] = { true, false, false, false, false },
|
||||
[MIPS_ABI_FP_SOFT] = { false, true, false, false, false },
|
||||
[MIPS_ABI_FP_OLD_64] = { false, false, false, false, false },
|
||||
[MIPS_ABI_FP_XX] = { false, false, true, true, true },
|
||||
[MIPS_ABI_FP_64] = { false, false, true, false, false },
|
||||
[MIPS_ABI_FP_64A] = { false, false, true, false, true }
|
||||
};
|
||||
|
||||
/*
|
||||
* Mode requirements when .MIPS.abiflags is not present in the ELF.
|
||||
* Not present means that everything is acceptable except FR1.
|
||||
*/
|
||||
static struct mode_req none_req = { true, true, false, true, true };
|
||||
|
||||
struct mode_req prog_req;
|
||||
struct mode_req interp_req;
|
||||
|
||||
for(i = 0; i < 32; i++) {
|
||||
env->active_tc.gpr[i] = regs->regs[i];
|
||||
}
|
||||
|
@ -747,6 +775,53 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
|
|||
if (regs->cp0_epc & 1) {
|
||||
env->hflags |= MIPS_HFLAG_M16;
|
||||
}
|
||||
|
||||
#ifdef TARGET_ABI_MIPSO32
|
||||
# define MAX_FP_ABI MIPS_ABI_FP_64A
|
||||
#else
|
||||
# define MAX_FP_ABI MIPS_ABI_FP_SOFT
|
||||
#endif
|
||||
if ((info->fp_abi > MAX_FP_ABI && info->fp_abi != MIPS_ABI_FP_UNKNOWN)
|
||||
|| (info->interp_fp_abi > MAX_FP_ABI &&
|
||||
info->interp_fp_abi != MIPS_ABI_FP_UNKNOWN)) {
|
||||
fprintf(stderr, "qemu: Unexpected FPU mode\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
prog_req = (info->fp_abi == MIPS_ABI_FP_UNKNOWN) ? none_req
|
||||
: fpu_reqs[info->fp_abi];
|
||||
interp_req = (info->interp_fp_abi == MIPS_ABI_FP_UNKNOWN) ? none_req
|
||||
: fpu_reqs[info->interp_fp_abi];
|
||||
|
||||
prog_req.single &= interp_req.single;
|
||||
prog_req.soft &= interp_req.soft;
|
||||
prog_req.fr1 &= interp_req.fr1;
|
||||
prog_req.frdefault &= interp_req.frdefault;
|
||||
prog_req.fre &= interp_req.fre;
|
||||
|
||||
bool cpu_has_mips_r2_r6 = env->insn_flags & ISA_MIPS32R2 ||
|
||||
env->insn_flags & ISA_MIPS64R2 ||
|
||||
env->insn_flags & ISA_MIPS32R6 ||
|
||||
env->insn_flags & ISA_MIPS64R6;
|
||||
|
||||
if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1) {
|
||||
env->CP0_Config5 |= (1 << CP0C5_FRE);
|
||||
if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
|
||||
env->hflags |= MIPS_HFLAG_FRE;
|
||||
}
|
||||
} else if ((prog_req.fr1 && prog_req.frdefault) ||
|
||||
(prog_req.single && !prog_req.frdefault)) {
|
||||
if ((env->active_fpu.fcr0 & (1 << FCR0_F64)
|
||||
&& cpu_has_mips_r2_r6) || prog_req.fr1) {
|
||||
env->CP0_Status |= (1 << CP0St_FR);
|
||||
env->hflags |= MIPS_HFLAG_F64;
|
||||
}
|
||||
} else if (!prog_req.fre && !prog_req.frdefault &&
|
||||
!prog_req.fr1 && !prog_req.single && !prog_req.soft) {
|
||||
fprintf(stderr, "qemu: Can't find a matching FPU mode\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (env->insn_flags & ISA_NANOMIPS32) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -247,5 +247,7 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env)
|
|||
/* MIPS-specific prctl() options */
|
||||
#define TARGET_PR_SET_FP_MODE 45
|
||||
#define TARGET_PR_GET_FP_MODE 46
|
||||
#define TARGET_PR_FP_MODE_FR (1 << 0)
|
||||
#define TARGET_PR_FP_MODE_FRE (1 << 1)
|
||||
|
||||
#endif /* MIPS_TARGET_SYSCALL_H */
|
||||
|
|
|
@ -244,5 +244,7 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env)
|
|||
/* MIPS-specific prctl() options */
|
||||
#define TARGET_PR_SET_FP_MODE 45
|
||||
#define TARGET_PR_GET_FP_MODE 46
|
||||
#define TARGET_PR_FP_MODE_FR (1 << 0)
|
||||
#define TARGET_PR_FP_MODE_FRE (1 << 1)
|
||||
|
||||
#endif /* MIPS64_TARGET_SYSCALL_H */
|
||||
|
|
|
@ -61,6 +61,10 @@ struct image_info {
|
|||
abi_ulong interpreter_loadmap_addr;
|
||||
abi_ulong interpreter_pt_dynamic_addr;
|
||||
struct image_info *other_info;
|
||||
#ifdef TARGET_MIPS
|
||||
int fp_abi;
|
||||
int interp_fp_abi;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef TARGET_I386
|
||||
|
|
|
@ -9529,11 +9529,65 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
|||
#endif
|
||||
#ifdef TARGET_MIPS
|
||||
case TARGET_PR_GET_FP_MODE:
|
||||
/* TODO: Implement TARGET_PR_SET_FP_MODE handling.*/
|
||||
return -TARGET_EINVAL;
|
||||
{
|
||||
CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
|
||||
ret = 0;
|
||||
if (env->CP0_Status & (1 << CP0St_FR)) {
|
||||
ret |= TARGET_PR_FP_MODE_FR;
|
||||
}
|
||||
if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
|
||||
ret |= TARGET_PR_FP_MODE_FRE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
case TARGET_PR_SET_FP_MODE:
|
||||
/* TODO: Implement TARGET_PR_GET_FP_MODE handling.*/
|
||||
return -TARGET_EINVAL;
|
||||
{
|
||||
CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
|
||||
bool old_fr = env->CP0_Status & (1 << CP0St_FR);
|
||||
bool new_fr = arg2 & TARGET_PR_FP_MODE_FR;
|
||||
bool new_fre = arg2 & TARGET_PR_FP_MODE_FRE;
|
||||
|
||||
if (new_fr && !(env->active_fpu.fcr0 & (1 << FCR0_F64))) {
|
||||
/* FR1 is not supported */
|
||||
return -TARGET_EOPNOTSUPP;
|
||||
}
|
||||
if (!new_fr && (env->active_fpu.fcr0 & (1 << FCR0_F64))
|
||||
&& !(env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
|
||||
/* cannot set FR=0 */
|
||||
return -TARGET_EOPNOTSUPP;
|
||||
}
|
||||
if (new_fre && !(env->active_fpu.fcr0 & (1 << FCR0_FREP))) {
|
||||
/* Cannot set FRE=1 */
|
||||
return -TARGET_EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int i;
|
||||
fpr_t *fpr = env->active_fpu.fpr;
|
||||
for (i = 0; i < 32 ; i += 2) {
|
||||
if (!old_fr && new_fr) {
|
||||
fpr[i].w[!FP_ENDIAN_IDX] = fpr[i + 1].w[FP_ENDIAN_IDX];
|
||||
} else if (old_fr && !new_fr) {
|
||||
fpr[i + 1].w[FP_ENDIAN_IDX] = fpr[i].w[!FP_ENDIAN_IDX];
|
||||
}
|
||||
}
|
||||
|
||||
if (new_fr) {
|
||||
env->CP0_Status |= (1 << CP0St_FR);
|
||||
env->hflags |= MIPS_HFLAG_F64;
|
||||
} else {
|
||||
env->CP0_Status &= ~(1 << CP0St_FR);
|
||||
}
|
||||
if (new_fre) {
|
||||
env->CP0_Config5 |= (1 << CP0C5_FRE);
|
||||
if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
|
||||
env->hflags |= MIPS_HFLAG_FRE;
|
||||
}
|
||||
} else {
|
||||
env->CP0_Config5 &= ~(1 << CP0C5_FRE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MIPS */
|
||||
#ifdef TARGET_AARCH64
|
||||
case TARGET_PR_SVE_SET_VL:
|
||||
|
|
|
@ -170,6 +170,16 @@ struct TCState {
|
|||
MSACSR_FS_MASK)
|
||||
|
||||
float_status msa_fp_status;
|
||||
|
||||
#define NUMBER_OF_MXU_REGISTERS 16
|
||||
target_ulong mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
|
||||
target_ulong mxu_cr;
|
||||
#define MXU_CR_LC 31
|
||||
#define MXU_CR_RC 30
|
||||
#define MXU_CR_BIAS 2
|
||||
#define MXU_CR_RD_EN 1
|
||||
#define MXU_CR_MXU_EN 0
|
||||
|
||||
};
|
||||
|
||||
typedef struct CPUMIPSState CPUMIPSState;
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
* bits 56-63: vendor-specific ASEs
|
||||
*/
|
||||
#define ASE_MMI 0x0100000000000000ULL
|
||||
#define ASE_MXU 0x0200000000000000ULL
|
||||
|
||||
/* MIPS CPU defines. */
|
||||
#define CPU_MIPS1 (ISA_MIPS1)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue