Commit d66c7132d23d41796f374aec2f5aff1fb01479ee
1 parent
324d9e32
target-mips: optimize gen_ldst()
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7093 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
64 additions
and
22 deletions
target-mips/translate.c
| @@ -932,7 +932,7 @@ OP_LD_ATOMIC(lld,ld64); | @@ -932,7 +932,7 @@ OP_LD_ATOMIC(lld,ld64); | ||
| 932 | #define OP_ST_ATOMIC(insn,fname,almask) \ | 932 | #define OP_ST_ATOMIC(insn,fname,almask) \ |
| 933 | static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ | 933 | static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ |
| 934 | { \ | 934 | { \ |
| 935 | - TCGv r_tmp = tcg_temp_local_new(); \ | 935 | + TCGv r_tmp = tcg_temp_new(); \ |
| 936 | int l1 = gen_new_label(); \ | 936 | int l1 = gen_new_label(); \ |
| 937 | int l2 = gen_new_label(); \ | 937 | int l2 = gen_new_label(); \ |
| 938 | int l3 = gen_new_label(); \ | 938 | int l3 = gen_new_label(); \ |
| @@ -944,13 +944,13 @@ static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ | @@ -944,13 +944,13 @@ static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ | ||
| 944 | gen_set_label(l1); \ | 944 | gen_set_label(l1); \ |
| 945 | tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \ | 945 | tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \ |
| 946 | tcg_gen_brcond_tl(TCG_COND_NE, t0, r_tmp, l2); \ | 946 | tcg_gen_brcond_tl(TCG_COND_NE, t0, r_tmp, l2); \ |
| 947 | + tcg_temp_free(r_tmp); \ | ||
| 947 | tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \ | 948 | tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \ |
| 948 | tcg_gen_movi_tl(t0, 1); \ | 949 | tcg_gen_movi_tl(t0, 1); \ |
| 949 | tcg_gen_br(l3); \ | 950 | tcg_gen_br(l3); \ |
| 950 | gen_set_label(l2); \ | 951 | gen_set_label(l2); \ |
| 951 | tcg_gen_movi_tl(t0, 0); \ | 952 | tcg_gen_movi_tl(t0, 0); \ |
| 952 | gen_set_label(l3); \ | 953 | gen_set_label(l3); \ |
| 953 | - tcg_temp_free(r_tmp); \ | ||
| 954 | } | 954 | } |
| 955 | OP_ST_ATOMIC(sc,st32,0x3); | 955 | OP_ST_ATOMIC(sc,st32,0x3); |
| 956 | #if defined(TARGET_MIPS64) | 956 | #if defined(TARGET_MIPS64) |
| @@ -963,8 +963,8 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, | @@ -963,8 +963,8 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, | ||
| 963 | int base, int16_t offset) | 963 | int base, int16_t offset) |
| 964 | { | 964 | { |
| 965 | const char *opn = "ldst"; | 965 | const char *opn = "ldst"; |
| 966 | - TCGv t0 = tcg_temp_local_new(); | ||
| 967 | - TCGv t1 = tcg_temp_local_new(); | 966 | + TCGv t0 = tcg_temp_new(); |
| 967 | + TCGv t1 = tcg_temp_new(); | ||
| 968 | 968 | ||
| 969 | if (base == 0) { | 969 | if (base == 0) { |
| 970 | tcg_gen_movi_tl(t0, offset); | 970 | tcg_gen_movi_tl(t0, offset); |
| @@ -979,32 +979,29 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, | @@ -979,32 +979,29 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, | ||
| 979 | switch (opc) { | 979 | switch (opc) { |
| 980 | #if defined(TARGET_MIPS64) | 980 | #if defined(TARGET_MIPS64) |
| 981 | case OPC_LWU: | 981 | case OPC_LWU: |
| 982 | + save_cpu_state(ctx, 0); | ||
| 982 | op_ldst_lwu(t0, ctx); | 983 | op_ldst_lwu(t0, ctx); |
| 983 | gen_store_gpr(t0, rt); | 984 | gen_store_gpr(t0, rt); |
| 984 | opn = "lwu"; | 985 | opn = "lwu"; |
| 985 | break; | 986 | break; |
| 986 | case OPC_LD: | 987 | case OPC_LD: |
| 988 | + save_cpu_state(ctx, 0); | ||
| 987 | op_ldst_ld(t0, ctx); | 989 | op_ldst_ld(t0, ctx); |
| 988 | gen_store_gpr(t0, rt); | 990 | gen_store_gpr(t0, rt); |
| 989 | opn = "ld"; | 991 | opn = "ld"; |
| 990 | break; | 992 | break; |
| 991 | case OPC_LLD: | 993 | case OPC_LLD: |
| 994 | + save_cpu_state(ctx, 0); | ||
| 992 | op_ldst_lld(t0, t1, ctx); | 995 | op_ldst_lld(t0, t1, ctx); |
| 993 | gen_store_gpr(t0, rt); | 996 | gen_store_gpr(t0, rt); |
| 994 | opn = "lld"; | 997 | opn = "lld"; |
| 995 | break; | 998 | break; |
| 996 | case OPC_SD: | 999 | case OPC_SD: |
| 1000 | + save_cpu_state(ctx, 0); | ||
| 997 | gen_load_gpr(t1, rt); | 1001 | gen_load_gpr(t1, rt); |
| 998 | op_ldst_sd(t0, t1, ctx); | 1002 | op_ldst_sd(t0, t1, ctx); |
| 999 | opn = "sd"; | 1003 | opn = "sd"; |
| 1000 | break; | 1004 | break; |
| 1001 | - case OPC_SCD: | ||
| 1002 | - save_cpu_state(ctx, 1); | ||
| 1003 | - gen_load_gpr(t1, rt); | ||
| 1004 | - op_ldst_scd(t0, t1, ctx); | ||
| 1005 | - gen_store_gpr(t0, rt); | ||
| 1006 | - opn = "scd"; | ||
| 1007 | - break; | ||
| 1008 | case OPC_LDL: | 1005 | case OPC_LDL: |
| 1009 | save_cpu_state(ctx, 1); | 1006 | save_cpu_state(ctx, 1); |
| 1010 | gen_load_gpr(t1, rt); | 1007 | gen_load_gpr(t1, rt); |
| @@ -1033,41 +1030,49 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, | @@ -1033,41 +1030,49 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, | ||
| 1033 | break; | 1030 | break; |
| 1034 | #endif | 1031 | #endif |
| 1035 | case OPC_LW: | 1032 | case OPC_LW: |
| 1033 | + save_cpu_state(ctx, 0); | ||
| 1036 | op_ldst_lw(t0, ctx); | 1034 | op_ldst_lw(t0, ctx); |
| 1037 | gen_store_gpr(t0, rt); | 1035 | gen_store_gpr(t0, rt); |
| 1038 | opn = "lw"; | 1036 | opn = "lw"; |
| 1039 | break; | 1037 | break; |
| 1040 | case OPC_SW: | 1038 | case OPC_SW: |
| 1039 | + save_cpu_state(ctx, 0); | ||
| 1041 | gen_load_gpr(t1, rt); | 1040 | gen_load_gpr(t1, rt); |
| 1042 | op_ldst_sw(t0, t1, ctx); | 1041 | op_ldst_sw(t0, t1, ctx); |
| 1043 | opn = "sw"; | 1042 | opn = "sw"; |
| 1044 | break; | 1043 | break; |
| 1045 | case OPC_LH: | 1044 | case OPC_LH: |
| 1045 | + save_cpu_state(ctx, 0); | ||
| 1046 | op_ldst_lh(t0, ctx); | 1046 | op_ldst_lh(t0, ctx); |
| 1047 | gen_store_gpr(t0, rt); | 1047 | gen_store_gpr(t0, rt); |
| 1048 | opn = "lh"; | 1048 | opn = "lh"; |
| 1049 | break; | 1049 | break; |
| 1050 | case OPC_SH: | 1050 | case OPC_SH: |
| 1051 | + save_cpu_state(ctx, 0); | ||
| 1051 | gen_load_gpr(t1, rt); | 1052 | gen_load_gpr(t1, rt); |
| 1052 | op_ldst_sh(t0, t1, ctx); | 1053 | op_ldst_sh(t0, t1, ctx); |
| 1053 | opn = "sh"; | 1054 | opn = "sh"; |
| 1054 | break; | 1055 | break; |
| 1055 | case OPC_LHU: | 1056 | case OPC_LHU: |
| 1057 | + save_cpu_state(ctx, 0); | ||
| 1056 | op_ldst_lhu(t0, ctx); | 1058 | op_ldst_lhu(t0, ctx); |
| 1057 | gen_store_gpr(t0, rt); | 1059 | gen_store_gpr(t0, rt); |
| 1058 | opn = "lhu"; | 1060 | opn = "lhu"; |
| 1059 | break; | 1061 | break; |
| 1060 | case OPC_LB: | 1062 | case OPC_LB: |
| 1063 | + save_cpu_state(ctx, 0); | ||
| 1061 | op_ldst_lb(t0, ctx); | 1064 | op_ldst_lb(t0, ctx); |
| 1062 | gen_store_gpr(t0, rt); | 1065 | gen_store_gpr(t0, rt); |
| 1063 | opn = "lb"; | 1066 | opn = "lb"; |
| 1064 | break; | 1067 | break; |
| 1065 | case OPC_SB: | 1068 | case OPC_SB: |
| 1069 | + save_cpu_state(ctx, 0); | ||
| 1066 | gen_load_gpr(t1, rt); | 1070 | gen_load_gpr(t1, rt); |
| 1067 | op_ldst_sb(t0, t1, ctx); | 1071 | op_ldst_sb(t0, t1, ctx); |
| 1068 | opn = "sb"; | 1072 | opn = "sb"; |
| 1069 | break; | 1073 | break; |
| 1070 | case OPC_LBU: | 1074 | case OPC_LBU: |
| 1075 | + save_cpu_state(ctx, 0); | ||
| 1071 | op_ldst_lbu(t0, ctx); | 1076 | op_ldst_lbu(t0, ctx); |
| 1072 | gen_store_gpr(t0, rt); | 1077 | gen_store_gpr(t0, rt); |
| 1073 | opn = "lbu"; | 1078 | opn = "lbu"; |
| @@ -1099,26 +1104,57 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, | @@ -1099,26 +1104,57 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, | ||
| 1099 | opn = "swr"; | 1104 | opn = "swr"; |
| 1100 | break; | 1105 | break; |
| 1101 | case OPC_LL: | 1106 | case OPC_LL: |
| 1107 | + save_cpu_state(ctx, 0); | ||
| 1102 | op_ldst_ll(t0, t1, ctx); | 1108 | op_ldst_ll(t0, t1, ctx); |
| 1103 | gen_store_gpr(t0, rt); | 1109 | gen_store_gpr(t0, rt); |
| 1104 | opn = "ll"; | 1110 | opn = "ll"; |
| 1105 | break; | 1111 | break; |
| 1112 | + } | ||
| 1113 | + MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); | ||
| 1114 | + tcg_temp_free(t0); | ||
| 1115 | + tcg_temp_free(t1); | ||
| 1116 | +} | ||
| 1117 | + | ||
| 1118 | +/* Store conditional */ | ||
| 1119 | +static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt, | ||
| 1120 | + int base, int16_t offset) | ||
| 1121 | +{ | ||
| 1122 | + const char *opn = "st_cond"; | ||
| 1123 | + TCGv t0, t1; | ||
| 1124 | + | ||
| 1125 | + t0 = tcg_temp_local_new(); | ||
| 1126 | + | ||
| 1127 | + if (base == 0) { | ||
| 1128 | + tcg_gen_movi_tl(t0, offset); | ||
| 1129 | + } else if (offset == 0) { | ||
| 1130 | + gen_load_gpr(t0, base); | ||
| 1131 | + } else { | ||
| 1132 | + tcg_gen_movi_tl(t0, offset); | ||
| 1133 | + gen_op_addr_add(ctx, t0, cpu_gpr[base]); | ||
| 1134 | + } | ||
| 1135 | + /* Don't do NOP if destination is zero: we must perform the actual | ||
| 1136 | + memory access. */ | ||
| 1137 | + | ||
| 1138 | + t1 = tcg_temp_local_new(); | ||
| 1139 | + gen_load_gpr(t1, rt); | ||
| 1140 | + switch (opc) { | ||
| 1141 | +#if defined(TARGET_MIPS64) | ||
| 1142 | + case OPC_SCD: | ||
| 1143 | + save_cpu_state(ctx, 0); | ||
| 1144 | + op_ldst_scd(t0, t1, ctx); | ||
| 1145 | + opn = "scd"; | ||
| 1146 | + break; | ||
| 1147 | +#endif | ||
| 1106 | case OPC_SC: | 1148 | case OPC_SC: |
| 1107 | - save_cpu_state(ctx, 1); | ||
| 1108 | - gen_load_gpr(t1, rt); | 1149 | + save_cpu_state(ctx, 0); |
| 1109 | op_ldst_sc(t0, t1, ctx); | 1150 | op_ldst_sc(t0, t1, ctx); |
| 1110 | - gen_store_gpr(t0, rt); | ||
| 1111 | opn = "sc"; | 1151 | opn = "sc"; |
| 1112 | break; | 1152 | break; |
| 1113 | - default: | ||
| 1114 | - MIPS_INVAL(opn); | ||
| 1115 | - generate_exception(ctx, EXCP_RI); | ||
| 1116 | - goto out; | ||
| 1117 | } | 1153 | } |
| 1118 | MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); | 1154 | MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); |
| 1119 | - out: | ||
| 1120 | - tcg_temp_free(t0); | ||
| 1121 | tcg_temp_free(t1); | 1155 | tcg_temp_free(t1); |
| 1156 | + gen_store_gpr(t0, rt); | ||
| 1157 | + tcg_temp_free(t0); | ||
| 1122 | } | 1158 | } |
| 1123 | 1159 | ||
| 1124 | /* Load and store */ | 1160 | /* Load and store */ |
| @@ -7997,9 +8033,11 @@ static void decode_opc (CPUState *env, DisasContext *ctx) | @@ -7997,9 +8033,11 @@ static void decode_opc (CPUState *env, DisasContext *ctx) | ||
| 7997 | case OPC_SB ... OPC_SW: | 8033 | case OPC_SB ... OPC_SW: |
| 7998 | case OPC_SWR: | 8034 | case OPC_SWR: |
| 7999 | case OPC_LL: | 8035 | case OPC_LL: |
| 8000 | - case OPC_SC: | ||
| 8001 | gen_ldst(ctx, op, rt, rs, imm); | 8036 | gen_ldst(ctx, op, rt, rs, imm); |
| 8002 | break; | 8037 | break; |
| 8038 | + case OPC_SC: | ||
| 8039 | + gen_st_cond(ctx, op, rt, rs, imm); | ||
| 8040 | + break; | ||
| 8003 | case OPC_CACHE: | 8041 | case OPC_CACHE: |
| 8004 | check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32); | 8042 | check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32); |
| 8005 | /* Treat as NOP. */ | 8043 | /* Treat as NOP. */ |
| @@ -8128,12 +8166,16 @@ static void decode_opc (CPUState *env, DisasContext *ctx) | @@ -8128,12 +8166,16 @@ static void decode_opc (CPUState *env, DisasContext *ctx) | ||
| 8128 | case OPC_SDL ... OPC_SDR: | 8166 | case OPC_SDL ... OPC_SDR: |
| 8129 | case OPC_LLD: | 8167 | case OPC_LLD: |
| 8130 | case OPC_LD: | 8168 | case OPC_LD: |
| 8131 | - case OPC_SCD: | ||
| 8132 | case OPC_SD: | 8169 | case OPC_SD: |
| 8133 | check_insn(env, ctx, ISA_MIPS3); | 8170 | check_insn(env, ctx, ISA_MIPS3); |
| 8134 | check_mips_64(ctx); | 8171 | check_mips_64(ctx); |
| 8135 | gen_ldst(ctx, op, rt, rs, imm); | 8172 | gen_ldst(ctx, op, rt, rs, imm); |
| 8136 | break; | 8173 | break; |
| 8174 | + case OPC_SCD: | ||
| 8175 | + check_insn(env, ctx, ISA_MIPS3); | ||
| 8176 | + check_mips_64(ctx); | ||
| 8177 | + gen_st_cond(ctx, op, rt, rs, imm); | ||
| 8178 | + break; | ||
| 8137 | case OPC_DADDI: | 8179 | case OPC_DADDI: |
| 8138 | case OPC_DADDIU: | 8180 | case OPC_DADDIU: |
| 8139 | check_insn(env, ctx, ISA_MIPS3); | 8181 | check_insn(env, ctx, ISA_MIPS3); |