Home | History | Annotate | Line # | Download | only in hpc
bicons.c revision 1.2.8.1
      1 /*	$NetBSD: bicons.c,v 1.2.8.1 2001/10/01 12:45:21 fvdl Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999-2001
      5  *         Shin Takemura and PocketBSD Project. All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the PocketBSD project
     18  *	and its contributors.
     19  * 4. Neither the name of the project nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  *
     35  */
     36 
     37 #define HALF_FONT
     38 
     39 #include <sys/param.h>
     40 #include <sys/device.h>
     41 #include <sys/systm.h>
     42 #include <sys/conf.h>
     43 #include <dev/cons.h>
     44 
     45 #include <machine/bootinfo.h>
     46 #include <machine/bus.h>
     47 #include <machine/platid.h>
     48 #include <machine/stdarg.h>
     49 
     50 #include <dev/hpc/biconsvar.h>
     51 #include <dev/hpc/bicons.h>
     52 extern u_int8_t font_clR8x8_data[];
     53 #define FONT_HEIGHT	8
     54 #define FONT_WIDTH	1
     55 
     56 static void put_oxel_D2_M2L_3(u_int8_t *, u_int8_t, u_int8_t);
     57 static void put_oxel_D2_M2L_3x2(u_int8_t *, u_int8_t, u_int8_t);
     58 static void put_oxel_D2_M2L_0(u_int8_t *, u_int8_t, u_int8_t);
     59 static void put_oxel_D2_M2L_0x2(u_int8_t *, u_int8_t, u_int8_t);
     60 static void put_oxel_D4_M2L_F(u_int8_t *, u_int8_t, u_int8_t);
     61 static void put_oxel_D4_M2L_Fx2(u_int8_t *, u_int8_t, u_int8_t);
     62 static void put_oxel_D4_M2L_0(u_int8_t *, u_int8_t, u_int8_t);
     63 static void put_oxel_D4_M2L_0x2(u_int8_t *, u_int8_t, u_int8_t);
     64 static void put_oxel_D8_00(u_int8_t *, u_int8_t, u_int8_t);
     65 static void put_oxel_D8_FF(u_int8_t *, u_int8_t, u_int8_t);
     66 static void put_oxel_D16_0000(u_int8_t *, u_int8_t, u_int8_t);
     67 static void put_oxel_D16_FFFF(u_int8_t *, u_int8_t, u_int8_t);
     68 
     69 struct {
     70 	int type;
     71 	char *name;
     72 	void (*func)(u_int8_t *, u_int8_t, u_int8_t);
     73 	u_int8_t clear_byte;
     74 	int16_t oxel_bytes;
     75 } fb_table[] = {
     76 	{ BIFB_D2_M2L_3,	BIFBN_D2_M2L_3,
     77 	  put_oxel_D2_M2L_3,	0,	2	},
     78 	{ BIFB_D2_M2L_3x2,	BIFBN_D2_M2L_3x2,
     79 	  put_oxel_D2_M2L_3x2,	0,	1	},
     80 	{ BIFB_D2_M2L_0,	BIFBN_D2_M2L_0,
     81 	  put_oxel_D2_M2L_0,	0xff,	2	},
     82 	{ BIFB_D2_M2L_0x2,	BIFBN_D2_M2L_0x2,
     83 	  put_oxel_D2_M2L_0x2,	0xff,	1	},
     84 	{ BIFB_D4_M2L_F,	BIFBN_D4_M2L_F,
     85 	  put_oxel_D4_M2L_F,	0x00,	4	},
     86 	{ BIFB_D4_M2L_Fx2,	BIFBN_D4_M2L_Fx2,
     87 	  put_oxel_D4_M2L_Fx2,	0x00,	2	},
     88 	{ BIFB_D4_M2L_0,	BIFBN_D4_M2L_0,
     89 	  put_oxel_D4_M2L_0,	0xff,	4	},
     90 	{ BIFB_D4_M2L_0x2,	BIFBN_D4_M2L_0x2,
     91 	  put_oxel_D4_M2L_0x2,	0xff,	2	},
     92 	{ BIFB_D8_00,		BIFBN_D8_00,
     93 	  put_oxel_D8_00,	0xff,	8	},
     94 	{ BIFB_D8_FF,		BIFBN_D8_FF,
     95 	  put_oxel_D8_FF,	0x00,	8	},
     96 	{ BIFB_D16_0000,	BIFBN_D16_0000,
     97 	  put_oxel_D16_0000,	0xff,	16	},
     98 	{ BIFB_D16_FFFF,	BIFBN_D16_FFFF,
     99 	  put_oxel_D16_FFFF,	0x00,	16	},
    100 };
    101 #define FB_TABLE_SIZE (sizeof(fb_table)/sizeof(*fb_table))
    102 
    103 static u_int8_t	*fb_vram;
    104 static int16_t	fb_line_bytes;
    105 static u_int8_t	fb_clear_byte;
    106 int16_t	bicons_ypixel;
    107 int16_t	bicons_xpixel;
    108 #ifdef HALF_FONT
    109 static int16_t	fb_oxel_bytes	= 1;
    110 int16_t	bicons_width	= 80;
    111 void	(*fb_put_oxel)(u_int8_t *, u_int8_t, u_int8_t) = put_oxel_D2_M2L_3x2;
    112 #else /* HALF_FONT */
    113 static int16_t	fb_oxel_bytes	= 2;
    114 int16_t	bicons_width	= 40;
    115 void	(*fb_put_oxel)(u_int8_t *, u_int8_t, u_int8_t) = put_oxel_D2_M2L_3;
    116 #endif /* HALF_FONT */
    117 int16_t bicons_height;
    118 static int16_t curs_x;
    119 static int16_t curs_y;
    120 
    121 cdev_decl(biconsdev);
    122 
    123 static int bicons_priority;
    124 void biconscninit(struct consdev *);
    125 void biconscnprobe(struct consdev *);
    126 void biconscnputc(dev_t, int);
    127 int biconscngetc(dev_t);	/* harmless place holder */
    128 
    129 static void draw_char(int, int, int);
    130 static void clear(int, int);
    131 static void scroll(int, int, int);
    132 static void bicons_puts(char *);
    133 static void bicons_printf(const char *, ...) __attribute__((__unused__));
    134 
    135 void
    136 bicons_init(struct consdev *cndev)
    137 {
    138 	biconscninit(cndev);
    139 	biconscnprobe(cndev);
    140 }
    141 
    142 void
    143 biconscninit(struct consdev *cndev)
    144 {
    145 	int fb_index = -1;
    146 
    147 	for (fb_index = 0; fb_index < FB_TABLE_SIZE; fb_index++)
    148 		if (fb_table[fb_index].type == bootinfo->fb_type)
    149 			break;
    150 
    151 	if (FB_TABLE_SIZE <= fb_index || fb_index == -1) {
    152 		/*
    153 		 *  Unknown frame buffer type, but what can I do ?
    154 		 */
    155 		fb_index = 0;
    156 	}
    157 
    158 	fb_vram = (u_int8_t *)bootinfo->fb_addr;
    159 	fb_line_bytes = bootinfo->fb_line_bytes;
    160 	bicons_xpixel = bootinfo->fb_width;
    161 	bicons_ypixel = bootinfo->fb_height;
    162 
    163 	fb_put_oxel = fb_table[fb_index].func;
    164 	fb_clear_byte = fb_table[fb_index].clear_byte;
    165 	fb_oxel_bytes = fb_table[fb_index].oxel_bytes;
    166 
    167 	bicons_width = bicons_xpixel / (8 * FONT_WIDTH);
    168 	bicons_height = bicons_ypixel / FONT_HEIGHT;
    169 	clear(0, bicons_ypixel);
    170 
    171 	curs_x = 0;
    172 	curs_y = 0;
    173 
    174 	bicons_puts("builtin console type = ");
    175 	bicons_puts(fb_table[fb_index].name);
    176 	bicons_puts("\n");
    177 }
    178 
    179 void
    180 biconscnprobe(struct consdev *cndev)
    181 {
    182 	int maj;
    183 
    184 	/* locate the major number */
    185 	for (maj = 0; maj < nchrdev; maj++)
    186 		if (cdevsw[maj].d_open == biconsdevopen)
    187 			break;
    188 
    189 	cndev->cn_dev = makedev(maj, 0);
    190 	cndev->cn_pri = bicons_priority;
    191 }
    192 
    193 void
    194 bicons_set_priority(int priority)
    195 {
    196 	bicons_priority = priority;
    197 }
    198 
    199 int
    200 biconscngetc(dev_t dev)
    201 {
    202 	printf("no input method. reboot me.\n");
    203 	while (1)
    204 		;
    205 	/* NOTREACHED */
    206 }
    207 
    208 void
    209 biconscnputc(dev_t dev, int c)
    210 {
    211 	int line_feed = 0;
    212 
    213 	switch (c) {
    214 	case 0x08: /* back space */
    215 		if (--curs_x < 0) {
    216 			curs_x = 0;
    217 		}
    218 		/* erase character ar cursor position */
    219 		draw_char(curs_x, curs_y, ' ');
    220 		break;
    221 	case '\r':
    222 		curs_x = 0;
    223 		break;
    224 	case '\n':
    225 		curs_x = 0;
    226 		line_feed = 1;
    227 		break;
    228 	default:
    229 		draw_char(curs_x, curs_y, c);
    230 		if (bicons_width <= ++curs_x) {
    231 			curs_x = 0;
    232 			line_feed = 1;
    233 		}
    234 	}
    235 
    236 	if (line_feed) {
    237 		if (bicons_height <= ++curs_y) {
    238 			/* scroll up */
    239 			scroll(FONT_HEIGHT, (bicons_height - 1) * FONT_HEIGHT,
    240 			       - FONT_HEIGHT);
    241 			clear((bicons_height - 1) * FONT_HEIGHT, FONT_HEIGHT);
    242 			curs_y--;
    243 		}
    244 	}
    245 }
    246 
    247 void
    248 bicons_puts(char *s)
    249 {
    250 	while (*s)
    251 		biconscnputc(NULL, *s++);
    252 }
    253 
    254 
    255 void
    256 bicons_putn(const char *s, int n)
    257 {
    258 	while (0 < n--)
    259 		biconscnputc(NULL, *s++);
    260 }
    261 
    262 void
    263 #ifdef __STDC__
    264 bicons_printf(const char *fmt, ...)
    265 #else
    266 bicons_printf(fmt, va_alist)
    267 	char *fmt;
    268 	va_dcl
    269 #endif
    270 {
    271 	va_list ap;
    272 	char buf[0x100];
    273 
    274 	va_start(ap, fmt);
    275 	vsnprintf(buf, sizeof(buf), fmt, ap);
    276 	va_end(ap);
    277 	bicons_puts(buf);
    278 }
    279 
    280 static void
    281 draw_char(int x, int y, int c)
    282 {
    283 	int i;
    284 	u_int8_t *p;
    285 
    286 	if (!fb_vram)
    287 		return;
    288 
    289 	p = &fb_vram[(y * FONT_HEIGHT * fb_line_bytes) +
    290 		    x * FONT_WIDTH * fb_oxel_bytes];
    291 	for (i = 0; i < FONT_HEIGHT; i++) {
    292 		(*fb_put_oxel)(p, font_clR8x8_data
    293 			       [FONT_WIDTH * (FONT_HEIGHT * c + i)], 0xff);
    294 		p += (fb_line_bytes);
    295 	}
    296 }
    297 
    298 static void
    299 clear(int y, int height)
    300 {
    301 	u_int8_t *p;
    302 
    303 	if (!fb_vram)
    304 		return;
    305 
    306 	p = &fb_vram[y * fb_line_bytes];
    307 
    308 	while (0 < height--) {
    309 		memset(p, fb_clear_byte,
    310 		       bicons_width * fb_oxel_bytes * FONT_WIDTH);
    311 		p += fb_line_bytes;
    312 	}
    313 }
    314 
    315 static void
    316 scroll(int y, int height, int d)
    317 {
    318 	u_int8_t *from, *to;
    319 
    320 	if (!fb_vram)
    321 		return;
    322 
    323 	if (d < 0) {
    324 		from = &fb_vram[y * fb_line_bytes];
    325 		to = from + d * fb_line_bytes;
    326 		while (0 < height--) {
    327 			memcpy(to, from, bicons_width * fb_oxel_bytes);
    328 			from += fb_line_bytes;
    329 			to += fb_line_bytes;
    330 		}
    331 	} else {
    332 		from = &fb_vram[(y + height - 1) * fb_line_bytes];
    333 		to = from + d * fb_line_bytes;
    334 		while (0 < height--) {
    335 			memcpy(to, from, bicons_xpixel * fb_oxel_bytes / 8);
    336 			from -= fb_line_bytes;
    337 			to -= fb_line_bytes;
    338 		}
    339 	}
    340 }
    341 
    342 /*=============================================================================
    343  *
    344  *	D2_M2L_3
    345  *
    346  */
    347 static void
    348 put_oxel_D2_M2L_3(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    349 {
    350 #if 1
    351 	u_int16_t *addr = (u_int16_t *)xaddr;
    352 	static u_int16_t map0[] = {
    353 		0x0000, 0x0300, 0x0c00, 0x0f00, 0x3000, 0x3300, 0x3c00, 0x3f00,
    354 		0xc000, 0xc300, 0xcc00, 0xcf00, 0xf000, 0xf300, 0xfc00, 0xff00,
    355 	};
    356 	static u_int16_t map1[] = {
    357 		0x0000, 0x0003, 0x000c, 0x000f, 0x0030, 0x0033, 0x003c, 0x003f,
    358 		0x00c0, 0x00c3, 0x00cc, 0x00cf, 0x00f0, 0x00f3, 0x00fc, 0x00ff,
    359 	};
    360 	*addr = (map1[data >> 4] | map0[data & 0x0f]);
    361 #else
    362 	static u_int8_t map[] = {
    363 		0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f,
    364 		0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff,
    365 	};
    366 	u_int8_t *addr = xaddr;
    367 
    368 	*addr++ = (map[(data >> 4) & 0x0f] & map[(mask >> 4) & 0x0f]) |
    369 		(*addr & ~map[(mask >> 4) & 0x0f]);
    370 	*addr   = (map[(data >> 0) & 0x0f] & map[(mask >> 0) & 0x0f]) |
    371 		(*addr & ~map[(mask >> 0) & 0x0f]);
    372 #endif
    373 }
    374 
    375 /*=============================================================================
    376  *
    377  *	D2_M2L_3x2
    378  *
    379  */
    380 static void
    381 put_oxel_D2_M2L_3x2(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    382 {
    383 	register u_int8_t odd = (data & 0xaa);
    384 	register u_int8_t even = (data & 0x55);
    385 
    386 	*xaddr = (odd | (even << 1)) | ((odd >> 1) & even);
    387 }
    388 
    389 /*=============================================================================
    390  *
    391  *	D2_M2L_0
    392  *
    393  */
    394 static void
    395 put_oxel_D2_M2L_0(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    396 {
    397 #if 1
    398 	u_int16_t *addr = (u_int16_t *)xaddr;
    399 	static u_int16_t map0[] = {
    400 		0xff00, 0xfc00, 0xf300, 0xf000, 0xcf00, 0xcc00, 0xc300, 0xc000,
    401 		0x3f00, 0x3c00, 0x3300, 0x3000, 0x0f00, 0x0c00, 0x0300, 0x0000,
    402 	};
    403 	static u_int16_t map1[] = {
    404 		0x00ff, 0x00fc, 0x00f3, 0x00f0, 0x00cf, 0x00cc, 0x00c3, 0x00c0,
    405 		0x003f, 0x003c, 0x0033, 0x0030, 0x000f, 0x000c, 0x0003, 0x0000,
    406 	};
    407 	*addr = (map1[data >> 4] | map0[data & 0x0f]);
    408 #else
    409 	static u_int8_t map[] = {
    410 		0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f,
    411 		0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff,
    412 	};
    413 	u_int8_t *addr = xaddr;
    414 
    415 	*addr++ = (~(map[(data >> 4) & 0x0f] & map[(mask >> 4) & 0x0f])) |
    416 		(*addr & ~map[(mask >> 4) & 0x0f]);
    417 	*addr   = (~(map[(data >> 0) & 0x0f] & map[(mask >> 0) & 0x0f])) |
    418 		(*addr & ~map[(mask >> 0) & 0x0f]);
    419 #endif
    420 }
    421 
    422 /*=============================================================================
    423  *
    424  *	D2_M2L_0x2
    425  *
    426  */
    427 static void
    428 put_oxel_D2_M2L_0x2(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    429 {
    430 	register u_int8_t odd = (data & 0xaa);
    431 	register u_int8_t even = (data & 0x55);
    432 
    433 	*xaddr = ~((odd | (even << 1)) | ((odd >> 1) & even));
    434 }
    435 
    436 /*=============================================================================
    437  *
    438  *	D4_M2L_F
    439  *
    440  */
    441 static void
    442 put_oxel_D4_M2L_F(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    443 {
    444 	u_int32_t *addr = (u_int32_t *)xaddr;
    445 	static u_int32_t map[] = {
    446 		0x0000, 0x0f00, 0xf000, 0xff00, 0x000f, 0x0f0f, 0xf00f, 0xff0f,
    447 		0x00f0, 0x0ff0, 0xf0f0, 0xfff0, 0x00ff, 0x0fff, 0xf0ff, 0xffff,
    448 	};
    449 	*addr = (map[data >> 4] | (map[data & 0x0f] << 16));
    450 }
    451 
    452 /*=============================================================================
    453  *
    454  *	D4_M2L_Fx2
    455  *
    456  */
    457 static void
    458 put_oxel_D4_M2L_Fx2(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    459 {
    460 	u_int16_t *addr = (u_int16_t *)xaddr;
    461 	static u_int16_t map[] = {
    462 		0x00, 0x08, 0x08, 0x0f, 0x80, 0x88, 0x88, 0x8f,
    463 		0x80, 0x88, 0x88, 0x8f, 0xf0, 0xf8, 0xf8, 0xff,
    464 	};
    465 
    466 	*addr = (map[data >> 4] | (map[data & 0x0f] << 8));
    467 }
    468 
    469 /*=============================================================================
    470  *
    471  *	D4_M2L_0
    472  *
    473  */
    474 static void
    475 put_oxel_D4_M2L_0(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    476 {
    477 	u_int32_t *addr = (u_int32_t *)xaddr;
    478 	static u_int32_t map[] = {
    479 		0xffff, 0xf0ff, 0x0fff, 0x00ff, 0xfff0, 0xf0f0, 0x0ff0, 0x00f0,
    480 		0xff0f, 0xf00f, 0x0f0f, 0x000f, 0xff00, 0xf000, 0x0f00, 0x0000,
    481 	};
    482 	*addr = (map[data >> 4] | (map[data & 0x0f] << 16));
    483 }
    484 
    485 /*=============================================================================
    486  *
    487  *	D4_M2L_0x2
    488  *
    489  */
    490 static void
    491 put_oxel_D4_M2L_0x2(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    492 {
    493 	u_int16_t *addr = (u_int16_t *)xaddr;
    494 	static u_int16_t map[] = {
    495 		0xff, 0xf8, 0xf8, 0xf0, 0x8f, 0x88, 0x88, 0x80,
    496 		0x8f, 0x88, 0x88, 0x80, 0x0f, 0x08, 0x08, 0x00,
    497 	};
    498 
    499 	*addr = (map[data >> 4] | (map[data & 0x0f] << 8));
    500 }
    501 
    502 /*=============================================================================
    503  *
    504  *	D8_00
    505  *
    506  */
    507 static void
    508 put_oxel_D8_00(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    509 {
    510 	int i;
    511 	u_int8_t *addr = xaddr;
    512 
    513 	for (i = 0; i < 8; i++) {
    514 		if (mask & 0x80) {
    515 			*addr = (data & 0x80) ? 0x00 : 0xFF;
    516 		}
    517 		addr++;
    518 		data <<= 1;
    519 		mask <<= 1;
    520 	}
    521 }
    522 
    523 /*=============================================================================
    524  *
    525  *	D8_FF
    526  *
    527  */
    528 static void
    529 put_oxel_D8_FF(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    530 {
    531 	int i;
    532 	u_int8_t *addr = xaddr;
    533 
    534 	for (i = 0; i < 8; i++) {
    535 		if (mask & 0x80) {
    536 			*addr = (data & 0x80) ? 0xFF : 0x00;
    537 		}
    538 		addr++;
    539 		data <<= 1;
    540 		mask <<= 1;
    541 	}
    542 }
    543 
    544 /*=============================================================================
    545  *
    546  *	D16_0000
    547  *
    548  */
    549 static void
    550 put_oxel_D16_0000(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    551 {
    552 	int i;
    553 	u_int16_t *addr = (u_int16_t *)xaddr;
    554 
    555 	for (i = 0; i < 8; i++) {
    556 		if (mask & 0x80) {
    557 			*addr = (data & 0x80) ? 0x0000 : 0xFFFF;
    558 		}
    559 		addr++;
    560 		data <<= 1;
    561 		mask <<= 1;
    562 	}
    563 }
    564 
    565 /*=============================================================================
    566  *
    567  *	D16_FFFF
    568  *
    569  */
    570 static void
    571 put_oxel_D16_FFFF(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    572 {
    573 	int i;
    574 	u_int16_t *addr = (u_int16_t *)xaddr;
    575 
    576 	for (i = 0; i < 8; i++) {
    577 		if (mask & 0x80) {
    578 			*addr = (data & 0x80) ? 0xFFFF : 0x0000;
    579 		}
    580 		addr++;
    581 		data <<= 1;
    582 		mask <<= 1;
    583 	}
    584 }
    585