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