Commit 4e9f853731f060236d9036663c12ca0594395d0d

Authored by ths
1 parent 0e21e12b

Fix [ls][wd][lr] instructions, by Aurelien Jarno.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3372 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -658,7 +658,7 @@ endif
658 658 ifeq ($(TARGET_BASE_ARCH), mips)
659 659 helper.o: cpu.h exec-all.h
660 660 op.o: op_template.c fop_template.c op_mem.c exec.h cpu.h
661   -op_helper.o: op_helper_mem.c exec.h softmmu_template.h cpu.h
  661 +op_helper.o: exec.h softmmu_template.h cpu.h
662 662 translate.o: translate_init.c exec-all.h disas.h
663 663 endif
664 664  
... ...
target-mips/exec.h
... ... @@ -100,36 +100,6 @@ void fpu_dump_state(CPUState *env, FILE *f,
100 100 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
101 101 int flags);
102 102 void dump_sc (void);
103   -void do_lwl_raw (uint32_t);
104   -void do_lwr_raw (uint32_t);
105   -uint32_t do_swl_raw (uint32_t);
106   -uint32_t do_swr_raw (uint32_t);
107   -#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
108   -void do_ldl_raw (uint64_t);
109   -void do_ldr_raw (uint64_t);
110   -uint64_t do_sdl_raw (uint64_t);
111   -uint64_t do_sdr_raw (uint64_t);
112   -#endif
113   -#if !defined(CONFIG_USER_ONLY)
114   -void do_lwl_user (uint32_t);
115   -void do_lwl_kernel (uint32_t);
116   -void do_lwr_user (uint32_t);
117   -void do_lwr_kernel (uint32_t);
118   -uint32_t do_swl_user (uint32_t);
119   -uint32_t do_swl_kernel (uint32_t);
120   -uint32_t do_swr_user (uint32_t);
121   -uint32_t do_swr_kernel (uint32_t);
122   -#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
123   -void do_ldl_user (uint64_t);
124   -void do_ldl_kernel (uint64_t);
125   -void do_ldr_user (uint64_t);
126   -void do_ldr_kernel (uint64_t);
127   -uint64_t do_sdl_user (uint64_t);
128   -uint64_t do_sdl_kernel (uint64_t);
129   -uint64_t do_sdr_user (uint64_t);
130   -uint64_t do_sdr_kernel (uint64_t);
131   -#endif
132   -#endif
133 103 void do_pmon (int function);
134 104  
135 105 void dump_sc (void);
... ...
target-mips/op_helper.c
... ... @@ -62,18 +62,6 @@ void do_raise_exception_direct (uint32_t exception)
62 62 do_raise_exception_direct_err (exception, 0);
63 63 }
64 64  
65   -#define MEMSUFFIX _raw
66   -#include "op_helper_mem.c"
67   -#undef MEMSUFFIX
68   -#if !defined(CONFIG_USER_ONLY)
69   -#define MEMSUFFIX _user
70   -#include "op_helper_mem.c"
71   -#undef MEMSUFFIX
72   -#define MEMSUFFIX _kernel
73   -#include "op_helper_mem.c"
74   -#undef MEMSUFFIX
75   -#endif
76   -
77 65 #if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
78 66 #if TARGET_LONG_BITS > HOST_LONG_BITS
79 67 /* Those might call libgcc functions. */
... ...
target-mips/op_mem.c
... ... @@ -75,34 +75,92 @@ void glue(op_sw, MEMSUFFIX) (void)
75 75  
76 76 /* "half" load and stores. We must do the memory access inline,
77 77 or fault handling won't work. */
78   -/* XXX: This is broken, CP0_BADVADDR has the wrong (aligned) value. */
  78 +
  79 +#ifdef TARGET_WORDS_BIGENDIAN
  80 +#define GET_LMASK(v) ((v) & 3)
  81 +#define GET_OFFSET(addr, offset) (addr + (offset))
  82 +#else
  83 +#define GET_LMASK(v) (((v) & 3) ^ 3)
  84 +#define GET_OFFSET(addr, offset) (addr - (offset))
  85 +#endif
  86 +
