1 |
; macro definitions: |
2 |
; e, e1, e2 are any '*' mode instrn. operands (eg. #3, label, !2, *0, @label) |
3 |
; they refer to an immediate value or a value at a memory location |
4 |
; addr is any mode 1 instrn. operand (eg. label, number) |
5 |
; x, Array, Ptr are any '+' mode instrn. operands (eg. label, !2, *0, @label) |
6 |
; they refer to a memory address |
7 |
; n is any +ve number (eg. 0, 2) |
8 |
; op is a PeANUt instruction |
9 |
|
10 |
macro Set1 (x, e) ; perform x = e |
11 |
load e ; (AC = <value referred by e>) |
12 |
store x ; (Memory[x] = AC) |
13 |
endmacro |
14 |
|
15 |
macro Set2 (x, e1, op, e2) ; perform x = e1 + e2 |
16 |
load e1 ; (AC = <value referred by e1>) |
17 |
op e2 ; (AC = AC op <value referred by e2>) |
18 |
store x ; (Memory[x] = AC) |
19 |
endmacro |
20 |
|
21 |
macro Comp (e1, e2) ; compare e1, e2 |
22 |
; (use for evaluating conditions in IF, WHILE, etc) |
23 |
load e1 ; (AC = <value referred by e1>) |
24 |
cmp e2 ; (PSW(10:13) set to compare AC with e2) |
25 |
endmacro |
26 |
|
27 |
macro Put (e) ; write value of e to terminal |
28 |
load e ; (AC = <value referred by e>) |
29 |
trap #3 ; (AC(0:7) written to standard output) |
30 |
endmacro |
31 |
|
32 |
macro Get (x) ; read next char from keyboard into x |
33 |
trap #2 ; (read next char from keyboard into AC) |
34 |
store x ; (Memory[x] = AC) |
35 |
endmacro |
36 |
|
37 |
macro Push (e) ; push value of e onto stack |
38 |
; (use before calling proc. with value parameters) |
39 |
load e ; (AC = <value referred by e>) |
40 |
incsp #1 ; (SP = SP + 1; done last in case e=!num) |
41 |
store !0 ; (Memory[SP] = AC) |
42 |
endmacro |
43 |
|
44 |
macro Pusha (Addr) ; push address of addr onto stack |
45 |
; (use before calling proc. with VAR/Array parameters) |
46 |
loada Addr ; (AC = Addr) |
47 |
incsp #1 ; (SP = SP + 1) |
48 |
store !0 ; (Memory[SP] = AC) |
49 |
endmacro |
50 |
|
51 |
macro Pop (n) ; pop n elements of the stack |
52 |
; (use at end of proc. call or end of proc body) |
53 |
incsp #-n ; (SP = SP - n) |
54 |
endmacro |
55 |
|
56 |
macro Call1 (Proc, e) ; call procedure Proc, having one value parameter |
57 |
Push (e) ; push e onto stack |
58 |
call Proc ; (call procedure Proc) |
59 |
Pop (1) ; (restore stack) |
60 |
endmacro |
61 |
|
62 |
macro Call2 (Proc, e1, e2); call procedure Proc, having 2 value parameters (e1,e2) |
63 |
; or a function Proc, with 1 value parameter (e2) |
64 |
; and stack is used for return value (e1=#0) |
65 |
load e1 ; (AC = <value referred by e1>) |
66 |
store !1 ; (Memory[SP+1] = AC) |
67 |
load e2 ; (AC = <value referred by e2>) |
68 |
store !2 ; (Memory[SP+2] = AC) |
69 |
incsp #2 ; (SP = SP + 2) |
70 |
call Proc ; (call procedure Proc) |
71 |
incsp #-2 ; (restore stack) |
72 |
endmacro |
73 |
|
74 |
macro SetXR (e) ; set XR to e |
75 |
load e ; (AC = <value referred by e>) |
76 |
storexr ; (XR = AC) |
77 |
endmacro |
78 |
|
79 |
; |
80 |
; |
81 |
; /* simplified version of some of Modula-2's |
82 |
; * InOut library for PeANUt |
83 |
; * |
84 |
; * Author: Peter Strazdins, DCS ANU |
85 |
; * Department of Computer Science, |
86 |
; * The Australian National University. |
87 |
; * |
88 |
; * Date written: July, 1991. |
89 |
; * Updated: June 1993 |
90 |
; * WriteInt(-32768,..) bug fixed |
91 |
; * Sep 94 |
92 |
; * Updated for C Apr 00 |
93 |
; */ |
94 |
; |
95 |
; #include <stdio.h> |
96 |
global Write ; /* these correspond to definition module |
97 |
global WriteInt ; * declarations; have almost identical |
98 |
global WriteString ; * behavior to the standard InUut module |
99 |
global ReadCard ; */ |
100 |
global WriteCard ; |
101 |
global Log10 ; |
102 |
; |
103 |
; /* Write(ch) = putchar(ch) */ |
104 |
ch = -1 ; void Write(char ch) { |
105 |
Write: ; |
106 |
load !ch ; putchar(ch); |
107 |
trap #3 ; |
108 |
ret ; } /*Write() */ |
109 |
; |
110 |
; /* WriteInt(x,4) = printf("%4d",x) */ |
111 |
x = -4 ; void WriteInt(short int x, |
112 |
n = -3 ; short unsigned int n) { |
113 |
MinInt: data -32768 ; short const int MinInt = -32768; |
114 |
; short int |
115 |
NSp = -1 ; NSp, /* # of ' ' to print */ |
116 |
aX = 0 ; aX; /* = |x| */ |
117 |
NumLocs = 2 ; /* number of local vars. = 2 */ |
118 |
WriteInt: ; |
119 |
incsp #NumLocs ; /* allocate stack space for local vars. */ |
120 |
Set2 (!NSp, !n, sub, #1); NSp = n - 1; |
121 |
Set1 (!aX, !x) ; aX = x; |
122 |
Comp (!x, MinInt) ; if (x == MinInt) { |
123 |
bne WIend1 ; /* avoid integer overflow */ |
124 |
Set2 (!aX, !aX, dvd, #10); aX = aX / 10; |
125 |
Set2 (!NSp, !NSp, sub, #1); NSp = NSp - 1; |
126 |
WIend1: ; } /*if*/ |
127 |
Comp (#0, !x) ; if (0 > x) { /* ie. x < 0 */ |
128 |
ble WIend2 ; |
129 |
Set2 (!aX, #0, sub, !aX); aX = 0 - aX; |
130 |
Set2 (!NSp, !NSp, sub, #1); NSp = NSp - 1; /* will write '-' */ |
131 |
WIend2: ; } /*if*/ |
132 |
Comp (#0, !aX) ; if (aX != 0) { |
133 |
beq WIend3 ; |
134 |
Call2 (Log10, #0, !aX); NSp = NSp - Log10(aX); |
135 |
Set2 (!NSp, !NSp, sub, !1); |
136 |
WIend3: ; } /*if*/ |
137 |
; |
138 |
WIwhile:Comp (!NSp, #0) ; while (NSp > 0) { |
139 |
ble WIendwh ; |
140 |
Set2 (!NSp, !NSp, sub, #1); NSp = NSp - 1; |
141 |
Put (#' ') ; putchar(' '); |
142 |
jmp WIwhile ; } /*while*/ |
143 |
WIendwh: ; |
144 |
Comp (#0, !x) ; if (0 > x) { /* ie. x < 0 */ |
145 |
ble WIend4 ; |
146 |
Put (#'-') ; putchar('-'); |
147 |
WIend4: ; } /*IF*/ |
148 |
Call1 (WriteCard, !aX); WriteCard(aX); |
149 |
Comp (!x, MinInt) ; if (x == MinInt) { |
150 |
bne WIend5 ; |
151 |
load !aX ; putchar((ax |
152 |
mul #-10 ; % 10 ) + |
153 |
sub !x ; |
154 |
add #'0' ; '0'); |
155 |
trap #3 ; |
156 |
WIend5: ; } /*if*/ |
157 |
incsp #-NumLocs ; } /*WriteInt()*/ /*take local vars off stack*/ |
158 |
ret ; |
159 |
; |
160 |
; /* Log10(x) = log to base 10 of x */ |
161 |
x = -2 ; short unsigned Log10( short unsigned int x){ |
162 |
RV = -3 ; /* return value via stack */ |
163 |
; |
164 |
Logx = 0; ; short unsigned int Logx; |
165 |
NumLocs = 1 ; /* number of local vars. = 1 */ |
166 |
Log10: ; |
167 |
incsp #NumLocs ; /* allocate stack space for local vars. */ |
168 |
Comp (!x, #0) ; if (x != 0) { |
169 |
beq Lelse ; |
170 |
Set1 (!Logx, #0) ; Logx = 0; |
171 |
Set2 (!x, !x, dvd, #10); x = x / 10; |
172 |
Lwhile: Comp (!x, #0) ; while (x != 0) { |
173 |
beq Lendwh ; |
174 |
Set2 (!Logx, !Logx, add, #1); Logx = Logx + 1; |
175 |
Set2 (!x, !x, dvd, #10); x = x / 10; |
176 |
jmp Lwhile ; } /*while*/ |
177 |
Lendwh: ; |
178 |
jmp Lendif ; } else { |
179 |
Lelse: ; |
180 |
Set1 (!Logx, #-1) ; Logx = -1; /* illegal value for 0*/ |
181 |
Lendif: ; } /*if*/ |
182 |
Set1 (!RV, !Logx) ; return Logx; |
183 |
incsp #-NumLocs ; } /*Log10()*/ /*take local vars off stack*/ |
184 |
load #-1 ; /* break callers using AC to get RV */ |
185 |
ret ; |
186 |
; |
187 |
;/* The procedure WriteCard converts its single cardinal parameter into its |
188 |
; * decimal representation, and outputs the resulting sequence of characters to |
189 |
; * the standard output. |
190 |
; |
191 |
; * This procedure first divides its parameter into two parts: the quotient and |
192 |
; * remainder after division by 10. This separates the leading digits, if any, |
193 |
; * from the last digit. For example, it divides the number 7623 into a leading |
194 |
; * part, 762, and its last digit, 3. If the leading part is non-zero, it calls |
195 |
; * itself (recursively) to write out that leading part. After the leading part |
196 |
; * (if any) has been output, we convert the last digit into an ascii character, |
197 |
; * and write that character to the standard output. |
198 |
; */ |
199 |
; /* WriteCard(x) = printf("%d", x) */ |
200 |
; void WriteCard( |
201 |
val = -4 ; short unsigned int val) { |
202 |
; short unsigned int |
203 |
quot = -2 ; quot, |
204 |
rem = -1 ; rem, |
205 |
temp = 0 ; temp; |
206 |
NumLocs = 3 ; /* number of local vars. = 3 */ |
207 |
WriteCard: ; |
208 |
incsp #NumLocs ; /* allocate stack space for local vars. */ |
209 |
Set2 (!quot, !val, dvd, #10); |
210 |
; quot = val / 10; |
211 |
Set2 (!temp, !quot, mul, #10); |
212 |
; temp = quot * 10; |
213 |
Set2 (!rem, !val, sub,!temp); |
214 |
; rem = val - temp; |
215 |
Comp (!quot, #0) ; if (quot != 0) { |
216 |
beq WCendif ; |
217 |
Call1 (WriteCard, !quot); WriteCard(quot); |
218 |
WCendif: ; } /*if*/; |
219 |
load !rem ; putchar(rem + '0'); |
220 |
add #'0' ; |
221 |
trap #3 ; |
222 |
incsp #-NumLocs ; } /*WriteCard()*/ /*take local off stack */ |
223 |
ret ; |
224 |
; /* WriteString(s) = printf("%s", s) */ |
225 |
; void WriteString( |
226 |
str = -2 ; char str[]) { |
227 |
; |
228 |
i = 0 ; short unsigned int i; |
229 |
NumLocs = 1 ; /* number of local vars. = 1 */ |
230 |
WriteString: ; |
231 |
incsp #NumLocs ; /* allocate stack space for local vars. */ |
232 |
Set1 (!i,#0) ; i = 0; |
233 |
WSwhile:load !str ; while (str[i] != 0) { |
234 |
add !i ; /* null char is last elt. of string */ |
235 |
storexr ; /* XR = address of str[i] */ |
236 |
Comp (*0, #0) ; |
237 |
beq WSendwh ; |
238 |
Put (*0) ; putchar( str[i] ); |
239 |
; |
240 |
Set2 (!i, !i, add, #1); i = i + 1; |
241 |
jmp WSwhile ; } /*while*/ |
242 |
WSendwh: ; |
243 |
incsp #-NumLocs ; } /*WriteString()*//*take locals off stack*/ |
244 |
ret ; |
245 |
; |
246 |
; /* ReadCard(&n) = scanf("%d", &n) */ |
247 |
; void ReadCard( |
248 |
n = -3 ; short unsigned int *n) { |
249 |
ch = -1 ; char ch: CHAR; |
250 |
n0 = 0 ; short unsigned int n0; |
251 |
NumLocs = 2 ; /* number of local vars. = 2 */ |
252 |
ReadCard: ; |
253 |
incsp #NumLocs ; /* allocate stack space for local vars. */ |
254 |
RCrepeat: ; do |
255 |
Get (!ch) ; ch = getchar(); |
256 |
Comp (#'0', !ch) ; while (('0' > ch) |
257 |
bgt RCrepeat ; |
258 |
Comp (!ch, #'9') ; && (ch > '9')); |
259 |
bgt RCrepeat ; |
260 |
Set1 (!n0, #0) ; n0 = 0; |
261 |
RCwhile:Comp (#'0', !ch) ; while (('0'<= ch) |
262 |
bgt RCendwh ; |
263 |
Comp (!ch, #'9') ; && (ch <= '9')) { |
264 |
bgt RCendwh ; |
265 |
Set2 (!ch, !ch, sub, #'0');ch = ch - '0'; |
266 |
; |
267 |
load !n0 ; n0 = n0 * 10 + ch; |
268 |
mul #10 ; |
269 |
add !ch ; |
270 |
store !n0 ; |
271 |
Get (!ch) ; ch = getchar(); |
272 |
jmp RCwhile2 ; } /*while*/ |
273 |
RCendwh: ; |
274 |
SetXR (!n); ; n = n0; /* XR = address of n*/ |
275 |
Set1 (*0, !n0) ; |
276 |
incsp #-NumLocs ; } /*ReadCard()*//*take local vars off stack*/ |
277 |
load #-1 ; /* break callers using AC to get value*/ |
278 |
ret ; |