Commit 0bbba166 authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 09ffed7e 64ea3d67
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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                  */
+37 −0
Original line number Diff line number Diff line
@@ -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,
+75 −0
Original line number Diff line number Diff line
@@ -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;
    }
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+2 −0
Original line number Diff line number Diff line
@@ -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 */
Loading