blob: c7abde3d65aeab24153697cfad24c8a88d2d7a2d (
plain) (
blame)
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
|
# CONVENTION:
# return value for functions : in register A
# arguments for functions : registers A, B, C, D
# all registers are caller-saved, except SP which is preserved by function calls
.text
jal run_unit_tests
li A msghello
jal ser_out_msg
push Z
main_loop:
# Process serial input
jal check_input
jz A end_process_input
jal run_cmd
end_process_input:
# Process clock ticking
pop D
li B _clock
lw B 0(B)
add D D B
push D
jz B main_loop
li A msgtick
jal ser_out_msg
j main_loop
# PROCEDURE: run_cmd
# ROLE: execute and clear command stored in cmdline
# ARGUMENTS: none
run_cmd:
push RA
li A prompt
jal ser_out_msg
li A cmdline
jal ser_out_msg
li A endl
jal ser_out_msg
li A error
jal ser_out_msg
li A cmdline_used
sw Z 0(A)
pop RA
jr RA
# PROCEDURE: ser_out_msg
# ROLE: write null-terminated string to serial output
# ARGUMENTS: address of string in register A
ser_out_msg:
li C _output
ser_out_msg_loop:
lb B 0(A)
jz B ser_out_msg_ret
sb B 0(C)
incri A 1
j ser_out_msg_loop
ser_out_msg_ret:
jr RA
# PROCEDURE: check_input
# ROLE: check if an input byte is available. if it is, and is different from '\n' (10), add it to cmdline
# ARGUMENTS: none
# RETURN VALUE: 1 if read byte was '\n', 0 otherwise
# WARNING: no buffer overflow check.
check_input:
li A _input
lb A 0(A)
jz A check_input_ret
move B A
sei A A '\n'
jz A add_b_to_string
move B Z
add_b_to_string:
push A
li A cmdline
li D cmdline_used
lw C 0(D)
add A A C
sb B 0(A)
incri C 1
sw C 0(D)
pop A
jz A check_input
check_input_ret:
jr RA
# PROCEDURE: run_unit_tests
# ROLE: check that CPU features work correctly ; displays message to serial output
# ARGUMENTS: none
run_unit_tests:
push RA
li A testbegin
jal ser_out_msg
li A test0
jal ser_out_msg
jal unit_test_0
li A testfail
jz B t0fail
li A testok
t0fail:
jal ser_out_msg
li A test1
jal ser_out_msg
jal unit_test_1
li A testfail
jz B t1fail
li A testok
t1fail:
jal ser_out_msg
li A test2
jal ser_out_msg
jal unit_test_2
li A testfail
jz B t2fail
li A testok
t2fail:
jal ser_out_msg
li A test3
jal ser_out_msg
jal unit_test_3
li A testfail
jz B t2fail
li A testok
t3fail:
jal ser_out_msg
pop RA
jr RA
unit_test_0:
li B 1
li C 12
li D 44
add C C D
sei A C 56
and B B A
li C -7
li D 7
add C C D
se A C Z
and B B A
jr RA
unit_test_1:
li B 1
jr RA
unit_test_2:
li B 1
jr RA
unit_test_3:
li B 1
jr RA
# READ-ONLY PROGRAM DATA
msghello:
ascii "Hello, world!\n"
msgtick:
ascii " ..."
prompt:
ascii "\n$ "
endl:
ascii "\n"
error:
ascii "Sorry but I'm to stupid to understand that.\n"
testbegin:
ascii "Runing CPU unit tests...\n"
testok:
ascii "OK\n"
testfail:
ascii "FAIL\n"
test0:
ascii "Addition/substraction: "
test1:
ascii "Unsigned multiplication: "
test2:
ascii "Unsigned division: "
test3:
ascii "Signed division/multiplication: "
.data
# Space where command-line is buffered from serial input
cmdline:
byte 256
# Number of bytes used in the command-line buffer
cmdline_used:
word 1
|