|
|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 92544 (0x16980)
Types: TextFile
Names: »SYSCALLS.SS«
└─⟦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«
ø 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»