DataMuseum.dk

Presents historical artifacts from the history of:

CP/M

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about CP/M

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download

⟦aaf85b54e⟧ TextFile

    Length: 92544 (0x16980)
    Types: TextFile
    Names: »SYSCALLS.SS«

Derivation

└─⟦909f4eb2b⟧ Bits:30009789/_.ft.Ibm2.50006622.imd Mogens Pelles Zilog 80,000 / EOS projekt
    └─⟦this⟧ »SYSCALLS.SS« 
└─⟦ddcd65152⟧ Bits:30009789/_.ft.Ibm2.50006617.imd Mogens Pelles Zilog 80,000 / EOS projekt
    └─⟦this⟧ »SYSCALLS.SS« 

TextFile

ø eos version of unix system calls
ø written by Vilhelm Rosenqvist and Peter Mikkelsen 1983
ø
ø the function names exported below are sorted by their
ø 'UNIX system call number'
ø the labels appear in the systable at the end of this text
ø
  .globl __exit,_fork,_read,_write,_open          ø 01-05
  .globl _close,_wait,_creat,_link,_unlink        ø 06-10
  .globl _exec,_chdir,_time,_mknod,_chmod         ø 11-15
  .globl _chown,_brk,_stat,_lseek,_getpid         ø 16-20
  .globl _mount,_umount,_setuid,_getuid,_stime    ø 21-25
  .globl _ptrace,_alarm,_fstat,_pause,_utime      ø 26-30
  .globl _stty,_gtty,    _access,_nice,_ftime     ø 31-35
  .globl _sync,_kill                              ø 36-40
  .globl _dup,_pipe,_times,_profil,_locking       ø 41-45
  .globl _setgid,_getgid,_signal                  ø 46-50
  .globl _acct,_phys,_lock,_ioctl                 ø 51-55
  .globl _mpxchan,             _execve,_umask     ø 56-60
  .globl _chroot                                  ø 61-65
  .globl _outline,_inpline,_putl,_getl,_gethc     ø 66-70 these numbers are
  .globl _get1b,_put1b,_macsbug                   ø 71-75  assigned
  .globl _sbrk,_dup2                              ø 76-80  by eos
  .globl _setmem                                  ø 64+17=81,  17=break
ø
ø run time variables in the .data section follows
ø
  .data
ø constants containing error codes:
eperm=1
enoent=2
esrch=3
eintr=4
eio=5
enxio=6
e2big=7
enoexec=8
ebadf=9
echild=10
eagain=11
enomem=12
eacces=13
efault=14
enotblk=15
ebusy=16
eexist=17
exdev=18
enodev=19
enotdir=20
eisdir=21
einval=22
enfile=23
emfile=24
enotty=25
etxtbsy=26
efbig=27
enospc=28
espipe=29
erofs=30
emlink=31
epipe=32
edom=33
erange=34
edeadlock=35
ø
ø unix signal constants
sighup=1
sigint=2
sigquit=3
sigill=4
sigtrap=5
sigiot=6
sigemt=7
sigfpe=8
sigkill=9
sigbus=10
sigsegv=11
sigsys=12
sigpipe=13
sigalrm=14
sigterm=15
 
sig_dfl=0
sig_ign=1
 
ø* stat record:
  st_dev        =0
  st_ino        =2
  st_mode       =4
  st_nlink      =6
  st_uid        =8
  st_gid        =10
  st_rdev       =12
  st_size       =14
  st_atime      =18
  st_mtime      =22
  st_ctime      =26
ø various constants used in the run time system:
eos=7
obj_call=0
obj_return=1
dealloc=7
hexop=0x00020028  ø print memory in hex
zero_act=22  ø size of obj call arg list with zero actuals
one_act=36   ø ------------------------------- one actual
two_act=50
dealarg=22   ø --------dealloc ---------------zero actuals
pagemask=0777   ø pagesize:= 512 (= 9 bits)
orgsys=0x000C0000   ø unix C-runtime system
pipename_size=48
pathname_size=64
øerror constants
  appl=0x0700         ø application family
  univers=0           ø universal family
  entry_ill=univers+0xfe
  data_ill=univers+0xf9
  proc_space_lim=univers+12
  give_up=univers+18
  no_resources=univers+22
  pipe_broken=11   ønot achitected cause from pipesys
  header_fe=univers+0xfd
øaux causes
  text_too_long=  0x0100  øpathname too long
  red_overflow=   0x0200  østack overflow during exception
  yellow_overflow=0x0300  øattempt to extend stack failed
get_ref=2
ø i/o family constants
  iofam=0x0400
  assign_entry=1
  creat_link_entry=4
  del_link_entry=5
  fstat_entry=17
  getfileinf=7
  readseq=1
  writeseq=2
  seek=5
  datasize=13
  waitready=15
  dup_entry=16
  neworold=0
  oldfile=1
  newfile=2
  no_right=0
  read_right=1
  write_right=2
  breakstatus=iofam+10
  breakreject=iofam+0xF6
ø entries in the emulator
   prepexec_entry=1
   forkbegin_entry=2
   forkend_entry=3
   wait_entry=4
   pause_entry=5
   alarm_entry=6
   sigsag_entry=7
   setgetid_entry=8
   getunique_entry=9
øsignal constants
   getsigstate=1
   setsigstate=2
   receive_sig=3
   sendsig=4
   sendsig_to_self=5
 
ø* entries in the clock object
  gettime_entry=1
  settime_entry=2
 
stack_mmu=0
code_mmu=1
data_mmu=2
work_mmu=3
work_addr=0x400000
in_ptr=1
out_ptr=2
rwe=7
ø propagate modes
   propreject=1
   propstop=0
   enable_except=3*4
   disable_except=0
ø kernel call constants
   map_call=33
   map_args=12
   prop_call=23
   prop_args=4
   tspeed_call=24
   tspeed_args=4
   copy_call=13
   copy_args=8
ø
ø a unix context consists of the following pointers
fml=0
temp=0x4000
local=0x8000
øtemporary pointers
  stack=temp+1
  work_ptr=temp+2
  fs_ref=temp+3 ø return pointer from get_ref, points to a file system
  work2_ptr=temp+3
ø formal pointers
   ff_env=0x00010001 ø Æf,1,fildesÅ
   emulator_ref=fml+2
   execargs_ref=fml+3
   oldstack_ref=fml+4
   olddata_ref=fml+5
ø local pointers
   code=local+1
   localdata=local+2
   objdir=local+4
   sched_ref=local+5
   alloc_ref=local+6
   clock_ref=local+7
   øego_env=local+8
local_1=local+1
legal_items=0x1C ø ...111..  a one indicates a legal return pointer kind
 
  .globl _etext,_edata,_end ø import symbol values from linker
  .globl _environ,_errno,_erreos  ø global variables
  .globl _erreoslo,_erreoshi
  .globl f_stk,f_data,top_text,top_bss ø used by cexappl
  .globl _testflag  ø0 means no testoutput
  .globl _clexflags øclose-on-exec bitmask
_environ: .long 0
_errno:   .long 0
_erreos:
_erreoslo: .long 0   ø holds d6/d7 after error calls
_erreoshi: .long 0
_eoscrtt: .long 0    ø test mask for the runtime system.
ø first byte : bit0=1: print stack before severe error return (prireturn)
ø              bit1=1: print stack when unimplemented syscalls are called
ø              bit2=1: print input/output buffers
ø              bit3=1: print calls to the kernel
ø
ø the following three _top_ values should (also) be present in the text
ø section when text and data segments are separate (reentrant programs)
ø because the values are needed to map the data segment.
top_text:  .long _etext  ø top of program = first of data
f_data:    .long 0       ø first of data segment
top_data:  .long _edata  ø top of initialised  data = first of bss
top_bss:   .long _end    ø top of bss, grows when _brk/_sbrk is called
ø
f_stk: .long 0             ø points to the first byte of the stack segment
f_valdata: .long 0         ø points to the first byte of the valdata
t_stk: .long 0             ø points to the firt byte after the stack segm.0
bsmax: .long 0             ø points to the top byte of the local data segment
                           ø _top_bss cannot grow beyond this value. at present
                           ø bsmax is fixed by the load format converter
                           ø program  and communicated via
                           ø long(5) in the text header (sym_size in ld)
 
fork_stackptr: .long 0     ø holds stack pointer across fork
fork_childid: .long 0
 
file_root: .long 0,0,0,0,0,0,0,0,0,0,0,0  ø file root name
top_file_root:
pipe_root: .long 0,0,0,0,0,0,0,0,0,0,0,0  ø pipe root name
top_pipe_root:
cur_work_dir: .long 0,0,0,0,0,0,0,0,0,0,0,0 ø current work dir name
top_cur_wd:
used_fildes: .long 0xE0000000 ø keeps track of pointers in the file envelope:
                           ø pointer Æfml,1,xÅ is free if bit 32-x equals zero
                           ø and Æfml,1,xÅ = nil pointer. in the demo version
                           ø the bit mask allone is trusted and the initial
                           ø value reserves  input,output,error_output
except_tab:
    .byte sigill,sigill,sigbus,sigill,sigill,sigfpe,sigfpe,sigfpe,sigill,sigtra
     øholds a table of signal constants indexed by exception causes
         ø   .byte  sigill,  øvector# 0: reset: initial ssp
                   øsigill,  øvector# 1 : reset: initial pc
                   øsigbus,  øvector# 2: bus error
                   øsigill,  øvector# 3: address error
                   øsigill,  øvector# 4: illegal instruction
                   øsigfpe,  øvector# 5: zero divide
                   øsigfpe,  øvector# 6: chk instruction
                   øsigfpe,  øvector# 7: trapv instruction
                   øsigill,  øvector# 8: privilege violation
                   øsigtrap  øvector# 9: trace
store_sp: .long 0 ø used for holding the stack ptr during execve if
                  ø an error return is needed.
_testflag: .long 0 ø0 means no test
_clexflags: .long 0     øbitmask indicating files to be closed-on-exec
dum_time: .long 0
f_exec: .long 0 ø#test# addr of first byte in execargs segment
ft_msec=4                  ø offset to millisec used in ftime
ft_zs=6                    ø offset to zone and daylight saving flag
 
ø entry address to program equals zero
ø d0= entry number: 0 (exception), 1 (run), and 2 (fork) are handled
ø
  .text
start:
ø#test#
ø movl  #1000000,d7
ø1$:
ø subl  #1,d7
ø bnes  1$              ø wait loop
ø=========================
ø called entry: d3.w= #formals, a5= f_stk, a6= t_stk, a7= f_val
  cmpw  #0,d0
  beq   except_entry     ø func=0: exception
  cmpw  #1,d0
  beq   run_entry        ø func=1: run
  cmpw  #2,d0
  beq   fork_entry       ø func=2: fork
ø================================
ø return entry_ill to the caller of this program
ø
trap #9
  movl  #orgsys,d6
  movl  #entry_ill,d7
  moveq #1,d5
  trap  #eos
 
  clrl  d0
  clrl  d0
  clrl  d0
  clrl  d0
  clrl  d0
  clrl  d0
  clrl  d0
  clrl  d0
  clrl  d0
  clrl  d0
  clrl  d0
  clrl  d0
 
prireturn:
ø===========
ø a4/a5 holds obj_result
ø print stack and return to obj_caller
btst #0,_eoscrtt
beqs 17$
movl a4,a7@-
movl a5,a7@-  ø put result on stack, may cause a trap if a7 is spoiled
movl #127,d2
movl a7,d4
movl #hexop,d5
trap #eos
17$:
movl a4,d6
movl a5,d7
moveq #1,d5
trap #eos
 
 
return:
ø===========
  movl  d6,a4
  movl  d7,a5
  jsr   print_state
  moveq #1,d5
  trap  #eos
 
rcheck_call:
ø===========    calls kernel and checks result. if not ok, return
ø               from utility
  bsr   check_call
  tstb  d7
  bnes  1$
  rts
1$:
  bras  return
 
fatal_error:
ø===========   a fatal system error occurred. objresult not defined
  movl  #orgsys,d6
  movl  #give_up,d7
  bras  return
 
fatal_stack_red:
ø================   stack overflow during exception caused by stack overflow
  movl  #proc_space_lim,d7
  movl  #orgsys,d6
  addl  #red_overflow,d6
  moveq #1,d5
  trap  #eos
 
fatal_stack_yellow:
ø===============    attempt to extend stack failed
  movl  #proc_space_lim,d7
  movl  #orgsys,d6
  addl  #yellow_overflow,d6
  bras  return
 
prolog:
ø============== called when entering the program (run and fork)
 
ø* round top_text up to nearest 32k byte boundary
ø  and put value in f_data:
  movl  #0x7fff,d0      ød0:=32k
  movl  #_etext,d1      ø
  addl  d0,d1           ød1:=_etext+32k-1
  notl  d0              ø
  andl  d0,d1           ød1:=round(d1)
  movl  d1,a4           øa4:=rounded value
ø* map data segment on this address
  movl  #localdata,a0   øa0:=segment
  moveq #data_mmu,d0    ød0:=data_mmu
ø bsr   map_segm        ømapsegm(in a0,a4,d0; out a1=actual addr)
ø map_segm is not called because it will attempt to print a
ø testoutput message. this isn't possible because localdata
ø hasn't yet been mapped. the code for map_segm is therefore
ø copied below
  link  a6,#-map_args
  movl  a6,a3
 
  movl  a0,a3@-         ø1st arg (segment)
  movl  a4,a3@-         ø2nd arg (preferred addr)
  movl  d0,a3@-         ø3rd arg (mmu ix)
 
  moveq #map_args,d2
  movl  a7,d4
  moveq #map_call,d5
  trap  #9
  trap  #7
 
  unlk  a6
  tstb  d7
  beqs  1$
 
  bra   return
1$:
  cmpl  a4,a1           øif preferred_addr<>actualaddr then
  bne   fatal_error     ø  goto fatal error
 
  rts
 
