source: xtideuniversalbios/trunk/Configurator/Inc/emulate.inc@ 416

Last change on this file since 416 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: 10.4 KB
RevLine 
[2]1; Project name : Emulation library
[293]2; Description : Macros for emulating later x86 instructions with older
[2]3; processors.
[293]4; Macros are used so optimized builds can be done
[2]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.
[2]14; If AT class PC is used (instead of XT), define USE_AT
[293]15
[2]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
[2]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
[2]36%endif
[293]37
[2]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; Moves byte with zero-extending to any Register.
144;
145; eMOVZX
146; Parameters:
147; %1: Destination Register (SP not supported)
148; %2: Byte register or byte address
149; Returns:
150; Nothing
151; Corrupts registers:
152; FLAGS
153;--------------------------------------------------------------------
154%macro eMOVZX 2
155%ifndef USE_386
156 %ifidni %1, ax
157 xor ax, ax
158 mov al, %2
159 %elifidni %1, bx
160 mov bl, %2
161 xor bh, bh ; %2 may use BX in effective address
162 %elifidni %1, cx
163 xor cx, cx
164 mov cl, %2
165 %elifidni %1, dx
166 xor dx, dx
167 mov dl, %2
168 %else ; SI, DI, BP (all may be used in effective address)
169 push ax
170 xor ax, ax
171 mov al, %2
172 xchg ax, %1
173 pop ax
174 %endif
175;-----------------------------------
176%else
177 movzx %1, %2
178%endif
179%endmacro
180
181
182;--------------------------------------------------------------------
183; Emulates PUSHA instruction when necessary.
184;
185; ePUSHA
186; Parameters:
187; Nothing
188; Returns:
189; Nothing
190; Corrupts registers:
191; Nothing
192;--------------------------------------------------------------------
193%macro ePUSHA 0
194%ifndef USE_186
195 push ax
196 push cx
197 push dx
198 push bx
199 ; SP before first push should be pushed here
200 push bp
201 push si
202 push di
203;-----------------------------------
204%else
205 pusha
206%endif
207%endmacro
208
209
210;--------------------------------------------------------------------
211; Emulates POPA instruction when necessary.
212;
213; ePOPA
214; Parameters:
215; Nothing
216; Returns:
217; Nothing
218; Corrupts registers:
219; Nothing
220;--------------------------------------------------------------------
221%macro ePOPA 0
222%ifndef USE_186
223 pop di
224 pop si
225 pop bp
226 ; Old SP should be skipped here
227 pop bx
228 pop dx
229 pop cx
230 pop ax
231;-----------------------------------
232%else
233 popa
234%endif
235%endmacro
236
237
238;--------------------------------------------------------------------
239; Emulates ENTER instruction when necessary.
240;
241; eENTER
242; Parameters:
243; %1: Number of bytes to reserve from stack
244; %2: The lexical nesting level (not emulated)
245; Returns:
246; SS:BP: Ptr to old BP
247; ([bp-2] points to highest local stack frame word)
248; Corrupts registers:
249; FLAGS
250;--------------------------------------------------------------------
251%macro eENTER 2
252%ifndef USE_186
253 push bp
254 mov bp, sp
255 sub sp, %1
256;-----------------------------------
257%else
258 enter %1, %2
259%endif
260%endmacro
261
262
263;--------------------------------------------------------------------
264; Emulates LEAVE instruction when necessary.
265;
266; eLEAVE
267; Parameters:
268; Nothing
269; Returns:
270; Nothing
271; Corrupts registers:
272; Nothing
273;--------------------------------------------------------------------
274%macro eLEAVE 0
275%ifndef USE_186
276 mov sp, bp
277 pop bp
278;-----------------------------------
279%else
280 leave
281%endif
282%endmacro
283
284
285;--------------------------------------------------------------------
286; Emulates LSS instruction when necessary.
287;
288; eLSS
289; Parameters:
290; %1: Destination register
291; %2: Source memory address without brackets
292; Returns:
293; IF: 0 (interrupts disabled)
294; Corrupts registers:
295; Nothing
296;--------------------------------------------------------------------
297%macro eLSS 2
298%ifndef USE_386
299 cli ; Disable interrupts
300 mov %1, [%2] ; Load offset
301 mov ss, [%2+2] ; Load segment
302;-----------------------------------
303%else
304 lss %1, [%2]
305%endif
306%endmacro
307
308
309;--------------------------------------------------------------------
310; Repeats string instruction with segment override.
311; This macro prevents 8088/8086 restart bug.
312;
313; eSEG_STR
314; Parameters:
315; %1: REP/REPNE or REPE prefix
316; %2: Source segment override (destination is always ES)
317; %3: String instruction
318; CX: Repeat count
319; Returns:
320; FLAGS for cmps and scas only
321; Corrupts registers:
322; Nothing
323;--------------------------------------------------------------------
324%macro eSEG_STR 3
325%ifndef USE_186 ; 8088/8086 has string instruction restart bug when more than one prefix
[223]326 %%Loop:
327 %1 ; REP is the prefix that can be lost
328 %2 ; SEG is the prefix that won't be lost
329 %3 ; String instruction
330 jcxz %%End ; Jump to end if no repeats left (preserves FLAGS)
331 jmp SHORT %%Loop ; Loop while repeats left
332 %%End:
[2]333%else ; No bug on V20/V30 and later, don't know about 188/186
[223]334 %2
335 %1 %3
[2]336%endif
337%endmacro
338
339
340;--------------------------------------------------------------------
341; Bit shifts and rotates with immediate.
342;
343; eSHIFT_IM
344; Parameters:
345; %1: Shift target
346; %2: Number of bits to shift
347; %3: Instruction (SHL, SHR, ROL, ROR, RCL, RCR)
348; Returns:
349; FLAGS
350; Corrupts registers:
351; Nothing
352;--------------------------------------------------------------------
353%macro eSHIFT_IM 3
354%ifndef USE_186
355 %ifidni %1, cl
356 times %2 %3 %1, 1
357 %elifidni %1, ch
358 times %2 %3 %1, 1
359 %elifidni %1, cx
360 times %2 %3 %1, 1
361 %else
362 %if %2 > 7
363 push cx
364 mov cl, %2
365 %3 %1, cl
366 pop cx
367 %else
368 times %2 %3 %1, 1
369 %endif
370 %endif
371;-----------------------------------
372%else
373 %3 %1, %2
374%endif
375%endmacro
376%macro eSHR_IM 2
377 eSHIFT_IM %1, %2, shr
378%endmacro
379%macro eSHL_IM 2
380 eSHIFT_IM %1, %2, shl
381%endmacro
382%macro eROR_IM 2
383 eSHIFT_IM %1, %2, ror
384%endmacro
385%macro eROL_IM 2
386 eSHIFT_IM %1, %2, rol
387%endmacro
388%macro eRCR_IM 2
389 eSHIFT_IM %1, %2, rcr
390%endmacro
391%macro eRCL_IM 2
392 eSHIFT_IM %1, %2, rcl
393%endmacro
394
395
396;--------------------------------------------------------------------
397; Emulates PUSH imm instruction when necessary.
398;
399; ePUSH_I
400; Parameters:
401; %1: Immediate to push
402; Returns:
403; Nothing
404; Corrupts registers:
405; Nothing
406;--------------------------------------------------------------------
407%macro ePUSH_I 1
408%ifndef USE_186
409 push bp ; Immediate goes here
410 push bp
411 mov bp, sp
412 mov WORD [bp+2], %1
413 pop bp
414;-----------------------------------
415%else
416 push %1
417%endif
418%endmacro
419
420
421;--------------------------------------------------------------------
422; Emulates PUSH imm instruction when necessary.
423; ePUSH_T uses temporary register for faster performance
424; and smaller code size than ePUSH_I.
425;
426; ePUSH_T
427; Parameters:
428; %1: Temporary Register
429; %2: Immediate to push
430; Returns:
431; Nothing
432; Corrupts registers:
433; %1
434;--------------------------------------------------------------------
435%macro ePUSH_T 2
436%ifndef USE_186
437 %ifidni %2, 0
438 xor %1, %1
439 %else
440 mov %1, %2
441 %endif
442 push %1
443;-----------------------------------
444%else
445 push %2
446%endif
447%endmacro
448
449
450%endif ; EMULATE_INC
Note: See TracBrowser for help on using the repository browser.