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