x86 segment base vs expand down segments?

Emulation of old PCs, PC hardware, or PC peripherals.

x86 segment base vs expand down segments?

Postby superfury » 2017-2-17 @ 15:06

What happens when a stack(or any expand-down data) segment (descriptor) is indexed with a register while using a expand-down segment? Say ESP=0, it gets decreased to 0xFFFFFFC for a dword write, then writing a value to SS:FFFFFFFC. The SS segment descriptor base pointing to 0x400, what memory address is the dword write written to? Is it written to 0x400+FFFFFFFC=3FC(according to the manual, it's just being added)? Or is the limit being added as well(0x400(base)+FFFFFFFC(index)+0x400(limit)=7FC), which would make more sense(the base still pointing to the start of the memory and the stack growing down from the end))?

Edit: This article seems to imply it's just simple addition, with the limit not being used in that case at all. So pushing a dword value to that stack will simply end up at linear memory address 0x3FC?

What happens when address sizes are changed? E.g. the base pointing to a 32-bit address, with a 16-bit offset being used? Is the offset simply sign-extended to 32-bits?

Edit: I've modified the accesses using 16-bits offsets within top-down segments to be extended to 32-bits by setting bits 16-31 to 1(offset |= 0xFFFF0000; ). Is that correct behaviour? Since the address space used is 32-bits wide(it's emulating a 32-bit x86 CPU(up to 80386 atm) with a 32-bit bus after all and 32-bits to address), setting those bits should ensure that 16-bit offsets behave correctly as the conversion to 32-bits and adding the upper 32 bits(before masking off the upper 8 bits when applying the address bus in the 80286) ensures that the address is indeed 'substracted' from the specified address)?
superfury
Oldbie
 
Posts: 1506
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 segment base vs expand down segments?

Postby crazyc » 2017-2-17 @ 23:01

superfury wrote:What happens when a stack(or any expand-down data) segment (descriptor) is indexed with a register while using a expand-down segment? Say ESP=0, it gets decreased to 0xFFFFFFC for a dword write, then writing a value to SS:FFFFFFFC. The SS segment descriptor base pointing to 0x400, what memory address is the dword write written to? Is it written to 0x400+FFFFFFFC=3FC(according to the manual, it's just being added)? Or is the limit being added as well(0x400(base)+FFFFFFFC(index)+0x400(limit)=7FC), which would make more sense(the base still pointing to the start of the memory and the stack growing down from the end))?
Yes, the base plus the offset is the address (so the base is the bottom of the segment just as expand up). The limit just refers to the lowest valid address rather than the highest.

superfury wrote:What happens when address sizes are changed? E.g. the base pointing to a 32-bit address, with a 16-bit offset being used? Is the offset simply sign-extended to 32-bits?

No sign extension. sp (esp truncated to 16 bits) is used if the descriptor D bit is 0 otherwise esp if D is 1.
crazyc
Newbie
 
Posts: 77
Joined: 2013-2-02 @ 16:17

Re: x86 segment base vs expand down segments?

Postby superfury » 2017-2-18 @ 10:04

My current logic always works with 32-bit offsets(on both ESP and SP). So what it does is convert 16-bit offsets(all offsets that are 16-bit in size, determined by a new parameter sent with the offset calculator parameters) into 32-bit offsets by, when calculating expand-down segments with 16-bit offsets only, OR-ing in 0xFFFF0000 into the offset(one extending) to make it 32-bit compatible. Normal 32-bit offsets are unchanged and only added to the base offset.

Is that correct behaviour?

My code doing that:
Code: Select all
OPTINLINE uint_32 MMU_realaddr(sword segdesc, word segment, uint_32 offset, byte wordop, byte is_offset16) //Real adress?
{
   SEGMENT_DESCRIPTOR *descriptor; //For checking Expand-down data descriptors!
   INLINEREGISTER uint_32 realaddress;
   //word originalsegment = segment;
   //uint_32 originaloffset = offset; //Save!
   realaddress = offset; //Load the address!
   if ((EMULATED_CPU==CPU_8086) || (EMULATED_CPU==CPU_NECV30 && !((realaddress==0x10000) && wordop))) //-NEC V20/V30 wraps offset arround 64kB? NEC V20/V30 allows 1 byte more in word operations!
   {
      realaddress &= 0xFFFF; //Wrap arround!
   }
   writeword = 0; //Reset word-write flag for checking next bytes!

   if (segdesc!=-1) //valid segment descriptor?
   {
      descriptor = &CPU[activeCPU].SEG_DESCRIPTOR[segdesc]; //Get our using descriptor!
      if ((GENERALSEGMENTPTR_S(descriptor) == 1) && (EXECSEGMENTPTR_ISEXEC(descriptor) == 0) && DATASEGMENTPTR_E(descriptor)) //Data segment that's expand-down?
      {
         if (is_offset16) //16-bits offset? Set the high bits for compatibility!
         {
            realaddress |= 0xFFFF0000; //Convert to 32-bits for adding correctly!
         }
      }
   }
   realaddress += CPU_MMU_start(segdesc, segment);

   realaddress &= MMU.wraparround; //Apply A20!

   if (is_XT && (EMULATED_CPU<CPU_80286)) realaddress &= 0xFFFFF; //Only 20-bits address is available on a XT without newer CPU!
   else if (EMULATED_CPU==CPU_80286) realaddress &= 0xFFFFFF; //Only 24-bits is available on a AT!

   //We work!
   //dolog("MMU","\nAddress translation: %04X:%08X=%08X",originalsegment,originaloffset,realaddress); //Log the converted address!
   latchBUS(realaddress); //This address is to be latched!
   return realaddress; //Give real adress!
}


The block checking "segdesc!=-1" is the block I'm talking about. That makes sure to convert the 16-bit offsets to a 32-bit compatible value(by setting bits 16-31 to make the offset behave negative compared to the base using the overflow logic). Otherwise the offset would be positive instead of negative(base+positive offset instead of base+negative offset).

The is_XT check takes care of any remaining processor-specific(address bus) wrapping that's required(24-bits 80286/AT, 20-bits 80(1)8X and 32-bit 80386+).
superfury
Oldbie
 
Posts: 1506
Joined: 2014-3-08 @ 11:25
Location: Netherlands


Return to PC Emulation

Who is online

Users browsing this forum: No registered users and 2 guests