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