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

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

Changes to Assembly Library:

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