*****************************************************************
*                                                               *
*               UNIX Low-memory Initialization                  *
*                                                               *
*               Perkin-Elmer 7/32, 8/32, 3220, 3240             *
*                                                               *
*               (C) 1980, Richard Miller                        *
*                   University of Wollongong                    *
*                                                               *
*****************************************************************

	entry   ii.psw,dat.psw
	entry   mm.npsw,mm.opsw
	extrn   start,dump
	extrn   call,trap,devint,handler,devmap
    ifnz PIC
	extrn   sytim
    endc

* PSW bit definitions

ps.flm  equ     y'40000'        floating-point masked (3200)
ps.iip  equ     y'20000'        interruptible instruction in progress (3200)
ps.wait equ     x'8000'         wait state
ps.io   equ     x'4000'         immediate interrupt mask
ps.mm   equ     x'2000'         machine malfunction interrupt mask
ps.af   equ     x'1000'         arith fault interrupt mask
ps.il   equ     x'0800'         multi level interrupts (8/32 & 3200)
ps.rp   equ     x'0400'         memory relocation / protection
ps.sq   equ     x'0200'         system queue service mask
ps.prot equ     x'0100'         protect mode
ps.ureg equ     x'00f0'         user register set

* PSW definitions

ps.user equ     ps.io+ps.mm+ps.af+ps.rp+ps.prot+ps.ureg
ps.idle equ     ps.wait+ps.io+ps.mm+ps.af+ps.rp+ps.ureg
ps.kern equ     ps.io+ps.mm+ps.af+ps.rp+ps.ureg
ps.disb equ     ps.mm+ps.af+ps.rp+ps.ureg
ps.trap equ     ps.mm+ps.af

* Register definitions

r0      equ     0
r1      equ     1
r2      equ     2
r3      equ     3
r4      equ     4
r5      equ     5
r6      equ     6
r7      equ     7
r8      equ     8
r9      equ     9
ra      equ     10
rb      equ     11
rc      equ     12
rd      equ     13
re      equ     14
rf      equ     15
sp      equ     r7

*****************************************************************
*                                                               *
*                  Reserved Locations                           *
*                                                               *
*       The following code must be loaded into fixed locations  *
*       in physical low memory determined by the P-E hardware.  *
*       Since the UNIX loader does not handle absolute code, it *
*       must be faked as 'pure'.                                *
*                                                               *
*****************************************************************

	pure
low     equ     *               Physical location 0

* Trap PSW's and pointers

	das     8               00  floating-point regs (7/32)
mm.opsw das     2               20  machine malfunction old psw
	das     1               28        -
	das     1               2C  machine malfunction LM address (3200)
	dc      ps.trap         30  illegal instruction new psw
	dc      trap.ii
mm.npsw equ     *
    ifnz M3200
	dc      ps.mm           38  machine malfunction new psw
    else
	dc      0               38  machine malfunction new psw
    endc
	dc      trap.mm
mm.stat das     1               40  machine malfunction status word (3200)
	das     1               44  machine malfunction program address (3200)
	dc      ps.trap         48  arith fault new psw
	dc      trap.af

* Bootstrap Loader information

	al      x'cf'           50  '50-sequence' loader
	b       x'80'           54  branch to bootstrap record

	org     low+x'60'
	b       start           60  LSU start address
	b       dump            66  dump start address

* Pointers and PSW's

	org     low+x'80'
	dc      0               80  &(system queue)
    ifnz M3200
	dc      pf.save         84  &(power-fail save area)
    else
	dc      z(pf.psw)       84  &(power-fail psw save area)
	dc      z(pf.regs)      86  &(power-fail reg save area)
    endc
	dc      ps.trap         88  system queue service new psw
	dc      trap.sq
	dc      ps.trap         90  relocation fault new psw
	dc      trap.mf

