1 |
2 |
sybreon |
* Simplified version of a 68000 monitor
|
2 |
|
|
* Designed to run with the Teesside 68K simulator
|
3 |
|
|
* Version of 3 October 1996
|
4 |
|
|
* Symbol equates
|
5 |
|
|
BS EQU $08 Back_space
|
6 |
|
|
CR EQU $0D Carriage_return
|
7 |
|
|
LF EQU $0A Line_feed
|
8 |
|
|
SPACE EQU $20 Space
|
9 |
|
|
WAIT EQU 'W' Wait character (to suspend output)
|
10 |
|
|
CTRL_A EQU $01 Control_A forces return to monitor
|
11 |
|
|
* Device addresses
|
12 |
|
|
X_BASE EQU $08 Start of exception vector table
|
13 |
|
|
TRAP_14 EQU $4E4E Code for TRAP #14
|
14 |
|
|
MAXCHR EQU 64 Length of input line buffer
|
15 |
|
|
*
|
16 |
|
|
DATA EQU $00000400 Data origin
|
17 |
|
|
LNBUFF DS.B MAXCHR Input line buffer
|
18 |
|
|
BUFFEND EQU LNBUFF+MAXCHR-1 End of line buffer
|
19 |
|
|
BUFFPT DS.L 1 Pointer to line buffer
|
20 |
|
|
PARAMTR DS.L 1 Last parameter from line buffer
|
21 |
|
|
ECHO DS.B 1 When clear this enable input echo
|
22 |
|
|
U_CASE DS.B 1 Flag for upper case conversion
|
23 |
|
|
TSK_T DS.W 37 Frame for D0-D7, A0-A6, USP, SSP, SW, PC
|
24 |
|
|
BP_TAB DS.W 24 Breakpoint table
|
25 |
|
|
*
|
26 |
|
|
*************************************************************************
|
27 |
|
|
*
|
28 |
|
|
* This is the main program which assembles a command in the line
|
29 |
|
|
* buffer, removes leading/embedded spaces and interprets it by matching
|
30 |
|
|
* it with a command in the user table or the built-in table COMTAB
|
31 |
|
|
* All variables are specified with respect to A6
|
32 |
|
|
*
|
33 |
|
|
ORG $00001000 Monitor origin
|
34 |
|
|
RESET EQU * Cold entry point for monitor
|
35 |
|
|
LEA.L DATA,A6 A6 points to data area
|
36 |
|
|
MOVE.B #1,ECHO(A6) No automatic character echo
|
37 |
|
|
CLR.B U_CASE(A6) Clear case conversion flag (UC<-LC)
|
38 |
|
|
BSR X_SET Setup exception table
|
39 |
|
|
LEA.L BANNER(PC),A4 Point to banner
|
40 |
|
|
BSR.S HEADING and print heading
|
41 |
|
|
WARM CLR.L D7 Warm entry point - clear error flag
|
42 |
|
|
BSR.S NEWLINE Print a newline
|
43 |
|
|
BSR.S GETLINE Get a command line
|
44 |
|
|
BSR EXECUTE Interpret command
|
45 |
|
|
BRA WARM Repeat indefinitely
|
46 |
|
|
*
|
47 |
|
|
*************************************************************************
|
48 |
|
|
*
|
49 |
|
|
* Some initialization and basic routines
|
50 |
|
|
*
|
51 |
|
|
NEWLINE EQU * Move cursor to start of newline
|
52 |
|
|
MOVEM.L A4,-(A7) Save A4
|
53 |
|
|
LEA.L CRLF(PC),A4 Point to CR/LF string
|
54 |
|
|
BSR.S PSTRING Print it
|
55 |
|
|
MOVEM.L (A7)+,A4 Restore A4
|
56 |
|
|
RTS Return
|
57 |
|
|
*
|
58 |
|
|
PSTRING EQU * Display the string pointed at by A4
|
59 |
|
|
MOVE.L D0,-(A7) Save D0
|
60 |
|
|
PS1 MOVE.B (A4)+,D0 Get character to be printed
|
61 |
|
|
BEQ.S PS2 If null then return
|
62 |
|
|
BSR PUTCHAR Else print it
|
63 |
|
|
BRA PS1 Continue
|
64 |
|
|
PS2 MOVE.L (A7)+,D0 Restore D0 and exit
|
65 |
|
|
RTS
|
66 |
|
|
*
|
67 |
|
|
HEADING BSR NEWLINE Same as PSTRING but with newline
|
68 |
|
|
BSR PSTRING
|
69 |
|
|
BRA NEWLINE
|
70 |
|
|
*
|
71 |
|
|
*************************************************************************
|
72 |
|
|
*
|
73 |
|
|
* GETLINE inputs a string of characters into a line buffer
|
74 |
|
|
* A3 points to next free entry in line buffer
|
75 |
|
|
* A2 points to end of buffer
|
76 |
|
|
* A1 points to start of buffer
|
77 |
|
|
* D0 holds character to be stored
|
78 |
|
|
*
|
79 |
|
|
GETLINE LEA.L LNBUFF(A6),A1 A1 points to start of line buffer
|
80 |
|
|
LEA.L (A1),A3 A3 points to start (initially)
|
81 |
|
|
LEA.L MAXCHR(A1),A2 A2 points to end of buffer
|
82 |
|
|
GETLN2 BSR GETCHAR Get a character
|
83 |
|
|
CMP.B #CTRL_A,D0 If control_A then reject this line
|
84 |
|
|
BEQ.S GETLN5 and get another line
|
85 |
|
|
CMP.B #BS,D0 If back_space then move back pointer
|
86 |
|
|
BNE.S GETLN3 Else skip past wind-back routine
|
87 |
|
|
CMP.L A1,A3 First check for empty buffer
|
88 |
|
|
BEQ GETLN2 If buffer empty then continue
|
89 |
|
|
LEA -1(A3),A3 Else decrement buffer pointer
|
90 |
|
|
BRA GETLN2 and continue with next character
|
91 |
|
|
GETLN3 MOVE.B D0,(A3)+ Store character and update pointer
|
92 |
|
|
CMP.B #CR,D0 Test for command terminator
|
93 |
|
|
BNE.S GETLN4 If not CR then skip past exit
|
94 |
|
|
BRA NEWLINE Else new line before next operation
|
95 |
|
|
GETLN4 CMP.L A2,A3 Test for buffer overflow
|
96 |
|
|
BNE GETLN2 If buffer not full then continue
|
97 |
|
|
GETLN5 BSR NEWLINE Else move to next line and
|
98 |
|
|
BRA GETLINE repeat this routine
|
99 |
|
|
*
|
100 |
|
|
*************************************************************************
|
101 |
|
|
*
|
102 |
|
|
* EXECUTE matches the first command in the line buffer with the
|
103 |
|
|
* commands in a command table.
|
104 |
|
|
*
|
105 |
|
|
EXECUTE LEA.L COMTAB(PC),A3 Try built-in command table
|
106 |
|
|
BSR.S SEARCH Look for command in built-in table
|
107 |
|
|
BCS.S EXEC2 If found then execute command
|
108 |
|
|
LEA.L ERMES2(PC),A4 Else print "invalid command"
|
109 |
|
|
BRA.L PSTRING and return
|
110 |
|
|
EXEC2 MOVE.L (A3),A3 Get the relative command address
|
111 |
|
|
LEA.L COMTAB(PC),A4 pointed at by A3 and add it to
|
112 |
|
|
ADD.L A4,A3 the PC to generate the actual
|
113 |
|
|
* JMP (A3) command address. Then execute it.
|
114 |
|
|
LEA LNBUFF,A2
|
115 |
|
|
E3 MOVE.B (A2)+,D0
|
116 |
|
|
CMP.B #$20,D0
|
117 |
|
|
BNE E3
|
118 |
|
|
MOVE.L A2,BUFFPT(A6)
|
119 |
|
|
JMP (A3)
|
120 |
|
|
*
|
121 |
|
|
SEARCH EQU * Match the command in the line buffer
|
122 |
|
|
CLR.L D0 with command table pointed at by A3
|
123 |
|
|
MOVE.B (A3),D0 Get the first character in the
|
124 |
|
|
BEQ.S SRCH7 current entry. If zero then exit
|
125 |
|
|
LEA.L 6(A3,D0.W),A4 Else calculate address of next entry
|
126 |
|
|
MOVE.B 1(A3),D1 Get number of characters to match
|
127 |
|
|
LEA.L LNBUFF(A6),A5 A5 points to command in line buffer
|
128 |
|
|
MOVE.B 2(A3),D2 Get first character in this entry
|
129 |
|
|
CMP.B (A5)+,D2 from the table and match with buffer
|
130 |
|
|
BEQ.S SRCH3 If match then try rest of string
|
131 |
|
|
SRCH2 MOVE.L A4,A3 Else get address of next entry
|
132 |
|
|
BRA SEARCH and try the next entry in the table
|
133 |
|
|
SRCH3 SUB.B #1,D1 One less character to match
|
134 |
|
|
BEQ.S SRCH6 If match counter zero then all done
|
135 |
|
|
LEA.L 3(A3),A3 Else point to next character in table
|
136 |
|
|
SRCH4 MOVE.B (A3)+,D2 Now match a pair of characters
|
137 |
|
|
CMP.B (A5)+,D2
|
138 |
|
|
BNE SRCH2 If no match then try next entry
|
139 |
|
|
SUB.B #1,D1 Else decrement match counter and
|
140 |
|
|
BNE SRCH4 repeat until no chars left to match
|
141 |
|
|
SRCH6 LEA.L -4(A4),A3 Calculate address of command entry
|
142 |
|
|
OR.B #1,CCR point. Mark carry flag as success
|
143 |
|
|
RTS and return
|
144 |
|
|
SRCH7 AND.B #$FE,CCR Fail - clear carry to indicate
|
145 |
|
|
RTS command not found and return
|
146 |
|
|
*
|
147 |
|
|
*************************************************************************
|
148 |
|
|
*
|
149 |
|
|
* Basic input routines
|
150 |
|
|
* HEX = Get one hexadecimal character into D0
|
151 |
|
|
* BYTE = Get two hexadecimal characters into D0
|
152 |
|
|
* WORD = Get four hexadecimal characters into D0
|
153 |
|
|
* LONGWD = Get eight hexadecimal characters into D0
|
154 |
|
|
* PARAM = Get a longword from the line buffer into D0
|
155 |
|
|
* Bit 0 of D7 is set to indicate a hexadecimal input error
|
156 |
|
|
*
|
157 |
|
|
HEX BSR GETCHAR Get a character from input device
|
158 |
|
|
SUB.B #$30,D0 Convert to binary
|
159 |
|
|
BMI.S NOT_HEX If less than $30 then exit with error
|
160 |
|
|
CMP.B #$09,D0 Else test for number (0 to 9)
|
161 |
|
|
BLE.S HEX_OK If number then exit - success
|
162 |
|
|
SUB.B #$07,D0 Else convert letter to hex
|
163 |
|
|
CMP.B #$0F,D0 If character in range "A" to "F"
|
164 |
|
|
BLE.S HEX_OK then exit successfully
|
165 |
|
|
NOT_HEX OR.B #1,D7 Else set error flag
|
166 |
|
|
HEX_OK RTS and return
|
167 |
|
|
*
|
168 |
|
|
BYTE MOVE.L D1,-(A7) Save D1
|
169 |
|
|
BSR HEX Get first hex character
|
170 |
|
|
ASL.B #4,D0 Move it to MS nybble position
|
171 |
|
|
MOVE.B D0,D1 Save MS nybble in D1
|
172 |
|
|
BSR HEX Get second hex character
|
173 |
|
|
ADD.B D1,D0 Merge MS and LS nybbles
|
174 |
|
|
MOVE.L (A7)+,D1 Restore D1
|
175 |
|
|
RTS
|
176 |
|
|
*
|
177 |
|
|
WORD BSR BYTE Get upper order byte
|
178 |
|
|
ASL.W #8,D0 Move it to MS position
|
179 |
|
|
BRA BYTE Get LS byte and return
|
180 |
|
|
*
|
181 |
|
|
LONGWD BSR WORD Get upper order word
|
182 |
|
|
SWAP D0 Move it to MS position
|
183 |
|
|
BRA WORD Get lower order word and return
|
184 |
|
|
*
|
185 |
|
|
* PARAM reads a parameter from the line buffer and puts it in both
|
186 |
|
|
* PARAMTR(A6) and D0. Bit 1 of D7 is set on error.
|
187 |
|
|
*
|
188 |
|
|
PARAM MOVE.L D1,-(A7) Save D1
|
189 |
|
|
CLR.L D1 Clear input accumulator
|
190 |
|
|
MOVE.L BUFFPT(A6),A0 A0 points to parameter in buffer
|
191 |
|
|
PARAM1 MOVE.B (A0)+,D0 Read character from line buffer
|
192 |
|
|
CMP.B #SPACE,D0 Test for delimiter
|
193 |
|
|
BEQ.S PARAM4 The permitted delimiter is a
|
194 |
|
|
CMP.B #CR,D0 space or a carriage return
|
195 |
|
|
BEQ.S PARAM4 Exit on either space or C/R
|
196 |
|
|
ASL.L #4,D1 Shift accumulated result 4 bits left
|
197 |
|
|
SUB.B #$30,D0 Convert new character to hex
|
198 |
|
|
BMI.S PARAM5 If less than $30 then not-hex
|
199 |
|
|
CMP.B #$09,D0 If less than 10
|
200 |
|
|
BLE.S PARAM3 then continue
|
201 |
|
|
SUB.B #$07,D0 Else assume $A - $F
|
202 |
|
|
CMP.B #$0F,D0 If more than $F
|
203 |
|
|
BGT.S PARAM5 then exit to error on not-hex
|
204 |
|
|
PARAM3 ADD.B D0,D1 Add latest nybble to total in D1
|
205 |
|
|
BRA PARAM1 Repeat until delimiter found
|
206 |
|
|
PARAM4 MOVE.L A0,BUFFPT(A6) Save pointer in memory
|
207 |
|
|
MOVE.L D1,PARAMTR(A6) Save parameter in memory
|
208 |
|
|
MOVE.L D1,D0 Put parameter in D0 for return
|
209 |
|
|
BRA.S PARAM6 Return without error
|
210 |
|
|
PARAM5 OR.B #2,D7 Set error flag before return
|
211 |
|
|
PARAM6 MOVE.L (A7)+,D1 Restore working register
|
212 |
|
|
RTS Return with error
|
213 |
|
|
*
|
214 |
|
|
*************************************************************************
|
215 |
|
|
*
|
216 |
|
|
* Output routines
|
217 |
|
|
* OUT1X = print one hexadecimal character
|
218 |
|
|
* OUT2X = print two hexadecimal characters
|
219 |
|
|
* OUT4X = print four hexadecimal characters
|
220 |
|
|
* OUT8X = print eight hexadecimal characters
|
221 |
|
|
* In each case, the data to be printed is in D0
|
222 |
|
|
*
|
223 |
|
|
OUT1X MOVE.W D0,-(A7) Save D0
|
224 |
|
|
AND.B #$0F,D0 Mask off MS nybble
|
225 |
|
|
ADD.B #$30,D0 Convert to ASCII
|
226 |
|
|
CMP.B #$39,D0 ASCII = HEX + $30
|
227 |
|
|
BLS.S OUT1X1 If ASCII <= $39 then print and exit
|
228 |
|
|
ADD.B #$07,D0 Else ASCII := HEX + 7
|
229 |
|
|
OUT1X1 BSR PUTCHAR Print the character
|
230 |
|
|
MOVE.W (A7)+,D0 Restore D0
|
231 |
|
|
RTS
|
232 |
|
|
*
|
233 |
|
|
OUT2X ROR.B #4,D0 Get MS nybble in LS position
|
234 |
|
|
BSR OUT1X Print MS nybble
|
235 |
|
|
ROL.B #4,D0 Restore LS nybble
|
236 |
|
|
BRA OUT1X Print LS nybble and return
|
237 |
|
|
*
|
238 |
|
|
OUT4X ROR.W #8,D0 Get MS byte in LS position
|
239 |
|
|
BSR OUT2X Print MS byte
|
240 |
|
|
ROL.W #8,D0 Restore LS byte
|
241 |
|
|
BRA OUT2X Print LS byte and return
|
242 |
|
|
*
|
243 |
|
|
OUT8X SWAP D0 Get MS word in LS position
|
244 |
|
|
BSR OUT4X Print MS word
|
245 |
|
|
SWAP D0 Restore LS word
|
246 |
|
|
BRA OUT4X Print LS word and return
|
247 |
|
|
*
|
248 |
|
|
*************************************************************************
|
249 |
|
|
*
|
250 |
|
|
* JUMP causes execution to begin at the address in the line buffer
|
251 |
|
|
*
|
252 |
|
|
JUMP BSR PARAM Get address from buffer
|
253 |
|
|
TST.B D7 Test for input error
|
254 |
|
|
BNE.S JUMP1 If error flag not zero then exit
|
255 |
|
|
TST.L D0 Else test for missing address
|
256 |
|
|
BEQ.S JUMP1 field. If no address then exit
|
257 |
|
|
MOVE.L D0,A0 Put jump address in A0 and call the
|
258 |
|
|
JMP (A0) subroutine. User to supply RTS!!
|
259 |
|
|
JUMP1 LEA.L ERMES1(PC),A4 Here for error - display error
|
260 |
|
|
BRA PSTRING message and return
|
261 |
|
|
*
|
262 |
|
|
*************************************************************************
|
263 |
|
|
*
|
264 |
|
|
* Display the contents of a memory location and modify it
|
265 |
|
|
*
|
266 |
|
|
MEMORY BSR PARAM Get start address from line buffer
|
267 |
|
|
TST.B D7 Test for input error
|
268 |
|
|
BNE.S MEM3 If error then exit
|
269 |
|
|
MOVE.L D0,A3 A3 points to location to be opened
|
270 |
|
|
MEM1 BSR NEWLINE
|
271 |
|
|
BSR.S ADR_DAT Print current address and contents
|
272 |
|
|
BSR.S PSPACE update pointer, A3, and O/P space
|
273 |
|
|
BSR GETCHAR Input char to decide next action
|
274 |
|
|
CMP.B #CR,D0 If carriage return then exit
|
275 |
|
|
BEQ.S MEM3 Exit
|
276 |
|
|
CMP.B #'-',D0 If "-" then move back
|
277 |
|
|
BNE.S MEM2 Else skip wind-back procedure
|
278 |
|
|
LEA.L -4(A3),A3 Move pointer back 2+2
|
279 |
|
|
BRA MEM1 Repeat until carriage return
|
280 |
|
|
MEM2 CMP.B #SPACE,D0 Test for space (= new entry)
|
281 |
|
|
BNE.S MEM1 If not space then repeat
|
282 |
|
|
BSR WORD Else get new word to store
|
283 |
|
|
TST.B D7 Test for input error
|
284 |
|
|
BNE.S MEM3 If error then exit
|
285 |
|
|
MOVE.W D0,-2(A3) Store new word
|
286 |
|
|
BRA MEM1 Repeat until carriage return
|
287 |
|
|
MEM3 RTS
|
288 |
|
|
*
|
289 |
|
|
ADR_DAT MOVE.L D0,-(A7) Print the contents of A3 and the
|
290 |
|
|
MOVE.L A3,D0 word pointed at by A3.
|
291 |
|
|
BSR OUT8X and print current address
|
292 |
|
|
BSR.S PSPACE Insert delimiter
|
293 |
|
|
MOVE.W (A3),D0 Get data at this address in D0
|
294 |
|
|
BSR OUT4X and print it
|
295 |
|
|
LEA.L 2(A3),A3 Point to next address to display
|
296 |
|
|
MOVE.L (A7)+,D0 Restore D0
|
297 |
|
|
RTS
|
298 |
|
|
*
|
299 |
|
|
PSPACE MOVE.B D0,-(A7) Print a single space
|
300 |
|
|
MOVE.B #SPACE,D0
|
301 |
|
|
BSR PUTCHAR
|
302 |
|
|
MOVE.B (A7)+,D0
|
303 |
|
|
RTS
|
304 |
|
|
*
|
305 |
|
|
*************************************************************************
|
306 |
|
|
*
|
307 |
|
|
* LOAD Loads data formatted in hexadecimal "S" format
|
308 |
|
|
*
|
309 |
|
|
LOAD MOVE.L BUFFPT(A6),A4 Any string in the line buffer is
|
310 |
|
|
LOAD1 MOVE.B (A4)+,D0 transmitted to the host computer
|
311 |
|
|
BSR PUTCHAR before the loading begins
|
312 |
|
|
CMP.B #CR,D0 Read from the buffer until EOL
|
313 |
|
|
BNE LOAD1
|
314 |
|
|
BSR NEWLINE Send newline before loading
|
315 |
|
|
LOAD2 BSR GETCHAR Records from the host must begin
|
316 |
|
|
CMP.B #'S',D0 with S1/S2 (data) or S9/S8 (term)
|
317 |
|
|
BNE.S LOAD2 Repeat GETCHAR until char = "S"
|
318 |
|
|
BSR GETCHAR Get character after "S"
|
319 |
|
|
CMP.B #'9',D0 Test for the two terminators S9/S8
|
320 |
|
|
BEQ.S LOAD3 If S9 record then exit else test
|
321 |
|
|
CMP.B #'8',D0 for S8 terminator. Fall through to
|
322 |
|
|
BNE.S LOAD6 exit on S8 else continue search
|
323 |
|
|
LOAD3 EQU * Exit point from LOAD
|
324 |
|
|
BTST.B #0,D7 Test for input errors
|
325 |
|
|
BEQ.S LOAD4 If no I/P error then look at checksum
|
326 |
|
|
LEA.L ERMES1(PC),A4 Else point to error message
|
327 |
|
|
BSR PSTRING Print it
|
328 |
|
|
LOAD4 BTST.B #3,D7 Test for checksum error
|
329 |
|
|
BEQ.S LOAD5 If clear then exit
|
330 |
|
|
LEA.L ERMES3(PC),A4 Else point to error message
|
331 |
|
|
BSR PSTRING Print it and return
|
332 |
|
|
LOAD5 RTS
|
333 |
|
|
*
|
334 |
|
|
LOAD6 CMP.B #'1',D0 Test for S1 record
|
335 |
|
|
BEQ.S LOAD6A If S1 record then read it
|
336 |
|
|
CMP.B #'2',D0 Else test for S2 record
|
337 |
|
|
BNE.S LOAD2 Repeat until valid header found
|
338 |
|
|
CLR.B D3 Read the S2 byte count and address,
|
339 |
|
|
BSR.S LOAD8 clear the checksum
|
340 |
|
|
SUB.B #4,D0 Calculate size of data field
|
341 |
|
|
MOVE.B D0,D2 D2 contains data bytes to read
|
342 |
|
|
CLR.L D0 Clear address accumulator
|
343 |
|
|
BSR.S LOAD8 Read most sig byte of address
|
344 |
|
|
ASL.L #8,D0 Move it one byte left
|
345 |
|
|
BSR.S LOAD8 Read the middle byte of address
|
346 |
|
|
ASL.L #8,D0 Move it one byte left
|
347 |
|
|
BSR.S LOAD8 Read least sig byte of address
|
348 |
|
|
MOVE.L D0,A2 A2 points to destination of record
|
349 |
|
|
BRA.S LOAD7 Skip past S1 header loader
|
350 |
|
|
LOAD6A CLR.B D3 S1 record found - clear checksum
|
351 |
|
|
BSR.S LOAD8 Get byte and update checksum
|
352 |
|
|
SUB.B #3,D0 Subtract 3 from record length
|
353 |
|
|
MOVE.B D0,D2 Save byte count in D2
|
354 |
|
|
CLR.L D0 Clear address accumulator
|
355 |
|
|
BSR.S LOAD8 Get MS byte of load address
|
356 |
|
|
ASL.L #8,D0 Move it to MS position
|
357 |
|
|
BSR.S LOAD8 Get LS byte in D2
|
358 |
|
|
MOVE.L D0,A2 A2 points to destination of data
|
359 |
|
|
LOAD7 BSR.S LOAD8 Get byte of data for loading
|
360 |
|
|
MOVE.B D0,(A2)+ Store it
|
361 |
|
|
SUB.B #1,D2 Decrement byte counter
|
362 |
|
|
BNE LOAD7 Repeat until count = 0
|
363 |
|
|
BSR.S LOAD8 Read checksum
|
364 |
|
|
ADD.B #1,D3 Add 1 to total checksum
|
365 |
|
|
BEQ LOAD2 If zero then start next record
|
366 |
|
|
OR.B #%00001000,D7 Else set checksum error bit,
|
367 |
|
|
BRA LOAD3 restore I/O devices and return
|
368 |
|
|
*
|
369 |
|
|
LOAD8 BSR BYTE Get a byte
|
370 |
|
|
ADD.B D0,D3 Update checksum
|
371 |
|
|
RTS and return
|
372 |
|
|
*
|
373 |
|
|
*************************************************************************
|
374 |
|
|
*
|
375 |
|
|
* DUMP Transmit S1 formatted records
|
376 |
|
|
* A3 = Starting address of data block
|
377 |
|
|
* A2 = End address of data block
|
378 |
|
|
* D1 = Checksum, D2 = current record length
|
379 |
|
|
*
|
380 |
|
|
DUMP BSR RANGE Get start and end address
|
381 |
|
|
TST.B D7 Test for input error
|
382 |
|
|
BEQ.S DUMP1 If no error then continue
|
383 |
|
|
LEA.L ERMES1(PC),A4 Else point to error message,
|
384 |
|
|
BRA PSTRING print it and return
|
385 |
|
|
DUMP1 CMP.L A3,D0 Compare start and end addresses
|
386 |
|
|
BPL.S DUMP2 If positive then start < end
|
387 |
|
|
LEA.L ERMES7(PC),A4 Else print error message
|
388 |
|
|
BRA PSTRING and return
|
389 |
|
|
DUMP2 BSR NEWLINE Send newline to host and wait
|
390 |
|
|
MOVE.L BUFFPT(A6),A4 Before dumping, send any string
|
391 |
|
|
DUMP3 MOVE.B (A4)+,D0 in the input buffer to the host
|
392 |
|
|
BSR PUTCHAR Repeat
|
393 |
|
|
CMP.B #CR,D0 Transmit char from buffer to host
|
394 |
|
|
BNE DUMP3 Until char = C/R
|
395 |
|
|
BSR NEWLINE
|
396 |
|
|
ADDQ.L #1,A2 A2 contains length of record + 1
|
397 |
|
|
DUMP4 MOVE.L A2,D2 D2 points to end address
|
398 |
|
|
SUB.L A3,D2 D2 contains bytes left to print
|
399 |
|
|
CMP.L #17,D2 If this is not a full record of 16
|
400 |
|
|
BCS.S DUMP5 then load D2 with record size
|
401 |
|
|
MOVEQ #16,D2 Else preset byte count to 16
|
402 |
|
|
DUMP5 LEA.L HEADER(PC),A4 Point to record header
|
403 |
|
|
BSR PSTRING Print header
|
404 |
|
|
CLR.B D1 Clear checksum
|
405 |
|
|
MOVE.B D2,D0 Move record length to output register
|
406 |
|
|
ADD.B #3,D0 Length includes address + count
|
407 |
|
|
BSR.S DUMP7 Print number of bytes in record
|
408 |
|
|
MOVE.L A3,D0 Get start address to be printed
|
409 |
|
|
ROL.W #8,D0 Get MS byte in LS position
|
410 |
|
|
BSR.S DUMP7 Print MS byte of address
|
411 |
|
|
ROR.W #8,D0 Restore LS byte
|
412 |
|
|
BSR.S DUMP7 Print LS byte of address
|
413 |
|
|
DUMP6 MOVE.B (A3)+,D0 Get data byte to be printed
|
414 |
|
|
BSR.S DUMP7 Print it
|
415 |
|
|
SUB.B #1,D2 Decrement byte count
|
416 |
|
|
BNE DUMP6 Repeat until all this record printed
|
417 |
|
|
NOT.B D1 Complement checksum
|
418 |
|
|
MOVE.B D1,D0 Move to output register
|
419 |
|
|
BSR.S DUMP7 Print checksum
|
420 |
|
|
BSR NEWLINE
|
421 |
|
|
CMP.L A2,A3 Have all records been printed?
|
422 |
|
|
BNE DUMP4 Repeat until all done
|
423 |
|
|
LEA.L TAIL(PC),A4 Point to message tail (S9 record)
|
424 |
|
|
BSR PSTRING Print it
|
425 |
|
|
RTS and return
|
426 |
|
|
*
|
427 |
|
|
DUMP7 ADD.B D0,D1 Update checksum, transmit byte
|
428 |
|
|
BRA OUT2X to host and return
|
429 |
|
|
*
|
430 |
|
|
RANGE EQU * Get the range of addresses to be
|
431 |
|
|
CLR.B D7 transmitted from the buffer
|
432 |
|
|
BSR PARAM Get starting address
|
433 |
|
|
MOVE.L D0,A3 Set up start address in A3
|
434 |
|
|
BSR PARAM Get end address
|
435 |
|
|
MOVE.L D0,A2 Set up end address in A2
|
436 |
|
|
RTS
|
437 |
|
|
*
|
438 |
|
|
*************************************************************************
|
439 |
|
|
*
|
440 |
|
|
* GETCHAR gets a character
|
441 |
|
|
*
|
442 |
|
|
GETCHAR MOVE.B D0,D1
|
443 |
|
|
MOVE.B #5,D0
|
444 |
|
|
TRAP #15
|
445 |
|
|
MOVE.B D1,D0
|
446 |
|
|
AND.B #$7F,D0 Strip msb of input
|
447 |
|
|
TST.B U_CASE(A6) Test for upper -> lower case conversion
|
448 |
|
|
BNE.S GETCH2 If flag not zero do not convert case
|
449 |
|
|
BTST.B #6,D0 Test input for lower case
|
450 |
|
|
BEQ.S GETCH2 If upper case then skip conversion
|
451 |
|
|
AND.B #%11011111,D0 Else clear bit 5 for upper case conv
|
452 |
|
|
GETCH2 TST.B ECHO(A6) Do we need to echo the input?
|
453 |
|
|
BNE.S GETCH3 If ECHO not zero then no echo
|
454 |
|
|
BSR.S PUTCHAR Else echo the input
|
455 |
|
|
GETCH3 RTS and return
|
456 |
|
|
*
|
457 |
|
|
*************************************************************************
|
458 |
|
|
*
|
459 |
|
|
* PUTCHAR sends a character to the console device
|
460 |
|
|
* The name of the output device is in CN_OVEC.
|
461 |
|
|
*
|
462 |
|
|
PUTCHAR MOVE.L D1,-(A7) Save working register
|
463 |
|
|
MOVE.B D0,D1
|
464 |
|
|
MOVE.B #6,D0
|
465 |
|
|
TRAP #15
|
466 |
|
|
MOVE.L (A7)+,D1 Restore working register
|
467 |
|
|
RTS
|
468 |
|
|
*
|
469 |
|
|
*************************************************************************
|
470 |
|
|
*
|
471 |
|
|
* Exception vector table initialization routine
|
472 |
|
|
* All vectors not setup are loaded with uninitialized routine vector
|
473 |
|
|
*
|
474 |
|
|
X_SET LEA.L X_BASE,A0 Point to base of exception table
|
475 |
|
|
MOVE.W #253,D0 Number of vectors - 3
|
476 |
|
|
X_SET1 CMPA.L #188,A0 Avoid TRAP #15 (required by the simulator)
|
477 |
|
|
BEQ X_SET2
|
478 |
|
|
MOVE.L #X_UN,(A0) Store uninitialized exception vector
|
479 |
|
|
X_SET2 ADDA.L #4,A0
|
480 |
|
|
DBRA D0,X_SET1 Repeat until all entries preset
|
481 |
|
|
SUB.L A0,A0 Clear A0 (points to vector table)
|
482 |
|
|
MOVE.L #BUS_ER,8(A0) Setup bus error vector
|
483 |
|
|
MOVE.L #ADD_ER,12(A0) Setup address error vector
|
484 |
|
|
MOVE.L #IL_ER,16(A0) Setup illegal instruction error vect
|
485 |
|
|
MOVE.L #TRACE,36(A0) Setup trace exception vector
|
486 |
|
|
MOVE.L #BRKPT,184(A0) Setup TRAP #14 vector = breakpoint
|
487 |
|
|
MOVE.W #7,D0 Now clear the breakpoint table
|
488 |
|
|
LEA.L BP_TAB(A6),A0 Point to table
|
489 |
|
|
X_SET3 CLR.L (A0)+ Clear an address entry
|
490 |
|
|
CLR.W (A0)+ Clear the corresponding data
|
491 |
|
|
DBRA D0,X_SET3 Repeat until all 8 cleared
|
492 |
|
|
RTS
|
493 |
|
|
*
|
494 |
|
|
*
|
495 |
|
|
*************************************************************************
|
496 |
|
|
*
|
497 |
|
|
* Display exception frame (D0 - D7, A0 - A6, USP, SSP, SR, PC)
|
498 |
|
|
* EX_DIS prints registers saved after a breakpoint or exception
|
499 |
|
|
* The registers are saved in TSK_T
|
500 |
|
|
*
|
501 |
|
|
EX_DIS LEA.L TSK_T(A6),A5 A5 points to display frame
|
502 |
|
|
LEA.L MES3(PC),A4 Point to heading
|
503 |
|
|
BSR HEADING and print it
|
504 |
|
|
MOVE.W #7,D6 8 pairs of registers to display
|
505 |
|
|
CLR.B D5 D5 is the line counter
|
506 |
|
|
EX_D1 MOVE.B D5,D0 Put current register number in D0
|
507 |
|
|
BSR OUT1X and print it
|
508 |
|
|
BSR PSPACE and a space
|
509 |
|
|
ADD.B #1,D5 Update counter for next pair
|
510 |
|
|
MOVE.L (A5),D0 Get data register to be displayed
|
511 |
|
|
BSR OUT8X from the frame and print it
|
512 |
|
|
LEA.L MES4(PC),A4 Print string of spaces
|
513 |
|
|
BSR.L PSTRING between data and address registers
|
514 |
|
|
MOVE.L 32(A5),D0 Get address register to be displayed
|
515 |
|
|
BSR OUT8X which is 32 bytes on from data reg
|
516 |
|
|
BSR NEWLINE
|
517 |
|
|
LEA.L 4(A5),A5 Point to next pair (ie Di, Ai)
|
518 |
|
|
DBRA D6,EX_D1 Repeat until all displayed
|
519 |
|
|
LEA.L 32(A5),A5 Adjust pointer by 8 longwords
|
520 |
|
|
BSR NEWLINE to point to SSP
|
521 |
|
|
LEA.L MES2A(PC),A4 Point to "SS ="
|
522 |
|
|
BSR PSTRING Print it
|
523 |
|
|
MOVE.L (A5)+,D0 Get SSP from frame
|
524 |
|
|
BSR OUT8X and display it
|
525 |
|
|
BSR NEWLINE
|
526 |
|
|
LEA.L MES1(PC),A4 Point to 'SR ='
|
527 |
|
|
BSR PSTRING Print it
|
528 |
|
|
MOVE.W (A5)+,D0 Get status register
|
529 |
|
|
BSR OUT4X Display status
|
530 |
|
|
BSR NEWLINE
|
531 |
|
|
LEA.L MES2(PC),A4 Point to 'PC ='
|
532 |
|
|
BSR PSTRING Print it
|
533 |
|
|
MOVE.L (A5)+,D0 Get PC
|
534 |
|
|
BSR OUT8X Display PC
|
535 |
|
|
BRA NEWLINE Newline and return
|
536 |
|
|
*
|
537 |
|
|
*************************************************************************
|
538 |
|
|
*
|
539 |
|
|
* Exception handling routines
|
540 |
|
|
*
|
541 |
|
|
IL_ER EQU * Illegal instruction exception
|
542 |
|
|
MOVE.L A4,-(A7) Save A4
|
543 |
|
|
LEA.L MES10(PC),A4 Point to heading
|
544 |
|
|
BSR HEADING Print it
|
545 |
|
|
MOVE.L (A7)+,A4 Restore A4
|
546 |
|
|
BSR.S GROUP2 Save registers in display frame
|
547 |
|
|
BSR EX_DIS Display registers saved in frame
|
548 |
|
|
BRA WARM Abort from illegal instruction
|
549 |
|
|
*
|
550 |
|
|
BUS_ER EQU * Bus error (group 1) exception
|
551 |
|
|
MOVE.L A4,-(A7) Save A4
|
552 |
|
|
LEA.L MES8(PC),A4 Point to heading
|
553 |
|
|
BSR HEADING Print it
|
554 |
|
|
MOVE.L (A7)+,A4 Restore A4
|
555 |
|
|
BRA.S GROUP1 Deal with group 1 exception
|
556 |
|
|
*
|
557 |
|
|
ADD_ER EQU * Address error (group 1) exception
|
558 |
|
|
MOVE.L A4,-(A7) Save A4
|
559 |
|
|
LEA.L MES9(PC),A4 Point to heading
|
560 |
|
|
BSR HEADING Print it
|
561 |
|
|
MOVE.L (A7)+,A4 Restore A4
|
562 |
|
|
BRA.S GROUP1 Deal with group 1 exception
|
563 |
|
|
*
|
564 |
|
|
BRKPT EQU * Deal with breakpoint
|
565 |
|
|
MOVEM.L D0-D7/A0-A6,-(A7) Save all registers
|
566 |
|
|
BSR BR_CLR Clear breakpoints in code
|
567 |
|
|
MOVEM.L (A7)+,D0-D7/A0-A6 Restore registers
|
568 |
|
|
BSR.S GROUP2 Treat as group 2 exception
|
569 |
|
|
LEA.L MES11(PC),A4 Point to heading
|
570 |
|
|
BSR HEADING Print it
|
571 |
|
|
BSR EX_DIS Display saved registers
|
572 |
|
|
BRA WARM Return to monitor
|
573 |
|
|
*
|
574 |
|
|
* GROUP1 is called by address and bus error exceptions
|
575 |
|
|
* These are "turned into group 2" exceptions (eg TRAP)
|
576 |
|
|
* by modifying the stack frame saved by a group 1 exception
|
577 |
|
|
*
|
578 |
|
|
GROUP1 MOVEM.L D0/A0,-(A7) Save working registers
|
579 |
|
|
MOVE.L 18(A7),A0 Get PC from group 1 stack frame
|
580 |
|
|
MOVE.W 14(A7),D0 Get instruction from stack frame
|
581 |
|
|
CMP.W -(A0),D0 Now backtrack to find the "correct PC"
|
582 |
|
|
BEQ.S GROUP1A by matching the op-code on the stack
|
583 |
|
|
CMP.W -(A0),D0 with the code in the region of the
|
584 |
|
|
BEQ.S GROUP1A PC on the stack
|
585 |
|
|
CMP.W -(A0),D0
|
586 |
|
|
BEQ.S GROUP1A
|
587 |
|
|
CMP.W -(A0),D0
|
588 |
|
|
BEQ.S GROUP1A
|
589 |
|
|
SUBQ.L #2,A0
|
590 |
|
|
GROUP1A MOVE.L A0,18(A7) Restore modified PC to stack frame
|
591 |
|
|
MOVEM.L (A7)+,D0/A0 Restore working registers
|
592 |
|
|
LEA.L 8(A7),A7 Adjust stack pointer to group 1 type
|
593 |
|
|
BSR.S GROUP2 Now treat as group 1 exception
|
594 |
|
|
BSR EX_DIS Display contents of exception frame
|
595 |
|
|
BRA WARM Exit to monitor - no RTE from group 2
|
596 |
|
|
*
|
597 |
|
|
GROUP2 EQU * Deal with group 2 exceptions
|
598 |
|
|
MOVEM.L A0-A7/D0-D7,-(A7) Save all registers on the stack
|
599 |
|
|
MOVE.W #14,D0 Transfer D0 - D7, A0 - A6 from
|
600 |
|
|
LEA.L TSK_T(A6),A0 the stack to the display frame
|
601 |
|
|
GROUP2A MOVE.L (A7)+,(A0)+ Move a register from stack to frame
|
602 |
|
|
DBRA D0,GROUP2A and repeat until D0-D7/A0-A6 moved
|
603 |
|
|
MOVE.L USP,A2 Get the user stack pointer and put it
|
604 |
|
|
MOVE.L A2,(A0)+ in the A7 position in the frame
|
605 |
|
|
MOVE.L (A7)+,D0 Now transfer the SSP to the frame,
|
606 |
|
|
SUB.L #10,D0 remembering to account for the
|
607 |
|
|
MOVE.L D0,(A0)+ data pushed on the stack to this point
|
608 |
|
|
MOVE.L (A7)+,A1 Copy TOS (return address) to A1
|
609 |
|
|
MOVE.W (A7)+,(A0)+ Move SR to display frame
|
610 |
|
|
MOVE.L (A7)+,D0 Get PC in D0
|
611 |
|
|
SUBQ.L #2,D0 Move back to current instruction
|
612 |
|
|
MOVE.L D0,(A0)+ Put adjusted PC in display frame
|
613 |
|
|
JMP (A1) Return from subroutine
|
614 |
|
|
*
|
615 |
|
|
*************************************************************************
|
616 |
|
|
*
|
617 |
|
|
* GO executes a program either from a supplied address or
|
618 |
|
|
* by using the data in the display frame
|
619 |
|
|
GO BSR PARAM Get entry address (if any)
|
620 |
|
|
TST.B D7 Test for error in input
|
621 |
|
|
BEQ.S GO1 If D7 zero then OK
|
622 |
|
|
LEA.L ERMES1(PC),A4 Else point to error message,
|
623 |
|
|
BRA PSTRING print it and return
|
624 |
|
|
GO1 TST.L D0 If no address entered then get
|
625 |
|
|
BEQ.S GO2 address from display frame
|
626 |
|
|
MOVE.L D0,TSK_T+70(A6) Else save address in display frame
|
627 |
|
|
MOVE.W #$2700,TSK_T+68(A6) Store dummy status in frame
|
628 |
|
|
GO2 BRA.S RESTORE Restore volatile environment and go
|
629 |
|
|
*
|
630 |
|
|
GB BSR BR_SET Same as go but presets breakpoints
|
631 |
|
|
BRA.S GO Execute program
|
632 |
|
|
*
|
633 |
|
|
* RESTORE moves the volatile environment from the display
|
634 |
|
|
* frame and transfers it to the 68000's registers. This
|
635 |
|
|
* re-runs a program suspended after an exception
|
636 |
|
|
*
|
637 |
|
|
RESTORE LEA.L TSK_T(A6),A3 A3 points to display frame
|
638 |
|
|
LEA.L 74(A3),A3 A3 now points to end of frame + 4
|
639 |
|
|
LEA.L 4(A7),A7 Remove return address from stack
|
640 |
|
|
MOVE.W #36,D0 Counter for 37 words to be moved
|
641 |
|
|
REST1 MOVE.W -(A3),-(A7) Move word from display frame to stack
|
642 |
|
|
DBRA D0,REST1 Repeat until entire frame moved
|
643 |
|
|
MOVEM.L (A7)+,D0-D7 Restore old data registers from stack
|
644 |
|
|
MOVEM.L (A7)+,A0-A6 Restore old address registers
|
645 |
|
|
LEA.L 8(A7),A7 Except SSP/USP - so adjust stack
|
646 |
|
|
RTE Return from exception to run program
|
647 |
|
|
*
|
648 |
|
|
TRACE EQU * TRACE exception (rudimentary version)
|
649 |
|
|
MOVE.L MES12(PC),A4 Point to heading
|
650 |
|
|
BSR HEADING Print it
|
651 |
|
|
BSR GROUP1 Save volatile environment
|
652 |
|
|
BSR EX_DIS Display it
|
653 |
|
|
BRA WARM Return to monitor
|
654 |
|
|
*
|
655 |
|
|
*************************************************************************
|
656 |
|
|
* Breakpoint routines: BR_GET gets the address of a breakpoint and
|
657 |
|
|
* puts it in the breakpoint table. It does not plant it in the code.
|
658 |
|
|
* BR_SET plants all breakpoints in the code. NOBR removes one or all
|
659 |
|
|
* breakpoints from the table. KILL removes breakpoints from the code.
|
660 |
|
|
*
|
661 |
|
|
BR_GET BSR PARAM Get breakpoint address in table
|
662 |
|
|
TST.B D7 Test for input error
|
663 |
|
|
BEQ.S BR_GET1 If no error then continue
|
664 |
|
|
LEA.L ERMES1(PC),A4 Else display error
|
665 |
|
|
BRA PSTRING and return
|
666 |
|
|
BR_GET1 LEA.L BP_TAB(A6),A3 A6 points to breakpoint table
|
667 |
|
|
MOVE.L D0,A5 Save new BP address in A5
|
668 |
|
|
MOVE.L D0,D6 and in D6 because D0 gets corrupted
|
669 |
|
|
MOVE.W #7,D5 Eight entries to test
|
670 |
|
|
BR_GET2 MOVE.L (A3)+,D0 Read entry from breakpoint table
|
671 |
|
|
BNE.S BR_GET3 If not zero display existing BP
|
672 |
|
|
TST.L D6 Only store a non-zero breakpoint
|
673 |
|
|
BEQ.S BR_GET4
|
674 |
|
|
MOVE.L A5,-4(A3) Store new breakpoint in table
|
675 |
|
|
MOVE.W (A5),(A3) Save code at BP address in table
|
676 |
|
|
CLR.L D6 Clear D6 to avoid repetition
|
677 |
|
|
BR_GET3 BSR OUT8X Display this breakpoint
|
678 |
|
|
BSR NEWLINE
|
679 |
|
|
BR_GET4 LEA.L 2(A3),A3 Step past stored op-code
|
680 |
|
|
DBRA D5,BR_GET2 Repeat until all entries tested
|
681 |
|
|
RTS Return
|
682 |
|
|
*
|
683 |
|
|
BR_SET EQU * Plant any breakpoints in user code
|
684 |
|
|
LEA.L BP_TAB(A6),A0 A0 points to BP table
|
685 |
|
|
LEA.L TSK_T+70(A6),A2 A2 points to PC in display frame
|
686 |
|
|
MOVE.L (A2),A2 Now A2 contains value of PC
|
687 |
|
|
MOVE.W #7,D0 Up to eight entries to plant
|
688 |
|
|
BR_SET1 MOVE.L (A0)+,D1 Read breakpoint address from table
|
689 |
|
|
BEQ.S BR_SET2 If zero then skip planting
|
690 |
|
|
CMP.L A2,D1 Don't want to plant BP at current PC
|
691 |
|
|
BEQ.S BR_SET2 location, so skip planting if same
|
692 |
|
|
MOVE.L D1,A1 Transfer BP address to address reg
|
693 |
|
|
MOVE.W #TRAP_14,(A1) Plant op-code for TRAP #14 in code
|
694 |
|
|
BR_SET2 LEA.L 2(A0),A0 Skip past op-code field in table
|
695 |
|
|
DBRA D0,BR_SET1 Repeat until all entries tested
|
696 |
|
|
RTS
|
697 |
|
|
*
|
698 |
|
|
NOBR EQU * Clear one or all breakpoints
|
699 |
|
|
BSR PARAM Get BP address (if any)
|
700 |
|
|
TST.B D7 Test for input error
|
701 |
|
|
BEQ.S NOBR1 If no error then skip abort
|
702 |
|
|
LEA.L ERMES1(PC),A4 Point to error message
|
703 |
|
|
BRA PSTRING Display it and return
|
704 |
|
|
NOBR1 TST.L D0 Test for null address (clear all)
|
705 |
|
|
BEQ.S NOBR4 If no address then clear all entries
|
706 |
|
|
MOVE.L D0,A1 Else just clear breakpoint in A1
|
707 |
|
|
LEA.L BP_TAB(A6),A0 A0 points to BP table
|
708 |
|
|
MOVE.W #7,D0 Up to eight entries to test
|
709 |
|
|
NOBR2 MOVE.L (A0)+,D1 Get entry and
|
710 |
|
|
LEA.L 2(A0),A0 skip past op-code field
|
711 |
|
|
CMP.L A1,D1 Is this the one?
|
712 |
|
|
BEQ.S NOBR3 If so go and clear entry
|
713 |
|
|
DBRA D0,NOBR2 Repeat until all tested
|
714 |
|
|
RTS
|
715 |
|
|
NOBR3 CLR.L -6(A0) Clear address in BP table
|
716 |
|
|
RTS
|
717 |
|
|
NOBR4 LEA.L BP_TAB(A6),A0 Clear all 8 entries in BP table
|
718 |
|
|
MOVE.W #7,D0 Eight entries to clear
|
719 |
|
|
NOBR5 CLR.L (A0)+ Clear breakpoint address
|
720 |
|
|
CLR.W (A0)+ Clear op-code field
|
721 |
|
|
DBRA D0,NOBR5 Repeat until all done
|
722 |
|
|
RTS
|
723 |
|
|
*
|
724 |
|
|
BR_CLR EQU * Remove breakpoints from code
|
725 |
|
|
LEA.L BP_TAB(A6),A0 A0 points to breakpoint table
|
726 |
|
|
MOVE.W #7,D0 Up to eight entries to clear
|
727 |
|
|
BR_CLR1 MOVE.L (A0)+,D1 Get address of BP in D1
|
728 |
|
|
MOVE.L D1,A1 and put copy in A1
|
729 |
|
|
TST.L D1 Test this breakpoint
|
730 |
|
|
BEQ.S BR_CLR2 If zero then skip BP clearing
|
731 |
|
|
MOVE.W (A0),(A1) Else restore op-code
|
732 |
|
|
BR_CLR2 LEA.L 2(A0),A0 Skip past op-code field
|
733 |
|
|
DBRA D0,BR_CLR1 Repeat until all tested
|
734 |
|
|
RTS
|
735 |
|
|
*
|
736 |
|
|
* REG_MOD modifies a register in the display frame. The command
|
737 |
|
|
* format is REG <reg> <value>. E.g. REG D3 1200
|
738 |
|
|
*
|
739 |
|
|
REG_MOD CLR.L D1 D1 to hold name of register
|
740 |
|
|
LEA.L BUFFPT(A6),A0 A0 contains address of buffer pointer
|
741 |
|
|
MOVE.L (A0),A0 A0 now points to next char in buffer
|
742 |
|
|
MOVE.B (A0)+,D1 Put first char of name in D1
|
743 |
|
|
ROL.W #8,D1 Move char one place left
|
744 |
|
|
MOVE.B (A0)+,D1 Get second char in D1
|
745 |
|
|
LEA.L 1(A0),A0 Move pointer past space in buffer
|
746 |
|
|
MOVE.L A0,BUFFPT(A6) Update buffer pointer
|
747 |
|
|
CLR.L D2 D2 is the character pair counter
|
748 |
|
|
LEA.L REGNAME(PC),A0 A0 points to string of character pairs
|
749 |
|
|
LEA.L (A0),A1 A1 also points to string
|
750 |
|
|
REG_MD1 CMP.W (A0)+,D1 Compare a char pair with input
|
751 |
|
|
BEQ.S REG_MD2 If match then exit loop
|
752 |
|
|
ADD.L #1,D2 Else increment match counter
|
753 |
|
|
CMP.L #19,D2 Test for end of loop
|
754 |
|
|
BNE REG_MD1 Continue until all pairs matched
|
755 |
|
|
LEA.L ERMES1(PC),A4 If here then error
|
756 |
|
|
BRA PSTRING Display error and return
|
757 |
|
|
REG_MD2 LEA.L TSK_T(A6),A1 A1 points to display frame
|
758 |
|
|
ASL.L #2,D2 Multiply offset by 4 (4 bytes/entry)
|
759 |
|
|
CMP.L #72,D2 Test for address of PC
|
760 |
|
|
BNE.S REG_MD3 If not PC then all is OK
|
761 |
|
|
SUB.L #2,D2 else dec PC pointer as Sr is a word
|
762 |
|
|
REG_MD3 LEA.L (A1,D2),A2 Calculate address of entry in disptable
|
763 |
|
|
MOVE.L (A2),D0 Get old contents
|
764 |
|
|
BSR OUT8X Display them
|
765 |
|
|
BSR NEWLINE
|
766 |
|
|
BSR PARAM Get new data
|
767 |
|
|
TST.B D7 Test for input error
|
768 |
|
|
BEQ.S REG_MD4 If no error then go and store data
|
769 |
|
|
LEA.L ERMES1(PC),A4 Else point to error message
|
770 |
|
|
BRA PSTRING print it and return
|
771 |
|
|
REG_MD4 CMP.L #68,D2 If this address is the SR then
|
772 |
|
|
BEQ.S REG_MD5 we have only a word to store
|
773 |
|
|
MOVE.L D0,(A2) Else store new data in display frame
|
774 |
|
|
RTS
|
775 |
|
|
REG_MD5 MOVE.W D0,(A2) Store SR (one word)
|
776 |
|
|
RTS
|
777 |
|
|
*
|
778 |
|
|
*************************************************************************
|
779 |
|
|
*
|
780 |
|
|
X_UN EQU * Uninitialized exception vector routine
|
781 |
|
|
LEA.L ERMES6(PC),A4 Point to error message
|
782 |
|
|
BSR PSTRING Display it
|
783 |
|
|
BSR EX_DIS Display registers
|
784 |
|
|
BRA WARM Abort
|
785 |
|
|
*
|
786 |
|
|
*************************************************************************
|
787 |
|
|
*
|
788 |
|
|
* All strings and other fixed parameters here
|
789 |
|
|
*
|
790 |
|
|
BANNER DC.B 'TSBUG Version 3.10.96',0,0
|
791 |
|
|
CRLF DC.B CR,LF,'?',0
|
792 |
|
|
HEADER DC.B CR,LF,'S','1',0,0
|
793 |
|
|
TAIL DC.B 'S9 ',0,0
|
794 |
|
|
MES1 DC.B ' SR = ',0
|
795 |
|
|
MES2 DC.B ' PC = ',0
|
796 |
|
|
MES2A DC.B ' SS = ',0
|
797 |
|
|
MES3 DC.B ' Data reg Address reg',0,0
|
798 |
|
|
MES4 DC.B ' ',0,0
|
799 |
|
|
MES8 DC.B 'Bus error ',0,0
|
800 |
|
|
MES9 DC.B 'Address error ',0,0
|
801 |
|
|
MES10 DC.B 'Illegal instruction ',0,0
|
802 |
|
|
MES11 DC.B 'Breakpoint ',0,0
|
803 |
|
|
MES12 DC.B 'Trace ',0
|
804 |
|
|
REGNAME DC.B 'D0D1D2D3D4D5D6D7'
|
805 |
|
|
DC.B 'A0A1A2A3A4A5A6A7'
|
806 |
|
|
DC.B 'SSSR'
|
807 |
|
|
DC.B 'PC ',0
|
808 |
|
|
ERMES1 DC.B 'Non-valid hexadecimal input ',0
|
809 |
|
|
ERMES2 DC.B 'Invalid command ',0
|
810 |
|
|
ERMES3 DC.B 'Loading error',0
|
811 |
|
|
ERMES4 DC.B 'Table full ',0,0
|
812 |
|
|
ERMES5 DC.B 'Breakpoint not active ',0,0
|
813 |
|
|
ERMES6 DC.B 'Uninitialized exception ',0,0
|
814 |
|
|
ERMES7 DC.B ' Range error',0
|
815 |
|
|
*
|
816 |
|
|
* COMTAB is the built-in command table. All entries are made up of
|
817 |
|
|
* a string length + number of characters to match + the string
|
818 |
|
|
* plus the address of the command relative to COMTAB
|
819 |
|
|
*
|
820 |
|
|
DC.L 0 Force table to even address
|
821 |
|
|
COMTAB DC.B 4,4 JUMP <address> causes execution to
|
822 |
|
|
DC.B 'JUMP' begin at <address>
|
823 |
|
|
DC.L JUMP-COMTAB n
|
824 |
|
|
DC.B 6,3 MEMORY <address> examines contents of
|
825 |
|
|
DC.B 'MEMORY' <address> and allows them to be changed
|
826 |
|
|
DC.L MEMORY-COMTAB
|
827 |
|
|
DC.B 4,2 LOAD <string> loads S1/S2 records
|
828 |
|
|
DC.B 'LOAD' from the host. <string> is sent to host
|
829 |
|
|
DC.L LOAD-COMTAB
|
830 |
|
|
DC.B 4,2 DUMP <string> sends S1 records to the
|
831 |
|
|
DC.B 'DUMP' host and is preceeded by <string>.
|
832 |
|
|
DC.L DUMP-COMTAB
|
833 |
|
|
DC.B 4,2 NOBR <address> removes the breakpoint
|
834 |
|
|
DC.B 'NOBR' at <address> from the BP table. If
|
835 |
|
|
DC.L NOBR-COMTAB no address is given all BPs are removed.
|
836 |
|
|
DC.B 4,2 DISP displays the contents of the
|
837 |
|
|
DC.B 'DISP' pseudo registers in TSK_T.
|
838 |
|
|
DC.L EX_DIS-COMTAB
|
839 |
|
|
DC.B 4,2 GO <address> starts program execution
|
840 |
|
|
DC.B 'GO' at <address> and loads regs from TSK_T
|
841 |
|
|
DC.L GO-COMTAB
|
842 |
|
|
DC.B 2,2 BRGT puts a breakpoint in the BP
|
843 |
|
|
DC.B 'BRGT' table - but not in the code
|
844 |
|
|
DC.L BR_GET-COMTAB
|
845 |
|
|
DC.B 4,2 PLAN puts the breakpoints in the code
|
846 |
|
|
DC.B 'PLAN'
|
847 |
|
|
DC.L BR_SET-COMTAB
|
848 |
|
|
DC.B 4,4 KILL removes breakpoints from the code
|
849 |
|
|
DC.B 'KILL'
|
850 |
|
|
DC.L BR_CLR-COMTAB
|
851 |
|
|
DC.B 4,2 GB <address> sets breakpoints and
|
852 |
|
|
DC.B 'GB ' then calls GO.
|
853 |
|
|
DC.L GB-COMTAB
|
854 |
|
|
DC.B 4,3 REG <reg> <value> loads <value>
|
855 |
|
|
DC.B 'REG ' into <reg> in TASK_T. Used to preset
|
856 |
|
|
DC.L REG_MOD-COMTAB registers before a GO or GB
|
857 |
|
|
DC.B 0,0
|
858 |
|
|
*
|
859 |
|
|
END $1000
|
860 |
|
|
|
861 |
|
|
|
862 |
|
|
|
863 |
|
|
|
864 |
|
|
|
865 |
|
|
|
866 |
|
|
|
867 |
|
|
|