source: xtideuniversalbios/trunk/Assembly_Library/Inc/Emulate.inc @ 568

Last change on this file since 568 was 568, checked in by krille_n_@…, 9 years ago

Changes:

  • SerDrive: Using named pipe mode (serdrive -p) now works under Windows XP/2000/Server 2003.
  • checksum.pl: Added a compatibility fix for 3Com 3C503 cards.
  • XTIDECFG will now scan every possible segment address to find and load the BIOS and/or its settings from EEPROM. This should simplify things for people using combined option ROMs.
  • Fixed a bug from r521 in BootSector.asm where the BIOS would not display a timeout error if it failed to load the boot sector from harddrive.
  • Fixed a bug from r541 in CompatibleDPT.asm where CompatibleDPT_CreateDeviceParameterTableExtensionToESBXfromDPTinDSSI would generate an invalid checksum in the DPTE.
  • Optimizations and other fixes.
File size: 14.1 KB
Line 
1; Project name  :   Emulation library
2; Description   :   Macros for emulating later x86 instructions with older
3;                   processors.
4;                   Macros are used so optimized builds can be done
5;                   easily for different processors.
6;
7;                   This file must be first to be included to
8;                   any source file.
9%ifndef EMULATE_INC
10%define EMULATE_INC
11
12; Defines for processor support (should be set in makefile).
13; Unsupported instructions will be emulated using macros.
14; If AT class PC is used (instead of XT), define USE_AT
15
16;%define USE_186                ; Define to use 18x/V20/V30 instructions
17;%define USE_286                ; Define to use 286 instructions
18;%define USE_386                ; Define to use 386 instructions
19;%define USE_AT                 ; Define for AT class machine
20
21%ifdef USE_386
22    %define USE_286             ; Define to use 286 instructions
23%endif
24%ifdef USE_286
25    %define USE_186             ; Define to use 18x/V20/V30 instructions
26    %define USE_UNDOC_INTEL     ; Not supported by NEC V20/V30
27%endif
28
29%ifdef USE_386
30    CPU 386                     ; Allow instructions up to 386
31%elifdef USE_286
32    CPU 286                     ; Allow instructions up to 286
33%elifdef USE_186
34    CPU 186                     ; Allow instructions up to 188/186/V20/V30
35%else
36    CPU 8086                    ; Allow 8088/8086 instructions only
37%endif
38
39BITS 16                         ; Set 16 bit code generation
40
41; Alignments for jump targets.
42; Following values are optimal for different processor types:
43; 286 and 386SX         WORD (16-bit, 2 bytes)
44; 386DX and 486         DWORD (32-bit, 4 bytes)
45; Pentium and later     QWORD (64-bit, 8 bytes)
46%ifdef USE_AT
47    %ifdef USE_386
48        JUMP_ALIGN      EQU     4
49        WORD_ALIGN      EQU     2
50    %else ; USE_286
51        JUMP_ALIGN      EQU     2
52        WORD_ALIGN      EQU     2
53    %endif
54%else ; XT
55    JUMP_ALIGN      EQU     1
56    WORD_ALIGN      EQU     1
57%endif
58
59;==========================================================================
60
61;--------------------------------------------------------------------
62; The undocumented instruction SALC (Set AL According to CF).
63; Available on all Intel processors and truly compatible clones.
64; Does not work on the NEC V20/V30 or Sony CXQ70108 processors.
65;
66; eSALC
67;   Parameters:
68;       Nothing
69;   Returns:
70;       AL:     FFh if CF=1
71;               00h if CF=0
72;   Corrupts registers:
73;       Nothing
74;--------------------------------------------------------------------
75%macro eSALC 0
76;   db      0D6h
77    salc
78%endmacro
79
80
81;--------------------------------------------------------------------
82; The AAD instruction (ASCII Adjust before Division).
83; Available on all Intel processors and truly compatible clones.
84; Does not work on the NEC V20/V30 or Sony CXQ70108 processors
85; unless %1 is 10 (0Ah).
86;
87; eAAD
88;   Parameters:
89;       %1:     Any 8 bit number (0...255)
90;   Returns:
91;       AL:     AH * %1 + AL
92;       AH:     0
93;       Flags:  Set according to result
94;   Corrupts registers:
95;       Nothing
96;--------------------------------------------------------------------
97%macro eAAD 1
98%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
99    %if %1 > 255
100        %error Invalid parameter passed to eAAD (%1 > 255)
101    %else
102        db      0D5h, %1
103    %endif
104%endif
105%endmacro
106
107
108;--------------------------------------------------------------------
109; The AAM instruction (ASCII Adjust after Multiplication).
110; Available on all Intel processors and truly compatible clones.
111; Does not work on the NEC V20/V30 or Sony CXQ70108 processors
112; unless %1 is 10 (0Ah).
113;
114; eAAM
115;   Parameters:
116;       %1:     Any 8 bit number except 0 (1...255)
117;   Returns:
118;       AL:     AL MOD %1
119;       AH:     AL / %1
120;       Flags:  Set according to result
121;   Corrupts registers:
122;       Nothing
123;--------------------------------------------------------------------
124%macro eAAM 1
125%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
126    %if %1 > 255
127        %error Invalid parameter passed to eAAM (%1 > 255)
128    %elif %1 = 0
129        %error Invalid parameter passed to eAAM (%1 = 0). This would cause a divide-by-zero exception!
130    %else
131        db      0D4h, %1
132    %endif
133%endif
134%endmacro
135
136
137;--------------------------------------------------------------------
138; Emulates BSF (Bit Scan Forward) instruction when necessary.
139; BSF is used to find index of least significant bit.
140;
141; eBSF
142;   Parameters:
143;       %1:     Destination WORD Register for bit index (not CX or same as %2!)
144;       %2:     Source WORD operand where to search bit (not CX or same as %1!)
145;   Returns:
146;       %1:     Index of highest order bit from %2
147;       ZF:     Set if %2 is zero
148;               Cleared if %2 is non-zero
149;   Corrupts registers:
150;       Nothing
151;--------------------------------------------------------------------
152%macro eBSF 2
153%ifndef USE_386
154    push    cx
155    cmp     WORD %2, BYTE 0     ; Source operand is zero?
156    je      SHORT %%Return      ;  If so, return with ZF set
157
158    ; Set destination to zero and load mask for bit 0
159    xor     %1, %1
160    mov     cx, 1
161
162ALIGN JUMP_ALIGN
163%%BitLoop:
164    test    %2, cx              ; Bit set?
165    jnz     SHORT %%Return      ;  If so, return with ZF cleared
166    shl     cx, 1               ; Prepare to test next bit
167    inc     %1                  ; Increment bit index
168    jmp     SHORT %%BitLoop     ; Loop until bit found
169%%Return:
170    pop     cx
171;-----------------------------------
172%else
173    bsf     %1, %2
174%endif
175%endmacro
176
177
178;--------------------------------------------------------------------
179; Emulates BSR (Bit Scan Reverse) instruction when necessary.
180; BSR is used to find index of most significant bit.
181;
182; eBSR
183;   Parameters:
184;       %1:     Destination WORD Register for bit index (not CX or same as %2!)
185;       %2:     Source WORD operand where to search bit (not CX or same as %1!)
186;   Returns:
187;       %1:     Index of highest order bit from %2
188;       ZF:     Set if %2 is zero
189;               Cleared if %2 is non-zero
190;   Corrupts registers:
191;       Nothing
192;--------------------------------------------------------------------
193%macro eBSR 2
194%ifndef USE_386
195    push    cx
196    cmp     WORD %2, BYTE 0     ; Source operand is zero?
197    je      SHORT %%Return      ;  If so, return with ZF set
198
199    ; Load mask for highest order bit
200    mov     cx, 1<<15
201    mov     %1, 15
202
203ALIGN JUMP_ALIGN
204%%BitLoop:
205    test    %2, cx              ; Bit set?
206    jnz     SHORT %%Return      ;  If so, return with ZF cleared
207    shr     cx, 1               ; Prepare to test next bit
208    dec     %1                  ; Decrement bit index
209    jmp     SHORT %%BitLoop     ; Loop until bit found
210%%Return:
211    pop     cx
212;-----------------------------------
213%else
214    bsr     %1, %2
215%endif
216%endmacro
217
218
219;--------------------------------------------------------------------
220; Conditional Move.
221;
222; eCMOVcc
223;   Parameters:
224;       %1:     Destination data
225;       %2:     Source data
226;   Returns:
227;       Nothing
228;   Corrupts registers:
229;       Nothing
230;--------------------------------------------------------------------
231%macro eCMOVA 2
232    jbe     SHORT %%Return
233    mov     %1, %2
234%%Return:
235%endmacro
236
237%macro eCMOVC 2
238    jnc     SHORT %%Return
239    mov     %1, %2
240%%Return:
241%endmacro
242
243%macro eCMOVNC 2
244    jc      SHORT %%Return
245    mov     %1, %2
246%%Return:
247%endmacro
248
249%macro eCMOVZ 2
250    jnz     SHORT %%Return
251    mov     %1, %2
252%%Return:
253%endmacro
254
255%macro eCMOVNZ 2
256    jz      SHORT %%Return
257    mov     %1, %2
258%%Return:
259%endmacro
260
261%macro eCMOVE 2
262    eCMOVZ %1, %2
263%endmacro
264
265%macro eCMOVNE 2
266    eCMOVNZ %1, %2
267%endmacro
268
269%macro eCMOVB 2
270    jnb     SHORT %%Return
271    mov     %1, %2
272%%Return:
273%endmacro
274
275%macro eCMOVS 2
276    jns     SHORT %%Return
277    mov     %1, %2
278%%Return:
279%endmacro
280
281%macro eCMOVNS 2
282    js      SHORT %%Return
283    mov     %1, %2
284%%Return:
285%endmacro
286
287
288;--------------------------------------------------------------------
289; Conditional Set.
290;
291; eCSETcc
292;   Parameters:
293;       %1:     Destination data
294;   Returns:
295;       Nothing
296;   Corrupts registers:
297;       Flags
298;--------------------------------------------------------------------
299%macro eCSETZ 1
300    mov     %1, 0           ; Clear while preserving flags
301    jnz     SHORT %%Return  ; Nothing to set
302    inc     %1
303%%Return:
304%endmacro
305
306
307;--------------------------------------------------------------------
308; Moves byte with zero-extending to any Register.
309;
310; eMOVZX
311;   Parameters:
312;       %1:     Destination Register (SP not supported)
313;       %2:     Byte register or byte address
314;   Returns:
315;       Nothing
316;   Corrupts registers:
317;       FLAGS
318;--------------------------------------------------------------------
319%macro eMOVZX 2
320%ifndef USE_386
321    %ifidni %1, ax
322        mov     al, %2
323        xor     ah, ah
324    %elifidni %1, bx
325        mov     bl, %2
326        xor     bh, bh      ; %2 may use BX in effective address
327    %elifidni %1, cx
328        mov     cl, %2
329        xor     ch, ch
330    %elifidni %1, dx
331        mov     dl, %2
332        xor     dh, dh
333    %else   ; SI, DI, BP (all may be used in effective address)
334        push    ax
335        mov     al, %2
336        xor     ah, ah
337        xchg    ax, %1
338        pop     ax
339    %endif
340;-----------------------------------
341%else
342    movzx   %1, %2
343%endif
344%endmacro
345
346
347;--------------------------------------------------------------------
348; Emulates PUSHA instruction when necessary.
349;
350; ePUSHA
351;   Parameters:
352;       Nothing
353;   Returns:
354;       Nothing
355;   Corrupts registers:
356;       Nothing
357;--------------------------------------------------------------------
358%macro ePUSHA 0
359%ifndef USE_186
360    push    ax
361    push    cx
362    push    dx
363    push    bx
364    push    sp
365    push    bp
366    push    si
367    push    di
368;-----------------------------------
369%else
370    pusha
371%endif
372%endmacro
373
374
375;--------------------------------------------------------------------
376; Emulates POPA instruction when necessary.
377;
378; ePOPA
379;   Parameters:
380;       Nothing
381;   Returns:
382;       Nothing
383;   Corrupts registers:
384;       Nothing
385;--------------------------------------------------------------------
386%macro ePOPA 0
387%ifndef USE_186
388    pop     di
389    pop     si
390    pop     bp
391    pop     ax      ; Skip SP
392    pop     bx
393    pop     dx
394    pop     cx
395    pop     ax
396;-----------------------------------
397%else
398    popa
399%endif
400%endmacro
401
402
403;--------------------------------------------------------------------
404; Emulates ENTER instruction when necessary.
405;
406; eENTER
407;   Parameters:
408;       %1:     Number of bytes to reserve from stack
409;       %2:     The lexical nesting level (not emulated, set to 0)
410;   Returns:
411;       SS:BP:  Ptr to old BP
412;               ([bp-2] points to highest local stack frame word)
413;   Corrupts registers:
414;       FLAGS
415;--------------------------------------------------------------------
416%macro eENTER 2
417%ifndef USE_186
418    push    bp
419    mov     bp, sp
420    sub     sp, %1
421;-----------------------------------
422%else
423    enter   %1, %2
424%endif
425%endmacro
426
427;--------------------------------------------------------------------
428; Emulates LEAVE instruction when necessary.
429;
430; eLEAVE
431;   Parameters:
432;       Nothing
433;   Returns:
434;       BP:     What it was before eENTER
435;   Corrupts registers:
436;       Nothing
437;--------------------------------------------------------------------
438%macro eLEAVE 0
439%ifndef USE_186
440    mov     sp, bp
441    pop     bp
442;-----------------------------------
443%else
444    leave
445%endif
446%endmacro
447
448
449;--------------------------------------------------------------------
450; Emulates LSS instruction when necessary.
451;
452; eLSS
453;   Parameters:
454;       %1:     Destination register
455;       %2:     Source memory address without brackets
456;   Returns:
457;       IF:     0 (interrupts disabled)
458;   Corrupts registers:
459;       Nothing
460;--------------------------------------------------------------------
461%macro eLSS 2
462%ifndef USE_386
463    cli                         ; Disable interrupts
464    mov     %1, [%2]            ; Load offset
465    mov     ss, [%2+2]          ; Load segment
466;-----------------------------------
467%else
468    lss     %1, [%2]
469%endif
470%endmacro
471
472
473;--------------------------------------------------------------------
474; Repeats string instruction with segment override.
475; This macro prevents 8088/8086 restart bug.
476;
477; eSEG_STR
478;   Parameters:
479;       %1:     REP/REPNE or REPE prefix
480;       %2:     Source segment override (destination is always ES)
481;       %3:     String instruction
482;       CX:     Repeat count
483;   Returns:
484;       FLAGS for cmps and scas only
485;   Corrupts registers:
486;       Nothing
487;--------------------------------------------------------------------
488%macro eSEG_STR 3
489%ifndef USE_186 ; 8088/8086 has string instruction restart bug when more than one prefix
490    %%Loop:
491        %1                      ; REP is the prefix that can be lost
492        %2                      ; SEG is the prefix that won't be lost
493        %3                      ; String instruction
494        jcxz    %%End           ; Jump to end if no repeats left (preserves FLAGS)
495        jmp     SHORT %%Loop    ; Loop while repeats left
496    %%End:
497%else   ; No bug on V20/V30 and later, don't know about 188/186
498    %2
499    %1 %3
500%endif
501%endmacro
502
503
504;--------------------------------------------------------------------
505; Bit shifts and rotates with immediate.
506;
507; eSHIFT_IM
508;   Parameters:
509;       %1:     Shift target
510;       %2:     Number of bits to shift
511;       %3:     Instruction (SHL, SHR, ROL, ROR, RCL, RCR)
512;   Returns:
513;       FLAGS
514;   Corrupts registers:
515;       Nothing
516;--------------------------------------------------------------------
517%macro eSHIFT_IM 3
518%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
519%ifndef USE_186
520    %ifidni %1, cl
521        times %2    %3      %1, 1
522    %elifidni %1, ch
523        times %2    %3      %1, 1
524    %elifidni %1, cx
525        times %2    %3      %1, 1
526    %else
527        %if %2 > 3  ; Size optimized value
528            push    cx
529            mov     cl, %2
530            %3      %1, cl
531            pop     cx
532        %else
533            times %2    %3      %1, 1
534        %endif
535    %endif
536;-----------------------------------
537%else
538    %3      %1, %2
539%endif
540%endif
541%endmacro
542
543%macro eSHR_IM 2
544    eSHIFT_IM   %1, %2, shr
545%endmacro
546
547%macro eSHL_IM 2
548%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
549%ifdef USE_386
550    %if %2 = 1
551        add     %1, %1  ; Same size but faster on 386 and 486. Fails if %1 is a memory operand.
552    %else
553        eSHIFT_IM   %1, %2, shl
554    %endif
555%else
556    eSHIFT_IM   %1, %2, shl
557%endif
558%endif
559%endmacro
560
561%macro eROR_IM 2
562    eSHIFT_IM   %1, %2, ror
563%endmacro
564
565%macro eROL_IM 2
566    eSHIFT_IM   %1, %2, rol
567%endmacro
568
569%macro eRCR_IM 2
570    eSHIFT_IM   %1, %2, rcr
571%endmacro
572
573%macro eRCL_IM 2
574    eSHIFT_IM   %1, %2, rcl
575%endmacro
576
577
578;--------------------------------------------------------------------
579; Emulates PUSH imm instruction when necessary.
580;
581; ePUSH_I
582;   Parameters:
583;       %1:     Immediate to push
584;   Returns:
585;       Nothing
586;   Corrupts registers:
587;       Nothing
588;--------------------------------------------------------------------
589%macro ePUSH_I 1
590%ifndef USE_186
591    push    bp                  ; Immediate goes here
592    push    bp
593    mov     bp, sp
594    mov     WORD [bp+2], %1
595    pop     bp
596;-----------------------------------
597%else
598    push    %1
599%endif
600%endmacro
601
602
603;--------------------------------------------------------------------
604; Emulates PUSH imm instruction when necessary.
605; ePUSH_T uses temporary register for faster performance
606; and smaller code size than ePUSH_I.
607;
608; ePUSH_T
609;   Parameters:
610;       %1:     Temporary Register
611;       %2:     Immediate to push
612;   Returns:
613;       Nothing
614;   Corrupts registers:
615;       %1
616;--------------------------------------------------------------------
617%macro ePUSH_T 2
618%ifndef USE_186
619    %ifidni %2, 0
620        xor     %1, %1
621    %else
622        mov     %1, %2
623    %endif
624    push    %1
625;-----------------------------------
626%else
627    push    %2
628%endif
629%endmacro
630
631
632%endif ; EMULATE_INC
Note: See TracBrowser for help on using the repository browser.