-
Notifications
You must be signed in to change notification settings - Fork 6
/
kernel.asm
2049 lines (1665 loc) · 57.2 KB
/
kernel.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;; Ram's Kernal
;; Madison Burke / Christian / Aneesh
.Code
;;; %G4 should still hold ram base
;;; %G5 should have kernal.length
;;; %G3 should have ram limit
;;; All functions must be CALLED now
COPY %G0 *0x1028 ;%G0 holds kernal base
COPY %G1 *0x102c ;%G1 holds kernal limit
SUBUS %G5 %G1 %G0 ;%G5 is kernal.length
COPY %G4 *0x1010 ;%G4 holds ram base
COPY %G0 *0x1014 ;%G0 holds ram limit
COPY %SP +RAM_limit ;Need extra register temporarily
COPY *%SP %G0 ;Ram_limit saved
ADD %G5 %G5 %G4 ;%G5 is ramkernal.limit
COPY %G0 +kernel_limit
COPY *%G0 %G5
COPY %SP %G5 ; initialize Stack and Frame pointer
COPY %FP %SP
COPY %G0 +kernel_base
COPY *%G0 %G4
COPY %G0 +ALM
ADDUS %G0 %G0 4
COPY *%G0 0x10
find_free_RAM:
BEQ +set_trap_base *%G5 0 ;Branch if Ram is empty
ADD %G5 %G5 16 ;else, check next instruction
JUMP +find_free_RAM
set_trap_base:
SETTBR %G5 ;Set trap base register to fresh ram
COPY %G0 0 ;Refresh %G0
COPY %G1 0
set_trap_table:
BEQ +clock_alarm_interrupt %G0 3
BEQ +system_call_interrupt %G0 9
COPY *%G5 +end
ADD %G0 %G0 1
ADD %G5 %G5 4
JUMP +set_trap_table
clock_alarm_interrupt:
COPY *%G5 +clock_Alarm
ADD %G0 %G0 1
ADD %G5 %G5 4
JUMP +set_trap_table
system_call_interrupt:
COPY *%G5 +system_Call
ADD %G0 %G0 1
ADD %G5 %G5 4
BGT +process_table_base_setup %G0 9
end: HALT ;Where all interrupts return atm
;; Set up process table base
process_table_base_setup:
ADDUS %G5 %G5 8 ; Balance it back out
COPY *%G5 0x210000 ; Halt after trap table
ADDUS %G5 %G5 16 ; %G5 is my pointer
COPY %G0 +IB ; Interrupt Buffer label set up
SETIBR %G0
COPY %G0 +process_table_base
COPY *%G0 %G5
COPY %G0 +next_free_process
COPY *%G0 %G5
COPY %G0 +process_table_pointer_base
COPY *%G0 %G5
COPY %G0 +process_table_pointer
COPY *%G0 *+process_table_pointer_base
ADDUS %G5 %G5 0x540
COPY %G0 +process_table_limit
COPY *%G0 %G5 ; Processes table can hold 24 processes atm
COPY %G0 +kernel_limit
ADDUS *%G0 %G5 1520 ; Extend kernal limit to include stack and process table
ADDUS %SP 0x5000 *+kernel_limit ; Initialize stack pointer
COPY %FP %SP
COPY %G0 +next_free_RAM
COPY *%G0 %SP
ADDUS *%G0 *+next_free_RAM 4
;;; Set kernal's place in process table using process_table_Add (Process table ADD function).
COPY %G0 +return
CALL +process_table_Add_Args *%G0 ; Decrements %SP automatically
COPY *%SP *+kernel_base ; P_add's 1st argument: BASE
SUBUS %SP %SP 4
COPY *%SP *+kernel_limit ; P_add's 2nd argument: LIMIT
SUBUS %SP %SP 4
COPY *%SP 0x01 ; 3rd arg: 1 means kernal is an active process
SUBUS %SP %SP 4
COPY *%SP *+total_PIDs ; 4th: kernel is its own parent
CALL +process_table_Add *%G0
;; All above this is successful.
COPY %G0 +kernel_limit
ADDUS *%G0 *+kernel_limit 0x5000
;;; Let's find the console.
procedure_find_console:
COPY %G0 4 ; Type
COPY %G1 1 ; Instance
COPY %G2 0x1000 ; Bus controller base
find_device_loop_top:
;; End the search with failure if we've reached the end of the table without finding the device.
BEQ +find_device_loop_failure *%G2 0
;; If this entry matches the device type we seek, then decrement the instance count. If the instance count hits zero, then
;; the search ends successfully.
BNEQ +find_device_continue_loop *%G2 %G0
SUB %G1 %G1 1
BEQ +find_device_loop_success %G1 0
find_device_continue_loop:
;; Advance to the next entry.
ADDUS %G2 %G2 12
JUMP +find_device_loop_top
find_device_loop_failure:
;; Set the return value to a null pointer.
HALT
find_device_loop_success:
;; Save the console base and limit in statics
ADDUS %G2 %G2 4
COPY %G0 +console_base
COPY *%G0 *%G2
ADDUS %G2 %G2 4
COPY %G0 +console_limit
COPY *%G0 *%G2
;; Fall through...
COPY %G0 +return ; console_base found
CALL +process_table_Print *%G0 ; works
;;; Let's find the block_device.
procedure_find_block:
COPY %G0 5 ; Type
COPY %G1 1 ; Instance
COPY %G2 0x1000 ; Bus controller base
find_block_loop_top:
;; End the search with failure if we've reached the end of the table without finding the device.
BEQ +find_block_loop_failure *%G2 0
;; If this entry matches the device type we seek, then decrement the instance count. If the instance count hits zero, then
;; the search ends successfully.
BNEQ +find_block_continue_loop *%G2 %G0
SUB %G1 %G1 1
BEQ +find_block_loop_success %G1 0
find_block_continue_loop:
;; Advance to the next entry.
ADDUS %G2 %G2 12
JUMP +find_block_loop_top
find_block_loop_failure:
;; Set the return value to a null pointer.
HALT
find_block_loop_success:
;; Save the console base and limit in statics
ADDUS %G2 %G2 4
COPY %G0 +block_base
COPY *%G0 *%G2
ADDUS %G2 %G2 4
COPY %G0 +block_limit
COPY *%G0 *%G2
COPY %G0 +block_trigger
COPY %G2 +block_limit
SUBUS *%G0 *%G2 4 ;; initialize address of trigger on block device
COPY %G0 +block_num
SUBUS *%G0 *%G2 8 ;; initialize address of block device block # input
COPY %G0 +block_buffer_limit
SUBUS *%G0 *%G2 12 ;; initialize address for buffer limit (base + 4096)
;; 1. WRITE CODE TO COPY INIT TO RAM HERE, THEN JUMP TO IT.
;; If 0x1030 is 2, copy and run it. Else, do nothing.
COPY %G1 *0x1030 ; type of next ROM
BNEQ +end %G1 2 ; if it isn't a program (init hopefully), HALT
SUBUS %G2 *0x1038 *0x1034 ; length of next program
ADDUS %G2 %G2 *+next_free_RAM ; limit in RAM of new process
COPY %G0 +return
CALL +copy_Args *%G0 ; Going to copy the program to RAM
COPY *%SP *0x1034 ; Base
SUBUS %SP %SP 4
COPY *%SP *0x1038 ; Limit
SUBUS %SP %SP 4
COPY *%SP *+next_free_RAM ; Destination (Correct)
;; successful ^^
CALL +copy *%G0 ; Begin copying
CALL +process_table_Add_Args *%G0
COPY *%SP *+next_free_RAM ; Base of init in RAM
SUBUS %SP %SP 4
COPY *%SP %G2 ; Limit of init
SUBUS %SP %SP 4
COPY *%SP 0x01 ; Status
SUBUS %SP %SP 4
COPY *%SP 0x00 ; Kernel is this program's parent
CALL +process_table_Add *%G0 ; Need to make PTADD more automatic.
;; this is a function call to "fileExists" function, and a few other tricks.
COPY %G0 +return ;; copy +return into a register
file_adding_test: ;;Let's add two files to the directory!
CALL +fileExists_Args *%G0 ;; call the functions Args section
COPY *%SP +file_name ;; copy your argument into the SP
CALL +fileExists *%G0 ;; call the function itself.
;; complete function call!
COPY %G3 *%SP ;; Copy result from fileExists into %G3
ADDUS %SP %SP 4
BEQ +add_file1_to_block_device %G3 0 ;; if it returned 0, then file not found
CALL +fileExists_Args *%G0
COPY *%SP +file_name2
CALL +fileExists *%G0
COPY %G3 *%SP ;; checking if file2 exists in your block_device
ADDUS %SP %SP 4
BEQ +add_file2_to_block_device %G3 0
JUMP +finish_file_adding_test ;; if both files exist, then we'll begin running processes
add_file1_to_block_device: ;; if file1 not found, lets add it to the directory
CALL +input_File_Args *%G0
COPY *%SP +file_name
CALL +input_File *%G0
JUMP +file_adding_test
add_file2_to_block_device: ;; if file2 not found, lets add it to the directory too
CALL +input_File_Args *%G0
COPY *%SP +file_name2
CALL +input_File *%G0
JUMP +file_adding_test
finish_file_adding_test:
; CALL +delete_File_Args *%G0
; COPY *%SP +file_name
; CALL +delete_File *%G0
; CALL +fileExists_Args *%G0
; COPY *%SP +file_name
; CALL +fileExists *%G0
; HALT
;; Run init, if it exists.
;; everything above this works.
JUMP +process_table_Run_Next
HALT ;Will set up init later
;;; Setup can only be run when total_PIDs is 1. Otherwise, it halts.
;;; Copy Init to Ram, and run it.
;;; Search Function: Checks block of data for particular item.
;;; Returns the address the item is at if found, or 0x00 if not found.
;;; Will help when picking next PID.
;;; args: 1. ITEM, 2. BASE, 3. LIMIT, 4. Increment results: 1
search_Args:
SUBUS %SP %SP 4
JUMP +fArgs
search:
SUBUS %SP %SP 4
COPY *%SP 1
COPY %G0 +return2
CALL +fCall *%G0
COPY %G0 *%FP ; ITEM
ADDUS %FP %FP 4
COPY %G1 *%FP ; BASE
ADDUS %FP %FP 4
COPY %G2 *%FP ; LIMIT
ADDUS %FP %FP 4
COPY %G3 *%FP ; By how much to increment, 4 is typical
COPY %G4 0x00 ; RESULT not yet found
search1:
BEQ +search2 %G0 *%G1 ; Checks to see if GO item is in address in G1
BEQ +search3 %G1 %G2 ; Finishes when G1 equals G2
ADD %G1 %G1 %G3 ; Increments G1 by %G3
JUMP +search1 ; LOOP
search2:
COPY %G4 %G1 ;Copies address in G1 to G5
search3:
SUBUS %SP %SP 4
COPY *%SP %G4 ; Buries its result
ADDUS %SP %SP 4
JUMP +fDone ; Jumps to fdone.
;;;Copy Function: Copies block of data from one place to another
;;;args: 1. BASE, 2. LIMIT, 3. DESTINATION results: 0
copy_Args:
JUMP +fArgs
copy:
SUBUS %SP %SP 4
COPY *%SP 0
COPY %G0 +return2
CALL +fCall *%G0
COPY %G0 *%FP ;Gets base
ADDUS %FP %FP 4
COPY %G1 *%FP ;Gets limit
ADDUS %FP %FP 4
COPY %G3 *%FP ;Gets destination base
copy1:
BGTE +copy2 %G0 %G1
COPY *%G3 *%G0
ADDUS %G0 %G0 4
ADDUS %G3 %G3 4
JUMP +copy1
copy2: ;G3 has base in RAM, and G0 has limit in RAM
;; next_free_RAM will change after the copy, during the process_add call.
JUMP +fDone
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; INTERRUPT HANDLERS ;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Interrupt # 2: CLOCK ALARM
;;; It's set to only work if +process_table_total_processes > 1
clock_Alarm:
SETALM *+ALM 0x00
;; Check if an interrupt handler was interrupted.
;; Later
ADDUS %SP %SP *+BS ; SP becomes physical again / Must be after every interrupt.
SUBUS %SP %SP 4
COPY *%SP %G0 ; save %G0 contents
COPY %G0 +return
COPY *%G0 +clock_Alarm1
COPY %G0 *%SP
ADDUS %SP %SP 4
JUMP +process_table_Update_Process_Args
clock_Alarm1:
COPY *%SP *+current_PID ;PT_update 1st arg: PID
COPY %G0 +return
SUBUS %SP %SP 4
COPY *%SP 0x01 ;PT_update 2nd arg: Status
CALL +process_table_Update_Process *%G0
;;Getting Kernel Info back. (probably irrelevant)
COPY %G0 +BS
COPY *%G0 0 ;Return BS to 0.
COPY %G0 +return
COPY %G5 %SP
CALL +process_table_Restore_Args *%G0 ; Restoring Kernel's info
COPY *%SP 0 ; PID of process to be restored
COPY %G0 +return
CALL +process_table_Restore *%G0 ; Kernel's registers restored
;; Running next process
JUMP +process_table_Run_Next
;; Interrupt #9: SYSTEM CALL
;;; Behold, the system call function.
;;; The arguments it takes should be put in numerics mode, right after the call
;;; Args: 1. type; The rest of the arguments depend on the type. Details in README.
system_Call:
SETALM *+ALM 0x00
;;; Save prog's registers in temp space, will then use process_table_Update_Process to put them in process table
;;; check IB for address of syscall, save it in %G0, and add 16 to %G0 to point at the syscall type
;;; If Syscall type is 1, then jump to +sys1(setup)
;; Save registers in temp without using registers
system_Call0:
ADDUS %SP %SP *+BS ; SP becomes physical again / Must be after every interrupt.
SUBUS %SP %SP 4
COPY *%SP %G0 ; save %G0 contents
COPY %G0 +syscall_Type
COPY *%G0 *%SP
COPY %G0 +syscall_Arg1
ADDUS *%G0 %G1 *+BS
COPY %G0 +syscall_Arg2
ADDUS *%G0 %G2 *+BS
COPY %G0 +syscall_Arg3
ADDUS *%G0 %G3 *+BS
COPY %G0 +syscall_Arg4
ADDUS *%G0 %G4 *+BS
COPY %G0 +syscall_Arg5
ADDUS *%G0 %G5 *+BS
COPY %G0 +return
COPY *%G0 +system_Call1
COPY %G0 *%SP
ADDUS %SP %SP 4
JUMP +process_table_Update_Process_Args
system_Call1:
COPY *%SP *+current_PID ;PT_update 1st arg: PID
COPY %G0 +return
SUBUS %SP %SP 4
COPY *%SP 0x01 ;PT_update 2nd arg: Status
CALL +process_table_Update_Process *%G0
;;Process's register information is secure
;;Need address of syscall
COPY %G0 +address_of_interruption
ADDUS *%G0 *+BS *+IB ;%G0 has place of interruption
;; Need to get Kernel's registers back.
COPY %G0 +BS
COPY *%G0 0 ;Return BS to 0.
COPY %G0 +return
CALL +process_table_Restore_Args *%G0 ; Restoring Kernel's info
COPY *%SP 0 ; PID of process to be restored
COPY %G0 +return
CALL +process_table_Restore *%G0 ; Kernel's registers restored
COPY %G0 *+address_of_interruption ;%G0 has physical address of syscall
ADDUS %G0 %G0 16 ; Address right after syscall
BEQ +system_setup *+syscall_Type 1 ; setup is syscall arg is 1
BEQ +system_exit *+syscall_Type 0 ; exit if syscall arg is 0
BEQ +system_fork *+syscall_Type 2 ; fork if syscall arg is 2
BEQ +system_write *+syscall_Type 5 ; write if syscall is 5
BEQ +system_read *+syscall_Type 4 ; read if syscall is 4
;; The address after the syscall had none of them
HALT
system_setup:
;; Get current_PID, if it's not 1, HALT
BNEQ +system_setup_denied *+current_PID 1
;; Get the base of the process that called SysCall[1]
;; For now I'll assume only init can use it, and thus I'll use
;; the bus controller to find init's base.
COPY %G5 *+kernel_limit ; Init base
COPY %G0 +next_free_RAM ; to overwrite init
COPY *%G0 %G5
COPY %G0 +return
CALL +process_table_Remove_Args *%G0
COPY *%SP 1
CALL +process_table_Remove *%G0 ;Remove process 1 (init) from process table
COPY %G1 0x103c ; type of next Rom
system_setup_copy:
BNEQ +system_setup_complete *%G1 2
ADDUS %G1 %G1 4
COPY %G2 *%G1 ;%G2 has base of new program
ADDUS %G1 %G1 4
COPY %G3 *%G1 ;%G3 has limit of new program
ADDUS %G1 %G1 4
;; Copy program to RAM
CALL +copy_Args *%G0
COPY *%SP %G2 ; Base of new program ROM
SUBUS %SP %SP 4
COPY *%SP %G3 ; Limit of new program ROM
SUBUS %SP %SP 4
COPY *%SP *+next_free_RAM ; next free RAM
CALL +copy *%G0
;; Put program in ProcessTable (need: Base, Limit, Status, Parent)
CALL +process_table_Add_Args *%G0
COPY *%SP *+next_free_RAM
SUBUS %SP %SP 4
SUBUS %G4 %G3 %G2 ; Length of program
ADDUS %G4 %G4 *+next_free_RAM ; it's limit in ram
COPY *%SP %G4
SUBUS %SP %SP 4
COPY *%SP 0x01 ; Assuming all initialized progs are active for now
SUBUS %SP %SP 4
COPY *%SP *+current_PID ; init is the parent
CALL +process_table_Add *%G0
;;Loop
JUMP +system_setup_copy
system_setup_complete:
JUMP +process_table_Run_Next
system_setup_denied:
;; only process 1 (init) can use the system_setup call.
HALT
system_exit:
;; Will halt for now (system.exit)
COPY %G0 +return
CALL +process_table_Remove_Args *%G0
COPY *%SP *+current_PID
CALL +process_table_Remove *%G0
JUMP +process_table_Run_Next
system_fork:
;; Will halt for now (system.fork)
HALT
;; Save temp in process table entry of current process
;; Need process_table_Update_Process_Current function
;; System_write expects at least 3 arguments, with %G4 being an optional argument
;; %G1 = pointer to filename; %G2 = pointer to file start; %G3 = pointer to file end; %G4 = permissions (4 bits, blank,r,w,x)
system_write: ; saving to block device buffer
;; syscall_Arg1 has the filename, syscall_Arg2 has the start address, syscall_Arg3 has the end address
COPY %G1 *+syscall_Arg1
COPY %G2 *+syscall_Arg2
COPY %G3 *+syscall_Arg3
;; syscall_Arg1 was copied to %G1, syscall_Arg2 to %G2, syscall_Arg3 to %G3
COPY %G4 +return
CALL +fileExists_Args *%G4
COPY *%SP %G1
CALL +fileExists *%G4 ; fileExists returns block number of file
COPY %G4 *%SP ; %G4 contains block number of file
ADDUS %SP %SP 4 ; undo decrementing of SP from the fileExists function
BEQ +file-not-found %G4 0
file-found:
COPY %G5 +return
CALL +write_block_Args *%G5
COPY *%SP %G2
SUBUS %SP %SP 4
COPY *%SP %G3
SUBUS %SP %SP 4
COPY *%SP %G4
CALL +write_block *%G5
;; HALT if debug
JUMP +process_table_Run_Next
file-not-found:
COPY %G5 +return
CALL +input_File_Args *%G5
COPY *%SP %G1
CALL +input_File *%G5
CALL +fileExists_Args *%G5 ;; call the functions Args section
COPY *%SP %G1 ;; copy your argument into the SP
CALL +fileExists *%G5 ;; call the function itself.
COPY %G3 *%SP ;; Copy result from fileExists into %G3
ADDUS %SP %SP 4
BEQ +file-failure %G3 0 ;; if it returned 0, then file not found
JUMP +file-found
file-failure:
HALT
system_read:
HALT
;;;These functions are used to manipulate the process table.
;;; Process Add Function: Prepares process table for the new process (some info not updated)
;;; Typically called right before process is copied into ram. Auto adds 720 extra space to process's limit.
;;; args: 1. BASE(in ram), 2. LIMIT, 3. ACTIVE, 4. Parent PID results: 0
process_table_Add_Args:
JUMP +fArgs
process_table_Add:
SUBUS %SP %SP 4
COPY *%SP 0
COPY %G0 +return2
CALL +fCall *%G0
COPY %G0 *%FP ;%G0 is BASE
ADDUS %FP %FP 4
ADDUS %G1 *%FP 0x5000 ;%G1 is LIMIT
ADDUS %FP %FP 4
COPY %G2 *%FP ;%G2 is ACTIVE
ADDUS %FP %FP 4
COPY %G3 *%FP ;%G3 is Parent PID
COPY *%FP 0x00 ; 0 means no pocket space in PT
COPY %G4 *+next_free_process ;%G4 has next empty space in process table
;; Checking for pocket space
BEQ +PTA1 *+process_table_pocket_space 0
COPY *%FP 1 ;means don't change next_free_process later
COPY %G4 +return
CALL +search_Args *%G4
COPY *%SP 0 ; Item (is an empty space)
SUBUS %SP %SP 4
ADDUS *%SP *+process_table_base 56 ;Base (entry after kernel)
SUBUS %SP %SP 4
COPY *%SP *+process_table_limit ;Limit
SUBUS %SP %SP 4
COPY *%SP 56 ;Increment(only looking at pids)
CALL +search *%G4
COPY %G4 *%SP ; Copy base of free_space to %G4
ADDUS %SP %SP 4 ;put SP back
PTA1:
COPY *%G4 *+total_PIDs ; PID# is the number of current total pids seen
COPY %G5 +total_PIDs
ADDUS *%G5 *+total_PIDs 1
ADDUS %G4 %G4 4
COPY *%G4 %G2 ;Is process active?
ADDUS %G4 %G4 4
COPY *%G4 %G1 ;The current stack pointer (the limit of the prog by default)
ADDUS %G4 %G4 4
COPY *%G4 %G1 ;The current frame pointer (the limit of the prog by default)
ADDUS %G4 %G4 4
; incremented 16 since PID
COPY *%G4 0 ; Saving all registers as 0 by default.
ADDUS %G4 %G4 4
COPY *%G4 0 ; %G1
ADDUS %G4 %G4 4
COPY *%G4 0 ;G2
ADDUS %G4 %G4 4
COPY *%G4 0 ;G3
ADDUS %G4 %G4 4
COPY *%G4 0 ;G4
ADDUS %G4 %G4 4
COPY *%G4 0 ;G5
ADDUS %G4 %G4 4
; Incremented 40 since PID
COPY *%G4 %G0 ;Input base
ADDUS %G4 %G4 4
COPY *%G4 %G1 ;Input limit
ADDUS %G4 %G4 4
COPY *%G4 0x00 ;Current IP is defaulted to 0 (will be offset in virtual mode)
ADDUS %G4 %G4 4
COPY *%G4 %G3 ;Input Parent PID
ADDUS %G4 %G4 4
;If *%FP is 0 next_free_process gets updated. Else, this gets skipped.
BEQ +PTA2 *%FP 1
COPY %G5 +next_free_process
COPY *%G5 %G4 ;remembers next free space
; Incremented 56 to get to next PID space.
JUMP +PTA3
PTA2:
;; Will clear process_table_pocket_space if no pockets are left.
BNEQ +PTA3 %G4 *+next_free_process
COPY %G5 +process_table_pocket_space
COPY *%G5 0x00
PTA3:
;; if the limit is bigger than the next_free_RAM, change next_free_RAM
BLT +process_table_Add_complete %G1 *+next_free_RAM
COPY %G0 +next_free_RAM
COPY *%G0 %G1
process_table_Add_complete:
COPY %G0 +process_table_total_processes ; if kernel is being added.
ADDUS *%G0 *%G0 1
process_table_Add_completeB:
JUMP +fDone ;Complete
;;; Process Remove function (pid), results: 0
process_table_Remove_Args:
JUMP +fArgs
process_table_Remove:
SUBUS %SP %SP 4
COPY *%SP 0
COPY %G0 +return2
CALL +fCall *%G0
COPY %G0 +return
CALL +process_table_Search_Args *%G0
COPY *%SP *%FP ; put PID as PT search argument
CALL +process_table_Search *%G0
COPY %G1 *%SP ; G1 has address of target pid
ADDUS %SP %SP 4 ; put SP back where it belongs
BEQ +process_table_Remove_fail %G1 0
COPY %G0 0
PTR1:
;; Clearing process table entry
BEQ +process_table_Remove_complete %G0 56
COPY *%G1 0
ADDUS %G1 %G1 4
ADDUS %G0 %G0 4
JUMP +PTR1
process_table_Remove_complete:
;; Remove complete
COPY %G0 +process_table_pocket_space
COPY *%G0 0x01
COPY %G0 +process_table_pointer_count
SUBUS *%G0 *%G0 1
COPY %G0 +process_table_total_processes
SUBUS *%G0 *%G0 1
COPY %G0 +process_table_pointer
SUBUS *%G0 *%G0 56
JUMP +fDone
process_table_Remove_fail:
COPY %G2 1 ;for debugging
HALT ; Could not find PID to remove process
;;; process_table Run Next Process (), results: 0
;;; Just jump to process_table_Run_Next; Do not Call it, it will not return.
;;; Increments current_PID and then runs that process.
;; Puts current_PID in register 1 for p_t_Run_Process(%G1)
process_table_Run_Next:
;; Save kernel's state in PT
SUBUS %SP %SP 16
COPY *%SP %G0 ;saving G0 contents
ADDUS %SP %SP 16
COPY %G0 +return
CALL +process_table_Update_Process_Args *%G0
SUBUS %SP %SP 12
COPY %G0 +reg0
COPY *%G0 *%SP ;put in real G0 contents
ADDUS %SP %SP 12
COPY %G0 +return
COPY *%SP 0x00 ; PT_update 1st arg, PID of kernel
SUBUS %SP %SP 4
COPY *%SP 0x01 ; PT_update 2nd arg, status
CALL +process_table_Update_Process *%G0
process_table_Run_again:
;; HALT if there are no more processes to run.
BEQ +process_table_Run_Next_none *+process_table_total_processes 1
COPY %G1 +process_table_pointer_count
COPY %G0 +process_table_pointer
ADDUS *%G1 *%G1 1
ADDUS *%G0 *%G0 56
;; Pointer loops back to 0x01 if it goes past the total amount of processes
BGT +process_table_Run_Next_loop *%G1 *+process_table_total_processes
COPY %G1 *%G0
BEQ +process_table_Run_Next_search *%G1 0
;; Put PID in %G1 and jump to process_table_Run_Process()
;; it needs PID in %G1 to be used.
COPY %G0 +current_PID
COPY *%G0 *%G1 ;update current_PID
COPY %G1 *+current_PID
JUMP +process_table_Run_Process ;Run's the process
;; Looking for next process in process table
process_table_Run_Next_search:
BGTE +process_table_Run_Next_loop *%G0 *+next_free_process
ADDUS *%G0 *%G0 56 ; Look for next process
COPY %G1 *%G0 ; Copy value into %G1 to check
BEQ +process_table_Run_Next_search *%G1 0
COPY %G0 +current_PID
COPY *%G0 *%G1 ;update current_PID
COPY %G1 *%G1
JUMP +process_table_Run_Process
;; Loops pointer back to 0x01 process when it goes too far.
process_table_Run_Next_loop:
COPY %G1 +process_table_pointer_count
COPY *%G1 1 ; Gets incremented to 1 at process_table_Run_Next
COPY %G1 +process_table_pointer_base
COPY %G0 +process_table_pointer
COPY *%G0 *%G1
JUMP +process_table_Run_again
process_table_Run_Next_none:
HALT ; No more processes to run
;;; Process Table Run Process (PID), results: 0
;;; Run's process with specified PID. Argument taken by register 1.
;;; Does not use kernel's Stack; saves kernel info in PT, clears registers;
;; So jump to process_table_Run_Process, not call.
process_table_Run_Process:
;; Assuming %G1 has the PID
COPY %G0 +return
CALL +process_table_Search_Args *%G0
COPY *%SP %G1
CALL +process_table_Search *%G0
COPY %G2 *%SP
ADDUS %SP %SP 4
BEQ +process_table_Run_Process_fail %G2 0
ADDUS %G2 %G2 40 ; Looking at process's Base
COPY %G0 +BS
COPY *%G0 *%G2
SETBS *%G2
ADDUS %G2 %G2 4 ; Looking at process's Limit
COPY %G0 +LM
COPY *%G0 *%G2
SETLM *%G2
ADDUS %G2 %G2 4 ; Find current IP
COPY %G0 +process_table_Run_jump_address
COPY *%G0 *%G2 ; saved jump_address, (not yet offset by BS)
;; Should clock be on if total_processes < 2? (Unless debugging)
;; Will keep it on for now.
;; Restore Registers
COPY %G0 +return
CALL +process_table_Restore_Args *%G0
COPY *%SP %G1 ; Assumes PID is in %G1
CALL +process_table_Restore *%G0 ; restores registers
BLT +process_table_Run_one *+process_table_total_processes 2
SETALM *+ALM 0x01 ; if it's only one process, alarm not set.
JUMPMD *+process_table_Run_jump_address 0x06 ; Jump to that IP, and offsets by BS.
process_table_Run_one:
JUMPMD *+process_table_Run_jump_address 0x06 ; Jump to that IP, and offsets by BS.
process_table_Run_Process_fail:
HALT ; Could not find PID to run process
;;; Process Table Update function (status), results: 0
;;; Updates the last interrupted process's PT information
;;; Jumps to next ready process
process_table_Update_Args:
JUMP +fArgs
process_table_Update:
SUBUS %SP %SP 4
COPY *%SP 0
COPY %G0 +return2
CALL +fCall *%G0
;; Updating Current Process
COPY %G0 *+reg0
COPY %G1 +reg00
COPY *%G1 %G0
COPY %G0 *+reg1
COPY %G1 +reg01
COPY *%G1 %G0
COPY %G0 *+reg2
COPY %G1 +reg02
COPY *%G1 %G0
COPY %G0 *+reg3
COPY %G1 +reg03
COPY *%G1 %G0
COPY %G0 *+reg4
COPY %G1 +reg04
COPY *%G1 %G0
COPY %G0 *+reg5
COPY %G1 +reg05
COPY *%G1 %G0
COPY %G0 +oldSP2
COPY *%G0 %SP ; Copied fCall's SP into oldSP2
COPY %G0 +oldFP2
COPY *%G0 %FP
COPY %G0 +return
COPY %G1 *%FP ; G1 has status
COPY %SP *+process_SP ; SP has the sp it had when update args was called
COPY %FP *+process_FP ; Suspicious
CALL +process_table_Update_Process_Args *%G0
COPY *%SP *+current_PID
SUBUS %SP %SP 4
COPY *%SP %G1
COPY %G0 *+reg00
COPY %G1 +reg0
COPY *%G1 %G0
COPY %G0 *+reg01
COPY %G1 +reg1
COPY *%G1 %G0
COPY %G0 *+reg02
COPY %G1 +reg2
COPY *%G1 %G0
COPY %G0 *+reg03
COPY %G1 +reg3
COPY *%G1 %G0
COPY %G0 *+reg04
COPY %G1 +reg4
COPY *%G1 %G0
COPY %G0 *+reg05
COPY %G1 +reg5
COPY *%G1 %G0
CALL +process_table_Update_Process *%G0
COPY %SP *+oldSP2
COPY %FP *+oldFP2
JUMP +fDone
;;; Process Table Update Process function (pid, status), results : 0
;;; Updates a chosen process's PT information
;;; Assumes all regs for process have been stored in temp space
process_table_Update_Process_Args:
JUMP +fArgs
process_table_Update_Process:
SUBUS %SP %SP 4
COPY *%SP 0
COPY %G0 +return2
CALL +fCall *%G0
COPY %G0 +return
CALL +process_table_Search_Args *%G0
COPY *%SP *%FP ; put PID as PT search argument
ADDUS %FP %FP 4
CALL +process_table_Search *%G0
COPY %G1 *%SP ; G1 has address of target pid
ADDUS %SP %SP 4 ; put SP back where it belongs
BEQ +process_table_Update_Process_fail %G1 0
ADDUS %G1 %G1 4 ; %G1 is looking at status of chosen PID
COPY *%G1 *%FP ; Input new status
ADDUS %G1 %G1 4
COPY *%G1 *+process_SP ; process's SP updated
ADDUS %G1 %G1 4
COPY *%G1 *+process_FP ; process's FP updated
ADDUS %G1 %G1 4
COPY *%G1 *+reg0
ADDUS %G1 %G1 4
COPY *%G1 *+reg1
ADDUS %G1 %G1 4
COPY *%G1 *+reg2
ADDUS %G1 %G1 4
COPY *%G1 *+reg3
ADDUS %G1 %G1 4
COPY *%G1 *+reg4
ADDUS %G1 %G1 4
COPY *%G1 *+reg5
ADDUS %G1 %G1 12 ;skip limit and base (they don't change)
COPY *%G1 *+IB ;copy where the interrupt took place (current IP)
CALL +process_table_Print *%G0
JUMP +fDone ; should just jump to whatever called it
process_table_Update_Process_fail:
;; Could not find requested PID. Update Fail
COPY %G2 2 ;for debugging
HALT
;;; Process Table Search function(PID). returns the address of requested PID.
process_table_Search_Args:
SUBUS %SP %SP 4
JUMP +fArgs
process_table_Search:
SUBUS %SP %SP 4
COPY *%SP 1
COPY %G0 +return2
CALL +fCall *%G0
COPY %G0 +return
CALL +search_Args *%G0
COPY *%SP *%FP ;give search the item (PID)
SUBUS %SP %SP 4
COPY *%SP *+process_table_base ; give search the base
SUBUS %SP %SP 4
COPY *%SP *+process_table_limit ; give search the limit
SUBUS %SP %SP 4
COPY *%SP 56 ; give search the increment amount
CALL +search *%G0
;; Search leaves the answer at the stack pointer
ADDUS %SP %SP 4 ;So we bury the answer, for fDone to find.
JUMP +fDone
;;; Process Restore function(PID). returns nothing
;;; It simply restores registers to how they were saved on the process table
process_table_Restore_Args:
JUMP +fArgs
process_table_Restore:
SUBUS %SP %SP 4
COPY *%SP 0
COPY %G0 +return2
CALL +fCall *%G0
COPY %G3 +process_table_Restore_jump_address
COPY *%G3 *+return
COPY %G0 +return
CALL +process_table_Search_Args *%G0
COPY *%SP *%FP ;input PID to PT_Search