-----------------------------
-- Lec-1-HW-3-OSbase.html
-----------------------------
What to turn in:
Check in your source code to your branch. Bring a written summary of your
progress and difficulties to class on the due date, with the usual 
information (Name, Course Title, HW Title, date).

Included in this document (see below) are source code text for two assembly 
language programs:

    os.asm   -- The starting base for you OS.
   usr.asm   -- A user program the OS jumps to, and provides services for.

Cut and paste these into files in your /src2, and svn add
them to your branch.

The task is to get the PUTC trap routine working, and have the
user program use it to display a character. In the interests of
simplicity, I have changed the base code to be all in one file, and
the macros are reduced to just a couple. The macros are included in
the source .asm code to simplify processing. You can, of course,
rearrange these as you like, and define new macros following the
pattern of the macros in os.asm. Be warned that editing the macros
can be very mysterious. I had a bug which could not be seen in the
text. The only way I got it working was to copy/paste from another
macro definition, and carefully change one character at at time,
testing each time to see if it still worked.

We will be using PennSim.jar for both assembly and simulation. The
command line in PennSim is the narrow window just below the "Next"
button. The two commands we will use are "as", assemble, and "ld",
load. We will pre-process our source code w/ m4. So, we will do
the following after editing our source code:

    cat os.asm | m4 > oss.asm
    cat usr.asm | m4 > usrr.asm

which expands all the macros in os.asm. You might want to put a few 
lines in your Makefile for this:

 all:
	make oss.asm
	make usrr.asm

 oss.asm: os.asm
	cat os.asm | m4 > oss.asm
 usrr.asm: usr.asm
	cat usr.asm | m4 > usrr.asm


Then, do "make all" to do the pre-processing. Next, we will assemble 
and load using PennSim's command line. Start PennSim in the directory
where you have os.asm and usr.asm. You will have to copy PennSim.jar
to that directory and double click it (or java -jar). Using PennSim's
command line window (just below the "Next" button) do,

    as oss.asm
    ld oss.obj
    as usrr.asm
    ld usrr.obj

Setting PennSim's PC = x0200, we execute our program using "Step".
The OS starts booting. When that is done, the OS jumps to the user
program. When the user program is finished, it returns to the OS via
TRAP x25 (HALT). The HALT routine simply reboots the OS. If you want
the program to run without Step'ing through it, place a breakpoint at
the start of HALT, for instance, and use "Continue."

You may use any LC3 instructions you care to. There is no restriction on
using LD, LDI, ST, STI, JSR, JSRR, or TRAP. However, it is probably a
good idea to comform to the convention of using the DATA table to call
subroutines and store all data constants and variables.

Refering to the DATA table's offsets, the macros for these have been
placed at the top of the source code files and the DATA segment has been
placed as it normally would be, at the bottom. Add to the offset macros
as you add new items to the data segments. The macros for the user
program and the OS will be different as the two data segments are in
different memory locations and contain different information.
The stack segments are also not the same. Therefore, the user must, as
a first step, reset the stack and data pointers to its own areas.


WHAT PUTC DOES

PUTC (i.e., TRAP x21, aka "OUT") receives as its argument an ASCII character 
code in the low byte of R0 (the upper byte is ignored). PUTC then
polls the display's status register, DSR (at address xFE04) to see if
its ready bit (DSR[15]) is 1. If it is, the display is ready to receive
a character to display, and the character is written to the data register,
DDR (xFE06). The caller has provided a return address in R7; so, PUTC
simply does JMP R7 (aka, RET) to exit.

The user progam does the following:

   -- loads R0 with a character code
   -- TRAP x21

The character code would be stored in the user's data segment.
For instance,

    DATA:
      ...
      .FILL x0061   ;-- 'a'
      ...

and loaded into a register, e.g., R0:

    ldr R0, GDP__, #char_a__

where char_a__ has been defined in a macro as the table offset to
that data table entry for 'a'.

REFERENCES:

LC3trunk/docs/LC3-3-PP-Append-A.pdf
LC3trunk/docs/LC3-4-Assembly-Manual.pdf
LC3trunk/docs/LC3-4-Assembly-CheatSheet
LC3trunk/docs/LC3-4-Assembly-ASCII.html
LC3tools/PennSim_Manual.pdf

SOURCE CODE:

##################################################################
### os.asm (begins on next line) #################################