79 87 void glue(op_lwl, MEMSUFFIX) (void)
80 88 {
81   - uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
82   - CALL_FROM_TB1(glue(do_lwl, MEMSUFFIX), tmp);
  89 + target_ulong tmp;
  90 +
  91 + tmp = glue(ldub, MEMSUFFIX)(T0);
  92 + T1 = (int32_t)((T1 & 0x00FFFFFF) | (tmp << 24));
  93 +
  94 + if (GET_LMASK(T0) <= 2) {
  95 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
  96 + T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
  97 + }
  98 +
  99 + if (GET_LMASK(T0) <= 1) {
  100 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
  101 + T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
  102 + }
  103 +
  104 + if (GET_LMASK(T0) == 0) {
  105 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
  106 + T1 = (T1 & 0xFFFFFF00) | tmp;
  107 + }
83 108 RETURN();
84 109 }
85 110  
86 111 void glue(op_lwr, MEMSUFFIX) (void)
87 112 {
88   - uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
89   - CALL_FROM_TB1(glue(do_lwr, MEMSUFFIX), tmp);
  113 + target_ulong tmp;
  114 +
  115 + tmp = glue(ldub, MEMSUFFIX)(T0);
  116 + T1 = (T1 & 0xFFFFFF00) | tmp;
  117 +
  118 + if (GET_LMASK(T0) >= 1) {
  119 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
  120 + T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
  121 + }
  122 +
  123 + if (GET_LMASK(T0) >= 2) {
  124 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
  125 + T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
  126 + }
  127 +
  128 + if (GET_LMASK(T0) == 3) {
  129 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
  130 + T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
  131 + }
90 132 RETURN();
91 133 }
92 134  
93 135 void glue(op_swl, MEMSUFFIX) (void)
94 136 {
95   - uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
96   - tmp = CALL_FROM_TB1(glue(do_swl, MEMSUFFIX), tmp);
97   - glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
  137 + glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 24));
  138 +
  139 + if (GET_LMASK(T0) <= 2)
  140 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 16));
  141 +
  142 + if (GET_LMASK(T0) <= 1)
  143 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 8));
  144 +
  145 + if (GET_LMASK(T0) == 0)
  146 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)T1);
  147 +
98 148 RETURN();
99 149 }
100 150  
101 151 void glue(op_swr, MEMSUFFIX) (void)
102 152 {
103   - uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
104   - tmp = CALL_FROM_TB1(glue(do_swr, MEMSUFFIX), tmp);
105   - glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
  153 + glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
  154 +
  155 + if (GET_LMASK(T0) >= 1)
  156 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
  157 +
  158 + if (GET_LMASK(T0) >= 2)
  159 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
  160 +
  161 + if (GET_LMASK(T0) == 3)
  162 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
  163 +
106 164 RETURN();
107 165 }
108 166  
... ... @@ -145,33 +203,156 @@ void glue(op_sd, MEMSUFFIX) (void)
145 203  
146 204 /* "half" load and stores. We must do the memory access inline,
147 205 or fault handling won't work. */
  206 +
  207 +#ifdef TARGET_WORDS_BIGENDIAN
  208 +#define GET_LMASK64(v) ((v) & 7)
  209 +#else
  210 +#define GET_LMASK64(v) (((v) & 7) ^ 7)
  211 +#endif
  212 +
148 213 void glue(op_ldl, MEMSUFFIX) (void)
149 214 {
150   - target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
151   - CALL_FROM_TB1(glue(do_ldl, MEMSUFFIX), tmp);
  215 + uint64_t tmp;
  216 +
  217 + tmp = glue(ldub, MEMSUFFIX)(T0);
  218 + T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
  219 +
  220 + if (GET_LMASK64(T0) <= 6) {
  221 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
  222 + T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
  223 + }
  224 +
  225 + if (GET_LMASK64(T0) <= 5) {
  226 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
  227 + T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
  228 + }
  229 +
  230 + if (GET_LMASK64(T0) <= 4) {
  231 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
  232 + T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
  233 + }
  234 +
  235 + if (GET_LMASK64(T0) <= 3) {
  236 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 4));
  237 + T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
  238 + }
  239 +
  240 + if (GET_LMASK64(T0) <= 2) {
  241 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 5));
  242 + T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
  243 + }
  244 +
  245 + if (GET_LMASK64(T0) <= 1) {
  246 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 6));
  247 + T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
  248 + }
  249 +
  250 + if (GET_LMASK64(T0) == 0) {
  251 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 7));
  252 + T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
  253 + }
  254 +
152 255 RETURN();
153 256 }
154 257  
155 258 void glue(op_ldr, MEMSUFFIX) (void)
156 259 {
157   - target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
158   - CALL_FROM_TB1(glue(do_ldr, MEMSUFFIX), tmp);
  260 + uint64_t tmp;
  261 +
  262 + tmp = glue(ldub, MEMSUFFIX)(T0);
  263 + T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
  264 +
  265 + if (GET_LMASK64(T0) >= 1) {
  266 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
  267 + T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
  268 + }
  269 +
  270 + if (GET_LMASK64(T0) >= 2) {
  271 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
  272 + T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
  273 + }
  274 +
  275 + if (GET_LMASK64(T0) >= 3) {
  276 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
  277 + T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
  278 + }
  279 +
  280 + if (GET_LMASK64(T0) >= 4) {
  281 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -4));
  282 + T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
  283 + }
  284 +
  285 + if (GET_LMASK64(T0) >= 5) {
  286 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -5));
  287 + T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
  288 + }
  289 +
  290 + if (GET_LMASK64(T0) >= 6) {
  291 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -6));
  292 + T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
  293 + }
  294 +
  295 + if (GET_LMASK64(T0) == 7) {
  296 + tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -7));
  297 + T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
  298 + }
  299 +
