diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index 462387a073..07c1ebe287 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -304,8 +304,10 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) if (env->insn_flags & ISA_NANOMIPS32) { return; } - if (((info->elf_flags & EF_MIPS_NAN2008) != 0) != - ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) { + if (info->fp_abi != MIPS_ABI_FP_SOFT + && ((info->elf_flags & EF_MIPS_NAN2008) != 0) != + ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) + { if ((env->active_fpu.fcr31_rw_bitmask & (1 << FCR31_NAN2008)) == 0) { fprintf(stderr, "ELF binary's NaN mode not supported by CPU\n"); diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index e2fab57183..a846746553 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -259,21 +259,20 @@ static void cvtstr(double value, char *str, size_t size) -static struct timespec tsub(struct timespec t1, struct timespec t2) +static struct timeval tsub(struct timeval t1, struct timeval t2) { - t1.tv_nsec -= t2.tv_nsec; - if (t1.tv_nsec < 0) { - t1.tv_nsec += NANOSECONDS_PER_SECOND; + t1.tv_usec -= t2.tv_usec; + if (t1.tv_usec < 0) { + t1.tv_usec += 1000000; t1.tv_sec--; } t1.tv_sec -= t2.tv_sec; return t1; } -static double tdiv(double value, struct timespec tv) +static double tdiv(double value, struct timeval tv) { - double seconds = tv.tv_sec + (tv.tv_nsec / 1e9); - return value / seconds; + return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0)); } #define HOURS(sec) ((sec) / (60 * 60)) @@ -286,27 +285,29 @@ enum { VERBOSE_FIXED_TIME = 0x2, }; -static void timestr(struct timespec *tv, char *ts, size_t size, int format) +static void timestr(struct timeval *tv, char *ts, size_t size, int format) { - double frac_sec = tv->tv_nsec / 1e9; + double usec = (double)tv->tv_usec / 1000000.0; if (format & TERSE_FIXED_TIME) { if (!HOURS(tv->tv_sec)) { - snprintf(ts, size, "%u:%05.2f", - (unsigned int) MINUTES(tv->tv_sec), - SECONDS(tv->tv_sec) + frac_sec); + snprintf(ts, size, "%u:%02u.%02u", + (unsigned int) MINUTES(tv->tv_sec), + (unsigned int) SECONDS(tv->tv_sec), + (unsigned int) (usec * 100)); return; } format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */ } if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) { - snprintf(ts, size, "%u:%02u:%05.2f", + snprintf(ts, size, "%u:%02u:%02u.%02u", (unsigned int) HOURS(tv->tv_sec), (unsigned int) MINUTES(tv->tv_sec), - SECONDS(tv->tv_sec) + frac_sec); + (unsigned int) SECONDS(tv->tv_sec), + (unsigned int) (usec * 100)); } else { - snprintf(ts, size, "%05.2f sec", frac_sec); + snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000)); } } @@ -467,7 +468,7 @@ static void dump_buffer(const void *buffer, int64_t offset, int64_t len) } } -static void print_report(const char *op, struct timespec *t, int64_t offset, +static void print_report(const char *op, struct timeval *t, int64_t offset, int64_t count, int64_t total, int cnt, bool Cflag) { char s1[64], s2[64], ts[64]; @@ -707,7 +708,7 @@ static const cmdinfo_t read_cmd = { static int read_f(BlockBackend *blk, int argc, char **argv) { - struct timespec t1, t2; + struct timeval t1, t2; bool Cflag = false, qflag = false, vflag = false; bool Pflag = false, sflag = false, lflag = false, bflag = false; int c, cnt, ret; @@ -825,13 +826,13 @@ static int read_f(BlockBackend *blk, int argc, char **argv) buf = qemu_io_alloc(blk, count, 0xab, flags & BDRV_REQ_REGISTERED_BUF); - clock_gettime(CLOCK_MONOTONIC, &t1); + gettimeofday(&t1, NULL); if (bflag) { ret = do_load_vmstate(blk, buf, offset, count, &total); } else { ret = do_pread(blk, buf, offset, count, flags, &total); } - clock_gettime(CLOCK_MONOTONIC, &t2); + gettimeofday(&t2, NULL); if (ret < 0) { printf("read failed: %s\n", strerror(-ret)); @@ -904,7 +905,7 @@ static const cmdinfo_t readv_cmd = { static int readv_f(BlockBackend *blk, int argc, char **argv) { - struct timespec t1, t2; + struct timeval t1, t2; bool Cflag = false, qflag = false, vflag = false; int c, cnt, ret; char *buf; @@ -964,9 +965,9 @@ static int readv_f(BlockBackend *blk, int argc, char **argv) return -EINVAL; } - clock_gettime(CLOCK_MONOTONIC, &t1); + gettimeofday(&t1, NULL); ret = do_aio_readv(blk, &qiov, offset, flags, &total); - clock_gettime(CLOCK_MONOTONIC, &t2); + gettimeofday(&t2, NULL); if (ret < 0) { printf("readv failed: %s\n", strerror(-ret)); @@ -1047,7 +1048,7 @@ static const cmdinfo_t write_cmd = { static int write_f(BlockBackend *blk, int argc, char **argv) { - struct timespec t1, t2; + struct timeval t1, t2; bool Cflag = false, qflag = false, bflag = false; bool Pflag = false, zflag = false, cflag = false, sflag = false; BdrvRequestFlags flags = 0; @@ -1190,7 +1191,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv) } } - clock_gettime(CLOCK_MONOTONIC, &t1); + gettimeofday(&t1, NULL); if (bflag) { ret = do_save_vmstate(blk, buf, offset, count, &total); } else if (zflag) { @@ -1200,7 +1201,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv) } else { ret = do_pwrite(blk, buf, offset, count, flags, &total); } - clock_gettime(CLOCK_MONOTONIC, &t2); + gettimeofday(&t2, NULL); if (ret < 0) { printf("write failed: %s\n", strerror(-ret)); @@ -1260,7 +1261,7 @@ static const cmdinfo_t writev_cmd = { static int writev_f(BlockBackend *blk, int argc, char **argv) { - struct timespec t1, t2; + struct timeval t1, t2; bool Cflag = false, qflag = false; BdrvRequestFlags flags = 0; int c, cnt, ret; @@ -1317,9 +1318,9 @@ static int writev_f(BlockBackend *blk, int argc, char **argv) return -EINVAL; } - clock_gettime(CLOCK_MONOTONIC, &t1); + gettimeofday(&t1, NULL); ret = do_aio_writev(blk, &qiov, offset, flags, &total); - clock_gettime(CLOCK_MONOTONIC, &t2); + gettimeofday(&t2, NULL); if (ret < 0) { printf("writev failed: %s\n", strerror(-ret)); @@ -1355,15 +1356,15 @@ struct aio_ctx { BlockAcctCookie acct; int pattern; BdrvRequestFlags flags; - struct timespec t1; + struct timeval t1; }; static void aio_write_done(void *opaque, int ret) { struct aio_ctx *ctx = opaque; - struct timespec t2; + struct timeval t2; - clock_gettime(CLOCK_MONOTONIC, &t2); + gettimeofday(&t2, NULL); if (ret < 0) { @@ -1394,9 +1395,9 @@ static void aio_write_done(void *opaque, int ret) static void aio_read_done(void *opaque, int ret) { struct aio_ctx *ctx = opaque; - struct timespec t2; + struct timeval t2; - clock_gettime(CLOCK_MONOTONIC, &t2); + gettimeofday(&t2, NULL); if (ret < 0) { printf("readv failed: %s\n", strerror(-ret)); @@ -1537,7 +1538,7 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv) return -EINVAL; } - clock_gettime(CLOCK_MONOTONIC, &ctx->t1); + gettimeofday(&ctx->t1, NULL); block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size, BLOCK_ACCT_READ); blk_aio_preadv(blk, ctx->offset, &ctx->qiov, ctx->flags, aio_read_done, @@ -1692,7 +1693,7 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv) return -EINVAL; } - clock_gettime(CLOCK_MONOTONIC, &ctx->t1); + gettimeofday(&ctx->t1, NULL); block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size, BLOCK_ACCT_WRITE); @@ -2159,7 +2160,7 @@ static const cmdinfo_t discard_cmd = { static int discard_f(BlockBackend *blk, int argc, char **argv) { - struct timespec t1, t2; + struct timeval t1, t2; bool Cflag = false, qflag = false; int c, ret; int64_t offset, bytes; @@ -2200,9 +2201,9 @@ static int discard_f(BlockBackend *blk, int argc, char **argv) return -EINVAL; } - clock_gettime(CLOCK_MONOTONIC, &t1); + gettimeofday(&t1, NULL); ret = blk_pdiscard(blk, offset, bytes); - clock_gettime(CLOCK_MONOTONIC, &t2); + gettimeofday(&t2, NULL); if (ret < 0) { printf("discard failed: %s\n", strerror(-ret)); diff --git a/scripts/archive-source.sh b/scripts/archive-source.sh index 65af8063e4..7f16803772 100755 --- a/scripts/archive-source.sh +++ b/scripts/archive-source.sh @@ -18,7 +18,13 @@ if test $# -lt 1; then error "Usage: $0 " fi -tar_file=$(realpath "$1") +which realpath +if [ $? -eq 0 ]; then + tar_file=$(realpath -s "$1") +else + d=$(dirname "$1") + tar_file=$(readlink -e "$d")"/"$(basename "$1") +fi sub_tdir=$(mktemp -d "${tar_file%.tar}.sub.XXXXXXXX") sub_file="${sub_tdir}/submodule.tar" diff --git a/target/mips/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc index fbf787d8ce..2b707cc5a7 100644 --- a/target/mips/cpu-defs.c.inc +++ b/target/mips/cpu-defs.c.inc @@ -462,7 +462,7 @@ const mips_def_t mips_defs[] = .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .SEGBITS = 32, .PABITS = 40, - .insn_flags = CPU_MIPS32R5, + .insn_flags = CPU_MIPS32R5 | ASE_MICROMIPS, .mmu_type = MMU_TYPE_R4000, }, { @@ -478,14 +478,15 @@ const mips_def_t mips_defs[] = (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) | (0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP), .CP0_Config2 = MIPS_CONFIG2, - .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_BP) | (1 << CP0C3_BI) | + .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_MSAP) | + (1 << CP0C3_BP) | (1 << CP0C3_BI) | (2 << CP0C3_ISA) | (1 << CP0C3_ULRI) | (1 << CP0C3_RXI) | (1U << CP0C3_M), .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) | (3 << CP0C4_IE) | (1U << CP0C4_M), .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_LLB), - .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) | - (1 << CP0C5_UFE), + .CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) | + (1 << CP0C5_FRE) | (1 << CP0C5_SBRI), .CP0_LLAddr_rw_bitmask = 0, .CP0_LLAddr_shift = 0, .SYNCI_Step = 32, @@ -499,6 +500,7 @@ const mips_def_t mips_defs[] = (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), .CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008), .CP1_fcr31_rw_bitmask = 0x0103FFFF, + .MSAIR = 0x03 << MSAIR_ProcID, .SEGBITS = 32, .PABITS = 32, .insn_flags = CPU_MIPS32R6 | ASE_MICROMIPS, @@ -676,7 +678,9 @@ const mips_def_t mips_defs[] = (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) | (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP), .CP0_Config2 = MIPS_CONFIG2, - .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_LPA), + .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_LPA) | + (1 << CP0C3_VInt) | (1 << CP0C3_MSAP), + .CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn), .CP0_LLAddr_rw_bitmask = 0, .CP0_LLAddr_shift = 0, .SYNCI_Step = 32, diff --git a/target/mips/helper.h b/target/mips/helper.h index 0f8462febb..752748d5e6 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -21,6 +21,8 @@ DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl) #endif +DEF_HELPER_3(crc32, tl, tl, tl, i32) +DEF_HELPER_3(crc32c, tl, tl, tl, i32) DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, i32, i32) /* microMIPS functions */ diff --git a/target/mips/meson.build b/target/mips/meson.build index a26d1e1f79..d2d686fc0c 100644 --- a/target/mips/meson.build +++ b/target/mips/meson.build @@ -7,6 +7,7 @@ mips_ss.add(files( 'gdbstub.c', 'msa.c', )) +mips_ss.add(zlib) if have_system subdir('sysemu') diff --git a/target/mips/sysemu/machine.c b/target/mips/sysemu/machine.c index 213fd637fc..91cd9f1900 100644 --- a/target/mips/sysemu/machine.c +++ b/target/mips/sysemu/machine.c @@ -142,6 +142,7 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size, qemu_get_betls(f, &v->VPN); qemu_get_be32s(f, &v->PageMask); qemu_get_be16s(f, &v->ASID); + qemu_get_be32s(f, &v->MMID); qemu_get_be16s(f, &flags); v->G = (flags >> 10) & 1; v->C0 = (flags >> 7) & 3; @@ -167,6 +168,7 @@ static int put_tlb(QEMUFile *f, void *pv, size_t size, r4k_tlb_t *v = pv; uint16_t asid = v->ASID; + uint32_t mmid = v->MMID; uint16_t flags = ((v->EHINV << 15) | (v->RI1 << 14) | (v->RI0 << 13) | @@ -183,6 +185,7 @@ static int put_tlb(QEMUFile *f, void *pv, size_t size, qemu_put_betls(f, &v->VPN); qemu_put_be32s(f, &v->PageMask); qemu_put_be16s(f, &asid); + qemu_put_be32s(f, &mmid); qemu_put_be16s(f, &flags); qemu_put_be64s(f, &v->PFN[0]); qemu_put_be64s(f, &v->PFN[1]); @@ -204,8 +207,8 @@ static const VMStateInfo vmstate_info_tlb = { static const VMStateDescription vmstate_tlb = { .name = "cpu/tlb", - .version_id = 2, - .minimum_version_id = 2, + .version_id = 3, + .minimum_version_id = 3, .fields = (const VMStateField[]) { VMSTATE_UINT32(nb_tlb, CPUMIPSTLBContext), VMSTATE_UINT32(tlb_in_use, CPUMIPSTLBContext), diff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c index 65403f1a87..b5e0b0d0f1 100644 --- a/target/mips/tcg/op_helper.c +++ b/target/mips/tcg/op_helper.c @@ -25,6 +25,8 @@ #include "exec/exec-all.h" #include "exec/memop.h" #include "fpu_helper.h" +#include "qemu/crc32c.h" +#include static inline target_ulong bitswap(target_ulong v) { @@ -143,6 +145,26 @@ target_ulong helper_rotx(target_ulong rs, uint32_t shift, uint32_t shiftx, return (int64_t)(int32_t)(uint32_t)tmp5; } +/* these crc32 functions are based on target/arm/helper-a64.c */ +target_ulong helper_crc32(target_ulong val, target_ulong m, uint32_t sz) +{ + uint8_t buf[8]; + target_ulong mask = ((sz * 8) == 64) ? -1ULL : ((1ULL << (sz * 8)) - 1); + + m &= mask; + stq_le_p(buf, m); + return (int32_t) (crc32(val ^ 0xffffffff, buf, sz) ^ 0xffffffff); +} + +target_ulong helper_crc32c(target_ulong val, target_ulong m, uint32_t sz) +{ + uint8_t buf[8]; + target_ulong mask = ((sz * 8) == 64) ? -1ULL : ((1ULL << (sz * 8)) - 1); + m &= mask; + stq_le_p(buf, m); + return (int32_t) (crc32c(val, buf, sz) ^ 0xffffffff); +} + void helper_fork(target_ulong arg1, target_ulong arg2) { /* diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 333469b268..256fa0893e 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -430,6 +430,7 @@ enum { OPC_LWE = 0x2F | OPC_SPECIAL3, /* R6 */ + OPC_CRC32 = 0x0F | OPC_SPECIAL3, R6_OPC_PREF = 0x35 | OPC_SPECIAL3, R6_OPC_CACHE = 0x25 | OPC_SPECIAL3, R6_OPC_LL = 0x36 | OPC_SPECIAL3, @@ -13691,6 +13692,30 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) } } +static void gen_crc32(DisasContext *ctx, int rd, int rs, int rt, int sz, + int crc32c) +{ + TCGv t0; + TCGv t1; + TCGv_i32 tsz = tcg_constant_i32(1 << sz); + if (rd == 0) { + /* Treat as NOP. */ + return; + } + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + + gen_load_gpr(t0, rt); + gen_load_gpr(t1, rs); + + if (crc32c) { + gen_helper_crc32c(cpu_gpr[rd], t0, t1, tsz); + } else { + gen_helper_crc32(cpu_gpr[rd], t0, t1, tsz); + } + +} + static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx) { int rs, rt, rd, sa; @@ -13705,6 +13730,17 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx) op1 = MASK_SPECIAL3(ctx->opcode); switch (op1) { + case OPC_CRC32: + if (unlikely(!ctx->crcp) || + unlikely((extract32(ctx->opcode, 6, 2) == 3) && + (!(ctx->hflags & MIPS_HFLAG_64))) || + unlikely((extract32(ctx->opcode, 8, 3) >= 2))) { + gen_reserved_instruction(ctx); + } + gen_crc32(ctx, rt, rs, rt, + extract32(ctx->opcode, 6, 2), + extract32(ctx->opcode, 8, 3)); + break; case R6_OPC_PREF: if (rt >= 24) { /* hint codes 24-31 are reserved and signal RI */ @@ -15346,6 +15382,7 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1; ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1; ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3; + ctx->crcp = (env->CP0_Config5 >> CP0C5_CRCP) & 1; restore_cpu_state(env, ctx); #ifdef CONFIG_USER_ONLY ctx->mem_idx = MIPS_HFLAG_UM; diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h index 2b6646b339..ce2c1da6f4 100644 --- a/target/mips/tcg/translate.h +++ b/target/mips/tcg/translate.h @@ -51,6 +51,7 @@ typedef struct DisasContext { bool abs2008; bool mi; int gi; + bool crcp; } DisasContext; #define DISAS_STOP DISAS_TARGET_0