Home | History | Annotate | Line # | Download | only in dev
ite_cc.c revision 1.5
      1 #include "ite.h"
      2 #if NITE > 0
      3 
      4 #include "param.h"
      5 #include "conf.h"
      6 #include "proc.h"
      7 #include "ioctl.h"
      8 #include "tty.h"
      9 #include "systm.h"
     10 
     11 #include "ite.h"
     12 #include "itevar.h"
     13 
     14 #include "machine/cpu.h"
     15 
     16 /* XXX */
     17 #include "grfioctl.h"
     18 #include "grfvar.h"
     19 #include "grf_ccreg.h"
     20 
     21 #include "../amiga/custom.h"
     22 
     23 extern caddr_t CHIPMEMADDR;
     24 
     25 extern unsigned char kernel_font_width, kernel_font_height;
     26 extern unsigned char kernel_font_lo, kernel_font_hi;
     27 extern unsigned char kernel_font[], kernel_cursor[];
     28 
     29 /*
     30  * This holds the instructions to retarget the plane 0 pointer
     31  * at each split point.
     32  */
     33 typedef struct {
     34   u_short wait[2];		/* wait instruction */
     35   u_short plane[4];		/* move + hi word, move + lo word */
     36 } COP_ROW;
     37 
     38 typedef struct {
     39   u_char *buf;			/* pointer to row within frame buffer */
     40   int polarity;			/* polarity for loading planes in copper list */
     41 } BUF_ROW;
     42 
     43 /*
     44  * This is what ip->priv points to;
     45  * it contains local variables for custom-chip ites.
     46  */
     47 struct ccite {
     48   struct ccfb *fb;
     49   BUF_ROW *buf_rows;		/* array of pointers into the frame buffer */
     50   COP_ROW *cop_rows[2];		/* extension to grf_cc's copper lists */
     51 };
     52 
     53 static struct ccite ccite[NITE];
     54 
     55 static BUF_ROW ccite_buf_rows[NITE][100]; /* XXX see below */
     56 
     57 extern struct itesw itesw[];
     58 
     59 /* 8-by-N routines */
     60 static void cc_8n_cursor(struct ite_softc *ip, int flag);
     61 static void cc_8n_putc(struct ite_softc *ip, int c, int dy, int dx, int mode);
     62 static void cc_8n_clear(struct ite_softc *ip, int sy, int sx, int h, int w);
     63 static void cc_8n_scroll(struct ite_softc *ip, int sy, int sx, int count, int dir);
     64 
     65 /* (M<=8)-by-N routines */
     66 static void cc_le32n_cursor(struct ite_softc *ip, int flag);
     67 static void cc_le8n_putc(struct ite_softc *ip, int c, int dy, int dx, int mode);
     68 static void cc_le8n_clear(struct ite_softc *ip, int sy, int sx, int h, int w);
     69 static void cc_le8n_scroll(struct ite_softc *ip, int sy, int sx, int count, int dir);
     70 
     71 /* Mykes: Insert your whiz-bang 8-by-8 routines here... ;-) */
     72 
     73 
     74 
     75 customc_init(ip)
     76 	register struct ite_softc *ip;
     77 {
     78   struct ccite *cci;
     79   struct ccfb *fb;
     80   struct itesw *sp = &itesw[ip->type];
     81 
     82   if (ip->grf == 0)
     83     ip->grf = &grf_softc[ip - ite_softc];
     84 
     85   cci = &ccite[ip - ite_softc];
     86   ip->priv = cci;
     87   fb = (struct ccfb *) ip->grf->g_data;
     88   cci->fb = fb;
     89 
     90   ip->font     = kernel_font;
     91   ip->font_lo  = kernel_font_lo;
     92   ip->font_hi  = kernel_font_hi;
     93   ip->ftwidth  = kernel_font_width;
     94   ip->ftheight = kernel_font_height;
     95 #if 0
     96   ip->cursor   = kernel_cursor;
     97 #endif
     98 
     99   ip->rows     = fb->disp_height / ip->ftheight;
    100   ip->cols     = fb->disp_width  / ip->ftwidth;
    101 
    102   /* Find the correct set of rendering routines for this font.  */
    103 #if 0
    104   /* The new unspecialized routines are faster than the old specialized ones
    105      for the same font!!! (and without even unrolling them...)
    106      Therefore I'm leaving them out for now.  */
    107   if (ip->ftwidth == 8)
    108     {
    109       sp->ite_cursor = cc_8n_cursor;
    110       sp->ite_putc = cc_8n_putc;
    111       sp->ite_clear = cc_8n_clear;
    112       sp->ite_scroll = cc_8n_scroll;
    113     }
    114   else
    115 #endif
    116   if (ip->ftwidth <= 8)
    117     {
    118       sp->ite_cursor = (void*)cc_le32n_cursor;
    119       sp->ite_putc = (void*)cc_le8n_putc;
    120       sp->ite_clear = (void*)cc_le8n_clear;
    121       sp->ite_scroll = (void*)cc_le8n_scroll;
    122     }
    123   else
    124     panic("kernel font size not supported");
    125 
    126   /* XXX It may be better if this was dynamic based on ip->rows,
    127      but is dynamic memory allocation available at this point?  */
    128   cci->buf_rows = ccite_buf_rows[ip - ite_softc];
    129 
    130   /* Now allocate memory for the special screen-split copper lists.
    131      We will need a COP_ROW structure for each text row,
    132      plus an extra row to terminate the list.  */
    133   /* testing for the result is really redundant because chipmem_steal
    134      panics if it runs out of memory.. */
    135   if (! (cci->cop_rows[0] = (COP_ROW *)
    136 	 chipmem_steal (sizeof(COP_ROW) * (ip->rows + 1)))
    137       || !(cci->cop_rows[1] = (COP_ROW *)
    138 	   chipmem_steal (sizeof(COP_ROW) * (ip->rows + 1))))
    139     return 0;
    140 
    141   /* Initialize the screen-split row arrays.  */
    142   {
    143     int i, ypos = 0;
    144     u_long rowbytes = fb->fb_width >> 3;
    145     u_long fbp, fbp2;
    146 
    147     fbp = ((u_long)fb->fb + (fb->fb_x >> 3) + fb->fb_y * rowbytes);
    148     for (i = 0; i < ip->rows; i++)
    149       {
    150 	cci->buf_rows[i].buf = (u_char*)fbp;
    151 	cci->buf_rows[i].polarity = (fb->disp_y + ypos) & 1;
    152 
    153 	COP_WAIT(cci->cop_rows[0][i].wait, (fb->disp_y + ypos + 1) >> 1);
    154 	fbp2 = (fbp - (u_long)CHIPMEMADDR
    155 		+ (cci->buf_rows[i].polarity ? rowbytes : 0));
    156 	COP_MOVE(cci->cop_rows[0][i].plane, bplpth(0), HIADDR(fbp2));
    157 	COP_MOVE(cci->cop_rows[0][i].plane+2, bplptl(0), LOADDR(fbp2));
    158 
    159 	COP_WAIT(cci->cop_rows[1][i].wait, (fb->disp_y + ypos) >> 1);
    160 	fbp2 = (fbp - (u_long)CHIPMEMADDR +
    161 		(cci->buf_rows[i].polarity ? 0 : rowbytes));
    162 	COP_MOVE(cci->cop_rows[1][i].plane, bplpth(0), HIADDR(fbp2));
    163 	COP_MOVE(cci->cop_rows[1][i].plane+2, bplptl(0), LOADDR(fbp2));
    164 
    165 	ypos += ip->ftheight;
    166 	fbp += ip->ftheight * rowbytes;
    167       }
    168 
    169     /* Turn the display off after the last row;
    170        otherwise we'll get funny text at the bottom of the screen
    171        because of reordered rows.  */
    172     COP_WAIT(cci->cop_rows[0][i].wait+0, (fb->disp_y + ypos + 1) >> 1);
    173     COP_MOVE(cci->cop_rows[0][i].wait+2, bplcon0, 0x8204);
    174     COP_END (cci->cop_rows[0][i].wait+4);
    175     COP_WAIT(cci->cop_rows[1][i].wait+0, (fb->disp_y + ypos) >> 1);
    176     COP_MOVE(cci->cop_rows[1][i].wait+2, bplcon0, 0x8204);
    177     COP_END (cci->cop_rows[1][i].wait+4);
    178   }
    179 
    180   /* Install the new copper list extensions.  */
    181   cc_install_cop_ext(ip->grf, cci->cop_rows[0], cci->cop_rows[1]);
    182 
    183 #if 0
    184   printf ("font@%x, cursor@%x\n", ip->font, ip->cursor);
    185   dump_copperlist (fb->cop1);
    186   dump_copperlist (fb->cop2);
    187 #endif
    188 }
    189 
    190 customc_deinit(ip)
    191 	struct ite_softc *ip;
    192 {
    193   ip->flags &= ~ITE_INITED;
    194 
    195   /* Take our grubby little fingers out of the grf's copper list.  */
    196   cc_uninstall_cop_ext(ip->grf);
    197 }
    198 
    199 /*
    200  * Swap two text rows in the display by modifying the copper list.
    201  */
    202 static __inline int
    203 swap_rows(struct ite_softc *ip, int row1, int row2)
    204 {
    205 	struct ccite *cci = (struct ccite *) ip->priv;
    206 	int rowbytes = cci->fb->fb_width >> 3;
    207 	u_char *tmp, *fbp2;
    208 
    209 	/* Swap the plane pointers */
    210 	tmp = cci->buf_rows[row1].buf;
    211 	cci->buf_rows[row1].buf = cci->buf_rows[row2].buf;
    212 	cci->buf_rows[row2].buf = tmp;
    213 
    214 	/* Update the copper lists */
    215 	fbp2 = (cci->buf_rows[row1].buf - (u_long)CHIPMEMADDR
    216 		+ (cci->buf_rows[row1].polarity ? rowbytes : 0));
    217 	cci->cop_rows[0][row1].plane[1] = HIADDR(fbp2);
    218 	cci->cop_rows[0][row1].plane[3] = LOADDR(fbp2);
    219 
    220 	fbp2 = (cci->buf_rows[row1].buf - (u_long)CHIPMEMADDR
    221 		+ (cci->buf_rows[row1].polarity ? 0 : rowbytes));
    222 	cci->cop_rows[1][row1].plane[1] = HIADDR(fbp2);
    223 	cci->cop_rows[1][row1].plane[3] = LOADDR(fbp2);
    224 
    225 	fbp2 = (cci->buf_rows[row2].buf - (u_long)CHIPMEMADDR
    226 		+ (cci->buf_rows[row2].polarity ? rowbytes : 0));
    227 	cci->cop_rows[0][row2].plane[1] = HIADDR(fbp2);
    228 	cci->cop_rows[0][row2].plane[3] = LOADDR(fbp2);
    229 
    230 	fbp2 = (cci->buf_rows[row2].buf - (u_long)CHIPMEMADDR
    231 		+ (cci->buf_rows[row2].polarity ? 0 : rowbytes));
    232 	cci->cop_rows[1][row2].plane[1] = HIADDR(fbp2);
    233 	cci->cop_rows[1][row2].plane[3] = LOADDR(fbp2);
    234 
    235 	/* If the drawn cursor was on either row, swap it too.  */
    236 	if (ip->cursory == row1)
    237 		ip->cursory = row2;
    238 	else if (ip->cursory == row2)
    239 		ip->cursory = row1;
    240 }
    241 
    242 
    243 
    244 /*** 8-by-N routines ***/
    245 
    246 static inline void
    247 cc_8n_windowmove (src, srcx, srcy, srcmod,
    248 		    dst, dstx, dsty, dstmod, h, w, op)
    249     unsigned char *src, *dst;
    250     unsigned short srcx, srcy, srcmod;
    251     unsigned short dstx, dsty, dstmod;
    252     unsigned short h, w;
    253     unsigned char op;
    254 {
    255   short i;	/* NOT unsigned! */
    256   unsigned char h1;
    257 
    258   src += srcmod * srcy + (srcx >> 3);
    259   dst += dstmod * dsty + (dstx >> 3);
    260 
    261 #if 0
    262 printf("ccwm: %x-%x-%x-%x-%c\n", src, dst, h, w,
    263 	op == RR_XOR ? '^' : op == RR_COPY ? '|' : op == RR_CLEAR ? 'C' : 'I');
    264 #endif
    265 
    266   /* currently, only drawing to byte slots is supported... */
    267   if ((srcx & 07) || (dstx & 07) || (w & 07))
    268     panic ("customc_windowmove: odd offset");
    269 
    270   w >>= 3;
    271 
    272   /* Ok, this is nastier than it could be to help the optimizer unroll
    273      loops for the most common case of 8x8 characters.
    274 
    275      Note that bzero() does some clever optimizations for large range
    276      clears, so it should pay the subroutine call. */
    277 
    278 /* perform OP on one bit row of data. */
    279 #define ONEOP(dst, src, op) \
    280 	do { if ((src) > (dst))					\
    281 	  for (i = 0; i < w; i++) (dst)[i] op (src)[i];		\
    282 	else							\
    283 	  for (i = w - 1; i >= 0; i--) (dst)[i] op (src)[i]; } while (0)
    284 
    285 /* perform a block of eight ONEOPs. This enables the optimizer to unroll
    286    the for-statements, as they have a loop counter known at compiletime */
    287 #define EIGHTOP(dst, src, op) \
    288 	for (h1 = 0; h1 < 8; h1++, src += srcmod, dst += dstmod) \
    289 	    ONEOP (dst, src, op);
    290 
    291   switch (op)
    292     {
    293     case RR_COPY:
    294       for (; h >= 8; h -= 8)
    295 	EIGHTOP (dst, src, =);
    296       for (; h > 0; h--, src += srcmod, dst += dstmod)
    297         ONEOP (dst, src, =);
    298       break;
    299 
    300     case RR_CLEAR:
    301       for (; h >= 8; h -= 8)
    302 	for (h1 = 0; h1 < 8; h1++, dst += dstmod)
    303 	  bzero (dst, w);
    304       for (; h > 0; h--, dst += dstmod)
    305         bzero (dst, w);
    306       break;
    307 
    308     case RR_XOR:
    309       for (; h >= 8; h -= 8)
    310 	EIGHTOP (dst, src, ^=);
    311       for (; h > 0; h--, src += srcmod, dst += dstmod)
    312         ONEOP (dst, src, ^=);
    313       break;
    314 
    315     case RR_COPYINVERTED:
    316       for (; h >= 8; h -= 8)
    317 	EIGHTOP (dst, src, =~);
    318       for (; h > 0; h--, src += srcmod, dst += dstmod)
    319         ONEOP (dst, src, =~);
    320       break;
    321     }
    322 }
    323 
    324 
    325 static void
    326 cc_8n_cursor(ip, flag)
    327 	register struct ite_softc *ip;
    328         register int flag;
    329 {
    330   struct ccite *cci = (struct ccite *) ip->priv;
    331   struct ccfb *fb = cci->fb;
    332   /* the cursor is always drawn in the last plane */
    333   unsigned char *ovplane, opclr, opset;
    334 
    335   ovplane = fb->fb + (fb->fb_z - 1) * (fb->fb_planesize);
    336 
    337   if (flag == START_CURSOROPT || flag == END_CURSOROPT)
    338     return;
    339 
    340   /* if drawing into an overlay plane, don't xor, clr and set */
    341   if (fb->fb_z > fb->disp_z)
    342     {
    343       opclr = RR_CLEAR; opset = RR_COPY;
    344     }
    345   else
    346     {
    347       opclr = opset = RR_XOR;
    348     }
    349 
    350   if (flag != DRAW_CURSOR)
    351     {
    352       /* erase it */
    353       cc_8n_windowmove (ip->cursor, 0, 0, 1,
    354 	  		  ovplane, fb->fb_x + ip->cursorx * ip->ftwidth,
    355     			  fb->fb_y + ip->cursory * ip->ftheight,
    356     			  fb->fb_width >> 3,
    357     			  ip->ftheight, ip->ftwidth, opclr);
    358     }
    359   if (flag == DRAW_CURSOR || flag == MOVE_CURSOR)
    360     {
    361       /* draw it */
    362       int newx = MIN(ip->curx, ip->cols - 1);
    363       cc_8n_windowmove (ip->cursor, 0, 0, 1,
    364 	    		  ovplane, fb->fb_x + newx * ip->ftwidth,
    365     			  fb->fb_y + ip->cury * ip->ftheight,
    366     			  fb->fb_width >> 3,
    367     			  ip->ftheight, ip->ftwidth, opset);
    368       ip->cursorx = newx;
    369       ip->cursory = ip->cury;
    370     }
    371 }
    372 
    373 static void
    374 cc_8n_putc(ip, c, dy, dx, mode)
    375 	register struct ite_softc *ip;
    376 	register int dy, dx;
    377 	int c, mode;
    378 {
    379   register int wrr = ((mode == ATTR_INV) ? RR_COPYINVERTED : RR_COPY);
    380   struct ccite *cci = (struct ccite *) ip->priv;
    381   struct ccfb *fb = cci->fb;
    382 
    383   if (c >= ip->font_lo && c <= ip->font_hi)
    384     {
    385       c -= ip->font_lo;
    386 
    387       cc_8n_windowmove (ip->font, 0, c * ip->ftheight, 1,
    388     			  cci->buf_rows[dy].buf,
    389 			  dx * ip->ftwidth, 0, fb->fb_width >> 3,
    390     			  ip->ftheight, ip->ftwidth, wrr);
    391     }
    392 }
    393 
    394 static void
    395 cc_8n_clear(ip, sy, sx, h, w)
    396 	struct ite_softc *ip;
    397 	register int sy, sx, h, w;
    398 {
    399   struct ccite *cci = (struct ccite *) ip->priv;
    400   struct ccfb *fb = cci->fb;
    401   int y;
    402 
    403   for (y = sy; y < sy + h; y++)
    404     cc_8n_windowmove (0, 0, 0, 0,
    405     			cci->buf_rows[y].buf, sx * ip->ftwidth, 0,
    406     		        fb->fb_width >> 3,
    407     		        ip->ftheight, w * ip->ftwidth, RR_CLEAR);
    408 }
    409 
    410 /* Note: sx is only relevant for SCROLL_LEFT or SCROLL_RIGHT.  */
    411 static void
    412 cc_8n_scroll(ip, sy, sx, count, dir)
    413         register struct ite_softc *ip;
    414         register int sy;
    415         int dir, sx, count;
    416 {
    417   struct ccite *cci = (struct ccite *) ip->priv;
    418 
    419   if (dir == SCROLL_UP)
    420     {
    421       int dy = sy - count;
    422       int bot = ip->inside_margins ? ip->bottom_margin : ip->rows - 1;
    423       int height = bot - sy + 1;
    424       int i;
    425 
    426       for (i = 0; i < height; i++)
    427 	swap_rows(ip, sy + i, dy + i);
    428     }
    429   else if (dir == SCROLL_DOWN)
    430     {
    431       int dy = sy + count;
    432       int bot = ip->inside_margins ? ip->bottom_margin : ip->rows - 1;
    433       int height = bot - dy + 1;
    434       int i;
    435 
    436       for (i = (height - 1); i >= 0; i--)
    437 	swap_rows(ip, sy + i, dy + i);
    438     }
    439   else if (dir == SCROLL_RIGHT)
    440     {
    441       struct ccfb *fb = cci->fb;
    442 
    443       cc_8n_cursor(ip, ERASE_CURSOR);
    444       cc_8n_windowmove(cci->buf_rows[sy].buf,
    445 			 sx * ip->ftwidth, 0, fb->fb_width >> 3,
    446 			 cci->buf_rows[sy].buf,
    447 			 (sx + count) * ip->ftwidth, 0, fb->fb_width >> 3,
    448 			 ip->ftheight, (ip->cols - (sx + count)) * ip->ftwidth, RR_COPY);
    449     }
    450   else
    451     {
    452       struct ccfb *fb = cci->fb;
    453 
    454       cc_8n_cursor(ip, ERASE_CURSOR);
    455       cc_8n_windowmove(cci->buf_rows[sy].buf,
    456 			 sx * ip->ftwidth, 0, fb->fb_width >> 3,
    457 			 cci->buf_rows[sy].buf,
    458 			 (sx - count) * ip->ftwidth, 0, fb->fb_width >> 3,
    459 			 ip->ftheight, (ip->cols - sx) * ip->ftwidth, RR_COPY);
    460     }
    461 }
    462 
    463 
    464 
    465 /*** (M<8)-by-N routines ***/
    466 
    467 /* NOTE: This routine assumes a cursor overlay plane,
    468    but it does allow cursors up to 32 pixels wide.  */
    469 static void
    470 cc_le32n_cursor(struct ite_softc *ip, int flag)
    471 {
    472   struct ccite *cci = (struct ccite *) ip->priv;
    473   struct ccfb *fb = cci->fb;
    474   /* the cursor is always drawn in the last plane */
    475   unsigned char *ovplane, opclr, opset;
    476 
    477   if (flag == START_CURSOROPT || flag == END_CURSOROPT)
    478     return;
    479 
    480   ovplane = fb->fb + (fb->fb_z - 1) * (fb->fb_planesize);
    481 
    482   if (flag != DRAW_CURSOR)
    483     {
    484       /* erase the cursor */
    485       u_char *pl = ovplane + ((fb->fb_y + ip->cursory * ip->ftheight) * (fb->fb_width >> 3));
    486       int ofs = fb->fb_x + ip->cursorx * ip->ftwidth;
    487       int h;
    488 
    489       for (h = ip->ftheight-1; h >= 0; h--)
    490 	{
    491 	  asm("bfclr %0@{%1:%2}"
    492 	      : : "a" (pl), "d" (ofs), "d" (ip->ftwidth));
    493 	  pl += fb->fb_width >> 3;
    494 	}
    495     }
    496   if (flag == DRAW_CURSOR || flag == MOVE_CURSOR)
    497     {
    498       u_char *pl;
    499       int ofs, h;
    500 
    501       /* store the position */
    502       ip->cursorx = MIN(ip->curx, ip->cols-1);
    503       ip->cursory = ip->cury;
    504 
    505       /* draw the cursor */
    506       pl = ovplane + ((fb->fb_y + ip->cursory * ip->ftheight) * (fb->fb_width >> 3));
    507       ofs = fb->fb_x + ip->cursorx * ip->ftwidth;
    508 
    509       for (h = ip->ftheight-1; h >= 0; h--)
    510 	{
    511 	  asm("bfset %0@{%1:%2}"
    512 	      : : "a" (pl), "d" (ofs), "d" (ip->ftwidth));
    513 	  pl += fb->fb_width >> 3;
    514 	}
    515     }
    516 }
    517 
    518 static void
    519 cc_le8n_putc(struct ite_softc *ip, int c, int dy, int dx, int mode)
    520 {
    521   if (c >= ip->font_lo && c <= ip->font_hi)
    522     {
    523       struct ccite *cci = (struct ccite *) ip->priv;
    524       struct ccfb *fb = cci->fb;
    525       u_char *pl = cci->buf_rows[dy].buf;
    526       int ofs = dx * ip->ftwidth;
    527       u_char *fontp = ip->font + (c - ip->font_lo) * ip->ftheight;
    528       int h;
    529 
    530       if (mode != ATTR_INV)
    531 	{
    532           for (h = ip->ftheight-1; h >= 0; h--)
    533 	    {
    534 	      asm("bfins %3,%0@{%1:%2}"
    535 	          : : "a" (pl), "d" (ofs), "d" (ip->ftwidth), "d" (*fontp++));
    536 	      pl += fb->fb_width >> 3;
    537 	    }
    538 	}
    539       else
    540 	{
    541           for (h = ip->ftheight-1; h >= 0; h--)
    542 	    {
    543 	      asm("bfins %3,%0@{%1:%2}"
    544 	          : : "a" (pl), "d" (ofs), "d" (ip->ftwidth), "d" (~(*fontp++)));
    545 	      pl += fb->fb_width >> 3;
    546 	    }
    547 	}
    548     }
    549 }
    550 
    551 static void
    552 cc_le8n_clear(struct ite_softc *ip, int sy, int sx, int h, int w)
    553 {
    554   struct ccite *cci = (struct ccite *) ip->priv;
    555   struct ccfb *fb = cci->fb;
    556 
    557   if ((sx == 0) && (w == ip->cols))
    558     {
    559       /* common case: clearing whole lines */
    560       while (h--)
    561 	{
    562           bzero(cci->buf_rows[sy].buf, (fb->fb_width >> 3) * ip->ftheight);
    563 	  sy++;
    564 	}
    565     }
    566   else
    567     {
    568       /* clearing only part of a line */
    569       /* XXX could be optimized MUCH better, but is it worth the trouble? */
    570       while (h--)
    571 	{
    572 	  u_char *pl = cci->buf_rows[sy].buf;
    573           int ofs = sx * ip->ftwidth;
    574 	  int i, j;
    575 	  for (i = w-1; i >= 0; i--)
    576 	    {
    577 	      u_char *ppl = pl;
    578               for (j = ip->ftheight-1; j >= 0; j--)
    579 	        {
    580 	          asm("bfclr %0@{%1:%2}"
    581 	              : : "a" (ppl), "d" (ofs), "d" (ip->ftwidth));
    582 	          ppl += fb->fb_width >> 3;
    583 	        }
    584 	      ofs += ip->ftwidth;
    585 	    }
    586 	  sy++;
    587 	}
    588     }
    589 }
    590 
    591 /* Note: sx is only relevant for SCROLL_LEFT or SCROLL_RIGHT.  */
    592 static void
    593 cc_le8n_scroll(ip, sy, sx, count, dir)
    594         register struct ite_softc *ip;
    595         register int sy;
    596         int dir, sx, count;
    597 {
    598   if (dir == SCROLL_UP)
    599     {
    600       int dy = sy - count;
    601       int bot = ip->inside_margins ? ip->bottom_margin : ip->rows - 1;
    602       int height = bot - sy + 1;
    603       int i;
    604 
    605       for (i = 0; i < height; i++)
    606 	swap_rows(ip, sy + i, dy + i);
    607     }
    608   else if (dir == SCROLL_DOWN)
    609     {
    610       int dy = sy + count;
    611       int bot = ip->inside_margins ? ip->bottom_margin : ip->rows - 1;
    612       int height = bot - dy + 1;
    613       int i;
    614 
    615       for (i = (height - 1); i >= 0; i--)
    616 	swap_rows(ip, sy + i, dy + i);
    617     }
    618   else if (dir == SCROLL_RIGHT)
    619     {
    620       struct ccite *cci = (struct ccite *) ip->priv;
    621       struct ccfb *fb = cci->fb;
    622       u_char *pl = cci->buf_rows[sy].buf;
    623       int sofs = (ip->cols - count) * ip->ftwidth;
    624       int dofs = (ip->cols) * ip->ftwidth;
    625       int i, j;
    626 
    627       cc_le32n_cursor(ip, ERASE_CURSOR);
    628       for (j = ip->ftheight-1; j >= 0; j--)
    629 	{
    630 	  int sofs2 = sofs, dofs2 = dofs;
    631 	  for (i = (ip->cols - (sx + count))-1; i >= 0; i--)
    632 	    {
    633 	      int t;
    634 	      sofs2 -= ip->ftwidth;
    635 	      dofs2 -= ip->ftwidth;
    636 	      asm("bfextu %1@{%2:%3},%0"
    637 	          : "=d" (t)
    638 		  : "a" (pl), "d" (sofs2), "d" (ip->ftwidth));
    639 	      asm("bfins %3,%0@{%1:%2}"
    640 	          : : "a" (pl), "d" (dofs2), "d" (ip->ftwidth), "d" (t));
    641 	    }
    642 	  pl += fb->fb_width >> 3;
    643 	}
    644     }
    645   else /* SCROLL_LEFT */
    646     {
    647       struct ccite *cci = (struct ccite *) ip->priv;
    648       struct ccfb *fb = cci->fb;
    649       u_char *pl = cci->buf_rows[sy].buf;
    650       int sofs = (sx) * ip->ftwidth;
    651       int dofs = (sx - count) * ip->ftwidth;
    652       int i, j;
    653 
    654       cc_le32n_cursor(ip, ERASE_CURSOR);
    655       for (j = ip->ftheight-1; j >= 0; j--)
    656 	{
    657 	  int sofs2 = sofs, dofs2 = dofs;
    658 	  for (i = (ip->cols - sx)-1; i >= 0; i--)
    659 	    {
    660 	      int t;
    661 	      asm("bfextu %1@{%2:%3},%0"
    662 	          : "=d" (t)
    663 		  : "a" (pl), "d" (sofs2), "d" (ip->ftwidth));
    664 	      asm("bfins %3,%0@{%1:%2}"
    665 	          : : "a" (pl), "d" (dofs2), "d" (ip->ftwidth), "d" (t));
    666 	      sofs2 += ip->ftwidth;
    667 	      dofs2 += ip->ftwidth;
    668 	    }
    669 	  pl += fb->fb_width >> 3;
    670 	}
    671     }
    672 }
    673 
    674 #endif
    675