From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1K9iHw-0005yL-F8 for qemu-devel@nongnu.org; Fri, 20 Jun 2008 11:12:32 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1K9iHv-0005y1-Nf for qemu-devel@nongnu.org; Fri, 20 Jun 2008 11:12:32 -0400 Received: from [199.232.76.173] (port=36273 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1K9iHv-0005xv-H9 for qemu-devel@nongnu.org; Fri, 20 Jun 2008 11:12:31 -0400 Received: from savannah.gnu.org ([199.232.41.3]:60979 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1K9iHk-0003C9-JA for qemu-devel@nongnu.org; Fri, 20 Jun 2008 11:12:31 -0400 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1K9iHe-0005Oj-OP for qemu-devel@nongnu.org; Fri, 20 Jun 2008 15:12:14 +0000 Received: from ths by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1K9iHe-0005Of-Ch for qemu-devel@nongnu.org; Fri, 20 Jun 2008 15:12:14 +0000 MIME-Version: 1.0 Errors-To: ths Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Thiemo Seufer Message-Id: Date: Fri, 20 Jun 2008 15:12:14 +0000 Subject: [Qemu-devel] [4759] Convert unaligned load/store to TCG. Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 4759 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4759 Author: ths Date: 2008-06-20 15:12:14 +0000 (Fri, 20 Jun 2008) Log Message: ----------- Convert unaligned load/store to TCG. Modified Paths: -------------- trunk/configure trunk/target-mips/helper.h trunk/target-mips/op.c trunk/target-mips/op_helper.c trunk/target-mips/translate.c Modified: trunk/configure =================================================================== --- trunk/configure 2008-06-20 15:06:42 UTC (rev 4758) +++ trunk/configure 2008-06-20 15:12:14 UTC (rev 4759) @@ -1280,28 +1280,22 @@ ;; mips|mipsel) echo "TARGET_ARCH=mips" >> $config_mak - echo "CONFIG_DYNGEN_OP=yes" >> $config_mak echo "#define TARGET_ARCH \"mips\"" >> $config_h echo "#define TARGET_MIPS 1" >> $config_h echo "#define TARGET_ABI_MIPSO32 1" >> $config_h - echo "#define CONFIG_DYNGEN_OP 1" >> $config_h ;; mipsn32|mipsn32el) echo "TARGET_ARCH=mipsn32" >> $config_mak - echo "CONFIG_DYNGEN_OP=yes" >> $config_mak echo "#define TARGET_ARCH \"mipsn32\"" >> $config_h echo "#define TARGET_MIPS 1" >> $config_h echo "#define TARGET_ABI_MIPSN32 1" >> $config_h - echo "#define CONFIG_DYNGEN_OP 1" >> $config_h ;; mips64|mips64el) echo "TARGET_ARCH=mips64" >> $config_mak - echo "CONFIG_DYNGEN_OP=yes" >> $config_mak echo "#define TARGET_ARCH \"mips64\"" >> $config_h echo "#define TARGET_MIPS 1" >> $config_h echo "#define TARGET_MIPS64 1" >> $config_h echo "#define TARGET_ABI_MIPSN64 1" >> $config_h - echo "#define CONFIG_DYNGEN_OP 1" >> $config_h ;; ppc) echo "TARGET_ARCH=ppc" >> $config_mak Modified: trunk/target-mips/helper.h =================================================================== --- trunk/target-mips/helper.h 2008-06-20 15:06:42 UTC (rev 4758) +++ trunk/target-mips/helper.h 2008-06-20 15:12:14 UTC (rev 4759) @@ -6,6 +6,17 @@ DEF_HELPER(void, do_raise_exception, (int excp)) DEF_HELPER(void, do_interrupt_restart, (void)) +#ifdef TARGET_MIPS64 +DEF_HELPER(void, do_ldl, (int mem_idx)) +DEF_HELPER(void, do_ldr, (int mem_idx)) +DEF_HELPER(void, do_sdl, (int mem_idx)) +DEF_HELPER(void, do_sdr, (int mem_idx)) +#endif +DEF_HELPER(void, do_lwl, (int mem_idx)) +DEF_HELPER(void, do_lwr, (int mem_idx)) +DEF_HELPER(void, do_swl, (int mem_idx)) +DEF_HELPER(void, do_swr, (int mem_idx)) + DEF_HELPER(void, do_clo, (void)) DEF_HELPER(void, do_clz, (void)) #ifdef TARGET_MIPS64 Modified: trunk/target-mips/op.c =================================================================== --- trunk/target-mips/op.c 2008-06-20 15:06:42 UTC (rev 4758) +++ trunk/target-mips/op.c 2008-06-20 15:12:14 UTC (rev 4759) @@ -19,29 +19,3 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "config.h" -#include "exec.h" -#include "host-utils.h" - -#ifndef CALL_FROM_TB0 -#define CALL_FROM_TB0(func) func() -#endif - -/* Load and store */ -#define MEMSUFFIX _raw -#include "op_mem.c" -#undef MEMSUFFIX -#if !defined(CONFIG_USER_ONLY) -#define MEMSUFFIX _user -#include "op_mem.c" -#undef MEMSUFFIX - -#define MEMSUFFIX _super -#include "op_mem.c" -#undef MEMSUFFIX - -#define MEMSUFFIX _kernel -#include "op_mem.c" -#undef MEMSUFFIX -#endif Modified: trunk/target-mips/op_helper.c =================================================================== --- trunk/target-mips/op_helper.c 2008-06-20 15:06:42 UTC (rev 4758) +++ trunk/target-mips/op_helper.c 2008-06-20 15:12:14 UTC (rev 4759) @@ -308,7 +308,344 @@ } #endif +#ifdef TARGET_WORDS_BIGENDIAN +#define GET_LMASK(v) ((v) & 3) +#define GET_OFFSET(addr, offset) (addr + (offset)) +#else +#define GET_LMASK(v) (((v) & 3) ^ 3) +#define GET_OFFSET(addr, offset) (addr - (offset)) +#endif + +void do_lwl(int mem_idx) +{ + target_ulong tmp; + #ifdef CONFIG_USER_ONLY +#define ldfun ldub_raw +#else + int (*ldfun)(target_ulong); + + switch (mem_idx) + { + case 0: ldfun = ldub_kernel; break; + case 1: ldfun = ldub_super; break; + default: + case 2: ldfun = ldub_user; break; + } +#endif + tmp = ldfun(T0); + T1 = (T1 & 0x00FFFFFF) | (tmp << 24); + + if (GET_LMASK(T0) <= 2) { + tmp = ldfun(GET_OFFSET(T0, 1)); + T1 = (T1 & 0xFF00FFFF) | (tmp << 16); + } + + if (GET_LMASK(T0) <= 1) { + tmp = ldfun(GET_OFFSET(T0, 2)); + T1 = (T1 & 0xFFFF00FF) | (tmp << 8); + } + + if (GET_LMASK(T0) == 0) { + tmp = ldfun(GET_OFFSET(T0, 3)); + T1 = (T1 & 0xFFFFFF00) | tmp; + } + T1 = (int32_t)T1; +} + +void do_lwr(int mem_idx) +{ + target_ulong tmp; + +#ifdef CONFIG_USER_ONLY +#define ldfun ldub_raw +#else + int (*ldfun)(target_ulong); + + switch (mem_idx) + { + case 0: ldfun = ldub_kernel; break; + case 1: ldfun = ldub_super; break; + default: + case 2: ldfun = ldub_user; break; + } +#endif + tmp = ldfun(T0); + T1 = (T1 & 0xFFFFFF00) | tmp; + + if (GET_LMASK(T0) >= 1) { + tmp = ldfun(GET_OFFSET(T0, -1)); + T1 = (T1 & 0xFFFF00FF) | (tmp << 8); + } + + if (GET_LMASK(T0) >= 2) { + tmp = ldfun(GET_OFFSET(T0, -2)); + T1 = (T1 & 0xFF00FFFF) | (tmp << 16); + } + + if (GET_LMASK(T0) == 3) { + tmp = ldfun(GET_OFFSET(T0, -3)); + T1 = (T1 & 0x00FFFFFF) | (tmp << 24); + } + T1 = (int32_t)T1; +} + +void do_swl(int mem_idx) +{ +#ifdef CONFIG_USER_ONLY +#define stfun stb_raw +#else + void (*stfun)(target_ulong, int); + + switch (mem_idx) + { + case 0: stfun = stb_kernel; break; + case 1: stfun = stb_super; break; + default: + case 2: stfun = stb_user; break; + } +#endif + stfun(T0, (uint8_t)(T1 >> 24)); + + if (GET_LMASK(T0) <= 2) + stfun(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 16)); + + if (GET_LMASK(T0) <= 1) + stfun(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 8)); + + if (GET_LMASK(T0) == 0) + stfun(GET_OFFSET(T0, 3), (uint8_t)T1); +} + +void do_swr(int mem_idx) +{ +#ifdef CONFIG_USER_ONLY +#define stfun stb_raw +#else + void (*stfun)(target_ulong, int); + + switch (mem_idx) + { + case 0: stfun = stb_kernel; break; + case 1: stfun = stb_super; break; + default: + case 2: stfun = stb_user; break; + } +#endif + stfun(T0, (uint8_t)T1); + + if (GET_LMASK(T0) >= 1) + stfun(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8)); + + if (GET_LMASK(T0) >= 2) + stfun(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16)); + + if (GET_LMASK(T0) == 3) + stfun(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24)); +} + +#if defined(TARGET_MIPS64) +/* "half" load and stores. We must do the memory access inline, + or fault handling won't work. */ + +#ifdef TARGET_WORDS_BIGENDIAN +#define GET_LMASK64(v) ((v) & 7) +#else +#define GET_LMASK64(v) (((v) & 7) ^ 7) +#endif + +void do_ldl(int mem_idx) +{ + uint64_t tmp; + +#ifdef CONFIG_USER_ONLY +#define ldfun ldub_raw +#else + target_ulong (*ldfun)(target_ulong); + + switch (mem_idx) + { + case 0: ldfun = ldub_kernel; break; + case 1: ldfun = ldub_super; break; + default: + case 2: ldfun = ldub_user; break; + } +#endif + tmp = ldfun(T0); + T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56); + + if (GET_LMASK64(T0) <= 6) { + tmp = ldfun(GET_OFFSET(T0, 1)); + T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48); + } + + if (GET_LMASK64(T0) <= 5) { + tmp = ldfun(GET_OFFSET(T0, 2)); + T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40); + } + + if (GET_LMASK64(T0) <= 4) { + tmp = ldfun(GET_OFFSET(T0, 3)); + T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32); + } + + if (GET_LMASK64(T0) <= 3) { + tmp = ldfun(GET_OFFSET(T0, 4)); + T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24); + } + + if (GET_LMASK64(T0) <= 2) { + tmp = ldfun(GET_OFFSET(T0, 5)); + T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16); + } + + if (GET_LMASK64(T0) <= 1) { + tmp = ldfun(GET_OFFSET(T0, 6)); + T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8); + } + + if (GET_LMASK64(T0) == 0) { + tmp = ldfun(GET_OFFSET(T0, 7)); + T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp; + } +} + +void do_ldr(int mem_idx) +{ + uint64_t tmp; + +#ifdef CONFIG_USER_ONLY +#define ldfun ldub_raw +#else + target_ulong (*ldfun)(target_ulong); + + switch (mem_idx) + { + case 0: ldfun = ldub_kernel; break; + case 1: ldfun = ldub_super; break; + default: + case 2: ldfun = ldub_user; break; + } +#endif + tmp = ldfun(T0); + T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp; + + if (GET_LMASK64(T0) >= 1) { + tmp = ldfun(GET_OFFSET(T0, -1)); + T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8); + } + + if (GET_LMASK64(T0) >= 2) { + tmp = ldfun(GET_OFFSET(T0, -2)); + T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16); + } + + if (GET_LMASK64(T0) >= 3) { + tmp = ldfun(GET_OFFSET(T0, -3)); + T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24); + } + + if (GET_LMASK64(T0) >= 4) { + tmp = ldfun(GET_OFFSET(T0, -4)); + T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32); + } + + if (GET_LMASK64(T0) >= 5) { + tmp = ldfun(GET_OFFSET(T0, -5)); + T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40); + } + + if (GET_LMASK64(T0) >= 6) { + tmp = ldfun(GET_OFFSET(T0, -6)); + T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48); + } + + if (GET_LMASK64(T0) == 7) { + tmp = ldfun(GET_OFFSET(T0, -7)); + T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56); + } +} + +void do_sdl(int mem_idx) +{ +#ifdef CONFIG_USER_ONLY +#define stfun stb_raw +#else + void (*stfun)(target_ulong, int); + + switch (mem_idx) + { + case 0: stfun = stb_kernel; break; + case 1: stfun = stb_super; break; + default: + case 2: stfun = stb_user; break; + } +#endif + stfun(T0, (uint8_t)(T1 >> 56)); + + if (GET_LMASK64(T0) <= 6) + stfun(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 48)); + + if (GET_LMASK64(T0) <= 5) + stfun(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 40)); + + if (GET_LMASK64(T0) <= 4) + stfun(GET_OFFSET(T0, 3), (uint8_t)(T1 >> 32)); + + if (GET_LMASK64(T0) <= 3) + stfun(GET_OFFSET(T0, 4), (uint8_t)(T1 >> 24)); + + if (GET_LMASK64(T0) <= 2) + stfun(GET_OFFSET(T0, 5), (uint8_t)(T1 >> 16)); + + if (GET_LMASK64(T0) <= 1) + stfun(GET_OFFSET(T0, 6), (uint8_t)(T1 >> 8)); + + if (GET_LMASK64(T0) <= 0) + stfun(GET_OFFSET(T0, 7), (uint8_t)T1); +} + +void do_sdr(int mem_idx) +{ +#ifdef CONFIG_USER_ONLY +#define stfun stb_raw +#else + void (*stfun)(target_ulong, int); + + switch (mem_idx) + { + case 0: stfun = stb_kernel; break; + case 1: stfun = stb_super; break; + default: + case 2: stfun = stb_user; break; + } +#endif + stfun(T0, (uint8_t)T1); + + if (GET_LMASK64(T0) >= 1) + stfun(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8)); + + if (GET_LMASK64(T0) >= 2) + stfun(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16)); + + if (GET_LMASK64(T0) >= 3) + stfun(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24)); + + if (GET_LMASK64(T0) >= 4) + stfun(GET_OFFSET(T0, -4), (uint8_t)(T1 >> 32)); + + if (GET_LMASK64(T0) >= 5) + stfun(GET_OFFSET(T0, -5), (uint8_t)(T1 >> 40)); + + if (GET_LMASK64(T0) >= 6) + stfun(GET_OFFSET(T0, -6), (uint8_t)(T1 >> 48)); + + if (GET_LMASK64(T0) == 7) + stfun(GET_OFFSET(T0, -7), (uint8_t)(T1 >> 56)); +} +#endif /* TARGET_MIPS64 */ + +#ifdef CONFIG_USER_ONLY void do_mfc0_random (void) { cpu_abort(env, "mfc0 random\n"); Modified: trunk/target-mips/translate.c =================================================================== --- trunk/target-mips/translate.c 2008-06-20 15:06:42 UTC (rev 4758) +++ trunk/target-mips/translate.c 2008-06-20 15:12:14 UTC (rev 4759) @@ -945,37 +945,6 @@ } /* load/store instructions. */ -#if defined(CONFIG_USER_ONLY) -#define op_ldst(name) gen_op_##name##_raw() -#define OP_LD_TABLE(width) -#define OP_ST_TABLE(width) -#else -#define op_ldst(name) (*gen_op_##name[ctx->mem_idx])() -#define OP_LD_TABLE(width) \ -static GenOpFunc *gen_op_l##width[] = { \ - &gen_op_l##width##_kernel, \ - &gen_op_l##width##_super, \ - &gen_op_l##width##_user, \ -} -#define OP_ST_TABLE(width) \ -static GenOpFunc *gen_op_s##width[] = { \ - &gen_op_s##width##_kernel, \ - &gen_op_s##width##_super, \ - &gen_op_s##width##_user, \ -} -#endif - -#if defined(TARGET_MIPS64) -OP_LD_TABLE(dl); -OP_LD_TABLE(dr); -OP_ST_TABLE(dl); -OP_ST_TABLE(dr); -#endif -OP_LD_TABLE(wl); -OP_LD_TABLE(wr); -OP_ST_TABLE(wl); -OP_ST_TABLE(wr); - #define OP_LD(insn,fname) \ void inline op_ldst_##insn(DisasContext *ctx) \ { \ @@ -1094,25 +1063,29 @@ opn = "scd"; break; case OPC_LDL: + save_cpu_state(ctx, 1); gen_load_gpr(cpu_T[1], rt); - op_ldst(ldl); + tcg_gen_helper_0_1i(do_ldl, ctx->mem_idx); gen_store_gpr(cpu_T[1], rt); opn = "ldl"; break; case OPC_SDL: + save_cpu_state(ctx, 1); gen_load_gpr(cpu_T[1], rt); - op_ldst(sdl); + tcg_gen_helper_0_1i(do_sdl, ctx->mem_idx); opn = "sdl"; break; case OPC_LDR: + save_cpu_state(ctx, 1); gen_load_gpr(cpu_T[1], rt); - op_ldst(ldr); + tcg_gen_helper_0_1i(do_ldr, ctx->mem_idx); gen_store_gpr(cpu_T[1], rt); opn = "ldr"; break; case OPC_SDR: + save_cpu_state(ctx, 1); gen_load_gpr(cpu_T[1], rt); - op_ldst(sdr); + tcg_gen_helper_0_1i(do_sdr, ctx->mem_idx); opn = "sdr"; break; #endif @@ -1157,25 +1130,29 @@ opn = "lbu"; break; case OPC_LWL: + save_cpu_state(ctx, 1); gen_load_gpr(cpu_T[1], rt); - op_ldst(lwl); + tcg_gen_helper_0_1i(do_lwl, ctx->mem_idx); gen_store_gpr(cpu_T[1], rt); opn = "lwl"; break; case OPC_SWL: + save_cpu_state(ctx, 1); gen_load_gpr(cpu_T[1], rt); - op_ldst(swl); + tcg_gen_helper_0_1i(do_swl, ctx->mem_idx); opn = "swr"; break; case OPC_LWR: + save_cpu_state(ctx, 1); gen_load_gpr(cpu_T[1], rt); - op_ldst(lwr); + tcg_gen_helper_0_1i(do_lwr, ctx->mem_idx); gen_store_gpr(cpu_T[1], rt); opn = "lwr"; break; case OPC_SWR: + save_cpu_state(ctx, 1); gen_load_gpr(cpu_T[1], rt); - op_ldst(swr); + tcg_gen_helper_0_1i(do_swr, ctx->mem_idx); opn = "swr"; break; case OPC_LL: