VirtualBox

Changeset 74612 in vbox for trunk/src


Ignore:
Timestamp:
Oct 4, 2018 1:24:24 PM (6 years ago)
Author:
vboxsync
Message:

BIOS: Slightly optimized INT 15h protected mode switching code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/BIOS/system.c

    r71423 r74612  
    8585 */
    8686
    87 void pm_stack_save(uint16_t cx, uint16_t es, uint16_t si, uint16_t frame);
     87void pm_stack_save(uint16_t cx, uint16_t es, uint16_t si);
    8888#pragma aux pm_stack_save =     \
    8989    ".386"                      \
    9090    "push   ds"                 \
    9191    "push   eax"                \
    92     "xor    eax, eax"           \
     92    "xor    ax, ax"             \
    9393    "mov    ds, ax"             \
    9494    "mov    ds:[467h], sp"      \
    9595    "mov    ds:[469h], ss"      \
    96     parm [cx] [es] [si] [ax] modify nomemory;
    97 
    98 /* Uses position independent code... because it was too hard to figure
    99  * out how to code the far call in inline assembler.
     96    parm [cx] [es] [si] modify nomemory;
     97
     98/* Uses position independent code to build a far return... because it was
     99 * too hard to figure out how to code the far call in inline assembler.
     100 *
     101 * NB: It would be lovely to do 'add [sp],N' instead of 'pop ax; add ax,M;
     102 * push ax'. Unfortunately the former cannot be encoded, though 'add [esp],N'
     103 * can be on 386 and later -- but it may be unwise to assume that the high
     104 * bits of ESP are all zero.
    100105 */
    101106void pm_enter(void);
    102107#pragma aux pm_enter =              \
    103108    ".386p"                         \
     109    "lgdt   fword ptr es:[si+8]"    \
     110    "lidt   fword ptr cs:pmode_IDT" \
     111    "push   20h"                    \
    104112    "call   pentry"                 \
    105113    "pentry:"                       \
    106114    "pop    ax"                     \
    107     "add    ax, 1Bh"                \
    108     "push   20h"                    \
     115    "add    ax, 0Eh"                \
    109116    "push   ax"                     \
    110     "lgdt   fword ptr es:[si+8]"    \
    111     "lidt   fword ptr cs:pmode_IDT" \
    112117    "mov    eax, cr0"               \
    113118    "or     al, 1"                  \
     
    115120    "retf"                          \
    116121    "pm_pm:"                        \
    117     "mov    ax, 28h"                \
    118     "mov    ss, ax"                 \
    119122    "mov    ax, 10h"                \
    120123    "mov    ds, ax"                 \
    121     "mov    ax, 18h"                \
     124    "add    al, 08h"                \
    122125    "mov    es, ax"                 \
     126    "add    al, 10h"                \
     127    "mov    ss, ax"                 \
    123128    modify nomemory;
    124129
     
    129134#pragma aux pm_exit =               \
    130135    ".386p"                         \
     136    "mov    ax, 28h"                \
     137    "mov    ds, ax"                 \
     138    "mov    es, ax"                 \
     139    "push   0F000h"                 \
    131140    "call   pexit"                  \
    132141    "pexit:"                        \
    133142    "pop    ax"                     \
    134     "push   0F000h"                 \
    135     "add    ax, 18h"                \
     143    "add    ax, 0Eh"                \
    136144    "push   ax"                     \
    137     "mov    ax, 28h"                \
    138     "mov    ds, ax"                 \
    139     "mov    es, ax"                 \
    140145    "mov    eax, cr0"               \
    141146    "and    al, 0FEh"               \
     
    176181/* Uses position independent code... because it was too hard to figure
    177182 * out how to code the far call in inline assembler.
    178  * NB: Trashes MSW bits but the CPU will be reset anyway.
    179183 */
    180184void pm_enter(void);
    181185#pragma aux pm_enter =              \
    182186    ".286p"                         \
     187    "lgdt   fword ptr es:[si+8]"    \
     188    "lidt   fword ptr cs:pmode_IDT" \
     189    "push   20h"                    \
    183190    "call   pentry"                 \
    184191    "pentry:"                       \
    185     "pop    di"                     \
    186     "add    di, 18h"                \
    187     "push   20h"                    \
    188     "push   di"                     \
    189     "lgdt   fword ptr es:[si+8]"    \
    190     "lidt   fword ptr cs:pmode_IDT" \
     192    "pop    ax"                     \
     193    "add    ax, 0Eh"                \
     194    "push   ax"                     \
     195    "smsw   ax"                     \
    191196    "or     al, 1"                  \
    192197    "lmsw   ax"                     \
    193198    "retf"                          \
    194199    "pm_pm:"                        \
    195     "mov    ax, 28h"                \
    196     "mov    ss, ax"                 \
    197200    "mov    ax, 10h"                \
    198201    "mov    ds, ax"                 \
    199     "mov    ax, 18h"                \
     202    "add    al, 08h"                \
    200203    "mov    es, ax"                 \
     204    "add    al, 10h"                \
     205    "mov    ss, ax"                 \
    201206    modify nomemory;
    202207
     
    227232#endif
    228233
     234/* NB: CX is set earlier in pm_stack_save */
    229235void pm_copy(void);
    230236#pragma aux pm_copy =               \
     
    233239    "cld"                           \
    234240    "rep    movsw"                  \
    235     modify [di] nomemory;
     241    modify [si di cx] nomemory;
    236242
    237243/* The pm_switch has a few crucial differences from pm_enter, hence
     
    241247#pragma aux pm_switch =             \
    242248    ".286p"                         \
     249    "lgdt   fword ptr es:[si+08h]"  \
     250    "lidt   fword ptr es:[si+10h]"  \
     251    "push   38h"                    \
    243252    "call   pentry"                 \
    244253    "pentry:"                       \
    245     "pop    di"                     \
    246     "add    di, 18h"                \
    247     "push   38h"                    \
    248     "push   di"                     \
    249     "lgdt   fword ptr es:[si+08h]"  \
    250     "lidt   fword ptr es:[si+10h]"  \
    251     "mov    ax, 1"                  \
     254    "pop    ax"                     \
     255    "add    ax, 0Eh"                \
     256    "push   ax"                     \
     257    "smsw   ax"                     \
     258    "or     al, 1"                  \
    252259    "lmsw   ax"                     \
    253260    "retf"                          \
    254261    "pm_pm:"                        \
    255     "mov    ax, 28h"                \
    256     "mov    ss, ax"                 \
    257262    "mov    ax, 18h"                \
    258263    "mov    ds, ax"                 \
    259     "mov    ax, 20h"                \
     264    "add    al, 08h"                \
    260265    "mov    es, ax"                 \
     266    "add    al, 08h"                \
     267    "mov    ss, ax"                 \
    261268    parm [si] modify nomemory;
    262269
     
    861868    // ==============================================
    862869    // 00..07   Unused  zeros      Null descriptor
    863     // 08..0f   GDT     zeros      filled in by BIOS
     870    // 08..0f   scratch zeros      work area used by BIOS
    864871    // 10..17   source  ssssssss   source of data
    865872    // 18..1f   dest    dddddddd   destination of data
     
    902909    write_word(ES, SI+0x28+6, 0x0000);   // base 31:24/reserved/limit 19:16
    903910
     911#if VBOX_BIOS_CPU >= 80386
     912    /* Not taking the address of the parameter allows the code generator
     913     * produce slightly better code for some unknown reason.
     914     */
     915    pm_stack_save(CX, ES, SI);
     916#else
    904917    pm_stack_save(CX, ES, SI, FP_OFF(&r));
     918#endif
    905919    pm_enter();
    906920    pm_copy();
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette