YARI bugfix: the shadow of a ld/st hazard wasn't flushed
[yari.git] / BeMicroSDK / tinymon.c
blob495f5bd48720dbe9daad1009b21fb3dc4b096df3
1 /*
2 This is a tiny program loader that takes it's input through the
3 serial port.
4 */
6 typedef void (*func_t)(void);
8 #if !defined(HOSTTEST)
10 asm(" .globl _start ");
11 asm("_init: ");
12 asm("_start: la $28,_gp ");
13 asm(" la $29,_gp+8192 ");/* + 8KiB */
14 asm(" jal main ");
15 asm(" nop ");
16 asm(" break ");
18 extern void set_leds(unsigned v);
19 asm(".globl set_leds;set_leds: mtlo $4;jr $31");
21 #define RS232IN_DATA (*(volatile unsigned *) 0xFF000004)
22 #define RS232IN_TAG (*(volatile unsigned *) 0xFF000008)
23 #define TSC (*(volatile unsigned *) 0xFF00000C)
24 #define SER_OUTBUSY() (*(volatile unsigned *)0xFF000000 != 0)
25 #define SER_OUT(data) (*(volatile unsigned *)0xFF000000 = (data))
27 #define BUF_SIZE 1024 // must be a power of two
29 unsigned last_serial_tag;
30 char serial_buffer[BUF_SIZE];
31 unsigned serial_buffer_wp;
32 unsigned serial_buffer_rp;
34 void init_serial(void)
36 last_serial_tag = RS232IN_TAG;
37 serial_buffer_rp = serial_buffer_wp = 1;
40 void check_serial_input(void)
42 unsigned char tag = RS232IN_TAG;
43 if (tag != last_serial_tag) {
44 serial_buffer[serial_buffer_wp++] = RS232IN_DATA;
45 serial_buffer_wp &= BUF_SIZE-1;
46 last_serial_tag = tag;
47 if (serial_buffer_wp == serial_buffer_rp) {
48 while (SER_OUTBUSY());
49 SER_OUT('<');
50 while (SER_OUTBUSY());
51 SER_OUT('#');
52 while (SER_OUTBUSY());
53 SER_OUT('>');
58 void serial_out(unsigned ch)
60 check_serial_input();
62 if (ch == '\n')
63 serial_out('\r');
65 check_serial_input();
67 while (SER_OUTBUSY()) {
68 set_leds(0);
69 check_serial_input();
72 SER_OUT(ch);
73 set_leds(ch);
76 unsigned char serial_in(void)
78 unsigned char tag, ch;
81 check_serial_input();
82 while (serial_buffer_wp == serial_buffer_rp);
84 ch = serial_buffer[serial_buffer_rp++];
85 serial_buffer_rp &= BUF_SIZE-1;
87 set_leds(ch);
89 return ch;
92 #define store4(addr, v) (*(volatile unsigned *)(addr) = (v))
93 #define load4(addr) (*(volatile unsigned *)(addr))
95 #else
97 void init_serial(void) { }
98 void serial_out(unsigned ch) { putchar(ch); }
99 unsigned char serial_in(void) {
100 int c = getchar();
101 if (c < 0)
102 exit(0);
105 unsigned memory[1024*1024/4];
106 #define store4(addr, v) (memory[(unsigned) (addr) / 4 & (1 << 18) - 1] = (v))
107 #define load4(addr) (memory[(unsigned) (addr) / 4 & (1 << 18) - 1])
109 #endif
111 unsigned char serial_in_lowercase(void)
113 unsigned char ch = serial_in();
115 if (ch == '\r')
116 ch = '\n';
118 if ('A' <= ch && ch <= 'Z')
119 ch = ch - 'A' + 'a';
121 return ch;
124 unsigned char c, chk;
125 unsigned in_error;
127 void print_hex2(unsigned char);
129 static int puts(const char *s)
131 while (*s)
132 serial_out(*s++);
134 return 0;
137 static inline void print_hex1(unsigned d)
139 serial_out(d + (d < 10 ? '0' : 'A' - 10));
142 void print_hex2(unsigned char v)
144 print_hex1((v >> 4) & 15);
145 print_hex1(v & 15);
148 void print_hex8(unsigned v)
150 int i;
152 for (i = 8; i; --i) {
153 print_hex1((v >> 28) & 0xF);
154 v <<= 4;
158 void print_dec(unsigned v)
160 if (v >= 10)
161 print_dec(v / 10);
162 serial_out((v % 10) + '0');
165 unsigned get_hexnum(void)
167 unsigned arg;
169 for (arg = 0;;) {
170 if ('0' <= c && c <= '9')
171 arg = (arg << 4) + c - '0';
172 else if ('a' <= c && c <= 'f')
173 arg = (arg << 4) + c - ('a' - 10);
174 else
175 break;
176 chk += c;
177 c = serial_in_lowercase();
180 return arg;
183 unsigned d85(unsigned v)
185 if (in_error)
186 goto fail;
188 unsigned char c;
190 c = serial_in();
191 while (c <= ' ');
193 if (c < '(' || '|' < c)
194 goto fail;
196 unsigned nv = v*85 + c - '(';
198 // Check for overflow
199 if (nv < v)
200 goto fail;
202 return nv;
204 fail:
205 in_error = 1;
206 return 0;
209 unsigned get_base85_word(void)
211 return d85(d85(d85(d85(d85(0)))));
214 #if defined(HOSTTEST)
215 void tinymon_encode_word_base85(unsigned w)
217 unsigned e = w % 85; w /= 85;
218 unsigned d = w % 85; w /= 85;
219 unsigned c = w % 85; w /= 85;
220 unsigned b = w % 85; w /= 85;
221 unsigned a = w % 85; w /= 85;
222 putchar(a + '(');
223 putchar(b + '(');
224 putchar(c + '(');
225 putchar(d + '(');
226 putchar(e + '(');
228 #endif
230 void help()
232 puts("Here we will tell about commands and "
233 "statistics (like available memory and frequency\n");
236 int main()
238 restart: ;
240 unsigned *addr = 0;
241 in_error = 0;
243 /* This is run out of the I$, which in practice means a ROM
244 * that cannot even be read. We must manually initialize all
245 * data and we can't use strings!
248 init_serial();
249 puts("\n\n");
252 * Very simple protocol
254 * <cmd> <hex8> ' ' <hex2> '\n'
256 * The <hex2> byte is the checksum of <cmd> + each byte of
257 * <hex8>. If a mismatch is detected all input is ignored
258 * until a clear command is seen.
260 * Commands
261 * C - clear the error state (arg ignored)
262 * L - set the load address
263 * W - write a word to the current load address and move it forwards
264 * R - read a word from the current load address and move it forwards
265 * E - execute starting at the given address
266 * X - receive a block of binary data in base85 encoding
269 for (;;) {
270 unsigned arg = 0;
271 unsigned i;
272 unsigned char cmd, chk_ext;
273 unsigned char error_code = ' ';
275 do {
276 puts("Tinymon 2010-11-10 (Use 'h' for help)\n");
279 c = serial_in_lowercase();
280 while (c == '\r' || c == ' ');
281 } while (c == '\n');
283 /* Skip cruft until a command is encountered. */
284 while (c != 'c' && c != 'l' && c != 'w' && c != 'r' && c != 'e' &&
285 c != 't' && c != 'x' && c != 'h')
286 c = serial_in_lowercase();
288 chk = cmd = c;
291 c = serial_in_lowercase();
292 while (c == ' ');
294 arg = get_hexnum();
296 while (c == ' ')
297 c = serial_in_lowercase();
299 if (c != '\n') {
300 unsigned char good_chk = chk;
301 // Non-interactive use
303 chk_ext = get_hexnum();
305 if (good_chk != chk_ext) {
306 serial_out('<');
307 print_hex2(good_chk);
308 serial_out('!');
309 serial_out('=');
310 print_hex2(chk_ext);
311 serial_out('>');
313 error_code = '1';
314 goto error;
317 while (c == ' ')
318 c = serial_in_lowercase();
320 if (c != '\n') {
321 error_code = '2';
322 goto error;
326 if (in_error && cmd != 'c' && cmd != 't')
327 continue;
329 if (cmd == 'h')
330 help();
331 else if (cmd == 'c')
332 in_error = 0;
333 else if (cmd == 'l')
334 addr = (unsigned *) arg;
335 #if 0
336 else if (cmd == 'w') {
337 store4(addr, arg);
338 if (load4(addr) != arg) {
339 serial_out('!');
340 goto error;
342 addr++;
344 #endif
345 else if (cmd == 'r') {
346 print_hex8(load4(addr++));
347 serial_out('\n');
349 else if (cmd == 'e') {
350 puts("\nExecute!\n");
351 #if defined(HOSTTEST)
352 printf("Execute from %08x\n", arg);
353 #else
354 ((func_t)arg)();
355 #endif
356 goto restart;
357 } else if (cmd == 'x') {
358 unsigned *end = addr + arg;
359 unsigned chk = 0;
360 unsigned k = 0;
362 serial_out('\n');
363 for (k = 1; addr != end; addr += 1, ++k) {
364 unsigned w = get_base85_word();
365 if (in_error) {
366 error_code = '8';
367 goto error;
369 chk += w;
370 store4(addr, w);
372 if (((unsigned) addr & (1 << 10) - 1) == 0)
373 serial_out('\r'), print_dec(100 * k / arg), serial_out('%');
375 serial_out('\r');
376 print_dec(100);
377 serial_out('%');
378 serial_out('\n');
380 k = get_base85_word();
381 if (k != -chk) {
382 #if defined(HOSTTEST)
383 printf("Got:");
384 tinymon_encode_word_base85(k);
385 printf("\nWanted:");
386 tinymon_encode_word_base85(-chk);
387 printf("\nRest: ");
388 while (~0 != (k = getchar()))
389 putchar(k);
390 #endif
391 error_code = '7';
392 goto error;
394 #if 0
395 } else if (cmd == 't') {
396 out4('Mem ');
397 out4('test');
398 serial_out('\n');
400 /* Simple memory tester */
401 for (addr = (unsigned *) 0x40000000;
402 addr != (unsigned *) 0x400E0000;
403 addr += 4) {
405 store4(addr, ((unsigned) addr >> 13) ^~ (unsigned) addr);
406 store4(addr + 1, ~ (unsigned) addr);
407 store4(addr + 2, 42 + (unsigned) addr);
408 store4(addr + 3, - (unsigned) addr);
411 for (addr = (unsigned *) 0x40000000;
412 addr != (unsigned *) 0x400E0000;
413 addr += 4) {
415 unsigned a, b, c, d;
416 a = ((unsigned) addr >> 13) ^~ (unsigned) addr;
417 b = ~ (unsigned) addr;
418 c = 42 + (unsigned) addr;
419 d = - (unsigned) addr;
421 if (a != load4(addr) ||
422 b != load4(addr + 1) ||
423 c != load4(addr + 2) ||
424 d != load4(addr + 3)) {
425 out4('Memo');
426 out4('ry e');
427 out4('rror');
428 out4(' at ');
429 print_hex8((unsigned) addr);
430 serial_out('\n');
431 goto restart;
434 out4('Ok!\n');
435 continue;
436 #endif
439 serial_out('.');
440 continue;
442 error:
443 serial_out('<');
444 serial_out(error_code);
445 serial_out('>');
446 in_error = 1;
447 while (c != '\n')
448 c = serial_in_lowercase();