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