Commit 93b12ccc62debf438f0881898e6be0eeb51e1bdd
1 parent
cfc05abe
Fix indexed FP load/store instructions.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2837 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
31 additions
and
41 deletions
target-mips/op.c
... | ... | @@ -3,6 +3,7 @@ |
3 | 3 | * |
4 | 4 | * Copyright (c) 2004-2005 Jocelyn Mayer |
5 | 5 | * Copyright (c) 2006 Marius Groeger (FPU operations) |
6 | + * Copyright (c) 2007 Thiemo Seufer (64-bit FPU support) | |
6 | 7 | * |
7 | 8 | * This library is free software; you can redistribute it and/or |
8 | 9 | * modify it under the terms of the GNU Lesser General Public | ... | ... |
target-mips/op_mem.c
... | ... | @@ -220,35 +220,13 @@ void glue(op_sdc1, MEMSUFFIX) (void) |
220 | 220 | glue(stq, MEMSUFFIX)(T0, DT0); |
221 | 221 | RETURN(); |
222 | 222 | } |
223 | -void glue(op_lwxc1, MEMSUFFIX) (void) | |
224 | -{ | |
225 | - WT0 = glue(ldl, MEMSUFFIX)(T0 + T1); | |
226 | - RETURN(); | |
227 | -} | |
228 | -void glue(op_swxc1, MEMSUFFIX) (void) | |
229 | -{ | |
230 | - glue(stl, MEMSUFFIX)(T0 + T1, WT0); | |
231 | - RETURN(); | |
232 | -} | |
233 | -void glue(op_ldxc1, MEMSUFFIX) (void) | |
234 | -{ | |
235 | - DT0 = glue(ldq, MEMSUFFIX)(T0 + T1); | |
236 | - RETURN(); | |
237 | -} | |
238 | -void glue(op_sdxc1, MEMSUFFIX) (void) | |
239 | -{ | |
240 | - glue(stq, MEMSUFFIX)(T0 + T1, DT0); | |
241 | - RETURN(); | |
242 | -} | |
243 | 223 | void glue(op_luxc1, MEMSUFFIX) (void) |
244 | 224 | { |
245 | - /* XXX: is defined as unaligned */ | |
246 | - DT0 = glue(ldq, MEMSUFFIX)(T0 + T1); | |
225 | + DT0 = glue(ldq, MEMSUFFIX)(T0 & ~0x7); | |
247 | 226 | RETURN(); |
248 | 227 | } |
249 | 228 | void glue(op_suxc1, MEMSUFFIX) (void) |
250 | 229 | { |
251 | - /* XXX: is defined as unaligned */ | |
252 | - glue(stq, MEMSUFFIX)(T0 + T1, DT0); | |
230 | + glue(stq, MEMSUFFIX)(T0 & ~0x7, DT0); | |
253 | 231 | RETURN(); |
254 | 232 | } | ... | ... |
target-mips/translate.c
... | ... | @@ -711,10 +711,6 @@ OP_LD_TABLE(wc1); |
711 | 711 | OP_ST_TABLE(wc1); |
712 | 712 | OP_LD_TABLE(dc1); |
713 | 713 | OP_ST_TABLE(dc1); |
714 | -OP_LD_TABLE(wxc1); | |
715 | -OP_ST_TABLE(wxc1); | |
716 | -OP_LD_TABLE(dxc1); | |
717 | -OP_ST_TABLE(dxc1); | |
718 | 714 | OP_LD_TABLE(uxc1); |
719 | 715 | OP_ST_TABLE(uxc1); |
720 | 716 | |
... | ... | @@ -1092,7 +1088,7 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, |
1092 | 1088 | return; |
1093 | 1089 | } |
1094 | 1090 | GEN_STORE_TN_REG(rt, T0); |
1095 | - MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm); | |
1091 | + MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm); | |
1096 | 1092 | } |
1097 | 1093 | |
1098 | 1094 | /* Arithmetic */ |
... | ... | @@ -5242,25 +5238,36 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
5242 | 5238 | |
5243 | 5239 | /* Coprocessor 3 (FPU) */ |
5244 | 5240 | static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, int fd, |
5245 | - int base, int index) | |
5241 | + int fs, int base, int index) | |
5246 | 5242 | { |
5247 | 5243 | const char *opn = "extended float load/store"; |
5244 | + int store = 0; | |
5248 | 5245 | |
5249 | 5246 | /* All of those work only on 64bit FPUs. */ |
5250 | 5247 | gen_op_cp1_64bitmode(); |
5251 | - GEN_LOAD_REG_TN(T0, base); | |
5252 | - GEN_LOAD_REG_TN(T1, index); | |
5248 | + if (base == 0) { | |
5249 | + if (index == 0) | |
5250 | + gen_op_reset_T0(); | |
5251 | + else | |
5252 | + GEN_LOAD_REG_TN(T0, index); | |
5253 | + } else if (index == 0) { | |
5254 | + GEN_LOAD_REG_TN(T0, base); | |
5255 | + } else { | |
5256 | + GEN_LOAD_REG_TN(T0, base); | |
5257 | + GEN_LOAD_REG_TN(T1, index); | |
5258 | + gen_op_addr_add(); | |
5259 | + } | |
5253 | 5260 | /* Don't do NOP if destination is zero: we must perform the actual |
5254 | 5261 | * memory access |
5255 | 5262 | */ |
5256 | 5263 | switch (opc) { |
5257 | 5264 | case OPC_LWXC1: |
5258 | - op_ldst(lwxc1); | |
5265 | + op_ldst(lwc1); | |
5259 | 5266 | GEN_STORE_FTN_FREG(fd, WT0); |
5260 | 5267 | opn = "lwxc1"; |
5261 | 5268 | break; |
5262 | 5269 | case OPC_LDXC1: |
5263 | - op_ldst(ldxc1); | |
5270 | + op_ldst(ldc1); | |
5264 | 5271 | GEN_STORE_FTN_FREG(fd, DT0); |
5265 | 5272 | opn = "ldxc1"; |
5266 | 5273 | break; |
... | ... | @@ -5270,26 +5277,30 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, int fd, |
5270 | 5277 | opn = "luxc1"; |
5271 | 5278 | break; |
5272 | 5279 | case OPC_SWXC1: |
5273 | - GEN_LOAD_FREG_FTN(WT0, fd); | |
5274 | - op_ldst(swxc1); | |
5280 | + GEN_LOAD_FREG_FTN(WT0, fs); | |
5281 | + op_ldst(swc1); | |
5275 | 5282 | opn = "swxc1"; |
5283 | + store = 1; | |
5276 | 5284 | break; |
5277 | 5285 | case OPC_SDXC1: |
5278 | - GEN_LOAD_FREG_FTN(DT0, fd); | |
5279 | - op_ldst(sdxc1); | |
5286 | + GEN_LOAD_FREG_FTN(DT0, fs); | |
5287 | + op_ldst(sdc1); | |
5280 | 5288 | opn = "sdxc1"; |
5289 | + store = 1; | |
5281 | 5290 | break; |
5282 | 5291 | case OPC_SUXC1: |
5283 | - GEN_LOAD_FREG_FTN(DT0, fd); | |
5292 | + GEN_LOAD_FREG_FTN(DT0, fs); | |
5284 | 5293 | op_ldst(suxc1); |
5285 | 5294 | opn = "suxc1"; |
5295 | + store = 1; | |
5286 | 5296 | break; |
5287 | 5297 | default: |
5288 | 5298 | MIPS_INVAL(opn); |
5289 | 5299 | generate_exception(ctx, EXCP_RI); |
5290 | 5300 | return; |
5291 | 5301 | } |
5292 | - MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[fd],regnames[index], regnames[base]); | |
5302 | + MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd], | |
5303 | + regnames[index], regnames[base]); | |
5293 | 5304 | } |
5294 | 5305 | |
5295 | 5306 | static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd, |
... | ... | @@ -5882,7 +5893,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
5882 | 5893 | case OPC_SWXC1: |
5883 | 5894 | case OPC_SDXC1: |
5884 | 5895 | case OPC_SUXC1: |
5885 | - gen_flt3_ldst(ctx, op1, sa, rs, rt); | |
5896 | + gen_flt3_ldst(ctx, op1, sa, rd, rs, rt); | |
5886 | 5897 | break; |
5887 | 5898 | case OPC_PREFX: |
5888 | 5899 | /* treat as noop */ | ... | ... |