run_entry:
ø============    scan arg and envir vector. get secret envir texts
ø                set up call to _main
  bsr   prolog          ømap localdata etc.
  movl  a4,f_data       øf_data:=rounded value of _etext
  movl  a6,t_stk        øt_stk:=a6;
  movl  a5,f_stk        øf_stk:=a5;
  movl  16,d0           ød0:=header.symsize;
  addl  a4,d0           ød0:=top of data segm.;
  movl  d0,bsmax        øbsmax:=top of localdata segment;
  bsr   print_entry
  bsr   print_data
ø bsr   print_state
  clrl  d0              ød0(#val params parsed):=0;
ø* push three zero words to ensure correct termination of valdata
  clrl  a7@-
  clrw  a7@-
  movl  a7,f_valdata
ø* scan arg texts
  bsr   scan_texts      øscan argument texts and put ptr's to them on
                        ø  auxstack.  d0:=#elt's
ø bsr   print_state
ø* build argument vector on stack
ø clrl  a7@-            ølast elt:=0  already pushed above!
1$:
  cmpl  f_stk,a5        øwhile not empty(auxstck) do
  beqs  2$
 
  movl  a5@-,a7@-       ø  push(pop(auxstack))
  bras  1$
2$:                     øendwhile;
ø bsr   print_state
  movl  a7,a1           øa1:=^arg vector
  movl  d0,d1           ød1:=#args+1 (for zero length val data)
  subql #1,d1           ød1:=nargs
ø* scan envir texts
  bsr   scan_texts
ø bsr   print_state
 
ø* build environment vector on stack
  clrl  a7@-            ølast elt:=0
3$:
  cmpl  f_stk,a5        øwhile not empty(auxstack) do
  beqs  4$
 
  movl  a5@-,a4         ø  a4:=pop(auxstack);
  cmpl  #0x5453543d,a4@ ø  if a4@="TST=" then
  bnes  33$
 
  movb  a4@(4),_testflag ø    testflag:=char;
33$:                    ø  end;
  movl  a4,a7@-         ø  push(a4);
  bras  3$
4$:                     øendwhile;
ø bsr   print_state
  movl  a7,_environ     ø_environ:=^envir vector
 
ø* push parameters for _main
  movl  _environ,a7@-   ø^envir vector
  movl  a1,a7@-         ø^arg vector
  movl  d1,a7@-         ønargs
 
ø bsr   print_state
ø* get the hidden environment
  bsr   scan_texts
ø bsr   print_state
 
  cmpl  f_stk,a5        øif no text then
  bgts  5$
 
  clrl  cur_work_dir    ø  cur_work_dir:=null
  bras  6$              øelse
5$:
  movl  #cur_work_dir,a1        ø  move cur_work_dir text
  movl  #top_cur_wd,d6
  movl  a5@-,a4
  movl  a5,a7@-         ø  save auxstack ptr
  bsr   mov_txt
ø bsr   print_state
ø bsr   print_data
 
  blt   98$
 
  movl  a7@+,a5         ø  pop auxstack ptr
6$:                     øendif;
  cmpl  f_stk,a5        øif no text then
  bgts  7$
 
  clrl  pipe_root       ø  pipe_root:=null
  bras  8$              øelse
7$:
  movl  #pipe_root,a1   ø  move pipe_root text
  movl  #top_pipe_root,d6
  movl  a5@-,a4
  movl  a5,a7@-         ø  save auxstack ptr
  bsr mov_txt
ø bsr   print_state
ø bsr   print_data
  blt   98$
 
  movl  a7@+,a5         øendif;
8$:
  cmpl  f_stk,a5        øif no text then
  bgts  10$
 
  clrl  file_root       ø  file_root:=null;
  bras  11$             øelse
10$:
  movl  #file_root,a1   ø  move file_root text
  movl  #top_file_root,d6
  movl  a5@-,a4
  cmpl  f_stk,a5        ø  if not last text then
  bnes  98$             ø    goto error
 
  bsr mov_txt
ø bsr   print_state
ø bsr   print_data
  blt   98$             øendif;
11$:
 
  bsr   enable          øenable exceptions;
 
ø* call _main
  bsr   print_state
  bsr   print_data
  jsr   _main
  bsr   print_state
  jsr   _exit           øc routine (close files etc)
  bra   main_exit
 
98$:                    ø data value illegal error
  movl  #data_ill,d7
  movl  #orgsys,d6
  addl  #text_too_long,d6
99$:                    ø fatal error return
  bra   return
 
 
 
fork_entry:
ø==============
  bsr   prolog          ømap localdata etc.
                        øa4=f_data,  a5=f_stk
  movl  a4,f_data       ø#test# for print_...
  movl  a6,t_stk        ø ----
  movl  a5,f_stk        ø ----
  bsr   print_entry
 
ø* copy olddata to localdata
  movl  #olddata_ref,a0 øa0:=segment ptr
  movl  #work_addr,a4   øa4:=preferred addr
  moveq #work_mmu,d0    ød0:=mmu_index
  bsr   map_segm        ømap olddata segment (a1:=addr, d3:=length)
 
  tstb  d7              øif res<>ok then
  bne   99$             ø  goto error
 
  movl  f_data,a2       ø* copy
  tstl  d3
1$:                     øwhile length>0 do
  bles  2$
  movl  a1@+,a2@+       ø  copy long from olddata to localdata
  subql #4,d3           ø  length:-4;
  bras  1$              øendwhile;
2$:
  bsr   print_data
ø* copy oldstack to this stack
  movl  #oldstack_ref,a0        øa0:=segment ptr
  movl  #work_addr,a4   øa4:=preferred addr;
  moveq #work_mmu,d0    ød0:=mmu_index;
  bsr   map_segm        ømap oldstack segment(a1:=addr,d3:=length)
 
  tstb  d7
  bne   99$
 
  movl  f_stk,a2
  tstl  d3
3$:                     øwhile lenght>0 do
  bles  4$
  movl  a1@+,a2@+       ø  copy long
  subql #4,d3           ø  length:-4;
  bras  3$
4$:
ø* restore stackptr as from forking process
ø  on stack is now (in pop-order):
ø    reg's a7-a2
ø    reg's d7-d2
ø  return addr corresponding to call of eos_fork
  movl  fork_stackptr,a7
 
ø* 'release' the two formal segments: oldstack and olddata by unmapping
ø  olddata and copying void to the two formal pointers:
  movl  #0,a0           øa0:=void;
  movl  #work_addr,a4
  movl  #work_mmu,d0
  bsr   map_segm        øunmap
  tstb  d7
  bne   fatal_error
 
  clrl  d1              ød1:=void
  movl  #oldstack_ref,d0
  bsr   copy
  tstb  d7
  bne   99$
 
  movl  #olddata_ref,d0
  bsr   copy
  tstb  d7
  bne   99$
 
ø* call emul.forkend to release parent
  link  a6,#-zero_act
  movl  a6,a3
  movl  #emulator_ref,a3@-      øemulator
  movl  #forkend_entry,a3@-     ø  .forkend
  clrl  a3@-                    ø  void val data
  clrw  a3@-
  clrl  a3@-
 
  moveq #zero_act,d2
  movl  a7,d4
  moveq #obj_call,d5
 
  bsr   check_call
  bne   99$
 
  unlk  a6
 
ø* store result of fork operation in localdata, i.e., childid=0
  clrl  fork_childid
 
ø* "return" to eos_fork routine
  bra   after_forkbegin
 
99$:                    ø fatal error: objreturn
  bra   return
 
touch_instruct:
  tstb  a7@(-100)       øconstant "100" is insignificant
 
except_entry:
ø===============
  cmpl  d1,a7           øif d1=a7 then
  beq   fatal_stack_red ø  red stack overflow
 
  movl  d1,a7           ø"push" reg's etc.  now on stack:
                        ø  all reg's, ccr, pc
ø###############kernel error
  subl  #6,a7@(60)      ø###patch kernel error in saved a7###
ø###############kernel error 83-11-10
 
  tstl  d3
  beqs  78$
 
  bsr   force_entry     øunconditional print_entry
  bsr   force_state     øunconditional print_state
  bras  79$
78$:
  bsr   print_entry
79$:
  cmpw  #2,d3           øif exception=address_error and
  bnes  2$
 
  cmpw  touch_instruct,d7       øinstruct=touch instruction
  bnes  2$
 
ø* extend stack
  bsr   print_state
 
  ø....
  bra fatal_stack_yellow        øyellow stack overflow
 
2$:
  tstw  d3              øif exception=speed up then
  beq   5$              ø  goto speedup exception;
 
  øsend appropriate signal to myself through emulator
  cmpw  #9,d3           øif exception>9 then
  bles  3$
 
  moveq #sigill,d1      ø  signal:=sigill (illegal instruction)?
  bras  4$              øelse
3$:
  clrl  d1
  movl  #except_tab,a0
  addw  d3,a0
  movb  a0@,d1          ø  d1:=except_tabÆd3:wÅ
4$:                     øendif;
  moveq #sendsig_to_self,d0 ød0:=sigop 5 (send signal to self)
  bsr   sigsag          øemul.sigsag(myself,d1)
  bra   7$              øgoto return;
 
5$:     øspeedup exception:
  movl  a0,a7@-         øsave handler addr
  bsr   test_speedup    øremove speedup condition
  movl  a7@+,a0         ørestore handler addr in a0
 
  øcall emulator to get signal
  moveq #1,d1           ø#fix vir's error in unixemulator
  moveq #receive_sig,d0 ød0:=sigop  (receive signal)
  bsr   sigsag          øemul.sigsag(receive_sig,d1:=sig,a0:=handler addr)
  tstb  d7
  bne   fatal_error
 
  movl  d1,a7@-         øpush argument to signal handler: sig #
 
  bsr   enable
  ømoveml a7@(4),#0xffff        ørestore reg's before calling handler
  jsr   a0@             ø***call handler***
 
  addl  #4,a7           øpop argument to handler
  bsr   print_state
  bras  8$              øgoto return (exceptions are enabled)
 
7$:
  bsr   enable
8$:
  moveml a7@+,#0xffff
  movb  a7@(1),a7@      øjust to be sure... (ccr)
  rtr                   ørestore reg's and status
 
 
ø******* v a r i o u s   a u x i l l i a r y   r o u t i n e s ******
ø********************************************************************
 
print_state:
ø============  testoutputs stack and auxstack.  requires that localdata
ø                is mapped. all reg's are unchanged
  tstl  _testflag
  bnes  75$
 
  rts
75$:
force_state:
  moveml #0xffff,a7@-
  movl  #text1_size,a7@-
  movl  #text1,a7@-
  bsr   _prttxt
  addl  #8,a7
 
  movl  #128,a7@-
  movl  f_stk,a7@-
  bsr   _prthex         øprint auxstack
  addl  #8,a7
 
  movl  #text2_size,a7@-
  movl  #text2,a7@-
  bsr   _prttxt
  addl  #8,a7
 
  movl  t_stk,a6
  subl  a7,a6
  movl  a6,a7@-
  movl  a7,d0
  addl  #4,d0
  movl  d0,a7@-
  bsr   _prthex         øprint satck (a7 - t_stk)
  addl  #8,a7
 
  moveml a7@+,#0xffff
  rts
text1:
  .ascii "eos/unix rts, auxstack: "
text1_size=24
text2:
  .ascii "eos/unix rts, stack:"
text2_size=20
 
print_entry:
ø==================
  tstl  _testflag
  bnes  75$
 
  rts
75$:
force_entry:            øunconditional print_entry:
  moveml #0xffff,a7@-
  movl  #text4_size,a7@-
  movl  #text4,a7@-
  bsr   _prttxt
  addl  #8,a7
 
  movl  a7,d0
  movl  #68,a7@-        øall regs + return addr
  movl  d0,a7@-
  bsr   _prthex
  addl  #8,a7
 
  moveml a7@+,#0xffff
  rts
text4:
  .ascii "********** E N T R Y   eos/unix RTS **********"
text4_size=46
 
print_pos:
ø==================
  moveml #0xffff,a7@-
  movl  #tpos_size,a7@-
  movl  #tpos,a7@-
  bsr   _prttxt
  addl  #8,a7
 
  moveml a7@+,#0xffff
  rts
tpos:
  .ascii "-----------positive entry --------------------"
tpos_size=46
 
print_neg:
ø==================
  moveml #0xffff,a7@-
  movl  #tneg_size,a7@-
  movl  #tneg,a7@-
  bsr   _prttxt
  addl  #8,a7
 
  moveml a7@+,#0xffff
  rts
tneg:
  .ascii "++++++++++++ negative entry ++++++++++++++++++"
tneg_size=46
 
print_call:
ø================= called when a rts routine is called
  tstl  _testflag
  bnes  75$
 
  rts
75$:
  moveml #0xffff,a7@-
  movl  #text5_size,a7@-
  movl  #text5,a7@-
  bsr   _prttxt
  addl  #8,a7
 
  bsr   print_state
 
  moveml a7@+,#0xffff
  rts
text5:
  .ascii "-------- eos/unix RTS   c a l l e d ----------"
text5_size=46
 
print_data:
ø============  testoutput localdata segment (first 256 bytes)
  tstl  _testflag
  bnes  75$
 
  rts
75$:
  moveml #0xffff,a7@-
  movl  #text3_size,a7@-
  movl  #text3,a7@-
  bsr   _prttxt
  addl  #8,a7
 
  movl  #0x300,a7@-
  movl  f_data,a7@-
  bsr   _prthex         øprint first 256 bytes of localdata
  addl  #8,a7
 
  moveml a7@+,#0xffff
  rts
text3:
  .ascii "eos/unix rts, localdata:"
text3_size=24
 
print_exec:
ø============  testoutput execargs segment (first 256 bytes)
  tstl  _testflag
  bnes  75$
 
  rts
75$:
  moveml #0xffff,a7@-
  movl  #text6_size,a7@-
  movl  #text6,a7@-
  bsr   _prttxt
  addl  #8,a7
 
  movl  #256,a7@-
  movl  f_exec,a7@-
  bsr   _prthex         øprint first 256 bytes of localdata
  addl  #8,a7
 
  moveml a7@+,#0xffff
  rts
text6:
  .ascii "eos/unix rts, execargs: "
text6_size=24
 
.globl  _printarea,_printtext,_printvar
_printarea:
ø===============
ø   may be called from c-programs like:  printarea("text:",addr,length);
  tstl  _testflag
  bnes  75$
 
  rts
75$:
  movl  a7@(4),a0       øa0:=^text;
  moveml #0xffff,a7@-
 
  movl  a0,a2
  clrl  d1
1$:
  addl  #1,d1
  tstb  a2@+
  bnes  1$
 
  movl  d1,a7@-
  movl  a0,a7@-
  bsr   _prttxt
  addl  #8,a7
 
  movl  a7@(72),a0      øa0:=^area
  movl  a7@(76),d0      ød0:=length of area
  beqs  2$              øif length>0 then
 
  movl  d0,a7@-
  movl  a0,a7@-         ø^area
  bsr   _prthex         ø  print area;
  addl  #8,a7
2$:                     øendif;
 
  moveml a7@+,#0xffff
  rts
 
_printvar:
ø==============
  tstl  _testflag
  bnes  75$
 
ø  rts
75$:
  movl  a0,a7@-
  movl  a7,a0
  addl  #12,a0  øa0:=^var
 
  movl  #4,a7@-
  movl  a0,a7@-
  subl  #4,a0   øa0:=^text
  movl  a0@,a7@-
  bsr   _printarea
  addl  #12,a7  øpop args
 
  movl  a7@+,a0
  rts
 
_printtext:
ø=============
  tstl  _testflag
  bnes  75$
 
  rts
75$:
  clrl  a7@-
  movl  #_printtext,a7@-        øor whatever...
  movl  a7@(12),a7@-
  bsr   _printarea
  addl  #12,a7
  rts
 
check_call:
ø=============  calls the kernel and tests the result returned.
ø               if not ok:
ø                  _erreos:=objcall result
ø                  d0:=-1
ø                  _errno:=res.auxcause
ø                  ccr:=lt
ø               if ok:
ø                  d0:=0
ø   d2/d4/d5=kernel call
ø   d0:=!, d6/d7:=res, other reg's may be smashed by kernel call
  bsr   print_state
  trap  #eos
  clrl  d0              ød0:=0;
  tstb  d7              øif res<>ok then
  beqs  1$
 
  moveml #0x00c0,_erreos
  movl  d6,d0           ød0:=res
  andl  #0x0000ffff,d0  øclear orgsys in d0
  lsrl  #8,d0           øclear argno in d0
  movl  d0,_errno       øerrno:=res.auxcause;
  moveq #-1,d0          øccr:=lt
1$:
  bsr   print_state
  tstl  d0              ø#test#
  rts
 
scan_texts:
ø============   scans an array of texts in valdata (from a6 decreasing
ø               to zero length valdata item). a pointer to each text
ø               is placed on the "auxilliary stack" (low addresses and
ø               up in stack segment).  d0 is increased by the number of
ø               vector elt's found (incl. zero valdata item).
ø note: this code is not re-entrant.
ø d0/a5/a6=!
ø d6/d7:=res, a6:=base of next valdata item (after zero item),
ø   d0:=d0+#elt's in vector,  a5:=top of auxstack
  cmpl  f_valdata,a6    øif no more val data then
  ble   9$              ø  goto error
 
  addql #1,d0           ød0:+1;
1$:
  movw  a6@-,d7         øwhile (d7:=length of next text)>0 do
  bles  3$
 
  clrw  a6@             ø  lengthfield:=0; to ensure terminating 0
  btst  #0,d7           ø  if odd length then
  beqs  2$
 
  addqw #1,d7           ø    d7:+1; now even
  clrb  a6@(-1)         ø    clear unused byte to ensure term. 0
2$:                     ø  endif;
  subw  d7,a6           ø  a6:=text addr;
  cmpl  f_valdata,a6    ø  if a6 outside valdata then
  blt   9$              ø    goto error
 
  movl  a6,a5@+         ø  "push" ptr to text on auxstack;
 
  cmpl  f_valdata,a6    ø  if no more valdata then
  bles  9$              ø    goto error;
 
  addql #1,d0           ø  d0:+1;
  bras  1$              øendwhile;
3$:
  blts  9$              øif length of text < 0 then goto error;
 
  clrl  d7              øres:=ok;
  rts
9$:             øerror:
  movl  #data_ill,d7
  movl  #orgsys,d6
  negl  d0
  andw  #0x000f,d0      øargno:=-valdata param #
  addw  d0,d6
  bra   return
 
size_text:
ø============
ø  returns the size of a text string not including a trailing null char.
ø  the size is rounded up to an even value.  if the text is empty (i.e.,
ø  only a zero char) a size of 2 is returned.
ø  a0@=^text
ø  d0:=length as explained above,  a1:=?
  clrl  d0
  movl  a0@,a1          øa1:=first of text
1$:
  tstb  a1@+            øwhile nextchar<>0 do
  beqs  2$
 
  addql #1,d0           ø  d0:+1;
  bras  1$              øendwhile;
2$:
  addql #1,d0           ø
  bclr  #0,d0           øround length up to even value
 
  rts
 
disable:
ø===========
ø  disables exceptions
ø  all reg's are unchanged
  moveml #0xffff,a7@-   øpush all reg's
  movl  #disable_except+propreject,d0
  bsr   propagate
 
  tstb  d7
  beqs  1$
 
  bra   fatal_error
1$:
  moveml a7@+,#0xffff   ørestore all reg's
  rts
 
enable:
ø=========
ø  enable exceptions
ø  all reg's are unchanged
  moveml #0xffff,a7@-   øpush all reg's
  movl  #enable_except+propreject,d0
  bsr   propagate
 
  tstb  d7
  beqs  1$
 
  bra   fatal_error
1$:
  moveml a7@+,#0xffff   ørestore all reg's
  rts
 
check_addr:
ø==============     check whether the address in a4 is in the address
ø                   space of the process.
ø   a4=addr to be checked
ø   d0:=if ok then 0 else -1,   _errno:=if not ok then efault
  movl  top_text,d0
  cmpl  d0,a4
  blts  1$
 
  movl  f_data,d0
  cmpl  d0,a4
  blts  99$
 
  movl  bsmax,d0
  cmpl  d0,a4
  bles  1$
 
  movl  f_stk,d0
  cmpl  d0,a4
  blts  99$
 
  movl  t_stk,d0
  cmpl  d0,a4
  blts  1$
99$:                    øaddress_error:
  movl  #efault,_errno  ø  _errno:=efault;
  movl  #-1,d0          ø  d0:=-1;
  rts
1$:                     øaddress_ok:
  clrl  d0              ø  d0:=0;
  rts
 
movtxt_or_nul:
ø============== moves a text to valdata segment. an empty text is moved as
ø               a zero word and a length of 1 is returned.
ø   a1=first dest.,  d6=top dest.,  a4=first source
ø   a1:=rounded next dest.  d7:=#chars moved (excl. null)
ø
  tstb  a4@             øif sourceÆ1Å=null then
  bnes  1$
 
  clrw  a1@+            ø  destÆ1..2Å:=null;
  moveq #1,d7           ø  #chars moved:=1;
  rts
1$:                     øelse
  bsr   mov_txt         ø  mov_txt
  rts                   øendif;
 
build_name:
ø=============  builds a complete pathname by prefixing an existing
ø               name with rootname and possibly cur_work_dir.
ø   a4=^oldpath,  a1=first dest.,  d6=top dest.
ø   a4:=^newpath,  d0:=0/-1   ccr:=  ge/lt
  moveml #0x7ff7,a7@-   øpush d1-d7,a0-a3,a5-a7
  movl  a4,a2           øa2:=oldpath
  clrl  d0              ø#chars in newpath:=0;
  movl  a1,a0           øa0:= save first dest.
 
  cmpb  #0x7e,a2@       øif oldpathÆ1Å='ü' then
  bnes  1$
 
  addl  #1,a2           ø   strip 'ü';
  bras  3$              ø   goto no prefix;
1$:                     øendif;
ø* copy file_root to new path
  movl  #file_root,a4   øa4:=first source
  bsr   mov_txt         ønewpath:=file_root;
  blt   99$
 
  movl  d7,d0           ød0:=#chars in newpath
  cmpb  #47,a2@         øif oldpathÆ1Å<>'/' then
  beqs  3$
 
ø* copy cur_work_dir to new_path
  movl  a0,a1
  addl  d0,a1           ø  a1:=first dest.
  movl  #cur_work_dir,a4 ø  a4:=first source
  bsr   print_state             ø#test#
  bsr   mov_txt         ø  newpath:+cur_work_dir;
  blt   99$
 
  addl  d7,d0           ø  d0:+#chars transferred
3$:                     øendif;
ø* copy oldpath to new_path
  movl  a0,a1
  addl  d0,a1           øa1:=first dest
  movl  a2,a4           øa4:=oldpath
  bsr   print_state             ø#test#
  bsr   mov_txt         ønewpath:+oldpath;
  blt   99$
 
  movl  a0,a4   øa4:=^newpath
  moveml a7@+,#0xeffe   øpop a7-a5,a3-a0,d7-d1
  bsr   print_state             ø#test#
  clrl  d0
  rts
99$:
  movl  #efault,_errno
  bsr   print_state
  moveml a7@+,#0xeffe
  movl  #-1,d0
  rts
 
chck_fildes:
ø============ check a file descriptor (0-31)
ø  d0=fildes
ø  if not ok:  d0:=-1,  errno:=ebadf,   ccr:=lt
ø  if ok:  all regs u.c.,               ccr:=ge
  cmpl  #31,d0
  bgts  99$
 
  tstl  d0
  blts  99$
 
  rts
99$:
  movl  #ebadf,_errno
  movl  #-1,d0
  rts
 
initstat:
ø============
ø  initialise buf to a 'standard' stat record
ø  a0=^buf   all reg's u.c.
  clrw  a0@(st_dev)
  clrw  a0@(st_ino)
  movw  #0100000,a0@(st_mode)
  movw  #1,a0@(st_nlink)
  clrw  a0@(st_uid)
  clrw  a0@(st_gid)
  clrw  a0@(st_rdev)
  clrl  a0@(st_size)
  clrl  a0@(st_atime)
  clrl  a0@(st_mtime)
  clrl  a0@(st_ctime)
  rts
 
ø***** k e r n e l   c a l l   r o u t i n e s *******
ø*****************************************************
 
copy:
ø========
ø    d0=dest ptr, d1=source ptr
ø    d6/d7:=res
  moveml #0xfcf0,a7@-   øpush d0-d5,a0-a3
  movl  a7,d4           ød4:=^d0/d1
  moveq #copy_args,d2
  moveq #copy_call,d5
  bsr   check_call
 
  moveml a7@+,#0x0f3f   øpop a3-a0,d5-d0
  rts
 
propagate:
ø==========
ø   d0=propagate mode
ø   all:=?
  link  a6,#-prop_args
  movl  d0,a7@          ø1st and only arg
  moveq #prop_args,d2
  movl  a7,d4
  moveq #prop_call,d5
 
  bsr   check_call
 
  unlk  a6
  rts
 
test_speedup:
ø===============
ø   d0:=speedup status, all:=?
  link  a6,#-tspeed_args
  moveq #tspeed_args,d2
  movl  a7,d4
  moveq #tspeed_call,d5
  bsr   rcheck_call
 
  movl  a7@,d0          ød0:=out speed up signal
  unlk  a6
  rts
 
map_segm:
ø==============
ø   a0=segment ptr, a4=preferred addr,  d0=mmu_index
ø   a1:=actual addr, d3:=#bytes, d5:=use bits
ø   all others:=?  d6/d7:=!  a4/a5/a6:=.
  link  a6,#-map_args
  movl  a6,a3
 
  movl  a0,a3@-         ø1st arg (segment)
  movl  a4,a3@-         ø2nd arg (preferred addr)
  movl  d0,a3@-         ø3rd arg (mmu ix)
 
  moveq #map_args,d2
  movl  a7,d4
  moveq #map_call,d5
  bsr   check_call
 
  unlk  a6
  rts
 
 
ø******* various object call routines*************
ø**************************************************
 
sigsag:
ø===========    call emulator's sigsag entry
ø   d0=sigop,  d1=sig#,   a0=sigfunc(pid)
ø   d1:=sig#,  a0:=handler addr,  d2/d3/d4/d5/a1/a3:=?,  d6/d7:=result
  link  a6,#-zero_act
  movl  f_stk,a1
  movl  a1,d5
  moveq #4,d3
 
  movl  a0,a1@+         øin out sigfunc
  movw  d3,a1@+
 
  movl  d1,a1@+         øin out sig#
  movw  d3,a1@+
 
  movl  d0,a1@+         øin sigop
  movw  d3,a1@+
 
  subl  d5,a1           øa1:=length of valdata
  movl  a6,a3           ø* prepare arguments
 
  movl  #emulator_ref,a3@-      øemulator
  movl  #sigsag_entry,a3@-      ø  .sigsag
  movl  #stack,a3@-             ø(valdata in stack
  movw  #rwe,a3@-               ø  rwe use bits
  clrl  a3@-                    ø  first=0
  movl  a1,a3@-                 ø  length)
 
  moveq #zero_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call
 
  movl  f_stk,a1
  movl  a1@,a0          øout sigfunc
  movl  a1@(6),d1       øout sig#
  unlk  a6
  rts
 
