1/*
2	d_copy.S
3
4	x86 assembly-language screen copying code.
5
6	Copyright (C) 1996-1997  Id Software, Inc.
7
8	This program is free software; you can redistribute it and/or
9	modify it under the terms of the GNU General Public License
10	as published by the Free Software Foundation; either version 2
11	of the License, or (at your option) any later version.
12
13	This program is distributed in the hope that it will be useful,
14	but WITHOUT ANY WARRANTY; without even the implied warranty of
15	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17	See the GNU General Public License for more details.
18
19	You should have received a copy of the GNU General Public License
20	along with this program; if not, write to:
21
22		Free Software Foundation, Inc.
23		59 Temple Place - Suite 330
24		Boston, MA  02111-1307, USA
25
26	$Id$
27*/
28
29#ifdef HAVE_CONFIG_H
30# include <config.h>
31#endif
32#include "asm_i386.h"
33#include "quakeasm.h"
34#include "asm_draw.h"
35
36#ifdef PIC
37# undef USE_INTEL_ASM //XXX asm pic hack
38#endif
39
40#ifdef USE_INTEL_ASM
41	.data
42
43LCopyWidth:		.long	0
44LBlockSrcStep:	.long	0
45LBlockDestStep:	.long	0
46LSrcDelta:		.long	0
47LDestDelta:		.long	0
48
49#define bufptr	4+16
50
51// copies 16 rows per plane at a pop; idea is that 16*512 = 8k, and since
52// no Mode X mode is wider than 360, all the data should fit in the cache for
53// the passes for the next 3 planes
54
55	.text
56
57.globl C(VGA_UpdatePlanarScreen)
58C(VGA_UpdatePlanarScreen):
59	pushl	%ebp				// preserve caller's stack frame
60	pushl	%edi
61	pushl	%esi				// preserve register variables
62	pushl	%ebx
63
64	movl	C(VGA_bufferrowbytes),%eax
65	shll	$1,%eax
66	movl	%eax,LBlockSrcStep
67	movl	C(VGA_rowbytes),%eax
68	shll	$1,%eax
69	movl	%eax,LBlockDestStep
70
71	movl	$0x3C4,%edx
72	movb	$2,%al
73	outb	%al,%dx		// point the SC to the Map Mask
74	incl	%edx
75
76	movl	bufptr(%esp),%esi
77	movl	C(VGA_pagebase),%edi
78	movl	C(VGA_height),%ebp
79	shrl	$1,%ebp
80
81	movl	C(VGA_width),%ecx
82	movl	C(VGA_bufferrowbytes),%eax
83	subl	%ecx,%eax
84	movl	%eax,LSrcDelta
85	movl	C(VGA_rowbytes),%eax
86	shll	$2,%eax
87	subl	%ecx,%eax
88	movl	%eax,LDestDelta
89	shrl	$4,%ecx
90	movl	%ecx,LCopyWidth
91
92LRowLoop:
93	movb	$1,%al
94
95LPlaneLoop:
96	outb	%al,%dx
97	movb	$2,%ah
98
99	pushl	%esi
100	pushl	%edi
101LRowSetLoop:
102	movl	LCopyWidth,%ecx
103LColumnLoop:
104	movb	12(%esi),%bh
105	movb	8(%esi),%bl
106	shll	$16,%ebx
107	movb	4(%esi),%bh
108	movb	(%esi),%bl
109	movl	%ebx,(%edi)
110	addl	$16,%esi
111	addl	$4,%edi
112	decl	%ecx
113	jnz		LColumnLoop
114
115	addl	LDestDelta,%edi
116	addl	LSrcDelta,%esi
117	decb	%ah
118	jnz		LRowSetLoop
119
120	popl	%edi
121	popl	%esi
122	incl	%esi
123
124	shlb	$1,%al
125	cmpb	$16,%al
126	jnz		LPlaneLoop
127
128	subl	$4,%esi
129	addl	LBlockSrcStep,%esi
130	addl	LBlockDestStep,%edi
131	decl	%ebp
132	jnz		LRowLoop
133
134	popl	%ebx				// restore register variables
135	popl	%esi
136	popl	%edi
137	popl	%ebp				// restore the caller's stack frame
138
139	ret
140
141
142#define srcptr			4+16
143#define destptr			8+16
144#define width			12+16
145#define height			16+16
146#define srcrowbytes		20+16
147#define destrowbytes	24+16
148
149.globl C(VGA_UpdateLinearScreen)
150C(VGA_UpdateLinearScreen):
151	pushl	%ebp				// preserve caller's stack frame
152	pushl	%edi
153	pushl	%esi				// preserve register variables
154	pushl	%ebx
155
156	cld
157	movl	srcptr(%esp),%esi
158	movl	destptr(%esp),%edi
159	movl	width(%esp),%ebx
160	movl	srcrowbytes(%esp),%eax
161	subl	%ebx,%eax
162	movl	destrowbytes(%esp),%edx
163	subl	%ebx,%edx
164	shrl	$2,%ebx
165	movl	height(%esp),%ebp
166LLRowLoop:
167	movl	%ebx,%ecx
168	rep/movsl	(%esi),(%edi)
169	addl	%eax,%esi
170	addl	%edx,%edi
171	decl	%ebp
172	jnz		LLRowLoop
173
174	popl	%ebx				// restore register variables
175	popl	%esi
176	popl	%edi
177	popl	%ebp				// restore the caller's stack frame
178
179	ret
180#endif /* USE_INTEL_ASM */
181