· 5 years ago · Feb 19, 2020, 03:24 AM
1#include "stdafx.h"
2
3#include <winsock2.h>
4
5/*
6* Author: George Gao (18043234)
7* Created : 24 / 01 / 20
8* Revised : 09 / 02 / 20
9* Description : Chimera - 2018 - J Emulator
10* User advice : None
11* Notes : Line 52, 62 added extra register
12*/
13
14/*
15Week 01:
16
17Week 02:
18
19Week 03:
20
21Week 04:
22
23Week 05:
24
25Week 06:
26
27*/
28
29# pragma comment(lib, "wsock32.lib")
30
31# define STUDENT_NUMBER "18043234"
32
33# define IP_ADDRESS_SERVER "127.0.0.1"
34
35# define PORT_SERVER 0x1984 //We define a port that we are going to use.
36# define PORT_CLIENT 0x1985 //We define a port that we are going to use.
37
38# define WORD unsigned short
39# define DWORD unsigned long
40# define BYTE unsigned char
41
42# define MAX_FILENAME_SIZE 500
43# define MAX_BUFFER_SIZE 500
44
45SOCKADDR_IN server_addr;
46SOCKADDR_IN client_addr;
47
48SOCKET sock; //This is our socket, it is the handle to the IO address to read/write packets
49
50WSADATA data;
51
52char InputBuffer[MAX_BUFFER_SIZE];
53
54char hex_file[MAX_BUFFER_SIZE];
55char trc_file[MAX_BUFFER_SIZE];
56
57//////////////////////////
58// Registers //
59//////////////////////////
60
61# define FLAG_I 0x80
62# define FLAG_N 0x20
63# define FLAG_V 0x10
64# define FLAG_Z 0x08
65# define FLAG_C 0x01
66
67# define REGISTER_M 7 //ADDED EXTRA REGISTER
68# define REGISTER_A 6
69# define REGISTER_H 5
70# define REGISTER_L 4
71# define REGISTER_E 3
72# define REGISTER_D 2
73# define REGISTER_C 1
74# define REGISTER_B 0
75
76WORD IndexRegister;
77
78BYTE Registers[8]; //CHANGED FROM 7 T0 8
79BYTE Flags;
80WORD ProgramCounter;
81WORD StackPointer;
82
83////////////
84// Memory //
85////////////
86
87# define MEMORY_SIZE 65536
88
89BYTE Memory[MEMORY_SIZE];
90
91# define TEST_ADDRESS_1 0x01FA
92# define TEST_ADDRESS_2 0x01FB
93# define TEST_ADDRESS_3 0x01FC
94# define TEST_ADDRESS_4 0x01FD
95# define TEST_ADDRESS_5 0x01FE
96# define TEST_ADDRESS_6 0x01FF
97# define TEST_ADDRESS_7 0x0200
98# define TEST_ADDRESS_8 0x0201
99# define TEST_ADDRESS_9 0x0202
100# define TEST_ADDRESS_10 0x0203
101# define TEST_ADDRESS_11 0x0204
102# define TEST_ADDRESS_12 0x0205
103
104///////////////////////
105// Control variables //
106///////////////////////
107
108bool memory_in_range = true;
109bool halt = false;
110
111///////////////////////
112// Disassembly table //
113///////////////////////
114
115char opcode_mneumonics[][14] = {
116 "BRA rel ",
117 "BCC rel ",
118 "BCS rel ",
119 "BNE rel ",
120 "BEQ rel ",
121 "BVC rel ",
122 "BVS rel ",
123 "BMI rel ",
124 "BPL rel ",
125 "BGE rel ",
126 "BLE rel ",
127 "BLS rel ",
128 "BHI rel ",
129 "ILLEGAL ",
130 "RTN impl ",
131 "ILLEGAL ",
132
133 "ST abs ",
134 "PSH ,A ",
135 "POP A, ",
136 "ILLEGAL ",
137 "ILLEGAL ",
138 "CLC impl ",
139 "SEC impl ",
140 "CLI impl ",
141 "STI impl ",
142 "SEV impl ",
143 "CLV impl ",
144 "DEX impl ",
145 "INX impl ",
146 "NOP impl ",
147 "WAI impl ",
148 "ILLEGAL ",
149
150 "ST abs,X ",
151 "PSH ,s ",
152 "POP s, ",
153 "ILLEGAL ",
154 "ILLEGAL ",
155 "ADI # ",
156 "SBI # ",
157 "CPI # ",
158 "ANI # ",
159 "XRI # ",
160 "MVI #,B ",
161 "MVI #,C ",
162 "MVI #,D ",
163 "MVI #,E ",
164 "MVI #,L ",
165 "MVI #,H ",
166
167 "ILLEGAL ",
168 "PSH ,B ",
169 "POP B, ",
170 "JPR abs ",
171 "CCC abs ",
172 "CCS abs ",
173 "CNE abs ",
174 "CEQ abs ",
175 "CVC abs ",
176 "CVS abs ",
177 "CMI abs ",
178 "CPL abs ",
179 "CHI abs ",
180 "CLE abs ",
181 "ILLEGAL ",
182 "ILLEGAL ",
183
184 "ILLEGAL ",
185 "PSH ,C ",
186 "POP C, ",
187 "TST abs ",
188 "INC abs ",
189 "DEC abs ",
190 "RCR abs ",
191 "RCL abs ",
192 "SAL abs ",
193 "ASR abs ",
194 "NOT abs ",
195 "ROL abs ",
196 "ROR abs ",
197 "ILLEGAL ",
198 "LDX # ",
199 "LODS # ",
200
201 "STOX abs ",
202 "PSH ,D ",
203 "POP D, ",
204 "TST abs,X ",
205 "INC abs,X ",
206 "DEC abs,X ",
207 "RCR abs,X ",
208 "RCL abs,X ",
209 "SAL abs,X ",
210 "ASR abs,X ",
211 "NOT abs,X ",
212 "ROL abs,X ",
213 "ROR abs,X ",
214 "ILLEGAL ",
215 "LDX abs ",
216 "LODS abs ",
217
218 "STOX abs,X ",
219 "PSH ,E ",
220 "POP E, ",
221 "TSTA A,A ",
222 "INCA A,A ",
223 "DECA A,A ",
224 "RCRA A,A ",
225 "RCLA A,A ",
226 "SALA A,A ",
227 "ASRA A,A ",
228 "NOTA A,A ",
229 "ROLA A,A ",
230 "RORA A,A ",
231 "ILLEGAL ",
232 "LDX abs,X ",
233 "LODS abs,X ",
234
235 "ILLEGAL ",
236 "PSH ,L ",
237 "POP L, ",
238 "ILLEGAL ",
239 "TAS impl ",
240 "TSA impl ",
241 "ILLEGAL ",
242 "ILLEGAL ",
243 "MOVE A,A ",
244 "MOVE B,A ",
245 "MOVE C,A ",
246 "MOVE D,A ",
247 "MOVE E,A ",
248 "MOVE L,A ",
249 "MOVE H,A ",
250 "MOVE M,A ",
251
252 "ILLEGAL ",
253 "PSH ,H ",
254 "POP H, ",
255 "ILLEGAL ",
256 "ILLEGAL ",
257 "SWI impl ",
258 "RTI impl ",
259 "ILLEGAL ",
260 "MOVE A,B ",
261 "MOVE B,B ",
262 "MOVE C,B ",
263 "MOVE D,B ",
264 "MOVE E,B ",
265 "MOVE L,B ",
266 "MOVE H,B ",
267 "MOVE M,B ",
268
269 "ADC A,B ",
270 "SBC A,B ",
271 "CMP A,B ",
272 "IOR A,B ",
273 "AND A,B ",
274 "XOR A,B ",
275 "BT A,B ",
276 "ILLEGAL ",
277 "MOVE A,C ",
278 "MOVE B,C ",
279 "MOVE C,C ",
280 "MOVE D,C ",
281 "MOVE E,C ",
282 "MOVE L,C ",
283 "MOVE H,C ",
284 "MOVE M,C ",
285
286 "ADC A,C ",
287 "SBC A,C ",
288 "CMP A,C ",
289 "IOR A,C ",
290 "AND A,C ",
291 "XOR A,C ",
292 "BT A,C ",
293 "ILLEGAL ",
294 "MOVE A,D ",
295 "MOVE B,D ",
296 "MOVE C,D ",
297 "MOVE D,D ",
298 "MOVE E,D ",
299 "MOVE L,D ",
300 "MOVE H,D ",
301 "MOVE M,D ",
302
303 "ADC A,D ",
304 "SBC A,D ",
305 "CMP A,D ",
306 "IOR A,D ",
307 "AND A,D ",
308 "XOR A,D ",
309 "BT A,D ",
310 "LD # ",
311 "MOVE A,E ",
312 "MOVE B,E ",
313 "MOVE C,E ",
314 "MOVE D,E ",
315 "MOVE E,E ",
316 "MOVE L,E ",
317 "MOVE H,E ",
318 "MOVE M,E ",
319
320 "ADC A,E ",
321 "SBC A,E ",
322 "CMP A,E ",
323 "IOR A,E ",
324 "AND A,E ",
325 "XOR A,E ",
326 "BT A,E ",
327 "LD abs ",
328 "MOVE A,L ",
329 "MOVE B,L ",
330 "MOVE C,L ",
331 "MOVE D,L ",
332 "MOVE E,L ",
333 "MOVE L,L ",
334 "MOVE H,L ",
335 "MOVE M,L ",
336
337 "ADC A,L ",
338 "SBC A,L ",
339 "CMP A,L ",
340 "IOR A,L ",
341 "AND A,L ",
342 "XOR A,L ",
343 "BT A,L ",
344 "LD abs,X ",
345 "MOVE A,H ",
346 "MOVE B,H ",
347 "MOVE C,H ",
348 "MOVE D,H ",
349 "MOVE E,H ",
350 "MOVE L,H ",
351 "MOVE H,H ",
352 "MOVE M,H ",
353
354 "ADC A,H ",
355 "SBC A,H ",
356 "CMP A,H ",
357 "IOR A,H ",
358 "AND A,H ",
359 "XOR A,H ",
360 "BT A,H ",
361 "ILLEGAL ",
362 "MOVE A,M ",
363 "MOVE B,M ",
364 "MOVE C,M ",
365 "MOVE D,M ",
366 "MOVE E,M ",
367 "MOVE L,M ",
368 "MOVE H,M ",
369 "MOVE -,- ",
370
371 "ADC A,M ",
372 "SBC A,M ",
373 "CMP A,M ",
374 "IOR A,M ",
375 "AND A,M ",
376 "XOR A,M ",
377 "BT A,M ",
378 "ILLEGAL ",
379 "ILLEGAL ",
380 "ILLEGAL ",
381 "JMP abs ",
382 "ILLEGAL ",
383 "ILLEGAL ",
384 "ILLEGAL ",
385 "ILLEGAL ",
386 "ILLEGAL ",
387};
388
389////////////////////////////////////////////////////////////////////////////////
390// Simulator/Emulator (Start) //
391////////////////////////////////////////////////////////////////////////////////
392BYTE fetch() {
393 BYTE byte = 0;
394
395 if ((ProgramCounter >= 0) && (ProgramCounter <= MEMORY_SIZE)) {
396 memory_in_range = true;
397 byte = Memory[ProgramCounter];
398 ProgramCounter++;
399 }
400 else {
401 memory_in_range = false;
402 }
403 return byte;
404}
405
406/*---------------------------------------------------------------------------*/
407
408/*---------------------------------------------------------------------------*/
409void set_flag_n(BYTE inReg) {
410 BYTE reg;
411 reg = inReg;
412
413 if ((reg & 0x80) != 0) //msbit set
414 {
415 Flags = Flags | FLAG_N;
416 }
417 else {
418 Flags = Flags & (0xFF - FLAG_N);
419 }
420}
421
422void set_flag_v(BYTE in1, BYTE in2, BYTE out1) {
423 BYTE reg1in;
424 BYTE reg2in;
425 BYTE regOut;
426
427 reg1in = in1;
428 reg2in = in2;
429 regOut = out1;
430
431 if ((((reg1in & 0x80) == 0x80) && ((reg2in & 0x80) == 0x80) && ((regOut & 0x80) != 0x80)) ||
432 (((reg1in & 0x80) != 0x80) && ((reg2in & 0x80) != 0x80) && ((regOut & 0x80) == 0x80))) {
433 Flags = Flags | FLAG_V;
434 }
435 else {
436 Flags = Flags & (0xFF - FLAG_V);
437 }
438}
439
440void set_flag_z(BYTE inReg) {
441 BYTE reg;
442 reg = inReg;
443
444 if (reg == 0) //zero set
445 {
446 Flags = Flags | FLAG_Z;
447 }
448 else {
449 Flags = Flags & (0xFF - FLAG_Z);
450 }
451}
452
453void Group_1(BYTE opcode) {
454 BYTE LB = 0;
455 BYTE HB = 0;
456 WORD address = 0;
457 WORD data = 0;
458
459 WORD temp_word;
460 WORD param1;
461 WORD param2;
462 WORD offset;
463 WORD saved_flags;
464
465 BYTE CF;
466 if ((Flags & FLAG_C) == 0) {
467 CF = 1;
468 }
469 else {
470 CF = 0;
471 }
472
473 BYTE NF;
474 if ((Flags & FLAG_N) == 0) {
475 NF = 1;
476 }
477 else {
478 NF = 0;
479 }
480
481 BYTE ZF;
482 if ((Flags & FLAG_Z) == 0) {
483 ZF = 1;
484 }
485 else {
486 ZF = 0;
487 }
488
489 BYTE VF;
490 if ((Flags & FLAG_V) == 0) {
491 VF = 1;
492 }
493 else {
494 VF = 0;
495 }
496
497 switch (opcode) {
498/*----------------------------LOADING AND STORING----------------------------*/
499 /*
500 * Opcode: LD
501 * Description: Loads Memory into Accumulator
502 * Flags: - - T - T - - 0
503 * Notes: None
504 */
505 case 0xB7: //LD IMMEDIATE ADDRESSING (#)
506 data = fetch();
507 Registers[REGISTER_A] = data;
508
509 set_flag_n(Registers[REGISTER_A]);
510 set_flag_z(Registers[REGISTER_A]);
511 Flags = Flags & (0xFF - FLAG_C);
512 break;
513
514 case 0xC7: //LD ABSOLUTE ADDRESSING (abs)
515 HB = fetch();
516 LB = fetch();
517 address += (WORD)((WORD)HB << 8) + LB;
518 if (address >= 0 && address < MEMORY_SIZE) {
519 Registers[REGISTER_A] = Memory[address];
520 }
521
522 set_flag_n(Registers[REGISTER_A]);
523 set_flag_z(Registers[REGISTER_A]);
524 Flags = Flags & (0xFF - FLAG_C);
525 break;
526
527 case 0xD7: //LD INDEXED ABSOLUTE ADDRESSING (abs,X)
528 address += IndexRegister;
529 HB = fetch();
530 LB = fetch();
531 address += (WORD)((WORD)HB << 8) + LB;
532 if (address >= 0 && address < MEMORY_SIZE) {
533 Registers[REGISTER_A] = Memory[address];
534 }
535
536 set_flag_n(Registers[REGISTER_A]);
537 set_flag_z(Registers[REGISTER_A]);
538 Flags = Flags & (0xFF - FLAG_C);
539 break;
540
541 /*
542 * Opcode: ST
543 * Description: Stores Accumulator into Memory
544 * Flags: - - T - T - - 0
545 * Notes: None
546 */
547 case 0x10: //ST ABSOLUTE ADDRESSING (abs)
548 HB = fetch();
549 LB = fetch();
550 address += (WORD)((WORD)HB << 8) + LB;
551 if (address >= 0 && address < MEMORY_SIZE) {
552 Memory[address] = Registers[REGISTER_A];
553 }
554
555 set_flag_n(Registers[REGISTER_A]);
556 set_flag_z(Registers[REGISTER_A]);
557 Flags = Flags & (0xFF - FLAG_C);
558 break;
559
560 case 0x20: //ST INDEXED ABSOLUTE ADDRESSING (abs,X)
561 address += IndexRegister;
562 HB = fetch();
563 LB = fetch();
564 address += (WORD)((WORD)HB << 8) + LB;
565 if (address >= 0 && address < MEMORY_SIZE) {
566 Memory[address] = Registers[REGISTER_A];
567 }
568
569 set_flag_n(Registers[REGISTER_A]);
570 set_flag_z(Registers[REGISTER_A]);
571 Flags = Flags & (0xFF - FLAG_C);
572 break;
573
574 /*
575 * Opcode: MVI
576 * Description: Loads Memory into register
577 * Flags: - - T - T - - 0
578 * Notes: None
579 */
580 case 0x2A: //MVI IMMEDIATE ADDRESSING (#); B
581 data = fetch();
582 Registers[REGISTER_B] = data;
583
584 set_flag_n(Registers[REGISTER_B]);
585 set_flag_z(Registers[REGISTER_B]);
586 Flags = Flags & (0xFF - FLAG_C);
587 break;
588
589 case 0x2B: //MVI IMMEDIATE ADDRESSING (#); C
590 data = fetch();
591 Registers[REGISTER_C] = data;
592
593 set_flag_n(Registers[REGISTER_C]);
594 set_flag_z(Registers[REGISTER_C]);
595 Flags = Flags & (0xFF - FLAG_C);
596 break;
597
598 case 0x2C: //MVI IMMEDIATE ADDRESSING (#); D
599 data = fetch();
600 Registers[REGISTER_D] = data;
601
602 set_flag_n(Registers[REGISTER_D]);
603 set_flag_z(Registers[REGISTER_D]);
604 Flags = Flags & (0xFF - FLAG_C);
605 break;
606
607 case 0x2D: //MVI IMMEDIATE ADDRESSING (#); E
608 data = fetch();
609 Registers[REGISTER_E] = data;
610
611 set_flag_n(Registers[REGISTER_E]);
612 set_flag_z(Registers[REGISTER_E]);
613 Flags = Flags & (0xFF - FLAG_C);
614 break;
615
616 case 0x2E: //MVI IMMEDIATE ADDRESSING (#); L
617 data = fetch();
618 Registers[REGISTER_L] = data;
619
620 set_flag_n(Registers[REGISTER_L]);
621 set_flag_z(Registers[REGISTER_L]);
622 Flags = Flags & (0xFF - FLAG_C);
623 break;
624
625 case 0x2F: //MVI IMMEDIATE ADDRESSING (#); H
626 data = fetch();
627 Registers[REGISTER_H] = data;
628
629 set_flag_n(Registers[REGISTER_H]);
630 set_flag_z(Registers[REGISTER_H]);
631 Flags = Flags & (0xFF - FLAG_C);
632 break;
633
634 /*
635 * Opcode: LODS
636 * Description: Loads Memory into Stackpointer
637 * Flags: - - T - T - - 0
638 * Notes: NOT DECLARED FLAGS YET
639 */
640 case 0x4F: //LODS IMMEDIATE ADDRESSING (#)
641 data = fetch();
642 StackPointer = data << 8;
643 StackPointer += fetch();
644 break;
645
646 case 0x5F: //LODS ABSOLUTE ADDRESSING (abs)
647 HB = fetch();
648 LB = fetch();
649 address += (WORD)((WORD)HB << 8) + LB;
650 if (address >= 0 && address < MEMORY_SIZE - 1) {
651 StackPointer = (WORD)Memory[address] << 8;
652 StackPointer += Memory[address + 1];
653 }
654 break;
655
656 case 0x6F: //LODS INDEXED ABSOLUTE ADDRESSING (abs, X)
657 address += IndexRegister;
658 HB = fetch();
659 LB = fetch();
660 address += (WORD)((WORD)HB << 8) + LB;
661 if (address >= 0 && address < MEMORY_SIZE - 1) {
662 StackPointer = (WORD)Memory[address] << 8;
663 StackPointer += Memory[address + 1];
664 }
665 break;
666
667 /*
668 * Opcode: LDX
669 * Description: Loads Memory into register X
670 * Flags: - - T - T - - 0
671 * Notes: None
672 */
673 case 0x4E: //LDX IMMEDIATE ADDRESSING (#)
674 data = fetch();
675 Registers[IndexRegister] = data;
676
677 set_flag_n(Registers[IndexRegister]);
678 set_flag_z(Registers[IndexRegister]);
679 Flags = Flags & (0xFF - FLAG_C);
680 break;
681
682 case 0x5E: //LDX ABSOLUTE ADDRESSING (abs)
683 HB = fetch();
684 LB = fetch();
685 address += (WORD)((WORD)HB << 8) + LB;
686 if (address >= 0 && address < MEMORY_SIZE) {
687 Registers[IndexRegister] = Memory[address];
688 }
689
690 set_flag_n(Registers[IndexRegister]);
691 set_flag_z(Registers[IndexRegister]);
692 Flags = Flags & (0xFF - FLAG_C);
693 break;
694
695 case 0x6E: //LDX INDEXED ABSOLUTE ADDRESSING (abs,X)
696 address += IndexRegister;
697 HB = fetch();
698 LB = fetch();
699 address += (WORD)((WORD)HB << 8) + LB;
700 if (address >= 0 && address < MEMORY_SIZE) {
701 Registers[IndexRegister] = Memory[address];
702 }
703
704 set_flag_n(Registers[IndexRegister]);
705 set_flag_z(Registers[IndexRegister]);
706 Flags = Flags & (0xFF - FLAG_C);
707 break;
708
709 /*
710 * Opcode: STOX
711 * Description: Stores register X into Memory
712 * Flags: - - T - T - - 0
713 * Notes: None
714 */
715 case 0x50: //STOX ABSOLUTE ADDRESSING (abs)
716 address += IndexRegister;
717 HB = fetch();
718 LB = fetch();
719 address += (WORD)((WORD)HB << 8) + LB;
720 if (address >= 0 && address < MEMORY_SIZE) {
721 Memory[address] = Registers[IndexRegister];
722 }
723
724 set_flag_n(Registers[IndexRegister]);
725 set_flag_z(Registers[IndexRegister]);
726 Flags = Flags & (0xFF - FLAG_C);
727 break;
728
729 case 0x60: //STOX INDEXED ABSOLUTE ADDRESSING (abs, X)
730 address += IndexRegister;
731 HB = fetch();
732 LB = fetch();
733 address += (WORD)((WORD)HB << 8) + LB;
734 if (address >= 0 && address < MEMORY_SIZE) {
735 Memory[address] = Registers[IndexRegister];
736 }
737
738 set_flag_n(Registers[IndexRegister]);
739 set_flag_z(Registers[IndexRegister]);
740 Flags = Flags & (0xFF - FLAG_C);
741 break;
742
743/*-----------------------------------FLAGS-----------------------------------*/
744 /*
745 * Opcode: ADC
746 * Description: Register added to Accumulator with Carry
747 * Flags: - - T T T - - T
748 * Notes: None
749 */
750 case 0x90: //ADC A-B
751 temp_word = (WORD)Registers[REGISTER_A] + (WORD)Registers[REGISTER_B];
752
753 if ((Flags & FLAG_C) != 0) {
754 temp_word++;
755 }
756
757 if (temp_word >= 0x100) {
758 Flags = Flags | FLAG_C; //Set carry flag
759 }
760 else {
761 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
762 }
763
764 set_flag_n((BYTE)temp_word);
765 set_flag_z((BYTE)temp_word);
766 set_flag_v(REGISTER_A, REGISTER_B, (BYTE)temp_word);
767 Registers[REGISTER_A] = (BYTE)temp_word;
768 break;
769
770 case 0xA0: //ADC A-C
771 temp_word = (WORD)Registers[REGISTER_A] + (WORD)Registers[REGISTER_C];
772
773 if ((Flags & FLAG_C) != 0) {
774 temp_word++;
775 }
776
777 if (temp_word >= 0x100) {
778 Flags = Flags | FLAG_C; //Set carry flag
779 }
780 else {
781 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
782 }
783
784 set_flag_n((BYTE)temp_word);
785 set_flag_z((BYTE)temp_word);
786 set_flag_v(REGISTER_A, REGISTER_C, (BYTE)temp_word);
787 Registers[REGISTER_A] = (BYTE)temp_word;
788 break;
789
790 case 0xB0: //ADC A-D
791 temp_word = (WORD)Registers[REGISTER_A] + (WORD)Registers[REGISTER_D];
792
793 if ((Flags & FLAG_C) != 0) {
794 temp_word++;
795 }
796
797 if (temp_word >= 0x100) {
798 Flags = Flags | FLAG_C; //Set carry flag
799 }
800 else {
801 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
802 }
803
804 set_flag_n((BYTE)temp_word);
805 set_flag_z((BYTE)temp_word);
806 set_flag_v(REGISTER_A, REGISTER_D, (BYTE)temp_word);
807 Registers[REGISTER_A] = (BYTE)temp_word;
808 break;
809
810 case 0xC0: //ADC A-E
811 temp_word = (WORD)Registers[REGISTER_A] + (WORD)Registers[REGISTER_E];
812
813 if ((Flags & FLAG_C) != 0) {
814 temp_word++;
815 }
816
817 if (temp_word >= 0x100) {
818 Flags = Flags | FLAG_C; //Set carry flag
819 }
820 else {
821 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
822 }
823
824 set_flag_n((BYTE)temp_word);
825 set_flag_z((BYTE)temp_word);
826 set_flag_v(REGISTER_A, REGISTER_E, (BYTE)temp_word);
827 Registers[REGISTER_A] = (BYTE)temp_word;
828 break;
829
830 case 0xD0: //ADC A-L
831 temp_word = (WORD)Registers[REGISTER_A] + (WORD)Registers[REGISTER_L];
832
833 if ((Flags & FLAG_C) != 0) {
834 temp_word++;
835 }
836
837 if (temp_word >= 0x100) {
838 Flags = Flags | FLAG_C; //Set carry flag
839 }
840 else {
841 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
842 }
843
844 set_flag_n((BYTE)temp_word);
845 set_flag_z((BYTE)temp_word);
846 set_flag_v(REGISTER_A, REGISTER_L, (BYTE)temp_word);
847 Registers[REGISTER_A] = (BYTE)temp_word;
848 break;
849
850 case 0xE0: //ADC A-H
851 temp_word = (WORD)Registers[REGISTER_A] + (WORD)Registers[REGISTER_H];
852
853 if ((Flags & FLAG_C) != 0) {
854 temp_word++;
855 }
856
857 if (temp_word >= 0x100) {
858 Flags = Flags | FLAG_C; //Set carry flag
859 }
860 else {
861 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
862 }
863
864 set_flag_n((BYTE)temp_word);
865 set_flag_z((BYTE)temp_word);
866 set_flag_v(REGISTER_A, REGISTER_H, (BYTE)temp_word);
867 Registers[REGISTER_A] = (BYTE)temp_word;
868 break;
869
870 case 0xF0: //ADC A-M
871 temp_word = (WORD)Registers[REGISTER_A] + (WORD)Registers[REGISTER_M];
872
873 if ((Flags & FLAG_C) != 0) {
874 temp_word++;
875 }
876
877 if (temp_word >= 0x100) {
878 Flags = Flags | FLAG_C; //Set carry flag
879 }
880 else {
881 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
882 }
883
884 set_flag_n((BYTE)temp_word);
885 set_flag_z((BYTE)temp_word);
886 set_flag_v(REGISTER_A, REGISTER_M, (BYTE)temp_word);
887 Registers[REGISTER_A] = (BYTE)temp_word;
888 break;
889
890 /*
891 * Opcode: CMP
892 * Description: Register compared to Accumulator
893 * Flags: - - T T T - - T
894 * Notes: None
895 */
896 case 0x92: //CMP A-B
897 param1 = Registers[REGISTER_A];
898 param2 = Registers[REGISTER_B];
899
900 temp_word = (WORD)param1 - (WORD)param2;
901
902 if (temp_word >= 0x100) {
903 Flags = Flags | FLAG_C; //Set carry flag
904 }
905 else {
906 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
907 }
908
909 set_flag_n((BYTE)temp_word);
910 set_flag_z((BYTE)temp_word);
911 set_flag_v(param1, param2, (BYTE)temp_word);
912 break;
913
914 case 0xA2: //CMP A-C
915 param1 = Registers[REGISTER_A];
916 param2 = Registers[REGISTER_C];
917
918 temp_word = (WORD)param1 - (WORD)param2;
919
920 if (temp_word >= 0x100) {
921 Flags = Flags | FLAG_C; //Set carry flag
922 }
923 else {
924 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
925 }
926
927 set_flag_n((BYTE)temp_word);
928 set_flag_z((BYTE)temp_word);
929 set_flag_v(param1, param2, (BYTE)temp_word);
930 break;
931
932 case 0xB2: //CMP A-D
933 param1 = Registers[REGISTER_A];
934 param2 = Registers[REGISTER_D];
935
936 temp_word = (WORD)param1 - (WORD)param2;
937
938 if (temp_word >= 0x100) {
939 Flags = Flags | FLAG_C; //Set carry flag
940 }
941 else {
942 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
943 }
944
945 set_flag_n((BYTE)temp_word);
946 set_flag_z((BYTE)temp_word);
947 set_flag_v(param1, param2, (BYTE)temp_word);
948 break;
949
950 case 0xC2: //CMP A-E
951 param1 = Registers[REGISTER_A];
952 param2 = Registers[REGISTER_E];
953
954 temp_word = (WORD)param1 - (WORD)param2;
955
956 if (temp_word >= 0x100) {
957 Flags = Flags | FLAG_C; //Set carry flag
958 }
959 else {
960 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
961 }
962
963 set_flag_n((BYTE)temp_word);
964 set_flag_z((BYTE)temp_word);
965 set_flag_v(param1, param2, (BYTE)temp_word);
966 break;
967
968 case 0xD2: //CMP A-L
969 param1 = Registers[REGISTER_A];
970 param2 = Registers[REGISTER_L];
971
972 temp_word = (WORD)param1 - (WORD)param2;
973
974 if (temp_word >= 0x100) {
975 Flags = Flags | FLAG_C; //Set carry flag
976 }
977 else {
978 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
979 }
980
981 set_flag_n((BYTE)temp_word);
982 set_flag_z((BYTE)temp_word);
983 set_flag_v(param1, param2, (BYTE)temp_word);
984 break;
985
986 case 0xE2: //CMP A-H
987 param1 = Registers[REGISTER_A];
988 param2 = Registers[REGISTER_H];
989
990 temp_word = (WORD)param1 - (WORD)param2;
991
992 if (temp_word >= 0x100) {
993 Flags = Flags | FLAG_C; //Set carry flag
994 }
995 else {
996 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
997 }
998
999 set_flag_n((BYTE)temp_word);
1000 set_flag_z((BYTE)temp_word);
1001 set_flag_v(param1, param2, (BYTE)temp_word);
1002 break;
1003
1004 case 0xF2: //CMP A-M
1005 param1 = Registers[REGISTER_A];
1006 param2 = Registers[REGISTER_M];
1007
1008 temp_word = (WORD)param1 - (WORD)param2;
1009
1010 if (temp_word >= 0x100) {
1011 Flags = Flags | FLAG_C; //Set carry flag
1012 }
1013 else {
1014 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
1015 }
1016
1017 set_flag_n((BYTE)temp_word);
1018 set_flag_z((BYTE)temp_word);
1019 set_flag_v(param1, param2, (BYTE)temp_word);
1020 break;
1021
1022 /*
1023 * Opcode: TSA
1024 * Description: Transfers Status register to Accumulator
1025 * Flags: - - - - - - - -
1026 * Notes: None
1027 */
1028 case 0x75: //TSA
1029 Registers[REGISTER_A] = Flags;
1030 break;
1031
1032 /*
1033 * Opcode: TAS
1034 * Description: Transfers Accumulator to Status register
1035 * Flags: - - - - - - - -
1036 * Notes: None
1037 */
1038 case 0x74: //TAS
1039 Flags = Registers[REGISTER_A];
1040 break;
1041
1042 /*
1043 * Opcode: CLC
1044 * Description: Clear Carry flag
1045 * Flags: - - - - - - - 0
1046 * Notes: None
1047 */
1048 case 0x15: //CLC
1049 Flags = Flags & (0xFF - FLAG_C);
1050 break;
1051
1052 /*
1053 * Opcode: SEC
1054 * Description: Set Carry flag
1055 * Flags: - - - - - - - 1
1056 * Notes: None
1057 */
1058 case 0x16: //SEC
1059 Flags = Flags | FLAG_C;
1060 break;
1061
1062 /*
1063 * Opcode: CLI
1064 * Description: Clear Interrupt flag
1065 * Flags: 0 - - - - - - -
1066 * Notes: None
1067 */
1068 case 0x17: //CLI
1069 Flags = Flags & (0xFF - FLAG_I);
1070 break;
1071
1072 /*
1073 * Opcode: STI
1074 * Description: Set Interrupt flag
1075 * Flags: 1 - - - - - - -
1076 * Notes: None
1077 */
1078 case 0x18: //STI
1079 Flags = Flags | FLAG_I;
1080 break;
1081
1082 /*
1083 * Opcode: SEV
1084 * Description: Set Overflow flag
1085 * Flags: - - - 1 - - - -
1086 * Notes: None
1087 */
1088 case 0x19: //SEV
1089 Flags = Flags | FLAG_V;
1090 break;
1091
1092 /*
1093 * Opcode: CLV
1094 * Description: Clear Overflow flag
1095 * Flags: - - - 0 - - - -
1096 * Notes: None
1097 */
1098 case 0x1A: //CLV
1099 Flags = Flags & (0xFF - FLAG_V);
1100 break;
1101
1102/*-----------------------------------STACK-----------------------------------*/
1103 /*
1104 * Opcode: PSH
1105 * Description: Pushes Register onto the Stack
1106 * Flags: - - - - - - - -
1107 * Notes: None
1108 */
1109 case 0x11: //PSH A
1110 if ((StackPointer >= 1) && (StackPointer < MEMORY_SIZE)) {
1111 Memory[StackPointer] = Registers[REGISTER_A];
1112 StackPointer--;
1113 }
1114 break;
1115
1116 case 0x21: //PSH FL
1117 Memory[StackPointer] = Flags;
1118 StackPointer--;
1119 break;
1120
1121 case 0x31: //PSH B
1122 if ((StackPointer >= 1) && (StackPointer < MEMORY_SIZE)) {
1123 Memory[StackPointer] = Registers[REGISTER_B];
1124 StackPointer--;
1125 }
1126 break;
1127
1128 case 0x41: //PSH C
1129 if ((StackPointer >= 1) && (StackPointer < MEMORY_SIZE)) {
1130 Memory[StackPointer] = Registers[REGISTER_C];
1131 StackPointer--;
1132 }
1133 break;
1134
1135 case 0x51: //PSH D
1136 if ((StackPointer >= 1) && (StackPointer < MEMORY_SIZE)) {
1137 Memory[StackPointer] = Registers[REGISTER_D];
1138 StackPointer--;
1139 }
1140 break;
1141
1142 case 0x61: //PSH E
1143 if ((StackPointer >= 1) && (StackPointer < MEMORY_SIZE)) {
1144 Memory[StackPointer] = Registers[REGISTER_E];
1145 StackPointer--;
1146 }
1147 break;
1148
1149 case 0x71: //PSH L
1150 if ((StackPointer >= 1) && (StackPointer < MEMORY_SIZE)) {
1151 Memory[StackPointer] = Registers[REGISTER_L];
1152 StackPointer--;
1153 }
1154 break;
1155
1156 case 0x81: //PSH H
1157 if ((StackPointer >= 1) && (StackPointer < MEMORY_SIZE)) {
1158 Memory[StackPointer] = Registers[REGISTER_H];
1159 StackPointer--;
1160 }
1161 break;
1162
1163 /*
1164 * Opcode: POP
1165 * Description: Pop the top of the Stack into the Register
1166 * Flags: - - - - - - - -
1167 * Notes: None
1168 */
1169 case 0x12: //POP A
1170 if ((StackPointer >= 0) && (StackPointer < MEMORY_SIZE - 1)) {
1171 StackPointer++;
1172 Registers[REGISTER_A] = Memory[StackPointer];
1173 }
1174 break;
1175
1176 case 0x22: //POP FL
1177 StackPointer++;
1178 Flags = Memory[StackPointer];
1179 break;
1180
1181 case 0x32: //POP B
1182 if ((StackPointer >= 0) && (StackPointer < MEMORY_SIZE - 1)) {
1183 StackPointer++;
1184 Registers[REGISTER_B] = Memory[StackPointer];
1185 }
1186 break;
1187
1188 case 0x42: //POP C
1189 if ((StackPointer >= 0) && (StackPointer < MEMORY_SIZE - 1)) {
1190 StackPointer++;
1191 Registers[REGISTER_C] = Memory[StackPointer];
1192 }
1193 break;
1194
1195 case 0x52: //POP D
1196 if ((StackPointer >= 0) && (StackPointer < MEMORY_SIZE - 1)) {
1197 StackPointer++;
1198 Registers[REGISTER_D] = Memory[StackPointer];
1199 }
1200 break;
1201
1202 case 0x62: //POP E
1203 if ((StackPointer >= 0) && (StackPointer < MEMORY_SIZE - 1)) {
1204 StackPointer++;
1205 Registers[REGISTER_E] = Memory[StackPointer];
1206 }
1207 break;
1208
1209 case 0x72: //POP L
1210 if ((StackPointer >= 0) && (StackPointer < MEMORY_SIZE - 1)) {
1211 StackPointer++;
1212 Registers[REGISTER_L] = Memory[StackPointer];
1213 }
1214 break;
1215
1216 case 0x82: //POP H
1217 if ((StackPointer >= 0) && (StackPointer < MEMORY_SIZE - 1)) {
1218 StackPointer++;
1219 Registers[REGISTER_H] = Memory[StackPointer];
1220 }
1221 break;
1222
1223 /*
1224 * Opcode: JMP
1225 * Description: Load Memory into ProgramCounter
1226 * Flags: - - - - - - - -
1227 * Notes: None
1228 */
1229 case 0xFA: //JMP ABSOLUTE ADDRESSING (abs)
1230 HB = fetch();
1231 LB = fetch();
1232 address = ((WORD)HB << 8) + (WORD)LB;
1233 ProgramCounter = address;
1234 break;
1235
1236 /*
1237 * Opcode: JPR
1238 * Description: Jump to subroutine
1239 * Flags: - - - - - - - -
1240 * Notes: None
1241 */
1242 case 0x33: //JPR ABSOLUTE ADDRESSING (abs)
1243 HB = fetch();
1244 LB = fetch();
1245 address = ((WORD)HB << 8) + (WORD)LB;
1246 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1247 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1248 StackPointer--;
1249 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1250 StackPointer--;
1251 }
1252 ProgramCounter = address;
1253 break;
1254
1255 /*
1256 * Opcode: RTN
1257 * Description: Return from subroutine
1258 * Flags: - - - - - - - -
1259 * Notes: None
1260 */
1261 case 0x0E: //RTN
1262 HB = fetch();
1263 LB = fetch();
1264 address = ((WORD)HB << 8) + (WORD)LB;
1265 if ((StackPointer >= 0) && (StackPointer < MEMORY_SIZE - 2)) {
1266 StackPointer++;
1267 HB = Memory[StackPointer];
1268 StackPointer++;
1269 LB = Memory[StackPointer];
1270 }
1271 ProgramCounter = ((WORD)HB << 8) + (WORD)LB;
1272 break;
1273
1274 //B derrived from Branch
1275 //C derrived from jump
1276
1277 //(Flags & FLAG_V) == 0 BCC
1278 //(Flags & FLAG_V) == FLAG_V BCS
1279
1280 /*
1281 * Opcode: BRA
1282 * Description: Branch always
1283 * Flags: - - - - - - - -
1284 * Notes: None
1285 */
1286 case 0x00: //BRA
1287 LB = fetch();
1288 offset = (WORD)LB;
1289 if ((offset & 0x80) != 0) {
1290 offset = offset + 0xFF00;
1291 }
1292 address = ProgramCounter + offset;
1293 break;
1294
1295 /*
1296 * Opcode: BCC
1297 * Description: Branch on Carry clear
1298 * Flags: - - - - - - - -
1299 * Notes: None
1300 */
1301 case 0x01: //BCC
1302 LB = fetch();
1303 if ((Flags & FLAG_C) == 0) {
1304 offset = (WORD)LB;
1305 if ((offset & 0x80) != 0) {
1306 offset = offset + 0xFF00;
1307 }
1308 address = ProgramCounter + offset;
1309 ProgramCounter = address;
1310 }
1311 break;
1312
1313 /*
1314 * Opcode: BCS
1315 * Description: Branch on Carry set
1316 * Flags: - - - - - - - -
1317 * Notes: None
1318 */
1319 case 0x02: //BCS
1320 LB = fetch();
1321 if ((Flags & FLAG_C) == FLAG_C) {
1322 offset = (WORD)LB;
1323 if ((offset & 0x80) != 0) {
1324 offset = offset + 0xFF00;
1325 }
1326 address = ProgramCounter + offset;
1327 ProgramCounter = address;
1328 }
1329 break;
1330
1331 /*
1332 * Opcode: BNE
1333 * Description: Branch on Result not Zero
1334 * Flags: - - - - - - - -
1335 * Notes: WRONG WRONG
1336 */
1337 case 0x03: //BNE
1338 LB = fetch();
1339 if ((Flags & FLAG_Z) == 0) {
1340 offset = (WORD)LB;
1341 if ((offset & 0x80) != 0) {
1342 offset = offset + 0xFF00;
1343 }
1344 address = ProgramCounter + offset;
1345 ProgramCounter = address;
1346 }
1347 break;
1348 /*
1349 * Opcode: BEQ
1350 * Description: Branch on Result equal to Zero
1351 * Flags: - - - - - - - -
1352 * Notes: WRONG WRONG
1353 */
1354 case 0x04: //BEQ
1355 LB = fetch();
1356 if ((Flags & FLAG_Z) != 0) {
1357 offset = (WORD)LB;
1358 if ((offset & 0x80) != 0) {
1359 offset = offset + 0xFF00;
1360 }
1361 address = ProgramCounter + offset;
1362 ProgramCounter = address;
1363 }
1364
1365 /*
1366 * Opcode: BVC
1367 * Description: Branch on Overflow clear
1368 * Flags: - - - - - - - -
1369 * Notes: WRONG WRONG
1370 */
1371 case 0x05: //BVC
1372 LB = fetch();
1373 if ((Flags & FLAG_V) == 0) {
1374 offset = (WORD)LB;
1375 if ((offset & 0x80) != 0) {
1376 offset = offset + 0xFF00;
1377 }
1378 address = ProgramCounter + offset;
1379 ProgramCounter = address;
1380 }
1381 break;
1382
1383 /*
1384 * Opcode: BVS
1385 * Description: Branch on Overflow set
1386 * Flags: - - - - - - - -
1387 * Notes: WRONG WRONG
1388 */
1389 case 0x06: //BVS
1390 LB = fetch();
1391 if ((Flags & FLAG_V) == FLAG_V) {
1392 offset = (WORD)LB;
1393 if ((offset & 0x80) != 0) {
1394 offset = offset + 0xFF00;
1395 }
1396 address = ProgramCounter + offset;
1397 ProgramCounter = address;
1398 }
1399 break;
1400
1401 /*
1402 * Opcode: BMI
1403 * Description: Branch on negative result
1404 * Flags: - - - - - - - -
1405 * Notes: WRONG WRONG
1406 */
1407 case 0x07: //BMI
1408 LB = fetch();
1409 if ((Flags & FLAG_N) != 0) {
1410 offset = (WORD)LB;
1411 if ((offset & 0x80) != 0) {
1412 offset = offset + 0xFF00;
1413 }
1414 address = ProgramCounter + offset;
1415 ProgramCounter = address;
1416 }
1417 break;
1418
1419 /*
1420 * Opcode: BPL
1421 * Description: Branch on positive result
1422 * Flags: - - - - - - - -
1423 * Notes: WRONG WRONG
1424 */
1425 case 0x08: //BPL
1426 LB = fetch();
1427 if ((Flags & FLAG_N) == 0) {
1428 offset = (WORD)LB;
1429 if ((offset & 0x80) != 0) {
1430 offset = offset + 0xFF00;
1431 }
1432 address = ProgramCounter + offset;
1433 ProgramCounter = address;
1434 }
1435 break;
1436
1437 /*
1438 * Opcode: BGE
1439 * Description: Branch on result less than or equal to zero
1440 * Flags: - - - - - - - -
1441 * Notes: WRONG WRONG
1442 */
1443 case 0x09: //BGE
1444 LB = fetch();
1445 if ((Flags & FLAG_C) == 0) {
1446 offset = (WORD)LB;
1447 if ((offset & 0x80) != 0) {
1448 offset = offset + 0xFF00;
1449 }
1450 address = ProgramCounter + offset;
1451 ProgramCounter = address;
1452 }
1453 break;
1454
1455 /*
1456 * Opcode: BLE
1457 * Description: Branch on result greater than or equal to zero
1458 * Flags: - - - - - - - -
1459 * Notes: WRONG WRONG
1460 */
1461 case 0x0A: //BLE
1462 LB = fetch();
1463 if ((Flags & FLAG_C) == 0) {
1464 offset = (WORD)LB;
1465 if ((offset & 0x80) != 0) {
1466 offset = offset + 0xFF00;
1467 }
1468 address = ProgramCounter + offset;
1469 ProgramCounter = address;
1470 }
1471 break;
1472
1473 /*
1474 * Opcode: BLS
1475 * Description: Branch on result same or lower
1476 * Flags: - - - - - - - -
1477 * Notes: WRONG WRONG
1478 */
1479 case 0x0B: //BLS
1480 LB = fetch();
1481 if ((((Flags & FLAG_C) | ((Flags & FLAG_Z))) != 0)) {
1482 offset = (WORD)LB;
1483 if ((offset & 0x80) != 0) {
1484 offset = offset + 0xFF00;
1485 }
1486 address = ProgramCounter + offset;
1487 ProgramCounter = address;
1488 }
1489 break;
1490
1491 /*
1492 * Opcode: BHI
1493 * Description: Branch on result higher
1494 * Flags: - - - - - - - -
1495 * Notes: WRONG WRONG
1496 */
1497 case 0x0C: //BHI
1498 LB = fetch();
1499 if ((((Flags & FLAG_C) | ((Flags & FLAG_Z))) == 0)) {
1500 offset = (WORD)LB;
1501 if ((offset & 0x80) != 0) {
1502 offset = offset + 0xFF00;
1503 }
1504 address = ProgramCounter + offset;
1505 ProgramCounter = address;
1506 }
1507 break;
1508
1509 /*
1510 * Opcode: CCC
1511 * Description: Call on Carry clear
1512 * Flags: - - - - - - - -
1513 * Notes: None
1514 */
1515 case 0x34: //CCC ABSOLUTE ADDRESSING (abs)
1516 HB = fetch();
1517 LB = fetch();
1518 if ((Flags & FLAG_C) == 0) {
1519 address += (WORD)((WORD)HB << 8) + LB;
1520 if (address >= 0 && address < MEMORY_SIZE) {
1521 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1522 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1523 StackPointer--;
1524 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1525 StackPointer--;
1526 }
1527 ProgramCounter = (WORD)address;
1528 }
1529 }
1530 break;
1531
1532 /*
1533 * Opcode: CCS
1534 * Description: Call on Carry set
1535 * Flags: - - - - - - - -
1536 * Notes: None
1537 */
1538 case 0x35: //CCS ABSOLUTE ADDRESSING (abs)
1539 HB = fetch();
1540 LB = fetch();
1541 if ((Flags & FLAG_C) == FLAG_C) {
1542 address += (WORD)((WORD)HB << 8) + LB;
1543 if (address >= 0 && address < MEMORY_SIZE) {
1544 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1545 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1546 StackPointer--;
1547 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1548 StackPointer--;
1549 }
1550 ProgramCounter = (WORD)address;
1551 }
1552 }
1553 break;
1554
1555 /*
1556 * Opcode: CNE
1557 * Description: Call on result not Zero
1558 * Flags: - - - - - - - -
1559 * Notes: None
1560 */
1561 case 0x36: //CNE ABSOLUTE ADDRESSING (abs)
1562 HB = fetch();
1563 LB = fetch();
1564 if ((Flags & FLAG_Z) == 0) {
1565 address += (WORD)((WORD)HB << 8) + LB;
1566 if (address >= 0 && address < MEMORY_SIZE) {
1567 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1568 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1569 StackPointer--;
1570 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1571 StackPointer--;
1572 }
1573 ProgramCounter = (WORD)address;
1574 }
1575 }
1576 break;
1577
1578 /*
1579 * Opcode: CEQ
1580 * Description: Call on result equal to Zero
1581 * Flags: - - - - - - - -
1582 * Notes: None
1583 */
1584 case 0x37: //CEQ ABSOLUTE ADDRESSING (abs)
1585 HB = fetch();
1586 LB = fetch();
1587 if ((Flags & FLAG_Z) != 0) {
1588 address += (WORD)((WORD)HB << 8) + LB;
1589 if (address >= 0 && address < MEMORY_SIZE) {
1590 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1591 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1592 StackPointer--;
1593 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1594 StackPointer--;
1595 }
1596 ProgramCounter = (WORD)address;
1597 }
1598 }
1599 break;
1600
1601 /*
1602 * Opcode: CVC
1603 * Description: Call on Overflow clear
1604 * Flags: - - - - - - - -
1605 * Notes: None
1606 */
1607 case 0x38: //CVC ABSOLUTE ADDRESSING (abs)
1608 HB = fetch();
1609 LB = fetch();
1610 if ((Flags & FLAG_V) == 0) {
1611 address += (WORD)((WORD)HB << 8) + LB;
1612 if (address >= 0 && address < MEMORY_SIZE) {
1613 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1614 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1615 StackPointer--;
1616 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1617 StackPointer--;
1618 }
1619 ProgramCounter = (WORD)address;
1620 }
1621 }
1622 break;
1623
1624 /*
1625 * Opcode: CVS
1626 * Description: Call on Overflow set
1627 * Flags: - - - - - - - -
1628 * Notes: None
1629 */
1630 case 0x39: //CVS ABSOLUTE ADDRESSING (abs)
1631 HB = fetch();
1632 LB = fetch();
1633 if ((Flags & FLAG_V) == FLAG_V) {
1634 address += (WORD)((WORD)HB << 8) + LB;
1635 if (address >= 0 && address < MEMORY_SIZE) {
1636 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1637 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1638 StackPointer--;
1639 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1640 StackPointer--;
1641 }
1642 ProgramCounter = (WORD)address;
1643 }
1644 }
1645 break;
1646
1647 /*
1648 * Opcode: CMI
1649 * Description: Call on negative result
1650 * Flags: - - - - - - - -
1651 * Notes: None
1652 */
1653 case 0x3A: //CMI ABSOLUTE ADDRESSING (abs)
1654 HB = fetch();
1655 LB = fetch();
1656 if ((Flags & FLAG_N) != 0) {
1657 address += (WORD)((WORD)HB << 8) + LB;
1658 if (address >= 0 && address < MEMORY_SIZE) {
1659 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1660 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1661 StackPointer--;
1662 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1663 StackPointer--;
1664 }
1665 ProgramCounter = (WORD)address;
1666 }
1667 }
1668 break;
1669
1670 /*
1671 * Opcode: CPL
1672 * Description: Call on positive result
1673 * Flags: - - - - - - - -
1674 * Notes: None
1675 */
1676 case 0x3B: //CPL ABSOLUTE ADDRESSING (abs)
1677 HB = fetch();
1678 LB = fetch();
1679 if ((Flags & FLAG_N) == 0) {
1680 address += (WORD)((WORD)HB << 8) + LB;
1681 if (address >= 0 && address < MEMORY_SIZE) {
1682 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1683 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1684 StackPointer--;
1685 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1686 StackPointer--;
1687 }
1688 ProgramCounter = (WORD)address;
1689 }
1690 }
1691 break;
1692
1693 /*
1694 * Opcode: CHI
1695 * Description: Call on result same or lower
1696 * Flags: - - - - - - - -
1697 * Notes: None
1698 */
1699 case 0x3C: //CHI ABSOLUTE ADDRESSING (abs)
1700 HB = fetch();
1701 LB = fetch();
1702 if ((((Flags & FLAG_C) | ((Flags & FLAG_Z))) != 0)) {
1703 address += (WORD)((WORD)HB << 8) + LB;
1704 if (address >= 0 && address < MEMORY_SIZE) {
1705 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1706 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1707 StackPointer--;
1708 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1709 StackPointer--;
1710 }
1711 ProgramCounter = (WORD)address;
1712 }
1713 }
1714 break;
1715
1716 /*
1717 * Opcode: CLE
1718 * Description: Call on result higher
1719 * Flags: - - - - - - - -
1720 * Notes: None
1721 */
1722 case 0x3D: //CLE ABSOLUTE ADDRESSING (abs)
1723 HB = fetch();
1724 LB = fetch();
1725 if ((((Flags & FLAG_C) | ((Flags & FLAG_Z))) == 0)) {
1726 address += (WORD)((WORD)HB << 8) + LB;
1727 if (address >= 0 && address < MEMORY_SIZE) {
1728 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1729 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1730 StackPointer--;
1731 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1732 StackPointer--;
1733 }
1734 ProgramCounter = (WORD)address;
1735 }
1736 }
1737 break;
1738
1739/*-------------------------------INC AND LOGIC-------------------------------*/
1740 /*
1741 * Opcode: INC
1742 * Description: Increment Memory or Accumulator
1743 * Flags: - - T - T - - -
1744 * Notes: None
1745 */
1746 case 0x44: //INC ABSOLUTE ADDRESSING (abs)
1747 HB = fetch();
1748 LB = fetch();
1749 if (address >= 0 && address < MEMORY_SIZE) {
1750 ++Memory[address];
1751 }
1752 set_flag_n(Memory[address]);
1753 set_flag_z(Memory[address]);
1754 break;
1755
1756 case 0x54: //INC INDEXED ABSOLUTE ADDRESSING (abs, X)
1757 address += IndexRegister;
1758 HB = fetch();
1759 LB = fetch();
1760 address += (WORD)((WORD)HB << 8) + LB;
1761
1762 if (address >= 0 && address < MEMORY_SIZE) {
1763 ++Memory[address];
1764 }
1765 set_flag_n(Memory[address]);
1766 set_flag_z(Memory[address]);
1767 break;
1768
1769 /*
1770 * Opcode: INCA
1771 * Description: Increment Memory or Accumulator
1772 * Flags: - - T - T - - -
1773 * Notes: None
1774 */
1775 case 0x64: //INCA
1776 ++Registers[REGISTER_A];
1777 set_flag_n(Registers[REGISTER_A]);
1778 set_flag_z(Registers[REGISTER_A]);
1779 break;
1780
1781 /*
1782 * Opcode: INX
1783 * Description: Increments register X
1784 * Flags: - - T - - - - -
1785 * Notes: None
1786 */
1787 case 0x1C: //INX
1788 ++IndexRegister;
1789 set_flag_z(IndexRegister);
1790 break;
1791
1792 /*
1793 * Opcode: DEX
1794 * Description: Decrements register X
1795 * Flags: - - T - - - - -
1796 * Notes: None
1797 */
1798 case 0x1B: //DEX
1799 --IndexRegister;
1800 set_flag_z(IndexRegister);
1801 break;
1802
1803 /*
1804 * Opcode: AND
1805 * Description: Register bitwise and with Accumulator
1806 * Flags: - - T - T - - -
1807 * Notes: None
1808 */
1809 case 0x94: //AND A-B
1810 Registers[REGISTER_A] = Registers[REGISTER_A] & Registers[REGISTER_B];
1811 set_flag_n(Registers[REGISTER_A]);
1812 set_flag_z(Registers[REGISTER_A]);
1813 break;
1814
1815 case 0xA4: //AND A-C
1816 Registers[REGISTER_A] = Registers[REGISTER_A] & Registers[REGISTER_C];
1817 set_flag_n(Registers[REGISTER_A]);
1818 set_flag_z(Registers[REGISTER_A]);
1819 break;
1820
1821 case 0xB4: //AND A-D
1822 Registers[REGISTER_A] = Registers[REGISTER_A] & Registers[REGISTER_D];
1823 set_flag_n(Registers[REGISTER_A]);
1824 set_flag_z(Registers[REGISTER_A]);
1825 break;
1826
1827 case 0xC4: //AND A-E
1828 Registers[REGISTER_A] = Registers[REGISTER_A] & Registers[REGISTER_E];
1829 set_flag_n(Registers[REGISTER_A]);
1830 set_flag_z(Registers[REGISTER_A]);
1831 break;
1832
1833 case 0xD4: //AND A-L
1834 Registers[REGISTER_A] = Registers[REGISTER_A] & Registers[REGISTER_L];
1835 set_flag_n(Registers[REGISTER_A]);
1836 set_flag_z(Registers[REGISTER_A]);
1837 break;
1838
1839 case 0xE4: //AND A-H
1840 Registers[REGISTER_A] = Registers[REGISTER_A] & Registers[REGISTER_H];
1841 set_flag_n(Registers[REGISTER_A]);
1842 set_flag_z(Registers[REGISTER_A]);
1843 break;
1844
1845 case 0xF4: //AND A-M
1846 Registers[REGISTER_A] = Registers[REGISTER_A] & Registers[REGISTER_M];
1847 set_flag_n(Registers[REGISTER_A]);
1848 set_flag_z(Registers[REGISTER_A]);
1849 break;
1850
1851 /*
1852 * Opcode: BT
1853 * Description: Register Bit tested with Accumulator
1854 * Flags: - - T - T - - -
1855 * Notes: None
1856 */
1857 case 0x96: //BT A-B
1858 data = Registers[REGISTER_A] & Registers[REGISTER_B];
1859 set_flag_n(data);
1860 set_flag_z(data);
1861 break;
1862
1863 case 0xA6: //BT A-C
1864 data = Registers[REGISTER_A] & Registers[REGISTER_C];
1865 set_flag_n(data);
1866 set_flag_z(data);
1867 break;
1868
1869 case 0xB6: //BT A-D
1870 data = Registers[REGISTER_A] & Registers[REGISTER_D];
1871 set_flag_n(data);
1872 set_flag_z(data);
1873 break;
1874
1875 case 0xC6: //BT A-E
1876 data = Registers[REGISTER_A] & Registers[REGISTER_E];
1877 set_flag_n(data);
1878 set_flag_z(data);
1879 break;
1880
1881 case 0xD6: //BT A-L
1882 data = Registers[REGISTER_A] & Registers[REGISTER_L];
1883 set_flag_n(data);
1884 set_flag_z(data);
1885 break;
1886
1887 case 0xE6: //BT A-H
1888 data = Registers[REGISTER_A] & Registers[REGISTER_H];
1889 set_flag_n(data);
1890 set_flag_z(data);
1891 break;
1892
1893 case 0xF6: //BT A-M
1894 data = Registers[REGISTER_A] & Registers[REGISTER_M];
1895 set_flag_n(data);
1896 set_flag_z(data);
1897 break;
1898
1899/*---------------------------------ARITHMATIC--------------------------------*/
1900 /*
1901 * Opcode: SBC
1902 * Description: Register subtracted to Accumulator with Carry
1903 * Flags: - - T T T - - T
1904 * Notes: None
1905 */
1906 case 0x91: //SBC A-B
1907 temp_word = (WORD)Registers[REGISTER_A] - (WORD)Registers[REGISTER_B];
1908
1909 if ((Flags & FLAG_C) != 0) {
1910 temp_word++;
1911 }
1912
1913 if (temp_word >= 0x100) {
1914 Flags = Flags | FLAG_C; //Set carry flag
1915 }
1916 else {
1917 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
1918 }
1919
1920 set_flag_n((BYTE)temp_word);
1921 set_flag_z((BYTE)temp_word);
1922 set_flag_v(REGISTER_A, REGISTER_B, (BYTE)temp_word);
1923 Registers[REGISTER_A] = (BYTE)temp_word;
1924 break;
1925
1926 case 0xA1: //SBC A-C
1927 temp_word = (WORD)Registers[REGISTER_A] - (WORD)Registers[REGISTER_C];
1928
1929 if ((Flags & FLAG_C) != 0) {
1930 temp_word++;
1931 }
1932
1933 if (temp_word >= 0x100) {
1934 Flags = Flags | FLAG_C; //Set carry flag
1935 }
1936 else {
1937 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
1938 }
1939
1940 set_flag_n((BYTE)temp_word);
1941 set_flag_z((BYTE)temp_word);
1942 set_flag_v(REGISTER_A, REGISTER_C, (BYTE)temp_word);
1943 Registers[REGISTER_A] = (BYTE)temp_word;
1944 break;
1945
1946 case 0xB1: //SBC A-D
1947 temp_word = (WORD)Registers[REGISTER_A] - (WORD)Registers[REGISTER_D];
1948
1949 if ((Flags & FLAG_C) != 0) {
1950 temp_word++;
1951 }
1952
1953 if (temp_word >= 0x100) {
1954 Flags = Flags | FLAG_C; //Set carry flag
1955 }
1956 else {
1957 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
1958 }
1959
1960 set_flag_n((BYTE)temp_word);
1961 set_flag_z((BYTE)temp_word);
1962 set_flag_v(REGISTER_A, REGISTER_D, (BYTE)temp_word);
1963 Registers[REGISTER_A] = (BYTE)temp_word;
1964 break;
1965
1966 case 0xC1: //SBC A-E
1967 temp_word = (WORD)Registers[REGISTER_A] - (WORD)Registers[REGISTER_E];
1968
1969 if ((Flags & FLAG_C) != 0) {
1970 temp_word++;
1971 }
1972
1973 if (temp_word >= 0x100) {
1974 Flags = Flags | FLAG_C; //Set carry flag
1975 }
1976 else {
1977 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
1978 }
1979
1980 set_flag_n((BYTE)temp_word);
1981 set_flag_z((BYTE)temp_word);
1982 set_flag_v(REGISTER_A, REGISTER_E, (BYTE)temp_word);
1983 Registers[REGISTER_A] = (BYTE)temp_word;
1984 break;
1985
1986 case 0xD1: //SBC A-L
1987 temp_word = (WORD)Registers[REGISTER_A] - (WORD)Registers[REGISTER_L];
1988
1989 if ((Flags & FLAG_C) != 0) {
1990 temp_word++;
1991 }
1992
1993 if (temp_word >= 0x100) {
1994 Flags = Flags | FLAG_C; //Set carry flag
1995 }
1996 else {
1997 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
1998 }
1999
2000 set_flag_n((BYTE)temp_word);
2001 set_flag_z((BYTE)temp_word);
2002 set_flag_v(REGISTER_A, REGISTER_L, (BYTE)temp_word);
2003 Registers[REGISTER_A] = (BYTE)temp_word;
2004 break;
2005
2006 case 0xE1: //SBC A-H
2007 temp_word = (WORD)Registers[REGISTER_A] - (WORD)Registers[REGISTER_H];
2008
2009 if ((Flags & FLAG_C) != 0) {
2010 temp_word++;
2011 }
2012
2013 if (temp_word >= 0x100) {
2014 Flags = Flags | FLAG_C; //Set carry flag
2015 }
2016 else {
2017 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
2018 }
2019
2020 set_flag_n((BYTE)temp_word);
2021 set_flag_z((BYTE)temp_word);
2022 set_flag_v(REGISTER_A, REGISTER_H, (BYTE)temp_word);
2023 Registers[REGISTER_A] = (BYTE)temp_word;
2024 break;
2025
2026 case 0xF1: //SBC A-M
2027 temp_word = (WORD)Registers[REGISTER_A] - (WORD)Registers[REGISTER_M];
2028
2029 if ((Flags & FLAG_C) != 0) {
2030 temp_word++;
2031 }
2032
2033 if (temp_word >= 0x100) {
2034 Flags = Flags | FLAG_C; //Set carry flag
2035 }
2036 else {
2037 Flags = Flags & (0xFF - FLAG_C); //Clear carry flag
2038 }
2039
2040 set_flag_n((BYTE)temp_word);
2041 set_flag_z((BYTE)temp_word);
2042 set_flag_v(REGISTER_A, REGISTER_M, (BYTE)temp_word);
2043 Registers[REGISTER_A] = (BYTE)temp_word;
2044 break;
2045
2046 /*
2047 * Opcode: IOR
2048 * Description: Register bitwise inclusive or with Accumulator
2049 * Flags: - - T - T - - -
2050 * Notes: None
2051 */
2052 case 0x93: //IOR A-B
2053 Registers[REGISTER_A] = Registers[REGISTER_A] | Registers[REGISTER_B];
2054 set_flag_n(Registers[REGISTER_A]);
2055 set_flag_z(Registers[REGISTER_A]);
2056 break;
2057
2058 case 0xA3: //IOR A-C
2059 Registers[REGISTER_A] = Registers[REGISTER_A] | Registers[REGISTER_C];
2060 set_flag_n(Registers[REGISTER_A]);
2061 set_flag_z(Registers[REGISTER_A]);
2062 break;
2063
2064 case 0xB3: //IOR A-D
2065 Registers[REGISTER_A] = Registers[REGISTER_A] | Registers[REGISTER_D];
2066 set_flag_n(Registers[REGISTER_A]);
2067 set_flag_z(Registers[REGISTER_A]);
2068 break;
2069
2070 case 0xC3: //IOR A-E
2071 Registers[REGISTER_A] = Registers[REGISTER_A] | Registers[REGISTER_E];
2072 set_flag_n(Registers[REGISTER_A]);
2073 set_flag_z(Registers[REGISTER_A]);
2074 break;
2075
2076 case 0xD3: //IOR A-L
2077 Registers[REGISTER_A] = Registers[REGISTER_A] | Registers[REGISTER_L];
2078 set_flag_n(Registers[REGISTER_A]);
2079 set_flag_z(Registers[REGISTER_A]);
2080 break;
2081
2082 case 0xE3: //IOR A-H
2083 Registers[REGISTER_A] = Registers[REGISTER_A] | Registers[REGISTER_H];
2084 set_flag_n(Registers[REGISTER_A]);
2085 set_flag_z(Registers[REGISTER_A]);
2086 break;
2087
2088 case 0xF3: //IOR A-M
2089 Registers[REGISTER_A] = Registers[REGISTER_A] | Registers[REGISTER_M];
2090 set_flag_n(Registers[REGISTER_A]);
2091 set_flag_z(Registers[REGISTER_A]);
2092 break;
2093
2094 /*
2095 * Opcode: XOR
2096 * Description: Register bitwise exclusive or with Accumulator
2097 * Flags: - - T - T - - -
2098 * Notes: None
2099 */
2100 case 0x95: //XOR A-B
2101 Registers[REGISTER_A] = Registers[REGISTER_A] ^ Registers[REGISTER_B];
2102 set_flag_n(Registers[REGISTER_A]);
2103 set_flag_z(Registers[REGISTER_A]);
2104 break;
2105
2106 case 0xA5: //XOR A-C
2107 Registers[REGISTER_A] = Registers[REGISTER_A] ^ Registers[REGISTER_C];
2108 set_flag_n(Registers[REGISTER_A]);
2109 set_flag_z(Registers[REGISTER_A]);
2110 break;
2111
2112 case 0xB5: //XOR A-D
2113 Registers[REGISTER_A] = Registers[REGISTER_A] ^ Registers[REGISTER_D];
2114 set_flag_n(Registers[REGISTER_A]);
2115 set_flag_z(Registers[REGISTER_A]);
2116 break;
2117
2118 case 0xC5: //XOR A-E
2119 Registers[REGISTER_A] = Registers[REGISTER_A] ^ Registers[REGISTER_E];
2120 set_flag_n(Registers[REGISTER_A]);
2121 set_flag_z(Registers[REGISTER_A]);
2122 break;
2123
2124 case 0xD5: //XOR A-L
2125 Registers[REGISTER_A] = Registers[REGISTER_A] ^ Registers[REGISTER_L];
2126 set_flag_n(Registers[REGISTER_A]);
2127 set_flag_z(Registers[REGISTER_A]);
2128 break;
2129
2130 case 0xE5: //XOR A-H
2131 Registers[REGISTER_A] = Registers[REGISTER_A] ^ Registers[REGISTER_H];
2132 set_flag_n(Registers[REGISTER_A]);
2133 set_flag_z(Registers[REGISTER_A]);
2134 break;
2135
2136 case 0xF5: //XOR A-M
2137 Registers[REGISTER_A] = Registers[REGISTER_A] ^ Registers[REGISTER_M];
2138 set_flag_n(Registers[REGISTER_A]);
2139 set_flag_z(Registers[REGISTER_A]);
2140 break;
2141
2142
2143 /*
2144 * Opcode: NOTA
2145 * Description: Negate Memory or Accumulator
2146 * Flags: - - T - T - - T
2147 * Notes: None
2148 */
2149 case 0x6A: //NOTA
2150 break;
2151
2152
2153 /*
2154 * Opcode: DEC
2155 * Description: Decrement Memory or Accumulator
2156 * Flags: - - T - T - - -
2157 * Notes: None
2158 */
2159 case 0x45: //DEC ABSOLUTE ADDRESSING (abs)
2160 HB = fetch();
2161 LB = fetch();
2162 address += (WORD)((WORD)HB << 8) + LB;
2163
2164 Registers[REGISTER_A]--;
2165 set_flag_z(Registers[REGISTER_A]);
2166 set_flag_n(Registers[REGISTER_A]);
2167 break;
2168
2169 case 0x55: //DEC INDEXED ABSOLUTE ADDRESSING (abs, X)
2170 address += IndexRegister;
2171 HB = fetch();
2172 LB = fetch();
2173 address += (WORD)((WORD)HB << 8) + LB;
2174
2175 Registers[REGISTER_A]--;
2176 set_flag_z(Registers[REGISTER_A]);
2177 set_flag_n(Registers[REGISTER_A]);
2178 break;
2179
2180 /*
2181 * Opcode: DECA
2182 * Description: Decrement Memory or Accumulator
2183 * Flags: - - T - T - - -
2184 * Notes: None
2185 */
2186 case 0x65: //DACA
2187 Registers[REGISTER_A]--;
2188 set_flag_z(Registers[REGISTER_A]);
2189 set_flag_n(Registers[REGISTER_A]);
2190 break;
2191
2192 /*
2193 * Opcode: TST
2194 * Description: Bit test Memory or Accumulator
2195 * Flags: - - T - T - - -
2196 * Notes: None
2197 */
2198 case 0x43: //TST ABSOLUTE ADDRESSING (abs)
2199 HB = fetch();
2200 LB = fetch();
2201 address += (WORD)((WORD)HB << 8) + LB;
2202
2203 Registers[REGISTER_A]--;
2204 set_flag_z(Registers[REGISTER_A]);
2205 set_flag_n(Registers[REGISTER_A]);
2206 break;
2207
2208 case 0x53: //TST INDEXED ABSOLUTE ADDRESSING (abs, X)
2209 address += IndexRegister;
2210 HB = fetch();
2211 LB = fetch();
2212 address += (WORD)((WORD)HB << 8) + LB;
2213
2214 Registers[REGISTER_A]--;
2215 set_flag_z(Registers[REGISTER_A]);
2216 set_flag_n(Registers[REGISTER_A]);
2217 break;
2218
2219 /*
2220 * Opcode: TSTA
2221 * Description: Bit test Memory or Accumulator
2222 * Flags: - - T - T - - -
2223 * Notes: None
2224 */
2225 case 0x63: //TSTA
2226 Registers[REGISTER_A]--;
2227 set_flag_z(Registers[REGISTER_A]);
2228 set_flag_n(Registers[REGISTER_A]);
2229 break;
2230
2231 /*
2232 * Opcode: SAL
2233 * Description: Arithmetic shift left Memory or Accumulator
2234 * Flags: - - T - T - - -
2235 * Notes: None
2236 */
2237 case 0x48: //SAL ABSOLUTE ADDRESSING (abs)
2238 HB = fetch();
2239 LB = fetch();
2240 address += (WORD)((WORD)HB << 8) + LB;
2241 break;
2242
2243 case 0x58: //SAL INDEXED ABSOLUTE ADDRESSING (abs, X)
2244 address += IndexRegister;
2245 HB = fetch();
2246 LB = fetch();
2247 address += (WORD)((WORD)HB << 8) + LB;
2248 break;
2249
2250 /*
2251 * Opcode: SALA
2252 * Description: Arithmetic shift left Memory or Accumulator
2253 * Flags: - - T - T - - T
2254 * Notes: None
2255 */
2256 case 0x68: // SALA
2257 if ((Registers[REGISTER_A] & 0x01) == 0x01) {
2258 Flags = Flags | FLAG_C;
2259 }
2260 else {
2261 Flags = Flags & (0xFF - FLAG_C);
2262 }
2263
2264 Registers[REGISTER_A] = (Registers[REGISTER_A] << 1) & 0x7F;
2265
2266 if ((Flags & FLAG_N) == FLAG_N) {
2267 Registers[REGISTER_A] = Registers[REGISTER_A] | 0x80;
2268 }
2269 break;
2270
2271
2272
2273 /*
2274 * Opcode: ASR
2275 * Description: Arithmetic shift right Memory or Accumulator
2276 * Flags: - - T - T - - -
2277 * Notes: None
2278 */
2279 case 0x49: //ASR ABSOLUTE ADDRESSING (abs)
2280
2281 break;
2282
2283 case 0x59: //ASR INDEXED ABSOLUTE ADDRESSING (abs, X)
2284
2285 break;
2286
2287 /*
2288 * Opcode: ASRA
2289 * Description: Arithmetic shift right Memory or Accumulator
2290 * Flags: - - T - T - - T
2291 * Notes: None
2292 */
2293 case 0x69: //ASRA
2294 if ((Registers[REGISTER_A] & 0x01) == 0x01) {
2295 Flags = Flags | FLAG_C;
2296 }
2297 else {
2298 Flags = Flags & (0xFF - FLAG_C);
2299 }
2300
2301 Registers[REGISTER_A] = (Registers[REGISTER_A] >> 1) & 0x7F;
2302
2303 if ((Flags & FLAG_N) == FLAG_N) {
2304 Registers[REGISTER_A] = Registers[REGISTER_A] | 0x80;
2305 }
2306
2307 set_flag_n(Registers[REGISTER_A]);
2308 set_flag_z(Registers[REGISTER_A]);
2309 break;
2310
2311 break;
2312
2313/*-----------------------------------ROTATE----------------------------------*/
2314 /*
2315 * Opcode: RCLA
2316 * Description: Rotate left through carry Memory or Accumulator
2317 * Flags: - - T - T - - T
2318 * Notes: None
2319 */
2320 case 0x67: // RCLA
2321 saved_flags = Flags;
2322
2323 if ((Registers[REGISTER_A] & 0x80) == 0x80) {
2324 Flags = Flags | FLAG_C;
2325 }
2326 else {
2327 Flags = Flags & (0xFF - FLAG_C);
2328 }
2329
2330 Registers[REGISTER_A] = (Registers[REGISTER_A] << 1) & 0xFE;
2331
2332 if ((saved_flags & FLAG_C) == FLAG_C) {
2333 Registers[REGISTER_A] = Registers[REGISTER_A] | 0x01;
2334 }
2335
2336 set_flag_n(Registers[REGISTER_A]);
2337 set_flag_z(Registers[REGISTER_A]);
2338 break;
2339 }
2340}
2341
2342void Group_2_Move(BYTE opcode) {
2343 WORD address = 0;
2344
2345 BYTE source = opcode >> 4;
2346 BYTE dest = opcode & 0x0F;
2347 int destReg = 0;
2348 int sourceReg = 0;
2349/*---------------------------------MOVE DEST---------------------------------*/
2350 switch (dest) {
2351 case 0x08:
2352 destReg = REGISTER_A;
2353 break;
2354
2355 case 0x09:
2356 destReg = REGISTER_B;
2357 break;
2358
2359 case 0x0A:
2360 destReg = REGISTER_C;
2361 break;
2362
2363 case 0x0B:
2364 destReg = REGISTER_D;
2365 break;
2366
2367 case 0x0C:
2368 destReg = REGISTER_E;
2369 break;
2370
2371 case 0x0D:
2372 destReg = REGISTER_L;
2373 break;
2374
2375 case 0x0E:
2376 destReg = REGISTER_H;
2377 break;
2378
2379 case 0x0F:
2380 destReg = REGISTER_M;
2381 break;
2382 }
2383
2384/*--------------------------------MOVE SOURCE--------------------------------*/
2385 switch (source) {
2386 case 0x07:
2387 sourceReg = REGISTER_A;
2388 break;
2389
2390 case 0x08:
2391 sourceReg = REGISTER_B;
2392 break;
2393
2394 case 0x09:
2395 sourceReg = REGISTER_C;
2396 break;
2397
2398 case 0x0A:
2399 sourceReg = REGISTER_D;
2400 break;
2401
2402 case 0x0B:
2403 sourceReg = REGISTER_E;
2404 break;
2405
2406 case 0x0C:
2407 sourceReg = REGISTER_L;
2408 break;
2409
2410 case 0x0D:
2411 sourceReg = REGISTER_H;
2412 break;
2413
2414 case 0x0E:
2415 sourceReg = REGISTER_M;
2416 break;
2417 }
2418
2419 if (sourceReg == REGISTER_M) {
2420 address = Registers[REGISTER_L];
2421 address += (WORD)Registers[REGISTER_H] << 8;
2422 Registers[destReg] = Memory[address];
2423 }
2424 Registers[destReg] = Registers[sourceReg];
2425
2426 if (destReg == REGISTER_M) {
2427 address = Registers[REGISTER_L];
2428 address += (WORD)Registers[REGISTER_H] << 8;
2429 Memory[address] = Registers[REGISTER_M];
2430 }
2431}
2432
2433void execute(BYTE opcode) {
2434 if (((opcode >= 0x78) && (opcode <= 0x7F)) ||
2435 ((opcode >= 0x88) && (opcode <= 0x8F)) ||
2436 ((opcode >= 0x98) && (opcode <= 0x9F)) ||
2437 ((opcode >= 0xA8) && (opcode <= 0xAF)) ||
2438 ((opcode >= 0xB8) && (opcode <= 0xBF)) ||
2439 ((opcode >= 0xC8) && (opcode <= 0xCF)) ||
2440 ((opcode >= 0xD8) && (opcode <= 0xDF)) ||
2441 ((opcode >= 0xE8) && (opcode <= 0xEF))) {
2442 Group_2_Move(opcode);
2443 }
2444 else {
2445 Group_1(opcode);
2446 }
2447}
2448
2449void emulate() {
2450 BYTE opcode;
2451
2452 ProgramCounter = 0;
2453 halt = false;
2454 memory_in_range = true;
2455
2456 int sanity = 0;
2457
2458 printf(" A B C D E L H X SP\n");
2459
2460 while ((!halt) && (memory_in_range)) {
2461 printf("%04X ", ProgramCounter); // Print current address
2462 opcode = fetch();
2463 execute(opcode);
2464
2465 sanity++;
2466 if (sanity > 500) halt = true;
2467
2468 printf("%s ", opcode_mneumonics[opcode]); // Print current opcode
2469
2470 printf("%02X ", Registers[REGISTER_A]);
2471 printf("%02X ", Registers[REGISTER_B]);
2472 printf("%02X ", Registers[REGISTER_C]);
2473 printf("%02X ", Registers[REGISTER_D]);
2474 printf("%02X ", Registers[REGISTER_E]);
2475 printf("%02X ", Registers[REGISTER_L]);
2476 printf("%02X ", Registers[REGISTER_H]);
2477 printf("%04X ", IndexRegister);
2478 printf("%04X ", StackPointer); // Print Stack Pointer
2479
2480 if ((Flags & FLAG_I) == FLAG_I) {
2481 printf("I=1 ");
2482 }
2483 else {
2484 printf("I=0 ");
2485 }
2486 if ((Flags & FLAG_N) == FLAG_N) {
2487 printf("N=1 ");
2488 }
2489 else {
2490 printf("N=0 ");
2491 }
2492 if ((Flags & FLAG_V) == FLAG_V) {
2493 printf("V=1 ");
2494 }
2495 else {
2496 printf("V=0 ");
2497 }
2498 if ((Flags & FLAG_Z) == FLAG_Z) {
2499 printf("Z=1 ");
2500 }
2501 else {
2502 printf("Z=0 ");
2503 }
2504 if ((Flags & FLAG_C) == FLAG_C) {
2505 printf("C=1 ");
2506 }
2507 else {
2508 printf("C=0 ");
2509 }
2510
2511 printf("\n"); // New line
2512 }
2513
2514 printf("\n"); // New line
2515}
2516
2517////////////////////////////////////////////////////////////////////////////////
2518// Simulator/Emulator (End) //
2519////////////////////////////////////////////////////////////////////////////////
2520
2521void initialise_filenames() {
2522 int i;
2523
2524 for (i = 0; i < MAX_FILENAME_SIZE; i++) {
2525 hex_file[i] = '\0';
2526 trc_file[i] = '\0';
2527 }
2528}
2529
2530int find_dot_position(char* filename) {
2531 int dot_position;
2532 int i;
2533 char chr;
2534
2535 dot_position = 0;
2536 i = 0;
2537 chr = filename[i];
2538
2539 while (chr != '\0') {
2540 if (chr == '.') {
2541 dot_position = i;
2542 }
2543 i++;
2544 chr = filename[i];
2545 }
2546
2547 return (dot_position);
2548}
2549
2550int find_end_position(char* filename) {
2551 int end_position;
2552 int i;
2553 char chr;
2554
2555 end_position = 0;
2556 i = 0;
2557 chr = filename[i];
2558
2559 while (chr != '\0') {
2560 end_position = i;
2561 i++;
2562 chr = filename[i];
2563 }
2564
2565 return (end_position);
2566}
2567
2568bool file_exists(char* filename) {
2569 bool exists;
2570 FILE* ifp;
2571
2572 exists = false;
2573
2574 if ((ifp = fopen(filename, "r")) != NULL) {
2575 exists = true;
2576
2577 fclose(ifp);
2578 }
2579
2580 return (exists);
2581}
2582
2583void create_file(char* filename) {
2584 FILE* ofp;
2585
2586 if ((ofp = fopen(filename, "w")) != NULL) {
2587 fclose(ofp);
2588 }
2589}
2590
2591bool getline(FILE* fp, char* buffer) {
2592 bool rc;
2593 bool collect;
2594 char c;
2595 int i;
2596
2597 rc = false;
2598 collect = true;
2599
2600 i = 0;
2601 while (collect) {
2602 c = getc(fp);
2603
2604 switch (c) {
2605 case EOF:
2606 if (i > 0) {
2607 rc = true;
2608 }
2609 collect = false;
2610 break;
2611
2612 case '\n':
2613 if (i > 0) {
2614 rc = true;
2615 collect = false;
2616 buffer[i] = '\0';
2617 }
2618 break;
2619
2620 default:
2621 buffer[i] = c;
2622 i++;
2623 break;
2624 }
2625 }
2626
2627 return (rc);
2628}
2629
2630void load_and_run(int args, _TCHAR** argv) {
2631 char chr;
2632 int ln;
2633 int dot_position;
2634 int end_position;
2635 long i;
2636 FILE* ifp;
2637 long address;
2638 long load_at;
2639 int code;
2640
2641 // Prompt for the .hex file
2642
2643 printf("\n");
2644 printf("Enter the hex filename (.hex): ");
2645
2646 if (args == 2) {
2647 ln = 0;
2648 chr = argv[1][ln];
2649 while (chr != '\0') {
2650 if (ln < MAX_FILENAME_SIZE) {
2651 hex_file[ln] = chr;
2652 trc_file[ln] = chr;
2653 ln++;
2654 }
2655 chr = argv[1][ln];
2656 }
2657 }
2658 else {
2659 ln = 0;
2660 chr = '\0';
2661 while (chr != '\n') {
2662 chr = getchar();
2663
2664 switch (chr) {
2665 case '\n':
2666 break;
2667 default:
2668 if (ln < MAX_FILENAME_SIZE) {
2669 hex_file[ln] = chr;
2670 trc_file[ln] = chr;
2671 ln++;
2672 }
2673 break;
2674 }
2675 }
2676
2677 }
2678 // Tidy up the file names
2679
2680 dot_position = find_dot_position(hex_file);
2681 if (dot_position == 0) {
2682 end_position = find_end_position(hex_file);
2683
2684 hex_file[end_position + 1] = '.';
2685 hex_file[end_position + 2] = 'h';
2686 hex_file[end_position + 3] = 'e';
2687 hex_file[end_position + 4] = 'x';
2688 hex_file[end_position + 5] = '\0';
2689 }
2690 else {
2691 hex_file[dot_position + 0] = '.';
2692 hex_file[dot_position + 1] = 'h';
2693 hex_file[dot_position + 2] = 'e';
2694 hex_file[dot_position + 3] = 'x';
2695 hex_file[dot_position + 4] = '\0';
2696 }
2697
2698 dot_position = find_dot_position(trc_file);
2699 if (dot_position == 0) {
2700 end_position = find_end_position(trc_file);
2701
2702 trc_file[end_position + 1] = '.';
2703 trc_file[end_position + 2] = 't';
2704 trc_file[end_position + 3] = 'r';
2705 trc_file[end_position + 4] = 'c';
2706 trc_file[end_position + 5] = '\0';
2707 }
2708 else {
2709 trc_file[dot_position + 0] = '.';
2710 trc_file[dot_position + 1] = 't';
2711 trc_file[dot_position + 2] = 'r';
2712 trc_file[dot_position + 3] = 'c';
2713 trc_file[dot_position + 4] = '\0';
2714 }
2715
2716 if (file_exists(hex_file)) {
2717 // Clear Registers and Memory
2718
2719 Registers[REGISTER_A] = 0;
2720 Registers[REGISTER_B] = 0;
2721 Registers[REGISTER_C] = 0;
2722 Registers[REGISTER_D] = 0;
2723 Registers[REGISTER_E] = 0;
2724 Registers[REGISTER_L] = 0;
2725 Registers[REGISTER_H] = 0;
2726 IndexRegister = 0;
2727 Flags = 0;
2728 ProgramCounter = 0;
2729 StackPointer = 0;
2730
2731 for (i = 0; i < MEMORY_SIZE; i++) {
2732 Memory[i] = 0x00;
2733 }
2734
2735 // Load hex file
2736
2737 if ((ifp = fopen(hex_file, "r")) != NULL) {
2738 printf("Loading file...\n\n");
2739
2740 load_at = 0;
2741
2742 while (getline(ifp, InputBuffer)) {
2743 if (sscanf(InputBuffer, "L=%x", &address) == 1) {
2744 load_at = address;
2745 }
2746 else if (sscanf(InputBuffer, "%x", &code) == 1) {
2747 if ((load_at >= 0) && (load_at <= MEMORY_SIZE)) {
2748 Memory[load_at] = (BYTE)code;
2749 }
2750 load_at++;
2751 }
2752 else {
2753 printf("ERROR> Failed to load instruction: %s \n", InputBuffer);
2754 }
2755 }
2756
2757 fclose(ifp);
2758 }
2759
2760 // Emulate
2761
2762 emulate();
2763 }
2764 else {
2765 printf("\n");
2766 printf("ERROR> Input file %s does not exist!\n", hex_file);
2767 printf("\n");
2768 }
2769}
2770
2771void building(int args, _TCHAR** argv) {
2772 char buffer[1024];
2773 load_and_run(args, argv);
2774 sprintf(buffer, "0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X",
2775 Memory[TEST_ADDRESS_1],
2776 Memory[TEST_ADDRESS_2],
2777 Memory[TEST_ADDRESS_3],
2778 Memory[TEST_ADDRESS_4],
2779 Memory[TEST_ADDRESS_5],
2780 Memory[TEST_ADDRESS_6],
2781 Memory[TEST_ADDRESS_7],
2782 Memory[TEST_ADDRESS_8],
2783 Memory[TEST_ADDRESS_9],
2784 Memory[TEST_ADDRESS_10],
2785 Memory[TEST_ADDRESS_11],
2786 Memory[TEST_ADDRESS_12]
2787 );
2788 sendto(sock, buffer, strlen(buffer), 0, (SOCKADDR*)&server_addr, sizeof(SOCKADDR));
2789}
2790
2791void test_and_mark() {
2792 char buffer[1024];
2793 bool testing_complete;
2794 int len = sizeof(SOCKADDR);
2795 char chr;
2796 int i;
2797 int j;
2798 bool end_of_program;
2799 long address;
2800 long load_at;
2801 int code;
2802 int mark;
2803 int passed;
2804
2805 printf("\n");
2806 printf("Automatic Testing and Marking\n");
2807 printf("\n");
2808
2809 testing_complete = false;
2810
2811 sprintf(buffer, "Test Student %s", STUDENT_NUMBER);
2812 sendto(sock, buffer, strlen(buffer), 0, (SOCKADDR*)&server_addr, sizeof(SOCKADDR));
2813
2814 while (!testing_complete) {
2815 memset(buffer, '\0', sizeof(buffer));
2816
2817 if (recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (SOCKADDR*)&client_addr, &len) != SOCKET_ERROR) {
2818 printf("Incoming Data: %s \n", buffer);
2819
2820 //if (strcmp(buffer, "Testing complete") == 1)
2821 if (sscanf(buffer, "Testing complete %d", &mark) == 1) {
2822 testing_complete = true;
2823 printf("Current mark = %d\n", mark, "%d\n/60");
2824
2825 }
2826 else if (sscanf(buffer, "Tests passed %d", &passed) == 1) {
2827 //testing_complete = true;
2828 printf("Passed = %d\n", passed);
2829
2830 }
2831 else if (strcmp(buffer, "Error") == 0) {
2832 printf("ERROR> Testing abnormally terminated\n");
2833 testing_complete = true;
2834 }
2835 else {
2836
2837 // Clear Registers and Memory
2838 Registers[REGISTER_A] = 0;
2839 Registers[REGISTER_B] = 0;
2840 Registers[REGISTER_C] = 0;
2841 Registers[REGISTER_D] = 0;
2842 Registers[REGISTER_E] = 0;
2843 Registers[REGISTER_L] = 0;
2844 Registers[REGISTER_H] = 0;
2845 IndexRegister = 0;
2846 Flags = 0;
2847 ProgramCounter = 0;
2848 StackPointer = 0;
2849 for (i = 0; i < MEMORY_SIZE; i++) {
2850 Memory[i] = 0;
2851 }
2852
2853 // Load hex file
2854
2855 i = 0;
2856 j = 0;
2857 load_at = 0;
2858 end_of_program = false;
2859 FILE* ofp;
2860 fopen_s(&ofp, "branch.txt", "a");
2861
2862 while (!end_of_program) {
2863 chr = buffer[i];
2864 switch (chr) {
2865 case '\0':
2866 end_of_program = true;
2867
2868 case ',':
2869 if (sscanf(InputBuffer, "L=%x", &address) == 1) {
2870 load_at = address;
2871 }
2872 else if (sscanf(InputBuffer, "%x", &code) == 1) {
2873 if ((load_at >= 0) && (load_at <= MEMORY_SIZE)) {
2874 Memory[load_at] = (BYTE)code;
2875 fprintf(ofp, "%02X\n", (BYTE)code);
2876 }
2877 load_at++;
2878 }
2879 else {
2880 printf("ERROR> Failed to load instruction: %s \n", InputBuffer);
2881 }
2882 j = 0;
2883 break;
2884
2885 default:
2886 InputBuffer[j] = chr;
2887 j++;
2888 break;
2889 }
2890 i++;
2891 }
2892 fclose(ofp);
2893 // Emulate
2894
2895 if (load_at > 1) {
2896 emulate();
2897 // Send and store results
2898 sprintf(buffer, "%02X%02X %02X%02X %02X%02X %02X%02X %02X%02X %02X%02X",
2899 Memory[TEST_ADDRESS_1],
2900 Memory[TEST_ADDRESS_2],
2901 Memory[TEST_ADDRESS_3],
2902 Memory[TEST_ADDRESS_4],
2903 Memory[TEST_ADDRESS_5],
2904 Memory[TEST_ADDRESS_6],
2905 Memory[TEST_ADDRESS_7],
2906 Memory[TEST_ADDRESS_8],
2907 Memory[TEST_ADDRESS_9],
2908 Memory[TEST_ADDRESS_10],
2909 Memory[TEST_ADDRESS_11],
2910 Memory[TEST_ADDRESS_12]
2911 );
2912 sendto(sock, buffer, strlen(buffer), 0, (SOCKADDR*)&server_addr, sizeof(SOCKADDR));
2913 }
2914 }
2915 }
2916 }
2917}
2918
2919int _tmain(int argc, _TCHAR* argv[]) {
2920 char chr;
2921 char dummy;
2922
2923 printf("\n");
2924 printf("Microprocessor Emulator\n");
2925 printf("UWE Computer and Network Systems Assignment 1\n");
2926 printf("\n");
2927
2928 initialise_filenames();
2929
2930 if (WSAStartup(MAKEWORD(2, 2), &data) != 0) return (0);
2931
2932 sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Here we create our socket, which will be a UDP socket (SOCK_DGRAM).
2933 if (!sock) {
2934 // Creation failed!
2935 }
2936
2937 memset(&server_addr, 0, sizeof(SOCKADDR_IN));
2938 server_addr.sin_family = AF_INET;
2939 server_addr.sin_addr.s_addr = inet_addr(IP_ADDRESS_SERVER);
2940 server_addr.sin_port = htons(PORT_SERVER);
2941
2942 memset(&client_addr, 0, sizeof(SOCKADDR_IN));
2943 client_addr.sin_family = AF_INET;
2944 client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
2945 client_addr.sin_port = htons(PORT_CLIENT);
2946
2947 chr = '\0';
2948 while ((chr != 'e') && (chr != 'E')) {
2949 printf("\n");
2950 printf("Please select option\n");
2951 printf("L - Load and run a hex file\n");
2952 printf("T - Have the server test and mark your emulator\n");
2953 printf("E - Exit\n");
2954 if (argc == 2) {
2955 building(argc, argv);
2956 exit(0);
2957 }
2958 printf("Enter option: ");
2959 chr = getchar();
2960 if (chr != 0x0A) {
2961 dummy = getchar(); // read in the <CR>
2962 }
2963 printf("\n");
2964
2965 switch (chr) {
2966 case 'L':
2967 case 'l':
2968 load_and_run(argc, argv);
2969 break;
2970
2971 case 'T':
2972 case 't':
2973 test_and_mark();
2974 break;
2975
2976 default:
2977 break;
2978 }
2979 }
2980
2981 closesocket(sock);
2982 WSACleanup();
2983
2984 return 0;
2985}