VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

When two 16-bit registers are added in offset calculations (e.g. [BX+SI]), can an exception occur when the two added are past 0xFFFF in real mode? Or is this truncated to 16-bit before, never causing any exceptions?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 1 of 15, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

On 16 bit processors (from 286 down) the BX+SI has to produce a 16bit offset, so the result is masked with 0xFFFF. Then it is added to the value of the segment shifted left by 4.

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 2 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

So even on the 80286, a limit of 0xFFFF with a BX(0x8000)+SI(0x8000) won't cause a general protection fault?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 3 of 15, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

So even on the 80286, a limit of 0xFFFF with a BX(0x8000)+SI(0x8000) won't cause a general protection fault?

It will if you try to read a word from offset 0xFFFF.

Reply 4 of 15, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

I think the key is that BX+SI has to produce a 16bit quantity. So with a limit of 0xFFFF you might not be able to get a GPF. Since no segment can be larger than 0xFFFF.

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 5 of 15, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie
Jepael wrote:
superfury wrote:

So even on the 80286, a limit of 0xFFFF with a BX(0x8000)+SI(0x8000) won't cause a general protection fault?

It will if you try to read a word from offset 0xFFFF.

not in realmode, no exception will be thrown.

also with debug.exe in dosbox, if you read a word like MOV AX,[BX+SI] where BX=8000, SI=7FFF... you will actually get the bytes at address 0xFFFF and 0x10000. easy to verify on a real machine with debug when I get home from work.

--/\-[ Stu : Bloody Cactus :: [ https://bloodycactus.com :: http://kråketær.com ]-/\--

Reply 6 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

And what about on a 80286? The 80386 is able to generate 17-bit offsets, but the 80286 can't(it's a 16-bit CPU). Will the 80286 fault on word reads on offset 0xFFFF?

Edit: This is a very odd case: the 0x10000 and higher offsets need to wrap(according to 16-bit offsets), but 0x10000 needs to fault on a word access, while 0x10000 generated during byte/word accesses of BX+SI(BX being 0x8000 and SI being 0x8000 with a byte access or 0x7FFF with a word read). What happens in those edge cases? When will it fault? When won't it fault(8086 conpatible wrap)? Will it fault in all those cases? Is there a difference in behaviour with 80386+ machines?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 8 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm. Page 3-10 says that any carry out from a 16-bit addition is ignored. So it BX+SI will wrap to 16-bits before any segment limit checks are performed. But word accesses at 0xFFFF cause a fault, although NOTHING is said about normal wrapping doing the same? How does normal under/overflow trigger a fault? Wrapping to 16-bits prevent faults(e.g. POP and PUSH). Code fetching shouldn't be a problem, as wrapping occurs before fetches and fetches are never word-sized(bytes into the FIFO)? Or are they? I know it happens with a single BIU fetch(always fetching words from memory), but how does that combine with even/odd addresses and wrapping? BIU IP being 0xFFFF will fault with a word fetch(CS limit), but it should wrap correctly? Or even worse, it should lock up afaik: IP being 0xFFFF requiring a word fetch(always on a 80286+) will make the BIU idle waiting for the EU to fault, but the EU will be waiting for the byte from 0xFFFF first, before reading the next from 0x0000(it DOES wrap)? Which one is correct?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 9 of 15, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie

On an 8088, accessing the word at [0xffff] will give you the byte at [0xffff] in the low byte and the byte at [0] in the high byte (I just tried it).

I don't have an 80286 to test this on, but I understand that accessing a word at [0xffff] on a 286 or later causes a general protection fault even in real mode. I think that this will not affect prefetching since (if I understand correctly) prefetch accesses are always aligned. If they weren't, the CPU would have to have a special case for prefetching word[0xffff] since (for example) it's legitimate to call a function at 0xffff (or more generally, at the very end of the segment in protected mode) which consists of a single RET instruction.

Reply 12 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

So the 80286 won't always perform a word prefetch?

Page 3-31, 2nd to last paragraph:

A prefetcher will perform only a byte code fetch operation for control transfers to an instruction beginning on a numerically odd physical address.

So it prefetches words when at an even address, but starting to prefetch when at an odd address, it prefetches a byte instead? Then all following accesses are word fetches again(since the address is aligned again)? So it won't fault on CS:0xFFFF being e.g. an IRET?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 13 of 15, by Jo22

User metadata
Rank l33t++
Rank
l33t++

I don't have an 80286 to test this on (..]

I do. If you guys sent me some code snippet, I'll perform a little testing here. 😀

"Time, it seems, doesn't flow. For some it's fast, for some it's slow.
In what to one race is no time at all, another race can rise and fall..." - The Minstrel

//My video channel//

Reply 14 of 15, by peterferrie

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:
So the 80286 won't always perform a word prefetch? […]
Show full quote

So the 80286 won't always perform a word prefetch?

Page 3-31, 2nd to last paragraph:

A prefetcher will perform only a byte code fetch operation for control transfers to an instruction beginning on a numerically odd physical address.

So it prefetches words when at an even address, but starting to prefetch when at an odd address, it prefetches a byte instead? Then all following accesses are word fetches again(since the address is aligned again)? So it won't fault on CS:0xFFFF being e.g. an IRET?

Yes, prefetches are two single-byte fetches if starting on an odd address, otherwise one word fetch on an even address.
However, running code doesn't benefit from that - accessing or executing from an address which would overflow (i.e. word at 0xffff on the 286+, dword at 0xfffd+ on the 386+) will cause a GPF.
That means that reading or writing to that address, or trying to run an instruction which spans that address (e.g. two-byte instruction beginning at 0xffff) will fault.

Reply 15 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

You say two single-byte transfers? But that won't work when the EU requests something to transfer(I/O or memory)? Don't you mean one byte transfer and normal word transfers after that(since it's aligned again?)? That's what UniPCemu does in it's current commits.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io