159 300 RETURN();
160 301 }
161 302  
162 303 void glue(op_sdl, MEMSUFFIX) (void)
163 304 {
164   - target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
165   - tmp = CALL_FROM_TB1(glue(do_sdl, MEMSUFFIX), tmp);
166   - glue(stq, MEMSUFFIX)(T0 & ~7, tmp);
  305 + glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 56));
  306 +
  307 + if (GET_LMASK64(T0) <= 6)
  308 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 48));
  309 +
  310 + if (GET_LMASK64(T0) <= 5)
  311 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 40));
  312 +
  313 + if (GET_LMASK64(T0) <= 4)
  314 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)(T1 >> 32));
  315 +
  316 + if (GET_LMASK64(T0) <= 3)
  317 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 4), (uint8_t)(T1 >> 24));
  318 +
  319 + if (GET_LMASK64(T0) <= 2)
  320 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 5), (uint8_t)(T1 >> 16));
  321 +
  322 + if (GET_LMASK64(T0) <= 1)
  323 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 6), (uint8_t)(T1 >> 8));
  324 +
  325 + if (GET_LMASK64(T0) <= 0)
  326 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 7), (uint8_t)T1);
  327 +
167 328 RETURN();
168 329 }
169 330  
170 331 void glue(op_sdr, MEMSUFFIX) (void)
171 332 {
172   - target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
173   - tmp = CALL_FROM_TB1(glue(do_sdr, MEMSUFFIX), tmp);
174   - glue(stq, MEMSUFFIX)(T0 & ~7, tmp);
  333 + glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
  334 +
  335 + if (GET_LMASK64(T0) >= 1)
  336 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
  337 +
  338 + if (GET_LMASK64(T0) >= 2)
  339 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
  340 +
  341 + if (GET_LMASK64(T0) >= 3)
  342 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
  343 +
  344 + if (GET_LMASK64(T0) >= 4)
  345 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -4), (uint8_t)(T1 >> 32));
  346 +
  347 + if (GET_LMASK64(T0) >= 5)
  348 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -5), (uint8_t)(T1 >> 40));
  349 +
  350 + if (GET_LMASK64(T0) >= 6)
  351 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -6), (uint8_t)(T1 >> 48));
  352 +
  353 + if (GET_LMASK64(T0) == 7)
  354 + glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -7), (uint8_t)(T1 >> 56));
  355 +
175 356 RETURN();
176 357 }
177 358  
... ...
target-mips/translate.c
... ... @@ -889,7 +889,7 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
889 889 case OPC_LDL:
890 890 GEN_LOAD_REG_TN(T1, rt);
891 891 op_ldst(ldl);
892   - GEN_STORE_TN_REG(rt, T0);
  892 + GEN_STORE_TN_REG(rt, T1);
893 893 opn = "ldl";
894 894 break;
895 895 case OPC_SDL:
... ... @@ -900,7 +900,7 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
900 900 case OPC_LDR:
901 901 GEN_LOAD_REG_TN(T1, rt);
902 902 op_ldst(ldr);
903   - GEN_STORE_TN_REG(rt, T0);
  903 + GEN_STORE_TN_REG(rt, T1);
904 904 opn = "ldr";
905 905 break;
906 906 case OPC_SDR:
... ... @@ -952,7 +952,7 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
952 952 case OPC_LWL:
953 953 GEN_LOAD_REG_TN(T1, rt);
954 954 op_ldst(lwl);
955   - GEN_STORE_TN_REG(rt, T0);
  955 + GEN_STORE_TN_REG(rt, T1);
956 956 opn = "lwl";
957 957 break;
958 958 case OPC_SWL:
... ... @@ -963,7 +963,7 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
963 963 case OPC_LWR:
964 964 GEN_LOAD_REG_TN(T1, rt);
965 965 op_ldst(lwr);
966   - GEN_STORE_TN_REG(rt, T0);
  966 + GEN_STORE_TN_REG(rt, T1);
967 967 opn = "lwr";
968 968 break;
969 969 case OPC_SWR:
... ...