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

Last change on this file since 390 was 390, checked in by aitotat@…, 12 years ago

Changes to Assembly Library:

  • Menu library now stores and restores display context.
  • Added couple of new eCMOVx macros.
File size: 11.8 KB
RevLine 
[41]1; Project name  :   Emulation library
[293]2; Description   :   Macros for emulating later x86 instructions with older
[41]3;                   processors.
[293]4;                   Macros are used so optimized builds can be done
[41]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
[293]12; Defines for processor support (should be set in makefile).
13; Unsupported instructions will be emulated using macros.
[41]14; If AT class PC is used (instead of XT), define USE_AT
[293]15
[41]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
[293]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%endif
27
28%ifdef USE_386
29    CPU 386                     ; Allow instructions up to 386
[41]30%elifdef USE_286
[293]31    CPU 286                     ; Allow instructions up to 286
32%elifdef USE_186
33    CPU 186                     ; Allow instructions up to 188/186/V20/V30
34%else
35    CPU 8086                    ; Allow 8088/8086 instructions only
[41]36%endif
[293]37
[41]38BITS 16                         ; Set 16 bit code generation
39
40; Alignments for jump targets.
41; Following values are optimal for different processor types:
42; 286 and 386SX         WORD (16-bit, 2 bytes)
43; 386DX and 486         DWORD (32-bit, 4 bytes)
44; Pentium and later     QWORD (64-bit, 8 bytes)
45%ifdef USE_AT
46    %ifdef USE_386
47        JUMP_ALIGN      EQU     4
48        WORD_ALIGN      EQU     2
49    %else ; USE_286
50        JUMP_ALIGN      EQU     2
51        WORD_ALIGN      EQU     2
52    %endif
53%else ; XT
54    JUMP_ALIGN      EQU     1
55    WORD_ALIGN      EQU     1
56%endif
57
58;==========================================================================
59
60;--------------------------------------------------------------------
61; Emulates BSF (Bit Scan Forward) instruction when necessary.
62; BSF is used to find index of least significant bit.
63;
64; eBSF
65;   Parameters:
66;       %1:     Destination WORD Register for bit index (not CX or same as %2!)
67;       %2:     Source WORD operand where to search bit (not CX or same as %1!)
68;   Returns:
69;       %1:     Index of highest order bit from %2
70;       ZF:     Set if %2 is zero
71;               Cleared if %2 is non-zero
72;   Corrupts registers:
73;       Nothing
74;--------------------------------------------------------------------
75%macro eBSF 2
76%ifndef USE_386
77    push    cx
78    cmp     WORD %2, BYTE 0     ; Source operand is zero?
79    je      SHORT %%Return      ;  If so, return with ZF set
80
81    ; Set destination to zero and load mask for bit 0
82    xor     %1, %1
83    mov     cx, 1
84
85ALIGN JUMP_ALIGN
86%%BitLoop:
87    test    %2, cx              ; Bit set?
88    jnz     SHORT %%Return      ;  If so, return with ZF cleared
89    shl     cx, 1               ; Prepare to test next bit
90    inc     %1                  ; Increment bit index
91    jmp     SHORT %%BitLoop     ; Loop until bit found
92%%Return:
93    pop     cx
94;-----------------------------------
95%else
96    bsf     %1, %2
97%endif
98%endmacro
99
100
101;--------------------------------------------------------------------
102; Emulates BSR (Bit Scan Reverse) instruction when necessary.
103; BSR is used to find index of most significant bit.
104;
105; eBSR
106;   Parameters:
107;       %1:     Destination WORD Register for bit index (not CX or same as %2!)
108;       %2:     Source WORD operand where to search bit (not CX or same as %1!)
109;   Returns:
110;       %1:     Index of highest order bit from %2
111;       ZF:     Set if %2 is zero
112;               Cleared if %2 is non-zero
113;   Corrupts registers:
114;       Nothing
115;--------------------------------------------------------------------
116%macro eBSR 2
117%ifndef USE_386
118    push    cx
119    cmp     WORD %2, BYTE 0     ; Source operand is zero?
120    je      SHORT %%Return      ;  If so, return with ZF set
121
122    ; Load mask for highest order bit
123    mov     cx, 1<<15
124    mov     %1, 15
125
126ALIGN JUMP_ALIGN
127%%BitLoop:
128    test    %2, cx              ; Bit set?
129    jnz     SHORT %%Return      ;  If so, return with ZF cleared
130    shr     cx, 1               ; Prepare to test next bit
131    dec     %1                  ; Decrement bit index
132    jmp     SHORT %%BitLoop     ; Loop until bit found
133%%Return:
134    pop     cx
135;-----------------------------------
136%else
137    bsr     %1, %2
138%endif
139%endmacro
140
141
142;--------------------------------------------------------------------
143; Conditional Move.
144;
145; eCMOVcc
146;   Parameters:
147;       %1:     Destination data
148;       %2:     Source data
149;   Returns:
150;       Nothing
151;   Corrupts registers:
152;       Nothing
153;--------------------------------------------------------------------
[146]154%macro eCMOVA 2
155    jbe     SHORT %%Return
156    mov     %1, %2
157%%Return:
158%endmacro
159
[41]160%macro eCMOVC 2
161    jnc     SHORT %%Return
162    mov     %1, %2
163%%Return:
164%endmacro
165
[390]166%macro eCMOVNC 2
167    jc      SHORT %%Return
168    mov     %1, %2
169%%Return:
170%endmacro
171
[64]172%macro eCMOVZ 2
173    jnz     SHORT %%Return
174    mov     %1, %2
175%%Return:
176%endmacro
177
[94]178%macro eCMOVNZ 2
179    jz      SHORT %%Return
[41]180    mov     %1, %2
181%%Return:
182%endmacro
183
[94]184%macro eCMOVE 2
185    eCMOVZ %1, %2
186%endmacro
187
188%macro eCMOVNE 2
189    eCMOVNZ %1, %2
190%endmacro
191
[60]192%macro eCMOVB 2
193    jnb     SHORT %%Return
194    mov     %1, %2
195%%Return:
196%endmacro
[41]197
[390]198%macro eCMOVS 2
199    jns     SHORT %%Return
200    mov     %1, %2
201%%Return:
202%endmacro
[41]203
[390]204
[168]205;--------------------------------------------------------------------
206; Conditional Set.
207;
208; eCSETcc
209;   Parameters:
210;       %1:     Destination data
211;   Returns:
212;       Nothing
213;   Corrupts registers:
214;       Flags
215;--------------------------------------------------------------------
216%macro eCSETZ 1
217    mov     %1, 0           ; Clear while preserving flags
218    jnz     SHORT %%Return  ; Nothing to set
219    inc     %1
220%%Return:
221%endmacro
[60]222
[168]223
[41]224;--------------------------------------------------------------------
225; Moves byte with zero-extending to any Register.
226;
227; eMOVZX
228;   Parameters:
229;       %1:     Destination Register (SP not supported)
230;       %2:     Byte register or byte address
231;   Returns:
232;       Nothing
233;   Corrupts registers:
234;       FLAGS
235;--------------------------------------------------------------------
236%macro eMOVZX 2
237%ifndef USE_386
238    %ifidni %1, ax
239        mov     al, %2
240        xor     ah, ah
241    %elifidni %1, bx
242        mov     bl, %2
243        xor     bh, bh      ; %2 may use BX in effective address
244    %elifidni %1, cx
245        mov     cl, %2
246        xor     ch, ch
247    %elifidni %1, dx
248        mov     dl, %2
249        xor     dh, dh
250    %else   ; SI, DI, BP (all may be used in effective address)
251        push    ax
252        mov     al, %2
253        xor     ah, ah
254        xchg    ax, %1
255        pop     ax
256    %endif
257;-----------------------------------
258%else
259    movzx   %1, %2
260%endif
261%endmacro
262
263
264;--------------------------------------------------------------------
265; Emulates PUSHA instruction when necessary.
266;
267; ePUSHA
268;   Parameters:
269;       Nothing
270;   Returns:
271;       Nothing
272;   Corrupts registers:
273;       Nothing
274;--------------------------------------------------------------------
275%macro ePUSHA 0
276%ifndef USE_186
277    push    ax
278    push    cx
279    push    dx
280    push    bx
[113]281    push    sp
[41]282    push    bp
283    push    si
284    push    di
285;-----------------------------------
286%else
287    pusha
288%endif
289%endmacro
290
291
292;--------------------------------------------------------------------
293; Emulates POPA instruction when necessary.
294;
295; ePOPA
296;   Parameters:
297;       Nothing
298;   Returns:
299;       Nothing
300;   Corrupts registers:
301;       Nothing
302;--------------------------------------------------------------------
303%macro ePOPA 0
304%ifndef USE_186
305    pop     di
306    pop     si
307    pop     bp
[113]308    pop     ax      ; Skip SP
[41]309    pop     bx
310    pop     dx
311    pop     cx
312    pop     ax
313;-----------------------------------
314%else
315    popa
316%endif
317%endmacro
318
319
320;--------------------------------------------------------------------
321; Emulates ENTER instruction when necessary.
322;
323; eENTER
324;   Parameters:
325;       %1:     Number of bytes to reserve from stack
326;       %2:     The lexical nesting level (not emulated, set to 0)
327;   Returns:
328;       SS:BP:  Ptr to old BP
329;               ([bp-2] points to highest local stack frame word)
330;   Corrupts registers:
331;       FLAGS
332;--------------------------------------------------------------------
333%macro eENTER 2
334%ifndef USE_186
335    push    bp
336    mov     bp, sp
337    sub     sp, %1
338;-----------------------------------
339%else
340    enter   %1, %2
341%endif
342%endmacro
343
344;--------------------------------------------------------------------
345; Emulates LEAVE instruction when necessary.
346;
347; eLEAVE
348;   Parameters:
349;       Nothing
350;   Returns:
351;       BP:     What it was before eENTER
352;   Corrupts registers:
353;       Nothing
354;--------------------------------------------------------------------
355%macro eLEAVE 0
356%ifndef USE_186
357    mov     sp, bp
358    pop     bp
359;-----------------------------------
360%else
361    leave
362%endif
363%endmacro
364
365
366;--------------------------------------------------------------------
367; Emulates LSS instruction when necessary.
368;
369; eLSS
370;   Parameters:
371;       %1:     Destination register
372;       %2:     Source memory address without brackets
373;   Returns:
374;       IF:     0 (interrupts disabled)
375;   Corrupts registers:
376;       Nothing
377;--------------------------------------------------------------------
378%macro eLSS 2
379%ifndef USE_386
380    cli                         ; Disable interrupts
381    mov     %1, [%2]            ; Load offset
382    mov     ss, [%2+2]          ; Load segment
383;-----------------------------------
384%else
385    lss     %1, [%2]
386%endif
387%endmacro
388
389
390;--------------------------------------------------------------------
391; Repeats string instruction with segment override.
392; This macro prevents 8088/8086 restart bug.
393;
394; eSEG_STR
395;   Parameters:
396;       %1:     REP/REPNE or REPE prefix
397;       %2:     Source segment override (destination is always ES)
398;       %3:     String instruction
399;       CX:     Repeat count
400;   Returns:
401;       FLAGS for cmps and scas only
402;   Corrupts registers:
403;       Nothing
404;--------------------------------------------------------------------
405%macro eSEG_STR 3
406%ifndef USE_186 ; 8088/8086 has string instruction restart bug when more than one prefix
[223]407    %%Loop:
408        %1                      ; REP is the prefix that can be lost
409        %2                      ; SEG is the prefix that won't be lost
410        %3                      ; String instruction
411        jcxz    %%End           ; Jump to end if no repeats left (preserves FLAGS)
412        jmp     SHORT %%Loop    ; Loop while repeats left
413    %%End:
[41]414%else   ; No bug on V20/V30 and later, don't know about 188/186
[223]415    %2
416    %1 %3
[41]417%endif
418%endmacro
419
420
421;--------------------------------------------------------------------
422; Bit shifts and rotates with immediate.
423;
424; eSHIFT_IM
425;   Parameters:
426;       %1:     Shift target
427;       %2:     Number of bits to shift
428;       %3:     Instruction (SHL, SHR, ROL, ROR, RCL, RCR)
429;   Returns:
430;       FLAGS
431;   Corrupts registers:
432;       Nothing
433;--------------------------------------------------------------------
434%macro eSHIFT_IM 3
435%ifndef USE_186
436    %ifidni %1, cl
437        times %2    %3      %1, 1
438    %elifidni %1, ch
439        times %2    %3      %1, 1
440    %elifidni %1, cx
441        times %2    %3      %1, 1
442    %else
[181]443;       %if %2 > 7  ; Original value
444        %if %2 > 3  ; Size optimized value
[41]445            push    cx
446            mov     cl, %2
447            %3      %1, cl
448            pop     cx
449        %else
450            times %2    %3      %1, 1
451        %endif
452    %endif
453;-----------------------------------
454%else
455    %3      %1, %2
456%endif
457%endmacro
458%macro eSHR_IM 2
459    eSHIFT_IM   %1, %2, shr
460%endmacro
461%macro eSHL_IM 2
462    eSHIFT_IM   %1, %2, shl
463%endmacro
464%macro eROR_IM 2
465    eSHIFT_IM   %1, %2, ror
466%endmacro
467%macro eROL_IM 2
468    eSHIFT_IM   %1, %2, rol
469%endmacro
470%macro eRCR_IM 2
471    eSHIFT_IM   %1, %2, rcr
472%endmacro
473%macro eRCL_IM 2
474    eSHIFT_IM   %1, %2, rcl
475%endmacro
476
477
478;--------------------------------------------------------------------
479; Emulates PUSH imm instruction when necessary.
480;
481; ePUSH_I
482;   Parameters:
483;       %1:     Immediate to push
484;   Returns:
485;       Nothing
486;   Corrupts registers:
487;       Nothing
488;--------------------------------------------------------------------
489%macro ePUSH_I 1
490%ifndef USE_186
491    push    bp                  ; Immediate goes here
492    push    bp
493    mov     bp, sp
494    mov     WORD [bp+2], %1
495    pop     bp
496;-----------------------------------
497%else
498    push    %1
499%endif
500%endmacro
501
502
503;--------------------------------------------------------------------
504; Emulates PUSH imm instruction when necessary.
505; ePUSH_T uses temporary register for faster performance
506; and smaller code size than ePUSH_I.
507;
508; ePUSH_T
509;   Parameters:
510;       %1:     Temporary Register
511;       %2:     Immediate to push
512;   Returns:
513;       Nothing
514;   Corrupts registers:
515;       %1
516;--------------------------------------------------------------------
517%macro ePUSH_T 2
518%ifndef USE_186
519    %ifidni %2, 0
520        xor     %1, %1
521    %else
522        mov     %1, %2
523    %endif
524    push    %1
525;-----------------------------------
526%else
527    push    %2
528%endif
529%endmacro
530
531
532%endif ; EMULATE_INC
Note: See TracBrowser for help on using the repository browser.