Index: kernel/genarch/src/fb/fb.c
===================================================================
--- kernel/genarch/src/fb/fb.c	(revision 250a435052de09253cdf2f5178b8589103c3d2c5)
+++ kernel/genarch/src/fb/fb.c	(revision 888c06e05177b71e23a0f4f5636be16622ad9463)
@@ -81,4 +81,6 @@
 	((glyph) * (instance)->glyphbytes + (y) * (instance)->glyphscanline)
 
+#define TAB_WIDTH 8
+
 typedef void (*rgb_conv_t)(void *, uint32_t);
 
@@ -99,5 +101,5 @@
 
 	/** Number of rows that fit on framebuffer */
-	unsigned int rowtrim;
+	unsigned int screen_rows;
 
 	unsigned int scanline;
@@ -124,4 +126,7 @@
 	/** Partial character between writes */
 	mbstate_t mbstate;
+
+	unsigned int row;
+	unsigned int column;
 } fb_instance_t;
 
@@ -250,5 +255,5 @@
 
 	unsigned int rel_row = row - instance->offset_row;
-	if (rel_row >= instance->rowtrim)
+	if (rel_row >= instance->screen_rows)
 		return;
 
@@ -262,61 +267,8 @@
 }
 
-/** Scroll screen down by one row
- *
- */
-static void screen_scroll(fb_instance_t *instance)
-{
-	if ((!instance->parea.mapped) || (console_override)) {
-		for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) {
-			unsigned int y = ROW2Y(rel_row);
-			unsigned int row = rel_row + instance->offset_row;
-
-			for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
-				unsigned int x;
-				unsigned int col;
-				size_t bb_pos = BB_POS(instance, 0, row);
-				size_t bb_pos1 = BB_POS(instance, 0, row + 1);
-
-				for (col = 0, x = 0; col < instance->cols;
-				    col++, x += FONT_WIDTH) {
-					uint16_t glyph;
-
-					if (row < instance->rows - 1) {
-						if (instance->backbuf[bb_pos] ==
-						    instance->backbuf[bb_pos1])
-							goto skip;
-
-						glyph = instance->backbuf[bb_pos1];
-					} else
-						glyph = 0;
-
-					memcpy(&instance->addr[FB_POS(instance, x, y + yd)],
-					    &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
-					    instance->glyphscanline);
-				skip:
-					BB_NEXT_COL(bb_pos);
-					BB_NEXT_COL(bb_pos1);
-				}
-			}
-		}
-	}
-
-	/*
-	 * Implement backbuffer scrolling by wrapping around
-	 * the cyclic buffer.
-	 */
-
-	instance->start_row++;
-	if (instance->start_row == instance->rows)
-		instance->start_row = 0;
-
-	memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)],
-	    instance->cols, 0);
-}
-
 static void cursor_put(fb_instance_t *instance)
 {
-	unsigned int col = instance->position % instance->cols;
-	unsigned int row = instance->position / instance->cols;
+	unsigned int col = instance->column;
+	unsigned int row = instance->row;
 
 	glyph_draw(instance, fb_font_glyph(U_CURSOR), col, row, true);
@@ -325,6 +277,6 @@
 static void cursor_remove(fb_instance_t *instance)
 {
-	unsigned int col = instance->position % instance->cols;
-	unsigned int row = instance->position / instance->cols;
+	unsigned int col = instance->column;
+	unsigned int row = instance->row;
 
 	glyph_draw(instance, instance->backbuf[BB_POS(instance, col, row)],
@@ -376,5 +328,5 @@
 static void fb_redraw_internal(fb_instance_t *instance)
 {
-	for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) {
+	for (unsigned int rel_row = 0; rel_row < instance->screen_rows; rel_row++) {
 		unsigned int y = ROW2Y(rel_row);
 		unsigned int row = rel_row + instance->offset_row;
@@ -407,8 +359,8 @@
 	}
 
-	if (ROW2Y(instance->rowtrim) < instance->yres) {
+	if (ROW2Y(instance->screen_rows) < instance->yres) {
 		unsigned int y;
 
-		for (y = ROW2Y(instance->rowtrim); y < instance->yres; y++)
+		for (y = ROW2Y(instance->screen_rows); y < instance->yres; y++)
 			memcpy(&instance->addr[FB_POS(instance, 0, y)],
 			    instance->bgscan, instance->bgscanbytes);
@@ -416,4 +368,36 @@
 }
 
+/** Scroll screen down by one row
+ *
+ */
+static void screen_scroll(fb_instance_t *instance)
+{
+	/*
+	 * Implement backbuffer scrolling by wrapping around
+	 * the cyclic buffer.
+	 */
+
+	instance->start_row++;
+	if (instance->start_row == instance->rows)
+		instance->start_row = 0;
+
+	if ((!instance->parea.mapped) || (console_override)) {
+		fb_redraw_internal(instance);
+	}
+}
+
+static void _advance_row(fb_instance_t *instance)
+{
+	instance->column = 0;
+	instance->row++;
+}
+
+static void _advance_column(fb_instance_t *instance)
+{
+	instance->column++;
+	if (instance->column == instance->cols)
+		_advance_row(instance);
+}
+
 /** Print character to screen
  *
@@ -425,32 +409,30 @@
 	switch (ch) {
 	case '\n':
-		instance->position += instance->cols;
-		instance->position -= instance->position % instance->cols;
+		_advance_row(instance);
 		break;
 	case '\r':
-		instance->position -= instance->position % instance->cols;
+		instance->column = 0;
 		break;
 	case '\b':
-		if (instance->position % instance->cols)
-			instance->position--;
+		if (instance->column > 0)
+			instance->column--;
 		break;
 	case '\t':
 		do {
 			glyph_draw(instance, fb_font_glyph(' '),
-			    instance->position % instance->cols,
-			    instance->position / instance->cols, false);
-			instance->position++;
-		} while (((instance->position % instance->cols) % 8 != 0) &&
-		    (instance->position < instance->cols * instance->rows));
+			    instance->column,
+			    instance->row, false);
+			_advance_column(instance);
+		} while (instance->column % TAB_WIDTH != 0);
 		break;
 	default:
 		glyph_draw(instance, fb_font_glyph(ch),
-		    instance->position % instance->cols,
-		    instance->position / instance->cols, false);
-		instance->position++;
-	}
-
-	if (instance->position >= instance->cols * instance->rows) {
-		instance->position -= instance->cols;
+		    instance->column,
+		    instance->row, false);
+		_advance_column(instance);
+	}
+
+	while (instance->row >= instance->rows) {
+		instance->row--;
 		screen_scroll(instance);
 	}
@@ -482,6 +464,6 @@
 	spinlock_lock(&instance->lock);
 
-	if (instance->offset_row >= instance->rowtrim / 2)
-		instance->offset_row -= instance->rowtrim / 2;
+	if (instance->offset_row >= instance->screen_rows / 2)
+		instance->offset_row -= instance->screen_rows / 2;
 	else
 		instance->offset_row = 0;
@@ -501,9 +483,9 @@
 	spinlock_lock(&instance->lock);
 
-	if (instance->offset_row + instance->rowtrim / 2 <=
-	    instance->rows - instance->rowtrim)
-		instance->offset_row += instance->rowtrim / 2;
+	if (instance->offset_row + instance->screen_rows / 2 <=
+	    instance->rows - instance->screen_rows)
+		instance->offset_row += instance->screen_rows / 2;
 	else
-		instance->offset_row = instance->rows - instance->rowtrim;
+		instance->offset_row = instance->rows - instance->screen_rows;
 
 	fb_redraw_internal(instance);
@@ -624,12 +606,13 @@
 	instance->scanline = props->scan;
 
-	instance->rowtrim = Y2ROW(instance->yres);
+	instance->screen_rows = Y2ROW(instance->yres);
 
 	instance->cols = X2COL(instance->xres);
-	instance->rows = FB_PAGES * instance->rowtrim;
-
-	instance->start_row = instance->rows - instance->rowtrim;
+	instance->rows = FB_PAGES * instance->screen_rows;
+
+	instance->start_row = instance->rows - instance->screen_rows;
 	instance->offset_row = instance->start_row;
-	instance->position = instance->start_row * instance->cols;
+	instance->row = instance->start_row;
+	instance->column = 0;
 
 	instance->glyphscanline = FONT_WIDTH * instance->pixelbytes;
