-
Notifications
You must be signed in to change notification settings - Fork 0
/
me.mac
318 lines (304 loc) · 10.2 KB
/
me.mac
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
TITLE ME,<MEMORY ALLOCATION>,08,06-SEP-80,TG/GPK
; ENTRY POINTS TO THIS MODULE:
;+
; INSERT -
; DELETE -
; FORGET -
; GETSPC -
;-
; EXTERNAL ROUTINES CALLED FROM THIS MODULE
;+
; SYSTEM - IO - SYSTEM IO
; SAVSYS - SB -
; ERROR - RC - PRINT AND ERROR
;-
ORG ME
.SBTTL INSERT - ADD A SEGMENT TO THE MEMORY LIST
;+
; I N S E R T
;
; THIS ROUTINE INSERTS A MEMORY SEGMENT INTO THE LINKED
; LIST OF MEMORY SEGMENTS IN SUCH A WAY THAT THE LIST
; WILL BE ORDERED BY SIZE OF THE SEGMENTS IN ASCENDING
; ORDER. THE ADDRESS OF THE SEGMENT TO BE INSERTED IS
; PASSED IN R0. ALL REGISTERS ARE PRESERVED.
;
; CALLING SEQUENCE:
;
; JSR PC,INSERT
;-
INSERT::MOV R1,-(SP) ;SAVE A REGISTER
MOV R2,-(SP) ; AND ANOTHER
MOV R3,-(SP) ; AND ANOTHER
MOV #M$STRT,R1 ;GET START OF MEMORY LIST
MOV M$SIZE(R0),R3 ;AND SIZE OF SEGMENT TO INSERT
BR 20$ ;AND ENTER THE LOOP
10$: MOV R2,R1 ;LINK UP TO NEXT SEGMENT
20$: MOV M$LINK(R1),R2 ;AND GET IT'S FWD LINK
BEQ 30$ ;UNLESS WE ARE AT THE END
CMP M$SIZE(R2),R3 ;ARE WE WHERE WE BELONG YET?
BLO 10$ ;NO, LOOP SOME MORE
30$: MOV R0,M$LINK(R1) ;NEW LINK FOR OLD SEGMENT
MOV R2,M$LINK(R0) ;OLD LINK FOR NEW SEGMENT
MOV (SP)+,R3 ;RESTORE A REGISTER
MOV (SP)+,R2 ; AND ANOTHER
MOV (SP)+,R1 ; AND ANOTHER
RTS PC ;THAT'S ALL FOLKS
.SBTTL DELETE - REMOVE A SEGMENT FROM THE MEMORY LIST
;+
; D E L E T E
;
; THIS ROUTINE REMOVES A MEMORY SEGMENT FROM THE LINKED
; LIST OF MEMORY SEGMENTS. THE ADDRESS OF THE SEGMENT
; TO BE DELETED IS PASSED IN R0. THE SEGMENT TO BE DE-
; LETED HAD BETTER BE IN THE LIST OR ELSE.
;
; CALLING SEQUENCE:
;
; JSR PC,DELETE
;-
DELETE::MOV R1,-(SP) ;NEED ONE WORKING REGISTER
MOV #M$STRT,R1 ;AND WE PUT THE MEMORY LIST IN IT
10$: CMP M$LINK(R1),R0 ;ARE WE POINTING AT OUR SEGMENT
BEQ 20$ ;YES, LET'S DELETE IT
MOV M$LINK(R1),R1 ;LINK TO NEXT SEGMENT
BNE 10$ ;IF THERE IS ONE
BPT ;THIS IS A REAL BAD ERROR
20$: MOV M$LINK(R0),M$LINK(R1) ;DIDDLE LINKS TO REMOVE SEGMENT
MOV (SP)+,R1 ;AND RESTORE THE REGISTER
RTS PC ;AND AWAY WE GO
.SBTTL FORGET - RETURN AND MERGE MEMORY SEGMENTS
;+
; F O R G E T
;
; THIS ROUTINE RETURNS A MEMORY SEGMENT FROM AN IN-USE
; STATUS TO THE AVAILABLE LIST. IT DOES THIS BY MARK-
; ING THE SEGMENT NOT PRESENT IN WHATEVER DESCRIPTIOR
; OWNS THIS SEGMENT. IT THEN CHECKS FOR ANY ADJACENT
; AVAILABLE SEGMENTS AND COMBINES THEM IF IT FINDS ANY.
; THE ADDRESS OF THE SEGMENT TO BE FORGOTTEN IS PASSED
; IN R0. THE ADDRESS OF THE NEW (POSSIBLY LARGER)
; FREE SEGMENT IS RETURNED IN R0. ALL OTHER REGISTERS
; ARE PRESERVED.
;
; CALLING SEQUENCE:
;
; JSR PC,FORGET
;-
FORGET::MOV R1,-(SP) ;SAVE ONE REGISTER
MOV R0,-(SP) ;WE MAY NEED A COPY OF THIS
CALL DELETE ; NOW MAKE THIS ONE GO AWAY
BIT #M.USED,(R0) ;IS SOMEONE USING IT?
BEQ 10$ ;NO, SO IS NOT NOW PRESENT
BIC #PRESNT,@M$PNTR(R0) ;IT ISN'T PRESENT NOW
BIC #M.USED,(R0) ;SO IT'S NO LONGER IN USE
10$: MOV M$SIZE(R0),R1 ;GET THE LENGTH OF THE SEGMENT
ADD #12,R1 ; PLUS INFO WORDS
ADD R0,R1 ;NOW POINT TO NEXT HIGHER SEGMENT
BIT #M.USED,(R1) ;IS THAT ONE AVAILABLE?
BNE 20$ ;NO, CAN'T COMBINE THEM
MOV R1,R0 ;SURE IS, LET'S DELETE IT
CALL DELETE ; THAT DOES IT
MOV (SP),R0 ;NOW GET THIS ONE BACK
CALL 40$ ; NOW PUT LENGTH AT END
20$: MOV R0,R1 ;GET A COPY OF SEGMENT ADDRESS
SUB -(R1),R1 ;USE SIZE OF PREVIOUS SEGMENT TO
SUB #10,R1 ; FIND BASE OF PREVIOUS SEGMENT
BIT #M.USED,(R1) ;IS THIS ONE AVAILABLE?
BNE 30$ ;NO, WE ARE NEARLY DONE
MOV R1,R0 ;MOVE POINTER SO AS TO
CALL DELETE ; DELETE THIS SEGMENT
MOV (SP),R1 ;GET ORIGINAL POINTER BACK
CALL 40$ ; NOW PUT LENGTH AT END
30$: CALL INSERT ; PU IT BACK IN THE LIST
TST (SP)+ ;DUMP THE OLD POINTER
MOV (SP)+,R1 ;AND RESTORE R1
.IF DF DEBUG
CALL MEMCHK ; CHECK THAT WE STILL HAVE IT ALL
.ENDC
RTS PC ;AND EXIT
40$: ADD M$SIZE(R1),M$SIZE(R0) ;INCREASE SIZE OF SEGMENT
ADD #12,M$SIZE(R0) ; PLUS SIZE OF INFO WORDS
ADD M$SIZE(R1),R1 ;MOVE UP TO END OF SEGMENT
MOV M$SIZE(R0),10(R1) ;AND NOW WE SHOULD BE DONE
RTS PC ;AND RETURN
.SBTTL OVRLAY - MAKE A MEMORY SEGMENT AVAILABLE
;+
; O V E R L A Y
;
; THIS ROUTINE MAKES MEMORY SEGMENTS AVAILABLE. IT DOES THIS
; BY WRITING THE CONTENTS OF THE SEGMENT ONTO THE OVERLAY DISK
; FILE IF THE SEGMENT IS A DATA SEGMENT. IT THEN CALLS FORGET
; TO MAKE THE SEGMENT AVAILABLE. THE ADDRESS OF THE SEGMENT TO
; BE OVERLAYED IS PASSED IN R0. ALL REGISTERS ARE PRESERVED.
;
; CALLING SEQUENCE:
;
; JSR PC,OVRLAY
;-
OVRLAY: BIT #M.USED,(R0) ;IS THE SEGMENT IN USE?
BEQ 30$ ;NO, THAT WAS EASY
BIT #M.DATA,(R0) ;YES, BUT IS IT DATA?
BEQ 20$ ;NO, THAT'S ALMOST AS EASY
BIC #M.DATA,(R0) ;IT'S DATA NO LONGER
BIT #M.MDFY,(R0) ;HAS THE DATA CHANGED LATELY?
BEQ 20$ ;NOPE, NO NEED TO OVERLAY IT
BIC #M.MDFY,(R0) ;SAY THAT IT'S NOT CHANGED NOW
CALLX SAVSYS ; AMKE I/O CALL RE-ENTRANT
MOV R1,-(SP) ;SAVE A REGISTER
MOV M$PNTR(R0),R1 ;FIND THE ARRAY DESCRIPTOR
MOV A$DISK(R1),SYS.RN ;SAVE THE OVERLAY ADDRESS
MOV (R1),R1 ;GET THE SEGMENT SIZE
BIC #160000,R1 ;LESS THE INFO BITS
BIT #M.REAL,(R0) ;IS THIS A REAL ARRAY
BEQ 10$ ;NO, ALL IS O.K.
BIC #140000,SYS.RN ;FIX UP THE DISK ADDRESS
ASL R1 ;AND ADJUST THE LENGTH
10$: ASL R1 ;CONVERT TO BYTES
MOV R1,SYS.CT ;SAVE THE SIZE
MOV R0,SYS.CA ;AND THE CORE ADDRESS
ADD #10,SYS.CA ;MOVE UP TO REAL DATA
MOV (SP)+,R1 ;RESTORE R1
MOV #VMEMFD,SYS.FD ;USE OVERLAY DISK FILE
MOV #1,SYS.IO ;AND DO A WRITE
CALLX SYSTEM ; CALL FOR I/O
20$: CALL FORGET ; NOW FORGET IT
30$: RTS PC ;NOW WE'RE DONE
.SBTTL GETSPC - ALLOCATE MEMORY SEGMENTS
;+
; G E T S P A C E
;
; THIS ROUTINE ATTEMPTS TO FIND A MEMORY SEGMENT WHOSE SIZE
; IS SPECIFIED IN R0. THE TYPE OF MEMORY TO ALLOCATE IS
; SPECIFIED IN R1. R0 IS RETURNED POINTING AT M$PNTR IN
; THE ALLOCATED MEMORY SEGMENT. ALL REGISTERS ARE PRESERVED.
; A SEARCH IS MADE FOR MEMORY IN THE FOLLOWING ORDER:
; 1) SEARCH FOR SMALLEST AVAILABLE SEGMENT LARGE ENOUGH.
; 2) SEARCH FOR SMALLEST CODE SEGMENT LARGE ENOUGH.
; 3) SEARCH FOR SMALLEST DATA SEGMENT LARGE ENOUGH.
; IF THIS FAILS THEN ALL NON-SAVE MEMORY SEGMENTS ARE FOR-
; GOTTEN AND THEN A SEARCH IS MADE FOR AN AVAILBLE SEGMENT.
; IF THIS FAILS, A 'NO MEMORY' ERROR IS RETURNED.
;
; CALLING SEQUENCE:
;
; JSR PC,GETSPC
;-
GETSPC::MOV R2,-(SP) ;SAVE A REGISTER
MOV R3,-(SP) ; AND ANOTHER
MOV PBASE,R2 ;CURRENT PROGRAM SEGMENT
MOV M$TYPE-M$PNTR(R2),-(SP) ;SAVE CURRENT SAVE STATUS
BIS #M.SAVE,M$TYPE-M$PNTR(R2) ;NOW MAKE IT SAVE
MOV R0,R2 ;NOW PUT SIZE HERE
MOV #M.TBL,R3 ;GET SEARCH LIST HERE
;;;? ASL R2 ;ADJUST SIZE TO BYTES
10$: MOV #M$STRT,R0 ;GET MEMORY LIST START
20$: MOV M$LINK(R0),R0 ;LINK TO NEXT SEGMENT
BEQ 30$ ;UNLESS THIS IS THE END
CMP M$SIZE(R0),R2 ;CHECK SIZE OF THIS SEGMENT
BLO 20$ ;NOT THERE YET
30$: MOV R0,-(SP) ;SAVE STARTING POINT
40$: MOV (SP),R0 ;RESTORE STARTING POINT
BEQ 60$ ;BUT THERE'S NOTHING TO SEARCH
50$: BIT (R3),(R0) ;THIS ONE THE RIGHT TYPE?
BEQ 70$ ;FOUND ONE, HOORAY!
MOV M$LINK(R0),R0 ;LINK UP TO NEXT SEGMENT
BNE 50$ ;IF THERE IS ONE
60$: TST (R3)+ ;MOVE TO NEXT SPOT
CMP R3,#M.END ;WHERE ARE WE NOW?
BLO 40$ ;LOOP FOR NEXT SEARCH
BEQ 90$ ;TRY TO FORGET A LITTLE
CALLX ERROR ; WELL, CAN'T WIN THEM ALL
.ASCIZ \?No memory for memory segment\
.EVEN
70$: CALL OVRLAY ; MAKE IT AVAILABLE FOR SURE
MOV M$SIZE(R0),R3 ;GET SIZE OF SEGMENT FOUND
ADD #40,R2 ;MAKE REQUESTED SIZE LARGER
CMP R2,R3 ; TO SEE IF MUCH TOO LARGE
BHIS 80$ ;SIZE IS O.K.
SUB #40,R2 ;RETURN TO REAL SIZE
CALL DELETE ; DELETE THE SEGMENT SO..
MOV R2,M$SIZE(R0) ; WE CAN MAKE IT SMALLER
MOV R0,-(SP) ;WILL NEED THIS LATER
ADD R2,R0 ;GET TO END OF SEGMENT
ADD #10,R0 ;PLUS LINK WORDS
MOV R2,(R0)+ ;NEW SIZE AT END ALSO
CLR (R0) ;NEW SEGMENT IS AVAILABLE
SUB R2,R3 ;ADJUST SIZE OF NEW SEGMENT
SUB #12,R3 ;THIS SHOULD BE IT'S SIZE
MOV R3,M$SIZE(R0) ;NOW INTO THE MEMORY LINKS
MOV R0,-(SP) ;GET POINTER ON STACK
ADD R3,(SP) ;AND MOVE UP TO THE
ADD #10,(SP) ; END OF THE SEGMENT
MOV R3,@(SP)+ ;AND INSERT IT'S SIZE THERE
CALL INSERT ; NOW MAKE IT AVAILABLE AGAIN
MOV (SP)+,R0 ;GET BACK THIS ONE
CALL INSERT ; AND PUT IT BACK ALSO
80$: TST (SP)+ ;DUMP MEMORY POINTER
MOV R1,(R0)+ ;SET IN THE PROPER TYPE
CMP (R0)+,(R0)+ ;MOVE UP TO WHERE WE SAID
MOV PBASE,R2 ;GET BACK THIS POINTER
MOV (SP)+,M$TYPE-M$PNTR(R2) ;AND PUT BACK ORIGINAL STATUS
MOV (SP)+,R3 ;AND RESTORE A REGISTER
MOV (SP)+,R2 ; AND ANOTHER
.IF DF DEBUG
CALL MEMCHK ; CHECK FOR CONSISTENCY
.ENDC
RTS PC ; AND AWAY WE GO
90$: MOV #M$STRT,R0 ;GET START OF MEMORY
TST (SP)+ ;DUMP OLD STARTING POINT
100$: TST (R0) ;IS THIS ONE 'SAVE'???
BMI 110$ ;YEP, CAN'T HAVE IT
CALL OVRLAY ; MAKE IT GO AWAY
110$: ADD M$SIZE(R0),R0 ;MOVE UP ADJACENTLY
ADD #12,R0 ; NOT LINKEDLY
.IF DF DEBUG
CMP R0,M$LAST ;ARE WE AT THE END
BHIS 120$ ;YEAH, CAN'T CHECK THIS ONE
MOV M$SIZE(R0),-(SP) ;GET SIZE OF SEGMENT
ADD #10,(SP) ;PLUS LENGTH OF LINKS
ADD R0,(SP) ;GET ADDRESS OF SECOND SIZE
CMP M$SIZE(R0),@(SP)+ ;ARE THEY THE SAME???
BEQ 120$ ;YES, WHAT DO YOU KNOW
BPT ;NO, AFRAID OF THAT
120$:
.ENDC
CMP R0,M$LAST ;AT THE END YET???
BLO 100$ ;NO GO AROUND AGAIN
BR 10$ ;GO SEARCH AGAIN
M.TBL: .WORD 160000 ;MEMORY MUST BE AVAILABLE
.WORD 120000 ;MEMORY MUST BE CODE
.WORD 100000 ;MEMORY MAY BE DATA
M.END: .WORD 160000 ;MEMORY MUST BE AVAIABLE
.SBTTL MEMCHK MEMORY CONSISTENCY CHECK (DEBUG)
;+
; M E M C H K
;
; THIS ROUTINE IS A CONSISTENCY CHECKER FOR THE
; MEMORY MANAGEMENT ROUTINES. ANY INCOSISTENCIES
; CAUSE A 'BPT' TO BE EXECUTED.
;-
.IF DF DEBUG
MEMCHK: MOV R0,-(SP) ;WE WILL NEED A BUNCH
MOV R1,-(SP) ; OF REGISTERS HERE
MOV R2,-(SP) ; THIS IS THE LAST ONE
MOV #M$STRT,R0 ;GET START OF MEMORY HERE
MOV #M$STRT,R1 ; AND HERE ALSO
10$: MOV R0,R2 ;COPY ADDRESS OF SEGMENT
ADD M$SIZE(R0),R2 ;MOVE UP TO END OF SEGMENT
CMP M$SIZE(R0),10(R2) ;TO SEE IF SIZES AGREE
BEQ 20$ ;THEY SURE DO
BPT ;NOPE THAT IS INCONSISTENT
20$: ADD M$SIZE(R0),R1 ;ADD SIZE OF DATA AREA TO TOTAL
ADD #12,R1 ;PLUS SIZE OF MEMORY LINKS
MOV M$LINK(R0),R0 ;LINK UP TO NEXT SEGMENT
BNE 10$ ;AND ADD UP SOME MORE
CMP R1,M$LAST ;GOT ENOUGH IN USE???
BEQ 30$ ;SURE DO, WHAT DO YOU KNOW
BPT ;NOPE, I WAS AFRAID OF THIS
30$: MOV (SP)+,R2 ;RESTORE A REGISTER
MOV (SP)+,R1 ; AND ANOTHER
MOV (SP)+,R0 ; AND ANOTHER
RTS PC ; AND EXIT...
.ENDC
.END