getsetclock:
ø===========    call clock object to get or set time
ø   d0=seconds,  a0=get or set_entry
ø   d0:=secs,  d1:=microsecs, d2:=timezone, d3:=daylight saving flag
ø     d6/d7:=result,  d4/d5/a0-a6:=?
  link  a6,#-zero_act
  movl  f_stk,a1
  movl  a1,d5
  moveq #4,d3
 
ø addl  d3,a1           øout dst_flag
  movl  #1,a1@+         ødefault=daylight saving time applies
  movw  d3,a1@+
 
ø addl  d3,a1           øout timezone
  movl  #-3600,a1@+     ødefault=-3600 seconds from gmt
  movw  d3,a1@+
 
  addl  d3,a1           øout microsecs
  movw  d3,a1@+
 
  movl  d0,a1@+         øin out seconds
  movw  d3,a1@+
 
  subl  d5,a1           øa1:=length of valdata
  movl  a6,a3           ø* prepare arguments
 
  movl  #clock_ref,a3@-         øclock
  movl  a0,a3@-                 ø  .get/set
  movl  #stack,a3@-             ø(valdata in stack
  movw  #rwe,a3@-               ø  rwe use bits
  clrl  a3@-                    ø  first=0
  movl  a1,a3@-                 ø  length)
 
  moveq #zero_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call
  unlk  a6
 
  tstb  d7
  bnes  99$
 
  movl  f_stk,a1
  movl  a1@(18),d0      øout seconds
  movl  a1@(12),d1      øout microsecs
  movl  a1@(6),d2       øout timezone
  movl  a1@,d3          øout dst_flag
