|
|
| version 1.31, 2012/01/08 18:26:10 | version 1.35, 2012/06/18 14:30:27 |
|---|---|
| Line 31 | Line 31 |
| /* | /* |
| * memory access check | * memory access check |
| */ | */ |
| static int MEMCALL check_limit_upstairs(descriptor_t *sdp, UINT32 offset, UINT len); | static int MEMCALL check_limit_upstairs(descriptor_t *sdp, UINT32 offset, UINT len, BOOL is32bit); |
| static void MEMCALL cpu_memoryread_check(descriptor_t *sdp, UINT32 offset, UINT len, int e); | static void MEMCALL cpu_memoryread_check(descriptor_t *sdp, UINT32 offset, UINT len, int e); |
| static void MEMCALL cpu_memorywrite_check(descriptor_t *sdp, UINT32 offset, UINT len, int e); | static void MEMCALL cpu_memorywrite_check(descriptor_t *sdp, UINT32 offset, UINT len, int e); |
| static int MEMCALL | static int MEMCALL |
| check_limit_upstairs(descriptor_t *sdp, UINT32 offset, UINT len) | check_limit_upstairs(descriptor_t *sdp, UINT32 offset, UINT len, BOOL is32bit) |
| { | { |
| UINT32 limit; | UINT32 limit; |
| UINT32 end; | UINT32 end; |
| Line 46 check_limit_upstairs(descriptor_t *sdp, | Line 46 check_limit_upstairs(descriptor_t *sdp, |
| len--; | len--; |
| end = offset + len; | end = offset + len; |
| limit = SEG_IS_32BIT(sdp) ? 0xffffffff : 0x0000ffff; | |
| if (SEG_IS_DATA(sdp) && SEG_IS_EXPANDDOWN_DATA(sdp)) { | if (SEG_IS_DATA(sdp) && SEG_IS_EXPANDDOWN_DATA(sdp)) { |
| /* expand-down data segment */ | /* expand-down data segment */ |
| limit = SEG_IS_32BIT(sdp) ? 0xffffffff : 0x0000ffff; | |
| if (sdp->u.seg.limit == 0) { | if (sdp->u.seg.limit == 0) { |
| /* | /* |
| * 32bit 16bit | * 32bit 16bit |
| Line 93 check_limit_upstairs(descriptor_t *sdp, | Line 93 check_limit_upstairs(descriptor_t *sdp, |
| } | } |
| } else { | } else { |
| /* expand-up data or code segment */ | /* expand-up data or code segment */ |
| if (sdp->u.seg.limit == limit) { | if (sdp->u.seg.limit == 0xffffffff) { |
| /* | /* |
| * 32bit 16bit | * 16/32bit |
| * +-------+ +-------+ FFFFFFFFh | * +-------+ FFFFFFFFh |
| * | | | | | * | | |
| * | | + [1] + 0000FFFFh | * | | |
| * | valid | | | | * | valid | |
| * | | +-------+ 0000FFFFh - len - 1 | * | | |
| * | | | valid | | * | | |
| * +-------+ +-------+ 00000000h | * +-------+ 00000000h |
| */ | */ |
| if (!SEG_IS_32BIT(sdp)) { | sdp->flag |= CPU_DESC_FLAG_WHOLEADR; |
| if ((len > limit) /* len check */ | |
| || (offset + len > limit)) { /* [1] */ | |
| goto exc; | |
| } | |
| } else { | |
| sdp->flag |= CPU_DESC_FLAG_WHOLEADR; | |
| } | |
| } else { | } else { |
| /* | /* |
| * 32bit 16bit | * 16/32bit |
| * +-------+ +-------+ FFFFFFFFh | * +-------+ FFFFFFFFh |
| * | | | | | * | | |
| * | | +.......+ 0000FFFFh | * | | |
| * | [1] | | [1] | | * | [1] | |
| * +.......+ +.......+ seg.limit | * +.......+ seg.limit |
| * | | | | | * | | |
| * +-------+ +-------+ seg.limit - len - 1 | * +-------+ seg.limit - len - 1 |
| * | valid | | valid | | * | valid | |
| * +-------+ +-------+ 00000000h | * +-------+ 00000000h |
| */ | */ |
| if ((len > sdp->u.seg.limit) /* len check */ | if ((len > sdp->u.seg.limit) /* len check */ |
| || (end < offset) /* wrap check */ | || (end < offset) /* wrap check */ |
| Line 166 cpu_memoryread_check(descriptor_t *sdp, | Line 159 cpu_memoryread_check(descriptor_t *sdp, |
| case 6: case 7: /* rw (expand down) */ | case 6: case 7: /* rw (expand down) */ |
| case 10: case 11: /* rx */ | case 10: case 11: /* rx */ |
| case 14: case 15: /* rxc */ | case 14: case 15: /* rxc */ |
| if (!check_limit_upstairs(sdp, offset, len)) | if (!check_limit_upstairs(sdp, offset, len, SEG_IS_32BIT(sdp))) |
| goto exc; | goto exc; |
| break; | break; |
| Line 205 cpu_memorywrite_check(descriptor_t *sdp, | Line 198 cpu_memorywrite_check(descriptor_t *sdp, |
| switch (sdp->type) { | switch (sdp->type) { |
| case 2: case 3: /* rw */ | case 2: case 3: /* rw */ |
| case 6: case 7: /* rw (expand down) */ | case 6: case 7: /* rw (expand down) */ |
| if (!check_limit_upstairs(sdp, offset, len)) | if (!check_limit_upstairs(sdp, offset, len, SEG_IS_32BIT(sdp))) |
| goto exc; | goto exc; |
| break; | break; |
| Line 224 exc: | Line 217 exc: |
| } | } |
| void MEMCALL | void MEMCALL |
| cpu_stack_push_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len) | cpu_stack_push_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len, |
| BOOL is32bit) | |
| { | { |
| UINT32 limit; | UINT32 limit; |
| UINT32 start; | UINT32 start; |
| Line 243 cpu_stack_push_check(UINT16 s, descripto | Line 237 cpu_stack_push_check(UINT16 s, descripto |
| } | } |
| start = sp - len; | start = sp - len; |
| limit = SEG_IS_32BIT(sdp) ? 0xffffffff : 0x0000ffff; | limit = is32bit ? 0xffffffff : 0x0000ffff; |
| if (SEG_IS_EXPANDDOWN_DATA(sdp)) { | if (SEG_IS_EXPANDDOWN_DATA(sdp)) { |
| /* expand-down stack */ | /* expand-down stack */ |
| Line 342 exc: | Line 336 exc: |
| } | } |
| void MEMCALL | void MEMCALL |
| cpu_stack_pop_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len) | cpu_stack_pop_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len, |
| BOOL is32bit) | |
| { | { |
| __ASSERT(sdp != NULL); | __ASSERT(sdp != NULL); |
| Line 356 cpu_stack_pop_check(UINT16 s, descriptor | Line 351 cpu_stack_pop_check(UINT16 s, descriptor |
| goto exc; | goto exc; |
| } | } |
| if (!check_limit_upstairs(sdp, sp, len)) | if (!check_limit_upstairs(sdp, sp, len, is32bit)) |
| goto exc; | goto exc; |
| return; | return; |
| Line 482 cpu_memorywrite_f(UINT32 paddr, const RE | Line 477 cpu_memorywrite_f(UINT32 paddr, const RE |
| #include "cpu_mem.mcr" | #include "cpu_mem.mcr" |
| VIRTUAL_ADDRESS_MEMORY_ACCESS_FUNCTION(b, UINT8, 1) | DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(b, UINT8, 1) |
| VIRTUAL_ADDRESS_MEMORY_ACCESS_FUNCTION(w, UINT16, 2) | DECLARE_VIRTUAL_ADDRESS_MEMORY_RMW_FUNCTIONS(b, UINT8, 1) |
| VIRTUAL_ADDRESS_MEMORY_ACCESS_FUNCTION(d, UINT32, 4) | DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(w, UINT16, 2) |
| DECLARE_VIRTUAL_ADDRESS_MEMORY_RMW_FUNCTIONS(w, UINT16, 2) | |
| UINT64 MEMCALL | DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(d, UINT32, 4) |
| cpu_vmemoryread_q(int idx, UINT32 offset) | DECLARE_VIRTUAL_ADDRESS_MEMORY_RMW_FUNCTIONS(d, UINT32, 4) |
| { | DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(q, UINT64, 8) |
| descriptor_t *sdp; | |
| UINT32 addr; | |
| int exc; | |
| __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); | |
| sdp = &CPU_STAT_SREG(idx); | |
| addr = sdp->u.seg.segbase + offset; | |
| if (!CPU_STAT_PM) | |
| return cpu_memoryread_q(addr); | |
| if (!SEG_IS_VALID(sdp)) { | |
| exc = GP_EXCEPTION; | |
| goto err; | |
| } | |
| if (!(sdp->flag & CPU_DESC_FLAG_READABLE)) { | |
| cpu_memoryread_check(sdp, offset, 8, CHOOSE_EXCEPTION(idx)); | |
| } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { | |
| if (!check_limit_upstairs(sdp, offset, 8)) | |
| goto range_failure; | |
| } | |
| return cpu_lmemoryread_q(addr, CPU_PAGE_READ_DATA | CPU_STAT_USER_MODE); | |
| range_failure: | |
| VERBOSE(("cpu_vmemoryread_q: type = %d, offset = %08x, limit = %08x", sdp->type, offset, sdp->u.seg.limit)); | |
| exc = CHOOSE_EXCEPTION(idx); | |
| err: | |
| EXCEPTION(exc, 0); | |
| return 0; /* compiler happy */ | |
| } | |
| void MEMCALL | |
| cpu_vmemorywrite_q(int idx, UINT32 offset, UINT64 value) | |
| { | |
| descriptor_t *sdp; | |
| UINT32 addr; | |
| int exc; | |
| __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); | |
| sdp = &CPU_STAT_SREG(idx); | |
| addr = sdp->u.seg.segbase + offset; | |
| if (!CPU_STAT_PM) { | |
| cpu_memorywrite_q(addr, value); | |
| return; | |
| } | |
| if (!SEG_IS_VALID(sdp)) { | |
| exc = GP_EXCEPTION; | |
| goto err; | |
| } | |
| if (!(sdp->flag & CPU_DESC_FLAG_WRITABLE)) { | |
| cpu_memorywrite_check(sdp, offset, 8, CHOOSE_EXCEPTION(idx)); | |
| } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { | |
| if (!check_limit_upstairs(sdp, offset, 8)) | |
| goto range_failure; | |
| } | |
| if (!CPU_STAT_PAGING) { | |
| cpu_memorywrite_q(addr, value); | |
| } else { | |
| cpu_linear_memory_write_q(addr, value, CPU_PAGE_READ_DATA | CPU_STAT_USER_MODE); | |
| } | |
| return; | |
| range_failure: | |
| VERBOSE(("cpu_vmemorywrite_q: type = %d, offset = %08x, limit = %08x", sdp->type, offset, sdp->u.seg.limit)); | |
| exc = CHOOSE_EXCEPTION(idx); | |
| err: | |
| EXCEPTION(exc, 0); | |
| } | |
| REG80 MEMCALL | REG80 MEMCALL |
| cpu_vmemoryread_f(int idx, UINT32 offset) | cpu_vmemoryread_f(int idx, UINT32 offset) |
| Line 584 cpu_vmemoryread_f(int idx, UINT32 offset | Line 507 cpu_vmemoryread_f(int idx, UINT32 offset |
| if (!(sdp->flag & CPU_DESC_FLAG_READABLE)) { | if (!(sdp->flag & CPU_DESC_FLAG_READABLE)) { |
| cpu_memoryread_check(sdp, offset, 10, CHOOSE_EXCEPTION(idx)); | cpu_memoryread_check(sdp, offset, 10, CHOOSE_EXCEPTION(idx)); |
| } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { | } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { |
| if (!check_limit_upstairs(sdp, offset, 10)) | if (!check_limit_upstairs(sdp, offset, 10, SEG_IS_32BIT(sdp))) |
| goto range_failure; | goto range_failure; |
| } | } |
| if (!CPU_STAT_PAGING) | return cpu_lmemoryread_f(addr, CPU_PAGE_READ_DATA | CPU_STAT_USER_MODE); |
| return cpu_memoryread_f(addr); | |
| return cpu_linear_memory_read_f(addr, CPU_PAGE_READ_DATA | CPU_PAGE_READ_DATA | CPU_STAT_USER_MODE); | |
| range_failure: | range_failure: |
| VERBOSE(("cpu_vmemoryread_f: type = %d, offset = %08x, limit = %08x", sdp->type, offset, sdp->u.seg.limit)); | VERBOSE(("cpu_vmemoryread_f: type = %d, offset = %08x, limit = %08x", sdp->type, offset, sdp->u.seg.limit)); |
| Line 627 cpu_vmemorywrite_f(int idx, UINT32 offse | Line 548 cpu_vmemorywrite_f(int idx, UINT32 offse |
| if (!(sdp->flag & CPU_DESC_FLAG_WRITABLE)) { | if (!(sdp->flag & CPU_DESC_FLAG_WRITABLE)) { |
| cpu_memorywrite_check(sdp, offset, 10, CHOOSE_EXCEPTION(idx)); | cpu_memorywrite_check(sdp, offset, 10, CHOOSE_EXCEPTION(idx)); |
| } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { | } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { |
| if (!check_limit_upstairs(sdp, offset, 10)) | if (!check_limit_upstairs(sdp, offset, 10, SEG_IS_32BIT(sdp))) |
| goto range_failure; | goto range_failure; |
| } | } |
| if (!CPU_STAT_PAGING) { | cpu_lmemorywrite_f(addr, value, CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE); |
| cpu_memorywrite_f(addr, value); | |
| } else { | |
| cpu_linear_memory_write_f(addr, value, CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE); | |
| } | |
| return; | return; |
| range_failure: | range_failure: |