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

Last change on this file since 380 was 293, checked in by krille_n_@…, 13 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.