* SVC table

	dc      ps.trap         98  SVC new psw status
	dc      z(trap.svc)             svc 0 - Version 7 system call
	dc      z(trap.isv)             svc 1
	dc      z(trap.isv)             svc 2
	dc      z(trap.isv)             svc 3
	dc      z(trap.isv)             svc 4
	dc      z(trap.isv)             svc 5
	dc      z(trap.isv)             svc 6
	dc      z(trap.isv)             svc 7
	dc      z(trap.isv)             svc 8
	dc      z(trap.isv)             svc 9
	dc      z(trap.isv)             svc 10
	dc      z(trap.isv)             svc 11
	dc      z(trap.isv)             svc 12
	dc      z(trap.isv)             svc 13
	dc      z(trap.osv)             svc 14 - Version 6 system call
    ifnz PIC
	dc      z(trap.tim)             svc 15 - quick and dirty access to PIC
    else
	dc      z(trap.isv)             svc 15
    endc

	org     low+x'BC'
	das     3               BC              -
    ifnz M3200
	dc      ps.trap         C8  data format fault new psw
	dc      trap.dat
    else
	das     2               C8              -
    endc

* Interrupt Service Pointer table

	entry   isp
isp     equ     *               D0  interrupt service pointer table
	nlist
	do      NDEVS
	dc      z(interupt)
	list
*       do      NDEVS
*       dc      z(interupt)             listing suppressed

* Memory Access Controller registers ( except 3240 )

    ifz M3240
	org     *-low+255&y'ffffff00'+low       (align 256 )
	entry   macregs
macregs equ     *               300 / 500 / 900, depending on NDEVS
	das     16              MAC segmentation registers
mac.rs  das     1               MAC status register ( 7/32 and 8/32 only )
	org     *-low+255&y'ffffff00'+low       ( align 256 )
    endc

*********************************************************
*                                                       *
*               Hardware-Dependent Areas                *
*                                                       *
*       Locations of the following code are not fixed,  *
*       but because of addressing or alignment must be  *
*       in the first 64K segment of physical memory.    *
*                                                       *
*********************************************************

* Power-fail save areas

	align   adc*2
pf.save equ     *               power-fail save area
pf.psw  das     2               psw
    ifz M3200
pf.regs das     8*16            general registers (2 sets)
    else
pf.regs das     8*16            general registers (8 sets)
	das     16              scratchpad registers
    endc
    ifnz FPREGS!DPREGS
pf.fpr  das     24              floating-point registers
    endc

* MAC segmentation registers ( except 3240 )
*       To establish address mapping, the user or kernel seg regs are
*       copied into the hardware MAC registers.

    ifz M3240
	align   adc
	entry   kisa0,useg,uisa0
kisa0   das     16              kernel mode segmentation registers
useg    equ     *-4             segmentation register for u area
uisa0   das     16              user mode segmentation registers
	align   adc

kst     dc      a(macregs-low*y'10000'+kisa0)    kernel seg table descriptor
ust     dc      a(macregs-low*y'10000'+uisa0)    user seg table descriptor
    endc

* MAT segment tables ( 3240 only )
*       To establish address mapping, a pointer to the user or kernel
*       seg regs is loaded into the hardware Segment Table Descriptor

    ifnz M3240
	entry   kisa0,useg,uisa0
	org     *-low+127&y'ffffff80'+low       ( align 128 )
kisa0   das     512              kernel mode segment table
useg    equ     *-8             segment table entry for u area
	org     *-low+127&y'ffffff80'+low       ( align 128 )
uisa0   das     512              user mode segment table
	org     *-low+127&y'ffffff80'+low       ( align 128 )
kiss0   dc      0,0             dummy kernel shared segment table
	org     *-low+127&y'ffffff80'+low
uiss0   dc      0,0             dummy user shared segment table
	align   adc

kst     dc      a(kisa0-low/128+y'1fe0000')      kernel seg table descriptor
	dc      a(kiss0-low/128)
ust     dc      a(uisa0-low/128+y'1fe0000')      user seg table descriptor
	dc      a(uiss0-low/128)
    endc

* Pointers to segment descriptors, for use in calls to addrsw and lraddr

	align   adc
	entry   kisa,uisa
kisa    dc      a(kst)          pointer to kernel seg descriptor
uisa    dc      a(ust)          pointer to user seg descriptor

* Auto-driver 'channel' control blocks

	align   adc
	entry   ccb
ccb     equ     *
	nlist
	do      NCCB
	dc      0,0,0,0,0,z(autod),x'0'
	list
*       do      NCCB
*       dc      0,0,0,0,0,z(autod),x'0'         listing suppressed

*********************************************************
*                                                       *
*               Trap Transfer Vector                    *
*                                                       *
* Initial entry from microcode on all interrupts        *
*                                                       *
*********************************************************

