Commit c8c2227e913e5a41cc44746e22ad73e9880c06fb

Authored by ths
1 parent 9fac3a3a

Convert unaligned load/store to TCG.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4759 c046a42c-6fe2-441c-8c8c-71466251a162
configure
... ... @@ -1280,28 +1280,22 @@ case "$target_cpu" in
1280 1280 ;;
1281 1281 mips|mipsel)
1282 1282 echo "TARGET_ARCH=mips" >> $config_mak
1283   - echo "CONFIG_DYNGEN_OP=yes" >> $config_mak
1284 1283 echo "#define TARGET_ARCH \"mips\"" >> $config_h
1285 1284 echo "#define TARGET_MIPS 1" >> $config_h
1286 1285 echo "#define TARGET_ABI_MIPSO32 1" >> $config_h
1287   - echo "#define CONFIG_DYNGEN_OP 1" >> $config_h
1288 1286 ;;
1289 1287 mipsn32|mipsn32el)
1290 1288 echo "TARGET_ARCH=mipsn32" >> $config_mak
1291   - echo "CONFIG_DYNGEN_OP=yes" >> $config_mak
1292 1289 echo "#define TARGET_ARCH \"mipsn32\"" >> $config_h
1293 1290 echo "#define TARGET_MIPS 1" >> $config_h
1294 1291 echo "#define TARGET_ABI_MIPSN32 1" >> $config_h
1295   - echo "#define CONFIG_DYNGEN_OP 1" >> $config_h
1296 1292 ;;
1297 1293 mips64|mips64el)
1298 1294 echo "TARGET_ARCH=mips64" >> $config_mak
1299   - echo "CONFIG_DYNGEN_OP=yes" >> $config_mak
1300 1295 echo "#define TARGET_ARCH \"mips64\"" >> $config_h
1301 1296 echo "#define TARGET_MIPS 1" >> $config_h
1302 1297 echo "#define TARGET_MIPS64 1" >> $config_h
1303 1298 echo "#define TARGET_ABI_MIPSN64 1" >> $config_h
1304   - echo "#define CONFIG_DYNGEN_OP 1" >> $config_h
1305 1299 ;;
1306 1300 ppc)
1307 1301 echo "TARGET_ARCH=ppc" >> $config_mak
... ...
target-mips/helper.h
... ... @@ -6,6 +6,17 @@ DEF_HELPER(void, do_raise_exception_err, (int excp, int err))
6 6 DEF_HELPER(void, do_raise_exception, (int excp))
7 7 DEF_HELPER(void, do_interrupt_restart, (void))
8 8  
  9 +#ifdef TARGET_MIPS64
  10 +DEF_HELPER(void, do_ldl, (int mem_idx))
  11 +DEF_HELPER(void, do_ldr, (int mem_idx))
  12 +DEF_HELPER(void, do_sdl, (int mem_idx))
  13 +DEF_HELPER(void, do_sdr, (int mem_idx))
  14 +#endif
  15 +DEF_HELPER(void, do_lwl, (int mem_idx))
  16 +DEF_HELPER(void, do_lwr, (int mem_idx))
  17 +DEF_HELPER(void, do_swl, (int mem_idx))
  18 +DEF_HELPER(void, do_swr, (int mem_idx))
  19 +