99$:
  rts
 
setgetid:
ø===========    call emulator's setgetid entry
ø   d0=id,  d1=func#
ø   d0:=id  d2/d3/d4/d5/a0-a5:=?,  d6/d7:=result
  link  a6,#-zero_act
  movl  f_stk,a1
  movl  a1,d5
  moveq #4,d3
 
  movl  d0,a1@+         øin out id
  movw  d3,a1@+
 
  movl  d1,a1@+         øin out func
  movw  d3,a1@+
 
  subl  d5,a1           øa1:=length of valdata
  movl  a6,a3           ø* prepare arguments
 
  movl  #emulator_ref,a3@-      øemulator
  movl  #setgetid_entry,a3@-    ø  .setgetid
  movl  #stack,a3@-             ø(valdata in stack
  movw  #rwe,a3@-               ø  rwe use bits
  clrl  a3@-                    ø  first=0
  movl  a1,a3@-                 ø  length)
 
  moveq #zero_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call
 
  movl  f_stk,a1
  movl  a1@,d0          øout id
  unlk  a6
  rts
 
getref:
ø================   calls objdir.getref
ø   a4=^name
ø   d6/d7:=result,  a3:=# used chars,  all other u.c.
  moveml #0xfcef,a7@-   øsave d0-d5,a0-a2,a4-a7
  movl  f_stk,a1
  movl  a1,d5
  moveq #4,d4
 
  addql #4,a1           øout item kind
  movw  d4,a1@+
 
  addql #4,a1           øout used chars
  movw  d4,a1@+
 
  movl  a7,d6
  subl  #one_act,d6     ød6:=top dest.  (a1=first dest.)
  bsr   mov_txt         ømov_txt(a4,a0,d6)
  bges  1$              øif error then
 
  bsr small_stk         ø  call small_stk;
1$:                     øendif;
  movw  d7,a1@+
  subl  d5,a1           øa1:=length of valdata
  link  a6,#-one_act
  movl  a6,a3
 
  movl  #objdir,a3@-            øobjdir
  movl  #get_ref,a3@-           ø  .getref
  movl  #stack,a3@-             ø  (valdata in stack
  movw  #rwe,a3@-               ø    use bits
  clrl  a3@-                    ø    first=0
  movl  a1,a3@-                 ø    length),
 
  movl  #work_ptr,a3@-          øout work_ptr
  movw  #out_ptr,a3@-
  clrl  a3@-
  clrl  a3@-
 
  movl  #one_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call              ø*call*
 
  unlk  a6
  movl  f_stk,a1
  movl  a1@(6),a3               øa3:=out used chars
  moveml a7@+,#0xf73f           ørestore a7-a4,a2-a0,d5-d0
  rts
 
assign:
ø=============   calls work_ptr.assign (out a5; a4,d0);
ø  a4=^name,  a5=fao pointer,  d0=iomode, d1=create_mode
ø  d6/d7:=result,  all other u.c.
  moveml #0xfcff,a7@-
  movl  f_stk,a1
  movl  a1,d5
  moveq #4,d4
 
  movl  d1,a1@+                 øin createmode
  movw  d4,a1@+
 
  movl  d0,a1@+                 øin iomode
  movw  d4,a1@+
 
  movl  a7,d6
  subl  #one_act+8,d6           ød6:=top dest.
  movl  a5,a7@-                 øsave fao ptr
  bsr   mov_txt
  bges  1$
 
  bsr   small_stk
1$:
  movl  a7@+,a5                 ørestore fao ptr
  movw  d7,a1@+                 øpush length of text
 
  subl  d5,a1           øa1:=length of valdata
  link  a6,#-one_act
  movl  a6,a3
 
  movl  #work_ptr,a3@-  øpipesys (from getref)
  movl  #assign_entry,a3@-
  movl  #stack,a3@-
  movw  #rwe,a3@-
  clrl  a3@-
  movl  a1,a3@-
 
  movl  a5,a3@-         øout fao_owner
  movw  #out_ptr,a3@-
  clrl  a7@
 
  moveq #one_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call      ø*call*
 
  unlk  a6
  moveml a7@+,#0xff3f
  rts
 
close_fildes:
ø================ closes a file
ø   d0=fildes
moveml  #0x3f3f,a7@-
bsr free_fildes       ø d0=fildes d6/d7:=??
link a6,#-dealarg
movl a6,a3            ø a3:= top_arg
addl #ff_env,d0       ø d0:= pointer address
movl d0,a3@-          ø 1. arg to dealloc
movl d0,a3@-          ø 2. arg to dealloc
clrw a3@-             ø void value arg
moveq #dealarg,d2     ø d2:= arg_length;
movl a7,d4            ø d4:= low_arg
moveq #dealloc,d5     ø d5:= func
  bsr   check_call
unlk a6
moveml  a7@+,#0xfcfc
rts
 
ø****** e o s   v e r s i o n s   o f   s y s t e m   c a l l s ******
ø*********************************************************************
 
eos_execve:
ø==============
  bsr   print_call              ø#test#
  movl  a7@(4),a1       øa1:=^path;
  movl  a7@(8),a0       øa0:=^argv
  movl  a7@(12),d0      ød0:=^envp;
 
  moveml #0x3f3f,a7@-   øpush d2-d7,a2-a7
  bsr   disable         ødisable exceptions
  movl  a7,store_sp     østore good stack ptr in case of an error
                        øreturn is needed.
  movl  a1,a4           øa4:=^path;
  movl  d0,a2           øa2:=^envp;
 
ø* compute the needed size of exec_args in d1
ø    for each text in arg's and env's: push ptr to text
ø    before any texts: push zero
ø    after arg texts: push zero
  clrl  a7@-            øpush zero before text ptrs
  clrl  d1              ød1:=0;
1$:
  tstl  a0@             øwhile argvectorÆiÅ<>nil do
  beqs  2$
 
  bsr   size_text       ø  d0:=size_text(argvectorÆiÅ);
  movl  a0@+,a7@-       ø  push(argvectorÆiÅ); i:+1;
  addl  d0,d1           ø  d1:+d0;
  addql #2,d1           ø  d1:+2;  for length field
  bras  1$              øendwhile;
2$:
  clrl  a7@-            øpush zero length between arg's and env's
  addql #2,d1           ød2:+2;  for zero valdata item
  movl  a2,a0           øa0:=^envp
3$:
  tstl  a0@             øwhile envvectorÆiÅ<>nil do
  beqs  4$
 
  bsr   size_text       ø  d0:=size_text(envvectorÆiÅ);
  movl  a0@+,a7@-       ø  push(envvectorÆiÅ);  i:+1;
  addl  d0,d1           ø  d1:+d0;
  addql #2,d1           ø  d1:+2;  for length field
  bras  3$              øendwhile;
4$:
ø   after env texts comes:
ø     - zero length
ø     - cur_work_dir
ø     - pipe_root
ø     - file_root
ø     - zero length
ø total: 2 + 3*(48+2) + 2 = 154
  addl  #154,d1
bsr print_state
ø* build complete pathname on stack
  link  a6,#-pathname_size
  movl  a7,a1           øa1:=first dest.
  movl  a6,d6           ød6:=top dest.
  bsr   build_name      øbuild_name(a1,a4,d6,a4:=new name);
  blt   99$
ø* call prepexec in emulator
  link  a6,#-one_act
  movl  f_stk,a1        øprepare valdata
  movl  a1,d2
  moveq #4,d4
 
  movl  d1,a1@+         øin argbytes (in exec_args)
  movw  d4,a1@+
 
  movl  a7,d6           øin pathname
  subql #4,d6           ød6:=top destination
  bsr   mov_txt         ømov_txt(a1=first dest, d6=top dest
                        ø        a4=first source, out d7:=#chars moved)
  movw  d7,a1@+
 
  subl  d2,a1           øa1:=length of valdata
  movl  a6,a3           øprepare aarg's
 
  movl  #emulator_ref,a3@-      øemulator
  movl  #prepexec_entry,a3@-    ø  .prepexec
  movl  #stack,a3@-             ø  (valdata in stack
  movw  #rwe,a3@-               ø   rwe use bist
  clrl  a3@-                    ø   first=0
  movl  a1,a3@-                 ø   length)
  movl  #execargs_ref,a3@-      ø out execargs
  movw  #out_ptr,a3@-
  clrl  a3@-
  clrl  a3@-
 
  movl  #one_act,d2     øprepare kernel call
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call
 
  unlk  a6              øpop call
  unlk  a6              øpop pathname
  tstb  d7              øif res<>ok then
  beqs  45$
 
  cmpw  #header_fe,d7
  bnes  44$
 
  movl  #enoexec,_errno
44$:
  bra   99$             ø  goto error
45$:
 
ø* close filedes's as indicated in close-on-exec flags
  clrl  d0
  movl  _clexflags,d1
46$:
  tstl  d1
  bges  47$
  movl  d0,a7@-
  movl  d1,a7@-
  bsr   close_fildes            øclose_fildes(d0)
  movl  a7@+,d1
  movl  a7@+,d0
47$:
  addql #1,d0
  cmpl  #31,d0
  bgts  48$
 
  lsll  #1,d1
  bras  46$
48$:
ø* map execargs segment
  movl  #execargs_ref,a0        øa0:=segment
  moveq #work_mmu,d0            ød0:=mmu ix
  movl  #work_addr,a4           øa4:=pref. addr
  bsr   map_segm                ømap execargs (a1:=actual addr, d3:=length)
 
  tstb  d7
  bne   99$
 
movl a1,f_exec   ø#test#
ø* fill execargs with valdata. filling starts with low addresses and
ø  proceeds in opposite order
  movl  a1,d6
  addl  d3,d6           ød6:=top destination in execargs
  clrw  a1@+            øterminating zero length item
 
  movl  #cur_work_dir,a4 ømove cur_work dir
  movl  #48,d0
5$:
  movb  a4@+,a1@+
  subl  #1,d0
  bnes  5$
  movw  #48,a1@+
 
  movl  #pipe_root,a4   ømove pipe_root
  movl  #48,d0
6$:
  movb  a4@+,a1@+
  subl  #1,d0
  bnes  6$
  movw  #48,a1@+
 
  movl  #file_root,a4   ømove file_root
  movl  #48,d0
7$:
  movb  a4@+,a1@+
  subl  #1,d0
  bnes  7$
  movw  #48,a1@+
 
  clrw  a1@+            øzero length item
 
10$:                    øenv pointers
  movl  a7@+,d7         øwhile (ptr:=popstack)<>nil do
  beqs  11$
 
  movl  d7,a4
  bsr   movtxt_or_nul           ø  mov_txt(a4,d7:=length);
  movw  d7,a1@+         ø  push(length);
  blt   fatal_error             ø  if length<0 goto fatalerror;
 
  bras  10$
11$:                    øendwhile;
  clrw  a1@+            øzero length item
12$:                    øarg pointers
  movl  a7@+,d7         øwhile (ptr:=popstack)<>nil do
  beqs  13$
 
  movl  d7,a4
  bsr   movtxt_or_nul           ø  mov_txt(a4,d7:=length);
  movw  d7,a1@+         ø  push(length);
  blt   fatal_error             ø  if length<0 goto fatalerror;
 
  bras  12$
13$:                    øendwhile;
 
ø* return from the exec'ing utility
  clrw  d7
  bra   return
 
99$:            øerror: return to caller
  movl  #-1,d0
  bsr   enable
  movl  store_sp,a7     øpop all irrelevant stuff
  moveml a7@+,#0xfcfc   øpop reg's a7-a2,d7-d2
  rts
 
eos_fork:
ø============
  bsr   print_call
  bsr   print_data
  moveml #0x3f3f,a7@-   øpush d2-d7,a2-a7
  movl  a7,fork_stackptr øsave sp in data segm.
  bsr   disable
 
  movl  #-1,fork_childid        øin case of an error (used as result)
