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