--- trunk/src/cpus/cpu_ppc_instr_loadstore.c 2007/10/08 16:18:51 14 +++ trunk/src/cpus/cpu_ppc_instr_loadstore.c 2007/10/08 16:19:23 20 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: cpu_ppc_instr_loadstore.c,v 1.1 2005/08/29 14:36:41 debug Exp $ + * $Id: cpu_ppc_instr_loadstore.c,v 1.6 2005/11/23 06:59:52 debug Exp $ * * POWER/PowerPC load/store instructions. * @@ -52,9 +52,16 @@ #endif unsigned char data[LS_SIZE]; + /* Synchronize the PC: */ + int low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page) + / sizeof(struct ppc_instr_call); + cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT); + cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT); + #ifndef LS_B - if (addr & (LS_SIZE-1)) { - fatal("PPC LOAD/STORE misalignment: TODO\n"); + if ((addr & 0xfff) + LS_SIZE-1 > 0xfff) { + fatal("PPC LOAD/STORE misalignment across page boundary: TODO" + " (addr=0x%08x, LS_SIZE=%i)\n", (int)addr, LS_SIZE); exit(1); } #endif @@ -62,8 +69,8 @@ #ifdef LS_LOAD if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data), MEM_READ, CACHE_DATA)) { - fatal("load failed: TODO\n"); - exit(1); + /* Exception. */ + return; } #ifdef LS_B reg(ic->arg[0]) = @@ -74,26 +81,36 @@ #endif #ifdef LS_H reg(ic->arg[0]) = +#ifdef LS_BYTEREVERSE + ((data[1] << 8) + data[0]); +#else #ifndef LS_ZERO (int16_t) #endif ((data[0] << 8) + data[1]); +#endif /* !BYTEREVERSE */ #endif #ifdef LS_W reg(ic->arg[0]) = +#ifdef LS_BYTEREVERSE + ((data[3] << 24) + (data[2] << 16) + + (data[1] << 8) + data[0]); +#else /* !LS_BYTEREVERSE */ #ifndef LS_ZERO (int32_t) +#else + (uint32_t) #endif ((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]); +#endif /* !LS_BYTEREVERSE */ #endif #ifdef LS_D - reg(ic->arg[0]) = - ((uint64_t)data[0] << 56) + - ((uint64_t)data[1] << 48) + - ((uint64_t)data[2] << 40) + - ((uint64_t)data[3] << 32) + - (data[4] << 24) + (data[5] << 16) + (data[6] << 8) + data[7]; + (*(uint64_t *)(ic->arg[0])) = + ((uint64_t)data[0] << 56) + ((uint64_t)data[1] << 48) + + ((uint64_t)data[2] << 40) + ((uint64_t)data[3] << 32) + + ((uint64_t)data[4] << 24) + (data[5] << 16) + + (data[6] << 8) + data[7]; #endif #else /* store: */ @@ -102,29 +119,42 @@ data[0] = reg(ic->arg[0]); #endif #ifdef LS_H +#ifdef LS_BYTEREVERSE + data[0] = reg(ic->arg[0]); + data[1] = reg(ic->arg[0]) >> 8; +#else data[0] = reg(ic->arg[0]) >> 8; data[1] = reg(ic->arg[0]); #endif +#endif #ifdef LS_W +#ifdef LS_BYTEREVERSE + data[0] = reg(ic->arg[0]); + data[1] = reg(ic->arg[0]) >> 8; + data[2] = reg(ic->arg[0]) >> 16; + data[3] = reg(ic->arg[0]) >> 24; +#else data[0] = reg(ic->arg[0]) >> 24; data[1] = reg(ic->arg[0]) >> 16; data[2] = reg(ic->arg[0]) >> 8; data[3] = reg(ic->arg[0]); +#endif /* !LS_BYTEREVERSE */ #endif #ifdef LS_D - data[0] = (uint64_t)reg(ic->arg[0]) >> 56; - data[1] = (uint64_t)reg(ic->arg[0]) >> 48; - data[2] = (uint64_t)reg(ic->arg[0]) >> 40; - data[3] = (uint64_t)reg(ic->arg[0]) >> 32; - data[4] = reg(ic->arg[0]) >> 24; - data[5] = reg(ic->arg[0]) >> 16; - data[6] = reg(ic->arg[0]) >> 8; - data[7] = reg(ic->arg[0]); + { uint64_t x = *(uint64_t *)(ic->arg[0]); + data[0] = x >> 56; + data[1] = x >> 48; + data[2] = x >> 40; + data[3] = x >> 32; + data[4] = x >> 24; + data[5] = x >> 16; + data[6] = x >> 8; + data[7] = x; } #endif if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data), MEM_WRITE, CACHE_DATA)) { - fatal("store failed: TODO\n"); - exit(1); + /* Exception. */ + return; } #endif @@ -164,14 +194,6 @@ #ifndef LS_B if (addr & (LS_SIZE-1)) { - fatal("PPC LOAD/STORE misalignment: TODO\n"); - exit(1); - -/* - * TODO: - * Removing the fatal() call above causes WEIRD BUGS with compaq's cc! :( - */ - LS_GENERIC_N(cpu, ic); return; } @@ -193,26 +215,37 @@ #endif /* LS_B */ #ifdef LS_H reg(ic->arg[0]) = +#ifdef LS_BYTEREVERSE + ((page[addr+1] << 8) + page[addr]); +#else #ifndef LS_ZERO (int16_t) #endif ((page[addr] << 8) + page[addr+1]); +#endif /* !BYTEREVERSE */ #endif /* LS_H */ #ifdef LS_W reg(ic->arg[0]) = +#ifdef LS_BYTEREVERSE + ((page[addr+3] << 24) + (page[addr+2] << 16) + + (page[addr+1] << 8) + page[addr]); +#else /* !LS_BYTEREVERSE */ #ifndef LS_ZERO (int32_t) +#else + (uint32_t) #endif ((page[addr] << 24) + (page[addr+1] << 16) + (page[addr+2] << 8) + page[addr+3]); +#endif /* !LS_BYTEREVERSE */ #endif /* LS_W */ #ifdef LS_D - reg(ic->arg[0]) = + (*(uint64_t *)(ic->arg[0])) = ((uint64_t)page[addr+0] << 56) + ((uint64_t)page[addr+1] << 48) + ((uint64_t)page[addr+2] << 40) + ((uint64_t)page[addr+3] << 32) + - (page[addr+4] << 24) + (page[addr+5] << 16) + + ((uint64_t)page[addr+4] << 24) + (page[addr+5] << 16) + (page[addr+6] << 8) + page[addr+7]; #endif /* LS_D */ @@ -223,24 +256,37 @@ page[addr] = reg(ic->arg[0]); #endif #ifdef LS_H +#ifdef LS_BYTEREVERSE + page[addr] = reg(ic->arg[0]); + page[addr+1] = reg(ic->arg[0]) >> 8; +#else page[addr] = reg(ic->arg[0]) >> 8; page[addr+1] = reg(ic->arg[0]); +#endif /* !BYTEREVERSE */ #endif #ifdef LS_W +#ifdef LS_BYTEREVERSE + page[addr] = reg(ic->arg[0]); + page[addr+1] = reg(ic->arg[0]) >> 8; + page[addr+2] = reg(ic->arg[0]) >> 16; + page[addr+3] = reg(ic->arg[0]) >> 24; +#else page[addr] = reg(ic->arg[0]) >> 24; page[addr+1] = reg(ic->arg[0]) >> 16; page[addr+2] = reg(ic->arg[0]) >> 8; page[addr+3] = reg(ic->arg[0]); +#endif /* !LS_BYTEREVERSE */ #endif #ifdef LS_D - page[addr] = (uint64_t)reg(ic->arg[0]) >> 56; - page[addr+1] = (uint64_t)reg(ic->arg[0]) >> 48; - page[addr+2] = (uint64_t)reg(ic->arg[0]) >> 40; - page[addr+3] = (uint64_t)reg(ic->arg[0]) >> 32; - page[addr+4] = reg(ic->arg[0]) >> 24; - page[addr+5] = reg(ic->arg[0]) >> 16; - page[addr+6] = reg(ic->arg[0]) >> 8; - page[addr+7] = reg(ic->arg[0]); + { uint64_t x = *(uint64_t *)(ic->arg[0]); + page[addr] = x >> 56; + page[addr+1] = x >> 48; + page[addr+2] = x >> 40; + page[addr+3] = x >> 32; + page[addr+4] = x >> 24; + page[addr+5] = x >> 16; + page[addr+6] = x >> 8; + page[addr+7] = x; } #endif #endif /* !LS_LOAD */ }