VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

How does the Intel Inboard 386 XT enable&disable the A20 address line to address more than 1MB memory(disabling the compatibility wrapping)? Seeing as it only has the PPI keyboard controller(which doesn't support line A20) and the Fast A20 port probably didn't exist back then?

Edit: According to http://collaboration.cmc.ec.gc.ca/science/rpn … 9007f/9007f.htm listing three, writing the values 0xDD/0xDF(Just like commands on the 8042) disable/enable the A20 gate. So are only those commands supported or are more commands supported using that single write I/O port(unused by the PPI)?

Last edited by superfury on 2023-03-08, 14:04. Edited 6 times in total.

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

Reply 1 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've implemented the port 60h results to affect the A20 line using the 8042 emulation routines(called externally by the seperate Inboard module). Now DD and DF written to port 60h will disable/enable the A20 line for the application to toggle the A20 line on and off(Using the 8042 to emulate the A20 line).

Now the Inboard Setup crashes when getting past the second information/warning screen, executing a ARPL instruction in Real mode?

https://www.dropbox.com/s/sjssf3vdr583hy2/deb … D_ARPL.zip?dl=0

Anyone can see what's going wrong?

Edit: Just found the cause:

00:01:35:94.01256: Reading from RAM: 0000FB7A=0F ()
00:01:35:94.01256: Reading from RAM: 0000FB7B=20 ( )
00:01:35:94.01264: Reading from RAM: 0000FB7C=C0 (À)
00:01:35:94.01272: Reading from RAM: 0000FB7D=66 (f)
00:01:35:94.01272: Reading from RAM: 0000FB7E=0D ( )
00:01:35:94.01280: 0F96:0219 (660F20C0)MOV CR0,CR0
00:01:35:94.01304: EU&BIU cycles: 18, Operation cycles: 4, HW interrupt cycles: 0, Prefix cycles: 2, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 20, BIU prefetching cycles: 6
00:01:35:94.01304: Registers:
00:01:35:94.01312: EAX: 00000096, EBX: 000014cb, ECX: 00000000, EDX: 00000030
00:01:35:94.01320: CS: 0F96, DS: 0F96, ES: 0F96, FS: 0000, GS: 0000 SS: 14CB
00:01:35:94.01320: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000910
00:01:35:94.01328: EIP: 00000219, EFLAGS: 00003886
00:01:35:94.01336: CR0: 00000000; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:01:35:94.01336: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:01:35:94.01344: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:01:35:94.01376: DR6: 00000000; DR5&7: 00000000
00:01:35:94.01376: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:01:35:94.01392: FLAGSINFO:c1P0a0zStidO11n0rv00000000000000
00:01:35:94.01400: Interrupt status: 0000000000000000
00:01:35:94.01400: VGA@323,270(CRT:350,304)
00:01:35:94.01408: Display=801,446

This should be "MOV EAX,CR0". The same applies to the instruction after the next, which is supposed to be "MOV CR0,EAX" to switch to protected mode(EAX=00000001).

Edit: After fixing that problem, now the first instruction generates a #GP immediately, because the rights check fails(CS=0F96, so RPL=3, CPL=0 and DPL=0) causing a General Protection fault on the very first instruction to be executed in protected mode. Is this correct? In this case, the CS selector low 2 bits need to be zeroed in order for the first instruction to succeed?

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

Reply 2 of 55, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

Oh that is interesting! Emulating Intel Inboard 386 should be challenging and fun. Is the listing you put in the OP the only doc you have? I would be interested in looking at that too?

I cannot do 386 yet but eventually I will.

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 3 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

Unfortunately it's the only doc I can find.

I try the Inboard 386 setup.exe from a floppy disk(gotten from minuszerodegrees), but eventually end up faulting incorrectly(it's in 16-bit protected mode it seems, as it's using 16-bit default operand/address sizes):

00:01:39:67.04240: Reading from RAM: 0000FB85=22 (")
00:01:39:67.04240: Reading from RAM: 0000FB86=C0 (À)
00:01:56:66.09104: Reading from RAM: 0000FB87=EA (ê)
00:01:56:66.09112: Reading from RAM: 0000FB88=2C (,)
00:01:56:66.09120: 0F96:0223 (660F22C0)MOV CR0,EAX
00:01:56:66.09160: EU&BIU cycles: 14, Operation cycles: 4, HW interrupt cycles: 0, Prefix cycles: 2, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 16, BIU prefetching cycles: 6
00:01:56:66.09160: Registers:
00:01:56:66.09176: EAX: 00000001, EBX: 000014cb, ECX: 00000000, EDX: 00000030
00:01:56:66.09200: CS: 0F96, DS: 0F96, ES: 0F96, FS: 0000, GS: 0000 SS: 14CB
00:01:56:66.09208: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000910
00:01:56:66.09216: EIP: 00000223, EFLAGS: 00003002
00:01:56:66.09240: CR0: 00000000; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:01:56:66.09248: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:01:56:66.09256: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:01:56:66.09272: DR6: 00000000; DR5&7: 00000000
00:01:56:66.09272: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:01:56:66.09280: FLAGSINFO:c1p0a0zstido11n0rv00000000000000
00:01:56:66.09288: Interrupt status: 0000000000000000
00:01:56:66.09296: VGA@327,48(CRT:354,82)
00:01:56:66.09296: Display=801,446

00:03:38:24.03296: Reading from RAM: 0000FB89=02 ()
00:03:38:24.03296: Reading from RAM: 0000FB8A=20 ( )
00:03:38:24.03312: Reading from RAM: 0000FB8B=00 ( )
00:04:45:48.07296: Reading from RAM: 0000FAA0=FF (ÿ)
00:04:46:04.06752: Reading from RAM: 0000FAA1=FF (ÿ)
00:04:46:05.00272: Reading from RAM: 0000FAA2=60 (`)
00:04:46:05.03440: Reading from RAM: 0000FAA3=F9 (ù)
00:04:46:05.06576: Reading from RAM: 0000FAA4=00 ( )
00:04:46:05.09680: Reading from RAM: 0000FAA5=9B (›)
00:04:46:06.02432: Reading from RAM: 0000FAA6=00 ( )
00:04:46:06.04864: Reading from RAM: 0000FAA7=00 ( )
00:06:22:85.05968: Reading from RAM: 0000FB8C=B8 (¸)
00:06:22:85.05968: Reading from RAM: 0000FB8D=28 (()
00:06:22:85.05968: Reading from RAM: 0000FB8E=00 ( )
00:06:22:85.05968: Reading from RAM: 0000FB8F=8E (Ž)
00:06:22:85.05968: Reading from RAM: 0000FB90=D0 (Ð)
00:06:22:85.06000: Reading from RAM: 0000FB91=B8 (¸)
00:06:22:85.06000: Reading from RAM: 0000FB92=10 ()
00:06:22:85.06000: Reading from RAM: 0000FB93=00 ( )
00:06:22:85.06000: 0F96:00000227 (EA2C022000)JMP 0020:022C
00:06:22:85.06032: EU&BIU cycles: 38, Operation cycles: 15, HW interrupt cycles: 0, Prefix cycles: 0, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 44, BIU prefetching cycles: 24
00:06:22:85.06032: Registers:
00:06:22:85.06064: EAX: 00000001, EBX: 000014cb, ECX: 00000000, EDX: 00000030
00:06:22:85.06064: CS: 0F96, DS: 0F96, ES: 0F96, FS: 0000, GS: 0000 SS: 14CB, TR: 0000, LDTR:0000
00:06:22:85.06128: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000910
00:06:22:85.06128: EIP: 00000227, EFLAGS: 00003002
00:06:22:85.06160: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:06:22:85.06160: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:06:22:85.06160: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:06:22:85.06160: DR6: 00000000; DR5&7: 00000000
00:06:22:85.06160: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:06:22:85.06192: FLAGSINFO:c1p0a0zstido11n0rv00000000000000
00:06:22:85.06192: Interrupt status: 0000000000000000
00:06:22:85.06192: VGA@393,48(CRT:420,82)
00:06:22:85.06192: Display=801,446

00:08:07:73.03440: Reading from RAM: 0000FB94=8E (Ž)
00:08:07:73.03440: 0020:0000022C (B82800)MOVW AX, 0028
00:08:07:73.03504: EU&BIU cycles: 5, Operation cycles: 4, HW interrupt cycles: 0, Prefix cycles: 0, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 4, BIU prefetching cycles: 3
Show last 356 lines
00:08:07:73.03504: Registers:
00:08:07:73.03504: EAX: 00000001, EBX: 000014cb, ECX: 00000000, EDX: 00000030
00:08:07:73.03536: CS: 0020, DS: 0F96, ES: 0F96, FS: 0000, GS: 0000 SS: 14CB, TR: 0000, LDTR:0000
00:08:07:73.03536: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000910
00:08:07:73.03536: EIP: 0000022c, EFLAGS: 00003002
00:08:07:73.03568: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:73.03568: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:73.03568: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:73.03600: DR6: 00000000; DR5&7: 00000000
00:08:07:73.03600: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:73.03632: FLAGSINFO:c1p0a0zstido11n0rv00000000000000
00:08:07:73.03632: Interrupt status: 0000000000000000
00:08:07:73.03632: VGA@572,48(CRT:599,82)
00:08:07:73.03632: Display=801,446

00:08:07:73.09456: Reading from RAM: 0000FAA8=FF (ÿ)
00:08:07:73.09456: Reading from RAM: 0000FAA9=FF (ÿ)
00:08:07:73.09456: Reading from RAM: 0000FAAA=B0 (°)
00:08:07:73.09456: Reading from RAM: 0000FAAB=4C (L)
00:08:07:73.09456: Reading from RAM: 0000FAAC=01 ()
00:08:07:73.09456: Reading from RAM: 0000FAAD=93 (“)
00:08:07:73.09488: Reading from RAM: 0000FAAE=00 ( )
00:08:07:73.09488: Reading from RAM: 0000FAAF=00 ( )
00:08:07:73.09488: 0020:0000022F (8ED0)MOVW SS,AX
00:08:07:73.09520: EU&BIU cycles: 2, Operation cycles: 0, HW interrupt cycles: 0, Prefix cycles: 0, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 0, BIU prefetching cycles: 0
00:08:07:73.09520: Registers:
00:08:07:73.09552: EAX: 00000028, EBX: 000014cb, ECX: 00000000, EDX: 00000030
00:08:07:73.09552: CS: 0020, DS: 0F96, ES: 0F96, FS: 0000, GS: 0000 SS: 14CB, TR: 0000, LDTR:0000
00:08:07:73.09552: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000910
00:08:07:73.09552: EIP: 0000022f, EFLAGS: 00003002
00:08:07:73.09584: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:73.09584: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:73.09584: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:73.09584: DR6: 00000000; DR5&7: 00000000
00:08:07:73.09616: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:73.09616: FLAGSINFO:c1p0a0zstido11n0rv00000000000000
00:08:07:73.09616: Interrupt status: 0000000000000000
00:08:07:73.09616: VGA@596,48(CRT:623,82)
00:08:07:73.09616: Display=801,446

00:08:07:73.09648: Reading from RAM: 0000FB95=D8 (Ø)
00:08:07:73.09648: 0020:00000231 (B81000)MOVW AX, 0010
00:08:07:73.09680: EU&BIU cycles: 5, Operation cycles: 4, HW interrupt cycles: 0, Prefix cycles: 0, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 4, BIU prefetching cycles: 3
00:08:07:73.09680: Registers:
00:08:07:73.09680: EAX: 00000028, EBX: 000014cb, ECX: 00000000, EDX: 00000030
00:08:07:73.09680: CS: 0020, DS: 0F96, ES: 0F96, FS: 0000, GS: 0000 SS: 0028, TR: 0000, LDTR:0000
00:08:07:73.09680: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000910
00:08:07:73.09680: EIP: 00000231, EFLAGS: 00003002
00:08:07:73.09712: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:73.09712: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:73.09712: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:73.09712: DR6: 00000000; DR5&7: 00000000
00:08:07:73.09712: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:73.09744: FLAGSINFO:c1p0a0zstido11n0rv00000000000000
00:08:07:73.09744: Interrupt status: 0000000000000000
00:08:07:73.09744: VGA@605,48(CRT:632,82)
00:08:07:73.09744: Display=801,446

00:08:07:73.09744: Reading from RAM: 0000FA90=FF (ÿ)
00:08:07:73.09744: Reading from RAM: 0000FA91=FF (ÿ)
00:08:07:73.09744: Reading from RAM: 0000FA92=60 (`)
00:08:07:73.09744: Reading from RAM: 0000FA93=F9 (ù)
00:08:07:73.09776: Reading from RAM: 0000FA94=00 ( )
00:08:07:73.09776: Reading from RAM: 0000FA95=93 (“)
00:08:07:73.09776: Reading from RAM: 0000FA96=00 ( )
00:08:07:73.09776: Reading from RAM: 0000FA97=00 ( )
00:08:07:73.09776: 0020:00000234 (8ED8)MOVW DS,AX
00:08:07:73.09808: EU&BIU cycles: 2, Operation cycles: 0, HW interrupt cycles: 0, Prefix cycles: 0, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 0, BIU prefetching cycles: 0
00:08:07:73.09808: Registers:
00:08:07:73.09808: EAX: 00000010, EBX: 000014cb, ECX: 00000000, EDX: 00000030
00:08:07:73.09808: CS: 0020, DS: 0F96, ES: 0F96, FS: 0000, GS: 0000 SS: 0028, TR: 0000, LDTR:0000
00:08:07:73.09808: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000910
00:08:07:73.09840: EIP: 00000234, EFLAGS: 00003002
00:08:07:73.09840: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:73.09840: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:73.09840: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:73.09840: DR6: 00000000; DR5&7: 00000000
00:08:07:73.09840: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:73.09872: FLAGSINFO:c1p0a0zstido11n0rv00000000000000
00:08:07:73.09872: Interrupt status: 0000000000000000
00:08:07:73.09872: VGA@629,48(CRT:656,82)
00:08:07:73.09872: Display=801,446

00:08:07:73.09872: Reading from RAM: 0000FB96=33 (3)
00:08:07:73.09872: Reading from RAM: 0000FB97=C9 (É)
00:08:07:73.09872: Reading from RAM: 0000FB98=66 (f)
00:08:07:73.09904: 0020:00000236 (33C9)XORW CX,CX
00:08:07:73.09904: EU&BIU cycles: 11, Operation cycles: 3, HW interrupt cycles: 0, Prefix cycles: 0, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 12, BIU prefetching cycles: 3
00:08:07:73.09904: Registers:
00:08:07:73.09904: EAX: 00000010, EBX: 000014cb, ECX: 00000000, EDX: 00000030
00:08:07:73.09968: CS: 0020, DS: 0010, ES: 0F96, FS: 0000, GS: 0000 SS: 0028, TR: 0000, LDTR:0000
00:08:07:73.09968: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000910
00:08:07:73.09968: EIP: 00000236, EFLAGS: 00003002
00:08:07:73.09968: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:73.09968: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:74.00000: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:74.00000: DR6: 00000000; DR5&7: 00000000
00:08:07:74.00000: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:74.00000: FLAGSINFO:c1p0a0zstido11n0rv00000000000000
00:08:07:74.00000: Interrupt status: 0000000000000000
00:08:07:74.00000: VGA@638,48(CRT:665,82)
00:08:07:74.00000: Display=801,446

00:08:07:74.00032: Reading from RAM: 0000FB99=33 (3)
00:08:07:74.00032: Reading from RAM: 0000FB9A=FF (ÿ)
00:08:07:74.00064: Reading from RAM: 0000FB9B=BA (º)
00:08:07:74.00096: 0020:00000238 (6633FF)XORD EDI,EDI
00:08:07:74.00128: EU&BIU cycles: 11, Operation cycles: 3, HW interrupt cycles: 0, Prefix cycles: 2, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 12, BIU prefetching cycles: 3
00:08:07:74.00128: Registers:
00:08:07:74.00128: EAX: 00000010, EBX: 000014cb, ECX: 00000000, EDX: 00000030
00:08:07:74.00128: CS: 0020, DS: 0010, ES: 0F96, FS: 0000, GS: 0000 SS: 0028, TR: 0000, LDTR:0000
00:08:07:74.00128: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000910
00:08:07:74.00128: EIP: 00000238, EFLAGS: 00003046
00:08:07:74.00160: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:74.00160: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:74.00160: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:74.00160: DR6: 00000000; DR5&7: 00000000
00:08:07:74.00160: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:74.00160: FLAGSINFO:c1P0a0Zstido11n0rv00000000000000
00:08:07:74.00192: Interrupt status: 0000000000000000
00:08:07:74.00192: VGA@690,48(CRT:717,82)
00:08:07:74.00192: Display=801,446

00:08:07:74.00192: Reading from RAM: 0000FB9C=18 ()
00:08:07:74.00192: Reading from RAM: 0000FB9D=00 ( )
00:08:07:74.00192: Reading from RAM: 0000FB9E=8E (Ž)
00:08:07:74.00192: 0020:0000023B (BA1800)MOVW DX, 0018
00:08:07:74.00224: EU&BIU cycles: 13, Operation cycles: 4, HW interrupt cycles: 0, Prefix cycles: 0, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 12, BIU prefetching cycles: 3
00:08:07:74.00224: Registers:
00:08:07:74.00224: EAX: 00000010, EBX: 000014cb, ECX: 00000000, EDX: 00000030
00:08:07:74.00256: CS: 0020, DS: 0010, ES: 0F96, FS: 0000, GS: 0000 SS: 0028, TR: 0000, LDTR:0000
00:08:07:74.00256: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000000
00:08:07:74.00256: EIP: 0000023b, EFLAGS: 00003046
00:08:07:74.00256: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:74.00256: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:74.00256: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:74.00288: DR6: 00000000; DR5&7: 00000000
00:08:07:74.00288: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:74.00288: FLAGSINFO:c1P0a0Zstido11n0rv00000000000000
00:08:07:74.00288: Interrupt status: 0000000000000000
00:08:07:74.00288: VGA@742,48(CRT:769,82)
00:08:07:74.00288: Display=801,446

00:08:07:74.00320: Reading from RAM: 0000FB9F=C2 (Â)
00:08:07:74.00320: Reading from RAM: 0000FA98=FF (ÿ)
00:08:07:74.00320: Reading from RAM: 0000FA99=FF (ÿ)
00:08:07:74.00320: Reading from RAM: 0000FA9A=00 ( )
00:08:07:74.00320: Reading from RAM: 0000FA9B=00 ( )
00:08:07:74.00320: Reading from RAM: 0000FA9C=10 ()
00:08:07:74.00320: Reading from RAM: 0000FA9D=93 (“)
00:08:07:74.00320: Reading from RAM: 0000FA9E=00 ( )
00:08:07:74.00352: Reading from RAM: 0000FA9F=00 ( )
00:08:07:74.00352: 0020:0000023E (8EC2)MOVW ES,DX
00:08:07:74.00352: EU&BIU cycles: 6, Operation cycles: 0, HW interrupt cycles: 0, Prefix cycles: 0, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 4, BIU prefetching cycles: 0
00:08:07:74.00352: Registers:
00:08:07:74.00384: EAX: 00000010, EBX: 000014cb, ECX: 00000000, EDX: 00000018
00:08:07:74.00384: CS: 0020, DS: 0010, ES: 0F96, FS: 0000, GS: 0000 SS: 0028, TR: 0000, LDTR:0000
00:08:07:74.00384: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000000
00:08:07:74.00384: EIP: 0000023e, EFLAGS: 00003046
00:08:07:74.00384: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:74.00416: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:74.00416: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:74.00416: DR6: 00000000; DR5&7: 00000000
00:08:07:74.00416: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:74.00416: FLAGSINFO:c1P0a0Zstido11n0rv00000000000000
00:08:07:74.00416: Interrupt status: 0000000000000000
00:08:07:74.00448: VGA@803,49(CRT:0,83)
00:08:07:74.00448: Display=801,446

00:08:07:74.00448: Reading from RAM: 0000FBA0=66 (f)
00:08:07:74.00448: Reading from RAM: 0000FBA1=26 (&)
00:08:07:74.00448: Reading from RAM: 0000FBA2=8B (‹)
00:08:07:74.00480: Reading from RAM: 0000FBA3=15 ()
00:08:07:74.00480: Reading from RAM: 0000FBA4=66 (f)
00:08:07:74.00480: Reading from RAM: 0000FBA5=B8 (¸)
00:08:07:74.00480: Reading from RAM: 0000FBA6=00 ( )
00:08:07:74.00480: Reading from RAM: 0000FBA7=00 ( )
00:08:07:74.00480: Reading from RAM: 000A0000=00 ( )
00:08:07:74.00480: Read from memory: 00100000=00 ( )
00:08:07:74.00512: Reading from RAM: 000A0001=00 ( )
00:08:07:74.00512: Read from memory: 00100001=00 ( )
00:08:07:74.00512: Reading from RAM: 000A0002=00 ( )
00:08:07:74.00512: Read from memory: 00100002=00 ( )
00:08:07:74.00512: Reading from RAM: 000A0003=00 ( )
00:08:07:74.00512: Read from memory: 00100003=00 ( )
00:08:07:74.00544: ModR/M address: 0018:0000B866
00:08:07:74.00544: 0020:00000240 (66268B1566B80000)MOVD EDX,[ES:0000B866]
00:08:07:74.00576: EU&BIU cycles: 34, Operation cycles: 2, HW interrupt cycles: 0, Prefix cycles: 4, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 32, BIU prefetching cycles: 0
00:08:07:74.00576: Registers:
00:08:07:74.00576: EAX: 00000010, EBX: 000014cb, ECX: 00000000, EDX: 00000018
00:08:07:74.00576: CS: 0020, DS: 0010, ES: 0018, FS: 0000, GS: 0000 SS: 0028, TR: 0000, LDTR:0000
00:08:07:74.00576: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000000
00:08:07:74.00576: EIP: 00000240, EFLAGS: 00003046
00:08:07:74.00608: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:74.00608: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:74.00608: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:74.00608: DR6: 00000000; DR5&7: 00000000
00:08:07:74.00608: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:74.00608: FLAGSINFO:c1P0a0Zstido11n0rv00000000000000
00:08:07:74.00640: Interrupt status: 0000000000000000
00:08:07:74.00640: VGA@832,49(CRT:0,83)
00:08:07:74.00640: Display=801,446

00:08:07:74.00640: Reading from RAM: 0000FBA8=00 ( )
00:08:07:74.00640: Reading from RAM: 0000FBA9=00 ( )
00:08:07:74.00640: Reading from RAM: 00010F4B=EB (ë)
00:08:07:74.00672: Read from memory: 00010F4B=EB (ë)
00:08:07:74.00672: Reading from RAM: 0000FBAA=66 (f)
00:08:07:74.00672: Reading from RAM: 0000FBAB=26 (&)
00:08:07:74.00672: Writing to memory: 00010F4B=FB (û)
00:08:07:74.00672: Writing to RAM: 00010F4B=FB (û)
00:08:07:74.00672: ModR/M address: 0010:000015EB
00:08:07:74.00672: 0020:00000248 (0000)ADDB [DS:BX+SI],AL
00:08:07:74.00704: EU&BIU cycles: 23, Operation cycles: 25, HW interrupt cycles: 0, Prefix cycles: 0, Exception cycles: 0, MMU read cycles: 4, MMU write cycles: 4, I/O bus cycles: 0, Prefetching cycles: 16, BIU prefetching cycles: 6
00:08:07:74.00704: Registers:
00:08:07:74.00704: EAX: 00000010, EBX: 000014cb, ECX: 00000000, EDX: 00000000
00:08:07:74.00736: CS: 0020, DS: 0010, ES: 0018, FS: 0000, GS: 0000 SS: 0028, TR: 0000, LDTR:0000
00:08:07:74.00736: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000000
00:08:07:74.00736: EIP: 00000248, EFLAGS: 00003046
00:08:07:74.00736: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:74.00736: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:74.00736: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:74.00768: DR6: 00000000; DR5&7: 00000000
00:08:07:74.00768: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:74.00768: FLAGSINFO:c1P0a0Zstido11n0rv00000000000000
00:08:07:74.00768: Interrupt status: 0000000000000000
00:08:07:74.00768: VGA@92,49(CRT:119,83)
00:08:07:74.00768: Display=801,446

00:08:07:74.00800: Reading from RAM: 0000FBAC=89 (‰)
00:08:07:74.00800: Reading from RAM: 0000FBAD=05 ()
00:08:07:74.00800: Reading from RAM: 0000FBAE=66 (f)
00:08:07:74.00800: Reading from RAM: 0000FBAF=26 (&)
00:08:07:74.00800: Reading from RAM: 0000FBB0=8B (‹)
00:08:07:74.00800: Reading from RAM: 0000FBB1=05 ()
00:08:07:74.00832: Writing to memory: 00100000=10 ()
00:08:07:74.00832: Writing to RAM: 000A0000=10 ()
00:08:07:74.00832: Writing to memory: 00100001=00 ( )
00:08:07:74.00832: Writing to RAM: 000A0001=00 ( )
00:08:07:74.00832: Writing to memory: 00100002=00 ( )
00:08:07:74.00832: Writing to RAM: 000A0002=00 ( )
00:08:07:74.00864: Writing to memory: 00100003=00 ( )
00:08:07:74.00864: Writing to RAM: 000A0003=00 ( )
00:08:07:74.00864: ModR/M address: 0018:058B2666
00:08:07:74.00864: 0020:0000024A (6626890566268B05)MOVD [ES:058B2666],EAX
00:08:07:74.00896: EU&BIU cycles: 26, Operation cycles: 2, HW interrupt cycles: 0, Prefix cycles: 4, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 24, BIU prefetching cycles: 0
00:08:07:74.00896: Registers:
00:08:07:74.00896: EAX: 00000010, EBX: 000014cb, ECX: 00000000, EDX: 00000000
00:08:07:74.00896: CS: 0020, DS: 0010, ES: 0018, FS: 0000, GS: 0000 SS: 0028, TR: 0000, LDTR:0000
00:08:07:74.00896: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000000
00:08:07:74.00928: EIP: 0000024a, EFLAGS: 00003082
00:08:07:74.00928: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:74.00928: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:74.00928: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:74.00928: DR6: 00000000; DR5&7: 00000000
00:08:07:74.00928: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:74.00960: FLAGSINFO:c1p0a0zStido11n0rv00000000000000
00:08:07:74.00960: Interrupt status: 0000000000000000
00:08:07:74.00960: VGA@201,49(CRT:228,83)
00:08:07:74.00960: Display=801,446

00:08:07:74.00960: Reading from RAM: 0000FBB2=66 (f)
00:08:07:74.00960: Reading from RAM: 0000FBB3=26 (&)
00:08:07:74.00992: Reading from RAM: 0000FBB4=89 (‰)
00:08:07:74.00992: Reading from RAM: 0000FBB5=15 ()
00:08:07:74.00992: Reading from RAM: 0000FBB6=66 (f)
00:08:07:74.00992: Reading from RAM: 0000FBB7=3D (=)
00:08:07:74.00992: Reading from RAM: 0000FBB8=FF (ÿ)
00:08:07:74.00992: Reading from RAM: 0000FBB9=FF (ÿ)
00:08:07:74.01024: Writing to memory: 00100000=00 ( )
00:08:07:74.01024: Writing to RAM: 000A0000=00 ( )
00:08:07:74.01024: Writing to memory: 00100001=00 ( )
00:08:07:74.01024: Writing to RAM: 000A0001=00 ( )
00:08:07:74.01024: Writing to memory: 00100002=00 ( )
00:08:07:74.01056: Writing to RAM: 000A0002=00 ( )
00:08:07:74.01056: Writing to memory: 00100003=00 ( )
00:08:07:74.01056: Writing to RAM: 000A0003=00 ( )
00:08:07:74.01056: ModR/M address: 0018:FFFF3D66
00:08:07:74.01056: 0020:00000252 (66268915663DFFFF)MOVD [ES:FFFF3D66],EDX
00:08:07:74.01088: EU&BIU cycles: 34, Operation cycles: 2, HW interrupt cycles: 0, Prefix cycles: 4, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 0, I/O bus cycles: 0, Prefetching cycles: 32, BIU prefetching cycles: 0
00:08:07:74.01088: Registers:
00:08:07:74.01088: EAX: 00000010, EBX: 000014cb, ECX: 00000000, EDX: 00000000
00:08:07:74.01120: CS: 0020, DS: 0010, ES: 0018, FS: 0000, GS: 0000 SS: 0028, TR: 0000, LDTR:0000
00:08:07:74.01120: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000000
00:08:07:74.01120: EIP: 00000252, EFLAGS: 00003082
00:08:07:74.01120: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:74.01120: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:74.01152: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:74.01152: DR6: 00000000; DR5&7: 00000000
00:08:07:74.01152: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:74.01152: FLAGSINFO:c1p0a0zStido11n0rv00000000000000
00:08:07:74.01152: Interrupt status: 0000000000000000
00:08:07:74.01152: VGA@323,49(CRT:350,83)
00:08:07:74.01152: Display=801,446

00:08:07:74.01184: Reading from RAM: 0000FBBA=FF (ÿ)
00:08:07:74.01184: Reading from RAM: 0000FBBB=FF (ÿ)
00:08:07:74.01184: Reading from RAM: 0000F9B0=65 (e)
00:08:07:74.01184: Reading from RAM: 0000F9B1=02 ()
00:08:07:74.01184: Reading from RAM: 0000F9B2=20 ( )
00:08:07:74.01184: Reading from RAM: 0000F9B3=00 ( )
00:08:07:74.01216: Reading from RAM: 0000F9B4=00 ( )
00:08:07:74.01216: Reading from RAM: 0000F9B5=87 (‡)
00:08:07:74.01216: Reading from RAM: 0000F9B6=00 ( )
00:08:07:74.01216: Reading from RAM: 0000F9B7=00 ( )
00:08:07:74.01216: Reading from RAM: 0000FAA0=FF (ÿ)
00:08:07:74.01216: Reading from RAM: 0000FAA1=FF (ÿ)
00:08:07:74.01216: Reading from RAM: 0000FAA2=60 (`)
00:08:07:74.01216: Reading from RAM: 0000FAA3=F9 (ù)
00:08:07:74.01216: Reading from RAM: 0000FAA4=00 ( )
00:08:07:74.01248: Reading from RAM: 0000FAA5=9B (›)
00:08:07:74.01248: Reading from RAM: 0000FAA6=00 ( )
00:08:07:74.01248: Reading from RAM: 0000FAA7=00 ( )
00:08:07:74.02144: Reading from RAM: 0000FBC5=8D ()
00:08:07:74.02400: Reading from RAM: 0000FBC6=36 (6)
00:08:07:74.02400: Reading from RAM: 0000FBC7=10 ()
00:08:07:74.02400: Reading from RAM: 0000FBC8=00 ( )
00:08:07:74.02400: Reading from RAM: 0000FBC9=2E (.)
00:08:07:74.02432: Reading from RAM: 0000FBCA=0F ()
00:08:07:74.02432: Reading from RAM: 0000FBCB=01 ()
00:08:07:74.02432: Reading from RAM: 0000FBCC=54 (T)
00:08:07:74.02432: Reading from RAM: 0000FBCD=08 ()
00:08:07:74.02432: Reading from RAM: 0000FBCE=B8 (¸)
00:08:07:74.02432: Reading from RAM: 0000FBCF=08 ()
00:08:07:74.02432: Reading from RAM: 0000FBD0=00 ( )
00:08:07:74.02432: Reading from RAM: 0000FBD1=8E (Ž)
00:08:07:74.02464: Writing to memory: 0001EAEE=82 (‚)
00:08:07:74.02464: Writing to RAM: 0001EAEE=82 (‚)
00:08:07:74.02464: Writing to memory: 0001EAEF=30 (0)
00:08:07:74.02464: Writing to RAM: 0001EAEF=30 (0)
00:08:07:74.02464: Writing to memory: 0001EAEC=20 ( )
00:08:07:74.02464: Writing to RAM: 0001EAEC=20 ( )
00:08:07:74.02464: Writing to memory: 0001EAED=00 ( )
00:08:07:74.02464: Writing to RAM: 0001EAED=00 ( )
00:08:07:74.02496: Writing to memory: 0001EAEA=5A (Z)
00:08:07:74.02496: Writing to RAM: 0001EAEA=5A (Z)
00:08:07:74.02496: Writing to memory: 0001EAEB=02 ()
00:08:07:74.02496: Writing to RAM: 0001EAEB=02 ()
00:08:07:74.02528: 0020:0000025A (FFFF)<NECV20/V30+ #UD(Possible cause:<UNKNOWN Opcode: GRP5(w) /7>)>
00:08:07:74.02560: EU&BIU cycles: 60, Operation cycles: 51, HW interrupt cycles: 61, Prefix cycles: 0, Exception cycles: 0, MMU read cycles: 0, MMU write cycles: 12, I/O bus cycles: 0, Prefetching cycles: 60, BIU prefetching cycles: 39
00:08:07:74.02560: Registers:
00:08:07:74.02560: EAX: 00000010, EBX: 000014cb, ECX: 00000000, EDX: 00000000
00:08:07:74.02560: CS: 0020, DS: 0010, ES: 0018, FS: 0000, GS: 0000 SS: 0028, TR: 0000, LDTR:0000
00:08:07:74.02592: ESP: 00009e40, EBP: 00000008, ESI: 00000120, EDI: 00000000
00:08:07:74.02592: EIP: 0000025a, EFLAGS: 00003082
00:08:07:74.02592: CR0: 00000001; CR1: 00000000; CR2: 00000000; CR3: 00000000
00:08:07:74.02592: CR4: 00000000; CR5: 00000000; CR6: 00000000; CR7: 00000000
00:08:07:74.02592: DR0: 00000000; DR1: 00000000; DR2: 00000000; CR3: 00000000
00:08:07:74.02592: DR6: 00000000; DR5&7: 00000000
00:08:07:74.02624: GDTR: 00000000FA80FFFF, IDTR: 00000000F9800100
00:08:07:74.02624: FLAGSINFO:c1p0a0zStido11n0rv00000000000000
00:08:07:74.02624: Interrupt status: 0000000000000000
00:08:07:74.02624: VGA@484,49(CRT:511,83)
00:08:07:74.02624: Display=801,446

Something's going terribly wrong here: it probably shouldn't be executing the 0xFFFF opcode? The A0000 RAM addresses aren't VRAM, they're the RAM mapping mapping the RAM addresses of 0x100000 to start at physical address A0000 to preserve memory(memory hole is emulated, but physical memory is increased that way). The same method is applied to the other ISA memory hole(at physical addresses 0xF00000-0x1000000). Directly accessing those memory holes literally discards the writes to memory(reads when no hardware is there are returning nothing(0xFF) always).

The jump to protected mode itself(initial EA JMP instruction after loading CR0) has been fixed by only making the CPU check for RPL vs DPL vs CPL when loading the segment registers, not when actually using them(which caused the previous fault entering protected mode).

I think this instruction might be going wrong:

0020:00000240 (66268B1566B80000)MOVD EDX,[ES:0000B866]

The EDX should be correct, but the offset generated should be incorrect? Shouldn't it be a 16-bit offset(32-bit operand size, 16-bit address size)?

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

Reply 4 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just took a look at my ModR/M module: it decoded 32-bit operand sizes using 32-bit memory addresses and 16-bit operand sizes as 16-bit memory addresses. I've added a little redirect from 32-bit to 16-bit and vice-versa to apply the Address size when addressing memory using the ModR/M.

Edit: The Inboard BIOS now correctly continues and detects the hardware:)

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

Reply 5 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

After a reboot, it scans the 6MB of RAM that's installed on the entire machine(with memory holes between addresses A0000-FFFFF(IBM PC memory hole) and F00000-FFFFFF(ISA memory hole)). It's still 6MB memory, just those memory holes have their memory moved up in RAM(the PC memory(hole) is moved to 1MB+. Then the ISA memory(hole) is moved 1MB+(100000-A0000) ahead).

OPTINLINE void applyMemoryHoles(uint_32 *realaddress, byte *nonexistant)
{
if (*realaddress >= LOW_MEMORYHOLE_END) //1MB+?
{
if ((*realaddress >= MID_MEMORYHOLE_START) && (*realaddress < MID_MEMORYHOLE_END)) //15-16M ISA memory hole?
{
*nonexistant = 1; //Non-existant memory!
}
else if (*realaddress<MID_MEMORYHOLE_START) //Mid memory(IBM AT memory range)?
{
*realaddress -= (LOW_MEMORYHOLE_END - LOW_MEMORYHOLE_START); //Patch to less memory to make memory linear!
}
else if (!((*realaddress>=MID_MEMORYHOLE_END) && (*realaddress<HIGH_MEMORYHOLE_START))) //Not High memory hole(32-bit memory range)?
{
*nonexistant = 1; //Non-existant memory!
}
else //High memory?
{
*realaddress -= (LOW_MEMORYHOLE_END - LOW_MEMORYHOLE_START)+(MID_MEMORYHOLE_END - MID_MEMORYHOLE_START); //Patch to less memory to make memory linear!
}
}
else if (*realaddress >= LOW_MEMORYHOLE_START) //640K ISA memory hole addressed?
{
*nonexistant = 1; //Non-existant memory!
}
}

Essentially, when non-existant(==1) or realaddress>memory size, it ignores the data and returns 0xFF(or data bus on XT) when reading RAM(when not mapped to hardware). Is this correct behaviour?

This is what I'm getting now:

341.jpg
Filename
341.jpg
File size
72.97 KiB
Views
2668 views
File comment
Memory fails?
File license
Fair use/fair dealing exception

Why does it error out with "The Inboard 386/PC's ROM BIOS shadow RAM failed."?

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

Reply 6 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

Apparently, the shadowing is failing because the BIOS ROM lives at F0000+ and F0000+ isn't mapped to memory(memory hole). How do I fix this on the XT?

Also, looking at https://en.wikipedia.org/wiki/BIOS#System_startup , it says that the ROM is mirrored across both locations. So the writes to mirror the high ROM (at FFFF0000) into the low ROM(at F0000) won't have any effect, defeating the whole purpose of the shadowing? Also the 80386 can't start without the ROM at FFFF0000, but the ROM isn't adjusted for this(it immediately jumps to segment F000 the very first instruction(reset vector at FFFFFFF0 being a intersegment direct address jmp(opcode 0xEA))). If the low ROM is just normal memory(as the shadow copying suggests), then it should map to the BIOS ROM at FFFF0000 until the shadowing is started. The problem is: how is this handled? Is it writing a value to port 60h(as it does with the A20 line) to enable/disable the mirroring of the high ROM into the low ROM(mapping the XT BIOS ROM to <address FFFF0000 and F0000> vs <address FFFF0000 only>)?

Edit: I do see port writes to port 0670 values 1E(at 0B54:A70A) and 1F(at 0B54:0B37). Maybe that's the command for the low BIOS area to become RAM(it's executed by the driver it seems)?

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

Reply 7 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

After some work, now the low memory (base memory) is 640K with extended memory whole chunks of 1MB. FOr some reason the shadow RAM still seems to fail, and out of 5120K(5MB extended memory), 704K is assumed bad?

346.jpg
Filename
346.jpg
File size
73 KiB
Views
2624 views
File comment
704K perfectly fine memory is assumed bad?
File license
Fair use/fair dealing exception

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

Reply 8 of 55, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

This might seem dumb but it might also help you figure out what is wrong.

704 = 640 + 64. So if your mmu somehow messes up the memory holes you can have that.

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 9 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

Well, currently the extended memory with expansion (port 670h having been written with 1Eh) is using the following layout:
[640K][1M+][MemoryHole1Remap], where MemoryHole1Remap is only used when port 670h is written with 1E. 1Fh disables the memory hole remapping. The remapped memory 'hole' is the memory from the 640K-1M area, mapped to the end of memory. The same can be done with the other 2 memory holes(16M-17M and 3G-4G). Only the 640K memory hole is mapped in this case(nowhere near 16M memory used).

The total memory(including the memory holes) currently follows the following formula(6M is allocated by default, provided the system has enough memory to allocate, which is done automatically):

		if (MMU.size>=0xA0000) //1MB+ detected?
{
extendedmemory = (MMU.size-0xA0000); //The amount of extended memory!
MMU.maxsize = 0xA0000+(extendedmemory&0xFFF00000); //Only take extended memory in chunks of 1MB!
}

That simply assumes 640K base memory, with the memory from 1M being mapped in contiguous 1MB blocks.

The MMU maps it like this:

OPTINLINE void applyMemoryHoles(uint_32 *realaddress, byte *nonexistant)
{
INLINEREGISTER byte memloc; //What memory block?
INLINEREGISTER byte memoryhole;
memloc = 0; //Default: first memory block: low memory!
memoryhole = 0; //Default: memory unavailable!
if (*realaddress>=LOW_MEMORYHOLE_START) //Start of first hole?
{
if (*realaddress<LOW_MEMORYHOLE_END) //First hole?
{
memoryhole = 1; //First memory hole!
}
else //Mid memory?
{
memloc = 1; //Second memory block: mid memory!
if (*realaddress>=MID_MEMORYHOLE_START) //Start of second hole?
{
if (*realaddress<MID_MEMORYHOLE_END) //Second hole?
{
memoryhole = 2; //Second memory hole!
}
else //High memory?
{
memloc = 2; //Third memory block!
if (*realaddress>=HIGH_MEMORYHOLE_START) //Start of third hole?
{
memoryhole = 3; //Third memory hole!
}
else
{
memloc = 3; //Fourth memory block!
}
}
}
}
}

if (memoryhole) //Memory hole?
{
*nonexistant = 1; //We're non-existant!
}
else //Plain memory?
{
switch (memloc) //What block?
{
case 0: //Main memory?
return; //Nothing to be done!
case 3: //4GB+ 64-bit memory?
if (MoveLowMemoryHigh&4) //Move high memory high?
{
*realaddress -= ((uint_64)HIGH_MEMORYHOLE_END-(uint_64)HIGH_MEMORYHOLE_START);
}
break;
case 2: //16MB+ high memory?
if (MoveLowMemoryHigh&2) //Move mid memory high?
{
*realaddress -= (MID_MEMORYHOLE_END-MID_MEMORYHOLE_START);
}
break;
case 1: //1MB+ mid memory?
Show last 8 lines
				if (MoveLowMemoryHigh&1) //Move low memory high?
{
*realaddress -= (LOW_MEMORYHOLE_END-LOW_MEMORYHOLE_START);
}
break;
}
}
}

Bit 1 of MoveLowMemoryHigh is the inverted bit 0 of values 1Eh and 1Fh written to port 670h.

				switch (value) //Special Inboard 386 commands?
{
case 0x1E: //Move memory high?
case 0x1F: //Move memory normal(using memory hole)?
MoveLowMemoryHigh = GETBITS(~value,0,1); //Disable/enable the HMA memory or BIOS ROM!
return 1;
break;
default: //Unsupported?
dolog("inboard","Unknown Inboard port 670h command: %02X",value);
break;
}

Direct RAM read/write handling:

byte MMU_INTERNAL_directrb(uint_32 realaddress, byte index) //Direct read from real memory (with real data direct)!
{
uint_32 originaladdress = realaddress; //Original address!
byte result;
byte nonexistant = 0;
applyMemoryHoles(&realaddress,&nonexistant); //Apply the memory holes!
if ((realaddress >= MMU.size) || ((realaddress>=MMU.maxsize) && MMU.maxsize) || nonexistant) //Overflow/invalid location?
{
MMU_INTERNAL_INVMEM(originaladdress,realaddress,0,0,index,nonexistant); //Invalid memory accessed!
if ((is_XT==0) || (EMULATED_CPU>=CPU_80286)) //To give NOT for detecting memory on AT only?
{
return 0xFF; //Give the last data read/written by the BUS!
}
else
{
return (byte)(mem_BUSValue >> ((index & 3) << 3)); //Give the last data read/written by the BUS!
}
}
result = MMU.memory[realaddress]; //Get data from memory!
DRAM_access(realaddress); //Tick the DRAM!
if (index != 0xFF) //Don't ignore BUS?
{
mem_BUSValue &= BUSmask[index & 3]; //Apply the bus mask!
mem_BUSValue |= ((uint_32)result << ((index & 3) << 3)); //Or into the last read/written value!
}
if (MMU_logging) //To log?
{
dolog("debugger", "Reading from RAM: %08X=%02X (%c)", realaddress, result, stringsafe(result)); //Log it!
}
return result; //Give existant memory!
}

void MMU_INTERNAL_directwb(uint_32 realaddress, byte value, byte index) //Direct write to real memory (with real data direct)!
{
uint_32 originaladdress = realaddress; //Original address!
if (LOG_MMU_WRITES) //Data debugging?
{
dolog("debugger", "MMU: Writing to real %08X=%02X (%c)", realaddress, value, stringsafe(value));
}
//Apply the 640K memory hole!
byte nonexistant = 0;
applyMemoryHoles(&realaddress,&nonexistant); //Apply the memory holes!
if (index != 0xFF) //Don't ignore BUS?
{
mem_BUSValue &= BUSmask[index & 3]; //Apply the bus mask!
mem_BUSValue |= ((uint_32)value << ((index & 3) << 3)); //Or into the last read/written value!
}
if ((realaddress >= MMU.size) || ((realaddress>=MMU.maxsize) && MMU.maxsize) || nonexistant) //Overflow/invalid location?
{
MMU_INTERNAL_INVMEM(originaladdress,realaddress,1,value,index,nonexistant); //Invalid memory accessed!
return; //Abort!
}
if (MMU_logging) //To log?
{
dolog("debugger", "Writing to RAM: %08X=%02X (%c)", realaddress, value, stringsafe(value)); //Log it!
}
MMU.memory[realaddress] = value; //Set data, full memory protection!
DRAM_access(realaddress); //Tick the DRAM!
if (realaddress>user_memory_used) //More written than present in memory (first write to addr)?
{
Show last 3 lines
		user_memory_used = realaddress; //Update max memory used!
}
}

realaddress is the address to read/write, value is the value to write and index is the subbyte in byte(always 0)/word(0-1)/dword(0-3) operations. So index should be the part of the DWORD in memory accesses(so essentially what part of the data bus is used to access data). I've tried using the mem_BUSvalue on the XT Inboard 386, but it misdetects memory and keeps going until it crashes into reboot when reaching the 15MB barrier. Also index is 0xFF when done by external hardware(e.g. the DMA controller), because it needs to use memory without affecting the CPU data bus.

Edit: Replacing the extended memory rounding with a 1MB rounding(which affects extended memory and low memory), the amount becomes 5504K with 960K bad RAM.

347.jpg
Filename
347.jpg
File size
72.97 KiB
Views
2610 views
File comment
5504K with 960K bad RAM.
File license
Fair use/fair dealing exception

That's 1MB minus 64K.

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

Reply 10 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

The CPU itself generates an address and data bus width and executes a read.

Then the MMU CPU logic splits 32-bit accesses up into two word reads with index 0 and 2 or'ed into the index. Word reads, in turn, split up in byte reads and are or'ed into the index by OR'ing in the values 0 and 1. This results in dword reads being split into memory byte reads indexes 0,1,2,3; Word reads being split up into byte reads indexes 0,1 and byte reads executing directly with index 0. This index is used by the MMU_internal_direct[r/w]b to access the bus data when writing and reading the bus data last written(updates on successfull reads and any writes) as can be seen in the functions. It should be the method to detect memory on x86 afaik, but when I enable it for the Inboard 386 drivers(automatically enabled for XT architectures, AT always returns 0xFF as can be seen), according to the osdev article on detecting (by probing) memory.

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

Reply 11 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just tried the Windows 3.0 setup again on the 80386 AT emulation:

Filename
348.jpg
File size
8.16 KiB
Downloads
No downloads
File comment
Error message once starting the GUI after copying disk1&2.
File license
Fair use/fair dealing exception

Anyone knows what's the cause of this?

Edit: it seems to be infinitely looping at the same point in the AT BIOS ROM as Megarace does.

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

Reply 12 of 55, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

Edit: it seems to be infinitely looping at the same point in the AT BIOS ROM as Megarace does.

If you do not already have the IBM AT BIOS source get it. I found it very useful to figure out what it is doing. It is OCRed from the IBM manuals so it has few errors here and there but generally very good.

Edit: HERE: https://sites.google.com/site/pcdosretro/ibmpcbios

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 13 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've just improved the (AT) 80386 CPU with better protection on jumping to addresses that are invalid(according to the destination segment limit). It's throwing a #GP(0) exception if it's invalid now.

Just tried running the Windows 95 setup.exe, but it seems to hang in an infinite loop. Also, at some point I see some strange #UD instruction which doesn't trigger an exception(as an exception would close the emulator). The debugger indicates it's executing opcode 0xCF(which should be an IRET instruction), but the debugger doesn't recognise the instruction(unimplemented debugger). Strange enough, the entries in the jumptable for the instruction are filled: 16-bits is 8086_OPCF and 32-bits is 80386_OPCF. The only two that don't generate debugger text are the 0F variants(16-bit 0F CF and 32-bit 0F CF), but that doesn't come through my debugger for some reason?

Isn't there ANY 80386 testsuite out there? There should exist one for a CPU that's so much used nowadays(if only because it's the base of all x86 programs)?

Also those 0F instructions are actually 80486 instructions afaik?
According to http://ref.x86asm.net/coder32.html#x0FC8 :

0F C8+r 04+ D22 BSWAP r16/32 Byte Swap

Is it detecting the CPU to be a 80486 for some reason? It's actually a 80386 being emulated(detectable by checking the AC bit, which is always 0).

Edit: Looking at the debugger log, it's executing a #GP fault simply for executing an invalid address?

Filename
debugger.log
File size
209.46 KiB
Downloads
66 downloads
File comment
Debugger log. Look for UNKOP, which indicates the faulting 'instruction'.
File license
Fair use/fair dealing exception

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

Reply 14 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've made a full log of trhe Windows 95 setup executing until it triggers the emulation to quit(main loop has executed a block of instructions and sees that the #UD handler has requested termination of the emulator):

https://www.dropbox.com/s/kuzmd15nc6zvke3/deb … 01_1952.7z?dl=0

Anyone can see why the Windows 95 setup(executed from the second hard disk(MS-DOS 5.0) containing the win95 folder(dutch version of Windows 95)) starts getting to the point of executing undefined opcodes and eventually #GP faults because of an invalid return address during IRET(warning: the log is about 3.5GB in size for just a few seconds of instructions at a speed of 6000 80286 cycles(in 1kHz cycles per second units, so 6MHz, according to the 80286 user reference timings, except for the prefetching(which isn't that accurate)))?

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

Reply 15 of 55, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

I don't think Windows 95 works on a 286, does it not need 386 instructions?

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 16 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

It's essentially a 80386 CPU running on the AT architecture, with 80286 timings for all instructions(including 32-bit operand size variants of the 80286 instructions having the same timings as their 16-bit operand size instructions) that existed on the 80286 and 4 cycles for all new 80386 instructions(80386+ new 0F instructions mainly). The 80386 timings haven't been implemented yet because the IBM AT BIOS requires 80286 speeds to be able to boot. I'll implement the 80386 timings once I've got the 80286/80386 CPU working without problems. Also, is the current lookup table used on the 80286 timings enough to implement the 80386 timings as well?

Current timing lookup entry structure:

//Essentially, each instruction is expressed as a 0F,OPcode,modr/m set. This specifies the entries that apply(base on 0F opcode used, opcode executed and modr/m set when modrm_reg!=0.
//Next, the bits 1-5 specify different kinds of filters that specifies the variant to use, if specified. Variants have priority over the non-variants(bits 1-5==0).

typedef struct
{
word basetiming;
word n; //With RO*/SH*/SAR is the amount of bytes actually shifted; With String instructions, added to base count with multiplier(number of repeats after first instruction)
byte addclock; //bit 0=Add one clock if we're using 3 memory operands! bit 1=n is count to add for string instructions (every repeat). This variant is only used with string instructions., bit 2=We depend on the gate used. The gate type we're for is specified in the low 4 bits of n. The upper 2(bits 4-5) bits of n specify: 1=Same privilege level Call gate, 2=Different privilege level Call gate, no parameters, 3=Different privilege level, X parameters, 0=Ignore privilege level/parameters in the cycle calculation, bit 3=This rule only fires when the jump is taken. bit 4=This rule fires only when the L value of the ENTER instruction matches and fits in the lowest bit of n. 5=This rule fires only when the L value of the ENTER instruction doesn't fit in 1 bit. L is multiplied with the n value and added to the base count cycles.
//Setting addclock bit 2, n lower bits to call gate and n higher bits to 2 adds 4 cycles for each parameter on a 80286.
//With addclock bit 4, n is the L value to be specified. With addclock bit 5, (L - 1) is multiplied with the n value and added to the base count cycles.
} MemoryTimingInfo; //First entry is register value(modr/m register-register), Second entry is memory value(modr/m register-memory)


typedef struct
{
byte CPU; //For what CPU(286 relative)? 0=286, 1=386, 2=486, 3=586(Pentium) etc
byte is32; //32-bit variant of the opcode?
byte is0F; //Are we an extended instruction(0F instruction)?
byte OPcode; //The opcode to be applied to!
byte OPcodemask; //The mask to be applied to the original opcode to match this opcode in order to be applied!
byte modrm_reg; //>0: Substract 1 for the modr/m reg requirement. Else no modr/m is looked at!
struct
{
MemoryTimingInfo ismemory[2]; //First entry is register value(modr/m register-register), Second entry is memory value(modr/m register-memory)
} CPUmode[2]; //0=Real mode, 1=Protected mode
} CPUPM_Timings;

Current timings table itself can be found at(only 80286 timings have been created atm, 80386+ timings still need to be added): https://bitbucket.org/superfury/unipcemu/src/ … ngs.c?at=master

It's the table that starts at line 5. I've already extended the table to be able to handle 32-bit operand sizes(is32 variable). Is this enough to parse the 80386+ timings as well(currently only parsing in a 80286-way)?

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

Reply 17 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've got a little question about the 0F Jcc instructions: They have a 16-bit operand size and 32-bit operand size variant. They both operate on EIP on the 80386+, while the 16-bit operand variant also truncates EIP to 16-bits(clearing the high 16-bits of EIP). So you either can jump to a relative 16-bit address targeting a 16-bit address or jump to a 32-bit address targeting a 32-bit address? So you can't have 32-bit code in a flat space(e.g. Windows/Linux applications) that jump to a relative address specified by a 16-bit integer?

So if I there's a 32-bit program that wants to check if some value is below another (AX<BX) and jump to a 32-bit address using a 16-bit immediate parameter that's almost immediately after the current instruction, it would either have to use a 32-bit immediate offset or 8-bit immediate offset?

So this is impossible:

CMP AX,BX
JC imm16
JMP imm32
imm16: do something

But this is:

CMP AX,BX
JC imm8
JMP imm32
imm8: do something

Also:

CMP AX,BX
JC imm32
JMP imm32after
imm32: do something
imm32after:

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

Reply 18 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've just been thinking about port 670h. Could it be that it's contents have more in it than is currently emulated? It's obvious bit 0 doing something to the memory holes and/or BIOS ROM mapping, while port 60h looks to be some kind of command register(matching 8042 A20 commands). I'll have to change the setup parameters to find out more about this(maybe stuff like cache control is in there as well. Also, nothing is known yet about the remaining bits that (aren't) set(bits 1-7 of port 670h).

So in these cases(default setup), it sets the value of port 670h to 00011110b, with the last bit being the A20 line enable bit. Now the question is: what do bits 1-7 do? Why are they set to 1s?

Edit: Looking around a bit, I've found this little piece of code, at https://github.com/sudleyplace/386SWAT/blob/m … er/SWAT_KEY.ASM:

@@:
test SWATINI.MD_ATTR,@MD_INBRD ; Izit an Inboard/AT?
jz short REBOOT_XINBRD ; Jump if not

; Ensure A20 gated on (huh????)

mov ah,@S2C_WOUT ; Write output port byte
mov al,@S2O_E20 ; Tell it to enable A20
;;;;;;;; or al,10010000b ; Ensure 6805 data line high,
; output buffer full
call U32_PPI_S2C_S2K ; Write command AH, data AL to 8042

mov al,0 ; Value for high speed (80h = slow)
mov dx,674h ; I/O port for speed
out dx,al ; Tell the board to run at high speed
call U32_DRAINPIQ ; Drain the Prefetch Instruction Queue

mov al,0 ; Value to disable cache (1 = enable)
mov dx,670h ; I/O port for cache
out dx,al ; Tell the board to stop caching
call U32_DRAINPIQ ; Drain the Prefetch Instruction Queue
REBOOT_XINBRD:

So the bit on 670 bit 0 isn't the swap bit, but instead a bit to enable caches on the Inboard 386? Also, port 674 bit 7 sets speed to slow(maybe another bit too for 4-level speed)? Maybe it's an 8-bit number to specify slowdown, in cycles?

Edit: Changing the config.sys entry to apply speed=3 with nocache and nodiags results in port 670h being written with the value 16h.

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

Reply 19 of 55, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've tried changing the CPU Wait States with the programs ISPEEDPC parameters 1-4. This results in the following values being written to port 0x670:
Level 1 speed: 0x00(30 Wait States)
Level 2 speed: 0x0E(16 Wait States)
Level 3 speed: 0x16(8 Wait States)
Level 4 speed: 0x1E(0 Wait States)

This makes the old 0x1E value written before the memory test invalid. So what does the 0x1F value written do? It doesn't do anything to the caches, apparently?

Edit: Fixed the Wait States being reversed(value 0=level 1=30 Wait States, which is the default on power-on).

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