ø* call emul.forkbegin(stack,data;out childid)
  link  a6,#-two_act
  movl  a6,a3           øprepare arg's
 
  movl  #emulator_ref,a3@-      øemulator
  movl  #forkbegin_entry,a3@-   ø  .forkbegin
  clrl  a3@-                    ø  (void valdata
  clrw  a3@-
  clrl  a3@-
  clrl  a3@-
 
  movl  #stack,a3@-             ø in stack
  movw  #in_ptr,a3@-
  clrl  a3@-
  clrl  a3@-
 
  movl  #localdata,a3@-         ø in localdata
  movw  #in_ptr,a3@-
  clrl  a3@-
  clrl  a3@-
 
  movl  #two_act,d2     øprepare call
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call      øemul.forkbegin
  bnes  1$
 
  øget childid from result!!!??
  moveq #16,d5
  lsrl  d5,d7                   øthe two low bytes
  movl  d7,fork_childid
  andl  #0xffff0000,d6          øthe two hi bytes
  addl  d6,fork_childid
1$:
  unlk  a6
 
after_forkbegin:        øthis is the place where the child "starts"
  bsr   enable
  moveml a7@+,#0xfcfc   øpop reg's a7-a2,d7-d2
                        ønote: d0-d1,a0-a1 need not be the same in child
                        ø      and father.
  movl  fork_childid,d0
  rts
 
eos_kill:
ø===========
  bsr   print_call
  movl  a7@(4),a0       øa0:=pid
  movl  a7@(8),d1       ød1:=sig
 
  moveml #0x3f3f,a7@-   øpush d2-d7,a2-a7
  bsr   disable
 
  bsr   sigsag          øcall emulator
 
  bsr   enable
  moveml a7@+,#0xfcfc   øpop a7-a2,d7-d2
  rts
 
eos_wait:
ø============
  bsr   print_call
  movl  a7@(4),a0       øa0 :=^location (in which to store status)
  moveml #0x3f3f,a7@-   øpush d2-d7,a2-a7
  movl  a0,a6           øa6:=^location;
  bsr   disable
 
  link  a6,#-zero_act
  movl  f_stk,a1
  movl  a1,d2
  moveq #4,d4
 
  clrl  a1@+            øout status
  movw  d4,a1@+
 
  clrl  a1@+            øout processid
  movw  d4,a1@+
 
  subl  d2,a1           øa1:=length of valdata
  movl  a6,a3
 
  movl  #emulator_ref,a3@-      øemulator
  movl  #wait_entry,a3@-        ø  .wait
  movl  #stack,a3@-             ø  (valdata in stack
  movw  #rwe,a3@-               ø   use bits
  clrl  a3@-                    ø   first=0
  movl  a1,a3@-                 ø   length)
 
  movl  #zero_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call
 
  unlk  a6
  tstb  d7
  bne   100$
 
  movl  f_stk,a0
  cmpl  #0,a6           øif location^<>nil then
  beqs  1$
 
  movl  a0@,a6@         ø  location^:=out status;
1$:                     øendif;
  addl  #6,a0
  movl  a0@,d0          ød0:=out processid
100$:
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
 
eos_pause:
ø=============
  bsr   print_call
  moveml #0x3f3f,a7@-
  bsr   disable
 
  link  a6,#-zero_act
  movl  a6,a3
 
  movl  #emulator_ref,a3@-      øemulator
  movl  #pause_entry,a3@-       ø  .pause
  clrl  a7@                     ø  (void valdata)
 
  moveq #zero_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call
 
  unlk  a6
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
 
eos_chdir:
ø============
  bsr   print_call
  movl  a7@(4),a0       øa0:=^path
  moveml #0x3f3f,a7@-
  bsr   disable
 
  movl  a0,a4           øa4:=^path;
  bsr   check_addr
  blts  1$
 
  movl  #cur_work_dir,a1
  movl  #top_cur_wd,d6
  clrl  d0
  bsr   print_state
  bsr   mov_txt
  bges  1$
 
  movl  #enotdir,_errno øif error in mov_txt then _errno:=enotdir??
  movl  #-1,d0
1$:
  bsr   print_data
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
 
eos_chroot:
ø============
  bsr   print_call
  movl  a7@(4),a0       øa0:=^path
  moveml #0x3f3f,a7@-
  bsr   disable
 
  movl  a0,a4           øa4:=path;
  bsr   check_addr
  blts  1$
 
  movl  #file_root,a1
  movl  #top_file_root,d6
  clrl  d0
  bsr   print_state
  bsr   mov_txt
  bges  1$
 
  movl  #enotdir,_errno øif error in mov_txt then _errno:=enotdir??
  movl  #-1,d0
1$:
  bsr   print_data
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
 
eos_alarm:
ø===========
  bsr   print_call
  movl  a7@(4),d0       ød0:=seconds
  moveml #0x3f3f,a7@-
  bsr   disable
 
  link  a6,#-zero_act
  movl  f_stk,a1
  movl  a1,d2
 
  movl  d0,a1@+         øin seconds
  movw  #4,a1@+
 
  subl  d2,a1
  movl  a6,a3
 
  movl  #emulator_ref,a3@-      øemulator
  movl  #alarm_entry,a3@-       ø  .alarm
  movl  #stack,a3@-             ø  (valdata in stack
  movw  #rwe,a3@-               ø   use bits
  clrl  a3@-                    ø   first=0
  movl  a1,a3@-                 ø   length)
 
  movl  #zero_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call
 
  unlk  a6
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
 
eos_signal:
ø===========
  bsr   print_call
  movl  a7@(4),d1       ød1:=sig#
  movl  a7@(8),a0       øa0:=func
  moveml #0x3f3f,a7@-
  bsr   disable
ø* check sig#
  cmpl  #19,d1          øif sig#>19 then
  bgt   99$             ø  goto error;
 
  tstl  d1              øif sig#<=0 then
  bles  99$
 
  cmpl  #sigkill,d1     øif sig=sigkill then
  beqs  99$             ø  goto error;
ø* check func
  cmpl  #sig_ign,a0     øif func=sig_ign then
  beqs  1$              ø  goto ok
 
  cmpl  #sig_dfl,a0     øif func=sig_dfl then
  beqs  1$
 
  movl  a0,a4           øa4:=func
  bsr   check_addr      øif check_addr(a4)<>ok then
  blts  100$            ø  goto return
1$:             øok:
  moveq #setsigstate,d0
  bsr   sigsag          øemul.sigsag(d0=setsigstate,d1=sig#
                        ø       a0=func,a0:=oldfunc);
  tstb  d7
  bnes  100$
 
  movl  a0,d0           ød0(return val):=old func;
100$:
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
99$:                    øerror in sig #:
  movl  #einval,_errno
  movl  #-1,d0
  bras  100$
 
eos_pipe:
ø=========
  bsr   print_call
  movl  a7@(4),a0       øa0:=^fildesarr
  moveml #0x3f3f,a7@-
  bsr   disable
 
ø movl _testflag,a7@-
ø movl #-1,_testflag
 
  movl  a0,a6           øa6:=^fildesarr
ø* allocate two fildes
  bsr   find_fildes     øif not find_fildes then
  movl  d0,a6@          øfildesarr^Æ0Å:=1. fildes
  blt   100$            ø  goto return;
 
  bsr   resv_fildes     øto enable 2nd call to find_fildes
  bsr   find_fildes     ø2nd fildes
  movl  d0,a6@(4)       øfildesarr^Æ1Å:=2nd fildes;
  movl  a6@,d0
  bsr   free_fildes     øthe first fildes is released but it is
                        ø  reserved again later if everything is ok.
  tstl  a6@(4)          øcheck 2nd fildes
  blt   100$
 
ø* call emulator to get unique pipe name
  movl  f_stk,a1
  movw  #pipename_size,a1@(pipename_size)
  link  a6,#-zero_act
  movl  a6,a3
 
  movl  #emulator_ref,a3@-
  movl  #getunique_entry,a3@-
  movl  #stack,a3@-
  movw  #rwe,a3@-
  clrl  a3@-
  movl  #pipename_size+2,a3@-
 
  movl  #zero_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   rcheck_call
  unlk  a6
 
ø* build complete pipe name in stack
  link  a6,#-pipename_size
 
  movl  #pipe_root,a4   øa4:=first source
  movl  a7,a1           øa1:=first dest.
  movl  a6,d6           ød6:=top dest.
bsr print_state
  bsr   mov_txt         øpipename:=pipe_root
  blt   fatal_error
bsr print_state
 
  movl  a7,a1
  addl  d7,a1           øa1:=first dest. after pipe_root
  movl  a1,a2           øsave address
  movl  f_stk,a4        øa4:=first source(out unique name)
  bsr   mov_txt
  blt   fatal_error
 
  addl  d7,a2           øsave address of char following unique name
 
ø* getref to pipe sys    a7=^pipe name
  movl  a7,a4           øa4:=^name
  bsr   getref          øgetref(a4,d6/d7:=result,a3:=#used chars)
  tstb  d7
  bne   fatal_error
 
ø* assign read end of pipe
  movl  a2,a1
  movl  #r_ch,a4
  movl  a6,d6
  bsr   mov_txt         ømov_txt(a1,a4,d6); --add /r to name
  blt   fatal_error
 
  movl  a6@,a0                  øa0:=old a6=^fildesarr
  movl  a0@,a5                  øa5:=fildes for read_end
  addl  #ff_env,a5              øa5:=pointer addr in file_env
  movl  a7,a4                   øa4:=pathname
  addl  a3,a4                   øa4:=pathnameÆused+1.. Å
  moveq #read_right,d0          ød0:=read_right
  moveq #newfile,d1             øcreatemode:=new file
  bsr   assign                  øassign(a5,a4,d0)
  tstb  d7
  bne   90$
 
ø* assign write end of pipe
  movl  a2,a1
  movl  #w_ch,a4
  movl  a6,d6
  bsr   mov_txt                 ømov_txt(a1,a4,d6); --add /w to name
  blt   fatal_error
 
  movl  a6@,a0          øa0:=old a6=^fildesarr
  movl  a0@(4),a5       øa5:=fildesarrÆ1Å
  addl  #ff_env,a5      øa5:=pointer addr in file_env
  movl  a7,a4
  addl  a3,a4
  moveq #write_right,d0
  moveq #oldfile,d1     øcreatemode:=old file;
  bsr   assign          øassign(a5,a4,d0);
  tstb  d7
  bnes  90$
 
ø* pop pipename from stack
  unlk  a6
ø* reserve the two fildes in fildesarr
  movl  a6@,d0
  bsr   resv_fildes
 
  movl  a6@(4),d0
  bsr   resv_fildes
  clrl  d0              øok return
100$:
 
ø movl a7@+,_testflag
 
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
90$:                    øerror: (pipe name is on stack)
  unlk  a6              ø  pop pipe name
  bras  100$            ø  goto return
r_ch:
  .ascii "/r"
  .word 0
w_ch:
  .ascii "/w"
  .word 0
 
eos_access:
ø============
  bsr   print_call
  movl  a7@(4),a0       øa0:=^path
  movl  a7@(8),d0       ød0:=amode
  moveml #0x3f3f,a7@-
  bsr   disable
 
  link  a6,#-pathname_size      ømake room form complete name
  movl  a7,a1           øa1:=first of path area
  movl  a6,d6           ød6:=top of area
  movl  a0,a4           øa4:=^path
  bsr   build_name      øbuild_name(a1,a4,d6,a4:=^new name)
  blts  100$
 
  bsr   getref          øgetref(a4=^path,a3:=used chars);
  tstb  d7
  bnes  99$
 
ø* try to assign file
  movl  #0,a5           øa5:=void ptr
  addl  a3,a4           øa4:=pathÆused+1.. Å
 
  øconvert unix amode to eos ioright. bits corresponds as follows:
  ø   amode=0 checks the existence of the file/catalog
  ø   bit #     amode:     iomode:
  ø    1         execute    read_right
  ø    2         write      write_right
  ø    3         read       read
  btst  #2,d0
  bnes  1$
 
  bclr  #2,d0           øclear bit 2 but set bit 0
  bset  #0,d0
1$:
  moveq #oldfile,d1     øcreatemode:=oldfile
  bsr   assign          øassign(a5,a4,d0,d1)
  tstb  d7
  bnes  99$
 
  clrl  d0
100$:
  unlk  a6
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
99$:
  movl  #-1,d0
  movl  #enoent,_errno
  bras  100$
 
specialfile=020000    øbit to indicate a character or block special
                      ø  file in mode.
eos_mknod:
ø============
  bsr   print_call
  movl  a7@(4),a0       øa0:=^path
  movl  a7@(8),d0       ød0:=mode
  moveml #0x3f3f,a7@-
  bsr   disable
 
  link  a6,#-pathname_size      ømake room form complete name
 
  andl  #specialfile,d0 øif mode=specialfile then
  bnes  99$             ø  goto error;
 
  movl  a7,a1           øa1:=first of path area
  movl  a6,d6           ød6:=top of area
  movl  a0,a4           øa4:=^path
  bsr   build_name      øbuild_name(a1,a4,d6,a4:=^new name)
  blts  100$
 
  bsr   getref          øgetref(a4=^path,a3:=used chars);
  tstb  d7
  bnes  99$
 
ø* create file or directory
  movl  #0,a5           øa5:=void ptr
  addl  a3,a4           øa4:=pathÆused+1.. Å
  moveq #newfile,d1     øcreatemode:=newfile
  bsr   assign          øassign(a5,a4,d0,d1)
  tstb  d7
  bnes  99$
 
  clrl  d0
100$:
  unlk  a6
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
99$:
  movl  #-1,d0
  movl  #enoent,_errno
  bras  100$
 
eos_link:
ø============
  bsr   print_call
  movl  a7@(4),a0       øa0:=^old name
  movl  a7@(8),a1       øa1:=^new name
  moveml #0x3f3f,a7@-
  bsr   disable
 
  link  a6,#-pathname_size      ømake room for complete new name
  movl  a1,a4           øa4:=^new name
  movl  a7,a1           øa1:=first of path area
  movl  a6,d6           ød6:=top of area
  bsr   build_name      øbuild_name(a1,a4,d6,a4:=^new name)
  blt   101$
 
  bsr   getref          øgetref(a4=^new name,a3:=used chars);
 
  tstb  d7
  bne   99$
 
  movl  a4,a2           øa2:=^new name (with prefix)
 
  link a6,#-pathname_size
  movl  a0,a4           øa4:=^old name
  movl  a7,a1           øa1:=first of path area
  movl  a6,d6           ød6:=top of area
  bsr   build_name      øbuild_name(a1,a4,d6,a4:=^old name)
  blt   100$
 
  movl  a4,a0           øa0:=old name incl. prefix
ø* test that the prefix of oldname and newname are identical
  movl  a2,a1           øa1:=^new name
  movl  a0,a5           øa5:=^old name
  movl  a3,d7           ød7:=# chars in prefix
51$:
  cmpmb a1@+,a5@+
  bnes  52$
  subl  #1,d7
  beqs  53$
  bras  51$
52$:            øerror: not identical prefixes
  movl  #exdev,_errno
  bras  97$
53$:            øsuccess: continue
ø* call createlink
  addl  a3,a2           øa2:=new pathÆused+1.. Å
 
  movl  a2,a4           øa4:=new path (excl. prefix)
  movl  f_stk,a1
  movl  a1,d5
 
  movl  a7,d6
  subl  #zero_act+4,d6          ød6:=top dest.
  bsr   mov_txt
  bges  1$
 
  bsr   small_stk
1$:
  movw  d7,a1@+                 øpush length of text
 
  addl  a3,a0           øa0:=old name excl. prefix
  movl  a0,a4
  bsr   mov_txt
  bges  2$
 
  bsr   small_stk
2$:
  movw  d7,a1@+         øpush length of text
 
  subl  d5,a1           øa1:=length of valdata
  link  a6,#-zero_act
  movl  a6,a3
 
  movl  #work_ptr,a3@-  øfilesys (from getref)
  movl  #creat_link_entry,a3@-
  movl  #stack,a3@-
  movw  #rwe,a3@-
  clrl  a3@-
  movl  a1,a3@-
 
  moveq #zero_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call      ø*call*
 
  unlk  a6              øpop call
  tstb  d7
  bnes  98$
 
  clrl  d0
100$:
  unlk  a6              øpop old name
101$:
  unlk  a6              øpop new name
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
97$:
  moveq #-1,d0
  bras  100$
98$:                    øerror: pop both names
  movl  #-1,d0
  movl  #enoent,_errno
  bras  100$
99$:                    øerror: pop new name
  movl  #-1,d0
  movl  #enoent,_errno
  bras  101$
 
eos_unlink:
ø============
  bsr   print_call
  movl  a7@(4),a0       øa0:=^path
  moveml #0x3f3f,a7@-
  bsr   disable
 
  link  a6,#-pathname_size      ømake room form complete name
  movl  a7,a1           øa1:=first of path area
  movl  a6,d6           ød6:=top of area
  movl  a0,a4           øa4:=^path
  bsr   build_name      øbuild_name(a1,a4,d6,a4:=^new name)
  blts  100$
 
  bsr   getref          øgetref(a4=^path,a3:=used chars);
  tstb  d7
  bnes  99$
 
ø* call deletelink
  addl  a3,a4           øa4:=pathÆused+1.. Å
 
  movl  f_stk,a1
  movl  a1,d5
 
  movl  a7,d6
  subl  #zero_act+4,d6          ød6:=top dest.
  bsr   mov_txt
  bges  1$
 
  bsr   small_stk
1$:
  movw  d7,a1@+                 øpush length of text
 
  subl  d5,a1           øa1:=length of valdata
  link  a6,#-zero_act
  movl  a6,a3
 
  movl  #work_ptr,a3@-  øfilesys (from getref)
  movl  #del_link_entry,a3@-
  movl  #stack,a3@-
  movw  #rwe,a3@-
  clrl  a3@-
  movl  a1,a3@-
 
  moveq #zero_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call      ø*call*
 
  unlk  a6
  tstb  d7
  bnes  99$
 
  clrl  d0
100$:
  unlk  a6
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
99$:
  movl  #-1,d0
  movl  #enoent,_errno
  bras  100$
 
eos_dup:
ø===============  and dup2
  bsr   print_call
  movl  a7@(4),d1       ød1:=old fildes;
  movl  a7@(8),d0       ød0:=new fildes (only if dup2)
  moveml #0x3f3f,a7@-
  bsr   disable
 
  cmpl  #0x40,d1        øif dup2_entry then (dup2 is marked by adding
                        ø                    hex 40 to old fildes)
  blts  1$
 
  subl  #0x40,d1        ø  remove dup2 mark;
  bsr   chck_fildes     ø  check new fildes (in d0)
  blt   100$
 
  bras  2$              øelse (ordinary dup entry)
