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

Last change on this file since 490 was 489, checked in by gregli@…, 12 years ago

Added version string to initial title banner, for cases where there is not a boot menu (just hotkeys, or no hotkeys). Also ifdef'd out some unused code.

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