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

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

Commit 1/2 (Library, Configurators and Serial Server):

  • Changed Emulate.inc so that making 286 and 386 versions now works. Additionally, only one processor type define is needed in the makefile.
  • Minor optimizations.
  • Fixed spelling and did some cleaning.
File size: 11.6 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
[64]166%macro eCMOVZ 2
167    jnz     SHORT %%Return
168    mov     %1, %2
169%%Return:
170%endmacro
171
[94]172%macro eCMOVNZ 2
173    jz      SHORT %%Return
[41]174    mov     %1, %2
175%%Return:
176%endmacro
177
[94]178%macro eCMOVE 2
179    eCMOVZ %1, %2
180%endmacro
181
182%macro eCMOVNE 2
183    eCMOVNZ %1, %2
184%endmacro
185
[60]186%macro eCMOVB 2
187    jnb     SHORT %%Return
188    mov     %1, %2
189%%Return:
190%endmacro
[41]191
192
[168]193;--------------------------------------------------------------------
194; Conditional Set.
195;
196; eCSETcc
197;   Parameters:
198;       %1:     Destination data
199;   Returns:
200;       Nothing
201;   Corrupts registers:
202;       Flags
203;--------------------------------------------------------------------
204%macro eCSETZ 1
205    mov     %1, 0           ; Clear while preserving flags
206    jnz     SHORT %%Return  ; Nothing to set
207    inc     %1
208%%Return:
209%endmacro
[60]210
[168]211
[41]212;--------------------------------------------------------------------
213; Moves byte with zero-extending to any Register.
214;
215; eMOVZX
216;   Parameters:
217;       %1:     Destination Register (SP not supported)
218;       %2:     Byte register or byte address
219;   Returns:
220;       Nothing
221;   Corrupts registers:
222;       FLAGS
223;--------------------------------------------------------------------
224%macro eMOVZX 2
225%ifndef USE_386
226    %ifidni %1, ax
227        mov     al, %2
228        xor     ah, ah
229    %elifidni %1, bx
230        mov     bl, %2
231        xor     bh, bh      ; %2 may use BX in effective address
232    %elifidni %1, cx
233        mov     cl, %2
234        xor     ch, ch
235    %elifidni %1, dx
236        mov     dl, %2
237        xor     dh, dh
238    %else   ; SI, DI, BP (all may be used in effective address)
239        push    ax
240        mov     al, %2
241        xor     ah, ah
242        xchg    ax, %1
243        pop     ax
244    %endif
245;-----------------------------------
246%else
247    movzx   %1, %2
248%endif
249%endmacro
250
251
252;--------------------------------------------------------------------
253; Emulates PUSHA instruction when necessary.
254;
255; ePUSHA
256;   Parameters:
257;       Nothing
258;   Returns:
259;       Nothing
260;   Corrupts registers:
261;       Nothing
262;--------------------------------------------------------------------
263%macro ePUSHA 0
264%ifndef USE_186
265    push    ax
266    push    cx
267    push    dx
268    push    bx
[113]269    push    sp
[41]270    push    bp
271    push    si
272    push    di
273;-----------------------------------
274%else
275    pusha
276%endif
277%endmacro
278
279
280;--------------------------------------------------------------------
281; Emulates POPA instruction when necessary.
282;
283; ePOPA
284;   Parameters:
285;       Nothing
286;   Returns:
287;       Nothing
288;   Corrupts registers:
289;       Nothing
290;--------------------------------------------------------------------
291%macro ePOPA 0
292%ifndef USE_186
293    pop     di
294    pop     si
295    pop     bp
[113]296    pop     ax      ; Skip SP
[41]297    pop     bx
298    pop     dx
299    pop     cx
300    pop     ax
301;-----------------------------------
302%else
303    popa
304%endif
305%endmacro
306
307
308;--------------------------------------------------------------------
309; Emulates ENTER instruction when necessary.
310;
311; eENTER
312;   Parameters:
313;       %1:     Number of bytes to reserve from stack
314;       %2:     The lexical nesting level (not emulated, set to 0)
315;   Returns:
316;       SS:BP:  Ptr to old BP
317;               ([bp-2] points to highest local stack frame word)
318;   Corrupts registers:
319;       FLAGS
320;--------------------------------------------------------------------
321%macro eENTER 2
322%ifndef USE_186
323    push    bp
324    mov     bp, sp
325    sub     sp, %1
326;-----------------------------------
327%else
328    enter   %1, %2
329%endif
330%endmacro
331
332;--------------------------------------------------------------------
333; Emulates LEAVE instruction when necessary.
334;
335; eLEAVE
336;   Parameters:
337;       Nothing
338;   Returns:
339;       BP:     What it was before eENTER
340;   Corrupts registers:
341;       Nothing
342;--------------------------------------------------------------------
343%macro eLEAVE 0
344%ifndef USE_186
345    mov     sp, bp
346    pop     bp
347;-----------------------------------
348%else
349    leave
350%endif
351%endmacro
352
353
354;--------------------------------------------------------------------
355; Emulates LSS instruction when necessary.
356;
357; eLSS
358;   Parameters:
359;       %1:     Destination register
360;       %2:     Source memory address without brackets
361;   Returns:
362;       IF:     0 (interrupts disabled)
363;   Corrupts registers:
364;       Nothing
365;--------------------------------------------------------------------
366%macro eLSS 2
367%ifndef USE_386
368    cli                         ; Disable interrupts
369    mov     %1, [%2]            ; Load offset
370    mov     ss, [%2+2]          ; Load segment
371;-----------------------------------
372%else
373    lss     %1, [%2]
374%endif
375%endmacro
376
377
378;--------------------------------------------------------------------
379; Repeats string instruction with segment override.
380; This macro prevents 8088/8086 restart bug.
381;
382; eSEG_STR
383;   Parameters:
384;       %1:     REP/REPNE or REPE prefix
385;       %2:     Source segment override (destination is always ES)
386;       %3:     String instruction
387;       CX:     Repeat count
388;   Returns:
389;       FLAGS for cmps and scas only
390;   Corrupts registers:
391;       Nothing
392;--------------------------------------------------------------------
393%macro eSEG_STR 3
394%ifndef USE_186 ; 8088/8086 has string instruction restart bug when more than one prefix
[223]395    %%Loop:
396        %1                      ; REP is the prefix that can be lost
397        %2                      ; SEG is the prefix that won't be lost
398        %3                      ; String instruction
399        jcxz    %%End           ; Jump to end if no repeats left (preserves FLAGS)
400        jmp     SHORT %%Loop    ; Loop while repeats left
401    %%End:
[41]402%else   ; No bug on V20/V30 and later, don't know about 188/186
[223]403    %2
404    %1 %3
[41]405%endif
406%endmacro
407
408
409;--------------------------------------------------------------------
410; Bit shifts and rotates with immediate.
411;
412; eSHIFT_IM
413;   Parameters:
414;       %1:     Shift target
415;       %2:     Number of bits to shift
416;       %3:     Instruction (SHL, SHR, ROL, ROR, RCL, RCR)
417;   Returns:
418;       FLAGS
419;   Corrupts registers:
420;       Nothing
421;--------------------------------------------------------------------
422%macro eSHIFT_IM 3
423%ifndef USE_186
424    %ifidni %1, cl
425        times %2    %3      %1, 1
426    %elifidni %1, ch
427        times %2    %3      %1, 1
428    %elifidni %1, cx
429        times %2    %3      %1, 1
430    %else
[181]431;       %if %2 > 7  ; Original value
432        %if %2 > 3  ; Size optimized value
[41]433            push    cx
434            mov     cl, %2
435            %3      %1, cl
436            pop     cx
437        %else
438            times %2    %3      %1, 1
439        %endif
440    %endif
441;-----------------------------------
442%else
443    %3      %1, %2
444%endif
445%endmacro
446%macro eSHR_IM 2
447    eSHIFT_IM   %1, %2, shr
448%endmacro
449%macro eSHL_IM 2
450    eSHIFT_IM   %1, %2, shl
451%endmacro
452%macro eROR_IM 2
453    eSHIFT_IM   %1, %2, ror
454%endmacro
455%macro eROL_IM 2
456    eSHIFT_IM   %1, %2, rol
457%endmacro
458%macro eRCR_IM 2
459    eSHIFT_IM   %1, %2, rcr
460%endmacro
461%macro eRCL_IM 2
462    eSHIFT_IM   %1, %2, rcl
463%endmacro
464
465
466;--------------------------------------------------------------------
467; Emulates PUSH imm instruction when necessary.
468;
469; ePUSH_I
470;   Parameters:
471;       %1:     Immediate to push
472;   Returns:
473;       Nothing
474;   Corrupts registers:
475;       Nothing
476;--------------------------------------------------------------------
477%macro ePUSH_I 1
478%ifndef USE_186
479    push    bp                  ; Immediate goes here
480    push    bp
481    mov     bp, sp
482    mov     WORD [bp+2], %1
483    pop     bp
484;-----------------------------------
485%else
486    push    %1
487%endif
488%endmacro
489
490
491;--------------------------------------------------------------------
492; Emulates PUSH imm instruction when necessary.
493; ePUSH_T uses temporary register for faster performance
494; and smaller code size than ePUSH_I.
495;
496; ePUSH_T
497;   Parameters:
498;       %1:     Temporary Register
499;       %2:     Immediate to push
500;   Returns:
501;       Nothing
502;   Corrupts registers:
503;       %1
504;--------------------------------------------------------------------
505%macro ePUSH_T 2
506%ifndef USE_186
507    %ifidni %2, 0
508        xor     %1, %1
509    %else
510        mov     %1, %2
511    %endif
512    push    %1
513;-----------------------------------
514%else
515    push    %2
516%endif
517%endmacro
518
519
520%endif ; EMULATE_INC
Note: See TracBrowser for help on using the repository browser.