1 /*
2 * This file is part of x48, an emulator of the HP-48sx Calculator.
3 * Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 /* $Log: actions.c,v $
21 * Revision 1.15 1995/01/11 18:20:01 ecd
22 * major update to support HP48 G/GX
23 *
24 * Revision 1.14 1994/12/07 20:20:50 ecd
25 * changed shutdown again: wake on TIMER1CTRL & XTRA
26 *
27 * Revision 1.14 1994/12/07 20:20:50 ecd
28 * changed shutdown again: wake on TIMER1CTRL & XTRA
29 *
30 * Revision 1.13 1994/11/28 02:00:51 ecd
31 * changed do_configure for internal debugging
32 *
33 * Revision 1.12 1994/11/02 14:40:38 ecd
34 * removed call to debug in do_shutdown()
35 *
36 * Revision 1.11 1994/10/09 20:29:47 ecd
37 * no real change, was just fiddling around with the display.
38 *
39 * Revision 1.10 1994/10/06 16:30:05 ecd
40 * added refresh_display()
41 *
42 * Revision 1.9 1994/10/05 08:36:44 ecd
43 * changed shutdown
44 *
45 * Revision 1.8 1994/10/01 10:12:53 ecd
46 * fixed bug in shutdown
47 *
48 * Revision 1.7 1994/09/30 12:37:09 ecd
49 * changed shutdown instruction
50 *
51 * Revision 1.6 1994/09/18 22:47:20 ecd
52 * fixed bug with overflow in timerdiff
53 *
54 * Revision 1.5 1994/09/18 15:29:22 ecd
55 * added SHUTDN implementation,
56 * started Real Time support.
57 *
58 * Revision 1.4 1994/09/13 16:57:00 ecd
59 * changed to plain X11
60 *
61 * Revision 1.3 1994/08/31 18:23:21 ecd
62 * changed memory read routines.
63 *
64 * Revision 1.2 1994/08/27 11:28:59 ecd
65 * changed keyboard interrupt handling.
66 *
67 * Revision 1.1 1994/08/26 11:09:02 ecd
68 * Initial revision
69 *
70 *
71 * $Id: actions.c,v 1.15 1995/01/11 18:20:01 ecd Exp ecd $
72 */
73
74 /* #define DEBUG_INTERRUPT 1 */
75 /* #define DEBUG_KBD_INT 1 */
76 /* #define DEBUG_SHUTDOWN 1 */
77 /* #define DEBUG_CONFIG 1 */
78 /* #define DEBUG_ID 1 */
79
80 #include "global.h"
81
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <unistd.h>
85
86 #include "hp48.h"
87 #include "hp48_emu.h"
88 #include "device.h"
89 #include "x48_x11.h"
90 #include "timer.h"
91 #include "debugger.h"
92 #include "romio.h"
93
94 static int interrupt_called = 0;
95 extern long nibble_masks[16];
96
97 int got_alarm;
98
99 int conf_bank1 = 0x00000;
100 int conf_bank2 = 0x00000;
101
102 void
103 #ifdef __FunctionProto__
do_in(void)104 do_in(void)
105 #else
106 do_in()
107 #endif
108 {
109 int i, in, out;
110
111 out = 0;
112 for (i = 2; i >= 0; i--) {
113 out <<= 4;
114 out |= saturn.OUT[i];
115 }
116 in = 0;
117 for (i = 0; i < 9; i++)
118 if (out & (1 << i))
119 in |= saturn.keybuf.rows[i];
120 #ifdef DEBUG_INOUT
121 fprintf(stderr, "saturn.OUT=%.3x, saturn.IN=%.4x\n", out, in);
122 #endif
123
124 for (i = 0; i < 4; i++) {
125 saturn.IN[i] = in & 0xf;
126 in >>= 4;
127 }
128 }
129
130 void
131 #ifdef __FunctionProto__
clear_program_stat(int n)132 clear_program_stat(int n)
133 #else
134 clear_program_stat(n)
135 int n;
136 #endif
137 {
138 saturn.PSTAT[n] = 0;
139 }
140
141 void
142 #ifdef __FunctionProto__
set_program_stat(int n)143 set_program_stat(int n)
144 #else
145 set_program_stat(n)
146 int n;
147 #endif
148 {
149 saturn.PSTAT[n] = 1;
150 }
151
152 int
153 #ifdef __FunctionProto__
get_program_stat(int n)154 get_program_stat(int n)
155 #else
156 get_program_stat(n)
157 int n;
158 #endif
159 {
160 return saturn.PSTAT[n];
161 }
162
163 void
164 #ifdef __FunctionProto__
register_to_status(unsigned char * r)165 register_to_status(unsigned char *r)
166 #else
167 register_to_status(r)
168 unsigned char *r;
169 #endif
170 {
171 int i;
172
173 for (i = 0; i < 12; i++) {
174 saturn.PSTAT[i] = (r[i / 4] >> (i % 4)) & 1;
175 }
176 }
177
178 void
179 #ifdef __FunctionProto__
status_to_register(unsigned char * r)180 status_to_register(unsigned char *r)
181 #else
182 status_to_register(r)
183 unsigned char *r;
184 #endif
185 {
186 int i;
187
188 for (i = 0; i < 12; i++) {
189 if (saturn.PSTAT[i]) {
190 r[i / 4] |= 1 << (i % 4);
191 } else {
192 r[i / 4] &= ~(1 << (i % 4)) & 0xf;
193 }
194 }
195 }
196
197 void
198 #ifdef __FunctionProto__
swap_register_status(unsigned char * r)199 swap_register_status(unsigned char *r)
200 #else
201 swap_register_status(r)
202 unsigned char *r;
203 #endif
204 {
205 int i, tmp;
206
207 for (i = 0; i < 12; i++) {
208 tmp = saturn.PSTAT[i];
209 saturn.PSTAT[i] = (r[i / 4] >> (i % 4)) & 1;
210 if (tmp) {
211 r[i / 4] |= 1 << (i % 4);
212 } else {
213 r[i / 4] &= ~(1 << (i % 4)) & 0xf;
214 }
215 }
216 }
217
218 void
219 #ifdef __FunctionProto__
clear_status(void)220 clear_status(void)
221 #else
222 clear_status()
223 #endif
224 {
225 int i;
226
227 for (i = 0; i < 12; i++) {
228 saturn.PSTAT[i] = 0;
229 }
230 }
231
232 void
233 #ifdef __FunctionProto__
set_register_nibble(unsigned char * reg,int n,unsigned char val)234 set_register_nibble(unsigned char *reg, int n, unsigned char val)
235 #else
236 set_register_nibble(reg, n, val)
237 unsigned char *reg;
238 int n;
239 unsigned char val;
240 #endif
241 {
242 reg[n] = val;
243 }
244
245 unsigned char
246 #ifdef __FunctionProto__
get_register_nibble(unsigned char * reg,int n)247 get_register_nibble(unsigned char *reg, int n)
248 #else
249 get_register_nibble(reg, n)
250 unsigned char *reg;
251 int n;
252 #endif
253 {
254 return reg[n];
255 }
256
257 void
258 #ifdef __FunctionProto__
set_register_bit(unsigned char * reg,int n)259 set_register_bit(unsigned char *reg, int n)
260 #else
261 set_register_bit(reg, n)
262 unsigned char *reg;
263 int n;
264 #endif
265 {
266 reg[n/4] |= (1 << (n%4));
267 }
268
269 void
270 #ifdef __FunctionProto__
clear_register_bit(unsigned char * reg,int n)271 clear_register_bit(unsigned char *reg, int n)
272 #else
273 clear_register_bit(reg, n)
274 unsigned char *reg;
275 int n;
276 #endif
277 {
278 reg[n/4] &= ~(1 << (n%4));
279 }
280
281 int
282 #ifdef __FunctionProto__
get_register_bit(unsigned char * reg,int n)283 get_register_bit(unsigned char *reg, int n)
284 #else
285 get_register_bit(reg, n)
286 unsigned char *reg;
287 int n;
288 #endif
289 {
290 return ((int)(reg[n/4] & (1 << (n%4))) > 0)?1:0;
291 }
292
293 short conf_tab_sx[] = { 1, 2, 2, 2, 2, 0 };
294 short conf_tab_gx[] = { 1, 2, 2, 2, 2, 0 };
295
296 void
297 #ifdef __FunctionProto__
do_reset(void)298 do_reset(void)
299 #else
300 do_reset()
301 #endif
302 {
303 int i;
304
305 for (i = 0; i < 6; i++)
306 {
307 if (opt_gx)
308 saturn.mem_cntl[i].unconfigured = conf_tab_gx[i];
309 else
310 saturn.mem_cntl[i].unconfigured = conf_tab_sx[i];
311 saturn.mem_cntl[i].config[0] = 0x0;
312 saturn.mem_cntl[i].config[1] = 0x0;
313 }
314
315 #ifdef DEBUG_CONFIG
316 fprintf(stderr, "%.5lx: RESET\n", saturn.PC);
317 for (i = 0; i < 6; i++)
318 {
319 if (saturn.mem_cntl[i].unconfigured)
320 fprintf(stderr, "MEMORY CONTROLLER %d is unconfigured\n", i);
321 else
322 fprintf(stderr, "MEMORY CONTROLLER %d is configured to %.5lx, %.5lx\n",
323 i, saturn.mem_cntl[i].config[0], saturn.mem_cntl[i].config[1]);
324 }
325 #endif
326 }
327
328 void
329 #ifdef __FunctionProto__
do_inton(void)330 do_inton(void)
331 #else
332 do_inton()
333 #endif
334 {
335 saturn.kbd_ien = 1;
336 }
337
338 void
339 #ifdef __FunctionProto__
do_intoff(void)340 do_intoff(void)
341 #else
342 do_intoff()
343 #endif
344 {
345 saturn.kbd_ien = 0;
346 }
347
348 void
349 #ifdef __FunctionProto__
do_return_interupt(void)350 do_return_interupt(void)
351 #else
352 do_return_interupt()
353 #endif
354 {
355 if (saturn.int_pending) {
356 #ifdef DEBUG_INTERRUPT
357 fprintf(stderr, "PC = %.5lx: RTI SERVICE PENDING INTERRUPT\n",
358 saturn.PC);
359 #endif
360 saturn.int_pending = 0;
361 saturn.intenable = 0;
362 saturn.PC = 0xf;
363 } else {
364 #ifdef DEBUG_INTERRUPT
365 fprintf(stderr, "PC = %.5lx: RETURN INTERRUPT to ", saturn.PC);
366 #endif
367 saturn.PC = pop_return_addr();
368 #ifdef DEBUG_INTERRUPT
369 fprintf(stderr, "%.5lx\n", saturn.PC);
370 #endif
371 saturn.intenable = 1;
372
373 if (adj_time_pending) {
374 schedule_event = 0;
375 sched_adjtime = 0;
376 }
377
378 }
379 }
380
381 void
382 #ifdef __FunctionProto__
do_interupt(void)383 do_interupt(void)
384 #else
385 do_interupt()
386 #endif
387 {
388 interrupt_called = 1;
389 if (saturn.intenable) {
390 #ifdef DEBUG_INTERRUPT
391 fprintf(stderr, "PC = %.5lx: INTERRUPT\n", saturn.PC);
392 #endif
393 push_return_addr(saturn.PC);
394 saturn.PC = 0xf;
395 saturn.intenable = 0;
396 }
397 }
398
399 void
400 #ifdef __FunctionProto__
do_kbd_int(void)401 do_kbd_int(void)
402 #else
403 do_kbd_int()
404 #endif
405 {
406 interrupt_called = 1;
407 if (saturn.intenable) {
408 #ifdef DEBUG_KBD_INT
409 fprintf(stderr, "PC = %.5lx: KBD INT\n", saturn.PC);
410 #endif
411 push_return_addr(saturn.PC);
412 saturn.PC = 0xf;
413 saturn.intenable = 0;
414 } else {
415 #ifdef DEBUG_KBD_INT
416 fprintf(stderr, "PC = %.5lx: KBD INT PENDING\n", saturn.PC);
417 #endif
418 saturn.int_pending = 1;
419 }
420 }
421
422 void
423 #ifdef __FunctionProto__
do_reset_interrupt_system(void)424 do_reset_interrupt_system(void)
425 #else
426 do_reset_interrupt_system()
427 #endif
428 {
429 int i, gen_intr;
430
431 saturn.kbd_ien = 1;
432 gen_intr = 0;
433 for (i = 0; i < 9; i++) {
434 if (saturn.keybuf.rows[i] != 0) {
435 gen_intr = 1;
436 break;
437 }
438 }
439 if (gen_intr) {
440 do_kbd_int();
441 }
442 }
443
444 void
445 #ifdef __FunctionProto__
do_unconfigure(void)446 do_unconfigure(void)
447 #else
448 do_unconfigure()
449 #endif
450 {
451 int i;
452 unsigned int conf;
453
454 conf = 0;
455 for (i = 4; i >= 0; i--) {
456 conf <<= 4;
457 conf |= saturn.C[i];
458 }
459
460 for (i = 0; i < 6; i++)
461 {
462 if (saturn.mem_cntl[i].config[0] == conf)
463 {
464 if (opt_gx)
465 saturn.mem_cntl[i].unconfigured = conf_tab_gx[i];
466 else
467 saturn.mem_cntl[i].unconfigured = conf_tab_sx[i];
468 saturn.mem_cntl[i].config[0] = 0x0;
469 saturn.mem_cntl[i].config[1] = 0x0;
470 break;
471 }
472 }
473
474 #ifdef DEBUG_CONFIG
475 fprintf(stderr, "%.5lx: UNCNFG %.5x:\n", saturn.PC, conf);
476 for (i = 0; i < 6; i++)
477 {
478 if (saturn.mem_cntl[i].unconfigured)
479 fprintf(stderr, "MEMORY CONTROLLER %d is unconfigured\n", i);
480 else
481 fprintf(stderr, "MEMORY CONTROLLER %d is configured to %.5lx, %.5lx\n",
482 i, saturn.mem_cntl[i].config[0], saturn.mem_cntl[i].config[1]);
483 }
484 #endif
485 }
486
487 void
488 #ifdef __FunctionProto__
do_configure(void)489 do_configure(void)
490 #else
491 do_configure()
492 #endif
493 {
494 int i;
495 unsigned long conf;
496
497 conf = 0;
498 for (i = 4; i >= 0; i--) {
499 conf <<= 4;
500 conf |= saturn.C[i];
501 }
502
503 for (i = 0; i < 6; i++)
504 {
505 if (saturn.mem_cntl[i].unconfigured)
506 {
507 saturn.mem_cntl[i].unconfigured--;
508 saturn.mem_cntl[i].config[saturn.mem_cntl[i].unconfigured] = conf;
509 break;
510 }
511 }
512
513 #ifdef DEBUG_CONFIG
514 fprintf(stderr, "%.5lx: CONFIG %.5lx:\n", saturn.PC, conf);
515 for (i = 0; i < 6; i++)
516 {
517 if (saturn.mem_cntl[i].unconfigured)
518 fprintf(stderr, "MEMORY CONTROLLER %d is unconfigured\n", i);
519 else
520 fprintf(stderr, "MEMORY CONTROLLER %d at %.5lx, %.5lx\n",
521 i, saturn.mem_cntl[i].config[0], saturn.mem_cntl[i].config[1]);
522 }
523 #endif
524 }
525
526 int
527 #ifdef __FunctionProto__
get_identification(void)528 get_identification(void)
529 #else
530 get_identification()
531 #endif
532 {
533 int i;
534 static int chip_id[]
535 = { 0, 0, 0, 0, 0x05, 0xf6, 0x07, 0xf8, 0x01, 0xf2, 0, 0 };
536 int id;
537
538 for (i = 0; i < 6; i++)
539 {
540 if (saturn.mem_cntl[i].unconfigured)
541 break;
542 }
543 if (i < 6)
544 id = chip_id[2 * i + (2 - saturn.mem_cntl[i].unconfigured)];
545 else
546 id = 0;
547
548 #ifdef DEBUG_ID
549 fprintf(stderr, "%.5lx: C=ID, returning: %x\n", saturn.PC, id);
550 for (i = 0; i < 6; i++)
551 {
552 if (saturn.mem_cntl[i].unconfigured == 2)
553 fprintf(stderr, "MEMORY CONTROLLER %d is unconfigured\n", i);
554 else if (saturn.mem_cntl[i].unconfigured == 1)
555 {
556 if (i == 0)
557 fprintf(stderr, "MEMORY CONTROLLER %d unconfigured\n", i);
558 else
559 fprintf(stderr, "MEMORY CONTROLLER %d configured to ????? %.5lx\n",
560 i, saturn.mem_cntl[i].config[1]);
561 }
562 else
563 fprintf(stderr, "MEMORY CONTROLLER %d configured to %.5lx, %.5lx\n",
564 i, saturn.mem_cntl[i].config[0], saturn.mem_cntl[i].config[1]);
565 }
566 #endif
567
568 for (i = 0; i < 3; i++)
569 {
570 saturn.C[i] = id & 0x0f;
571 id >>= 4;
572 }
573 return 0;
574 }
575
576 void
577 #ifdef __FunctionProto__
do_shutdown(void)578 do_shutdown(void)
579 #else
580 do_shutdown()
581 #endif
582 {
583 int wake, alarms;
584 t1_t2_ticks ticks;
585
586 if (device.display_touched) {
587 device.display_touched = 0;
588 update_display();
589 #ifdef HAVE_XSHM
590 if (disp.display_update) refresh_display();
591 #endif
592 }
593
594 stop_timer(RUN_TIMER);
595 start_timer(IDLE_TIMER);
596
597 if (is_zero_register(saturn.OUT, OUT_FIELD)) {
598 #ifdef DEBUG_SHUTDOWN
599 fprintf(stderr, "%.5lx: SHUTDN: PC = 0\n", saturn.PC);
600 #endif
601 saturn.intenable = 1;
602 saturn.int_pending = 0;
603 }
604
605 #ifdef DEBUG_SHUTDOWN
606 fprintf(stderr, "%.5lx:\tSHUTDN: Timer 1 Control = %x, Timer 1 = %d\n",
607 saturn.PC, saturn.t1_ctrl, saturn.timer1);
608 fprintf(stderr, "%.5lx:\tSHUTDN: Timer 2 Control = %x, Timer 2 = %ld\n",
609 saturn.PC, saturn.t2_ctrl, saturn.timer2);
610 #endif
611
612 if (in_debugger)
613 wake = 1;
614 else
615 wake = 0;
616
617 alarms = 0;
618
619 do {
620
621 pause();
622
623 if (got_alarm) {
624 got_alarm = 0;
625
626 #ifdef HAVE_XSHM
627 if (disp.display_update) refresh_display();
628 #endif
629
630 ticks = get_t1_t2();
631 if (saturn.t2_ctrl & 0x01) {
632 saturn.timer2 = ticks.t2_ticks;
633 }
634 saturn.timer1 = set_t1 - ticks.t1_ticks;
635 set_t1 = ticks.t1_ticks;
636
637 interrupt_called = 0;
638 if (GetEvent()) {
639 if (interrupt_called)
640 wake = 1;
641 }
642
643 if (saturn.timer2 <= 0)
644 {
645 if (saturn.t2_ctrl & 0x04)
646 {
647 wake = 1;
648 }
649 if (saturn.t2_ctrl & 0x02)
650 {
651 wake = 1;
652 saturn.t2_ctrl |= 0x08;
653 do_interupt();
654 }
655 }
656
657 if (saturn.timer1 <= 0)
658 {
659 saturn.timer1 &= 0x0f;
660 if (saturn.t1_ctrl & 0x04)
661 {
662 wake = 1;
663 }
664 if (saturn.t1_ctrl & 0x03)
665 {
666 wake = 1;
667 saturn.t1_ctrl |= 0x08;
668 do_interupt();
669 }
670 }
671
672 if (wake == 0) {
673 interrupt_called = 0;
674 receive_char();
675 if (interrupt_called)
676 wake = 1;
677 }
678
679 alarms++;
680 }
681
682 if (enter_debugger)
683 {
684 wake = 1;
685 }
686 } while (wake == 0);
687
688 stop_timer(IDLE_TIMER);
689 start_timer(RUN_TIMER);
690 }
691
692 void
693 #ifdef __FunctionProto__
set_hardware_stat(int op)694 set_hardware_stat(int op)
695 #else
696 set_hardware_stat(op)
697 int op;
698 #endif
699 {
700 if (op & 1) saturn.XM = 1;
701 if (op & 2) saturn.SB = 1;
702 if (op & 4) saturn.SR = 1;
703 if (op & 8) saturn.MP = 1;
704 }
705
706 void
707 #ifdef __FunctionProto__
clear_hardware_stat(int op)708 clear_hardware_stat(int op)
709 #else
710 clear_hardware_stat(op)
711 int op;
712 #endif
713 {
714 if (op & 1) saturn.XM = 0;
715 if (op & 2) saturn.SB = 0;
716 if (op & 4) saturn.SR = 0;
717 if (op & 8) saturn.MP = 0;
718 }
719
720 int
721 #ifdef __FunctionProto__
is_zero_hardware_stat(int op)722 is_zero_hardware_stat(int op)
723 #else
724 is_zero_hardware_stat(op)
725 int op;
726 #endif
727 {
728 if (op & 1) if (saturn.XM != 0) return 0;
729 if (op & 2) if (saturn.SB != 0) return 0;
730 if (op & 4) if (saturn.SR != 0) return 0;
731 if (op & 8) if (saturn.MP != 0) return 0;
732 return 1;
733 }
734
735 void
736 #ifdef __FunctionProto__
push_return_addr(long addr)737 push_return_addr(long addr)
738 #else
739 push_return_addr(addr)
740 long addr;
741 #endif
742 {
743 int i;
744
745 if (++saturn.rstkp >= NR_RSTK) {
746 #if 0
747 fprintf(stderr, "%.5lx: RSTK overflow !!!\n", saturn.PC);
748 for (i = saturn.rstkp - 1; i >= 0; i--) {
749 fprintf(stderr, "\tRSTK[%d] %.5lx\n", i, saturn.rstk[i]);
750 }
751 #endif
752 for (i = 1; i < NR_RSTK; i++)
753 saturn.rstk[i-1] = saturn.rstk[i];
754 saturn.rstkp--;
755 }
756 saturn.rstk[saturn.rstkp] = addr;
757 #ifdef DEBUG_RSTK
758 fprintf(stderr, "PUSH %.5x:\n", addr);
759 for (i = saturn.rstkp; i >= 0; i--) {
760 fprintf(stderr, "RSTK[%d] %.5x\n", i, saturn.rstk[i]);
761 }
762 #endif
763 }
764
765 long
766 #ifdef __FunctionProto__
pop_return_addr(void)767 pop_return_addr(void)
768 #else
769 pop_return_addr()
770 #endif
771 {
772 #ifdef DEBUG_RSTK
773 int i;
774
775 for (i = saturn.rstkp; i >= 0; i--) {
776 fprintf(stderr, "RSTK[%d] %.5x\n", i, saturn.rstk[i]);
777 }
778 fprintf(stderr, "POP %.5x:\n",
779 (saturn.rstkp >= 0) ? saturn.rstk[saturn.rstkp]:0);
780 #endif
781 if (saturn.rstkp < 0)
782 return 0;
783 return saturn.rstk[saturn.rstkp--];
784 }
785
786 char *
787 #ifdef __FunctionProto__
make_hexstr(long addr,int n)788 make_hexstr(long addr, int n)
789 #else
790 make_hexstr(addr, n)
791 long addr;
792 int n;
793 #endif
794 {
795 static char str[44];
796 int i, t, trunc;
797
798 trunc = 0;
799 if (n > 40) {
800 n = 40;
801 trunc = 1;
802 }
803 for (i = 0; i < n; i++) {
804 t = read_nibble(addr+i);
805 if (t <= 9)
806 str[i] = '0' + t;
807 else
808 str[i] = 'a' + (t - 10);
809 }
810 str[n] = '\0';
811 if (trunc) {
812 str[n] = '.';
813 str[n+1] = '.';
814 str[n+2] = '.';
815 str[n+3] = '\0';
816 }
817 return str;
818 }
819
820 void
821 #ifdef __FunctionProto__
load_constant(unsigned char * reg,int n,long addr)822 load_constant(unsigned char *reg, int n, long addr)
823 #else
824 load_constant(reg, n, addr)
825 unsigned char *reg;
826 int n;
827 long addr;
828 #endif
829 {
830 int i, p;
831
832 p = saturn.P;
833 for (i = 0; i < n; i++) {
834 reg[p] = read_nibble(addr + i);
835 p = (p + 1) & 0xf;
836 }
837 }
838
839 void
840 #ifdef __FunctionProto__
load_addr(word_20 * dat,long addr,int n)841 load_addr(word_20 *dat, long addr, int n)
842 #else
843 load_addr(dat, addr, n)
844 word_20 *dat;
845 long addr;
846 int n;
847 #endif
848 {
849 int i;
850
851 for (i = 0; i < n; i++) {
852 *dat &= ~nibble_masks[i];
853 *dat |= read_nibble(addr + i) << (i * 4);
854 }
855 }
856
857 void
858 #ifdef __FunctionProto__
load_address(unsigned char * reg,long addr,int n)859 load_address(unsigned char *reg, long addr, int n)
860 #else
861 load_address(reg, addr, n)
862 unsigned char *reg;
863 long addr;
864 int n;
865 #endif
866 {
867 int i;
868
869 for (i = 0; i < n; i++) {
870 reg[i] = read_nibble(addr + i);
871 }
872 }
873
874 void
875 #ifdef __FunctionProto__
register_to_address(unsigned char * reg,word_20 * dat,int s)876 register_to_address(unsigned char *reg, word_20 *dat, int s)
877 #else
878 register_to_address(reg, dat, s)
879 unsigned char *reg;
880 word_20 *dat;
881 int s;
882 #endif
883 {
884 int i, n;
885
886 if (s)
887 n = 4;
888 else
889 n = 5;
890 for (i = 0; i < n; i++) {
891 *dat &= ~nibble_masks[i];
892 *dat |= (reg[i] & 0x0f) << (i * 4);
893 }
894 }
895
896 void
897 #ifdef __FunctionProto__
address_to_register(word_20 dat,unsigned char * reg,int s)898 address_to_register(word_20 dat, unsigned char *reg, int s)
899 #else
900 address_to_register(dat, reg, s)
901 word_20 dat;
902 unsigned char *reg;
903 int s;
904 #endif
905 {
906 int i, n;
907
908 if (s)
909 n = 4;
910 else
911 n = 5;
912 for (i = 0; i < n; i++) {
913 reg[i] = dat & 0x0f;
914 dat >>= 4;
915 }
916 }
917
918 long
919 #ifdef __FunctionProto__
dat_to_addr(unsigned char * dat)920 dat_to_addr(unsigned char *dat)
921 #else
922 dat_to_addr(dat)
923 unsigned char *dat;
924 #endif
925 {
926 int i;
927 long addr;
928
929 addr = 0;
930 for (i = 4; i >= 0; i--) {
931 addr <<= 4;
932 addr |= (dat[i] & 0xf);
933 }
934 return addr;
935 }
936
937 void
938 #ifdef __FunctionProto__
addr_to_dat(long addr,unsigned char * dat)939 addr_to_dat(long addr, unsigned char *dat)
940 #else
941 addr_to_dat(addr, dat)
942 long addr;
943 unsigned char *dat;
944 #endif
945 {
946 int i;
947
948 for (i = 0; i < 5; i++) {
949 dat[i] = (addr & 0xf);
950 addr >>= 4;
951 }
952 }
953
954 void
955 #ifdef __FunctionProto__
add_address(word_20 * dat,int add)956 add_address(word_20 *dat, int add)
957 #else
958 add_address(dat, add)
959 word_20 *dat;
960 int add;
961 #endif
962 {
963 *dat += add;
964 if (*dat & (word_20)0xfff00000) {
965 saturn.CARRY = 1;
966 } else {
967 saturn.CARRY = 0;
968 }
969 *dat &= 0xfffff;
970 }
971
972 static int start_fields[] = {
973 -1, 0, 2, 0, 15, 3, 0, 0,
974 -1, 0, 2, 0, 15, 3, 0, 0,
975 0, 0, 0
976 };
977
978 static int end_fields[] = {
979 -1, -1, 2, 2, 15, 14, 1, 15,
980 -1, -1, 2, 2, 15, 14, 1, 4,
981 3, 2, 0
982 };
983
984 static inline int
985 #ifdef __FunctionProto__
get_start(int code)986 get_start(int code)
987 #else
988 get_start(code)
989 int code;
990 #endif
991 {
992 int s;
993
994 if ((s = start_fields[code]) == -1) {
995 s = saturn.P;
996 }
997 return s;
998 }
999
1000 static inline int
1001 #ifdef __FuntionProto__
get_end(int code)1002 get_end(int code)
1003 #else
1004 get_end(code)
1005 int code;
1006 #endif
1007 {
1008 int e;
1009
1010 if ((e = end_fields[code]) == -1) {
1011 e = saturn.P;
1012 }
1013 return e;
1014 }
1015
1016 void
1017 #ifdef __FunctionProto__
store(word_20 dat,unsigned char * reg,int code)1018 store(word_20 dat, unsigned char *reg, int code)
1019 #else
1020 store(dat, reg, code)
1021 word_20 dat;
1022 unsigned char *reg;
1023 int code;
1024 #endif
1025 {
1026 int i, s, e;
1027
1028 s = get_start(code);
1029 e = get_end(code);
1030 for (i = s; i <= e; i++) {
1031 write_nibble(dat++, reg[i]);
1032 }
1033 }
1034
1035 void
1036 #ifdef __FunctionProto__
store_n(word_20 dat,unsigned char * reg,int n)1037 store_n(word_20 dat, unsigned char *reg, int n)
1038 #else
1039 store_n(dat, reg, n)
1040 word_20 dat;
1041 unsigned char *reg;
1042 int n;
1043 #endif
1044 {
1045 int i;
1046
1047 for (i = 0; i < n; i++) {
1048 write_nibble(dat++, reg[i]);
1049 }
1050 }
1051
1052 void
1053 #ifdef __FunctionProto__
recall(unsigned char * reg,word_20 dat,int code)1054 recall(unsigned char *reg, word_20 dat, int code)
1055 #else
1056 recall(reg, dat, code)
1057 unsigned char *reg;
1058 word_20 dat;
1059 int code;
1060 #endif
1061 {
1062 int i, s, e;
1063
1064 s = get_start(code);
1065 e = get_end(code);
1066 for (i = s; i <= e; i++) {
1067 reg[i] = read_nibble_crc(dat++);
1068 }
1069 }
1070
1071 void
1072 #ifdef __FunctionProto__
recall_n(unsigned char * reg,word_20 dat,int n)1073 recall_n(unsigned char *reg, word_20 dat, int n)
1074 #else
1075 recall_n(reg, dat, n)
1076 unsigned char *reg;
1077 word_20 dat;
1078 int n;
1079 #endif
1080 {
1081 int i;
1082
1083 for (i = 0; i < n; i++) {
1084 reg[i] = read_nibble_crc(dat++);
1085 }
1086 }
1087
1088