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

Last change on this file since 146 was 146, checked in by aitotat, 13 years ago

Changes to Assembly Library:

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