changecom(`;',)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; os.asm
;; 
;; This code uses m4 macro definitions.
;; You must pre-preocess this w/ m4, e.g.:
;;
;;   cat os.asm | m4 > os_pre.asm
;;
;; The m4 definitions follow this header. The "changecom" at the
;; top tells m4 we are using ";" as our comment delimiter.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;; BEGIN Macro Defs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;

define(`GDP__',`R4')dnl
define(`BP__',`R5')dnl
define(`SP__',`R6')dnl
define(`push__',`
   ADD SP__, SP__, #-1
   STR $1, SP__, #0')dnl
define(`pop__',`
   LDR $1, SP__, #0
   ADD SP__, SP__, #1')dnl

;------ DATA table offset definitions.
define(`CODE__',                 `0')dnl
define(`STACK__',                `1')dnl
define(`HALT_vect__',            `2')dnl 
define(`HALT_init__',            `3')dnl
define(`HALT_begin__',           `4')dnl
define(`USR_CODE__',             `5')dnl

;;;;;;;;;;; END Macro Defs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;


   .ORIG x0200

;================================================
; Code Segment
;================================================
CODE:

;-------------------------------------------
;-- OS initialization ----------------------
;-------------------------------------------

   ;---------------------------------
   ; Set up GDP
   ;---------------------------------
   LEA GDP__, DATA_PTR    ;-- GDP gets address of pointer.
   LDR GDP__, GDP__, #0   ;-- GDP gets pointer to DATA.
   BR L1                  ;-- Jump over local data.
DATA_PTR: .FILL DATA      ;--
L1:

   ;---------------------------------------
   ; Set up statck.
   ;---------------------------------------

   LDR SP__, GDP__, #STACK__
   LDR BP__, GDP__, #STACK__

   ;---------------------------------------
   ; Set up Vector Table
   ;---------------------------------------
   JSR HALT_init


;-------------------------------------------
;-- OS main --------------------------------
;-------------------------------------------
main:

   LDR R7, GDP__, #USR_CODE__   ;-- get user's code address,
   JMP R7                       ;-- go to user's code (returns via HALT)

;----------------------------------------
;-- Service Routines --------------------
;----------------------------------------
   
   ;----------------------------------------
   ;-- HALT_init
   ;----------------------------------------
HALT_init:
   LDR R0, GDP__, #HALT_vect__  ;-- Get VT slot address.
   LDR R1, GDP__, #HALT_begin__ ;-- Get HALT's address.
   STR R1, R0, #0               ;-- Load the VT slot.
   JMP R7

   ;----------------------------------------
   ;-- HALT, TRAP x25
   ;-- User program's exit and return to OS.
   ;-- Restarts the OS. Cannot trust the values of
   ;-- GDP, SP, or BP. User may have altered them.
   ;----------------------------------------
HALT_begin:
   LEA R7, HALT_data  ;-- get pointer
   LDR R7, R7, #0     ;-- get data
   JMP R7             ;-- jump (reboot)
HALT_data: .FILL CODE

   
;================================================
; Data Segment
; NOTE: m4 macros define table offsets. The definitions
; cannot be used above where they are defined. That's why
; They are defined at the top of this file.
;================================================
DATA:
    ;--- content ------------------ offset name
   .FILL CODE                   ;-- CODE__
   .FILL x3000                  ;-- STACK__
   .FILL x0025                  ;-- HALT_vect__
   .FILL HALT_init              ;-- HALT_init__
   .FILL HALT_begin             ;-- HALT_begin__
   .FILL x3000                  ;-- USR_CODE__

   .END

## END of os.asm (ends on line above) ##########################
################################################################

##################################################################
### usr.asm ( begins next line) ##################################

changecom(`;',)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; usr.asm
;; 
;; This looks initially just like os.asm, however
;; it is assembled separately. Labels turn into addresses.
;; The .ORIG is x3000. The addresses will be different.
;; It has its own CODE and DATA and STACK segments. They are 
;; not shared with the OS code. The user has to initialize the
;; GDP, SP, and BP to point to its own segments.
;; The user uses the OS services by jumping via TRAP. The user 
;; code does not know what the OS service routine's addresses 
;; are at runtime.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;; BEGIN Macro Defs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
define(`GDP__',`R4')dnl
define(`BP__',`R5')dnl
define(`SP__',`R6')dnl
define(`push__',`
   ADD SP__, SP__, #-1
   STR $1, SP__, #0')dnl
define(`pop__',`
   LDR $1, SP__, #0
   ADD SP__, SP__, #1')dnl

;------ DATA table offset definitions.
define(`CODE__',                 `0')dnl
define(`STACK__',                `1')dnl
;;;;;;;;;;; END Macro Defs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;

   .ORIG x3000

;================================================
; Code Segment
;================================================
CODE:

   ;---------------------------------
   ; Set up GDP
   ;---------------------------------
   LEA GDP__, DATA_PTR    ;-- GDP gets address of pointer.
   LDR GDP__, GDP__, #0   ;-- GDP gets pointer to DATA.
   BR L1                  ;-- Jump over local data.
DATA_PTR: .FILL DATA      ;--
L1:

   ;---------------------------------------
   ; Set up statck.
   ;---------------------------------------

   LDR SP__, GDP__, #STACK__
   LDR BP__, GDP__, #STACK__


;-------------------------------------------
;-- main --------------------------------
;-------------------------------------------
main:

   TRAP x25   ; HALT, return to OS

;================================================
; Data Segment
; NOTE: m4 macros define table offsets. The definitions
; cannot be used above where they are defined. That's why
; They are defined at the top of this file.
;================================================
DATA:
    ;--- content ------------------ offset name
   .FILL CODE                   ;-- CODE__
   .FILL xFE00                  ;-- STACK__

   .END

## END of usr.asm (ends on line above) #########################
################################################################