9 20 DEF_HELPER(void, do_clo, (void))
10 21 DEF_HELPER(void, do_clz, (void))
11 22 #ifdef TARGET_MIPS64
... ...
target-mips/op.c
... ... @@ -19,29 +19,3 @@
19 19 * License along with this library; if not, write to the Free Software
20 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 21 */
22   -
23   -#include "config.h"
24   -#include "exec.h"
25   -#include "host-utils.h"
26   -
27   -#ifndef CALL_FROM_TB0
28   -#define CALL_FROM_TB0(func) func()
29   -#endif
30   -
31   -/* Load and store */
32   -#define MEMSUFFIX _raw
33   -#include "op_mem.c"
34   -#undef MEMSUFFIX
35   -#if !defined(CONFIG_USER_ONLY)
36   -#define MEMSUFFIX _user
37   -#include "op_mem.c"
38   -#undef MEMSUFFIX
39   -
40   -#define MEMSUFFIX _super
41   -#include "op_mem.c"
42   -#undef MEMSUFFIX
43   -
44   -#define MEMSUFFIX _kernel
45   -#include "op_mem.c"
46   -#undef MEMSUFFIX
47   -#endif
... ...
target-mips/op_helper.c
... ... @@ -308,6 +308,343 @@ void do_dmultu (void)
308 308 }
309 309 #endif
310 310  
  311 +#ifdef TARGET_WORDS_BIGENDIAN
  312 +#define GET_LMASK(v) ((v) & 3)
  313 +#define GET_OFFSET(addr, offset) (addr + (offset))
  314 +#else
  315 +#define GET_LMASK(v) (((v) & 3) ^ 3)
  316 +#define GET_OFFSET(addr, offset) (addr - (offset))
  317 +#endif
  318 +
  319 +void do_lwl(int mem_idx)
  320 +{
  321 + target_ulong tmp;
  322 +
  323 +#ifdef CONFIG_USER_ONLY
  324 +#define ldfun ldub_raw
  325 +#else
  326 + int (*ldfun)(target_ulong);
  327 +
  328 + switch (mem_idx)
  329 + {
  330 + case 0: ldfun = ldub_kernel; break;
  331 + case 1: ldfun = ldub_super; break;
  332 + default:
  333 + case 2: ldfun = ldub_user; break;
  334 + }
  335 +#endif
  336 + tmp = ldfun(T0);
  337 + T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
  338 +
  339 + if (GET_LMASK(T0) <= 2) {
  340 + tmp = ldfun(GET_OFFSET(T0, 1));
  341 + T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
  342 + }
  343 +
  344 + if (GET_LMASK(T0) <= 1) {
  345 + tmp = ldfun(GET_OFFSET(T0, 2));
  346 + T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
  347 + }
  348 +
  349 + if (GET_LMASK(T0) == 0) {
  350 + tmp = ldfun(GET_OFFSET(T0, 3));
  351 + T1 = (T1 & 0xFFFFFF00) | tmp;
  352 + }
  353 + T1 = (int32_t)T1;
  354 +}
  355 +
  356 +void do_lwr(int mem_idx)
  357 +{
  358 + target_ulong tmp;
  359 +
  360 +#ifdef CONFIG_USER_ONLY
  361 +#define ldfun ldub_raw
  362 +#else
  363 + int (*ldfun)(target_ulong);
  364 +
  365 + switch (mem_idx)
  366 + {
  367 + case 0: ldfun = ldub_kernel; break;
  368 + case 1: ldfun = ldub_super; break;
  369 + default:
  370 + case 2: ldfun = ldub_user; break;
  371 + }
  372 +#endif
  373 + tmp = ldfun(T0);
  374 + T1 = (T1 & 0xFFFFFF00) | tmp;
  375 +
  376 + if (GET_LMASK(T0) >= 1) {
  377 + tmp = ldfun(GET_OFFSET(T0, -1));
  378 + T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
  379 + }
  380 +
  381 + if (GET_LMASK(T0) >= 2) {
  382 + tmp = ldfun(GET_OFFSET(T0, -2));
  383 + T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
  384 + }
  385 +
  386 + if (GET_LMASK(T0) == 3) {
  387 + tmp = ldfun(GET_OFFSET(T0, -3));
  388 + T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
  389 + }
  390 + T1 = (int32_t)T1;
  391 +}
  392 +
  393 +void do_swl(int mem_idx)
  394 +{
  395 +#ifdef CONFIG_USER_ONLY
  396 +#define stfun stb_raw
  397 +#else
  398 + void (*stfun)(target_ulong, int);
  399 +
  400 + switch (mem_idx)
  401 + {
  402 + case 0: stfun = stb_kernel; break;
  403 + case 1: stfun = stb_super; break;
  404 + default:
  405 + case 2: stfun = stb_user; break;
  406 + }
  407 +#endif
  408 + stfun(T0, (uint8_t)(T1 >> 24));
  409 +
  410 + if (GET_LMASK(T0) <= 2)
  411 + stfun(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 16));
  412 +
  413 + if (GET_LMASK(T0) <= 1)
  414 + stfun(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 8));
  415 +
  416 + if (GET_LMASK(T0) == 0)
  417 + stfun(GET_OFFSET(T0, 3), (uint8_t)T1);
  418 +}
  419 +
  420 +void do_swr(int mem_idx)
  421 +{
  422 +#ifdef CONFIG_USER_ONLY
  423 +#define stfun stb_raw
  424 +#else
  425 + void (*stfun)(target_ulong, int);
  426 +
  427 + switch (mem_idx)
  428 + {
  429 + case 0: stfun = stb_kernel; break;
  430 + case 1: stfun = stb_super; break;
  431 + default:
  432 + case 2: stfun = stb_user; break;
  433 + }
  434 +#endif
  435 + stfun(T0, (uint8_t)T1);
  436 +
  437 + if (GET_LMASK(T0) >= 1)
  438 + stfun(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
  439 +
  440 + if (GET_LMASK(T0) >= 2)
  441 + stfun(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
  442 +
  443 + if (GET_LMASK(T0) == 3)
  444 + stfun(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
  445 +}
  446 +
  447 +#if defined(TARGET_MIPS64)
  448 +/* "half" load and stores. We must do the memory access inline,
  449 + or fault handling won't work. */
  450 +
  451 +#ifdef TARGET_WORDS_BIGENDIAN
  452 +#define GET_LMASK64(v) ((v) & 7)
  453 +#else
  454 +#define GET_LMASK64(v) (((v) & 7) ^ 7)
  455 +#endif
  456 +
  457 +void do_ldl(int mem_idx)
  458 +{
  459 + uint64_t tmp;
  460 +
  461 +#ifdef CONFIG_USER_ONLY
  462 +#define ldfun ldub_raw
  463 +#else
  464 + target_ulong (*ldfun)(target_ulong);
  465 +
  466 + switch (mem_idx)
  467 + {
  468 + case 0: ldfun = ldub_kernel; break;
  469 + case 1: ldfun = ldub_super; break;
  470 + default:
  471 + case 2: ldfun = ldub_user; break;
  472 + }
  473 +#endif
  474 + tmp = ldfun(T0);
  475 + T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
  476 +
  477 + if (GET_LMASK64(T0) <= 6) {
  478 + tmp = ldfun(GET_OFFSET(T0, 1));
  479 + T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
  480 + }
  481 +
  482 + if (GET_LMASK64(T0) <= 5) {
  483 + tmp = ldfun(GET_OFFSET(T0, 2));
  484 + T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
  485 + }
  486 +
  487 + if (GET_LMASK64(T0) <= 4) {
  488 + tmp = ldfun(GET_OFFSET(T0, 3));
  489 + T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
  490 + }
  491 +
  492 + if (GET_LMASK64(T0) <= 3) {
  493 + tmp = ldfun(GET_OFFSET(T0, 4));
  494 + T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
  495 + }
  496 +
  497 + if (GET_LMASK64(T0) <= 2) {
  498 + tmp = ldfun(GET_OFFSET(T0, 5));
  499 + T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
  500 + }
  501 +
  502 + if (GET_LMASK64(T0) <= 1) {
  503 + tmp = ldfun(GET_OFFSET(T0, 6));
  504 + T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
  505 + }
  506 +
  507 + if (GET_LMASK64(T0) == 0) {
  508 + tmp = ldfun(GET_OFFSET(T0, 7));
  509 + T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
  510 + }
  511 +}
  512 +
  513 +void do_ldr(int mem_idx)
  514 +{
  515 + uint64_t tmp;
  516 +
  517 +#ifdef CONFIG_USER_ONLY
  518 +#define ldfun ldub_raw
  519 +#else
  520 + target_ulong (*ldfun)(target_ulong);
  521 +
  522 + switch (mem_idx)
  523 + {
  524 + case 0: ldfun = ldub_kernel; break;
  525 + case 1: ldfun = ldub_super; break;
  526 + default:
  527 + case 2: ldfun = ldub_user; break;
  528 + }
  529 +#endif
  530 + tmp = ldfun(T0);
  531 + T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
  532 +
  533 + if (GET_LMASK64(T0) >= 1) {
  534 + tmp = ldfun(GET_OFFSET(T0, -1));
  535 + T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
  536 + }
  537 +
  538 + if (GET_LMASK64(T0) >= 2) {
  539 + tmp = ldfun(GET_OFFSET(T0, -2));
  540 + T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
  541 + }
  542 +
  543 + if (GET_LMASK64(T0) >= 3) {
  544 + tmp = ldfun(GET_OFFSET(T0, -3));
  545 + T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
  546 + }
  547 +
  548 + if (GET_LMASK64(T0) >= 4) {
  549 + tmp = ldfun(GET_OFFSET(T0, -4));
  550 + T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
  551 + }
  552 +
  553 + if (GET_LMASK64(T0) >= 5) {
  554 + tmp = ldfun(GET_OFFSET(T0, -5));
  555 + T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
  556 + }
  557 +
  558 + if (GET_LMASK64(T0) >= 6) {
  559 + tmp = ldfun(GET_OFFSET(T0, -6));
  560 + T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
  561 + }
  562 +
  563 + if (GET_LMASK64(T0) == 7) {
  564 + tmp = ldfun(GET_OFFSET(T0, -7));
  565 + T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
  566 + }
  567 +}
  568 +
  569 +void do_sdl(int mem_idx)
  570 +{
  571 +#ifdef CONFIG_USER_ONLY
  572 +#define stfun stb_raw
  573 +#else
  574 + void (*stfun)(target_ulong, int);
  575 +
  576 + switch (mem_idx)
  577 + {
  578 + case 0: stfun = stb_kernel; break;
  579 + case 1: stfun = stb_super; break;
  580 + default:
  581 + case 2: stfun = stb_user; break;
  582 + }
  583 +#endif
  584 + stfun(T0, (uint8_t)(T1 >> 56));
  585 +
  586 + if (GET_LMASK64(T0) <= 6)
  587 + stfun(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 48));
  588 +
  589 + if (GET_LMASK64(T0) <= 5)
  590 + stfun(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 40));
  591 +
  592 + if (GET_LMASK64(T0) <= 4)
  593 + stfun(GET_OFFSET(T0, 3), (uint8_t)(T1 >> 32));
  594 +
  595 + if (GET_LMASK64(T0) <= 3)
  596 + stfun(GET_OFFSET(T0, 4), (uint8_t)(T1 >> 24));
  597 +
  598 + if (GET_LMASK64(T0) <= 2)
  599 + stfun(GET_OFFSET(T0, 5), (uint8_t)(T1 >> 16));
  600 +
  601 + if (GET_LMASK64(T0) <= 1)
  602 + stfun(GET_OFFSET(T0, 6), (uint8_t)(T1 >> 8));
  603 +
  604 + if (GET_LMASK64(T0) <= 0)
  605 + stfun(GET_OFFSET(T0, 7), (uint8_t)T1);
  606 +}
  607 +
  608 +void do_sdr(int mem_idx)
  609 +{
  610 +#ifdef CONFIG_USER_ONLY
  611 +#define stfun stb_raw
  612 +#else
  613 + void (*stfun)(target_ulong, int);
  614 +
  615 + switch (mem_idx)
  616 + {
  617 + case 0: stfun = stb_kernel; break;
  618 + case 1: stfun = stb_super; break;
  619 + default:
  620 + case 2: stfun = stb_user; break;
  621 + }
  622 +#endif
  623 + stfun(T0, (uint8_t)T1);
  624 +
  625 + if (GET_LMASK64(T0) >= 1)
  626 + stfun(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
  627 +
  628 + if (GET_LMASK64(T0) >= 2)
  629 + stfun(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
  630 +
  631 + if (GET_LMASK64(T0) >= 3)
  632 + stfun(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
  633 +
  634 + if (GET_LMASK64(T0) >= 4)
  635 + stfun(GET_OFFSET(T0, -4), (uint8_t)(T1 >> 32));
  636 +
  637 + if (GET_LMASK64(T0) >= 5)
  638 + stfun(GET_OFFSET(T0, -5), (uint8_t)(T1 >> 40));
  639 +
  640 + if (GET_LMASK64(T0) >= 6)
  641 + stfun(GET_OFFSET(T0, -6), (uint8_t)(T1 >> 48));
  642 +
  643 + if (GET_LMASK64(T0) == 7)
  644 + stfun(GET_OFFSET(T0, -7), (uint8_t)(T1 >> 56));
  645 +}
  646 +#endif /* TARGET_MIPS64 */
  647 +
311 648 #ifdef CONFIG_USER_ONLY
312 649 void do_mfc0_random (void)
313 650 {
... ...
target-mips/translate.c
... ... @@ -945,37 +945,6 @@ static always_inline void check_mips_64(DisasContext *ctx)
945 945 }
946 946  
947 947 /* load/store instructions. */
948   -#if defined(CONFIG_USER_ONLY)
949   -#define op_ldst(name) gen_op_##name##_raw()
950   -#define OP_LD_TABLE(width)
951   -#define OP_ST_TABLE(width)
952   -#else
953   -#define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
954   -#define OP_LD_TABLE(width) \
955   -static GenOpFunc *gen_op_l##width[] = { \
956   - &gen_op_l##width##_kernel, \
957   - &gen_op_l##width##_super, \
958   - &gen_op_l##width##_user, \
959   -}
960   -#define OP_ST_TABLE(width) \
961   -static GenOpFunc *gen_op_s##width[] = { \
962   - &gen_op_s##width##_kernel, \
963   - &gen_op_s##width##_super, \
964   - &gen_op_s##width##_user, \
965   -}
966   -#endif
967   -
968   -#if defined(TARGET_MIPS64)
969   -OP_LD_TABLE(dl);
970   -OP_LD_TABLE(dr);
971   -OP_ST_TABLE(dl);
972   -OP_ST_TABLE(dr);
973   -#endif
974   -OP_LD_TABLE(wl);
975   -OP_LD_TABLE(wr);
976   -OP_ST_TABLE(wl);
977   -OP_ST_TABLE(wr);
978   -
979 948 #define OP_LD(insn,fname) \
980 949 void inline op_ldst_##insn(DisasContext *ctx) \
981 950 { \
... ... @@ -1094,25 +1063,29 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
1094 1063 opn = "scd";
1095 1064 break;
1096 1065 case OPC_LDL:
  1066 + save_cpu_state(ctx, 1);
1097 1067 gen_load_gpr(cpu_T[1], rt);
1098   - op_ldst(ldl);
  1068 + tcg_gen_helper_0_1i(do_ldl, ctx->mem_idx);
1099 1069 gen_store_gpr(cpu_T[1], rt);
1100 1070 opn = "ldl";
1101 1071 break;
1102 1072 case OPC_SDL:
  1073 + save_cpu_state(ctx, 1);
1103 1074 gen_load_gpr(cpu_T[1], rt);
1104   - op_ldst(sdl);
  1075 + tcg_gen_helper_0_1i(do_sdl, ctx->mem_idx);
1105 1076 opn = "sdl";
1106 1077 break;
1107 1078 case OPC_LDR:
  1079 + save_cpu_state(ctx, 1);
1108 1080 gen_load_gpr(cpu_T[1], rt);
1109   - op_ldst(ldr);
  1081 + tcg_gen_helper_0_1i(do_ldr, ctx->mem_idx);
1110 1082 gen_store_gpr(cpu_T[1], rt);
1111 1083 opn = "ldr";
1112 1084 break;
1113 1085 case OPC_SDR:
  1086 + save_cpu_state(ctx, 1);
1114 1087 gen_load_gpr(cpu_T[1], rt);
1115   - op_ldst(sdr);
  1088 + tcg_gen_helper_0_1i(do_sdr, ctx->mem_idx);
1116 1089 opn = "sdr";
1117 1090 break;
1118 1091 #endif
... ... @@ -1157,25 +1130,29 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
1157 1130 opn = "lbu";
1158 1131 break;
1159 1132 case OPC_LWL:
  1133 + save_cpu_state(ctx, 1);
1160 1134 gen_load_gpr(cpu_T[1], rt);
1161   - op_ldst(lwl);
  1135 + tcg_gen_helper_0_1i(do_lwl, ctx->mem_idx);
1162 1136 gen_store_gpr(cpu_T[1], rt);
1163 1137 opn = "lwl";
1164 1138 break;
1165 1139 case OPC_SWL:
  1140 + save_cpu_state(ctx, 1);
1166 1141 gen_load_gpr(cpu_T[1], rt);
1167   - op_ldst(swl);
  1142 + tcg_gen_helper_0_1i(do_swl, ctx->mem_idx);
1168 1143 opn = "swr";
1169 1144 break;
1170 1145 case OPC_LWR:
  1146 + save_cpu_state(ctx, 1);
1171 1147 gen_load_gpr(cpu_T[1], rt);
1172   - op_ldst(lwr);
  1148 + tcg_gen_helper_0_1i(do_lwr, ctx->mem_idx);
1173 1149 gen_store_gpr(cpu_T[1], rt);
1174 1150 opn = "lwr";
1175 1151 break;
1176 1152 case OPC_SWR:
  1153 + save_cpu_state(ctx, 1);
1177 1154 gen_load_gpr(cpu_T[1], rt);
1178   - op_ldst(swr);
  1155 + tcg_gen_helper_0_1i(do_swr, ctx->mem_idx);
1179 1156 opn = "swr";
1180 1157 break;
1181 1158 case OPC_LL:
... ...