Changeset bd48f4c in mainline for kernel/arch/ia32/src/asm.S
- Timestamp:
- 2010-07-12T10:53:30Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- bd11d3e
- Parents:
- c40e6ef (diff), bee2d4c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ia32/src/asm.S
rc40e6ef rbd48f4c 1 # 2 # Copyright (c) 2001-2004 Jakub Jermar 3 # All rights reserved. 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions 7 # are met: 8 # 9 # - Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # - Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # - The name of the author may not be used to endorse or promote products 15 # derived from this software without specific prior written permission. 16 # 17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 # 28 29 ## very low and hardware-level functions 30 31 # Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error 32 # word and 1 means interrupt with error word 33 #define ERROR_WORD_INTERRUPT_LIST 0x00027d00 1 /* 2 * Copyright (c) 2001 Jakub Jermar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * - The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** Very low and hardware-level functions 30 * 31 */ 32 33 /** 34 * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int 35 * has no error word and 1 means interrupt with error word 36 * 37 */ 38 #define ERROR_WORD_INTERRUPT_LIST 0x00027d00 39 40 #include <arch/pm.h> 41 #include <arch/mm/page.h> 34 42 35 43 .text 36 37 44 .global paging_on 38 45 .global enable_l_apic_in_msr 39 .global interrupt_handlers40 46 .global memsetb 41 47 .global memsetw … … 45 51 .global memcpy_to_uspace 46 52 .global memcpy_to_uspace_failover_address 47 48 49 # Wrapper for generic memsetb 53 .global early_putchar 54 55 /* Wrapper for generic memsetb */ 50 56 memsetb: 51 57 jmp _memsetb 52 58 53 # Wrapper for generic memsetw 59 /* Wrapper for generic memsetw */ 54 60 memsetw: 55 61 jmp _memsetw 56 62 57 58 #define MEMCPY_DST 4 59 #define MEMCPY_SRC 8 60 #define MEMCPY_SIZE 12 63 #define MEMCPY_DST 4 64 #define MEMCPY_SRC 8 65 #define MEMCPY_SIZE 12 61 66 62 67 /** Copy memory to/from userspace. … … 68 73 * or copy_to_uspace(). 69 74 * 70 * @param MEMCPY_DST(%esp) 71 * @param MEMCPY_SRC(%esp) 72 * @param MEMCPY_SIZE(%esp) 75 * @param MEMCPY_DST(%esp) Destination address. 76 * @param MEMCPY_SRC(%esp) Source address. 77 * @param MEMCPY_SIZE(%esp) Size. 73 78 * 74 79 * @return MEMCPY_DST(%esp) on success and 0 on failure. 80 * 75 81 */ 76 82 memcpy: 77 83 memcpy_from_uspace: 78 84 memcpy_to_uspace: 79 movl %edi, %edx 80 movl %esi, %eax 85 movl %edi, %edx /* save %edi */ 86 movl %esi, %eax /* save %esi */ 81 87 82 88 movl MEMCPY_SIZE(%esp), %ecx 83 shrl $2, %ecx 89 shrl $2, %ecx /* size / 4 */ 84 90 85 91 movl MEMCPY_DST(%esp), %edi 86 92 movl MEMCPY_SRC(%esp), %esi 87 93 88 rep movsl /* copy whole words */ 89 94 /* Copy whole words */ 95 rep movsl 96 90 97 movl MEMCPY_SIZE(%esp), %ecx 91 andl $3, %ecx 98 andl $3, %ecx /* size % 4 */ 92 99 jz 0f 93 100 94 rep movsb /* copy the rest byte by byte */ 95 96 0: 97 movl %edx, %edi 98 movl %eax, %esi 99 movl MEMCPY_DST(%esp), %eax /* MEMCPY_DST(%esp), success */ 100 ret 101 101 /* Copy the rest byte by byte */ 102 rep movsb 103 104 0: 105 106 movl %edx, %edi 107 movl %eax, %esi 108 109 /* MEMCPY_DST(%esp), success */ 110 movl MEMCPY_DST(%esp), %eax 111 ret 112 102 113 /* 103 114 * We got here from as_page_fault() after the memory operations … … 108 119 movl %edx, %edi 109 120 movl %eax, %esi 110 xorl %eax, %eax /* return 0, failure */ 121 122 /* Return 0, failure */ 123 xorl %eax, %eax 111 124 ret 112 125 113 ## Turn paging on 114 # 115 # Enable paging and write-back caching in CR0. 116 # 126 /** Turn paging on 127 * 128 * Enable paging and write-back caching in CR0. 129 * 130 */ 117 131 paging_on: 118 132 movl %cr0, %edx 119 orl $(1 << 31), %edx # paging on 120 # clear Cache Disable and not Write Though 133 orl $(1 << 31), %edx /* paging on */ 134 135 /* Clear Cache Disable and not Write Though */ 121 136 andl $~((1 << 30) | (1 << 29)), %edx 122 movl %edx, %cr0137 movl %edx, %cr0 123 138 jmp 0f 124 0: 125 ret 126 127 128 ## Enable local APIC 129 # 130 # Enable local APIC in MSR. 131 # 139 140 0: 141 ret 142 143 /** Enable local APIC 144 * 145 * Enable local APIC in MSR. 146 * 147 */ 132 148 enable_l_apic_in_msr: 133 149 movl $0x1b, %ecx … … 138 154 ret 139 155 140 # Clear nested flag 141 # overwrites %ecx 156 /** Clear nested flag 157 * 158 */ 142 159 .macro CLEAR_NT_FLAG 143 160 pushfl 144 pop %ecx 145 and $0xffffbfff, %ecx 146 push %ecx 161 andl $0xffffbfff, (%esp) 147 162 popfl 148 .endm 163 .endm 164 165 #define ISTATE_OFFSET_EDX 0 166 #define ISTATE_OFFSET_ECX 4 167 #define ISTATE_OFFSET_EBX 8 168 #define ISTATE_OFFSET_ESI 12 169 #define ISTATE_OFFSET_EDI 16 170 #define ISTATE_OFFSET_EBP 20 171 #define ISTATE_OFFSET_EAX 24 172 #define ISTATE_OFFSET_EBP_FRAME 28 173 #define ISTATE_OFFSET_EIP_FRAME 32 174 #define ISTATE_OFFSET_GS 36 175 #define ISTATE_OFFSET_FS 40 176 #define ISTATE_OFFSET_ES 44 177 #define ISTATE_OFFSET_DS 48 178 #define ISTATE_OFFSET_ERROR_WORD 52 179 #define ISTATE_OFFSET_EIP 56 180 #define ISTATE_OFFSET_CS 60 181 #define ISTATE_OFFSET_EFLAGS 64 182 #define ISTATE_OFFSET_ESP 68 183 #define ISTATE_OFFSET_SS 72 184 185 /* 186 * Size of the istate structure without the hardware-saved part 187 * and without the error word. 188 */ 189 #define ISTATE_SOFT_SIZE 52 190 191 /* 192 * Size of the entire istate structure including the error word and the 193 * hardware-saved part. 194 */ 195 #define ISTATE_REAL_SIZE (ISTATE_SOFT_SIZE + 24) 149 196 150 197 /* … … 160 207 sysenter_handler: 161 208 sti 162 pushl %ebp # remember user stack 163 pushl %edi # remember return user address 164 165 pushl %gs # remember TLS 166 167 pushl %eax # syscall number 168 subl $8, %esp # unused sixth and fifth argument 169 pushl %esi # fourth argument 170 pushl %ebx # third argument 171 pushl %ecx # second argument 172 pushl %edx # first argument 173 209 subl $(ISTATE_REAL_SIZE), %esp 210 211 /* 212 * Save the return address and the userspace stack in the istate 213 * structure on locations that would normally be taken by them. 214 */ 215 movl %ebp, ISTATE_OFFSET_ESP(%esp) 216 movl %edi, ISTATE_OFFSET_EIP(%esp) 217 218 /* 219 * Push syscall arguments onto the stack 220 */ 221 movl %eax, ISTATE_OFFSET_EAX(%esp) 222 movl %ebx, ISTATE_OFFSET_EBX(%esp) 223 movl %ecx, ISTATE_OFFSET_ECX(%esp) 224 movl %edx, ISTATE_OFFSET_EDX(%esp) 225 movl %esi, ISTATE_OFFSET_ESI(%esp) 226 movl %edi, ISTATE_OFFSET_EDI(%esp) /* observability; not needed */ 227 movl %ebp, ISTATE_OFFSET_EBP(%esp) /* observability; not needed */ 228 229 /* 230 * Fake up the stack trace linkage. 231 */ 232 movl %edi, ISTATE_OFFSET_EIP_FRAME(%esp) 233 movl $0, ISTATE_OFFSET_EBP_FRAME(%esp) 234 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 235 236 /* 237 * Save TLS. 238 */ 239 movl %gs, %edx 240 movl %edx, ISTATE_OFFSET_GS(%esp) 241 242 /* 243 * Switch to kernel selectors. 244 */ 174 245 movw $16, %ax 175 246 movw %ax, %ds 176 247 movw %ax, %es 177 248 178 249 cld 179 250 call syscall_handler 180 addl $28, %esp # remove arguments from stack 181 182 pop %gs # restore TLS 183 184 pop %edx # prepare return EIP for SYSEXIT 185 pop %ecx # prepare userspace ESP for SYSEXIT 186 187 sysexit # return to userspace 188 189 190 ## Declare interrupt handlers 191 # 192 # Declare interrupt handlers for n interrupt 193 # vectors starting at vector i. 194 # 195 # The handlers setup data segment registers 196 # and call exc_dispatch(). 197 # 198 #define INTERRUPT_ALIGN 64 199 .macro handler i n 200 201 .ifeq \i - 0x30 # Syscall handler 202 pushl %ds 203 pushl %es 204 pushl %fs 205 pushl %gs 206 207 # 208 # Push syscall arguments onto the stack 209 # 210 # NOTE: The idea behind the order of arguments passed in registers is to 211 # use all scratch registers first and preserved registers next. 212 # An optimized libc syscall wrapper can make use of this setup. 213 # 214 pushl %eax 215 pushl %ebp 216 pushl %edi 217 pushl %esi 218 pushl %ebx 219 pushl %ecx 220 pushl %edx 221 222 # we must fill the data segment registers 223 movw $16, %ax 224 movw %ax, %ds 225 movw %ax, %es 251 252 /* 253 * Restore TLS. 254 */ 255 movl ISTATE_OFFSET_GS(%esp), %edx 256 movl %edx, %gs 257 258 /* 259 * Prepare return address and userspace stack for SYSEXIT. 260 */ 261 movl ISTATE_OFFSET_EIP(%esp), %edx 262 movl ISTATE_OFFSET_ESP(%esp), %ecx 263 264 addl $(ISTATE_REAL_SIZE), %esp 265 266 sysexit /* return to userspace */ 267 268 /** Declare interrupt handlers 269 * 270 * Declare interrupt handlers for n interrupt 271 * vectors starting at vector i. 272 * 273 */ 274 275 .macro handler i 276 .global int_\i 277 int_\i: 278 .ifeq \i - 0x30 279 /* Syscall handler */ 280 subl $(ISTATE_SOFT_SIZE + 4), %esp 281 282 /* 283 * Push syscall arguments onto the stack 284 * 285 * NOTE: The idea behind the order of arguments passed 286 * in registers is to use all scratch registers 287 * first and preserved registers next. An optimized 288 * libc syscall wrapper can make use of this setup. 289 * The istate structure is arranged in the way to support 290 * this idea. 291 * 292 */ 293 movl %eax, ISTATE_OFFSET_EAX(%esp) 294 movl %ebx, ISTATE_OFFSET_EBX(%esp) 295 movl %ecx, ISTATE_OFFSET_ECX(%esp) 296 movl %edx, ISTATE_OFFSET_EDX(%esp) 297 movl %edi, ISTATE_OFFSET_EDI(%esp) 298 movl %esi, ISTATE_OFFSET_ESI(%esp) 299 movl %ebp, ISTATE_OFFSET_EBP(%esp) 300 301 /* 302 * Save the selector registers. 303 */ 304 movl %gs, %ecx 305 movl %fs, %edx 306 307 movl %ecx, ISTATE_OFFSET_GS(%esp) 308 movl %edx, ISTATE_OFFSET_FS(%esp) 309 310 movl %es, %ecx 311 movl %ds, %edx 312 313 movl %ecx, ISTATE_OFFSET_ES(%esp) 314 movl %edx, ISTATE_OFFSET_DS(%esp) 315 316 /* 317 * Switch to kernel selectors. 318 */ 319 movl $16, %eax 320 movl %eax, %ds 321 movl %eax, %es 322 323 movl $0, ISTATE_OFFSET_EBP_FRAME(%esp) 324 movl ISTATE_OFFSET_EIP(%esp), %eax 325 movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp) 326 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 226 327 227 328 cld 228 329 sti 229 # syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) 330 331 /* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */ 230 332 call syscall_handler 231 cli 232 addl $28, %esp # clean-up of parameters 233 234 popl %gs 235 popl %fs 236 popl %es 237 popl %ds 238 333 239 334 CLEAR_NT_FLAG 335 336 /* 337 * Restore the selector registers. 338 */ 339 movl ISTATE_OFFSET_GS(%esp), %ecx 340 movl ISTATE_OFFSET_FS(%esp), %edx 341 342 movl %ecx, %gs 343 movl %edx, %fs 344 345 movl ISTATE_OFFSET_ES(%esp), %ecx 346 movl ISTATE_OFFSET_DS(%esp), %edx 347 348 movl %ecx, %es 349 movl %edx, %ds 350 351 /* 352 * Restore the preserved registers the handler cloberred itself 353 * (i.e. EBP). 354 */ 355 movl ISTATE_OFFSET_EBP(%esp), %ebp 356 357 addl $(ISTATE_SOFT_SIZE + 4), %esp 240 358 iret 359 241 360 .else 242 361 /* 243 * This macro distinguishes between two versions of ia32 exceptions. 244 * One version has error word and the other does not have it. 245 * The latter version fakes the error word on the stack so that the 246 * handlers and istate_t can be the same for both types. 362 * This macro distinguishes between two versions of ia32 363 * exceptions. One version has error word and the other 364 * does not have it. The latter version fakes the error 365 * word on the stack so that the handlers and istate_t 366 * can be the same for both types. 247 367 */ 248 368 .iflt \i - 32 249 369 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST 250 370 /* 251 * With error word,do nothing371 * Exception with error word: do nothing 252 372 */ 253 373 .else 254 374 /* 255 * Version without error word375 * Exception without error word: fake up one 256 376 */ 257 subl $4, %esp377 pushl $0 258 378 .endif 259 379 .else 260 380 /* 261 * Version without error word381 * Interrupt: fake up one 262 382 */ 263 subl $4, %esp383 pushl $0 264 384 .endif 265 385 266 pushl %ds 267 pushl %es 268 pushl %fs 269 pushl %gs 270 271 pushl %ebp 272 pushl %edx 273 pushl %ecx 274 pushl %eax 275 276 # we must fill the data segment registers 277 278 movw $16, %ax 279 movw %ax, %ds 280 movw %ax, %es 281 282 # stop stack traces here 386 subl $ISTATE_SOFT_SIZE, %esp 387 388 /* 389 * Save the general purpose registers. 390 */ 391 movl %eax, ISTATE_OFFSET_EAX(%esp) 392 movl %ebx, ISTATE_OFFSET_EBX(%esp) 393 movl %ecx, ISTATE_OFFSET_ECX(%esp) 394 movl %edx, ISTATE_OFFSET_EDX(%esp) 395 movl %edi, ISTATE_OFFSET_EDI(%esp) 396 movl %esi, ISTATE_OFFSET_ESI(%esp) 397 movl %ebp, ISTATE_OFFSET_EBP(%esp) 398 399 /* 400 * Save the selector registers. 401 */ 402 movl %gs, %eax 403 movl %fs, %ebx 404 movl %es, %ecx 405 movl %ds, %edx 406 407 movl %eax, ISTATE_OFFSET_GS(%esp) 408 movl %ebx, ISTATE_OFFSET_FS(%esp) 409 movl %ecx, ISTATE_OFFSET_ES(%esp) 410 movl %edx, ISTATE_OFFSET_DS(%esp) 411 412 /* 413 * Switch to kernel selectors. 414 */ 415 movl $16, %eax 416 movl %eax, %ds 417 movl %eax, %es 418 419 /* 420 * Imitate a regular stack frame linkage. 421 * Stop stack traces here if we came from userspace. 422 */ 423 cmpl $8, ISTATE_OFFSET_CS(%esp) 424 jz 0f 283 425 xorl %ebp, %ebp 284 426 285 pushl %esp # *istate 286 pushl $(\i) # intnum 287 call exc_dispatch # exc_dispatch(intnum, *istate) 288 addl $8, %esp # Clear arguments from stack 289 290 CLEAR_NT_FLAG # Modifies %ecx 291 292 popl %eax 293 popl %ecx 294 popl %edx 295 popl %ebp 296 297 popl %gs 298 popl %fs 299 popl %es 300 popl %ds 301 302 # skip error word, no matter whether real or fake 303 addl $4, %esp 304 iret 305 .endif 306 307 .align INTERRUPT_ALIGN 308 .if (\n- \i) - 1 309 handler "(\i + 1)", \n 427 0: 428 429 movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp) 430 movl ISTATE_OFFSET_EIP(%esp), %eax 431 movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp) 432 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 433 434 cld 435 436 pushl %esp /* pass istate address */ 437 pushl $(\i) /* pass intnum */ 438 439 /* Call exc_dispatch(intnum, istate) */ 440 call exc_dispatch 441 442 addl $8, %esp /* clear arguments from the stack */ 443 444 CLEAR_NT_FLAG 445 446 /* 447 * Restore the selector registers. 448 */ 449 movl ISTATE_OFFSET_GS(%esp), %eax 450 movl ISTATE_OFFSET_FS(%esp), %ebx 451 movl ISTATE_OFFSET_ES(%esp), %ecx 452 movl ISTATE_OFFSET_DS(%esp), %edx 453 454 movl %eax, %gs 455 movl %ebx, %fs 456 movl %ecx, %es 457 movl %edx, %ds 458 459 /* 460 * Restore the scratch registers and the preserved 461 * registers the handler cloberred itself 462 * (i.e. EBX and EBP). 463 */ 464 movl ISTATE_OFFSET_EAX(%esp), %eax 465 movl ISTATE_OFFSET_EBX(%esp), %ebx 466 movl ISTATE_OFFSET_ECX(%esp), %ecx 467 movl ISTATE_OFFSET_EDX(%esp), %edx 468 movl ISTATE_OFFSET_EBP(%esp), %ebp 469 470 addl $(ISTATE_SOFT_SIZE + 4), %esp 471 iret 472 310 473 .endif 311 474 .endm 312 475 313 # keep in sync with pm.h !!! 314 IDT_ITEMS = 64 315 .align INTERRUPT_ALIGN 476 #define LIST_0_63 \ 477 0, 1, 2, 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,\ 478 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,\ 479 53,54,55,56,57,58,59,60,61,62,63 480 316 481 interrupt_handlers: 317 h_start: 318 handler 0 IDT_ITEMS 319 h_end: 320 321 .data 322 .global interrupt_handler_size 323 324 interrupt_handler_size: .long (h_end - h_start) / IDT_ITEMS 482 .irp cnt, LIST_0_63 483 handler \cnt 484 .endr 485 486 /** Print Unicode character to EGA display. 487 * 488 * If CONFIG_EGA is undefined or CONFIG_FB is defined 489 * then this function does nothing. 490 * 491 * Since the EGA can only display Extended ASCII (usually 492 * ISO Latin 1) characters, some of the Unicode characters 493 * can be displayed in a wrong way. Only newline and backspace 494 * are interpreted, all other characters (even unprintable) are 495 * printed verbatim. 496 * 497 * @param %ebp+0x08 Unicode character to be printed. 498 * 499 */ 500 early_putchar: 501 502 #if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB))) 503 504 /* Prologue, save preserved registers */ 505 pushl %ebp 506 movl %esp, %ebp 507 pushl %ebx 508 pushl %esi 509 pushl %edi 510 511 movl $(PA2KA(0xb8000)), %edi /* base of EGA text mode memory */ 512 xorl %eax, %eax 513 514 /* Read bits 8 - 15 of the cursor address */ 515 movw $0x3d4, %dx 516 movb $0xe, %al 517 outb %al, %dx 518 519 movw $0x3d5, %dx 520 inb %dx, %al 521 shl $8, %ax 522 523 /* Read bits 0 - 7 of the cursor address */ 524 movw $0x3d4, %dx 525 movb $0xf, %al 526 outb %al, %dx 527 528 movw $0x3d5, %dx 529 inb %dx, %al 530 531 /* Sanity check for the cursor on screen */ 532 cmp $2000, %ax 533 jb early_putchar_cursor_ok 534 535 movw $1998, %ax 536 537 early_putchar_cursor_ok: 538 539 movw %ax, %bx 540 shl $1, %eax 541 addl %eax, %edi 542 543 movl 0x08(%ebp), %eax 544 545 cmp $0x0a, %al 546 jne early_putchar_backspace 547 548 /* Interpret newline */ 549 550 movw %bx, %ax /* %bx -> %dx:%ax */ 551 xorw %dx, %dx 552 553 movw $80, %cx 554 idivw %cx, %ax /* %dx = %bx % 80 */ 555 556 /* %bx <- %bx + 80 - (%bx % 80) */ 557 addw %cx, %bx 558 subw %dx, %bx 559 560 jmp early_putchar_skip 561 562 early_putchar_backspace: 563 564 cmp $0x08, %al 565 jne early_putchar_print 566 567 /* Interpret backspace */ 568 569 cmp $0x0000, %bx 570 je early_putchar_skip 571 572 dec %bx 573 jmp early_putchar_skip 574 575 early_putchar_print: 576 577 /* Print character */ 578 579 movb $0x0e, %ah /* black background, yellow foreground */ 580 stosw 581 inc %bx 582 583 early_putchar_skip: 584 585 /* Sanity check for the cursor on the last line */ 586 cmp $2000, %bx 587 jb early_putchar_no_scroll 588 589 /* Scroll the screen (24 rows) */ 590 movl $(PA2KA(0xb80a0)), %esi 591 movl $(PA2KA(0xb8000)), %edi 592 movl $960, %ecx 593 rep movsl 594 595 /* Clear the 24th row */ 596 xorl %eax, %eax 597 movl $40, %ecx 598 rep stosl 599 600 /* Go to row 24 */ 601 movw $1920, %bx 602 603 early_putchar_no_scroll: 604 605 /* Write bits 8 - 15 of the cursor address */ 606 movw $0x3d4, %dx 607 movb $0xe, %al 608 outb %al, %dx 609 610 movw $0x3d5, %dx 611 movb %bh, %al 612 outb %al, %dx 613 614 /* Write bits 0 - 7 of the cursor address */ 615 movw $0x3d4, %dx 616 movb $0xf, %al 617 outb %al, %dx 618 619 movw $0x3d5, %dx 620 movb %bl, %al 621 outb %al, %dx 622 623 /* Epilogue, restore preserved registers */ 624 popl %edi 625 popl %esi 626 popl %ebx 627 leave 628 629 #endif 630 631 ret 632
Note:
See TracChangeset
for help on using the changeset viewer.