1$:
  movl  d1,a7@-         ø  save old fildes
  bsr   find_fildes     ø  find unused fildes;
  tstl  d0
  blt   100$
  movl  a7@+,d1         ø  restore old fildes
2$:                     øend;
  movl  d0,a6           øa6:=new unused fildes;
  movl  d1,d0
  bsr   chck_fildes     øcheck old fildes
  blt   100$
 
  movl  a6,d0
 
ø* call clone to get duplicate
  link  a6,#-one_act
  movl  a6,a3
 
  addl  #ff_env,d1      ød1:=addr of old clone ptr
  movl  d1,a3@-         øoldclone
  movl  #dup_entry,a3@- ø   .dup
  clrl  a3@-            ø   (void valdata
  clrw  a3@-
  clrl  a3@-
  clrl  a3@-
 
  addl  #ff_env,d0      ød0:=addr of new clone ptr
  movl  d0,a3@-         øout newclone
  movw  #out_ptr,a3@-
  clrl  a3@-
  clrl  a3@-
 
  movl  #one_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call      øclone.dup
  bnes  90$
 
  unlk  a6
  movl  a6,d0           ød0:=new fildes again
  bsr   resv_fildes
100$:
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
90$:
  unlk  a6
  bras  100$
 
eos_fstat:
ø===============
  bsr   print_call
  movl  a7@(4),d0       ød0:=fildes
  movl  a7@(8),a0       øa0:=^buf
  moveml #0x3f3f,a7@-
  bsr   disable
 
  movl  a0,a7@-         øsave ^buf and fildes
  movl  d0,a7@-
 
ø* check fildes
  bsr   chck_fildes
  blt   100$
 
ø* try to call not-architected entry 'fstat' on fao
  link a6,#-one_act
  movl  a6,a3
 
  addl  #ff_env,d0      ød0:=fao's ptr addr
  movl  d0,a3@-         øfao
  movl  #fstat_entry,a3@- ø .fstat
  clrl  a3@-
  clrw  a3@-
  clrl  a3@-
  clrl  a3@-
 
  movl  #stack,a3@-     øfstatrec in auxstack
  movw  #rwe,a3@-
  clrl  a3@-
  movl  #30,a3@-        ølength of statrec
 
  moveq #one_act,d2
  movl  a7,d4
  moveq #obj_call,d5
  bsr   check_call
 
  unlk  a6
 
  tstb  d7
  bnes  5$
 
  movl  #30,d1          øcopy fstatrec to buf
  movl  f_stk,a1        øsource
  movl  a7@(4),a0       ødestination
3$:
  movb  a1@+,a0@+
  subl  #1,d1
  bnes  3$
5$:
 
  cmpw  #entry_ill,d7   øif res<>entry_illegal then return
  bne   100$
 
øentry illegal, try getfileinf instead:
  movl  a7@,d0          ød0:=saved fildes
  movl  a7@(4),a0       øa0:=save ^buf
 
  bsr   initstat
 
  movl  f_stk,a1
  movl  a1,d5
  moveq #4,d4
 
  addl  d4,a1           øout cylsize
  movw  d4,a1@+
 
  addl  d4,a1           øout minbufsize
  movw  d4,a1@+
 
  addl  d4,a1           øout datasize
  movw  d4,a1@+
 
  addl  d4,a1           øout bytes allocated
  movw  d4,a1@+
 
  addl  d4,a1           øout devclass
  movw  d4,a1@+
 
  addl  #pathname_size,a1 øout filename
  movw  #pathname_size,a1@+
 
  addl  d4,a1           øout localid
  movw  d4,a1@+
 
  subl  d5,a1           øa1:=length of valdata
  link  a6,#-one_act
  movl  a6,a3
 
  addl  #ff_env,d0      ød0:=fao's ptr addr
  movl  d0,a3@-
  movl  #getfileinf,a3@-
  movl  #stack,a3@-
  movw  #rwe,a3@-
  clrl  a3@-
  movl  a1,a3@-
 
  movl  #work_ptr,a3@-  øout iosys
  movw  #out_ptr,a3@-
  clrl  a3@-
  clrl  a3@-
 
  moveq #one_act,d2
  movl  a7,d4
  moveq #obj_call,d5
 
  bsr   check_call
 
  unlk  a6
 
  tstb  d7
  beqs  7$
 
  cmpw  #entry_ill,d7           øif illres=entry_ill then
  bnes  100$
 
  clrl  d0                      ø  return(ok_result);
  bras  100$                    øend;
7$:
  movl  f_stk,a1
  movl  a7@(4),a0               øa0:=save ^buf
  movl  a1@(24),d1              ød1:=devclass
  addl  #pathname_size+32,a1
  movw  a1@,a0@(st_dev)         øst_dev:=localid
  movw  a1@(2),a0@(st_ino)      øst_ino:=localid
  tstl  d1
  beqs  10$
 
  movw  #0020000,a0@(st_mode)   øif devclass=terminal then st_mode=char spec
  bras  11$
10$:
  movw  #0100000,a0@(st_mode)   øif devcalls=disc then st_mode:=regular
11$:
  movl  a1@(12),a0@(st_size)    øst_size:=datasize
  clrl  d0
100$:
  addl  #8,a7           øpop saved fildes and ^buf
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
 
eos_getpid:
ø================
  bsr   print_call
  moveml #0x3f3f,a7@-
  bsr   disable
 
  moveq #1,d1           ød1:=getpid func
  bsr   setgetid        øsetgetid(d1,d0:=id);
 
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
 
eos_stime:
ø==============
  bsr   print_call
  movl  a7@(4),a1       øa1:=^timeloc
  moveml #0x3f3f,a7@-
  bsr   disable
 
  movl  a1@,d0          ød0:=seconds
  movl  #settime_entry,a0
  bsr   getsetclock
  tstb  d7
  beqs  1$
 
  movl  #-1,d0
  bras  2$
1$:
  clrl  d0
2$:
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
 
eos_time:
ø==============
  bsr   print_call
  movl  a7@(4),a1       øa1:=^timeloc
  moveml #0x3f3f,a7@-
  bsr   disable
 
  movl  a1,a7@-         øsave ^timeloc
  movl  #gettime_entry,a0
  bsr   getsetclock
  movl  a7@+,a1         ørestore ^timeloc
 
  tstb  d7
  bnes  1$
 
  movl  a1,d1           øif ^timeloc<>null then
  beqs  1$              ø
 
  movl  d0,a1@          ø   timeloc^:=gettime;
1$:                     øendif;
 
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
 
eos_ftime:
ø==============
  bsr   print_call
  movl  a7@(4),a1       øa1:=^timeloc
  moveml #0x3f3f,a7@-
  bsr   disable
 
  movl  a1,a7@-         øsave ^timeloc
  movl  #gettime_entry,a0
  bsr   getsetclock
  movl  a7@+,a1         ørestore ^timeloc
 
  tstb  d7
  bnes  99$
 
  movl  d0,a1@          øtimeb.time:=gettime
  divu  #1000,d1
  movl  d1,a1@(4)       øtimeb.millitm:=microsecs/1000;
  movl  d2,a1@(6)       øtimeb.timezone
  movl  d3,a1@(8)       øtimeb.dst_flag
99$:
  bsr   enable
  moveml a7@+,#0xfcfc
  rts
 
small_stk:
ø==========
movl #no_resources,a5 ø future d7
movl a7,a4            ø future d6:= stacktop
bra prireturn
 
 
 
popsys:
  movl a7@+,a0  ø return addr
  movl a7@+,d0  ø syscall label
  subl  #systable,d0
  lsrl  #2,d0
  addl  #0xEE0000,d0
  movl a0,a7@-  ø return addr
btst #1,_eoscrtt
beqs 17$
  movl d0,a7@-  ø syscall index
  moveq #126,d0
  movl d0,a7@-
  movl a7,a7@-
  bsr _prthex
  addql #8,a7
  movl a7@+,d0     ø d0:= index
17$:
  rts
 
negative:
  bsr   print_state
  bsrs popsys
  movl d0,_errno       ø _errno:= syscall index + not implemented
  moveq #-1,d0         ø d0:= -1 ; "not ok"
  rts
 
 
ppositive:
  bsr   print_state
  bsrs popsys
  moveq #0,d0            ø d0:= 0 ; "ok"
  rts
 
.globl _trap9
_trap9:   ø called by c test programs
ø===================================
movl a7@(4),d0
movl _errno,d1
bsr     print_state
ø trap #9
rts
 
trp7: ø print arg and result of kernel call
btst #2,_eoscrtt
bnes 17$
trap #eos
rts
17$:
movl d5,a7@-
movl d4,a7@-
movl d2,a7@-
movl #hexop,d5
addql #1,d2
trap #eos ø print args
movl a7@,d2
movl a7@(4),d4
movl a7@(8),d5
trap #eos ø call operation
movl d7,a7@-
movl d6,a7@-
movl f_stk,d4
movl #32,d2
movl #hexop,d5
trap #eos ø print return value data
movl a7,d4
moveq #20,d2    ø  print regs
movl #hexop,d5
trap #eos ø print registers
movl a6@,d4
moveq #127,d2
movl #hexop,d5
trap #eos ø print stack below system call
movl a7@+,d6
movl a7@+,d7 ø restore original result of op
addl #12,a7 ø pop regs
rts
 
 
ø  trp7: ø testversion of trap #eos
movl a7,d7       ø save stack pointer
movl f_stk,a7    ø stack pointer:= first of stack;
ø movl #6,a7@    ø return value in get_ref,read and write
ø movl #3,a7@(6) ø return value in get_ref
trap #9     ø print regs and stack segm
movl d7,a7  ø restore stack pointer
ø moveq #0,d7 ø simulate
ø moveq #0,d6 ø simulate
trap #eos
rts
 
.globl _prttxt,_prthex
_prttxt:
moveq #1,d0
bra dollar1
_prthex:
moveq #2,d0
dollar1:
movl a7@(4),a0    ø a0:= address
movl a7@(8),d1    ø d1:= length
link a6,#-56
moveml #0x3FFF,a7@   ø save regs
movl a0,d4    ø d4:= address
movl d1,d2    ø d2:= length
addql #1,d2     ø compensate for odd addresses rounded down by the kernel
moveq #40,d5
swap d5
movw d0,d5
swap d5
trap #eos
tstb d7
beq 2$
moveq #-1,d7
bras 3$
2$: moveq #0,d7
3$: movl d7,a7@  ø saved d0:= result  ( 0 or -1)
moveml a7@,#0x3FFF   ø restor regs
unlk a6
rts
 
 
 
ø procedures shared between syscalls
ø
 
assfao:  ø d0=fildes, d1=create_mode d2=unix_io_mode, a4=name
ø========ø a5:= end_of_name, da:=???  saved d0 is on stack at call time.
ø
subql #2,d2          ø if unix_io_mode <0 or > 2
bgts 9$              ø then goto error
addql #3,d2          ø d2:= eos_io_rights:= unix_io_mode + 1;
bles 9$
link a6,#-one_act    ø a6:= top_arg, a7:= low_arg;
movl f_stk,a1        ø a1:= valdata:= f_stk;
movl a1,d5           ø d5:= valdata;
moveq #4,d3          ø d3:= length of integer:= 4;
movl d1,a1@+         ø push create mode in valdata
movw d3,a1@+         ø length of integer
movl d2,a1@+         ø push io_rights in valdata
movw d3,a1@+         ø length of integer
movl a7,d6
subql #4,d6          ø d6:= max destination; "protect the stack"
bsr mov_txt          ø mov_txt(a1/a4/d6=!,a1/a5/d7:=!);
blt small_stk        ø when destination to small goto stack to small
movw d7,a1@+         ø length of name in valdata
subl d5,a1           ø a1 := length of valdata:= valdata-top of valdata
movl a6,a3           ø a3:= top_arg
movl #fs_ref,a3@-    ø fs_ref
movl #assign_entry,a3@-    ø .assign
movl #stack,a3@-     ø valdata in stack
movw #7,a3@-
clrl a3@-
movl a1,a3@-         ø length of valdata
addl #ff_env,d0      ø d0:= pointer address into file_env;
movl d0,a3@-         ø 1. actual := pointer addr
movw #2,a3@-         ø return pointer
clrl a7@             ø actual type := pointer
moveq #one_act,d2    ø d2:= arg_length
movl a7,d4           ø d4:= low_arg
moveq #0,d5          ø d5:= obj_call
bsr check_call            ø call kernel
unlk a6              ø pop call
tstb d7
beqs 1$
bra obj_call_error   ø if result <> ok then goto obj_call_error;
1$: rts
9$:              ø error:
moveq #einval,d0 ø_errno:= invalid argument
movl d0,_errno
bra neg_d0
 
 
obj_call_error:   ø d6/d7=result, one 'rts' and saved d0 is on the stack
ø=============
ø
movw #1,_errno        ø _errno:= hex 10000
movw d7,_errno+2      ø        + family/cause
moveml #0x00C0,_erreos ø _erreos:= result in d6/d7
neg_d0:  ø
ø========ø
moveq #-1,d0          ø d0:= saved d0:= -1
movl d0,a7@(4)        ø ccr:= lt ;
rts                   ø return
 
 
 
mov_txt:  ø a1=first destination, d6=top destination, a4=first source
ø=========ø a1:= rounded next dest., a5:= end_source,
ø            d7:= #chars moved excl. null
ø
ø copy chars from a4 to a1 while a1 is increased. copying stops normally
ø after a null_char is reached, or abnormally if d6 is reached.
ø normal termination  : d7 >= 0, ccr = ge
øabnormal termination : d7 <  0, ccr = lt
ø
movl a1,d7           ø d7:= old destination
movl a4,a5           ø a5:= old source
1$:             ø next two chars:
cmpl a1,d6           ø when destination >= max_destination then
bles 9$              ø goto error
movb a5@+,a1@+       ø copy char, update a5/a1
beqs 2$              ø if null char goto normal termination
movb a5@+,a1@+       ø copy char, update a5/a1
bnes 1$              ø if not null char goto next two chars;
2$:             ø normal termination:
subql #1,a1          ø a1:= address of copied null char; "the top dest addr"
subl a1,d7           ø d7:= - #chars:= (top_destination - destination);
addql #1,a1
exg   a1,d7          ø d7:=:a1
bclr #0,d7           ø destnation has been rounded
exg   d7,a1          ø a1:=:d7
negl d7              ø d7:= #chars, ccr:= ge ;
rts
 
9$:             ø abnormal:
moveq #-1,d7         ø d7:= -1, ccr:= lt ;
rts
 
 
 
get_fs_ref: ø call objdir to get ref to file system
ø====================================================
ø a4=f_txt, saved d0 is assumed to be on top of stack
ø return:   ccr<>lt : ok return: a3=pos_txt,a4=f_txt,a5=top_txt,other=undef
ø            ccr=lt: error return (no item/no objdir etc)
link a6,#-one_act      ø a6:=top_arg; a7:=low_arg;
movl a7,d4             ø d4:=lowarg
movl f_stk,a1          ø d5:=a1:= first byte of stack
movl a1,d5
moveq #4,d7            ø d7:= length of integer
addql #4,a1            ø room for return integer: item_kind
movw d7,a1@+           ø length of int
addql #4,a1            ø room for return integer: used chars
movw d7,a1@+           ø length of int
movl a7,d6
subql #4,d6            ø d6:= max_destination
bsr mov_txt            ø mov_txt(a1=destin"updated",d6=max_destin,
                       ø         a4=f_txt,a5:=end_txt,d7:=length );
blts 9$                ø if stack to small goto error
movw d7,a1@+           ø length of name in val data
subl d5,a1             ø a1:= length of val data seg
movl a6,a3             ø a3:= top_arg
movl #objdir,a3@-      ø call objdir
movl #get_ref,a3@-     ø      .getref
movl #stack,a3@-       ø val data in stack
movw #3,a3@-
clrl a3@-
movl a1,a3@-           ø push length of val data seg
movl #fs_ref,a3@-      ø pointer address of pointer, to receive pointer to fs
movw #2,a3@-           ø return pointer
clrl a7@               ø actual type=pointer actual
moveq #one_act,d2
movl a7,d4
moveq #0,d5
bsr check_call
unlk a6
tstb d7
bnes 9$                    ø if result of call <> ok then goto error
movl f_stk,a1
movl a1@,d6            ø d6:= returned item kind , ccr:= ge (if objdir is ok)
moveq #legal_items,d7  ø d7:= ones for legal kinds;
btst d6,d7
beqs 9$                ø when illegal item kind then goto error
addql #6,a1
movl a1@,a3            ø a3:= returned used chars
addl a4,a3             ø a3:= pos address
clrl d7
rts                    ø return with ccr <> lt
9$:
moveml #0x00C0,_erreos ø save d6,d7
movl #enoent,_errno
moveq #-1,d0           ø d0:= saved d0:= -1
movl d0,a7@(4)
rts                    ø return with ccr=lt
 
 
 
check_nil:  ø d0=fildes, d7:=result, d0/d1/a4/a5/a6 survives
ø============================================================
ø d7=0 : Æf,1,d0+1Å is a nil pointer
ø d7=1 : fildes specifies a nonexsisting pointer
ø d7=4 : Æf,1,d0+1Å is not a nil pointer
ø
ø until ref_equal has been implemented by the kernal, the demo version
ø below will be used. the demo version assumes that used_fildes is
ø a correct reflection of the pointer situation.
ø
cmpl #19,d0
bhis 1$  ø when fildes < 0 or > 19 then goto error_1
movl used_fildes,d7
moveq #31,d6
subw d0,d6      ø d6:= bit# fildes := 31-fildes;
btst d6,d7
bnes 4$  ø when bit# fildes is set in used_fildes then goto error_4
moveq #0,d7     ø result = ok
rts
4$:
moveq #4,d7     ø result := fildes is not free
rts
1$:
moveq #1,d7     ø result := fildes is illegal
rts
 
 
 
find_fildes: ø compute unused fildes integer
ø============================================
ø returns -1 (_errno=emfile) or
ø         free fildes >=0 in d0
ø spoiles all registers except a4/a5/a6/a7
 
moveq #0,d0            ø d0:=fildes:=0
movl used_fildes,d1   ø d1:= help mask
1$:                ø next sign bit
blts 2$                ø when sign bit is on goto pointer in use
bsr check_nil          ø check_nil(d0=index,d7:=result,d1=same);
subqb #1,d7            ø d7=0 ok
beqs 9$                ø d7=1 pointer index too big, goto error
bgts 3$                ø d7=4 pointer not nil, try next
ø pointer is free:
rts                    ø return with index in d0
3$:                ø pointer was not nil
bsr resv_fildes        ø update bit in mask
2$:                ø bit was on, pointer in use:
addql #1,d0            ø d0:= next index
lsll #1,d1             ø next bit in mask
bras 1$                ø goto next sign bit
9$:                ø no free pointers
moveq #emfile,d0       ø errno:= emfile
movl d0,_errno
moveq #-1,d0           ø do:=no free:=-1
rts
 
 
resv_fildes: ø d0=fildes,d6/d7:=????
ø=============================================
bsr check_fildes ø returns only if fildes is ok
bset d7,d6       ø set the bit
movl d6,used_fildes
rts
 
check_fildes: ø dirty return is made below
ø==============================================
ø d0=fildes  d6:=used_fildes  d7:=bit# of fildes
moveq #31,d7
cmpl d7,d0
bhis 1$      ø when fildes <0 or > 31 goto dirty
subl d0,d7   ø d7:= bit# := 31-fildes
movl used_fildes,d6
rts               ø normal return
1$:  ø dirty
addql #4,a7       ø pop return
rts               ø dirty return
 
 
free_fildes: ø d0=fildes, d6/d7:=????
ø=============================================
bsr check_fildes    ø returns only if fildes ok
bclr d7,d6        ø clear the bit
movl d6,used_fildes
rts
 
 
 
ø eos implementations of unix system calls
ø in alfabetic order
 
eos_brk:
ø====================
 
  bsr   print_call
  moveq #0,d1
  movl d1,a1      ø a1:= ok_result:= zero;
  movl a7@(4),d1      ø d1:= new _top_bss := first argument;
  bras set_break
 
eos_sbrk:
ø===================
 
  bsr   print_call
  movl top_bss,a1     ø a1:= ok_result:= old top_bss;
  movl a7@(4),d1      ø d1:= new top_bss:= increment (=first argument)
  addl a1,d1          ø   +  old top_bss;
 
set_break:  ø  d1= new top_bss, a1= ok_result (zero or old top_bss)
ø=================================================
 
ø round up d1
  movl #pagemask,d0   ø d0:= 000...111 ;
  addl d0,d1          ø d1:= d1 + (pagesize-1);
  notl d0             ø d0:= 111...000 ;
  andl d0,d1          ø d1:= d1 div pagesize * pagesize;
  cmpl bsmax,d1       ø ccr:= d1-bsmax  (<= req.)
  bhis 9$             ø when d1 > bsmax goto error
ø cmpl top_data,d1    ø ccr:= d1-top_data   ( >  req.)
ø blss 9$             ø when d1 <= top_data goto error
  movl d1,top_bss     ø top_bss:= new top_bss;
  movl a1,d0          ø d0:= ok_result;
  rts
 
9$:                 ø error:
  moveq #enomem,d0  ø
  movl d0,_errno    ø ø _errno:= no memmory;
  moveq #-1,d0        ø d0:= not ok;
  rts
 
 
 
eos_close:   ø (fildes)
ø======================
 
close_frm=56
bsr     print_call
link a6,#-close_frm
moveml #0x3FFF,a7@    ø save regs
moveq #0,d0
movw a6@(10),d0       ø d0:= positive fildes
bsr     close_fildes
  movl  d0,a7@          øsaved d0
  beqs  1$
  movl  #ebadf,_errno
1$:
moveml a7@,#0x3FFF
unlk a6
rts
 
eos_create:
ø=================
 
bsr     print_call
moveq #neworold,d1 ø d1:= eos_create_mode; "this is a create call"
moveq #2,d0        ø a0:= unix io_mode:= write;
movl d0,a0
bra open_create
 
eos__exit:
ø===============
 
bsr     print_call
movl a7@(4),d0         ø d6:= exit status
 
main_exit:
ø=========
movl #orgsys,d6
movb d0,d6             ø d6:= orgsys, exit status;
lslw #8,d6             ø      shift 8
moveq #0,d7            ø d7:= return due to exit:= ok
moveq #1,d5            ø d5:= obj_return;
  bsr   print_state
trap #eos              ø call kernel
 
eos_lseek:
ø=====================
lseek_frm=56
bsr     print_call
link a6,#-lseek_frm
moveml #0x3FFF,a7@
movl a6,a5          ø a5:= arg base;
link a6,#-zero_act  ø a6:=a3:= top_arg, a7:= low_arg;
movl a6,a3
movl #ff_env,d0
addw a5@(10),d0     ø d0:= Æf,1,fildes+1Å
movl d0,a3@-        ø push fao address
moveq #seek,d0
movl d0,a3@-        ø push function = seek
movl #stack,a3@-    ø stack
movw #3,a3@-        ø holds
clrl a3@-           ø val data
moveq #18,d0        ø length of val data
movl d0,a3@-        ø := 18 = 3 * 6 (3 integers)
movl f_stk,a0       ø a0:= low stack
moveq #4,d7         ø d7:= length of integer
addql #4,a0         ø room for returned position
movw d7,a0@+        ø integer
movl a5@(12),a0@+   ø push offset bytes
movw d7,a0@+        ø integer
movl a5@(16),a0@+   ø push base mode
movw d7,a0@+        ø integer
cmpl a7,a0          ø ccr:= a0-a7 ( <=0 req.)
bgt small_stk       ø when a0 > a7 goto small_stack
moveq #zero_act,d2
movl a7,d4
moveq #obj_call,d5
bsr check_call
unlk a6
tstb d7
beqs 1$
bsr obj_call_error  ø when result <> ok then call obj_call_error;
bras 2$
1$: movl f_stk,a0
movl a0@,a7@        ø saved d0:= returned position
2$: moveml a7@,#0x3FFF ø restore regs
unlk a6
rts
 
 
 
eos_open:
ø================
 
bsr     print_call
moveq #oldfile,d1  ø d1:= eos_create_mode; "this is an open call"
movl a7@(8),a0     ø a0:= unix io_mode:= 2.arg
ø continue in open create
 
open_create: ø d1=eos_create_mode, a0=unix io_mode
opcr_frm=56+pathname_size
link a6,#-opcr_frm      ømake room for pathname + reg's
moveml #0x3FFF,a7@    ø save regs including d1,a0 with argument values
bsr find_fildes   ø d0:= fildes;
movl d0,a7@       ø saved d0:= fildes;
blts 1$           ø when error goto return
movl a6@(8),a4    ø a4:= name:= 1.arg
  movl  a6,a1
  subl  #pathname_size,a1       øa1:=first of path area
  movl  a6,d6                   ød6:=top of path area
  bsr build_name
  blts  1$
bsr get_fs_ref    ø get_fs_ref(a4=name,a3:=rest_name);
blts 1$           ø when error goto return
  bsr   print_state
movl a7@,d0       ø d0:= fildes;
movl a7@(4),d1    ø d1:= saved d1:=eos_create_mode;
movl a7@(32),d2   ø d2:= save a0:= unix io_mode;
movl a3,a4        ø a4:= file_name:= rest_name;
  bsr   print_state
bsr assfao        ø fs_ref.assign(d0/d1/d2/a4=!)
bnes 1$           ø when errror goto return
movl a7@,d0       ø d0:= fildes
bsr resv_fildes   ø reserve fildes (d0=fildes,d6/d7:=?)
movl a7@(4),d1    ø d1:=eos_create_mode;
cmpl #oldfile,d1  ø test if oldfile was used as create mode
beqs 1$           ø if open was called (oldfile was used) goto return
  bsr   print_state
bsr cut_file      ø cut_file to zero bytes (create was called)
1$:            ø return:
moveml a7@,#0x3FFF
unlk a6
rts
 
cut_file:    ø d0=fildes
 
link a6,#-zero_act      ø a6:= top_arg; a7:= lowarg;
movl a6,a3              ø
movl d0,a3@-
addl #ff_env,a3@        ø push pointer to fao
moveq #datasize,d1
movl d1,a3@-            ø push function code
movl #stack,a3@-        ø value data
movw #7,a3@-            ø argument
clrl a3@-
moveq #6,d1
movl d1,a3@-            ø in first 6 bytes of stack segment
movl f_stk,a0           ø room is present because assfao could be called
clrl a0@+               ø data size of file:= 0;
movw #4,a0@+            ø integer
movl a7,d4              ø low_arg
moveq #zero_act,d2      ø length of arg
moveq #0,d5             ø obj_call
bsr check_call               ø call kernel
unlk a6
rts
 
 
 
eos_read:
ø====================
moveq #readseq,d0
movl d0,a1           ø a1:=function code := readseq;
øcontinue in read_write below
 
read_write:   ø a1= function = read or write
rw_frm=56
link a6,#-rw_frm
moveml #0x3FFF,a7@   ø save regs
50$:
  movl a6@(8),d0        ø d0:= fildes
  movl a6@(12),a0       ø a0:= buf
  movl a6@(16),d1       ø d1:= nbytes
  movl a6@(-20),a1      ø restore a1=function code
link a6,#-one_act    ø room for kernel call
ømik 83-10-14:
  øbuf may be in one of three segments: code, localdata, or stack
  movl  f_stk,a2
  cmpl  a2,a0           øif buf >= f_stk then
  blts  1$              ø  (buf is in stack)
 
  movl  #stack,d2
  subl  a2,a0           ø  a0:=offset
  bras  22$             øelse
1$:
  movl  f_data,a2       ø  if buf >= f_data then
  cmpl  a2,a0           ø    (buf is in localdata)
  blts  2$
 
  movl  #localdata,d2
  subl  a2,a0           ø    a0:=offset;
  bras  22$             ø  else
2$:
  movl  #code,d2        ø    (buf is in code segment, a0 is offset)
22$:                    øendif;
 
movl    f_stk,a2
moveq #4,d7          ø d7:= integer type:= 4;
moveq #1,d6          ø mode:= unix-i/o := 1;
movl d6,a2@+         ø mode is a call value;
movw d7,a2@+         ø mode is an integer;
addql #4,a2          ø room for return integer: nbytes
movw d7,a2@+         ø integer
cmpl a7,a2           ø ccr:= a2-a7  ( <= req.)
bles    23$
bsr small_stk        ø when a2 > a7 then goto small_stack;
23$:
movl a6,a3           ; a3:= top of arg
addl #ff_env,d0      ; d0:= pointer addres to fao
movl d0,a3@-         ø push pointer addr
movl a1,a3@-         ø push function (read_seq or write_seq)
movl #stack,a3@-     ø value data in stack
movw #7,a3@-
clrl a3@-
moveq #12,d7
movl d7,a3@-         ø 12 bytes valuedata
movl d2,a3@-         ø create sub seg argument for buf
movw #3,a3@-         ø read+write allowed
movl a0,a3@-         ø offset to buf
movl d1,a3@-         ø length of buf
moveq #one_act,d2    ø d2:= length of arg
movl a7,d4           ø d4:= low_arg
moveq #0,d5          ø d5:= obj_call
trap    #eos
unlk a6              ø pop call
tstb d7              ø mik mak
beqs 3$
ømik 83-10-17:
  bsr   print_state
  cmpw  #breakstatus,d7
  beqs  110$
 
  cmpw  #breakreject,d7
  beqs  110$
 
  cmpw  #pipe_broken,d7
  beqs  120$
 
  bras  33$
 
110$:                   øcase break condition:
  movl  a6@(8),d0       ørestore fildes;
  link  a6,#-zero_act
  movl  a6,a3
 
  addl  #ff_env,d0      ød0:=ptr addr of fao
  movl  d0,a3@-
  movl  #waitready,a3@- ø     .waitready
  clrl  a3@-            ø      void valdata
  clrw  a3@-
  clrl  a3@-
  clrl  a3@-
 
  moveq #zero_act,d2
  movl  a7,d4
  moveq #obj_call,d5
 
  bsr   check_call
  unlk  a6              øpop call
  tstb  d7
  bnes  33$
 
  bra   50$             øif waitready=ok then repeat i/o
ø changed 83-12-06/mik:  NO! PROBLEM!? scheduling of speed-up...
ø movl  #eintr,_errno
ø bsr   neg_d0          øvir's gylle
ø bras  4$
 
120$:           øcase pipe_broken:
  moveq #sigpipe,d1
  moveq #sendsig_to_self,d0
  bsr   sigsag          ø   emul.sigsag(myself,broken_pipe);
  tstb  d7
  bnes  33$
 
  bras  3$
33$:                    øend case;
bsr obj_call_error   ø if result <> ok then pack result and saved d0
bra 4$               ø else
3$: movl f_stk,a0    ø a0:= val data
movl a0@(6),a7@      ø saved d0:= returned byte count;
btst #3,_eoscrtt
beqs 17$
movl a7@(32),a0      ø length is already on stack
movl a0,a7@-         ø push buf address
bsr _prthex          ø print io buffer
addql #4,a7          ø pop address
17$:
4$: moveml a7@,#0x3FFF
unlk a6
rts
 
 
eos_write:
ø===============
 
moveq #writeseq,d0
movl d0,a1          ø a1:= function:= write
bra read_write
 
 
 
ø below follows the systable. all calls to syscalls jumps via this table
ø
.globl _e_link,_e_unlin,_e_mknod,_e_chmod,_e_chown,_e_stat
.globl _e_mount,_e_umoun,_e_setui,_e_getui,_e_stime,_e_ptrac
.globl _e_fstat,_e_utime,_e_nice,_e_sync,_e_times,_e_profi
.globl _e_locki,_e_setgi,_e_getgi,_e_acct,_e_phys,_e_lock
.globl _e_ioctl,_e_umask,_e_dup2
.globl _e_geteu,_e_geteg
systable:
__exit:     bra eos__exit      ø 01 terminate a process
_fork:      bra eos_fork       ø 02 fork a new process
_read:      bra eos_read       ø 03 read from a file
_write:     bra eos_write      ø 04 write to a file
_open:      bra eos_open       ø 05 open a file for read or write
_close:     bra eos_close      ø 06 close a file
_wait:      bra eos_wait       ø 07 wait for a process to terminate
_creat:     bra eos_create     ø 08 create a new file
_link:      bra eos_link      ø 09 link to a file
_unlink:    bra eos_unlink     ø 10 remove a directory entry
_exec:      bsr     negative   ø 11 execute a file (obsolete?)
_chdir:     bra eos_chdir      ø 12 change current working directory
_time:      bra eos_time       ø 13 get date and time
_mknod:     bra eos_mknod      ø 14 make a directory or a special file
_chmod:     jmp _e_chmod      ø 15 change mode of a file
_chown:     jmp _e_chown      ø 16 change owner and group of a file
_brk:       bra eos_brk        ø 17 extend heep segment
_stat:      jmp _e_stat       ø 18 get status of a file
_lseek:     bra eos_lseek      ø 19 position in a file
_getpid:    bra eos_getpid     ø 20 get process id
_mount:     jmp _e_mount      ø 21 mount a file system
_umount:    jmp _e_umoun     ø 22 unmount a file system
_setuid:    jmp _e_setui     ø 23 set user id
_getuid:    jmp _e_getui     ø 24 get user id
_stime:     bra eos_stime      ø 25 set time
_ptrace:    jmp _e_ptrac    ø 26 process trace
_alarm:     bra eos_alarm      ø 27 schedule signal after specified time
_fstat:     bra eos_fstat      ø 28 get file status
_pause:     bra eos_pause      ø 29 stop until signal
_utime:     jmp _e_utime      ø 30 set file times
_stty:      jmp _e_stty       ø 31 stty is obsolete
_gtty:      jmp _e_gtty       ø 32 gtty is obsolete
_access:    bra eos_access     ø 33 determine accessibility of a file
_nice:      jmp _e_nice       ø 34 set program priority
_ftime:     bra eos_ftime      ø 35 get date and time
_sync:      jmp _e_sync       ø 36 update the super block
_kill:      bra eos_kill       ø 37 send signal to kill a process
            bsr     negative   ø 38 not assigned
            bsr     negative   ø 39 not assigned
            bsr     negative   ø 40 tell is obsolete
 
 
 
_dup:       bra eos_dup        ø 41 duplicate an open file descriptor
_pipe:      bra eos_pipe       ø 42 create an interprocess channel
_times:     jmp _e_times      ø 43 get process times
_profil:    jmp _e_profi     ø 44 make execution time profile
_locking:   jmp _e_locki    ø 45 file concurrency control
_setgid:    jmp _e_setgi     ø 46 set group id
_getgid:    jmp _e_getgi     ø 47 get group id
_signal:    bra eos_signal     ø 48 catch or ignore signals
            bsr     negative   ø 49 not assigned
            bsr     negative   ø 50 not assigned
_acct:      jmp _e_acct       ø 51 turn accounting on or off
_phys:      jmp _e_phys       ø 52 map user virtual address to physical memory
_lock:      jmp _e_lock       ø 53 lock a process in primary memory
_ioctl:     jmp _e_ioctl      ø 54 control device
            bsr     negative   ø 55 not assigned
_mpxchan:   bsr     negative   ø 56 ??
            bsr     negative   ø 57 not assigned
            bsr     negative   ø 58 not assigned
_execve:    bra eos_execve     ø 59 execute a file
_umask:     jmp _e_umask      ø 60 set file creation mode mask
_chroot:    bra eos_chroot     ø 61 change root directory
            bsr     negative   ø 62 not assigned
            bsr     negative   ø 63 not assigned
            bsr     negative   ø 64 not assigned
            bsr     negative   ø 65 not assigned
_outline:   bsr     negative   ø 66 mio?
_inpline:   bsr     negative   ø 67 mio?
_putl:      bsr     negative   ø 68 mio?
_getl:      bsr     negative   ø 69 mio?
_gethc:     bsr     negative   ø 70 mio?
_get1b:     bsr     negative   ø 71 mio?
_put1b:     bsr     negative   ø 72 mio?
_macsbug:   bsr     negative   ø 73 mio?
            bsr     negative   ø 74 not assigned
            bsr     negative   ø 75 not assigned
_sbrk:      bra eos_sbrk       ø 76 extend heep segment
_dup2:      jmp _e_dup2       ø 77 duplicate filedescriptor
            bsr     negative   ø 78 not assigned
            bsr     negative   ø 79 not assigned
            bsr     negative   ø 80 not assigned
_setmem:    bsr     negative   ø 81 ??  81=64+17, 17=_brk
            bsr     negative   ø transmission problem ?
_geteuid:   jmp _e_geteu
_getegid:   jmp _e_geteg
 
 
 
ø end of eos syscalls
«eof»