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

Last change on this file since 584 was 568, checked in by krille_n_@…, 10 years ago

Changes:

  • SerDrive: Using named pipe mode (serdrive -p) now works under Windows XP/2000/Server 2003.
  • checksum.pl: Added a compatibility fix for 3Com 3C503 cards.
  • XTIDECFG will now scan every possible segment address to find and load the BIOS and/or its settings from EEPROM. This should simplify things for people using combined option ROMs.
  • Fixed a bug from r521 in BootSector.asm where the BIOS would not display a timeout error if it failed to load the boot sector from harddrive.
  • Fixed a bug from r541 in CompatibleDPT.asm where CompatibleDPT_CreateDeviceParameterTableExtensionToESBXfromDPTinDSSI would generate an invalid checksum in the DPTE.
  • Optimizations and other fixes.
File size: 14.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 %define USE_UNDOC_INTEL ; Not supported by NEC V20/V30
27%endif
28
29%ifdef USE_386
30 CPU 386 ; Allow instructions up to 386
31%elifdef USE_286
32 CPU 286 ; Allow instructions up to 286
33%elifdef USE_186
34 CPU 186 ; Allow instructions up to 188/186/V20/V30
35%else
36 CPU 8086 ; Allow 8088/8086 instructions only
37%endif
38
39BITS 16 ; Set 16 bit code generation
40
41; Alignments for jump targets.
42; Following values are optimal for different processor types:
43; 286 and 386SX WORD (16-bit, 2 bytes)
44; 386DX and 486 DWORD (32-bit, 4 bytes)
45; Pentium and later QWORD (64-bit, 8 bytes)
46%ifdef USE_AT
47 %ifdef USE_386
48 JUMP_ALIGN EQU 4
49 WORD_ALIGN EQU 2
50 %else ; USE_286
51 JUMP_ALIGN EQU 2
52 WORD_ALIGN EQU 2
53 %endif
54%else ; XT
55 JUMP_ALIGN EQU 1
56 WORD_ALIGN EQU 1
57%endif
58
59;==========================================================================
60
61;--------------------------------------------------------------------
62; The undocumented instruction SALC (Set AL According to CF).
63; Available on all Intel processors and truly compatible clones.
64; Does not work on the NEC V20/V30 or Sony CXQ70108 processors.
65;
66; eSALC
67; Parameters:
68; Nothing
69; Returns:
70; AL: FFh if CF=1
71; 00h if CF=0
72; Corrupts registers:
73; Nothing
74;--------------------------------------------------------------------
75%macro eSALC 0
76; db 0D6h
77 salc
78%endmacro
79
80
81;--------------------------------------------------------------------
82; The AAD instruction (ASCII Adjust before Division).
83; Available on all Intel processors and truly compatible clones.
84; Does not work on the NEC V20/V30 or Sony CXQ70108 processors
85; unless %1 is 10 (0Ah).
86;
87; eAAD
88; Parameters:
89; %1: Any 8 bit number (0...255)
90; Returns:
91; AL: AH * %1 + AL
92; AH: 0
93; Flags: Set according to result
94; Corrupts registers:
95; Nothing
96;--------------------------------------------------------------------
97%macro eAAD 1
98%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
99 %if %1 > 255
100 %error Invalid parameter passed to eAAD (%1 > 255)
101 %else
102 db 0D5h, %1
103 %endif
104%endif
105%endmacro
106
107
108;--------------------------------------------------------------------
109; The AAM instruction (ASCII Adjust after Multiplication).
110; Available on all Intel processors and truly compatible clones.
111; Does not work on the NEC V20/V30 or Sony CXQ70108 processors
112; unless %1 is 10 (0Ah).
113;
114; eAAM
115; Parameters:
116; %1: Any 8 bit number except 0 (1...255)
117; Returns:
118; AL: AL MOD %1
119; AH: AL / %1
120; Flags: Set according to result
121; Corrupts registers:
122; Nothing
123;--------------------------------------------------------------------
124%macro eAAM 1
125%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
126 %if %1 > 255
127 %error Invalid parameter passed to eAAM (%1 > 255)
128 %elif %1 = 0
129 %error Invalid parameter passed to eAAM (%1 = 0). This would cause a divide-by-zero exception!
130 %else
131 db 0D4h, %1
132 %endif
133%endif
134%endmacro
135
136
137;--------------------------------------------------------------------
138; Emulates BSF (Bit Scan Forward) instruction when necessary.
139; BSF is used to find index of least significant bit.
140;
141; eBSF
142; Parameters:
143; %1: Destination WORD Register for bit index (not CX or same as %2!)
144; %2: Source WORD operand where to search bit (not CX or same as %1!)
145; Returns:
146; %1: Index of highest order bit from %2
147; ZF: Set if %2 is zero
148; Cleared if %2 is non-zero
149; Corrupts registers:
150; Nothing
151;--------------------------------------------------------------------
152%macro eBSF 2
153%ifndef USE_386
154 push cx
155 cmp WORD %2, BYTE 0 ; Source operand is zero?
156 je SHORT %%Return ; If so, return with ZF set
157
158 ; Set destination to zero and load mask for bit 0
159 xor %1, %1
160 mov cx, 1
161
162ALIGN JUMP_ALIGN
163%%BitLoop:
164 test %2, cx ; Bit set?
165 jnz SHORT %%Return ; If so, return with ZF cleared
166 shl cx, 1 ; Prepare to test next bit
167 inc %1 ; Increment bit index
168 jmp SHORT %%BitLoop ; Loop until bit found
169%%Return:
170 pop cx
171;-----------------------------------
172%else
173 bsf %1, %2
174%endif
175%endmacro
176
177
178;--------------------------------------------------------------------
179; Emulates BSR (Bit Scan Reverse) instruction when necessary.
180; BSR is used to find index of most significant bit.
181;
182; eBSR
183; Parameters:
184; %1: Destination WORD Register for bit index (not CX or same as %2!)
185; %2: Source WORD operand where to search bit (not CX or same as %1!)
186; Returns:
187; %1: Index of highest order bit from %2
188; ZF: Set if %2 is zero
189; Cleared if %2 is non-zero
190; Corrupts registers:
191; Nothing
192;--------------------------------------------------------------------
193%macro eBSR 2
194%ifndef USE_386
195 push cx
196 cmp WORD %2, BYTE 0 ; Source operand is zero?
197 je SHORT %%Return ; If so, return with ZF set
198
199 ; Load mask for highest order bit
200 mov cx, 1<<15
201 mov %1, 15
202
203ALIGN JUMP_ALIGN
204%%BitLoop:
205 test %2, cx ; Bit set?
206 jnz SHORT %%Return ; If so, return with ZF cleared
207 shr cx, 1 ; Prepare to test next bit
208 dec %1 ; Decrement bit index
209 jmp SHORT %%BitLoop ; Loop until bit found
210%%Return:
211 pop cx
212;-----------------------------------
213%else
214 bsr %1, %2
215%endif
216%endmacro
217
218
219;--------------------------------------------------------------------
220; Conditional Move.
221;
222; eCMOVcc
223; Parameters:
224; %1: Destination data
225; %2: Source data
226; Returns:
227; Nothing
228; Corrupts registers:
229; Nothing
230;--------------------------------------------------------------------
231%macro eCMOVA 2
232 jbe SHORT %%Return
233 mov %1, %2
234%%Return:
235%endmacro
236
237%macro eCMOVC 2
238 jnc SHORT %%Return
239 mov %1, %2
240%%Return:
241%endmacro
242
243%macro eCMOVNC 2
244 jc SHORT %%Return
245 mov %1, %2
246%%Return:
247%endmacro
248
249%macro eCMOVZ 2
250 jnz SHORT %%Return
251 mov %1, %2
252%%Return:
253%endmacro
254
255%macro eCMOVNZ 2
256 jz SHORT %%Return
257 mov %1, %2
258%%Return:
259%endmacro
260
261%macro eCMOVE 2
262 eCMOVZ %1, %2
263%endmacro
264
265%macro eCMOVNE 2
266 eCMOVNZ %1, %2
267%endmacro
268
269%macro eCMOVB 2
270 jnb SHORT %%Return
271 mov %1, %2
272%%Return:
273%endmacro
274
275%macro eCMOVS 2
276 jns SHORT %%Return
277 mov %1, %2
278%%Return:
279%endmacro
280
281%macro eCMOVNS 2
282 js SHORT %%Return
283 mov %1, %2
284%%Return:
285%endmacro
286
287
288;--------------------------------------------------------------------
289; Conditional Set.
290;
291; eCSETcc
292; Parameters:
293; %1: Destination data
294; Returns:
295; Nothing
296; Corrupts registers:
297; Flags
298;--------------------------------------------------------------------
299%macro eCSETZ 1
300 mov %1, 0 ; Clear while preserving flags
301 jnz SHORT %%Return ; Nothing to set
302 inc %1
303%%Return:
304%endmacro
305
306
307;--------------------------------------------------------------------
308; Moves byte with zero-extending to any Register.
309;
310; eMOVZX
311; Parameters:
312; %1: Destination Register (SP not supported)
313; %2: Byte register or byte address
314; Returns:
315; Nothing
316; Corrupts registers:
317; FLAGS
318;--------------------------------------------------------------------
319%macro eMOVZX 2
320%ifndef USE_386
321 %ifidni %1, ax
322 mov al, %2
323 xor ah, ah
324 %elifidni %1, bx
325 mov bl, %2
326 xor bh, bh ; %2 may use BX in effective address
327 %elifidni %1, cx
328 mov cl, %2
329 xor ch, ch
330 %elifidni %1, dx
331 mov dl, %2
332 xor dh, dh
333 %else ; SI, DI, BP (all may be used in effective address)
334 push ax
335 mov al, %2
336 xor ah, ah
337 xchg ax, %1
338 pop ax
339 %endif
340;-----------------------------------
341%else
342 movzx %1, %2
343%endif
344%endmacro
345
346
347;--------------------------------------------------------------------
348; Emulates PUSHA instruction when necessary.
349;
350; ePUSHA
351; Parameters:
352; Nothing
353; Returns:
354; Nothing
355; Corrupts registers:
356; Nothing
357;--------------------------------------------------------------------
358%macro ePUSHA 0
359%ifndef USE_186
360 push ax
361 push cx
362 push dx
363 push bx
364 push sp
365 push bp
366 push si
367 push di
368;-----------------------------------
369%else
370 pusha
371%endif
372%endmacro
373
374
375;--------------------------------------------------------------------
376; Emulates POPA instruction when necessary.
377;
378; ePOPA
379; Parameters:
380; Nothing
381; Returns:
382; Nothing
383; Corrupts registers:
384; Nothing
385;--------------------------------------------------------------------
386%macro ePOPA 0
387%ifndef USE_186
388 pop di
389 pop si
390 pop bp
391 pop ax ; Skip SP
392 pop bx
393 pop dx
394 pop cx
395 pop ax
396;-----------------------------------
397%else
398 popa
399%endif
400%endmacro
401
402
403;--------------------------------------------------------------------
404; Emulates ENTER instruction when necessary.
405;
406; eENTER
407; Parameters:
408; %1: Number of bytes to reserve from stack
409; %2: The lexical nesting level (not emulated, set to 0)
410; Returns:
411; SS:BP: Ptr to old BP
412; ([bp-2] points to highest local stack frame word)
413; Corrupts registers:
414; FLAGS
415;--------------------------------------------------------------------
416%macro eENTER 2
417%ifndef USE_186
418 push bp
419 mov bp, sp
420 sub sp, %1
421;-----------------------------------
422%else
423 enter %1, %2
424%endif
425%endmacro
426
427;--------------------------------------------------------------------
428; Emulates LEAVE instruction when necessary.
429;
430; eLEAVE
431; Parameters:
432; Nothing
433; Returns:
434; BP: What it was before eENTER
435; Corrupts registers:
436; Nothing
437;--------------------------------------------------------------------
438%macro eLEAVE 0
439%ifndef USE_186
440 mov sp, bp
441 pop bp
442;-----------------------------------
443%else
444 leave
445%endif
446%endmacro
447
448
449;--------------------------------------------------------------------
450; Emulates LSS instruction when necessary.
451;
452; eLSS
453; Parameters:
454; %1: Destination register
455; %2: Source memory address without brackets
456; Returns:
457; IF: 0 (interrupts disabled)
458; Corrupts registers:
459; Nothing
460;--------------------------------------------------------------------
461%macro eLSS 2
462%ifndef USE_386
463 cli ; Disable interrupts
464 mov %1, [%2] ; Load offset
465 mov ss, [%2+2] ; Load segment
466;-----------------------------------
467%else
468 lss %1, [%2]
469%endif
470%endmacro
471
472
473;--------------------------------------------------------------------
474; Repeats string instruction with segment override.
475; This macro prevents 8088/8086 restart bug.
476;
477; eSEG_STR
478; Parameters:
479; %1: REP/REPNE or REPE prefix
480; %2: Source segment override (destination is always ES)
481; %3: String instruction
482; CX: Repeat count
483; Returns:
484; FLAGS for cmps and scas only
485; Corrupts registers:
486; Nothing
487;--------------------------------------------------------------------
488%macro eSEG_STR 3
489%ifndef USE_186 ; 8088/8086 has string instruction restart bug when more than one prefix
490 %%Loop:
491 %1 ; REP is the prefix that can be lost
492 %2 ; SEG is the prefix that won't be lost
493 %3 ; String instruction
494 jcxz %%End ; Jump to end if no repeats left (preserves FLAGS)
495 jmp SHORT %%Loop ; Loop while repeats left
496 %%End:
497%else ; No bug on V20/V30 and later, don't know about 188/186
498 %2
499 %1 %3
500%endif
501%endmacro
502
503
504;--------------------------------------------------------------------
505; Bit shifts and rotates with immediate.
506;
507; eSHIFT_IM
508; Parameters:
509; %1: Shift target
510; %2: Number of bits to shift
511; %3: Instruction (SHL, SHR, ROL, ROR, RCL, RCR)
512; Returns:
513; FLAGS
514; Corrupts registers:
515; Nothing
516;--------------------------------------------------------------------
517%macro eSHIFT_IM 3
518%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
519%ifndef USE_186
520 %ifidni %1, cl
521 times %2 %3 %1, 1
522 %elifidni %1, ch
523 times %2 %3 %1, 1
524 %elifidni %1, cx
525 times %2 %3 %1, 1
526 %else
527 %if %2 > 3 ; Size optimized value
528 push cx
529 mov cl, %2
530 %3 %1, cl
531 pop cx
532 %else
533 times %2 %3 %1, 1
534 %endif
535 %endif
536;-----------------------------------
537%else
538 %3 %1, %2
539%endif
540%endif
541%endmacro
542
543%macro eSHR_IM 2
544 eSHIFT_IM %1, %2, shr
545%endmacro
546
547%macro eSHL_IM 2
548%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS
549%ifdef USE_386
550 %if %2 = 1
551 add %1, %1 ; Same size but faster on 386 and 486. Fails if %1 is a memory operand.
552 %else
553 eSHIFT_IM %1, %2, shl
554 %endif
555%else
556 eSHIFT_IM %1, %2, shl
557%endif
558%endif
559%endmacro
560
561%macro eROR_IM 2
562 eSHIFT_IM %1, %2, ror
563%endmacro
564
565%macro eROL_IM 2
566 eSHIFT_IM %1, %2, rol
567%endmacro
568
569%macro eRCR_IM 2
570 eSHIFT_IM %1, %2, rcr
571%endmacro
572
573%macro eRCL_IM 2
574 eSHIFT_IM %1, %2, rcl
575%endmacro
576
577
578;--------------------------------------------------------------------
579; Emulates PUSH imm instruction when necessary.
580;
581; ePUSH_I
582; Parameters:
583; %1: Immediate to push
584; Returns:
585; Nothing
586; Corrupts registers:
587; Nothing
588;--------------------------------------------------------------------
589%macro ePUSH_I 1
590%ifndef USE_186
591 push bp ; Immediate goes here
592 push bp
593 mov bp, sp
594 mov WORD [bp+2], %1
595 pop bp
596;-----------------------------------
597%else
598 push %1
599%endif
600%endmacro
601
602
603;--------------------------------------------------------------------
604; Emulates PUSH imm instruction when necessary.
605; ePUSH_T uses temporary register for faster performance
606; and smaller code size than ePUSH_I.
607;
608; ePUSH_T
609; Parameters:
610; %1: Temporary Register
611; %2: Immediate to push
612; Returns:
613; Nothing
614; Corrupts registers:
615; %1
616;--------------------------------------------------------------------
617%macro ePUSH_T 2
618%ifndef USE_186
619 %ifidni %2, 0
620 xor %1, %1
621 %else
622 mov %1, %2
623 %endif
624 push %1
625;-----------------------------------
626%else
627 push %2
628%endif
629%endmacro
630
631
632%endif ; EMULATE_INC
Note: See TracBrowser for help on using the repository browser.