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