diff options
-rw-r--r-- | sim/mips/ChangeLog | 28 | ||||
-rw-r--r-- | sim/mips/cp1.c | 35 | ||||
-rw-r--r-- | sim/mips/interp.c | 160 | ||||
-rw-r--r-- | sim/mips/mips.igen | 21 |
4 files changed, 190 insertions, 54 deletions
diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog index 44fd87f..b6e956e 100644 --- a/sim/mips/ChangeLog +++ b/sim/mips/ChangeLog @@ -1,3 +1,31 @@ +2007-02-19 Thiemo Seufer <ths@mips.com> + Nigel Stephens <nigel@mips.com> + David Ung <davidu@mips.com> + + * cp1.c (value_fpr): Don't inherit existing FPR_STATE for + uninterpreted formats. If fmt is one of the uninterpreted types + don't update the FPR_STATE. Handle fmt_uninterpreted_32 like + fmt_word, and fmt_uninterpreted_64 like fmt_long. + (store_fpr): When writing an invalid odd register, set the + matching even register to fmt_unknown, not the following register. + * interp.c (sim_open): If STATE_MEM_SIZE isn't set then set it to + the the memory window at offset 0 set by --memory-size command + line option. + (sim_store_register): Handle storing 4 bytes to an 8 byte floating + point register. + (sim_fetch_register): Likewise for reading 4 bytes from an 8 byte + register. + (sim_monitor): When returning the memory size to the MIPS + application, use the value in STATE_MEM_SIZE, not an arbitrary + hardcoded value. + (cop_lw): Don' mess around with FPR_STATE, just pass + fmt_uninterpreted_32 to StoreFPR. + (cop_sw): Similarly. + (cop_ld): Pass fmt_uninterpreted_64 not fmt_uninterpreted. + (cop_sd): Similarly. + * mips.igen (not_word_value): Single version for mips32, mips64 + and mips16. + 2007-02-19 Thiemo Seufer <ths@mips.com> Nigel Stephens <nigel@mips.com> diff --git a/sim/mips/cp1.c b/sim/mips/cp1.c index 5e569ef..d8ee00e 100644 --- a/sim/mips/cp1.c +++ b/sim/mips/cp1.c @@ -111,10 +111,10 @@ value_fpr (sim_cpu *cpu, int err = 0; /* Treat unused register values, as fixed-point 64bit values. */ - if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown)) + if (fmt == fmt_unknown) { #if 1 - /* If request to read data as "uninterpreted", then use the current + /* If request to read data as "unknown", then use the current encoding: */ fmt = FPR_STATE[fpr]; #else @@ -123,20 +123,23 @@ value_fpr (sim_cpu *cpu, } /* For values not yet accessed, set to the desired format. */ - if (FPR_STATE[fpr] == fmt_uninterpreted) + if (fmt < fmt_uninterpreted) { - FPR_STATE[fpr] = fmt; + if (FPR_STATE[fpr] == fmt_uninterpreted) + { + FPR_STATE[fpr] = fmt; #ifdef DEBUG - printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr, - fpu_format_name (fmt)); + printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr, + fpu_format_name (fmt)); #endif /* DEBUG */ - } - if (fmt != FPR_STATE[fpr]) - { - sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n", - fpr, fpu_format_name (FPR_STATE[fpr]), - fpu_format_name (fmt), pr_addr (cia)); - FPR_STATE[fpr] = fmt_unknown; + } + else if (fmt != FPR_STATE[fpr]) + { + sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n", + fpr, fpu_format_name (FPR_STATE[fpr]), + fpu_format_name (fmt), pr_addr (cia)); + FPR_STATE[fpr] = fmt_unknown; + } } if (FPR_STATE[fpr] == fmt_unknown) @@ -156,11 +159,13 @@ value_fpr (sim_cpu *cpu, { switch (fmt) { + case fmt_uninterpreted_32: case fmt_single: case fmt_word: value = (FGR[fpr] & 0xFFFFFFFF); break; + case fmt_uninterpreted_64: case fmt_uninterpreted: case fmt_double: case fmt_long: @@ -177,11 +182,13 @@ value_fpr (sim_cpu *cpu, { switch (fmt) { + case fmt_uninterpreted_32: case fmt_single: case fmt_word: value = (FGR[fpr] & 0xFFFFFFFF); break; + case fmt_uninterpreted_64: case fmt_uninterpreted: case fmt_double: case fmt_long: @@ -299,7 +306,7 @@ store_fpr (sim_cpu *cpu, else { FPR_STATE[fpr] = fmt_unknown; - FPR_STATE[fpr + 1] = fmt_unknown; + FPR_STATE[fpr ^ 1] = fmt_unknown; SignalException (ReservedInstruction, 0); } break; diff --git a/sim/mips/interp.c b/sim/mips/interp.c index a8921f9..9bef890 100644 --- a/sim/mips/interp.c +++ b/sim/mips/interp.c @@ -131,6 +131,9 @@ static void ColdReset PARAMS((SIM_DESC sd)); /* Note that the monitor code essentially assumes this layout of memory. If you change these, change the monitor code, too. */ +/* FIXME Currently addresses are truncated to 32-bits, see + mips/sim-main.c:address_translation(). If that changes, then these + values will need to be extended, and tested for more carefully. */ #define K0BASE (0x80000000) #define K0SIZE (0x20000000) #define K1BASE (0xA0000000) @@ -365,17 +368,67 @@ sim_open (kind, cb, abfd, argv) if (board == NULL) { /* Allocate core managed memory */ - + sim_memopt *entry, *match = NULL; + address_word mem_size = 0; + int mapped = 0; /* For compatibility with the old code - under this (at level one) are the kernel spaces K0 & K1. Both of these map to a single smaller sub region */ sim_do_command(sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */ - sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x", - K1BASE, K0SIZE, - MEM_SIZE, /* actual size */ - K0BASE); - + + /* Look for largest memory region defined on command-line at + phys address 0. */ +#ifdef SIM_HAVE_FLATMEM + mem_size = STATE_MEM_SIZE (sd); +#endif + for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next) + { + /* If we find an entry at address 0, then we will end up + allocating a new buffer in the "memory alias" command + below. The region at address 0 will be deleted. */ + address_word size = (entry->modulo != 0 + ? entry->modulo : entry->nr_bytes); + if (entry->addr == 0 + && (!match || entry->level < match->level)) + match = entry; + else if (entry->addr == K0BASE || entry->addr == K1BASE) + mapped = 1; + else + { + sim_memopt *alias; + for (alias = entry->alias; alias != NULL; alias = alias->next) + { + if (alias->addr == 0 + && (!match || entry->level < match->level)) + match = entry; + else if (alias->addr == K0BASE || alias->addr == K1BASE) + mapped = 1; + } + } + } + + if (!mapped) + { + if (match) + { + /* Get existing memory region size. */ + mem_size = (match->modulo != 0 + ? match->modulo : match->nr_bytes); + /* Delete old region. */ + sim_do_commandf (sd, "memory delete %d:0x%lx@%d", + match->space, match->addr, match->level); + } + else if (mem_size == 0) + mem_size = MEM_SIZE; + /* Limit to KSEG1 size (512MB) */ + if (mem_size > K1SIZE) + mem_size = K1SIZE; + /* memory alias K1BASE@1,K1SIZE%MEMSIZE,K0BASE */ + sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x", + K1BASE, K1SIZE, (long)mem_size, K0BASE); + } + device_init(sd); } else if (board != NULL @@ -868,8 +921,16 @@ sim_store_register (sd,rn,memory,length) } else { - cpu->fgr[rn - FGR_BASE] = T2H_8 (*(unsigned64*)memory); - return 8; + if (length == 8) + { + cpu->fgr[rn - FGR_BASE] = T2H_8 (*(unsigned64*)memory); + return 8; + } + else + { + cpu->fgr[rn - FGR_BASE] = T2H_4 (*(unsigned32*)memory); + return 4; + } } } @@ -889,8 +950,16 @@ sim_store_register (sd,rn,memory,length) } else { - cpu->registers[rn] = T2H_8 (*(unsigned64*)memory); - return 8; + if (length == 8) + { + cpu->registers[rn] = T2H_8 (*(unsigned64*)memory); + return 8; + } + else + { + cpu->registers[rn] = (signed32) T2H_4(*(unsigned32*)memory); + return 4; + } } return 0; @@ -939,8 +1008,16 @@ sim_fetch_register (sd,rn,memory,length) } else { - *(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGR_BASE]); - return 8; + if (length == 8) + { + *(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGR_BASE]); + return 8; + } + else + { + *(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->fgr[rn - FGR_BASE])); + return 4; + } } } @@ -960,8 +1037,17 @@ sim_fetch_register (sd,rn,memory,length) } else { - *(unsigned64*)memory = H2T_8 ((unsigned64)(cpu->registers[rn])); - return 8; + if (length == 8) + { + *(unsigned64*)memory = + H2T_8 ((unsigned64) (cpu->registers[rn])); + return 8; + } + else + { + *(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->registers[rn])); + return 4; + } } return 0; @@ -1235,8 +1321,39 @@ sim_monitor (SIM_DESC sd, /* [A0 + 4] = instruction cache size */ /* [A0 + 8] = data cache size */ { - unsigned_4 value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */; + unsigned_4 value; unsigned_4 zero = 0; + address_word mem_size; + sim_memopt *entry, *match = NULL; + + /* Search for memory region mapped to KSEG0 or KSEG1. */ + for (entry = STATE_MEMOPT (sd); + entry != NULL; + entry = entry->next) + { + if ((entry->addr == K0BASE || entry->addr == K1BASE) + && (!match || entry->level < match->level)) + match = entry; + else + { + sim_memopt *alias; + for (alias = entry->alias; + alias != NULL; + alias = alias->next) + if ((alias->addr == K0BASE || alias->addr == K1BASE) + && (!match || entry->level < match->level)) + match = entry; + } + } + + /* Get region size, limit to KSEG1 size (512MB). */ + SIM_ASSERT (match != NULL); + mem_size = (match->modulo != 0 + ? match->modulo : match->nr_bytes); + if (mem_size > K1SIZE) + mem_size = K1SIZE; + + value = mem_size; H2T (value); sim_write (sd, A0 + 0, (char *)&value, 4); sim_write (sd, A0 + 4, (char *)&zero, 4); @@ -1924,8 +2041,7 @@ cop_lw (SIM_DESC sd, #ifdef DEBUG printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword)); #endif - StoreFPR(coproc_reg,fmt_word,(uword64)memword); - FPR_STATE[coproc_reg] = fmt_uninterpreted; + StoreFPR(coproc_reg,fmt_uninterpreted_32,(uword64)memword); break; } @@ -1956,7 +2072,7 @@ cop_ld (SIM_DESC sd, case 1: if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) { - StoreFPR(coproc_reg,fmt_uninterpreted,memword); + StoreFPR(coproc_reg,fmt_uninterpreted_64,memword); break; } @@ -1987,11 +2103,7 @@ cop_sw (SIM_DESC sd, case 1: if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) { - FP_formats hold; - hold = FPR_STATE[coproc_reg]; - FPR_STATE[coproc_reg] = fmt_word; - value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted); - FPR_STATE[coproc_reg] = hold; + value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted_32); break; } @@ -2018,7 +2130,7 @@ cop_sd (SIM_DESC sd, case 1: if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) { - value = ValueFPR(coproc_reg,fmt_uninterpreted); + value = ValueFPR(coproc_reg,fmt_uninterpreted_64); break; } diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen index 85d08ea..6109589 100644 --- a/sim/mips/mips.igen +++ b/sim/mips/mips.igen @@ -176,29 +176,18 @@ *vr4100: *vr5000: *r3900: -{ - /* For historical simulator compatibility (until documentation is - found that makes these operations unpredictable on some of these - architectures), this check never returns true. */ - return 0; -} - -:function:::int:not_word_value:unsigned_word value *mips32: *mips32r2: -{ - /* On MIPS32, since registers are 32-bits, there's no check to be done. */ - return 0; -} - -:function:::int:not_word_value:unsigned_word value *mips64: *mips64r2: { - return ((value >> 32) != (value & 0x80000000 ? 0xFFFFFFFF : 0)); +#if WITH_TARGET_WORD_BITSIZE == 64 + return value != (((value & 0xffffffff) ^ 0x80000000) - 0x80000000); +#else + return 0; +#endif } - // Helper: // // Handle UNPREDICTABLE operation behaviour. The goal here is to prevent |