Changeset 59765 in vbox
- Timestamp:
- Feb 22, 2016 8:51:07 AM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/BIOS/invop.c
r56292 r59765 20 20 #include "biosint.h" 21 21 #include "inlines.h" 22 23 //#define EMU_386_LOADALL 22 24 23 25 /* The layout of 286 LOADALL descriptors. */ … … 63 65 ct_assert(sizeof(ldall_286_s) == 0x66); 64 66 67 #ifdef EMU_386_LOADALL 68 69 /* The layout of 386 LOADALL descriptors. */ 70 typedef struct tag_ldal3_desc { 71 uint32_t attr; /* Segment attributes. */ 72 uint32_t base; /* Expanded segment base. */ 73 uint32_t limit; /* Expanded segment limit. */ 74 } ldal3_desc; 75 76 /* The 386 LOADALL memory buffer pointed to by ES:EDI. 77 */ 78 typedef struct tag_ldall_386 { 79 uint32_t cr0; /* 00h */ 80 uint32_t eflags; /* 04h */ 81 uint32_t eip; /* 08h */ 82 uint32_t edi; /* 0Ch */ 83 uint32_t esi; /* 10h */ 84 uint32_t ebp; /* 14h */ 85 uint32_t esp; /* 18h */ 86 uint32_t ebx; /* 1Ch */ 87 uint32_t edx; /* 20h */ 88 uint32_t ecx; /* 24h */ 89 uint32_t eax; /* 28h */ 90 uint32_t dr6; /* 2Ch */ 91 uint32_t dr7; /* 30h */ 92 uint32_t tr; /* 34h */ 93 uint32_t ldt; /* 38h */ 94 uint32_t gs; /* 3Ch */ 95 uint32_t fs; /* 40h */ 96 uint32_t ds; /* 44h */ 97 uint32_t ss; /* 4Ch */ 98 uint32_t cs; /* 48h */ 99 uint32_t es; /* 50h */ 100 ldal3_desc tss_desc; /* 54h */ 101 ldal3_desc idt_desc; /* 60h */ 102 ldal3_desc gdt_desc; /* 6Ch */ 103 ldal3_desc ldt_desc; /* 78h */ 104 ldal3_desc gs_desc; /* 84h */ 105 ldal3_desc fs_desc; /* 90h */ 106 ldal3_desc ds_desc; /* 9Ch */ 107 ldal3_desc ss_desc; /* A8h */ 108 ldal3_desc cs_desc; /* B4h */ 109 ldal3_desc es_desc; /* C0h */ 110 } ldall_386_s; 111 ct_assert(sizeof(ldall_386_s) == 0xCC); 112 113 #endif 114 65 115 /* 66 116 * LOADALL emulation assumptions: … … 146 196 parm nomemory modify nomemory aborts; 147 197 198 #ifdef EMU_386_LOADALL 199 200 /* 386 version of the above. */ 201 void ldal3_finish(void); 202 #pragma aux ldal3_finish = \ 203 ".386" \ 204 "mov sp, 28h" \ 205 "popad" \ 206 "mov sp, ss:[18h]" \ 207 "sub sp, 6" \ 208 "mov ss, ss:[48h]" \ 209 "iret" \ 210 parm nomemory modify nomemory aborts; 211 212 /* 386 version of load_rm_segs. 213 * NB: Must not touch CX! 214 */ 215 void load_rm_seg3(int seg_flags, uint16_t ss_base); 216 #pragma aux load_rm_seg3 = \ 217 "mov ss, ax" \ 218 "mov ax, ss:[44h]" \ 219 "mov ds, ax" \ 220 "mov ax, ss:[50h]" \ 221 "mov es, ax" \ 222 parm [ax] [cx] nomemory modify nomemory; 223 224 #endif 148 225 149 226 #define LOAD_ES 0x01 /* ES needs to be loaded in protected mode. */ … … 213 290 load_pm_segs(); 214 291 ldall_finish(); 292 #ifdef EMU_386_LOADALL 293 } else if (*(uint16_t __far *)ins == 0x070F) { 294 /* 386 LOADALL. NB: Same opcode as SYSRET. */ 295 ldall_386_s __far *ldbuf = (void __far *)es :> gr.u.r16.di; /* Assume 16-bit value in EDI. */ 296 ldall_286_s __far *ldbuf2 = 0 :> 0x800; 297 iret_addr_t __far *ret_addr; 298 uint32_t seg_base; 299 int seg_flags = 0; 300 301 /* NB: BIG FAT ASSUMPTION! Users of 386 LOADALL are assumed to also 302 * have a 286 LOADALL buffer at physical address 800h. We use unused fields 303 * in that buffer for temporary storage. 304 */ 305 306 /* Set up return stack. */ 307 ret_addr = ldbuf->ss :> (ldbuf->esp - sizeof(iret_addr_t)); 308 ret_addr->ip = ldbuf->eip; 309 ret_addr->cs = ldbuf->cs; 310 ret_addr->flags.u.r16.flags = ldbuf->eflags; 311 312 /* Examine ES/DS. */ 313 seg_base = ldbuf->es_desc.base; 314 if (seg_base != (uint32_t)ldbuf->es << 4) 315 seg_flags |= LOAD_ES; 316 seg_base = ldbuf->ds_desc.base; 317 if (seg_base != (uint32_t)ldbuf->ds << 4) 318 seg_flags |= LOAD_DS; 319 320 /* The LOADALL buffer doubles as a tiny GDT. */ 321 load_gdtr(0x800, 4 * 8 - 1); 322 323 /* Store the ES base/limit/attributes in the unused words (GDT selector 8). */ 324 ldbuf2->unused2[0] = ldbuf->es_desc.limit; 325 ldbuf2->unused2[1] = (uint16_t)ldbuf->es_desc.base; 326 ldbuf2->unused2[2] = (ldbuf->es_desc.attr & 0xFF00) | (ldbuf->es_desc.base >> 16); 327 ldbuf2->unused2[3] = 0; 328 329 /* Store the DS base/limit/attributes in other unused words. */ 330 ldbuf2->unused1[0] = ldbuf->ds_desc.limit; 331 ldbuf2->unused1[1] = (uint16_t)ldbuf->ds_desc.base; 332 ldbuf2->unused1[2] = (ldbuf->ds_desc.attr & 0xFF00) | (ldbuf->ds_desc.base >> 16); 333 334 /* Load the IDTR as specified. */ 335 seg_base = ldbuf->idt_desc.base; 336 load_idtr(seg_base, ldbuf->idt_desc.limit); 337 338 /* Do the tricky bits now. */ 339 load_rm_seg3(es, seg_flags); 340 load_pm_segs(); 341 ldal3_finish(); 342 #endif 215 343 } else { 216 344 /* There isn't much point in executing the invalid opcode handler
Note:
See TracChangeset
for help on using the changeset viewer.