fixed ljmp and iret to TSS
[qemu] / hw / vga_template.h
1 /*
2  * QEMU VGA Emulator templates
3  * 
4  * Copyright (c) 2003 Fabrice Bellard
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24
25 #if DEPTH == 8
26 #define BPP 1
27 #define PIXEL_TYPE uint8_t 
28 #elif DEPTH == 15 || DEPTH == 16
29 #define BPP 2
30 #define PIXEL_TYPE uint16_t 
31 #elif DEPTH == 32
32 #define BPP 4
33 #define PIXEL_TYPE uint32_t 
34 #else
35 #error unsupport depth
36 #endif
37
38 #if DEPTH != 15
39
40 static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d, 
41                                                      uint32_t font_data,
42                                                      uint32_t xorcol, 
43                                                      uint32_t bgcol)
44 {
45 #if BPP == 1
46         ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
47         ((uint32_t *)d)[3] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
48 #elif BPP == 2
49         ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
50         ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
51         ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
52         ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
53 #else
54         ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
55         ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
56         ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
57         ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
58         ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
59         ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
60         ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
61         ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
62 #endif
63 }
64
65 static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
66                                           const uint8_t *font_ptr, int h,
67                                           uint32_t fgcol, uint32_t bgcol)
68 {
69     uint32_t font_data, xorcol;
70     
71     xorcol = bgcol ^ fgcol;
72     do {
73         font_data = font_ptr[0];
74         glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol);
75         font_ptr += 4;
76         d += linesize;
77     } while (--h);
78 }
79
80 static void glue(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize,
81                                           const uint8_t *font_ptr, int h,
82                                           uint32_t fgcol, uint32_t bgcol)
83 {
84     uint32_t font_data, xorcol;
85     
86     xorcol = bgcol ^ fgcol;
87     do {
88         font_data = font_ptr[0];
89         glue(vga_draw_glyph_line_, DEPTH)(d, 
90                                           expand4to8[font_data >> 4], 
91                                           xorcol, bgcol);
92         glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP, 
93                                           expand4to8[font_data & 0x0f], 
94                                           xorcol, bgcol);
95         font_ptr += 4;
96         d += linesize;
97     } while (--h);
98 }
99
100 static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize,
101                                           const uint8_t *font_ptr, int h, 
102                                           uint32_t fgcol, uint32_t bgcol, int dup9)
103 {
104     uint32_t font_data, xorcol, v;
105     
106     xorcol = bgcol ^ fgcol;
107     do {
108         font_data = font_ptr[0];
109         /* XXX: unaligned accesses are done */
110 #if BPP == 1
111         ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
112         v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
113         ((uint32_t *)d)[3] = v;
114         if (dup9)
115             ((uint8_t *)d)[8] = v >> (24 * (1 - BIG));
116         else
117             ((uint8_t *)d)[8] = bgcol;
118         
119 #elif BPP == 2
120         ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
121         ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
122         ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
123         v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
124         ((uint32_t *)d)[3] = v;
125         if (dup9)
126             ((uint16_t *)d)[8] = v >> (16 * (1 - BIG));
127         else
128             ((uint16_t *)d)[8] = bgcol;
129 #else
130         ((uint32_t *)d)[0] = ((-(font_data >> 7)) & xorcol) ^ bgcol;
131         ((uint32_t *)d)[1] = ((-(font_data >> 6) & 1) & xorcol) ^ bgcol;
132         ((uint32_t *)d)[2] = ((-(font_data >> 5) & 1) & xorcol) ^ bgcol;
133         ((uint32_t *)d)[3] = ((-(font_data >> 4) & 1) & xorcol) ^ bgcol;
134         ((uint32_t *)d)[4] = ((-(font_data >> 3) & 1) & xorcol) ^ bgcol;
135         ((uint32_t *)d)[5] = ((-(font_data >> 2) & 1) & xorcol) ^ bgcol;
136         ((uint32_t *)d)[6] = ((-(font_data >> 1) & 1) & xorcol) ^ bgcol;
137         v = ((-(font_data >> 0) & 1) & xorcol) ^ bgcol;
138         ((uint32_t *)d)[7] = v;
139         if (dup9)
140             ((uint32_t *)d)[8] = v;
141         else
142             ((uint32_t *)d)[8] = bgcol;
143 #endif
144         font_ptr += 4;
145         d += linesize;
146     } while (--h);
147 }
148
149 /* 
150  * 4 color mode
151  */
152 static void glue(vga_draw_line2_, DEPTH)(VGAState *s1, uint8_t *d, 
153                                          const uint8_t *s, int width)
154 {
155     uint32_t plane_mask, *palette, data, v;
156     int x;
157
158     palette = s1->last_palette;
159     plane_mask = mask16[s1->ar[0x12] & 0xf];
160     width >>= 3;
161     for(x = 0; x < width; x++) {
162         data = ((uint32_t *)s)[0];
163         data &= plane_mask;
164         v = expand2[GET_PLANE(data, 0)];
165         v |= expand2[GET_PLANE(data, 2)] << 2;
166         ((PIXEL_TYPE *)d)[0] = palette[v >> 12];
167         ((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf];
168         ((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf];
169         ((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf];
170
171         v = expand2[GET_PLANE(data, 1)];
172         v |= expand2[GET_PLANE(data, 3)] << 2;
173         ((PIXEL_TYPE *)d)[4] = palette[v >> 12];
174         ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
175         ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
176         ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
177         d += BPP * 8;
178         s += 4;
179     }
180 }
181
182 #if BPP == 1
183 #define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v)
184 #elif BPP == 2
185 #define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v)
186 #else
187 #define PUT_PIXEL2(d, n, v) \
188 ((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
189 #endif
190
191 /* 
192  * 4 color mode, dup2 horizontal
193  */
194 static void glue(vga_draw_line2d2_, DEPTH)(VGAState *s1, uint8_t *d, 
195                                            const uint8_t *s, int width)
196 {
197     uint32_t plane_mask, *palette, data, v;
198     int x;
199
200     palette = s1->last_palette;
201     plane_mask = mask16[s1->ar[0x12] & 0xf];
202     width >>= 3;
203     for(x = 0; x < width; x++) {
204         data = ((uint32_t *)s)[0];
205         data &= plane_mask;
206         v = expand2[GET_PLANE(data, 0)];
207         v |= expand2[GET_PLANE(data, 2)] << 2;
208         PUT_PIXEL2(d, 0, palette[v >> 12]);
209         PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
210         PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
211         PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
212
213         v = expand2[GET_PLANE(data, 1)];
214         v |= expand2[GET_PLANE(data, 3)] << 2;
215         PUT_PIXEL2(d, 4, palette[v >> 12]);
216         PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
217         PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
218         PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
219         d += BPP * 16;
220         s += 4;
221     }
222 }
223
224 /* 
225  * 16 color mode
226  */
227 static void glue(vga_draw_line4_, DEPTH)(VGAState *s1, uint8_t *d, 
228                                          const uint8_t *s, int width)
229 {
230     uint32_t plane_mask, data, v, *palette;
231     int x;
232
233     palette = s1->last_palette;
234     plane_mask = mask16[s1->ar[0x12] & 0xf];
235     width >>= 3;
236     for(x = 0; x < width; x++) {
237         data = ((uint32_t *)s)[0];
238         data &= plane_mask;
239         v = expand4[GET_PLANE(data, 0)];
240         v |= expand4[GET_PLANE(data, 1)] << 1;
241         v |= expand4[GET_PLANE(data, 2)] << 2;
242         v |= expand4[GET_PLANE(data, 3)] << 3;
243         ((PIXEL_TYPE *)d)[0] = palette[v >> 28];
244         ((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf];
245         ((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf];
246         ((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf];
247         ((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf];
248         ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
249         ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
250         ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
251         d += BPP * 8;
252         s += 4;
253     }
254 }
255
256 /* 
257  * 16 color mode, dup2 horizontal
258  */
259 static void glue(vga_draw_line4d2_, DEPTH)(VGAState *s1, uint8_t *d, 
260                                            const uint8_t *s, int width)
261 {
262     uint32_t plane_mask, data, v, *palette;
263     int x;
264
265     palette = s1->last_palette;
266     plane_mask = mask16[s1->ar[0x12] & 0xf];
267     width >>= 3;
268     for(x = 0; x < width; x++) {
269         data = ((uint32_t *)s)[0];
270         data &= plane_mask;
271         v = expand4[GET_PLANE(data, 0)];
272         v |= expand4[GET_PLANE(data, 1)] << 1;
273         v |= expand4[GET_PLANE(data, 2)] << 2;
274         v |= expand4[GET_PLANE(data, 3)] << 3;
275         PUT_PIXEL2(d, 0, palette[v >> 28]);
276         PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
277         PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
278         PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
279         PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
280         PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
281         PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
282         PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
283         d += BPP * 16;
284         s += 4;
285     }
286 }
287
288 /* 
289  * 256 color mode, double pixels
290  *
291  * XXX: add plane_mask support (never used in standard VGA modes)
292  */
293 static void glue(vga_draw_line8d2_, DEPTH)(VGAState *s1, uint8_t *d, 
294                                            const uint8_t *s, int width)
295 {
296     uint32_t *palette;
297     int x;
298
299     palette = s1->last_palette;
300     width >>= 3;
301     for(x = 0; x < width; x++) {
302         PUT_PIXEL2(d, 0, palette[s[0]]);
303         PUT_PIXEL2(d, 1, palette[s[1]]);
304         PUT_PIXEL2(d, 2, palette[s[2]]);
305         PUT_PIXEL2(d, 3, palette[s[3]]);
306         d += BPP * 8;
307         s += 4;
308     }
309 }
310
311 /* 
312  * standard 256 color mode
313  *
314  * XXX: add plane_mask support (never used in standard VGA modes)
315  */
316 static void glue(vga_draw_line8_, DEPTH)(VGAState *s1, uint8_t *d, 
317                                          const uint8_t *s, int width)
318 {
319     uint32_t *palette;
320     int x;
321
322     palette = s1->last_palette;
323     width >>= 3;
324     for(x = 0; x < width; x++) {
325         ((PIXEL_TYPE *)d)[0] = palette[s[0]];
326         ((PIXEL_TYPE *)d)[1] = palette[s[1]];
327         ((PIXEL_TYPE *)d)[2] = palette[s[2]];
328         ((PIXEL_TYPE *)d)[3] = palette[s[3]];
329         ((PIXEL_TYPE *)d)[4] = palette[s[4]];
330         ((PIXEL_TYPE *)d)[5] = palette[s[5]];
331         ((PIXEL_TYPE *)d)[6] = palette[s[6]];
332         ((PIXEL_TYPE *)d)[7] = palette[s[7]];
333         d += BPP * 8;
334         s += 8;
335     }
336 }
337
338 #endif /* DEPTH != 15 */
339
340
341 /* XXX: optimize */
342
343 /* 
344  * 15 bit color
345  */
346 static void glue(vga_draw_line15_, DEPTH)(VGAState *s1, uint8_t *d, 
347                                           const uint8_t *s, int width)
348 {
349 #if DEPTH == 15 && !defined(WORDS_BIGENDIAN)
350     memcpy(d, s, width * 2);
351 #else
352     int w;
353     uint32_t v, r, g, b;
354
355     w = width;
356     do {
357         v = lduw_raw((void *)s);
358         r = (v >> 7) & 0xf8;
359         g = (v >> 2) & 0xf8;
360         b = (v << 3) & 0xf8;
361         ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
362         s += 2;
363         d += BPP;
364     } while (--w != 0);
365 #endif    
366 }
367
368 /* 
369  * 16 bit color
370  */
371 static void glue(vga_draw_line16_, DEPTH)(VGAState *s1, uint8_t *d, 
372                                           const uint8_t *s, int width)
373 {
374 #if DEPTH == 16 && !defined(WORDS_BIGENDIAN)
375     memcpy(d, s, width * 2);
376 #else
377     int w;
378     uint32_t v, r, g, b;
379
380     w = width;
381     do {
382         v = lduw_raw((void *)s);
383         r = (v >> 8) & 0xf8;
384         g = (v >> 3) & 0xfc;
385         b = (v << 3) & 0xf8;
386         ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
387         s += 2;
388         d += BPP;
389     } while (--w != 0);
390 #endif    
391 }
392
393 /* 
394  * 24 bit color
395  */
396 static void glue(vga_draw_line24_, DEPTH)(VGAState *s1, uint8_t *d, 
397                                           const uint8_t *s, int width)
398 {
399     int w;
400     uint32_t r, g, b;
401
402     w = width;
403     do {
404         b = s[0];
405         g = s[1];
406         r = s[2];
407         ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
408         s += 3;
409         d += BPP;
410     } while (--w != 0);
411 }
412
413 /* 
414  * 32 bit color
415  */
416 static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d, 
417                                           const uint8_t *s, int width)
418 {
419 #if DEPTH == 32 && !defined(WORDS_BIGENDIAN)
420     memcpy(d, s, width * 4);
421 #else
422     int w;
423     uint32_t r, g, b;
424
425     w = width;
426     do {
427         b = s[0];
428         g = s[1];
429         r = s[2];
430         ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
431         s += 4;
432         d += BPP;
433     } while (--w != 0);
434 #endif
435 }
436
437 #undef PUT_PIXEL2
438 #undef DEPTH
439 #undef BPP
440 #undef PIXEL_TYPE