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