home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.pdx.edu / 2014.02.ftp.ee.pdx.edu.tar / ftp.ee.pdx.edu / pub / users / Harry / Blitz / OSProject / p2 / Runtime.s < prev    next >
Text File  |  2007-09-19  |  33KB  |  1,095 lines

  1. ! KPL Programming Language Runtime Support Code
  2. !
  3. ! ==========  THIS VERSION IS TO SUPPORT THE BLITZ OS PROJECT  ==========
  4. !
  5. ! Harry Porter  -  05/30/03
  6. !                  12/09/03
  7. !
  8. ! The following functions are implemented in this file and may be used by
  9. ! the KPL programmer.  They follow the standard KPL calling
  10. ! conventions.
  11. !
  12.     .export    print
  13.     .export    printInt
  14.     .export    printHex
  15.     .export    printChar
  16.     .export    printBool
  17.     .export    Cleari
  18.     .export    Seti
  19.     .export    Wait
  20.     .export    RuntimeExit
  21.     .export    getCatchStack
  22.     .export    MemoryZero
  23.     .export    MemoryCopy
  24. !
  25. ! The following functions are implemented in this file and
  26. ! are used by the code generated by the KPL compiler:
  27. !
  28.     .export _putString
  29.     .export    _heapInitialize
  30.     .export    _heapAlloc
  31.     .export    _heapFree
  32.     .export    _RestoreCatchStack
  33.     .export    _PerformThrow
  34.     .export    _IsKindOf
  35.     .export    _PosInf
  36.     .export    _NegInf
  37.     .export    _NegZero
  38. !
  39. ! Jumps to the following labels may be generated by the KPL compiler.
  40. ! Each will print an error message and halt program execution.
  41. !
  42.     .export    _runtimeErrorOverflow
  43.     .export    _runtimeErrorZeroDivide
  44.     .export    _runtimeErrorNullPointer
  45.     .export    _runtimeErrorUninitializedObject
  46.     .export    _runtimeErrorWrongObject
  47.     .export    _runtimeErrorWrongObject2
  48.     .export    _runtimeErrorWrongObject3
  49.     .export    _runtimeErrorBadObjectSize
  50.     .export    _runtimeErrorDifferentArraySizes
  51.     .export    _runtimeErrorWrongArraySize
  52.     .export    _runtimeErrorUninitializedArray
  53.     .export    _runtimeErrorBadArrayIndex
  54.     .export    _runtimeErrorNullPointerDuringCall
  55.     .export    _runtimeErrorArrayCountNotPositive
  56.     .export    _runtimeErrorRestoreCatchStackError
  57. !
  58. ! Jumps to the following labels may be generated occur only in this file.
  59. !
  60. !    _runtimeErrorThrowHandlerHasReturned
  61. !    _runtimeErrorFatalThrowError
  62. !    _runtimeErrorInterruptsEnabled
  63. !
  64. ! Routines that are created by the KPL Compiler and called from here:
  65. !
  66.     .import _mainEntry
  67. !
  68. ! Symbols that are created by the KPL compiler and used in this file:
  69. !
  70.     .import _Error_P_System_UncaughtThrowError
  71. !
  72. ! Routines that should be implemented in KPL and called from here:
  73. !
  74.     .import _P_System_KPLSystemInitialize
  75.     .import _P_System_KPLMemoryAlloc
  76.     .import _P_System_KPLMemoryFree
  77.     .import _P_System_KPLUncaughtThrow
  78.     .import _P_System_KPLIsKindOf
  79.     .import _P_Thread_TimerInterruptHandler
  80. !
  81. ! The initial stack will start at high memory and grow downward:
  82. !
  83. STACK_START    =    0x00ffff00
  84.  
  85.  
  86.  
  87. !
  88. ! =====================  Program entry point  =====================
  89. !
  90.     .text
  91. _entry:
  92.  
  93.  
  94.  
  95. !
  96. ! =====================  Interrupt Trap Vector (in low memory)  =====================
  97. !
  98. ! Here is the interrupt vector, which will be loaded at address 0x00000000.
  99. ! Each entry is 4 bytes.  They are located at fixed, pre-defined addresses.
  100. ! Each entry contains a jump to the handler routine.
  101. !
  102. ! This program handles the following:
  103. !      TIMER_INTERRUPT
  104. !      SERIAL_INTERRUPT
  105. !      DISK_INTERRUPT
  106. !      SYSCALL_TRAP
  107. ! None of the other interrupts should occur; if they do, we will print an error
  108. ! message and halt.
  109. !
  110. PowerOnReset:
  111.         jmp     RuntimeStartup
  112. TimerInterrupt:
  113.         jmp     TimerInterruptHandler
  114. DiskInterrupt:
  115.         jmp     DiskInterruptHandler
  116. SerialInterrupt:
  117.         jmp     SerialInterruptHandler
  118. HardwareFault:
  119.         jmp     HardwareFaultHandler
  120. IllegalInstruction:
  121.         jmp     IllegalInstructionHandler
  122. ArithmeticException:
  123.         jmp     ArithmeticExceptionHandler
  124. AddressException:
  125.         jmp     AddressExceptionHandler
  126. PageInvalidException:
  127.         jmp     PageInvalidExceptionHandler
  128. PageReadonlyException:
  129.         jmp     PageReadonlyExceptionHandler
  130. PrivilegedInstruction:
  131.         jmp     PrivilegedInstructionHandler
  132. AlignmentException:
  133.         jmp     AlignmentExceptionHandler
  134. ExceptionDuringInterrupt:
  135.         jmp     ExceptionDuringInterruptHandler
  136. SyscallTrap:
  137.         jmp     SyscallTrapHandler
  138.  
  139.  
  140.  
  141. ! =====================  TimerInterruptHandler  =====================
  142. TimerInterruptHandler:
  143.     push    r1                ! Save all int registers on the 
  144.     push    r2                ! .  interrupted thread's system stack
  145.     push    r3                ! .
  146.     push    r4                ! .
  147.     push    r5                ! .
  148.     push    r6                ! .
  149.     push    r7                ! .
  150.     push    r8                ! .
  151.     push    r9                ! .
  152.     push    r10                ! .
  153.     push    r11                ! .
  154.     push    r12                ! .
  155.     call    _P_Thread_TimerInterruptHandler    ! Perform up-call
  156.     pop    r12                ! Restore int registers
  157.     pop    r11                ! .
  158.     pop    r10                ! .
  159.     pop    r9                ! .
  160.     pop    r8                ! .
  161.     pop    r7                ! .
  162.     pop    r6                ! .
  163.     pop    r5                ! .
  164.     pop    r4                ! .
  165.     pop    r3                ! .
  166.     pop    r2                ! .
  167.     pop    r1                ! .
  168.     reti                    ! Return from interrupt
  169.  
  170.  
  171.  
  172. ! =====================  All Other Interrupt Handlers  =====================
  173. DiskInterruptHandler:
  174.     set    ExceptMess11,r1            ! Print an error message
  175.     jmp    printRuntimeError        ! .  and terminate all execution
  176.  
  177. SerialInterruptHandler:
  178.     set    ExceptMess12,r1            ! Print an error message
  179.     jmp    printRuntimeError        ! .  and terminate all execution
  180.  
  181. HardwareFaultHandler:
  182.     set    ExceptMess1,r1            ! Print an error message
  183.     jmp    printRuntimeError        ! .  and terminate all execution
  184.  
  185. IllegalInstructionHandler:
  186.     set    ExceptMess2,r1            ! Print an error message
  187.     jmp    printRuntimeError        ! .  and terminate all execution
  188.  
  189. ArithmeticExceptionHandler:
  190.     set    ExceptMess3,r1            ! Print an error message
  191.     jmp    printRuntimeError        ! .  and terminate all execution
  192.  
  193. AddressExceptionHandler:
  194.     set    ExceptMess4,r1            ! Print an error message
  195.     jmp    printRuntimeError        ! .  and terminate all execution
  196.  
  197. PageInvalidExceptionHandler:
  198.     set    ExceptMess5,r1            ! Print an error message
  199.     jmp    printRuntimeError        ! .  and terminate all execution
  200.  
  201. PageReadonlyExceptionHandler:
  202.     set    ExceptMess6,r1            ! Print an error message
  203.     jmp    printRuntimeError        ! .  and terminate all execution
  204.  
  205. PrivilegedInstructionHandler:
  206.     set    ExceptMess7,r1            ! Print an error message
  207.     jmp    printRuntimeError        ! .  and terminate all execution
  208.  
  209. AlignmentExceptionHandler:
  210.     set    ExceptMess8,r1            ! Print an error message
  211.     jmp    printRuntimeError        ! .  and terminate all execution
  212.  
  213. ExceptionDuringInterruptHandler:
  214.     set    STACK_START,r15            ! Reset stack so printing works
  215.     set    ExceptMess9,r1            ! Print an error message
  216.     jmp    printRuntimeError        ! .  and terminate all execution
  217.  
  218. SyscallTrapHandler:
  219.     set    STACK_START,r15            ! Reset stack so printing works
  220.     set    ExceptMess10,r1            ! Print an error message
  221.     jmp    printRuntimeError        ! .  and terminate all execution
  222.  
  223. ExceptMess1:
  224.     .ascii    "\nA HardwareFaultException has occurred!  Type 'st' to see stack.\n\0"
  225. ExceptMess2:
  226.     .ascii    "\nAn IllegalInstructionException has occurred!  Type 'st' to see stack.\n\0"
  227. ExceptMess3:
  228.     .ascii    "\nAn ArithmeticException has occurred!  Type 'st' to see stack.\n\0"
  229. ExceptMess4:
  230.     .ascii    "\nAn AddressException has occurred!  Type 'st' to see stack.\n\0"
  231. ExceptMess5:
  232.     .ascii    "\nA PageInvalidException has occurred!  Type 'st' to see stack.\n\0"
  233. ExceptMess6:
  234.     .ascii    "\nA PageReadonlyException has occurred!  Type 'st' to see stack.\n\0"
  235. ExceptMess7:
  236.     .ascii    "\nA PrivilegedInstruction has occurred!  Type 'st' to see stack.\n\0"
  237. ExceptMess8:
  238.     .ascii    "\nAn AlignmentException has occurred!  Type 'st' to see stack.\n\0"
  239. ExceptMess9:
  240.     .ascii    "\nA ExceptionDuringInterrupt has occurred!  Type 'st' to see stack.\n\0"
  241. ExceptMess10:
  242.     .ascii    "\nA SyscallTrap has occurred!  Type 'st' to see stack.\n\0"
  243. ExceptMess11:
  244.     .ascii    "\nA DiskInterupt has occurred!  Type 'st' to see stack.\n\0"
  245. ExceptMess12:
  246.     .ascii    "\nA SerialInterupt has occurred!  Type 'st' to see stack.\n\0"
  247.     .align
  248.  
  249.  
  250.  
  251. ! =====================  KPL Runtime Error Handlers  =====================
  252. _runtimeErrorOverflow:
  253.     set    ErrorMess1,r1        ! Print an error message
  254.     jmp    printRuntimeError    ! .  and terminate all execution
  255.  
  256. _runtimeErrorZeroDivide:
  257.     set    ErrorMess2,r1        ! Print an error message
  258.     jmp    printRuntimeError    ! .  and terminate all execution
  259.  
  260. _runtimeErrorNullPointer:
  261.     set    ErrorMess3,r1        ! Print an error message
  262.     jmp    printRuntimeError    ! .  and terminate all execution
  263.  
  264. _runtimeErrorUninitializedObject:
  265.     set    ErrorMess4,r1        ! Print an error message
  266.     jmp    printRuntimeError    ! .  and terminate all execution
  267.  
  268. _runtimeErrorWrongObject:
  269.     set    ErrorMess5,r1        ! Print an error message
  270.     jmp    printRuntimeError    ! .  and terminate all execution
  271.  
  272. _runtimeErrorWrongObject2:
  273.     set    ErrorMess6,r1        ! Print an error message
  274.     jmp    printRuntimeError    ! .  and terminate all execution
  275.  
  276. _runtimeErrorWrongObject3:
  277.     set    ErrorMess7,r1        ! Print an error message
  278.     jmp    printRuntimeError    ! .  and terminate all execution
  279.  
  280. _runtimeErrorBadObjectSize:
  281.     set    ErrorMess8,r1        ! Print an error message
  282.     jmp    printRuntimeError    ! .  and terminate all execution
  283.  
  284. _runtimeErrorDifferentArraySizes:
  285.     call    stopInterrupts        ! suspend any thread switching
  286.     push    r1            ! save r1 and r3
  287.     push    r3            ! .  so the user can look at them
  288.     set    ErrorMess9,r1        ! print the error message
  289.     call    _putString        ! .
  290.     pop    r3            ! restore r1 and r3
  291.     pop    r1            ! .
  292.     jmp    TerminateRuntime    ! Can't continue: invoke "debug"
  293.  
  294. _runtimeErrorWrongArraySize:
  295.     call    stopInterrupts        ! suspend any thread switching
  296.     push    r1            ! save r1 and r2
  297.     push    r2            ! .  so the user can look at them
  298.     set    ErrorMess10,r1        ! print the error message
  299.     call    _putString        ! .
  300.     pop    r2            ! restore r1 and r2
  301.     pop    r1            ! .
  302.     jmp    TerminateRuntime    ! terminate all execution
  303.  
  304. _runtimeErrorUninitializedArray:
  305.     set    ErrorMess11a,r1        ! Print an error message
  306.     jmp    printRuntimeError    ! .  and terminate all execution
  307.  
  308. _runtimeErrorBadArrayIndex:
  309.     call    stopInterrupts        ! suspend any thread switching
  310.     push    r2            ! save r2 so the user can look at it
  311.     set    ErrorMess11,r1        ! print the error message
  312.     call    _putString        ! .
  313.     pop    r2            ! restore r2
  314.     jmp    TerminateRuntime    ! terminate all execution
  315.  
  316. _runtimeErrorNullPointerDuringCall:
  317.     set    ErrorMess12,r1        ! Print an error message
  318.     jmp    printRuntimeError    ! .  and terminate all execution
  319.  
  320. _runtimeErrorArrayCountNotPositive:
  321.     call    stopInterrupts        ! suspend any thread switching
  322.     push    r1            ! save r1 so the user can look at it
  323.     set    ErrorMess13,r1        ! print the error message
  324.     call    _putString        ! .
  325.     pop    r1            ! restore r1
  326.     jmp    TerminateRuntime    ! terminate all execution
  327.  
  328. _runtimeErrorRestoreCatchStackError:
  329.     set    ErrorMess14,r1        ! Print an error message
  330.     jmp    printRuntimeError    ! .  and terminate all execution
  331.  
  332. _runtimeErrorThrowHandlerHasReturned:
  333.     set    ErrorMess15,r1        ! Print an error message
  334.     jmp    printRuntimeError    ! .  and terminate all execution
  335.  
  336. _runtimeErrorFatalThrowError:
  337.     set    ErrorMess16,r1        ! Print an error message
  338.     jmp    printRuntimeError    ! .  and terminate all execution
  339.  
  340. _runtimeErrorInterruptsEnabled:
  341.     set    ErrorMess17,r1        ! Print an error message
  342.     jmp    printRuntimeError    ! .  and terminate all execution
  343.  
  344.  
  345. ErrorMess1:
  346.     .ascii    "\nArithmetic overflow has occurred!  Type 'st' to see stack.\n\0"
  347. ErrorMess2:
  348.     .ascii    "\nDivide-by-zero has occurred!  Type 'st' to see stack.\n\0"
  349. ErrorMess3:
  350.     .ascii    "\nAttempt to use a null pointer!  Type 'st' to see stack.\n\0"
  351. ErrorMess4:
  352.     .ascii    "\nAttempt to use an uninitialized object!  Type 'st' to see stack.\n\0"
  353. ErrorMess5:
  354.     .ascii    "\nDuring an assignment of the form '*ptr = x', the ptr does not already point to an instance of the same class as x!  Type 'st' to see stack.\n\0"
  355. ErrorMess6:
  356.     .ascii    "\nDuring an assignment of the form 'x = *ptr', the ptr does not already point to an instance of the same class as x!  Type 'st' to see stack.\n\0"
  357. ErrorMess7:
  358.     .ascii    "\nDuring an object assignment of the form '*ptr1 = *ptr2', the two objects are not instances of the same class!  Type 'st' to see stack.\n\0"
  359. ErrorMess8:
  360.     .ascii    "\nDuring an object assignment or object equality test, something is wrong with the dispatch table pointer, the dispatch table, "
  361.     .ascii   "or the class descriptor; the size of the object is less than 4!  Type 'st' to see stack.\n\0"
  362. ErrorMess9:
  363.     .ascii    "\nDuring an array copy, the two arrays have different sizes  (r1=target size, r3=source size)!  Type 'st' to see stack.\n\0"
  364. ErrorMess10:
  365.     .ascii    "\nDuring an array copy, a dynamic array does not have the correct size (r1=actual size, r2=expected size)!  Type 'st' to see stack.\n\0"
  366. ErrorMess11:
  367.     .ascii    "\nDuring an array index calculation, the index is either less than 0 or greater than or equal to the array size (r2=index)!  Type 'st' to see stack.\n\0"
  368. ErrorMess11a:
  369.     .ascii    "\nAttempt to use an uninitialized array!  Type 'st' to see stack.\n\0"
  370. ErrorMess12:
  371.     .ascii    "\nDuring the invocation of a nameless function, the function pointer was null!  Type 'st' to see stack.\n\0"
  372. ErrorMess13:
  373.     .ascii    "\nDuring the initialization of an array, a 'count' expression was zero or less (r1=count)!  Type 'st' to see stack.\n\0"
  374.     .align
  375. ErrorMess14:
  376.     .ascii    "\nWhile popping the Catch Stack, an error has occurred!  Type 'st' to see stack.\n\0"
  377. ErrorMess15:
  378.     .ascii    "\nAttempt to return from KPLUncaughtThrow!  Type 'st' to see stack.\n\0"
  379. ErrorMess16:
  380.     .ascii    "\nError 'UncaughtThrowError' has been thrown but not caught!  Type 'st' to see stack.\n\0"
  381. ErrorMess17:
  382.     .ascii    "\nAttempt to perform serial I/O while interrupts are not disabled!  Type 'st' to see stack.\n\0"
  383.     .align
  384.  
  385.  
  386.  
  387. ! =====================  printRuntimeError  =====================
  388. !
  389. ! Come here to print a runtime error message and die.
  390. ! On entry, r1 points to the message.
  391. !
  392. printRuntimeError:
  393.     call    stopInterrupts        ! suspend any thread switching
  394.     call    _putString        ! .
  395.     jmp    TerminateRuntime    ! Can't continue: invoke "debug"
  396.  
  397.  
  398.  
  399. ! =====================  stopInterrupts  =====================
  400. ! This routine is called when a runtime error occurs; we are planning to
  401. ! print a final error message and suspend execution.  The problem is that
  402. ! the running program may be an operating system with multiple threads.
  403. ! An interrupt could occur during the printing of the error message, causing
  404. ! a thread switch, which might result in incomplete or incorrect execution of
  405. ! the code to print the message.
  406. !
  407. ! This routine disables interrutps, so that the message can be printed safely.
  408. ! When this routine is called, interrupts may or may not be enabled.  Also we
  409. ! may or may not be in System mode, we cannot simply execute a "cleari" instruction.
  410. !
  411. ! This routine overwrites the syscall interrupt vector and then executes a
  412. ! syscall instruction.  This will have the effect of clearing the "I" bit and
  413. ! setting the "S" bit, achieving the desired effect.
  414. !
  415. ! Registers modified: none.
  416. !
  417. stopInterrupts:
  418.     bis    needToClear        ! If interrupts are disabled  &&
  419.     bsc    needToClear        ! .  we are in System mode
  420.     ret                !   return
  421. needToClear:                ! EndIf
  422.     push    r1            ! Save r1 and r2
  423.     push    r2            ! .
  424.     set    relAddr,r1        ! Move a rel addr of keepGoing into r1
  425.     load    [r1],r1            ! .
  426.     set    0xa1000000,r2        ! Add in "jmp" op code
  427.     or    r1,r2,r1        ! .
  428.     store    r1,[r0+0x00000034]    ! Store that jmp in the syscall vector
  429.     syscall    0            ! Execute a syscall trap
  430.  
  431. relAddr:
  432.     .word    (keepGoing-0x00000034)
  433.  
  434. keepGoing:
  435.     pop    r0            ! The interrupt pushed 3 words onto
  436.     pop    r0            ! .  the stack; get rid of them.
  437.     pop    r0            ! .
  438.     pop    r2            ! Restore r1 and r2
  439.     pop    r1            ! .
  440.     ret                ! return to caller
  441.  
  442.  
  443.  
  444. !
  445. ! Misc Floating-Point Constants
  446. !
  447. _PosInf:
  448.     .word    0x7ff00000
  449.     .word    0x00000000
  450. _NegInf:
  451.     .word    0xfff00000
  452.     .word    0x00000000
  453. _NegZero:
  454.     .word    0x80000000
  455.     .word    0x00000000
  456.  
  457.  
  458.  
  459. !
  460. ! Name of this file
  461. !
  462. SourceFileName:
  463.     .ascii    "Runtime.s\0"
  464.     .align
  465.  
  466.  
  467.  
  468. ! =====================  RuntimeStartup  =====================
  469. !
  470. ! Prepare for KPL program execution.  Initialize the stack pointer,
  471. ! print the "PROGRAM STARTING" message, and call the "main" function.
  472. !
  473. RuntimeStartup:
  474.     set    STACK_START,r15        ! Initialize the stack pointer
  475.     set    startupMessage,r1    ! Print start-up message
  476.     call    _putString        ! .
  477.                     ! Interrupts are initially disabled
  478.     call    _mainEntry        ! Call "_mainEntry"
  479.     jmp    RuntimeExit        ! Perform normal termination
  480. startupMessage:
  481.     .ascii    "====================  KPL PROGRAM STARTING  ====================\n\0"
  482.     .align
  483.  
  484.  
  485.  
  486. ! =====================  RuntimeExit  =====================
  487. ! external RuntimeExit ()
  488. !
  489. ! This routine prints the normal program termination message and
  490. ! never returns.  This routine is also callable from KPL code.
  491. !
  492. RuntimeExit:
  493.     call    stopInterrupts        ! suspend any thread switching
  494.     set    goodbyeMessage,r1    ! print message
  495.     call    _putString        ! .
  496.     jmp    TerminateRuntime    ! goto TerminateRuntime
  497. goodbyeMessage:
  498.     .ascii    "\n====================  KPL PROGRAM TERMINATION  ====================\n\0"
  499.     .align
  500.  
  501.  
  502.  
  503. !
  504. ! =====================  TerminateRuntime  =====================
  505. !
  506. ! Come here when there is nothing more that can be done.
  507. ! NOTE: Interrupts must be disabled before calling this routine, to
  508. ! prevent any further thread switching.
  509. !
  510. TerminateRuntime:
  511.     debug                ! Pop up to BLITZ Emulator command mode
  512.     set    noGoMessage,r1        ! Print "You may not continue"
  513.     call    _putString        ! .
  514.     jmp    TerminateRuntime    ! ... and repeat, if "go" is entered
  515. noGoMessage:
  516.     .ascii    "\nThe KPL program has terminated; you may not continue!\n\0"
  517.     .align
  518.  
  519.  
  520.  
  521. ! =====================  _putString  =====================
  522. ! This routine is passed r1 = a pointer to a string of characters, terminated
  523. ! by '\0'.  It prints all of them except the final '\0'.  The string is printed
  524. ! atomically by calling 'debug2'.
  525. !
  526. ! r1: ptr to string
  527. ! r2: ptr to string (saved version)
  528. ! r3: count
  529. ! r4: character 
  530. !
  531. ! Registers modified: none
  532. !
  533. _putString:
  534.     push    r1            ! save registers
  535.     push    r2            ! .
  536.     push    r3            ! .
  537.     push    r4            ! .
  538.     mov    r1,r2            ! r2 := ptr to the string
  539.     mov    0,r3            ! r3 := count of characters
  540. putStLoop:                ! loop
  541.     loadb    [r1],r4            !   r4 := next char
  542.     cmp    r4,0            !   if (r4 == '\0')
  543.     be    putStExit        !     then break
  544.     add    r1,1,r1            !   incr ptr
  545.     add    r3,1,r3            !   incr count
  546.     jmp    putStLoop        ! end
  547. putStExit:                ! .
  548.     mov    2,r1            ! perform upcall to emulator to
  549.     debug2                ! . do the printing
  550.     pop    r4            ! restore regs
  551.     pop    r3            ! .
  552.     pop    r2            ! .
  553.     pop    r1            ! .
  554.     ret                ! return
  555.  
  556.  
  557.  
  558. ! =====================  Cleari  =====================
  559. ! external Cleari ()
  560. Cleari:
  561.         cleari            ! set interrupts to DISABLED
  562.         ret            ! return
  563.  
  564.  
  565.  
  566. ! =====================  Seti  =====================
  567. ! external Seti ()
  568. Seti:
  569.         seti            ! set interrupts to ENABLED
  570.         ret            ! return
  571.  
  572.  
  573.  
  574. ! =====================  Clearp  =====================
  575. ! external Clearp ()
  576. Clearp:
  577.         clearp            ! turn off paging
  578.         ret            ! return
  579.  
  580.  
  581.  
  582. ! =====================  Setp  =====================
  583. ! external Setp ()
  584. Setp:
  585.         setp            ! turn on paging
  586.         ret            ! return
  587.  
  588.  
  589.  
  590. ! =====================  Clears  =====================
  591. ! external Clears ()
  592. Clears:
  593.         clears            ! switch from System to User mode
  594.         ret            ! return
  595.  
  596.  
  597.  
  598. ! =====================  Wait  =====================
  599. ! external Wait ()
  600. Wait:
  601.         wait            ! suspend CPU execution and wait for an interrupt
  602.         ret            ! return
  603.  
  604.  
  605.  
  606. ! =====================  getCatchStack  =====================
  607. ! external getCatchStack () returns ptr to CATCH_RECORD
  608. !
  609. ! This routine returns the value of r12, which points to the Catch-Stack.
  610. ! The Catch-Stack is a linked list of CATCH_RECORDs, possibly NULL.
  611. !
  612. ! NOTE:  Whenever we leave the body statements in a try (i.e., fall-thru,
  613. !        throw, or return), records from the catch stack will be popped and
  614. !        freed.  "getCatchStack" returns a pointer to a list of CATCH_RECORDs
  615. !        as it is when "getCatchStack" is called, so watch out that the caller
  616. !        does not use records after they are freed.
  617. getCatchStack:
  618.         store    r12,[r15+4]        ! put r12 in the result position
  619.         ret                ! return
  620.  
  621.  
  622.  
  623. ! =====================  MemoryZero  =====================
  624. ! external MemoryZero (p: ptr to void, byteCount: int)
  625. !
  626. ! This function is passed "p" = a pointer, and "byteCount" = the number
  627. ! of bytes.  It sets that block of memory to all zeros.  The byteCount may
  628. ! be zero or negative, in which case this routine zeroes nothing.  This
  629. ! routine performs no other error checking.
  630. !
  631. ! Here is the algorithm:
  632. !
  633. !      while byteCount > 0 && p asInteger % 4 != 0
  634. !        *(p asPtrTo char) = '\x00'
  635. !        p = p + 1
  636. !        byteCount = byteCount - 1
  637. !      endWhile
  638. !      while byteCount > 3
  639. !        *(p asPtrTo int) = 0
  640. !        p = p + 4
  641. !        byteCount = byteCount - 4
  642. !      endWhile
  643. !      if byteCount == 3
  644. !        *(p asPtrTo char) = '\x00'
  645. !        *((p+1) asPtrTo char) = '\x00'
  646. !        *((p+2) asPtrTo char) = '\x00'
  647. !      elseIf byteCount == 2
  648. !        *(p asPtrTo char) = '\x00'
  649. !        *((p+1) asPtrTo char) = '\x00'
  650. !      elseIf byteCount == 1
  651. !        *(p asPtrTo char) = '\x00'
  652. !      endIf
  653. !
  654. ! Register usage:
  655. !   r1 = p
  656. !   r2 = byteCount
  657. !   r3 = work reg
  658. !
  659. MemoryZero:
  660.         load    [r15+4],r1        ! r1 = arg1 (p)
  661.         load    [r15+8],r2        ! r2 = arg2 (byteCount)
  662. mzLoop1:                    ! LOOP:
  663.         cmp    r2,0            !   if byteCount <= 0 exit
  664.         ble    mzLoop2Test        !   .
  665.         and    r1,0x00000003,r3    !   tmp = p % 4
  666.         cmp    r3,0            !   if tmp == 0 exit
  667.         be    mzLoop2Test        !   .
  668.         storeb    r0,[r1]            !   *p = 0x00
  669.         add    r1,1,r1            !   p = p + 1
  670.         sub    r2,1,r2            !   byteCount = byteCount - 1
  671.         jmp    mzLoop1            ! ENDLOOP
  672. !        jmp    mzLoop2Test        ! LOOP
  673. mzLoop2:                    ! .
  674.         store    r0,[r1]            !   *p = 0x00000000
  675.         add    r1,4,r1            !   p = p + 4
  676.         sub    r2,4,r2            !   byteCount = byteCount - 4
  677. mzLoop2Test:
  678.         cmp    r2,3            !   if byteCount > 3 then repeat
  679.         bg    mzLoop2            !   .
  680.  
  681.         cmp    r2,3            ! if byteCount == 3
  682.         bne    mzTry2            ! .
  683.         storeb    r0,[r1]            !   *p = 0x00
  684.         storeb    r0,[r1+1]        !   *(p+1) = 0x00
  685.         storeb    r0,[r1+2]        !   *(p+2) = 0x00
  686.         ret                !   return
  687. mzTry2:        cmp    r2,2            ! else if byteCount == 2
  688.         bne    mzTry1            ! .
  689.         storeb    r0,[r1]            !   *p = 0x00
  690.         storeb    r0,[r1+1]        !   *(p+1) = 0x00
  691.         ret                !   return
  692. mzTry1:        cmp    r2,1            ! else if byteCount == 1
  693.         bne    mzDone            ! .
  694.         storeb    r0,[r1]            !   *p = 0x00
  695. mzDone:                        ! endif
  696.         ret                ! return
  697.  
  698.  
  699.  
  700. ! =====================  MemoryCopy  =====================
  701. ! external MemoryCopy (destPtr: ptr to void, srcPtr: ptr to void, byteCount: int)
  702. !
  703. ! This routine copies "byteCount" bytes of data from the memory area pointed
  704. ! to by "srcPtr" to the area pointed to by "destPtr".  The pointers and the
  705. ! byteCount do not have to be multiples of 4 and the count may be less than
  706. ! zero, in which case, nothing will be copied.  However, the memory areas must
  707. ! not overlap!  (This routine does not test for overlap and if they overlap, the
  708. ! wrong data may be copied.)
  709. !
  710. ! Here is the algorithm:
  711. !
  712. !      if (destPtr asInteger % 4 == 0) && 
  713. !         (srcPtr asInteger % 4 == 0)
  714. !        while byteCount > 3
  715. !          *(destPtr asPtrTo int) = *(srcPtr asPtrTo int)
  716. !          destPtr = destPtr + 4
  717. !          srcPtr = srcPtr + 4
  718. !          byteCount = byteCount - 4
  719. !        endWhile
  720. !      endIf
  721. !      while byteCount > 0
  722. !        *(destPtr asPtrTo char) = *(srcPtr asPtrTo char)
  723. !        destPtr = destPtr + 1
  724. !        srcPtr = srcPtr + 1
  725. !        byteCount = byteCount - 1
  726. !      endWhile
  727. !
  728. ! Register usage:
  729. !   r1 = destPtr
  730. !   r2 = srcPtr
  731. !   r3 = byteCount
  732. !   r4 = work reg
  733. MemoryCopy:
  734.         load    [r15+4],r1        ! r1 = arg1 (destPtr)
  735.         load    [r15+8],r2        ! r2 = arg2 (srcPtr)
  736.         load    [r15+12],r3        ! r3 = arg3 (byteCount)
  737.         and    r1,0x00000003,r4    ! if destPtr % 4 == 0
  738.         bne    mcDoBytes        ! .
  739.         and    r2,0x00000003,r4    ! .   and srcPtr % 4 == 0
  740.         bne    mcDoBytes        ! .
  741. mcWordLoop:                    !   LOOP:
  742.         cmp    r3,3            !     if byteCount <= 3 exit loop
  743.         ble    mcWordLoopExit        !     .
  744.         pop    [r2++],r4        !     *destPtr = *(srcPtr++)
  745.         store    r4,[r1]            !     .
  746.         add    r1,4,r1            !     destPtr = destPtr + 4
  747.         sub    r3,4,r3            !     byteCount = byteCount - 4
  748.         jmp    mcWordLoop        !   ENDLOOP
  749. mcWordLoopExit:                    !   .
  750. mcDoBytes:                    ! endif
  751. mcByteLoop:                    ! LOOP
  752.         cmp    r3,0            !   if byteCount <= 0 exit loop
  753.         ble    mcByteLoopExit        !   .
  754.         loadb    [r2],r4            !   *destPtr = *srcPtr
  755.         storeb    r4,[r1]            !   .
  756.         add    r1,1,r1            !   destPtr = destPtr + 1
  757.         add    r2,1,r2            !   srcPtr = srcPtr + 1
  758.         sub    r3,1,r3            !   byteCount = byteCount - 1
  759.         jmp    mcByteLoop        ! ENDLOOP
  760. mcByteLoopExit:                    ! .
  761.         ret                ! return
  762.  
  763.  
  764.  
  765. ! =====================  print  =====================
  766. ! external print (s: ptr to array of char)
  767. !
  768. ! This routine prints data directly and immediately to the output.  It is
  769. ! intended only for use in debugging the kernel; as such it bypass the serial
  770. ! I/O device entirely and uses the debug2 "back-door" to the virtual machine.
  771. ! It may be called from any code, including from within an interrupt handler.
  772. !
  773. ! This routine will print \n, \t, and any printable ASCII characters.
  774. ! It will print \n as "\r\n".  It will print everything else in the form "\xHH".
  775. print:
  776.         load    [r15+4],r2        ! Move the argument "s" into r2
  777.         pop    [r2++],r3        ! Move the count into r3 and incr ptr
  778.         mov    2,r1            ! Move function code into r1
  779.         debug2                ! Do the upcall
  780.         ret                ! Return
  781.  
  782.  
  783.  
  784. ! =====================  printInt  =====================
  785. ! external printInt (i: int)
  786. !
  787. ! This routine prints data directly and immediately to the output.  It is
  788. ! intended only for use in debugging the kernel.
  789. printInt:
  790.         load    [r15+4],r2        ! Move the argument "i" into r2
  791.         mov    1,r1            ! Move function code into r1
  792.         debug2                ! Do the upcall
  793.         ret                ! Return
  794.  
  795.  
  796.  
  797. ! =====================  printHex  =====================
  798. ! external printHex (i: int)
  799. !
  800. ! This routine prints data directly and immediately to the output.  It is
  801. ! intended only for use in debugging the kernel.
  802. !
  803. ! This routine will print the argument in the form "0x0012ABCD".
  804. printHex:
  805.         load    [r15+4],r2        ! Move the argument "i" into r2
  806.         mov    6,r1            ! Move function code into r1
  807.         debug2                ! Do the upcall
  808.         ret                ! Return
  809.  
  810.  
  811.  
  812. ! =====================  printChar  =====================
  813. ! external printChar (c: char)
  814. !
  815. ! This routine prints data directly and immediately to the output.  It is
  816. ! intended only for use in debugging the kernel.
  817. !
  818. ! This routine will print \n, \t, and any printable ASCII character.
  819. ! It will print \n as "\r\n".  It will print everything else in the form "\xHH".
  820. printChar:
  821.         loadb    [r15+4],r2        ! Move the argument "c" into r2
  822.         mov    3,r1            ! Move function code into r1
  823.         debug2                ! Do the upcall
  824.         ret                ! Return
  825.  
  826.  
  827.  
  828. ! =====================  printBool  =====================
  829. ! external printBool (b: bool)
  830. !
  831. ! This routine prints data directly and immediately to the output.  It is
  832. ! intended only for use in debugging the kernel.
  833. !
  834. ! This routine will print either "TRUE" or "FALSE".
  835. printBool:
  836.         loadb    [r15+4],r2        ! Move the argument "b" into r2
  837.         mov    5,r1            ! Move function code into r1
  838.         debug2                ! Do the upcall
  839.         ret                ! Return
  840.  
  841.  
  842.  
  843. ! =====================  _heapInitialize  =====================
  844. ! This routine is passed nothing and returns nothing.  It is called during
  845. ! startup to initialize the heap, as necessary.
  846. !
  847. ! This routine will perform an "upcall" to a routine written in KPL.
  848. !
  849. ! Registers modified: Same as any KPL function.
  850. !
  851. _heapInitialize:
  852.     jmp    _P_System_KPLSystemInitialize
  853.  
  854.  
  855.  
  856. ! =====================  _heapAlloc  =====================
  857. ! This routine is passed the number of bytes in r1.  It allocates that many bytes
  858. ! and returns a pointer to the area in r1.  It never returns NULL.  If there is
  859. ! insufficient memory, an error will be signalled.
  860. !
  861. ! This routine is called from code generated by the compiler.  It will perform
  862. ! an "upcall" to a routine written in KPL.
  863. !
  864. ! Registers modified: Same as any KPL function.
  865. !
  866. _heapAlloc:
  867.     push    r1                ! Prepare the argument
  868.     call    _P_System_KPLMemoryAlloc    ! Perform the upcall
  869.     pop    r1                ! Retrieve the result
  870.     ret
  871.  
  872.  
  873.  
  874. ! =====================  _heapFree  =====================
  875. ! This routine is passed a pointer in r1.  This should point to a block of
  876. ! memory previously allocated using "malloc" (not "alloc").  It returns
  877. ! this memory to the free pool for subsequent allocation.
  878. !
  879. ! This routine is called from code generated by the compiler.  It will perform
  880. ! an "upcall" to a routine written in KPL.
  881. !
  882. ! Registers modified: Same as any KPL function.
  883. !
  884. _heapFree:
  885.     push    r1                ! Prepare the argument
  886.     call    _P_System_KPLMemoryFree        ! Perform the upcall
  887.     pop    r1                ! Pop the argument
  888.     ret
  889.  
  890.  
  891.  
  892. ! =====================  _IsKindOf  =====================
  893. ! This routine is passed a pointer to an object in r1 and a pointer to
  894. ! a type descriptor in r2.  It determines whether that object "is a kind of"
  895. ! that type.  It returns either TRUE (0x00000001) or FALSE (0x00000000) in r1.
  896. !
  897. ! This routine is called from code generated by the compiler.  It will perform
  898. ! an "upcall" to a routine written in KPL.
  899. !
  900. ! Registers modified: Same as any KPL function.
  901. !
  902. _IsKindOf:
  903.     push    r2                ! Push arg 2
  904.     push    r1                ! Push arg 1
  905.     call    _P_System_KPLIsKindOf        ! Perform the upcall
  906.     pop    r1                ! Pop result
  907.     pop    r2                ! Pop arg 2
  908.     ret
  909.  
  910.  
  911.  
  912. ! =====================  _RestoreCatchStack  =====================
  913. ! This routine is passed a pointer to a CatchRecord in r4 (possibly NULL).
  914. ! This is the previous value of "CatchStackTop".  This routine pops the
  915. ! CatchStack (calling _heapFree for each record) until the top thing on
  916. ! the CatchStack is the record pointed to by r4.
  917. !
  918. ! Registers modified: Same as any KPL function.
  919. !
  920. ! This routine is called from code generated by the compiler.  It does this:
  921. !
  922. !    <<  load   <temp>, r4    THIS IS DONE IN THE COMPILED CODE >>
  923. !        r1 := r12 (CatchStack top ptr)
  924. !        r12 := r4
  925. !    loop:
  926. !        if r1 == r4 goto done
  927. !        if r1 == NULL goto _runtimeErrorRestoreCatchStackError
  928. !                             This would occur if we are asked to pop
  929. !                             the catch stack back to an earlier
  930. !                             state, but after popping records, we never
  931. !                             can get to the earlier state.  This might
  932. !                             happen if there is a compiler logic error
  933. !                             or if memory has gotten corrupted.
  934. !        load   [r1], r2
  935. !        push   r2
  936. !        push   r4
  937. !        free   (r1)
  938. !        pop    r4
  939. !        pop    r1
  940. !        goto   loop
  941. !    done:
  942. !
  943. _RestoreCatchStack:
  944.     mov    r12,r1                ! r1 = saved value of CatchStack top
  945.     mov    r4,r12                ! Save r4 as new CatchStack top
  946. _RestoreCatchStack_loop:            ! LOOP:
  947.     cmp    r1,r4                !   if r1 == r4 goto DONE
  948.     be    _RestoreCatchStack_done        !   .
  949.     cmp    r1,0                !   if r1 == NULL goto error
  950.     be    _runtimeErrorRestoreCatchStackError  !
  951.     load    [r1], r2            !   r2 = r1->next 
  952.     push    r2                !   save ptr to next record
  953.     push    r4                !   save target ptr (r4)
  954.     call    _heapFree            !   free the record pointed to by r1
  955.     pop    r4                !   restore target ptr (r4)
  956.     pop    r1                !   r1 = ptr to next record
  957.     jmp    _RestoreCatchStack_loop        !   goto LOOP
  958. _RestoreCatchStack_done:            ! DONE:
  959.     ret                    !   return
  960.  
  961.  
  962.  
  963. ! =====================  _PerformThrow  =====================
  964. ! This routine is passed r4 = an ErrorID (just a ptr to an error name string).
  965. ! It looks down the Catch Stack until it finds a CATCH_RECORD with a matching
  966. ! ErrorID.  Then it jumps to the corresponding catch code, using the ptr stored
  967. ! in the CATCH_RECORD.  It also restores the FP and SP to their saved values,
  968. ! which makes it possible to re-enter the suspended routine.
  969. !
  970. ! This routine does not free any CATCH_RECORDS.
  971. !
  972. ! When an error is thown, but not caught, this code will perform an upcall to
  973. ! the routine "KPLUncaughtThrow" in package "System".  That routine
  974. ! should print some info about the situation and then throw "UncaughtError".
  975. ! Thus, we should never be returning from the call.  (The user code may or may
  976. ! not catch "UncaughtError", but if this too is uncaught, this code will goto
  977. ! "_runtimeErrorFatalThrowError".)
  978. !
  979. ! Registers modified: Same as any KPL function.
  980. !
  981. ! This routine is called from code generated by the compiler.  It does this:
  982. !
  983. !     << r4 = errorID    THIS IS DONE IN THE COMPILED CODE >>
  984. !        r1 = r12 (ptr to record on top of CATCH STACK)
  985. !    loop:
  986. !          if r1 == NULL
  987. !            if r4 == "uncaughtException" goto _runtimeErrorFatalThrowError
  988. !            call KPLUncaughtThrow
  989. !            goto _runtimeErrorThrowHandlerHasReturned
  990. !          end
  991. !          if r1->errorID == r4 then break
  992. !          r1 = r1->next
  993. !        goto loop
  994. !        restore FP from r1->oldFP
  995. !        restore SP from r1->oldSP
  996. !        jump to r1->catchCode
  997. !
  998. _PerformThrow:
  999.     mov    r12,r1                ! r1 = r12 (CatchStack top ptr)
  1000. _PerformThrow_loop:                ! LOOP:
  1001.     cmp    r1,0                !   if r1 == NULL
  1002.     bne    _PerformThrow_else        !   .
  1003.     set    _Error_P_System_UncaughtThrowError,r2 ! if r4 == "UncaughtThrowError"
  1004.     cmp    r2,r4                !       .                
  1005.     be    _runtimeErrorFatalThrowError    !       goto runtime error
  1006.     load    [r14+-8],r1            !     Push ptr to current rout. desc.
  1007.     push    r1                !     .
  1008.     push    r13                !     Push the current line number
  1009.     push    r4                !     Push ptr to error name
  1010.     call    _P_System_KPLUncaughtThrow    !     call KPLUncaughtThrow
  1011.     pop    r4                !     retore regs
  1012.     pop    r13                !     .
  1013.     pop    r1                !     .
  1014.     jmp    _runtimeErrorThrowHandlerHasReturned  ! goto runtime error
  1015. _PerformThrow_else:                !   end
  1016.     load    [r1+4],r3            !   r3 = errorID of this record
  1017.     cmp    r3,r4                !   if it matches r4
  1018.     be    _PerformThrow_found        !     goto FOUND
  1019.     load    [r1],r1                !   r1 = r1->next
  1020.         jmp     _PerformThrow_loop        !   goto LOOP
  1021. _PerformThrow_found:                ! FOUND:
  1022.     load    [r1+8],r2            !   r2 = catch code ptr
  1023.     load    [r1+12],r14            !   Restore FP
  1024.     load    [r1+16],r6            !   Save the new SP in r6
  1025.     jmp    r2                !   jump to catch code
  1026.  
  1027.