* Machine malfunction

	align   adc
trap.mm equ     *
    ifnz M3200
	l       r0,mm.stat      get reason code
	ti      r0,y'38000000'  memory parity error?
	bnz     trap.mp
	ti      r0,y'07000000'  non-configured memory error?
	bnz     trap.mf
    else
	btc     6,trap.mp
    endc
	lm      re,mm.opsw      get saved old psw
	bal     r6,trapx
	dc      h'4'

* Memory parity error

	align   adc
trap.mp equ     *
	lm      re,mm.opsw      get saved old psw
	bal     r6,trapx
	dc      h'0'

* Arithmetic fault

	align   adc
trap.af equ     *
    ifnz M3200
	ti      re,ps.af        floating-point underflow masked off?
	bnz     af1               no - take interrupt
	lr      rf,rc             yes - ignore all arithmetic faults
	lpswr   re                      (i.e. same as 7/32)
af1     equ     *
    endc
	bal     r6,trapx
	dc      h'8'

* Segmentation fault

	align   adc
trap.mf equ     *
    ifz M3200
	lis     r0,0
	st      r0,mac.rs               clear mac status register
    endc
	bal     r6,trapx
	dc      h'9'

* Illegal instruction / protect mode

trap.ii equ     *
	stm     re,ii.psw
	bal     r6,trapx
	dc      h'1'
	align   adc
ii.psw  dc      0,0     illegal instruction old psw.

* Supervisor Call

trap.isv equ    *               illegal supervisor call
	bal     r6,trapx
	dc      h'10'

trap.osv equ    *               Version 6 supervisor call
	ai      rd,x'100'       set flag for trap()
trap.svc equ    *               Version 7 supervisor call
	bal     r6,trapx
	dc      h'6'

    ifnz        PIC
trap.tim equ    *       quick and dirty access to precision clock values

*       return in user r0 the current value of
*       sytim , utime , or itime
*       user must supply in r1 one of 0,4,8 to get
*       the corresponding value of the above

	stm     re,nr.psw       save old psw for quick return
	epsr    rc,rc           current ps
	ohi     rc,ps.ureg      switch to user regs
	epsr    r0,rc
	ni      r1,x'c'         make sure offset is legal
	l       r0,sytim(r1)    load requested time value
	lpsw    nr.psw          exit quickly without telling anyone

	align   adc*2
nr.psw  das     2               space to save psw
    endc

* System queue service ( should never happen )

trap.sq equ     *
	bal     r6,trapx
	dc      h'4'

* Data format fault ( 3200 only )

    ifnz M3200
trap.dat equ    *
	stm     rc,dat.psw
	bal     r6,trapx
	dc      h'13'
    endc
	align   adc
dat.psw dc      0,0,0,0

* Common trap routine - get reason code & status and go to C trap routine

trapx   equ     *
	lr      r3,rd           'stat' is effective arg address (SVC) etc.
	lh      r2,0(r6)        get trap code
	epsr    rd,rd           current psw
	li      rb,ps.kern      new psw: kernel mode, enabled
	la      rc,trap
	b       call            go call c trap handler

* I/O Interrupt - get address of C interrupt handler and go to it

autod   equ     *               entry from auto-driver 'channel'
	bnm     autod1          L bit in condition code ?
	oi      r3,x'100'         yes - bad status
	b       autod2
autod1  bnp     autod2          G bit in condition code ?
	oi      r3,x'200'         yes - buffer limit
autod2  equ     *               fall through to interrupt code

interupt equ    *               entry from immediate interrupt
	lb      rc,devint(r2)   handler table offset
	l       rc,handler(rc)  address of C interrupt handler
	lb      r2,devmap(r2)   minor device number
	lr      re,r0           move psw to correct regs
	lr      rf,r1
	epsr    rd,rd           current psw
	nhi     rd,x'ffff'-ps.il        all interrupt levels off ( 3200 )
	epsr    r0,rd
	li      rb,ps.disb      new psw: kernel mode, disabled
	b       call            go call c interrupt-handler
	align   adc
	db      c'@(#)L.s	2.2.1.4',0
	entry   consaddr,conscmd2
consaddr db     y'10'           device address of 'system console'
conscmd2 db     x'ee'           pals command 2 for 'system console'

	pure
	align adc*2
	impur
	align adc*2

