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

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

Changes to Assembly Library:

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