xref: /plan9/sys/src/cmd/gs/src/gdevegaa.asm (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1;    Copyright (C) 1989, 1992 Aladdin Enterprises.  All rights reserved.
2;
3; This software is provided AS-IS with no warranty, either express or
4; implied.
5;
6; This software is distributed under license and may not be copied,
7; modified or distributed except as expressly authorized under the terms
8; of the license contained in the file LICENSE in this distribution.
9;
10; For more information about licensing, please refer to
11; http://www.ghostscript.com/licensing/. For information on
12; commercial licensing, go to http://www.artifex.com/licensing/ or
13; contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14; San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
16; $Id: gdevegaa.asm,v 1.4 2002/02/21 22:24:51 giles Exp $
17; gdevegaasm.asm
18; Assembly code for Ghostscript PC frame buffer driver
19
20gdevegaasm_TEXT	SEGMENT	BYTE PUBLIC 'CODE'
21	ASSUME	CS:gdevegaasm_TEXT
22
23; Note: Turbo C uses si and di for register variables, so
24; we have to preserve them.
25
26; Normal entry and exit.  Arguments are relative to bp.
27enterp	macro
28	push	bp
29	mov	bp,sp
30	x = 6				; offset of arguments,
31					; large code model
32	endm
33leavep	macro
34	pop	bp
35	endm
36; Fast entry and exit, for procedures that don't use bx until
37; they've fetched all their arguments.  Arguments are relative to ss:bx.
38enterf	macro
39	mov	bx,sp
40	x = 4				; offset of arguments,
41					; large code model
42	endm
43leavef	macro
44	endm
45
46; Fast call to VESA set-page routine.
47; void vesa_call_set_page(void (*set_page_proc)(int), int page_no, int win_no)
48	PUBLIC	_vesa_call_set_page
49_vesa_call_set_page proc far
50	enterf
51	mov ax,4f05h
52	mov dx,ss:[bx+x+4]			; page_no
53	push ss:[bx+x+2]			; set_page_proc
54	push ss:[bx+x]
55	mov bx,ss:[bx+x+6]			; win_no
56	ret
57_vesa_call_set_page endp
58
59; Structure for operation parameters.
60; Note that this structure is shared with C code.
61; Not all parameters are used for every operation.
62; typedef struct rop_params_s {
63p_dest	equ	0	; fb_ptr dest;	/* pointer to frame buffer */
64p_draster equ	4	; int draster;	/* raster of frame buffer */
65p_src	equ	6	; const byte far *src; /* pointer to source data */
66p_sraster equ	10	; int sraster;	/* source raster */
67p_width	equ	12	; int width;	/* width in bytes */
68p_height equ	14	; int height;	/* height in scan lines */
69p_shift equ	16	; int shift;	/* amount to right shift source */
70p_invert equ	18	; int invert;	/* 0 or -1 to invert source */
71p_data	equ	20	; int data;	/* data for fill */
72; } rop_params;
73
74; void memsetcol(rop_params _ss *rop)
75; {	byte far *addr = rop->dest;
76;	int yc = rop->height;
77;	while ( yc-- )
78;	 { byte discard = *addr;
79;	   *addr = rop->data;
80;	   addr += rop->draster;
81;	 }
82; }
83	PUBLIC	_memsetcol
84_memsetcol proc	far
85	enterf
86	push	ds
87	mov	ax,ss
88	mov	ds,ax
89	mov	bx,[bx+x]			; rop
90	mov	cx,[bx].p_height
91	jcxz	msc0				; height == 0
92	mov	ax,[bx].p_data
93	mov	dx,[bx].p_draster
94	lds	bx,[bx].p_dest
95; Unroll the loop -- two copies.
96	inc	cx		;round up to nearest word.  cx>=2 now.
97	shr	cx,1		;make byte count into word count.
98	jnc	msc2		;if it had been odd, do a half word first.
99msc1:	mov	ah,[bx]
100	mov	[bx],al
101	add	bx,dx
102msc2:	mov	ah,[bx]
103	mov	[bx],al
104	add	bx,dx
105	loop	msc1
106	pop	ds
107msc0:	leavef
108	ret
109_memsetcol ENDP
110
111; void memsetrect(rop_params _ss *rop)
112; {	byte far *addr = rop->dest;
113;	int yc = rop->height;
114;	while ( yc-- )
115;	 { int cnt = rop->width;
116;	   while ( cnt-- ) *addr++ = rop->data;
117;	   addr += rop->drast - rop->width;
118;	 }
119; }
120	PUBLIC	_memsetrect
121_memsetrect proc	far
122	enterf
123	push	ds
124	mov	ax,ss
125	mov	ds,ax
126	mov	bx,[bx+x]			; rop
127	mov	cx,[bx].p_height
128	jcxz	msr0				; height == 0
129	push	si
130	push	di
131	mov	ax,[bx].p_data
132	les	di,[bx].p_dest
133	cld
134	mov	dx,[bx].p_draster
135	mov	si,cx				; si = height
136	mov	cx,[bx].p_width
137	sub	dx,cx
138	cmp	cx,10
139	ja	msrl				; large count, use fast loop
140; Small count, rep stosb is faster.
141msrs:	mov	cx,[bx].p_width
142	rep	stosb
143	add	di,dx
144	dec	si				; count reps
145	jnz	msrs
146	pop	di
147	pop	si
148msr0:	pop	ds
149	leavef
150	ret
151; Large count, loop by words rather than bytes.
152msrl:	mov	ah,al			;we may be storing words...
153msr1:	mov	cx,[bx].p_width
154	test	di,1			;test for an even address
155	je	msr2			;if even, we can store words.
156	stosb				;otherwise we need to even it out.
157	dec	cx			;(cx is at least one here)
158msr2:	shr	cx,1			;convert byte count into word count
159	rep	stosw			;store them puppies as fast as we can.
160	jnc	msr3			;if an odd number, store it, too.
161	stosb				;(no need to dec cx here).
162msr3:	add	di,dx
163	dec	si			; count reps
164	jnz	msr1
165	pop	di
166	pop	si
167	pop	ds
168	leavef
169	ret
170_memsetrect ENDP
171
172; void memrwcol(rop_params _ss *rop)
173; {	byte far *dp = rop->dest;
174;	const byte far *sp = rop->src;
175;	int yc = rop->height;
176;	int shift = rop->shift;
177;	while ( yc-- )
178;	 { byte discard = *dp;
179;	   *dp = ((*sp >> shift) + (*sp << (8 - shift))) ^ rop->invert;
180;	   dp += rop->draster, sp += rop->sraster;
181;	 }
182; }
183	PUBLIC	_memrwcol
184_memrwcol proc far
185	enterp
186	push	ds
187	mov	ax,ss
188	mov	ds,ax
189	mov	bx,[bp+x]			; rop
190	cmp	word ptr [bx].p_height,0
191	jz	short mrw0
192	push	si
193	push	di
194; Register usage:
195;   ds:si = sp, es:di = dp, bx = sraster, dx = draster, cl = shift,
196;   ch = invert, ah = low byte of yc.
197	push	[bx].p_height
198	mov	dx,[bx].p_draster
199	mov	ax,[bx].p_sraster
200	mov	cl,[bx].p_shift
201	mov	ch,[bx].p_invert
202	les	di,[bx].p_dest
203	lds	si,[bx].p_src
204	mov	bx,ax
205	mov	ah,[bp-8]			; low byte of yc
206	test	ah,ah
207	jz	mrw2
208mrw1:	mov	al,[si]
209	ror	al,cl
210	xor	al,ch
211	xchg	es:[di],al
212	add	si,bx
213	add	di,dx
214	dec	ah
215	jnz	mrw1
216mrw2:	dec	byte ptr [bp-7]			; high byte of yc
217	jge	mrw1
218	add	sp,2				; pop yc
219	pop	di
220	pop	si
221mrw0:	pop	ds
222	leavep
223	ret
224_memrwcol ENDP
225
226; void memrwcol2(rop_params _ss *rop)
227; {	byte far *dp = rop->dest;
228;	const byte far *sp = rop->src;
229;	int yc = rop->height;
230;	int shift = rop->shift;
231;	while ( yc-- )
232;	 { byte discard = *dp;
233;	   *dp = ((sp[1] >> shift) + (*sp << (8 - shift))) ^ rop->invert;
234;	   dp += rop->draster, sp += rop->sraster;
235;	 }
236; }
237	PUBLIC	_memrwcol2
238_memrwcol2 proc far
239	enterp
240	push	ds
241	mov	ax,ss
242	mov	ds,ax
243	mov	bx,[bp+x]			; rop
244	cmp	word ptr [bx].p_height,0
245	jz	short mrw20
246	push	si
247	push	di
248; Register usage:
249;   ds:si = sp, es:di = dp, bx = sraster, dx = draster, cl = shift,
250;   ch = invert.
251	push	[bx].p_height
252	mov	dx,[bx].p_draster
253	mov	ax,[bx].p_sraster
254	mov	cl,[bx].p_shift
255	mov	ch,[bx].p_invert
256	les	di,[bx].p_dest
257	lds	si,[bx].p_src
258	mov	bx,ax
259mrw21:	mov	ax,[si]				; bytes are in wrong order...
260	ror	ax,cl
261	xor	ah,ch				; ... so result is in ah
262	xchg	es:[di],ah
263	add	si,bx
264	add	di,dx
265	dec	word ptr [bp-8]			; yc
266	jg	mrw21
267	add	sp,2				; pop yc
268	pop	di
269	pop	si
270mrw20:	pop	ds
271	leavep
272	ret
273_memrwcol2 ENDP
274
275gdevegaasm_TEXT	ENDS
276	END
277