· 8 years ago · Feb 21, 2018, 01:02 PM
1#include "stdafx.h"
2#include <winsock2.h>
3
4#pragma comment(lib, "wsock32.lib")
5
6#define STUDENT_NUMBER "17043938"
7#define IP_ADDRESS_SERVER "127.0.0.1"
8
9#define PORT_SERVER 0x1984 //We define a port that we are going to use.
10#define PORT_CLIENT 0x1985 //We define a port that we are going to use.
11
12#define WORD unsigned short
13#define DWORD unsigned long
14#define BYTE unsigned char
15
16#define MAX_FILENAME_SIZE 500
17#define MAX_BUFFER_SIZE 500
18
19SOCKADDR_IN server_addr;
20SOCKADDR_IN client_addr;
21
22SOCKET sock; //This is our socket, it is the handle to the IO address to read/write packets
23
24WSADATA data;
25
26char InputBuffer [MAX_BUFFER_SIZE];
27char hex_file [MAX_BUFFER_SIZE];
28char trc_file [MAX_BUFFER_SIZE];
29
30//////////////////////////
31// Registers //
32//////////////////////////
33
34#define FLAG_I 0x10
35#define FLAG_V 0x08
36#define FLAG_N 0x04
37#define FLAG_Z 0x02
38#define FLAG_C 0x01
39#define REGISTER_A 5
40#define REGISTER_F 4
41#define REGISTER_E 3
42#define REGISTER_D 2
43#define REGISTER_C 1
44#define REGISTER_B 0
45#define REGISTER_X 0
46#define REGISTER_Y 1
47BYTE Index_Registers[2];
48BYTE Registers[6];
49BYTE Flags;
50WORD ProgramCounter, StackPointer;
51
52////////////
53// Memory //
54////////////
55
56#define MEMORY_SIZE 65536
57
58BYTE Memory[MEMORY_SIZE];
59
60#define TEST_ADDRESS_1 0x01FA
61#define TEST_ADDRESS_2 0x01FB
62#define TEST_ADDRESS_3 0x01FC
63#define TEST_ADDRESS_4 0x01FD
64#define TEST_ADDRESS_5 0x01FE
65#define TEST_ADDRESS_6 0x01FF
66#define TEST_ADDRESS_7 0x0200
67#define TEST_ADDRESS_8 0x0201
68#define TEST_ADDRESS_9 0x0202
69#define TEST_ADDRESS_10 0x0203
70#define TEST_ADDRESS_11 0x0204
71#define TEST_ADDRESS_12 0x0205
72
73///////////////////////
74// Control variables //
75///////////////////////
76
77bool memory_in_range = true;
78bool halt = false;
79
80///////////////////////
81// Disassembly table //
82///////////////////////
83
84char opcode_mneumonics[][14] = {
85"ILLEGAL ",
86"ILLEGAL ",
87"STX abs ",
88"ILLEGAL ",
89"ILLEGAL ",
90"ILLEGAL ",
91"ILLEGAL ",
92"MV #,B ",
93"MV #,C ",
94"MV #,D ",
95"MV #,E ",
96"MV #,F ",
97"MAY impl ",
98"MYA impl ",
99"MAS impl ",
100"CSA impl ",
101
102"ILLEGAL ",
103"ILLEGAL ",
104"STX abs,X ",
105"ILLEGAL ",
106"ILLEGAL ",
107"ILLEGAL ",
108"SWI impl ",
109"RTI impl ",
110"CLC impl ",
111"SEC impl ",
112"CLI impl ",
113"STI impl ",
114"STV impl ",
115"CLV impl ",
116"ILLEGAL ",
117"ILLEGAL ",
118
119"ILLEGAL ",
120"ILLEGAL ",
121"STX abs,Y ",
122"ADD A,B ",
123"SUB A,B ",
124"CMP A,B ",
125"OR A,B ",
126"AND A,B ",
127"EOR A,B ",
128"BT A,B ",
129"LD A,A ",
130"LD B,A ",
131"LD C,A ",
132"LD D,A ",
133"LD E,A ",
134"LD F,A ",
135
136"ILLEGAL ",
137"LDX # ",
138"STX abs,XY ",
139"ADD A,C ",
140"SUB A,C ",
141"CMP A,C ",
142"OR A,C ",
143"AND A,C ",
144"EOR A,C ",
145"BT A,C ",
146"LD A,B ",
147"LD B,B ",
148"LD C,B ",
149"LD D,B ",
150"LD E,B ",
151"LD F,B ",
152
153"ILLEGAL ",
154"LDX abs ",
155"STX (ind),XY ",
156"ADD A,D ",
157"SUB A,D ",
158"CMP A,D ",
159"OR A,D ",
160"AND A,D ",
161"EOR A,D ",
162"BT A,D ",
163"LD A,C ",
164"LD B,C ",
165"LD C,C ",
166"LD D,C ",
167"LD E,C ",
168"LD F,C ",
169
170"ILLEGAL ",
171"LDX abs,X ",
172"ILLEGAL ",
173"ADD A,E ",
174"SUB A,E ",
175"CMP A,E ",
176"OR A,E ",
177"AND A,E ",
178"EOR A,E ",
179"BT A,E ",
180"LD A,D ",
181"LD B,D ",
182"LD C,D ",
183"LD D,D ",
184"LD E,D ",
185"LD F,D ",
186
187"ILLEGAL ",
188"LDX abs,Y ",
189"ILLEGAL ",
190"ADD A,F ",
191"SUB A,F ",
192"CMP A,F ",
193"OR A,F ",
194"AND A,F ",
195"EOR A,F ",
196"BT A,F ",
197"LD A,E ",
198"LD B,E ",
199"LD C,E ",
200"LD D,E ",
201"LD E,E ",
202"LD F,E ",
203
204"ILLEGAL ",
205"LDX abs,XY ",
206"ILLEGAL ",
207"NOP impl ",
208"HLT impl ",
209"ILLEGAL ",
210"ILLEGAL ",
211"ILLEGAL ",
212"ILLEGAL ",
213"ILLEGAL ",
214"LD A,F ",
215"LD B,F ",
216"LD C,F ",
217"LD D,F ",
218"LD E,F ",
219"LD F,F ",
220
221"ILLEGAL ",
222"LDX (ind),XY ",
223"ADI # ",
224"SBI # ",
225"CPI # ",
226"ORI # ",
227"ANI # ",
228"XRI # ",
229"ILLEGAL ",
230"ILLEGAL ",
231"ILLEGAL ",
232"ILLEGAL ",
233"ILLEGAL ",
234"ILLEGAL ",
235"ILLEGAL ",
236"ILLEGAL ",
237
238"LDA # ",
239"TST abs ",
240"INC abs ",
241"DEC abs ",
242"RCR abs ",
243"RLC abs ",
244"ASL abs ",
245"SAR abs ",
246"COM abs ",
247"RAL abs ",
248"ROR abs ",
249"LX #,A ",
250"ILLEGAL ",
251"LODS # ",
252"PUSH ,A ",
253"POP A, ",
254
255"LDA abs ",
256"TST abs,X ",
257"INC abs,X ",
258"DEC abs,X ",
259"RCR abs,X ",
260"RLC abs,X ",
261"ASL abs,X ",
262"SAR abs,X ",
263"COM abs,X ",
264"RAL abs,X ",
265"ROR abs,X ",
266"ILLEGAL ",
267"STO abs ",
268"LODS abs ",
269"PUSH ,s ",
270"POP s, ",
271
272"LDA abs,X ",
273"TST abs,Y ",
274"INC abs,Y ",
275"DEC abs,Y ",
276"RCR abs,Y ",
277"RLC abs,Y ",
278"ASL abs,Y ",
279"SAR abs,Y ",
280"COM abs,Y ",
281"RAL abs,Y ",
282"ROR abs,Y ",
283"ILLEGAL ",
284"STO abs,X ",
285"LODS abs,X ",
286"PUSH ,B ",
287"POP B, ",
288
289"LDA abs,Y ",
290"TST abs,XY ",
291"INC abs,XY ",
292"DEC abs,XY ",
293"RCR abs,XY ",
294"RLC abs,XY ",
295"ASL abs,XY ",
296"SAR abs,XY ",
297"COM abs,XY ",
298"RAL abs,XY ",
299"ROR abs,XY ",
300"ILLEGAL ",
301"STO abs,Y ",
302"LODS abs,Y ",
303"PUSH ,C ",
304"POP C, ",
305
306"LDA abs,XY ",
307"TSTA A,A ",
308"INCA A,A ",
309"DECA A,A ",
310"RCRA A,A ",
311"RLCA A,A ",
312"ASLA A,A ",
313"SARA A,A ",
314"COMA A,A ",
315"RALA A,A ",
316"RORA A,A ",
317"RTN impl ",
318"STO abs,XY ",
319"LODS abs,XY ",
320"PUSH ,D ",
321"POP D, ",
322
323"LDA (ind),XY ",
324"DEX impl ",
325"INX impl ",
326"DEY impl ",
327"INCY impl ",
328"ILLEGAL ",
329"ILLEGAL ",
330"ILLEGAL ",
331"ILLEGAL ",
332"JSR abs ",
333"JMP abs ",
334"ILLEGAL ",
335"STO (ind),XY ",
336"LODS (ind),XY",
337"PUSH ,E ",
338"POP E, ",
339
340"BRA rel ",
341"BCC rel ",
342"BCS rel ",
343"BNE rel ",
344"BEQ rel ",
345"BVC rel ",
346"BVS rel ",
347"BMI rel ",
348"BPL rel ",
349"BGE rel ",
350"BLE rel ",
351"BGT rel ",
352"BLT rel ",
353"ILLEGAL ",
354"PUSH ,F ",
355"POP F, ",
356};
357
358////////////////////////////////////////////////////////////////////////////////
359// Emulator (Start) //
360////////////////////////////////////////////////////////////////////////////////
361
362BYTE fetch() { //returns value in memory
363 BYTE byte = 0;
364
365 if ((ProgramCounter >= 0) && (ProgramCounter <= MEMORY_SIZE)) {
366 memory_in_range = true;
367 byte = Memory[ProgramCounter];
368 ProgramCounter++;
369 } else memory_in_range = false;
370
371 return byte;
372}
373
374//functions for setting flags
375void set_flag_v(BYTE in1, BYTE in2, BYTE out) { //overflow flag (set when last operation resulted in overflow)
376 if ((((in1 & 0x80) == 0x80) && ((in2 & 0x80) == 0x80) && ((out & 0x80) != 0x80))
377 || (((in1 & 0x80) != 0x80) && ((in2 & 0x80) != 0x80) && ((out & 0x80) == 0x80)))
378 {
379 Flags = Flags | FLAG_V;
380 }
381 else Flags = Flags & (0xFF - FLAG_V);
382}
383void set_flag_n(BYTE inReg) { //negative flag (set when last operation had negative answer)
384 if ((inReg & 0x80) != 0) Flags = Flags | FLAG_N;
385 else Flags = Flags & (0xFF - FLAG_N);
386}
387void set_flag_z(BYTE inReg) { //zero flag (set when last operation answer was 0)
388 if (inReg == 0) Flags = Flags | FLAG_Z;
389 else Flags = Flags & (0xFF - FLAG_Z);
390}
391void set_flags_nz(BYTE inReg) { //sets flags n and z at same time, as they usually come in pairs
392 set_flag_n(inReg);
393 set_flag_z(inReg);
394}
395void set_flag_c(WORD inWord) { //carry flag (set when last operation carry bit = 1)
396 if (inWord >= 0x100) Flags = Flags | FLAG_C;
397 else Flags = Flags & (0xFF - FLAG_C);
398}
399
400//these functions return the address depending on the addressing mode
401WORD address_abs() {
402 BYTE HB = fetch();
403 BYTE LB = fetch();
404 WORD address = (WORD)((WORD)HB << 8) + LB;
405 return address;
406}
407WORD address_absX() {
408 BYTE HB = fetch();
409 BYTE LB = fetch();
410 WORD address = Index_Registers[REGISTER_X];
411 address += (WORD)((WORD)HB << 8) + LB;
412 return address;
413}
414WORD address_absY() {
415 BYTE HB = fetch();
416 BYTE LB = fetch();
417 WORD address = Index_Registers[REGISTER_Y];
418 address += (WORD)((WORD)HB << 8) + LB;
419 return address;
420}
421WORD address_absXY() {
422 BYTE HB = fetch();
423 BYTE LB = fetch();
424 WORD address = (WORD)((WORD)Index_Registers[REGISTER_Y] << 8) + Index_Registers[REGISTER_X];
425 address += (WORD)((WORD)HB << 8) + LB;
426 return address;
427}
428WORD address_indXY() {
429 BYTE HB = fetch();
430 BYTE LB = fetch();
431 WORD address = (WORD)((WORD)HB << 8) + LB;
432 HB = Memory[address];
433 LB = Memory[address + 1];
434 address = (WORD)((WORD)HB << 8) + LB;
435 address += Index_Registers[REGISTER_X] + (WORD)((WORD)Index_Registers[REGISTER_Y] << 8);
436 return address;
437}
438
439//these functions are called for different operations, depending on the opcode
440//these are not all the operations, as some simpler operations don't need functions
441void LDA(WORD address) { //i.e. when the opcode is 0x90,0xA0,0xB0,0xC0,0xD0,0xE0 LDA is called (load memory into accumulator)
442 if (address >= 0 && address < MEMORY_SIZE) {
443 Registers[REGISTER_A] = Memory[address];
444 set_flags_nz((BYTE)Registers[REGISTER_A]);
445 }
446}
447void STO(WORD address) { //store accumulator into memory
448 if (address >= 0 && address < MEMORY_SIZE) { //if address is within memory...
449 Memory[address] = Registers[REGISTER_A]; //store accumulator into memory
450 set_flags_nz((BYTE)Registers[REGISTER_A]); //set flags accordingly
451 }
452}
453void MV(BYTE reg) { //set a register to the value in memory
454 Registers[reg] = fetch();
455 set_flags_nz((BYTE)Registers[reg]);
456}
457void LODS(WORD address) { //load memory into StackPointer
458 if (address >= 0 && address < MEMORY_SIZE - 1) {
459 StackPointer = (WORD)Memory[address] << 8;
460 StackPointer += Memory[address + 1];
461 set_flags_nz((BYTE)StackPointer);
462 }
463}
464void ADD(BYTE reg) {
465 WORD temp_word = (WORD)Registers[REGISTER_A] + (WORD)Registers[reg]; //addition of accumulator to a register
466 if ((Flags & FLAG_C) != 0) temp_word++;
467
468 set_flag_v((BYTE)Registers[REGISTER_A], (BYTE)Registers[reg], (BYTE)temp_word); //set flags accordingly
469 set_flags_nz((BYTE)temp_word);
470 set_flag_c((WORD)temp_word);
471
472 Registers[REGISTER_A] = (BYTE)temp_word; //store result into accumulator
473}
474void SUB(BYTE reg) {
475 WORD temp_word = (WORD)Registers[REGISTER_A] - (WORD)Registers[reg]; //subtraction of accumulator with a register
476 if ((Flags & FLAG_C) != 0) temp_word--;
477
478 set_flag_v((BYTE)Registers[REGISTER_A], (BYTE)(-Registers[reg]), (BYTE)temp_word);
479 set_flags_nz((BYTE)temp_word);
480 set_flag_c((WORD)temp_word);
481
482 Registers[REGISTER_A] = (BYTE)temp_word;
483}
484void AND(BYTE reg) {
485 WORD temp_word = (WORD)Registers[REGISTER_A] & (WORD)Registers[reg]; //logical AND operation of accumulator with a register
486 set_flags_nz((BYTE)temp_word);
487 Flags = Flags & (0xFF - FLAG_V); //clear overflow flag, as AND, OR and XOR don't result in overflow
488 Registers[REGISTER_A] = (BYTE)temp_word;
489}
490void OR(BYTE reg) {
491 WORD temp_word = (WORD)Registers[REGISTER_A] | (WORD)Registers[reg]; //logical OR operation of accumulator with a register
492 set_flags_nz((BYTE)temp_word);
493 Flags = Flags & (0xFF - FLAG_V);
494 Registers[REGISTER_A] = (BYTE)temp_word;
495}
496void EOR(BYTE reg) {
497 WORD temp_word = (WORD)Registers[REGISTER_A] ^ (WORD)Registers[reg]; //logical XOR operation of accumulator with a register
498 set_flags_nz((BYTE)temp_word);
499 Flags = Flags & (0xFF - FLAG_V);
500 Registers[REGISTER_A] = (BYTE)temp_word;
501}
502void BT(BYTE reg) { //register bit tested with accumulator
503 WORD temp_word = (WORD)Registers[REGISTER_A] & (WORD)Registers[reg];
504 set_flags_nz((BYTE)temp_word);
505}
506void CMP(BYTE reg) { //register compared to accumulator
507 WORD temp_word = (WORD)Registers[REGISTER_A] - (WORD)Registers[reg];
508 set_flag_v((BYTE)Registers[REGISTER_A], (BYTE)(-Registers[reg]), (BYTE)temp_word);
509 set_flags_nz((BYTE)temp_word);
510 set_flag_c((WORD)temp_word);
511}
512void LDX(WORD address) { //load memory into index register X
513 if (address >= 0 && address < MEMORY_SIZE) {
514 Index_Registers[REGISTER_X] = Memory[address];
515 set_flags_nz((BYTE)Index_Registers[REGISTER_X]);
516 }
517}
518void STX(WORD address) { //store index register X into memory
519 if (address >= 0 && address < MEMORY_SIZE) {
520 Memory[address] = Index_Registers[REGISTER_X];
521 set_flags_nz((BYTE)Index_Registers[REGISTER_X]);
522 }
523}
524void INC(WORD address) { //increment memory
525 if (address >= 0 && address < MEMORY_SIZE) {
526 Memory[address]++;
527 set_flags_nz((BYTE)Memory[address]);
528 }
529}
530void DEC(WORD address) { //decrement memory
531 if (address >= 0 && address < MEMORY_SIZE) {
532 Memory[address]--;
533 set_flags_nz((BYTE)Memory[address]);
534 }
535}
536void TST(WORD address) { //bit test memory
537 if (address >= 0 && address < MEMORY_SIZE) {
538 WORD temp_word = (WORD)Memory[address];
539 Memory[address] = (BYTE)temp_word;
540 set_flags_nz((BYTE)temp_word);
541 }
542}
543void ASL(WORD address) { //arithmetic left shift memory
544 if (address >= 0 && address < MEMORY_SIZE) {
545 WORD temp_word = Memory[address] << 1;
546 Memory[address] = (BYTE)temp_word;
547 set_flags_nz((BYTE)temp_word);
548 set_flag_c((WORD)temp_word);
549 }
550}
551void SAR(WORD address) { //arithmetic right shift memory
552 if (address >= 0 && address < MEMORY_SIZE) {
553 WORD temp_word = Memory[address] >> 1;
554 Memory[address] = (BYTE)temp_word;
555 set_flags_nz((BYTE)temp_word);
556 set_flag_c((WORD)temp_word);
557 }
558}
559void RLC(WORD address) { //rotate memory left with carry
560 if (address >= 0 && address < MEMORY_SIZE) {
561 BYTE saved_flags = Flags;
562 if ((Memory[address] & 0x80) == 0x80) Flags = Flags | FLAG_C;
563 else Flags = Flags & (0xFF - FLAG_C);
564
565 Memory[address] = (Memory[address] << 1) & 0xFE;
566 if ((saved_flags & FLAG_C) == FLAG_C) Memory[address] = Memory[address] | 0x01;
567
568 set_flags_nz((BYTE)Memory[address]);
569 }
570}
571void RCR(WORD address) { //rotate memory right with carry
572 if (address >= 0 && address < MEMORY_SIZE) {
573 BYTE saved_flags = Flags;
574 if ((Memory[address] & 0x01) == 0x01) Flags = Flags | FLAG_C;
575 else Flags = Flags & (0xFF - FLAG_C);
576
577 Memory[address] = (Memory[address] >> 1) & 0x7F;
578 if ((saved_flags & FLAG_C) == FLAG_C) Memory[address] = Memory[address] | 0x80;
579
580 set_flags_nz((BYTE)Memory[address]);
581 }
582}
583void RAL(WORD address) { //rotate memory left without carry
584 if (address >= 0 && address < MEMORY_SIZE) {
585 WORD temp_word = (Memory[address] << 1);
586 if (temp_word >= 0x100) temp_word = temp_word | 0x01;
587
588 Memory[address] = (BYTE)temp_word;
589 set_flags_nz((BYTE)Memory[address]);
590 }
591}
592void ROR(WORD address) { //rotate memory right without carry
593 if (address >= 0 && address < MEMORY_SIZE) {
594 WORD temp_word = (Memory[address] >> 1);
595 if ((Memory[address] & 0x01) != 0) temp_word = temp_word | 0x80;
596
597 Memory[address] = (BYTE)temp_word;
598 set_flags_nz((BYTE)Memory[address]);
599 }
600}
601void COM(WORD address) { //negate memory
602 if (address >= 0 && address < MEMORY_SIZE) {
603 WORD temp_word = ~Memory[address]; // ~ is the bitwise complement
604 set_flag_c((WORD)temp_word);
605 Memory[address] = (BYTE)temp_word;
606 set_flags_nz((BYTE)Memory[address]);
607 }
608}
609void PUSH(BYTE reg) { //push a register onto stack
610 if ((StackPointer >= 1) && (StackPointer < MEMORY_SIZE)) {
611 Memory[StackPointer] = Registers[reg];
612 StackPointer--;
613 }
614}
615void POP(BYTE reg) { //pop top of stack into a register
616 if ((StackPointer >= 0) && (StackPointer < MEMORY_SIZE - 1)) {
617 StackPointer++;
618 Registers[reg] = Memory[StackPointer];
619 }
620}
621void BRA(BYTE LB) { //branch always
622 WORD offset = (WORD)LB;
623 if ((offset & 0x80) != 0) offset += 0xFF00;
624
625 ProgramCounter += offset;
626}
627
628void Group_1(BYTE opcode) {
629 BYTE LB = 0, HB = 0, saved_flags = 0;
630 WORD data = 0, temp_word = 0, offset = 0;
631
632 switch (opcode) {
633 //------------------------------------------------ NOP (no operation) ------------------------------------------------
634 case 0x73: //NOP impl
635 //nothing
636 break;
637 //------------------------------------------------ HLT (wait for interrupt) ------------------------------------------------
638 case 0x74: //HLT impl
639 halt = true;
640 break;
641 //------------------------------------------------ LDA (load memory into accumulator) ------------------------------------------------
642 case 0x90: //LDA #
643 Registers[REGISTER_A] = fetch(); //set accumulator to value in memory
644 set_flags_nz((BYTE)Registers[REGISTER_A]); //set flags accordingly
645 break;
646 case 0xA0: //LDA abs
647 LDA(address_abs()); //call LDA function on address according to the addressing mode
648 break;
649 case 0xB0: //LDA abs,X
650 LDA(address_absX());
651 break;
652 case 0xC0: //LDA abs,Y
653 LDA(address_absY());
654 break;
655 case 0xD0: //LDA abs,XY
656 LDA(address_absXY());
657 break;
658 case 0xE0: //LDA (ind),XY
659 LDA(address_indXY());
660 break;
661 //------------------------------------------------ STO (store accumulator into memory) ------------------------------------------------
662 case 0xAC: //STO abs
663 STO(address_abs());
664 break;
665 case 0xBC: //STO abs,X
666 STO(address_absX());
667 break;
668 case 0xCC: //STO abs,Y
669 STO(address_absY());
670 break;
671 case 0xDC: //STO abs,XY
672 STO(address_absXY());
673 break;
674 case 0xEC: //STO (ind),XY
675 STO(address_indXY());
676 break;
677 //------------------------------------------------ MV (load memory into register) ------------------------------------------------
678 case 0x07: //MV B,#
679 MV(REGISTER_B);
680 break;
681 case 0x08: //MV C,#
682 MV(REGISTER_C);
683 break;
684 case 0x09: //MV D,#
685 MV(REGISTER_D);
686 break;
687 case 0x0A: //MV E,#
688 MV(REGISTER_E);
689 break;
690 case 0x0B: //MV F,#
691 MV(REGISTER_F);
692 break;
693 //------------------------------------------------ LODS (load memory into StackPointer) ------------------------------------------------
694 case 0x9D: //LODS #
695 data = fetch();
696 StackPointer = data << 8;
697 StackPointer += fetch();
698 set_flags_nz((BYTE)StackPointer);
699 break;
700 case 0xAD: //LODS abs
701 LODS(address_abs());
702 break;
703 case 0xBD: //LODS abs,X
704 LODS(address_absX());
705 break;
706 case 0xCD: //LODS abs,Y
707 LODS(address_absY());
708 break;
709 case 0xDD: //LODS abs,XY
710 LODS(address_absXY());
711 break;
712 case 0xED: //LODS (ind),XY
713 LODS(address_indXY());
714 break;
715 //------------------------------------------------ ADD (register added to accumulator with carry) ------------------------------------------------
716 case 0x23: //ADD A,B
717 ADD(REGISTER_B);
718 break;
719 case 0x33: //ADD A,C
720 ADD(REGISTER_C);
721 break;
722 case 0x43: //ADD A,D
723 ADD(REGISTER_D);
724 break;
725 case 0x53: //ADD A,E
726 ADD(REGISTER_E);
727 break;
728 case 0x63: //ADD A,F
729 ADD(REGISTER_F);
730 break;
731 //------------------------------------------------ SUB (register subtracted to accumulator with carry) ------------------------------------------------
732 case 0x24: //SUB A,B
733 SUB(REGISTER_B);
734 break;
735 case 0x34: //SUB A,C
736 SUB(REGISTER_C);
737 break;
738 case 0x44: //SUB A,D
739 SUB(REGISTER_D);
740 break;
741 case 0x54: //SUB A,E
742 SUB(REGISTER_E);
743 break;
744 case 0x64: //SUB A,F
745 SUB(REGISTER_F);
746 break;
747 //------------------------------------------------ ADI (data added to accumulator with carry) ------------------------------------------------
748 case 0x82: //ADI #
749 data = fetch();
750 temp_word = (WORD)Registers[REGISTER_A] + (WORD)data;
751 if ((Flags & FLAG_C) != 0) temp_word++;
752
753 set_flag_v((BYTE)Registers[REGISTER_A], (BYTE)data, (BYTE)temp_word);
754 set_flags_nz((BYTE)temp_word);
755 set_flag_c((WORD)temp_word);
756
757 Registers[REGISTER_A] = (BYTE)temp_word;
758 break;
759 //------------------------------------------------ SBI (data subtracted to accumulator with carry) ------------------------------------------------
760 case 0x83: //SBI #
761 data = fetch();
762 temp_word = (WORD)Registers[REGISTER_A] - (WORD)data;
763 if ((Flags & FLAG_C) != 0) temp_word--;
764
765 set_flag_v((BYTE)Registers[REGISTER_A], (BYTE)(-data), (BYTE)temp_word);
766 set_flags_nz((BYTE)temp_word);
767 set_flag_c((WORD)temp_word);
768
769 Registers[REGISTER_A] = (BYTE)temp_word;
770 break;
771 //------------------------------------------------ AND (register bitwise AND with accumulator) ------------------------------------------------
772 case 0x27: //AND A,B
773 AND(REGISTER_B);
774 break;
775 case 0x37: //AND A,C
776 AND(REGISTER_C);
777 break;
778 case 0x47: //AND A,D
779 AND(REGISTER_D);
780 break;
781 case 0x57: //AND A,E
782 AND(REGISTER_E);
783 break;
784 case 0x67: //AND A,F
785 AND(REGISTER_F);
786 break;
787 //------------------------------------------------ OR (register bitwise OR with accumulator) ------------------------------------------------
788 case 0x26: //OR A,B
789 OR(REGISTER_B);
790 break;
791 case 0x36: //OR A,C
792 OR(REGISTER_C);
793 break;
794 case 0x46: //OR A,D
795 OR(REGISTER_D);
796 break;
797 case 0x56: //OR A,E
798 OR(REGISTER_E);
799 break;
800 case 0x66: //OR A,F
801 OR(REGISTER_F);
802 break;
803 //------------------------------------------------ EOR (register bitwise XOR with accumulator) ------------------------------------------------
804 case 0x28: //EOR A,B
805 EOR(REGISTER_B);
806 break;
807 case 0x38: //EOR A,C
808 EOR(REGISTER_C);
809 break;
810 case 0x48: //EOR A,D
811 EOR(REGISTER_D);
812 break;
813 case 0x58: //EOR A,E
814 EOR(REGISTER_E);
815 break;
816 case 0x68: //EOR A,F
817 EOR(REGISTER_F);
818 break;
819 //------------------------------------------------ BT (test register bit with accumulator) ------------------------------------------------
820 case 0x29: //BT A,B
821 BT(REGISTER_B);
822 break;
823 case 0x39: //BT A,C
824 BT(REGISTER_C);
825 break;
826 case 0x49: //BT A,D
827 BT(REGISTER_D);
828 break;
829 case 0x59: //BT A,E
830 BT(REGISTER_E);
831 break;
832 case 0x69: //BT A,F
833 BT(REGISTER_F);
834 break;
835 //------------------------------------------------ CMP (compare register to accumulator) ------------------------------------------------
836 case 0x25: //CMP A,B
837 CMP(REGISTER_B);
838 break;
839 case 0x35: //CMP A,C
840 CMP(REGISTER_C);
841 break;
842 case 0x45: //CMP A,D
843 CMP(REGISTER_D);
844 break;
845 case 0x55: //CMP A,E
846 CMP(REGISTER_E);
847 break;
848 case 0x65: //CMP A,F
849 CMP(REGISTER_F);
850 break;
851 //------------------------------------------------ CPI (compare data to accumulator) ------------------------------------------------
852 case 0x84: //CPI #
853 data = fetch();
854 temp_word = (WORD)Registers[REGISTER_A] - data;
855 set_flag_v((BYTE)Registers[REGISTER_A], (BYTE)(-data), (BYTE)temp_word);
856 set_flags_nz((BYTE)temp_word);
857 set_flag_c((WORD)temp_word);
858 break;
859 //------------------------------------------------ ANI (data bitwise AND with accumulator) ------------------------------------------------
860 case 0x86: //ANI #
861 data = fetch();
862 temp_word = (WORD)data & (WORD)Registers[REGISTER_A];
863 set_flags_nz((BYTE)temp_word);
864 Registers[REGISTER_A] = (BYTE)temp_word;
865 break;
866 //------------------------------------------------ ORI (data bitwise OR with accumulator) ------------------------------------------------
867 case 0x85: //ORI #
868 data = fetch();
869 temp_word = (WORD)data | (WORD)Registers[REGISTER_A];
870 set_flags_nz((BYTE)temp_word);
871 Registers[REGISTER_A] = (BYTE)temp_word;
872 break;
873 //------------------------------------------------ XRI (data bitwise XOR with accumulator) ------------------------------------------------
874 case 0x87: //XRI #
875 data = fetch();
876 temp_word = (WORD)data ^ (WORD)Registers[REGISTER_A];
877 set_flags_nz((BYTE)temp_word);
878 Registers[REGISTER_A] = (BYTE)temp_word;
879 break;
880 //------------------------------------------------ CSA (transfer status register to accumulator) ------------------------------------------------
881 case 0x0F: //CSA impl
882 Registers[REGISTER_A] = Flags;
883 break;
884 //------------------------------------------------ LDX (load memory into index register X) ------------------------------------------------
885 case 0x31: //LDX #
886 Index_Registers[REGISTER_X] = fetch();
887 set_flags_nz((BYTE)Index_Registers[REGISTER_X]);
888 break;
889 case 0x41: //LDX abs
890 LDX(address_abs());
891 break;
892 case 0x51: //LDX abs,X
893 LDX(address_absX());
894 break;
895 case 0x61: //LDX abs,Y
896 LDX(address_absY());
897 break;
898 case 0x71: //LDX abs,XY
899 LDX(address_absXY());
900 break;
901 case 0x81: //LDX (ind),XY
902 LDX(address_indXY());
903 break;
904 //------------------------------------------------ STX (store index register X into memory) ------------------------------------------------
905 case 0x02: //STX abs
906 STX(address_abs());
907 break;
908 case 0x12: //STX abs,X
909 STX(address_absX());
910 break;
911 case 0x22: //STX abs,Y
912 STX(address_absY());
913 break;
914 case 0x32: //STX abs,XY
915 STX(address_absXY());
916 break;
917 case 0x42: //STX (ind),XY
918 STX(address_indXY());
919 break;
920 //------------------------------------------------ MAY (transfer accumulator into index register Y) ------------------------------------------------
921 case 0x0C: //MAY impl
922 Index_Registers[REGISTER_Y] = Registers[REGISTER_A];
923 set_flag_n((BYTE)Registers[REGISTER_A]);
924 break;
925 //------------------------------------------------ MYA (transfer index register Y to accumulator) ------------------------------------------------
926 case 0x0D: //MYA impl
927 Registers[REGISTER_A] = Index_Registers[REGISTER_Y];
928 set_flags_nz((BYTE)Index_Registers[REGISTER_Y]);
929 break;
930 //------------------------------------------------ MAS (transfer accumulator to status register) ------------------------------------------------
931 case 0x0E: //MAS impl
932 Flags = Registers[REGISTER_A];
933 break;
934 //------------------------------------------------ INC (increment memory) ------------------------------------------------
935 case 0x92: //INC abs
936 INC(address_abs());
937 break;
938 case 0xA2: //INC abs,X
939 INC(address_absX());
940 break;
941 case 0xB2: //INC abs,Y
942 INC(address_absY());
943 break;
944 case 0xC2: //INC abs,XY
945 INC(address_absXY());
946 break;
947 //------------------------------------------------ INCA (increment accumulator) ------------------------------------------------
948 case 0xD2: //INCA A
949 Registers[REGISTER_A]++;
950 set_flags_nz((BYTE)Registers[REGISTER_A]);
951 break;
952 //------------------------------------------------ DEC (decrement memory) ------------------------------------------------
953 case 0x93: //DEC abs
954 DEC(address_abs());
955 break;
956 case 0xA3: //DEC abs,X
957 DEC(address_absX());
958 break;
959 case 0xB3: //DEC abs,Y
960 DEC(address_absY());
961 break;
962 case 0xC3: //DEC abs,XY
963 DEC(address_absXY());
964 break;
965 //------------------------------------------------ DECA (decrement accumulator) ------------------------------------------------
966 case 0xD3: //DECA A
967 Registers[REGISTER_A]--;
968 set_flags_nz((BYTE)Registers[REGISTER_A]);
969 break;
970 //------------------------------------------------ TST (bit test memory) ------------------------------------------------
971 case 0x91: //TST abs
972 TST(address_abs());
973 break;
974 case 0xA1: //TST abs,X
975 TST(address_absX());
976 break;
977 case 0xB1: //TST abs,Y
978 TST(address_absY());
979 break;
980 case 0xC1: //TST abs,XY
981 TST(address_absXY());
982 break;
983 //------------------------------------------------ TSTA (bit test accumulator) ------------------------------------------------
984 case 0xD1: //TSTA A
985 temp_word = (WORD)Registers[REGISTER_A];
986 set_flags_nz((BYTE)temp_word);
987 Registers[REGISTER_A] = (BYTE)temp_word;
988 break;
989 //------------------------------------------------ INX (increment index register X) ------------------------------------------------
990 case 0xE2: //INX impl
991 Index_Registers[REGISTER_X]++;
992 set_flag_z((BYTE)Index_Registers[REGISTER_X]);
993 break;
994 //------------------------------------------------ DEX (decrement index register X) ------------------------------------------------
995 case 0xE1: //DEX impl
996 Index_Registers[REGISTER_X]--;
997 set_flag_z((BYTE)Index_Registers[REGISTER_X]);
998 break;
999 //------------------------------------------------ INCY (increment index register Y) ------------------------------------------------
1000 case 0xE4: //INCY impl
1001 Index_Registers[REGISTER_Y]++;
1002 set_flag_z((BYTE)Index_Registers[REGISTER_Y]);
1003 break;
1004 //------------------------------------------------ DEY (decrement index register Y) ------------------------------------------------
1005 case 0xE3: //DEY impl
1006 Index_Registers[REGISTER_Y]--;
1007 set_flag_z((BYTE)Index_Registers[REGISTER_Y]);
1008 break;
1009 //------------------------------------------------ ASL (arithmetic left shift memory) ------------------------------------------------
1010 case 0x96: //ASL abs
1011 ASL(address_abs());
1012 break;
1013 case 0xA6: //ASL abs,X
1014 ASL(address_absX());
1015 break;
1016 case 0xB6: //ASL abs,Y
1017 ASL(address_absY());
1018 break;
1019 case 0xC6: //ASL abs,XY
1020 ASL(address_absXY());
1021 break;
1022 //------------------------------------------------ ASLA (arithmetic left shift accumulator) ------------------------------------------------
1023 case 0xD6: //ASLA A
1024 temp_word = Registers[REGISTER_A] << 1;
1025 Registers[REGISTER_A] = (BYTE)temp_word;
1026 set_flags_nz((BYTE)temp_word);
1027 set_flag_c((WORD)temp_word);
1028 break;
1029 //------------------------------------------------ SAR (arithmetic right shift memory) ------------------------------------------------
1030 case 0x97: //SAR abs
1031 SAR(address_abs());
1032 break;
1033 case 0xA7: //SAR abs,X
1034 SAR(address_absX());
1035 break;
1036 case 0xB7: //SAR abs,Y
1037 SAR(address_absY());
1038 break;
1039 case 0xC7: //SAR abs,XY
1040 SAR(address_absXY());
1041 break;
1042 //------------------------------------------------ SARA (arithmetic right shift accumulator) ------------------------------------------------
1043 case 0xD7: //SARA A
1044 temp_word = Registers[REGISTER_A] >> 1;
1045 Registers[REGISTER_A] = (BYTE)temp_word;
1046 set_flags_nz((BYTE)temp_word);
1047 set_flag_c((WORD)temp_word);
1048 break;
1049 //------------------------------------------------ RCR (rotate memory right with carry) ------------------------------------------------
1050 case 0x94: //RCR abs
1051 RCR(address_abs());
1052 break;
1053 case 0xA4: //RCR abs,X
1054 RCR(address_absX());
1055 break;
1056 case 0xB4: //RCR abs,Y
1057 RCR(address_absY());
1058 break;
1059 case 0xC4: //RCR abs,XY
1060 RCR(address_absXY());
1061 break;
1062 //------------------------------------------------ RCRA (rotate accumulator right with carry) ------------------------------------------------
1063 case 0xD4: //RCRA A
1064 if ((Registers[REGISTER_A] & 0x01) == 0x01) Flags = Flags | FLAG_C;
1065 else Flags = Flags & (0xFF - FLAG_C);
1066 Registers[REGISTER_A] = (Registers[REGISTER_A] >> 1) & 0x7F;
1067 if ((Flags & FLAG_C) == FLAG_C) Registers[REGISTER_A] = Registers[REGISTER_A] | 0x80;
1068 set_flags_nz((BYTE)Registers[REGISTER_A]);
1069 break;
1070 //------------------------------------------------ RLC (rotate memory left with carry) ------------------------------------------------
1071 case 0x95: //RLC abs
1072 RLC(address_abs());
1073 break;
1074 case 0xA5: //RLC abs,X
1075 RLC(address_absX());
1076 break;
1077 case 0xB5: //RLC abs,Y
1078 RLC(address_absY());
1079 break;
1080 case 0xC5: //RLC abs,XY
1081 RLC(address_absXY());
1082 break;
1083 //------------------------------------------------ RLCA (rotate accumulator left with carry) ------------------------------------------------
1084 case 0xD5: //RLCA A
1085 if ((Registers[REGISTER_A] & 0x80) == 0x80) Flags = Flags | FLAG_C; //set carry based on MSB of accumulator
1086 else Flags = Flags & (0xFF - FLAG_C);
1087
1088 Registers[REGISTER_A] = (Registers[REGISTER_A] << 1) & 0xFE;
1089 if ((Flags & FLAG_C) == FLAG_C) Registers[REGISTER_A] = Registers[REGISTER_A] | 0x01;
1090
1091 set_flags_nz((BYTE)Registers[REGISTER_A]);
1092 break;
1093 //------------------------------------------------ RAL (rotate memory left without carry) ------------------------------------------------
1094 case 0x99: //RAL abs
1095 RAL(address_abs());
1096 break;
1097 case 0xA9: //RAL abs,X
1098 RAL(address_absX());
1099 break;
1100 case 0xB9: //RAL abs,Y
1101 RAL(address_absY());
1102 break;
1103 case 0xC9: //RAL abs,XY
1104 RAL(address_absXY());
1105 break;
1106 //------------------------------------------------ RALA (rotate accumulator left without carry) ------------------------------------------------
1107 case 0xD9: //RALA A
1108 temp_word = (Registers[REGISTER_A] << 1);
1109 if (temp_word >= 0x100) temp_word = temp_word | 0x01;
1110 Registers[REGISTER_A] = (BYTE)temp_word;
1111 set_flags_nz((BYTE)Registers[REGISTER_A]);
1112 break;
1113 //------------------------------------------------ ROR (rotate memory right without carry) ------------------------------------------------
1114 case 0x9A: //ROR abs
1115 ROR(address_abs());
1116 break;
1117 case 0xAA: //ROR abs,X
1118 ROR(address_absX());
1119 break;
1120 case 0xBA: //ROR abs,Y
1121 ROR(address_absY());
1122 break;
1123 case 0xCA: //ROR abs,XY
1124 ROR(address_absXY());
1125 break;
1126 //------------------------------------------------ RORA (rotate accumulator right without carry) ------------------------------------------------
1127 case 0xDA: //RORA A
1128 temp_word = (Registers[REGISTER_A] >> 1);
1129 if ((Registers[REGISTER_A] & 0x01) != 0) temp_word = temp_word | 0x80;
1130 Registers[REGISTER_A] = (BYTE)temp_word;
1131 set_flags_nz((BYTE)Registers[REGISTER_A]);
1132 break;
1133 //------------------------------------------------ COM (negate memory) ------------------------------------------------
1134 case 0x98: //COM abs
1135 COM(address_abs());
1136 break;
1137 case 0xA8: //COM abs,X
1138 COM(address_absX());
1139 break;
1140 case 0xB8: //COM abs,Y
1141 COM(address_absY());
1142 break;
1143 case 0xC8: //COM abs,XY
1144 COM(address_absXY());
1145 break;
1146 //------------------------------------------------ COMA (negate accumulator) ------------------------------------------------
1147 case 0xD8: //COMA A
1148 temp_word = ~Registers[REGISTER_A];
1149 set_flags_nz((BYTE)temp_word);
1150 set_flag_c((WORD)temp_word);
1151 Registers[REGISTER_A] = (BYTE)temp_word;
1152 break;
1153 //------------------------------------------------ LX (load memory into register pair) ------------------------------------------------
1154 case 0x9B: //LX AB,#
1155 HB = fetch();
1156 LB = fetch();
1157 Registers[REGISTER_A] = LB;
1158 Registers[REGISTER_B] = HB;
1159 temp_word = ((WORD)LB << 8) + (WORD)HB;
1160 set_flags_nz((BYTE)temp_word);
1161 break;
1162 //------------------------------------------------ JMP (load memory into ProgramCounter) ------------------------------------------------
1163 case 0xEA: //JMP abs
1164 ProgramCounter = address_abs();
1165 break;
1166 //------------------------------------------------ JSR (jump to subroutine) ------------------------------------------------
1167 case 0xE9: //JSR abs
1168 ProgramCounter = address_abs();
1169 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1170 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1171 StackPointer--;
1172 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1173 StackPointer--;
1174 }
1175 break;
1176 //------------------------------------------------ RTN (return from subroutine) ------------------------------------------------
1177 case 0xDB: //RTN impl
1178 ProgramCounter = ((WORD)HB << 8) + (WORD)LB;
1179 if ((StackPointer >= 0) && (StackPointer < MEMORY_SIZE - 2)) {
1180 StackPointer++;
1181 HB = Memory[StackPointer];
1182 StackPointer++;
1183 LB = Memory[StackPointer];
1184 }
1185 break;
1186 //------------------------------------------------ BRA (branch always) ------------------------------------------------
1187 case 0xF0: //BRA rel
1188 LB = fetch();
1189 BRA(LB);
1190 break;
1191 //------------------------------------------------ BCC (branch on carry clear) ------------------------------------------------
1192 case 0xF1: //BCC rel
1193 LB = fetch();
1194 if (FLAG_C == 0x00) {
1195 BRA(LB);
1196 } else fetch();
1197 break;
1198 //------------------------------------------------ BCS (branch on carry set) ------------------------------------------------
1199 case 0xF2: //BCS rel
1200 LB = fetch();
1201 if (FLAG_C == 0x01) {
1202 BRA(LB);
1203 } else fetch();
1204 break;
1205 //------------------------------------------------ BNE (branch on result not zero) ------------------------------------------------
1206 case 0xF3: //BNE rel
1207 LB = fetch();
1208 if (FLAG_Z == 0x00) {
1209 BRA(LB);
1210 } else fetch();
1211 break;
1212 //------------------------------------------------ BEQ (branch on result equal to zero) ------------------------------------------------
1213 case 0xF4: //BEQ rel
1214 LB = fetch();
1215 if (FLAG_Z == 0x01) {
1216 BRA(LB);
1217 } else fetch();
1218 break;
1219 //------------------------------------------------ BVC (branch on overflow clear) ------------------------------------------------
1220 case 0xF5: //BVC rel
1221 LB = fetch();
1222 if (FLAG_V == 0x00) {
1223 BRA(LB);
1224 } else fetch();
1225 break;
1226 //------------------------------------------------ BVS (branch on overflow set) ------------------------------------------------
1227 case 0xF6: //BVS rel
1228 LB = fetch();
1229 if (FLAG_V == 0x01) {
1230 BRA(LB);
1231 } else fetch();
1232 break;
1233 //------------------------------------------------ BMI (branch on negative result) ------------------------------------------------
1234 case 0xF7: //BMI rel
1235 LB = fetch();
1236 if (FLAG_N == 0x01) {
1237 BRA(LB);
1238 } else fetch();
1239 break;
1240 //------------------------------------------------ BPL (branch on positive result) ------------------------------------------------
1241 case 0xF8: //BPL rel
1242 LB = fetch();
1243 if (FLAG_N == 0x00) {
1244 BRA(LB);
1245 } else fetch();
1246 break;
1247 //------------------------------------------------ BGE (branch on result <= 0) ------------------------------------------------
1248 case 0xF9: //BGE rel
1249 LB = fetch();
1250 if ((FLAG_N ^ FLAG_V) == 0x00) {
1251 BRA(LB);
1252 } else fetch();
1253 break;
1254 //------------------------------------------------ BLE (branch on result >= 0) ------------------------------------------------
1255 case 0xFA: //BLE rel
1256 LB = fetch();
1257 if ((FLAG_Z | FLAG_N ^ FLAG_V) == 0x01) {
1258 BRA(LB);
1259 } else fetch();
1260 break;
1261 //------------------------------------------------ BGT (branch on result < 0) ------------------------------------------------
1262 case 0xFB: //BGT rel
1263 LB = fetch();
1264 if ((FLAG_Z | FLAG_N ^ FLAG_V) == 0x00) {
1265 BRA(LB);
1266 } else fetch();
1267 break;
1268 //------------------------------------------------ BLT (branch on result > 0) ------------------------------------------------
1269 case 0xFC: //BLT rel
1270 LB = fetch();
1271 if ((FLAG_N ^ FLAG_V) == 0x01) {
1272 BRA(LB);
1273 } else fetch();
1274 break;
1275 //------------------------------------------------ PUSH (pushes register onto stack) ------------------------------------------------
1276 case 0x9E: //PUSH A
1277 PUSH(REGISTER_A);
1278 break;
1279 case 0xAE: //PUSH FL (status reg)
1280 PUSH(Flags);
1281 break;
1282 case 0xBE: //PUSH B
1283 PUSH(REGISTER_B);
1284 break;
1285 case 0xCE: //PUSH C
1286 PUSH(REGISTER_C);
1287 break;
1288 case 0xDE: //PUSH D
1289 PUSH(REGISTER_D);
1290 break;
1291 case 0xEE: //PUSH E
1292 PUSH(REGISTER_E);
1293 break;
1294 case 0xFE: //PUSH F
1295 PUSH(REGISTER_F);
1296 break;
1297 //------------------------------------------------ POP (pop top of stack into register) ------------------------------------------------
1298 case 0x9F: //POP A
1299 POP(REGISTER_A);
1300 break;
1301 case 0xAF: //POP FL
1302 POP(Flags);
1303 break;
1304 case 0xBF: //POP B
1305 POP(REGISTER_B);
1306 break;
1307 case 0xCF: //POP C
1308 POP(REGISTER_C);
1309 break;
1310 case 0xDF: //POP D
1311 POP(REGISTER_D);
1312 break;
1313 case 0xEF: //POP E
1314 POP(REGISTER_E);
1315 break;
1316 case 0xFF: //POP F
1317 POP(REGISTER_F);
1318 break;
1319 //------------------------------------------------ SWI (software interrupt) ------------------------------------------------
1320 case 0x16: //SWI impl
1321
1322 break;
1323 //------------------------------------------------ RTN (return from software interrupt) ------------------------------------------------
1324 case 0x17: //RTN impl
1325
1326 break;
1327 //------------------------------------------------ SEC (set carry flag) ------------------------------------------------
1328 case 0x19: //SEC impl
1329 Flags = Flags | FLAG_C;
1330 break;
1331 //------------------------------------------------ CLC (clear carry flag) ------------------------------------------------
1332 case 0x18: //CLC impl
1333 Flags = Flags & (0xFF - FLAG_C);
1334 break;
1335 //------------------------------------------------ STI (set interrupt flag) ------------------------------------------------
1336 case 0x1B: //STI impl
1337 Flags = Flags | FLAG_I;
1338 break;
1339 //------------------------------------------------ CLI (clear interrupt flag) ------------------------------------------------
1340 case 0x1A: //CLI impl
1341 Flags = Flags & (0xFF - FLAG_I);
1342 break;
1343 //------------------------------------------------ STV (set overflow flag) ------------------------------------------------
1344 case 0x1C: //STV impl
1345 Flags = Flags | FLAG_V;
1346 break;
1347 //------------------------------------------------ CLV (clear overflow flag) ------------------------------------------------
1348 case 0x1D: //CLV impl
1349 Flags = Flags & (0xFF - FLAG_V);
1350 break;
1351 }
1352}
1353
1354//LD function
1355void Group_2_Move(BYTE opcode) {
1356 BYTE destination = opcode >> 4; //top four bits point at one register....shift right to keep only top four
1357 BYTE source = opcode & 0x0F;//takes bottom four bits
1358 int destReg = 0, sourceReg = 0;
1359
1360 switch (destination) { //COMBO OF DEST AND SOURCE GIVE REGISTERS ADDRESSES TO FOR MEMORY ADRESSER AT BOTTOM
1361 case 0x02://top four bits from op code
1362 destReg = REGISTER_A;
1363 break;
1364 case 0x03:
1365 destReg = REGISTER_B;
1366 break;
1367 case 0x04:
1368 destReg = REGISTER_C;
1369 break;
1370 case 0x05:
1371 destReg = REGISTER_D;
1372 break;
1373 case 0x06:
1374 destReg = REGISTER_E;
1375 break;
1376 case 0x07:
1377 destReg = REGISTER_F;
1378 break;
1379 }
1380
1381 switch (source) {
1382 case 0x0A:
1383 sourceReg = REGISTER_A;
1384 break;
1385 case 0x0B:
1386 sourceReg = REGISTER_B;
1387 break;
1388 case 0x0C:
1389 sourceReg = REGISTER_C;
1390 break;
1391 case 0x0D:
1392 sourceReg = REGISTER_D;
1393 break;
1394 case 0x0E:
1395 sourceReg = REGISTER_E;
1396 break;
1397 case 0x0F:
1398 sourceReg = REGISTER_F;
1399 break;
1400 }
1401
1402 Registers[sourceReg] = Registers[destReg]; //assign source reg to dest reg
1403}
1404
1405void execute(BYTE opcode) {
1406 if (((opcode >= 0x2A) && (opcode <= 0x2F))
1407 || ((opcode >= 0x3A) && (opcode <= 0x3F))
1408 || ((opcode >= 0x4A) && (opcode <= 0x4F))
1409 || ((opcode >= 0x5A) && (opcode <= 0x5F))
1410 || ((opcode >= 0x6A) && (opcode <= 0x6F))
1411 || ((opcode >= 0x7A) && (opcode <= 0x7F)))
1412 {
1413 Group_2_Move(opcode);
1414 }
1415 else Group_1(opcode);
1416}
1417
1418void emulate() {
1419 BYTE opcode;
1420 int sanity = 0;
1421
1422 ProgramCounter = 0;
1423 halt = false;
1424 memory_in_range = true;
1425
1426 //printf(" A B C D E F X Y SP\n");
1427
1428 while ((!halt) && (memory_in_range)) {
1429 sanity++;
1430 if (sanity > 500) halt = true;
1431 // printf("%04X ", ProgramCounter); // Print current address
1432 opcode = fetch();
1433 execute(opcode);
1434 /*
1435 printf("%s ", opcode_mneumonics[opcode]); // Print current opcode
1436 printf("%02X ", Registers[REGISTER_A]);
1437 printf("%02X ", Registers[REGISTER_B]);
1438 printf("%02X ", Registers[REGISTER_C]);
1439 printf("%02X ", Registers[REGISTER_D]);
1440 printf("%02X ", Registers[REGISTER_E]);
1441 printf("%02X ", Registers[REGISTER_F]);
1442 printf("%02X ", Index_Registers[REGISTER_X]);
1443 printf("%02X ", Index_Registers[REGISTER_Y]);
1444 printf("%04X ", StackPointer); // Print Stack Pointer
1445
1446 if ((Flags & FLAG_I) == FLAG_I) printf("I = 1, ");
1447 else printf("I = 0, ");
1448
1449 if ((Flags & FLAG_V) == FLAG_V) printf("V = 1, ");
1450 else printf("V = 0, ");
1451
1452 if ((Flags & FLAG_N) == FLAG_N) printf("N = 1, ");
1453 else printf("N = 0, ");
1454
1455 if ((Flags & FLAG_Z) == FLAG_Z) printf("Z = 1, ");
1456 else printf("Z = 0, ");
1457
1458 if ((Flags & FLAG_C) == FLAG_C) printf("C = 1 ");
1459 else printf("C = 0 ");
1460
1461 printf("\n");*/
1462 }
1463 printf("\n");
1464}
1465
1466
1467////////////////////////////////////////////////////////////////////////////////
1468// Emulator (End) //
1469////////////////////////////////////////////////////////////////////////////////
1470
1471void initialise_filenames() {
1472 int i;
1473
1474 for (i=0; i<MAX_FILENAME_SIZE; i++) {
1475 hex_file [i] = '\0';
1476 trc_file [i] = '\0';
1477 }
1478}
1479
1480int find_dot_position(char *filename) {
1481 int dot_position;
1482 int i;
1483 char chr;
1484
1485 dot_position = 0;
1486 i = 0;
1487 chr = filename[i];
1488
1489 while (chr != '\0') {
1490 if (chr == '.') dot_position = i;
1491
1492 i++;
1493 chr = filename[i];
1494 }
1495
1496 return dot_position;
1497}
1498
1499int find_end_position(char *filename) {
1500 int end_position;
1501 int i;
1502 char chr;
1503
1504 end_position = 0;
1505 i = 0;
1506 chr = filename[i];
1507
1508 while (chr != '\0') {
1509 end_position = i;
1510 i++;
1511 chr = filename[i];
1512 }
1513
1514 return end_position;
1515}
1516
1517bool file_exists(char *filename) {
1518 bool exists;
1519 FILE *ifp;
1520
1521 exists = false;
1522
1523 if ((ifp = fopen(filename, "r")) != NULL) {
1524 exists = true;
1525
1526 fclose(ifp);
1527 }
1528
1529 return exists;
1530}
1531
1532void create_file(char *filename) {
1533 FILE *ofp;
1534
1535 if ((ofp = fopen(filename, "w")) != NULL) fclose(ofp);
1536}
1537
1538bool getline(FILE *fp, char *buffer) {
1539 bool rc;
1540 bool collect;
1541 char c;
1542 int i;
1543
1544 rc = false;
1545 collect = true;
1546
1547 i = 0;
1548 while (collect) {
1549 c = getc(fp);
1550
1551 switch (c) {
1552 case EOF:
1553 if (i > 0) rc = true;
1554
1555 collect = false;
1556 break;
1557 case '\n':
1558 if (i > 0) {
1559 rc = true;
1560 collect = false;
1561 buffer[i] = '\0';
1562 }
1563 break;
1564 default:
1565 buffer[i] = c;
1566 i++;
1567 }
1568 }
1569
1570 return rc;
1571}
1572
1573void load_and_run(int args,_TCHAR** argv) {
1574 char chr;
1575 int ln;
1576 int dot_position;
1577 int end_position;
1578 long i;
1579 FILE *ifp;
1580 long address;
1581 long load_at;
1582 int code;
1583
1584 // Prompt for the .hex file
1585
1586 printf("\n");
1587 printf("Enter the hex filename (.hex): ");
1588
1589 if(args == 2) {
1590 ln = 0;
1591 chr = argv[1][ln];
1592 while (chr != '\0') {
1593 if (ln < MAX_FILENAME_SIZE) {
1594 hex_file [ln] = chr;
1595 trc_file [ln] = chr;
1596 ln++;
1597 }
1598 chr = argv[1][ln];
1599 }
1600 } else {
1601 ln = 0;
1602 chr = '\0';
1603 while (chr != '\n') {
1604 chr = getchar();
1605
1606 switch(chr) {
1607 case '\n':
1608 break;
1609 default:
1610 if (ln < MAX_FILENAME_SIZE) {
1611 hex_file [ln] = chr;
1612 trc_file [ln] = chr;
1613 ln++;
1614 }
1615 break;
1616 }
1617 }
1618 }
1619 // Tidy up the file names
1620
1621 dot_position = find_dot_position(hex_file);
1622 if (dot_position == 0) {
1623 end_position = find_end_position(hex_file);
1624
1625 hex_file[end_position + 1] = '.';
1626 hex_file[end_position + 2] = 'h';
1627 hex_file[end_position + 3] = 'e';
1628 hex_file[end_position + 4] = 'x';
1629 hex_file[end_position + 5] = '\0';
1630 } else {
1631 hex_file[dot_position + 0] = '.';
1632 hex_file[dot_position + 1] = 'h';
1633 hex_file[dot_position + 2] = 'e';
1634 hex_file[dot_position + 3] = 'x';
1635 hex_file[dot_position + 4] = '\0';
1636 }
1637
1638 dot_position = find_dot_position(trc_file);
1639 if (dot_position == 0) {
1640 end_position = find_end_position(trc_file);
1641
1642 trc_file[end_position + 1] = '.';
1643 trc_file[end_position + 2] = 't';
1644 trc_file[end_position + 3] = 'r';
1645 trc_file[end_position + 4] = 'c';
1646 trc_file[end_position + 5] = '\0';
1647 } else {
1648 trc_file[dot_position + 0] = '.';
1649 trc_file[dot_position + 1] = 't';
1650 trc_file[dot_position + 2] = 'r';
1651 trc_file[dot_position + 3] = 'c';
1652 trc_file[dot_position + 4] = '\0';
1653 }
1654
1655 if (file_exists(hex_file)) {
1656 // Clear Registers and Memory
1657 Registers[REGISTER_A] = 0;
1658 Registers[REGISTER_B] = 0;
1659 Registers[REGISTER_C] = 0;
1660 Registers[REGISTER_D] = 0;
1661 Registers[REGISTER_E] = 0;
1662 Registers[REGISTER_F] = 0;
1663 Index_Registers[REGISTER_X] = 0;
1664 Index_Registers[REGISTER_Y] = 0;
1665 Flags = 0;
1666 ProgramCounter = 0;
1667 StackPointer = 0;
1668
1669 for (i = 0; i < MEMORY_SIZE; i++) Memory[i] = 0x00;
1670
1671 // Load hex file
1672 if ((ifp = fopen(hex_file, "r")) != NULL) {
1673 printf("Loading file...\n\n");
1674
1675 load_at = 0;
1676
1677 while (getline(ifp, InputBuffer)) {
1678 if (sscanf(InputBuffer, "L=%x", &address) == 1) load_at = address;
1679 else if (sscanf(InputBuffer, "%x", &code) == 1) {
1680 if ((load_at >= 0) && (load_at <= MEMORY_SIZE)) Memory[load_at] = (BYTE)code;
1681
1682 load_at++;
1683 } else printf("ERROR> Failed to load instruction: %s \n", InputBuffer);
1684 }
1685
1686 fclose(ifp);
1687 }
1688
1689 emulate();
1690 } else {
1691 printf("\n");
1692 printf("ERROR> Input file %s does not exist!\n", hex_file);
1693 printf("\n");
1694 }
1695}
1696
1697void building(int args,_TCHAR** argv){
1698 char buffer[1024];
1699 load_and_run(args,argv);
1700 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",
1701 Memory[TEST_ADDRESS_1],
1702 Memory[TEST_ADDRESS_2],
1703 Memory[TEST_ADDRESS_3],
1704 Memory[TEST_ADDRESS_4],
1705 Memory[TEST_ADDRESS_5],
1706 Memory[TEST_ADDRESS_6],
1707 Memory[TEST_ADDRESS_7],
1708 Memory[TEST_ADDRESS_8],
1709 Memory[TEST_ADDRESS_9],
1710 Memory[TEST_ADDRESS_10],
1711 Memory[TEST_ADDRESS_11],
1712 Memory[TEST_ADDRESS_12]
1713 );
1714 sendto(sock, buffer, strlen(buffer), 0, (SOCKADDR *)&server_addr, sizeof(SOCKADDR));
1715}
1716
1717void test_and_mark() {
1718 char buffer[1024];
1719 bool testing_complete;
1720 int len = sizeof(SOCKADDR);
1721 char chr;
1722 int i;
1723 int j;
1724 bool end_of_program;
1725 long address;
1726 long load_at;
1727 int code;
1728 int mark;
1729 int passed;
1730
1731 printf("Automatic Testing and Marking\n");
1732 printf("\n");
1733
1734 testing_complete = false;
1735
1736 sprintf(buffer, "Test Student %s", STUDENT_NUMBER);
1737 sendto(sock, buffer, strlen(buffer), 0, (SOCKADDR *)&server_addr, sizeof(SOCKADDR));
1738
1739 while (!testing_complete) {
1740 memset(buffer, '\0', sizeof(buffer));
1741
1742 if (recvfrom(sock, buffer, sizeof(buffer)-1, 0, (SOCKADDR *)&client_addr, &len) != SOCKET_ERROR) {
1743 printf("Incoming Data: %s \n", buffer);
1744
1745 //if (strcmp(buffer, "Testing complete") == 1)
1746 if (sscanf(buffer, "Testing complete %d", &mark) == 1) {
1747 testing_complete = true;
1748 printf("Current mark = %d\n", mark);
1749 }else if (sscanf(buffer, "Tests passed %d", &passed) == 1) {
1750 //testing_complete = true;
1751 printf("Passed = %d\n", passed);
1752 } else if (strcmp(buffer, "Error") == 0) {
1753 printf("ERROR> Testing abnormally terminated\n");
1754 testing_complete = true;
1755 } else {
1756 // Clear Registers and Memory
1757 Registers[REGISTER_A] = 0;
1758 Registers[REGISTER_B] = 0;
1759 Registers[REGISTER_C] = 0;
1760 Registers[REGISTER_D] = 0;
1761 Registers[REGISTER_E] = 0;
1762 Registers[REGISTER_F] = 0;
1763 Index_Registers[REGISTER_X] = 0;
1764 Index_Registers[REGISTER_Y] = 0;
1765 Flags = 0;
1766 ProgramCounter = 0;
1767 StackPointer = 0;
1768 for (i = 0; i < MEMORY_SIZE; i++) Memory[i] = 0;
1769
1770 // Load hex file
1771 i = 0;
1772 j = 0;
1773 load_at = 0;
1774 end_of_program = false;
1775 FILE *ofp;
1776 fopen_s(&ofp ,"branch.txt", "a");
1777
1778 while (!end_of_program) {
1779 chr = buffer[i];
1780 switch (chr) {
1781 case '\0':
1782 end_of_program = true;
1783 case ',':
1784 if (sscanf(InputBuffer, "L=%x", &address) == 1) load_at = address;
1785 else if (sscanf(InputBuffer, "%x", &code) == 1) {
1786 if ((load_at >= 0) && (load_at <= MEMORY_SIZE)) {
1787 Memory[load_at] = (BYTE)code;
1788 fprintf(ofp, "%02X\n", (BYTE)code);
1789 }
1790 load_at++;
1791 } else printf("ERROR> Failed to load instruction: %s \n", InputBuffer);
1792
1793 j = 0;
1794 break;
1795 default:
1796 InputBuffer[j] = chr;
1797 j++;
1798 break;
1799 }
1800 i++;
1801 }
1802 fclose(ofp);
1803 // Emulate
1804
1805 if (load_at > 1) {
1806 emulate();
1807 // Send and store results
1808 sprintf(buffer, "%02X%02X %02X%02X %02X%02X %02X%02X %02X%02X %02X%02X",
1809 Memory[TEST_ADDRESS_1],
1810 Memory[TEST_ADDRESS_2],
1811 Memory[TEST_ADDRESS_3],
1812 Memory[TEST_ADDRESS_4],
1813 Memory[TEST_ADDRESS_5],
1814 Memory[TEST_ADDRESS_6],
1815 Memory[TEST_ADDRESS_7],
1816 Memory[TEST_ADDRESS_8],
1817 Memory[TEST_ADDRESS_9],
1818 Memory[TEST_ADDRESS_10],
1819 Memory[TEST_ADDRESS_11],
1820 Memory[TEST_ADDRESS_12]
1821 );
1822 sendto(sock, buffer, strlen(buffer), 0, (SOCKADDR *)&server_addr, sizeof(SOCKADDR));
1823 }
1824 }
1825 }
1826 }
1827}
1828
1829int _tmain(int argc, _TCHAR* argv[]) {
1830 char chr;
1831 char dummy;
1832
1833 printf("Microprocessor Emulator\n");
1834 printf("UWE Computer and Network Systems Assignment 1\n");
1835 printf("\n");
1836
1837 initialise_filenames();
1838
1839 if (WSAStartup(MAKEWORD(2, 2), &data) != 0) return(0);
1840
1841 sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Here we create our socket, which will be a UDP socket (SOCK_DGRAM).
1842 if (!sock) {
1843 //Creation failed!
1844 }
1845
1846 memset(&server_addr, 0, sizeof(SOCKADDR_IN));
1847 server_addr.sin_family = AF_INET;
1848 server_addr.sin_addr.s_addr = inet_addr(IP_ADDRESS_SERVER);
1849 server_addr.sin_port = htons(PORT_SERVER);
1850
1851 memset(&client_addr, 0, sizeof(SOCKADDR_IN));
1852 client_addr.sin_family = AF_INET;
1853 client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
1854 client_addr.sin_port = htons(PORT_CLIENT);
1855
1856 chr = '\0';
1857 while ((chr != 'e') && (chr != 'E')) {
1858 printf("\nPlease select option\n");
1859 printf("L - Load and run a hex file\n");
1860 printf("T - Have the server test and mark your emulator\n");
1861 printf("E - Exit\n");
1862 if(argc == 2){ building(argc,argv); exit(0);}
1863 printf("Enter option: ");
1864 chr = getchar();
1865 if (chr != 0x0A) dummy = getchar(); // read in the <CR>
1866
1867 printf("\n");
1868
1869 switch (chr) {
1870 case 'L': case 'l':
1871 load_and_run(argc,argv);
1872 break;
1873 case 'T': case 't':
1874 test_and_mark();
1875 break;
1876 }
1877 }
1878
1879 closesocket(sock);
1880 WSACleanup();
1881
1882 return 0;
1883}