From patchwork Fri Jun 30 12:30:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 782843 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wzbYt33wzz9s7f for ; Fri, 30 Jun 2017 22:34:10 +1000 (AEST) Received: from localhost ([::1]:44344 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dQv7g-0001W5-37 for incoming@patchwork.ozlabs.org; Fri, 30 Jun 2017 08:34:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33293) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dQv4h-0008Bu-7z for qemu-devel@nongnu.org; Fri, 30 Jun 2017 08:31:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dQv4b-0005wJ-F1 for qemu-devel@nongnu.org; Fri, 30 Jun 2017 08:31:03 -0400 Received: from mout.kundenserver.de ([212.227.126.131]:54506) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dQv4b-0005sr-2j for qemu-devel@nongnu.org; Fri, 30 Jun 2017 08:30:57 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue001 [212.227.15.167]) with ESMTPSA (Nemesis) id 0MPuXS-1dLzO110s6-0051f1; Fri, 30 Jun 2017 14:30:55 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Fri, 30 Jun 2017 14:30:50 +0200 Message-Id: <20170630123050.19834-8-laurent@vivier.eu> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170630123050.19834-1-laurent@vivier.eu> References: <20170630123050.19834-1-laurent@vivier.eu> X-Provags-ID: V03:K0:f4KI6nPX6yzYFvLE1JXYIlb8EBoGhj/BrW7WNjJ9u9r1/5uo//S u4g+AyoEezptoCw+NpZT7qQTFWKE070TaT6DVoY3VsiQpVxXSsn3xZR5vm8DqMJ550xUnMI 0wTJjRhIq9z/VLTkN5TGWMtHc5Qf86NpQH+KJG4Y9JW+lE/9ihwm5PWmdWGsX24nNBzmV/J kMw60TfgxLAhP2VLDgxOQ== X-UI-Out-Filterresults: notjunk:1; V01:K0:7CgJ7jVLp1s=:qYAtNBNwL8VhmBrSUUybMg kdnG5VuqCPiJnjy8XWI/ji2n/08k84YyK6dX4T6eUIEiDOhUrAOb+c5zgBZ8vtYEY+XuEuN2P thdBLTv8i7DYXexLyecblRVd8ws5LzfvqX09l0gMLAijaf3MkwTnCa3kbgkyg/jV4VlPujkoA kGV+rF8BJLl0olomd8jo44wZANY+5vUGCdJL629aU5xeEeUnUDOjCq/hrp3kS6tcmMX/AsB+L GOB5zs8ZYyDzLNV1m0xNCw1KPTyIiGXy/6iM003+kKN0ana+EFd2PnNxc7mMWc32sjny0fMNC ac8NZD8qv5Er/EBVI8soTtcNEGdw4NqmXgaLlt12QSur25TlolqSaBKa4WaFul0KY09SjqQ80 sEGQEdNnZy0eLBd8zjMhxE+H5ZdPPWQfrdfCL4B6rZva29rHxzg2Q4DnD5TKKQYtZfGt4LtaM eX0qVJuE2MFkfZihJyWq9ikqOqHEWAdbaTb7V9gzefjQesv0qD64lXMkAmEnRJpAZA04VSLlH rWiVC3Yxmk5OOZFj6Ai74QwnAo62UNQjFIsxjPCHO03K6ukRZj0HFokIUbV79GYrSil+87YUg acF2+L0y38+0IZf2BcaXvrh96PrfFsTLCsbgYq6NIoNUH0+x7ZWYbem5r5gftSkkrMd0zO05j 0318BO3bp+XAlvIkY4+TugafCYHoZjcFokzXYC9YRHWbPFKwwwWBv5uWyDkH0/wB8LPk= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.126.131 Subject: [Qemu-devel] [PULL 7/7] target/m68k: add fmovem X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Laurent Vivier Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Laurent Vivier Reviewed-by: Richard Henderson Message-Id: <20170628204241.32106-8-laurent@vivier.eu> --- target/m68k/fpu_helper.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++ target/m68k/helper.h | 6 +++ target/m68k/translate.c | 93 ++++++++++++++++++++++++------------ 3 files changed, 189 insertions(+), 30 deletions(-) diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c index 382fbc1..bdfc537 100644 --- a/target/m68k/fpu_helper.c +++ b/target/m68k/fpu_helper.c @@ -22,6 +22,7 @@ #include "cpu.h" #include "exec/helper-proto.h" #include "exec/exec-all.h" +#include "exec/cpu_ldst.h" /* Undefined offsets may be different on various FPU. * On 68040 they return 0.0 (floatx80_zero) @@ -388,3 +389,122 @@ void HELPER(fconst)(CPUM68KState *env, FPReg *val, uint32_t offset) { val->d = fpu_rom[offset]; } + +typedef int (*float_access)(CPUM68KState *env, uint32_t addr, FPReg *fp, + uintptr_t ra); + +static uint32_t fmovem_predec(CPUM68KState *env, uint32_t addr, uint32_t mask, + float_access access) +{ + uintptr_t ra = GETPC(); + int i, size; + + for (i = 7; i >= 0; i--, mask <<= 1) { + if (mask & 0x80) { + size = access(env, addr, &env->fregs[i], ra); + if ((mask & 0xff) != 0x80) { + addr -= size; + } + } + } + + return addr; +} + +static uint32_t fmovem_postinc(CPUM68KState *env, uint32_t addr, uint32_t mask, + float_access access) +{ + uintptr_t ra = GETPC(); + int i, size; + + for (i = 0; i < 8; i++, mask <<= 1) { + if (mask & 0x80) { + size = access(env, addr, &env->fregs[i], ra); + addr += size; + } + } + + return addr; +} + +static int cpu_ld_floatx80_ra(CPUM68KState *env, uint32_t addr, FPReg *fp, + uintptr_t ra) +{ + uint32_t high; + uint64_t low; + + high = cpu_ldl_data_ra(env, addr, ra); + low = cpu_ldq_data_ra(env, addr + 4, ra); + + fp->l.upper = high >> 16; + fp->l.lower = low; + + return 12; +} + +static int cpu_st_floatx80_ra(CPUM68KState *env, uint32_t addr, FPReg *fp, + uintptr_t ra) +{ + cpu_stl_data_ra(env, addr, fp->l.upper << 16, ra); + cpu_stq_data_ra(env, addr + 4, fp->l.lower, ra); + + return 12; +} + +static int cpu_ld_float64_ra(CPUM68KState *env, uint32_t addr, FPReg *fp, + uintptr_t ra) +{ + uint64_t val; + + val = cpu_ldq_data_ra(env, addr, ra); + fp->d = float64_to_floatx80(*(float64 *)&val, &env->fp_status); + + return 8; +} + +static int cpu_st_float64_ra(CPUM68KState *env, uint32_t addr, FPReg *fp, + uintptr_t ra) +{ + float64 val; + + val = floatx80_to_float64(fp->d, &env->fp_status); + cpu_stq_data_ra(env, addr, *(uint64_t *)&val, ra); + + return 8; +} + +uint32_t HELPER(fmovemx_st_predec)(CPUM68KState *env, uint32_t addr, + uint32_t mask) +{ + return fmovem_predec(env, addr, mask, cpu_st_floatx80_ra); +} + +uint32_t HELPER(fmovemx_st_postinc)(CPUM68KState *env, uint32_t addr, + uint32_t mask) +{ + return fmovem_postinc(env, addr, mask, cpu_st_floatx80_ra); +} + +uint32_t HELPER(fmovemx_ld_postinc)(CPUM68KState *env, uint32_t addr, + uint32_t mask) +{ + return fmovem_postinc(env, addr, mask, cpu_ld_floatx80_ra); +} + +uint32_t HELPER(fmovemd_st_predec)(CPUM68KState *env, uint32_t addr, + uint32_t mask) +{ + return fmovem_predec(env, addr, mask, cpu_st_float64_ra); +} + +uint32_t HELPER(fmovemd_st_postinc)(CPUM68KState *env, uint32_t addr, + uint32_t mask) +{ + return fmovem_postinc(env, addr, mask, cpu_st_float64_ra); +} + +uint32_t HELPER(fmovemd_ld_postinc)(CPUM68KState *env, uint32_t addr, + uint32_t mask) +{ + return fmovem_postinc(env, addr, mask, cpu_ld_float64_ra); +} diff --git a/target/m68k/helper.h b/target/m68k/helper.h index b396899..475a1f2 100644 --- a/target/m68k/helper.h +++ b/target/m68k/helper.h @@ -54,6 +54,12 @@ DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_RWG, void, env, fp, fp) DEF_HELPER_FLAGS_2(set_fpcr, TCG_CALL_NO_RWG, void, env, i32) DEF_HELPER_FLAGS_2(ftst, TCG_CALL_NO_RWG, void, env, fp) DEF_HELPER_3(fconst, void, env, fp, i32) +DEF_HELPER_3(fmovemx_st_predec, i32, env, i32, i32) +DEF_HELPER_3(fmovemx_st_postinc, i32, env, i32, i32) +DEF_HELPER_3(fmovemx_ld_postinc, i32, env, i32, i32) +DEF_HELPER_3(fmovemd_st_predec, i32, env, i32, i32) +DEF_HELPER_3(fmovemd_st_postinc, i32, env, i32, i32) +DEF_HELPER_3(fmovemd_ld_postinc, i32, env, i32, i32) DEF_HELPER_3(mac_move, void, env, i32, i32) DEF_HELPER_3(macmulf, i64, env, i32, i32) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 89ac2c7..3a519b7 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -4505,13 +4505,72 @@ static void gen_op_fmove_fcr(CPUM68KState *env, DisasContext *s, tcg_temp_free_i32(addr); } +static void gen_op_fmovem(CPUM68KState *env, DisasContext *s, + uint32_t insn, uint32_t ext) +{ + int opsize; + TCGv addr, tmp; + int mode = (ext >> 11) & 0x3; + int is_load = ((ext & 0x2000) == 0); + + if (m68k_feature(s->env, M68K_FEATURE_FPU)) { + opsize = OS_EXTENDED; + } else { + opsize = OS_DOUBLE; /* FIXME */ + } + + addr = gen_lea(env, s, insn, opsize); + if (IS_NULL_QREG(addr)) { + gen_addr_fault(s); + return; + } + + tmp = tcg_temp_new(); + if (mode & 0x1) { + /* Dynamic register list */ + tcg_gen_ext8u_i32(tmp, DREG(ext, 4)); + } else { + /* Static register list */ + tcg_gen_movi_i32(tmp, ext & 0xff); + } + + if (!is_load && (mode & 2) == 0) { + /* predecrement addressing mode + * only available to store register to memory + */ + if (opsize == OS_EXTENDED) { + gen_helper_fmovemx_st_predec(tmp, cpu_env, addr, tmp); + } else { + gen_helper_fmovemd_st_predec(tmp, cpu_env, addr, tmp); + } + } else { + /* postincrement addressing mode */ + if (opsize == OS_EXTENDED) { + if (is_load) { + gen_helper_fmovemx_ld_postinc(tmp, cpu_env, addr, tmp); + } else { + gen_helper_fmovemx_st_postinc(tmp, cpu_env, addr, tmp); + } + } else { + if (is_load) { + gen_helper_fmovemd_ld_postinc(tmp, cpu_env, addr, tmp); + } else { + gen_helper_fmovemd_st_postinc(tmp, cpu_env, addr, tmp); + } + } + } + if ((insn & 070) == 030 || (insn & 070) == 040) { + tcg_gen_mov_i32(AREG(insn, 0), tmp); + } + tcg_temp_free(tmp); +} + /* ??? FP exceptions are not implemented. Most exceptions are deferred until immediately before the next FP instruction is executed. */ DISAS_INSN(fpu) { uint16_t ext; int opmode; - TCGv tmp32; int opsize; TCGv_ptr cpu_src, cpu_dest; @@ -4548,36 +4607,10 @@ DISAS_INSN(fpu) return; case 6: /* fmovem */ case 7: - { - TCGv addr; - TCGv_ptr fp; - uint16_t mask; - int i; - if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0) - goto undef; - tmp32 = gen_lea(env, s, insn, OS_LONG); - if (IS_NULL_QREG(tmp32)) { - gen_addr_fault(s); - return; - } - addr = tcg_temp_new_i32(); - tcg_gen_mov_i32(addr, tmp32); - mask = 0x80; - fp = tcg_temp_new_ptr(); - for (i = 0; i < 8; i++) { - if (ext & mask) { - tcg_gen_addi_ptr(fp, cpu_env, - offsetof(CPUM68KState, fregs[i])); - gen_ldst_fp(s, OS_DOUBLE, addr, fp, - (ext & (1 << 13)) ? EA_STORE : EA_LOADS); - if (ext & (mask - 1)) - tcg_gen_addi_i32(addr, addr, 8); - } - mask >>= 1; - } - tcg_temp_free_i32(addr); - tcg_temp_free_ptr(fp); + if ((ext & 0x1000) == 0 && !m68k_feature(s->env, M68K_FEATURE_FPU)) { + goto undef; } + gen_op_fmovem(env, s, insn, ext); return; } if (ext & (1 << 14)) {