· 8 years ago · Feb 24, 2018, 01:40 PM
1/*
2 Author: Sam Barba, student no. 17043938
3 Created: 06/02/2018
4 Final revision: 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; //set it
392 }
393 else Flags = Flags & (0xFF - FLAG_V); //clear it
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 operation 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) { //if address in range of memory...
459 Registers[REGISTER_A] = Memory[address]; //load memory at 'address' into accumulator...
460 set_flags_nz((BYTE)Registers[REGISTER_A]); //and set flags accordingly (negative flag and zero flag in this case)
461 }
462}
463void STO(WORD address) { //store accumulator into memory
464 if (address >= 0 && address < MEMORY_SIZE) {
465 Memory[address] = Registers[REGISTER_A];
466 set_flags_nz((BYTE)Registers[REGISTER_A]);
467 }
468}
469void MV(BYTE reg) { //set a register to the value in memory
470 Registers[reg] = fetch(); //'fetch' returns the value in memory
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) { //addition of accumulator to a register
481 WORD temp_word = (WORD)Registers[REGISTER_A] + (WORD)Registers[reg];
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) { //subtraction of accumulator with a register
491 WORD temp_word = (WORD)Registers[REGISTER_A] - (WORD)Registers[reg];
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) { //logical AND operation of accumulator with a register
501 WORD temp_word = (WORD)Registers[REGISTER_A] & (WORD)Registers[reg];
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) { //logical OR operation of accumulator with a register
507 WORD temp_word = (WORD)Registers[REGISTER_A] | (WORD)Registers[reg];
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) { //logical XOR operation of accumulator with a register
513 WORD temp_word = (WORD)Registers[REGISTER_A] ^ (WORD)Registers[reg];
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) offset += 0xFF00;
640 ProgramCounter += offset;
641}
642
643void Group_1(BYTE opcode) {
644 BYTE LB = 0, HB = 0, saved_flags = 0;
645 WORD data = 0, temp_word = 0;
646
647 switch (opcode) {
648 //------------------------------------------------ NOP (no operation)
649 case 0x73: //NOP impl
650 //nothing
651 break;
652 //------------------------------------------------ HLT (wait for interrupt)
653 case 0x74: //HLT impl
654 halt = true;
655 break;
656 //------------------------------------------------ LDA (load memory into accumulator)
657 case 0x90: //LDA #
658 Registers[REGISTER_A] = fetch(); //set accumulator to value in memory
659 set_flags_nz((BYTE)Registers[REGISTER_A]); //set flags accordingly
660 break;
661 case 0xA0: //LDA abs
662 LDA(address_abs()); //call LDA function on address according to the addressing mode
663 break;
664 case 0xB0: //LDA abs,X
665 LDA(address_absX());
666 break;
667 case 0xC0: //LDA abs,Y
668 LDA(address_absY());
669 break;
670 case 0xD0: //LDA abs,XY
671 LDA(address_absXY());
672 break;
673 case 0xE0: //LDA (ind),XY
674 LDA(address_indXY());
675 break;
676 //------------------------------------------------ STO (store accumulator into memory)
677 case 0xAC: //STO abs
678 STO(address_abs());
679 break;
680 case 0xBC: //STO abs,X
681 STO(address_absX());
682 break;
683 case 0xCC: //STO abs,Y
684 STO(address_absY());
685 break;
686 case 0xDC: //STO abs,XY
687 STO(address_absXY());
688 break;
689 case 0xEC: //STO (ind),XY
690 STO(address_indXY());
691 break;
692 //------------------------------------------------ MV (load memory into register)
693 case 0x07: //MV B,#
694 MV(REGISTER_B);
695 break;
696 case 0x08: //MV C,#
697 MV(REGISTER_C);
698 break;
699 case 0x09: //MV D,#
700 MV(REGISTER_D);
701 break;
702 case 0x0A: //MV E,#
703 MV(REGISTER_E);
704 break;
705 case 0x0B: //MV F,#
706 MV(REGISTER_F);
707 break;
708 //------------------------------------------------ LODS (load memory into StackPointer)
709 case 0x9D: //LODS #
710 data = fetch();
711 StackPointer = data << 8;
712 StackPointer += fetch();
713 set_flags_nz((BYTE)StackPointer);
714 break;
715 case 0xAD: //LODS abs
716 LODS(address_abs());
717 break;
718 case 0xBD: //LODS abs,X
719 LODS(address_absX());
720 break;
721 case 0xCD: //LODS abs,Y
722 LODS(address_absY());
723 break;
724 case 0xDD: //LODS abs,XY
725 LODS(address_absXY());
726 break;
727 case 0xED: //LODS (ind),XY
728 LODS(address_indXY());
729 break;
730 //------------------------------------------------ ADD (register added to accumulator with carry)
731 case 0x23: //ADD A,B
732 ADD(REGISTER_B);
733 break;
734 case 0x33: //ADD A,C
735 ADD(REGISTER_C);
736 break;
737 case 0x43: //ADD A,D
738 ADD(REGISTER_D);
739 break;
740 case 0x53: //ADD A,E
741 ADD(REGISTER_E);
742 break;
743 case 0x63: //ADD A,F
744 ADD(REGISTER_F);
745 break;
746 //------------------------------------------------ SUB (register subtracted to accumulator with carry)
747 case 0x24: //SUB A,B
748 SUB(REGISTER_B);
749 break;
750 case 0x34: //SUB A,C
751 SUB(REGISTER_C);
752 break;
753 case 0x44: //SUB A,D
754 SUB(REGISTER_D);
755 break;
756 case 0x54: //SUB A,E
757 SUB(REGISTER_E);
758 break;
759 case 0x64: //SUB A,F
760 SUB(REGISTER_F);
761 break;
762 //------------------------------------------------ ADI (data added to accumulator with carry)
763 case 0x82: //ADI #
764 data = fetch();
765 temp_word = (WORD)Registers[REGISTER_A] + (WORD)data;
766 if ((Flags & FLAG_C) != 0) temp_word++;
767
768 set_flag_v((BYTE)Registers[REGISTER_A], (BYTE)data, (BYTE)temp_word);
769 set_flags_nz((BYTE)temp_word);
770 set_flag_c((WORD)temp_word);
771
772 Registers[REGISTER_A] = (BYTE)temp_word;
773 break;
774 //------------------------------------------------ SBI (data subtracted to accumulator with carry)
775 case 0x83: //SBI #
776 data = fetch();
777 temp_word = (WORD)Registers[REGISTER_A] - (WORD)data;
778 if ((Flags & FLAG_C) != 0) temp_word--;
779
780 set_flag_v((BYTE)Registers[REGISTER_A], (BYTE)(-data), (BYTE)temp_word);
781 set_flags_nz((BYTE)temp_word);
782 set_flag_c((WORD)temp_word);
783
784 Registers[REGISTER_A] = (BYTE)temp_word;
785 break;
786 //------------------------------------------------ AND (register bitwise AND with accumulator)
787 case 0x27: //AND A,B
788 AND(REGISTER_B);
789 break;
790 case 0x37: //AND A,C
791 AND(REGISTER_C);
792 break;
793 case 0x47: //AND A,D
794 AND(REGISTER_D);
795 break;
796 case 0x57: //AND A,E
797 AND(REGISTER_E);
798 break;
799 case 0x67: //AND A,F
800 AND(REGISTER_F);
801 break;
802 //------------------------------------------------ OR (register bitwise OR with accumulator)
803 case 0x26: //OR A,B
804 OR(REGISTER_B);
805 break;
806 case 0x36: //OR A,C
807 OR(REGISTER_C);
808 break;
809 case 0x46: //OR A,D
810 OR(REGISTER_D);
811 break;
812 case 0x56: //OR A,E
813 OR(REGISTER_E);
814 break;
815 case 0x66: //OR A,F
816 OR(REGISTER_F);
817 break;
818 //------------------------------------------------ EOR (register bitwise XOR with accumulator)
819 case 0x28: //EOR A,B
820 EOR(REGISTER_B);
821 break;
822 case 0x38: //EOR A,C
823 EOR(REGISTER_C);
824 break;
825 case 0x48: //EOR A,D
826 EOR(REGISTER_D);
827 break;
828 case 0x58: //EOR A,E
829 EOR(REGISTER_E);
830 break;
831 case 0x68: //EOR A,F
832 EOR(REGISTER_F);
833 break;
834 //------------------------------------------------ BT (test register bit with accumulator)
835 case 0x29: //BT A,B
836 BT(REGISTER_B);
837 break;
838 case 0x39: //BT A,C
839 BT(REGISTER_C);
840 break;
841 case 0x49: //BT A,D
842 BT(REGISTER_D);
843 break;
844 case 0x59: //BT A,E
845 BT(REGISTER_E);
846 break;
847 case 0x69: //BT A,F
848 BT(REGISTER_F);
849 break;
850 //------------------------------------------------ CMP (compare register to accumulator)
851 case 0x25: //CMP A,B
852 CMP(REGISTER_B);
853 break;
854 case 0x35: //CMP A,C
855 CMP(REGISTER_C);
856 break;
857 case 0x45: //CMP A,D
858 CMP(REGISTER_D);
859 break;
860 case 0x55: //CMP A,E
861 CMP(REGISTER_E);
862 break;
863 case 0x65: //CMP A,F
864 CMP(REGISTER_F);
865 break;
866 //------------------------------------------------ CPI (compare data to accumulator)
867 case 0x84: //CPI #
868 data = fetch();
869 temp_word = (WORD)Registers[REGISTER_A] - data;
870 set_flag_v((BYTE)Registers[REGISTER_A], (BYTE)(-data), (BYTE)temp_word);
871 set_flags_nz((BYTE)temp_word);
872 set_flag_c((WORD)temp_word);
873 break;
874 //------------------------------------------------ ANI (data bitwise AND with accumulator)
875 case 0x86: //ANI #
876 data = fetch();
877 temp_word = (WORD)data & (WORD)Registers[REGISTER_A];
878 set_flags_nz((BYTE)temp_word);
879 Registers[REGISTER_A] = (BYTE)temp_word;
880 break;
881 //------------------------------------------------ ORI (data bitwise OR with accumulator)
882 case 0x85: //ORI #
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 //------------------------------------------------ XRI (data bitwise XOR with accumulator)
889 case 0x87: //XRI #
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 //------------------------------------------------ CSA (transfer status register to accumulator)
896 case 0x0F: //CSA impl
897 Registers[REGISTER_A] = Flags;
898 break;
899 //------------------------------------------------ LDX (load memory into index register X)
900 case 0x31: //LDX #
901 Index_Registers[REGISTER_X] = fetch();
902 set_flags_nz((BYTE)Index_Registers[REGISTER_X]);
903 break;
904 case 0x41: //LDX abs
905 LDX(address_abs());
906 break;
907 case 0x51: //LDX abs,X
908 LDX(address_absX());
909 break;
910 case 0x61: //LDX abs,Y
911 LDX(address_absY());
912 break;
913 case 0x71: //LDX abs,XY
914 LDX(address_absXY());
915 break;
916 case 0x81: //LDX (ind),XY
917 LDX(address_indXY());
918 break;
919 //------------------------------------------------ STX (store index register X into memory)
920 case 0x02: //STX abs
921 STX(address_abs());
922 break;
923 case 0x12: //STX abs,X
924 STX(address_absX());
925 break;
926 case 0x22: //STX abs,Y
927 STX(address_absY());
928 break;
929 case 0x32: //STX abs,XY
930 STX(address_absXY());
931 break;
932 case 0x42: //STX (ind),XY
933 STX(address_indXY());
934 break;
935 //------------------------------------------------ MAY (transfer accumulator into index register Y)
936 case 0x0C: //MAY impl
937 Index_Registers[REGISTER_Y] = Registers[REGISTER_A];
938 set_flag_n((BYTE)Registers[REGISTER_A]);
939 break;
940 //------------------------------------------------ MYA (transfer index register Y to accumulator)
941 case 0x0D: //MYA impl
942 Registers[REGISTER_A] = Index_Registers[REGISTER_Y];
943 set_flags_nz((BYTE)Index_Registers[REGISTER_Y]);
944 break;
945 //------------------------------------------------ MAS (transfer accumulator to status register)
946 case 0x0E: //MAS impl
947 Flags = Registers[REGISTER_A];
948 break;
949 //------------------------------------------------ INC (increment memory)
950 case 0x92: //INC abs
951 INC(address_abs());
952 break;
953 case 0xA2: //INC abs,X
954 INC(address_absX());
955 break;
956 case 0xB2: //INC abs,Y
957 INC(address_absY());
958 break;
959 case 0xC2: //INC abs,XY
960 INC(address_absXY());
961 break;
962 //------------------------------------------------ INCA (increment accumulator)
963 case 0xD2: //INCA A
964 Registers[REGISTER_A]++;
965 set_flags_nz((BYTE)Registers[REGISTER_A]);
966 break;
967 //------------------------------------------------ DEC (decrement memory)
968 case 0x93: //DEC abs
969 DEC(address_abs());
970 break;
971 case 0xA3: //DEC abs,X
972 DEC(address_absX());
973 break;
974 case 0xB3: //DEC abs,Y
975 DEC(address_absY());
976 break;
977 case 0xC3: //DEC abs,XY
978 DEC(address_absXY());
979 break;
980 //------------------------------------------------ DECA (decrement accumulator)
981 case 0xD3: //DECA A
982 Registers[REGISTER_A]--;
983 set_flags_nz((BYTE)Registers[REGISTER_A]);
984 break;
985 //------------------------------------------------ TST (bit test memory)
986 case 0x91: //TST abs
987 TST(address_abs());
988 break;
989 case 0xA1: //TST abs,X
990 TST(address_absX());
991 break;
992 case 0xB1: //TST abs,Y
993 TST(address_absY());
994 break;
995 case 0xC1: //TST abs,XY
996 TST(address_absXY());
997 break;
998 //------------------------------------------------ TSTA (bit test accumulator)
999 case 0xD1: //TSTA A
1000 temp_word = (WORD)Registers[REGISTER_A];
1001 set_flags_nz((BYTE)temp_word);
1002 Registers[REGISTER_A] = (BYTE)temp_word;
1003 break;
1004 //------------------------------------------------ INX (increment index register X)
1005 case 0xE2: //INX impl
1006 Index_Registers[REGISTER_X]++;
1007 set_flag_z((BYTE)Index_Registers[REGISTER_X]);
1008 break;
1009 //------------------------------------------------ DEX (decrement index register X)
1010 case 0xE1: //DEX impl
1011 Index_Registers[REGISTER_X]--;
1012 set_flag_z((BYTE)Index_Registers[REGISTER_X]);
1013 break;
1014 //------------------------------------------------ INCY (increment index register Y)
1015 case 0xE4: //INCY impl
1016 Index_Registers[REGISTER_Y]++;
1017 set_flag_z((BYTE)Index_Registers[REGISTER_Y]);
1018 break;
1019 //------------------------------------------------ DEY (decrement index register Y)
1020 case 0xE3: //DEY impl
1021 Index_Registers[REGISTER_Y]--;
1022 set_flag_z((BYTE)Index_Registers[REGISTER_Y]);
1023 break;
1024 //------------------------------------------------ ASL (arithmetic left shift memory)
1025 case 0x96: //ASL abs
1026 ASL(address_abs());
1027 break;
1028 case 0xA6: //ASL abs,X
1029 ASL(address_absX());
1030 break;
1031 case 0xB6: //ASL abs,Y
1032 ASL(address_absY());
1033 break;
1034 case 0xC6: //ASL abs,XY
1035 ASL(address_absXY());
1036 break;
1037 //------------------------------------------------ ASLA (arithmetic left shift accumulator)
1038 case 0xD6: //ASLA A
1039 temp_word = Registers[REGISTER_A] << 1;
1040 Registers[REGISTER_A] = (BYTE)temp_word;
1041 set_flags_nz((BYTE)temp_word);
1042 set_flag_c((WORD)temp_word);
1043 break;
1044 //------------------------------------------------ SAR (arithmetic right shift memory)
1045 case 0x97: //SAR abs
1046 SAR(address_abs());
1047 break;
1048 case 0xA7: //SAR abs,X
1049 SAR(address_absX());
1050 break;
1051 case 0xB7: //SAR abs,Y
1052 SAR(address_absY());
1053 break;
1054 case 0xC7: //SAR abs,XY
1055 SAR(address_absXY());
1056 break;
1057 //------------------------------------------------ SARA (arithmetic right shift accumulator)
1058 case 0xD7: //SARA A
1059 temp_word = (Registers[REGISTER_A] >> 1) & 0x7F;
1060 Registers[REGISTER_A] = (BYTE)temp_word;
1061 set_flags_nz((BYTE)temp_word);
1062 set_flag_c((WORD)temp_word);
1063 break;
1064 //------------------------------------------------ RLC (rotate memory left with carry)
1065 case 0x95: //RLC abs
1066 RLC(address_abs());
1067 break;
1068 case 0xA5: //RLC abs,X
1069 RLC(address_absX());
1070 break;
1071 case 0xB5: //RLC abs,Y
1072 RLC(address_absY());
1073 break;
1074 case 0xC5: //RLC abs,XY
1075 RLC(address_absXY());
1076 break;
1077 //------------------------------------------------ RLCA (rotate accumulator left with carry)
1078 case 0xD5: //RLCA A
1079 Registers[REGISTER_A] = (Registers[REGISTER_A] << 1) & 0xFE;
1080 if ((Flags & FLAG_C) == FLAG_C) Registers[REGISTER_A] = Registers[REGISTER_A] | 0x01;
1081
1082 if ((Registers[REGISTER_A] & 0x80) == 0x80) Flags = Flags | FLAG_C; //set carry based on MSB of accumulator
1083 else Flags = Flags & (0xFF - FLAG_C);
1084
1085 set_flags_nz((BYTE)Registers[REGISTER_A]);
1086 break;
1087 //------------------------------------------------ RCR (rotate memory right with carry)
1088 case 0x94: //RCR abs
1089 RCR(address_abs());
1090 break;
1091 case 0xA4: //RCR abs,X
1092 RCR(address_absX());
1093 break;
1094 case 0xB4: //RCR abs,Y
1095 RCR(address_absY());
1096 break;
1097 case 0xC4: //RCR abs,XY
1098 RCR(address_absXY());
1099 break;
1100 //------------------------------------------------ RCRA (rotate accumulator right with carry)
1101 case 0xD4: //RCRA A
1102 Registers[REGISTER_A] = (Registers[REGISTER_A] >> 1) & 0x7F;
1103 if ((Flags & FLAG_C) == FLAG_C) Registers[REGISTER_A] = Registers[REGISTER_A] | 0x80;
1104
1105 if ((Registers[REGISTER_A] & 0x01) == 0x01) Flags = Flags | FLAG_C;
1106 else Flags = Flags & (0xFF - FLAG_C);
1107
1108 set_flags_nz((BYTE)Registers[REGISTER_A]);
1109 break;
1110 //------------------------------------------------ RAL (rotate memory left without carry)
1111 case 0x99: //RAL abs
1112 RAL(address_abs());
1113 break;
1114 case 0xA9: //RAL abs,X
1115 RAL(address_absX());
1116 break;
1117 case 0xB9: //RAL abs,Y
1118 RAL(address_absY());
1119 break;
1120 case 0xC9: //RAL abs,XY
1121 RAL(address_absXY());
1122 break;
1123 //------------------------------------------------ RALA (rotate accumulator left without carry)
1124 case 0xD9: //RALA A
1125 temp_word = Registers[REGISTER_A] << 1;
1126 if (temp_word >= 0x100) temp_word = temp_word | 0x01;
1127
1128 Registers[REGISTER_A] = (BYTE)temp_word;
1129 set_flags_nz((BYTE)Registers[REGISTER_A]);
1130 break;
1131 //------------------------------------------------ ROR (rotate memory right without carry)
1132 case 0x9A: //ROR abs
1133 ROR(address_abs());
1134 break;
1135 case 0xAA: //ROR abs,X
1136 ROR(address_absX());
1137 break;
1138 case 0xBA: //ROR abs,Y
1139 ROR(address_absY());
1140 break;
1141 case 0xCA: //ROR abs,XY
1142 ROR(address_absXY());
1143 break;
1144 //------------------------------------------------ RORA (rotate accumulator right without carry)
1145 case 0xDA: //RORA A
1146 temp_word = Registers[REGISTER_A] >> 1;
1147 if ((Registers[REGISTER_A] & 0x01) != 0) temp_word = temp_word | 0x80;
1148
1149 Registers[REGISTER_A] = (BYTE)temp_word;
1150 set_flags_nz((BYTE)Registers[REGISTER_A]);
1151 break;
1152 //------------------------------------------------ COM (negate memory)
1153 case 0x98: //COM abs
1154 COM(address_abs());
1155 break;
1156 case 0xA8: //COM abs,X
1157 COM(address_absX());
1158 break;
1159 case 0xB8: //COM abs,Y
1160 COM(address_absY());
1161 break;
1162 case 0xC8: //COM abs,XY
1163 COM(address_absXY());
1164 break;
1165 //------------------------------------------------ COMA (negate accumulator)
1166 case 0xD8: //COMA A
1167 temp_word = ~Registers[REGISTER_A];
1168 set_flags_nz((BYTE)temp_word);
1169 set_flag_c((WORD)temp_word);
1170 Registers[REGISTER_A] = (BYTE)temp_word;
1171 break;
1172 //------------------------------------------------ LX (load memory into register pair)
1173 case 0x9B: //LX AB,#
1174 HB = fetch();
1175 LB = fetch();
1176 Registers[REGISTER_A] = LB;
1177 Registers[REGISTER_B] = HB;
1178 temp_word = ((WORD)LB << 8) + (WORD)HB;
1179 set_flags_nz((BYTE)temp_word);
1180 break;
1181 //------------------------------------------------ JMP (load memory into ProgramCounter)
1182 case 0xEA: //JMP abs
1183 ProgramCounter = address_abs();
1184 break;
1185 //------------------------------------------------ JSR (jump to subroutine)
1186 case 0xE9: //JSR abs
1187 if ((StackPointer >= 2) && (StackPointer < MEMORY_SIZE)) {
1188 Memory[StackPointer] = (BYTE)(ProgramCounter & 0xFF);
1189 StackPointer--;
1190 Memory[StackPointer] = (BYTE)((ProgramCounter >> 8) & 0xFF);
1191 StackPointer--;
1192 }
1193 ProgramCounter = address_abs();
1194 break;
1195 //------------------------------------------------ RTN (return from subroutine)
1196 case 0xDB: //RTN impl
1197 if ((StackPointer >= 0) && (StackPointer < MEMORY_SIZE - 2)) {
1198 StackPointer++;
1199 HB = Memory[StackPointer];
1200 StackPointer++;
1201 LB = Memory[StackPointer];
1202 }
1203 ProgramCounter = ((WORD)HB << 8) + (WORD)LB;
1204 break;
1205 //------------------------------------------------ BRA (branch always)
1206 case 0xF0: //BRA rel
1207 BRA(fetch());
1208 break;
1209 //------------------------------------------------ BCC (branch on carry clear)
1210 case 0xF1: //BCC rel
1211 data = fetch();
1212 if (!(Flags & FLAG_C)) BRA(data);
1213 break;
1214 //------------------------------------------------ BCS (branch on carry set)
1215 case 0xF2: //BCS rel
1216 data = fetch();
1217 if (Flags & FLAG_C) BRA(data);
1218 break;
1219 //------------------------------------------------ BNE (branch on result not zero)
1220 case 0xF3: //BNE rel
1221 data = fetch();
1222 if (!(Flags & FLAG_Z)) BRA(data);
1223 break;
1224 //------------------------------------------------ BEQ (branch on result equal to zero)
1225 case 0xF4: //BEQ rel
1226 data = fetch();
1227 if (Flags & FLAG_Z) BRA(data);
1228 break;
1229 //------------------------------------------------ BVC (branch on overflow clear)
1230 case 0xF5: //BVC rel
1231 data = fetch();
1232 if (!(Flags & FLAG_V)) BRA(data);
1233 break;
1234 //------------------------------------------------ BVS (branch on overflow set)
1235 case 0xF6: //BVS rel
1236 data = fetch();
1237 if (Flags & FLAG_V) BRA(data);
1238 break;
1239 //------------------------------------------------ BMI (branch on negative result)
1240 case 0xF7: //BMI rel
1241 data = fetch();
1242 if (Flags & FLAG_N) BRA(data);
1243 break;
1244 //------------------------------------------------ BPL (branch on positive result)
1245 case 0xF8: //BPL rel
1246 data = fetch();
1247 if (!(Flags & FLAG_N)) BRA(data);
1248 break;
1249 //------------------------------------------------ BGE (branch on result <= 0)
1250 case 0xF9: //BGE rel
1251 data = fetch();
1252 if (!((Flags & FLAG_N) ^ (Flags & FLAG_V))) BRA(data);
1253 break;
1254 //------------------------------------------------ BLE (branch on result >= 0)
1255 case 0xFA: //BLE rel
1256 data = fetch();
1257 if ((Flags & FLAG_Z) | (Flags & FLAG_N) ^ (Flags & FLAG_V)) BRA(data);
1258 break;
1259 //------------------------------------------------ BGT (branch on result < 0)
1260 case 0xFB: //BGT rel
1261 data = fetch();
1262 if (!((Flags & FLAG_Z) | (Flags & FLAG_N) ^ (Flags & FLAG_V))) BRA(data);
1263 break;
1264 //------------------------------------------------ BLT (branch on result > 0)
1265 case 0xFC: //BLT rel
1266 data = fetch();
1267 if ((Flags & FLAG_N) ^ (Flags & FLAG_V)) BRA(data);
1268 break;
1269 //------------------------------------------------ PUSH (pushes register onto stack)
1270 case 0x9E: //PUSH A
1271 PUSH(REGISTER_A);
1272 break;
1273 case 0xAE: //PUSH FL (status reg)
1274 if ((StackPointer >= 1) && (StackPointer < MEMORY_SIZE)) {
1275 Memory[StackPointer] = Flags;
1276 StackPointer--;
1277 }
1278 break;
1279 case 0xBE: //PUSH B
1280 PUSH(REGISTER_B);
1281 break;
1282 case 0xCE: //PUSH C
1283 PUSH(REGISTER_C);
1284 break;
1285 case 0xDE: //PUSH D
1286 PUSH(REGISTER_D);
1287 break;
1288 case 0xEE: //PUSH E
1289 PUSH(REGISTER_E);
1290 break;
1291 case 0xFE: //PUSH F
1292 PUSH(REGISTER_F);
1293 break;
1294 //------------------------------------------------ POP (pop top of stack into register)
1295 case 0x9F: //POP A
1296 POP(REGISTER_A);
1297 break;
1298 case 0xAF: //POP FL
1299 if ((StackPointer >= 0) && (StackPointer < MEMORY_SIZE - 1)) {
1300 StackPointer++;
1301 Flags = Memory[StackPointer];
1302 }
1303 break;
1304 case 0xBF: //POP B
1305 POP(REGISTER_B);
1306 break;
1307 case 0xCF: //POP C
1308 POP(REGISTER_C);
1309 break;
1310 case 0xDF: //POP D
1311 POP(REGISTER_D);
1312 break;
1313 case 0xEF: //POP E
1314 POP(REGISTER_E);
1315 break;
1316 case 0xFF: //POP F
1317 POP(REGISTER_F);
1318 break;
1319 //------------------------------------------------ SWI (software interrupt)
1320 case 0x16: //SWI impl
1321 if (StackPointer >= 1 && StackPointer < MEMORY_SIZE) {
1322 Memory[StackPointer] = Registers[REGISTER_A];
1323 StackPointer--;
1324 }
1325 if (StackPointer >= 1 && StackPointer < MEMORY_SIZE) {
1326 Memory[StackPointer] = Registers[REGISTER_B];
1327 StackPointer--;
1328 }
1329 if (StackPointer >= 1 && StackPointer < MEMORY_SIZE) {
1330 Memory[StackPointer] = Registers[REGISTER_C];
1331 StackPointer--;
1332 }
1333 if (StackPointer >= 1 && StackPointer < MEMORY_SIZE) {
1334 Memory[StackPointer] = Registers[REGISTER_D];
1335 StackPointer--;
1336 }
1337 if (StackPointer >= 1 && StackPointer < MEMORY_SIZE) {
1338 Memory[StackPointer] = Registers[REGISTER_E];
1339 StackPointer--;
1340 }
1341 if (StackPointer >= 1 && StackPointer < MEMORY_SIZE) {
1342 Memory[StackPointer] = Registers[REGISTER_F];
1343 StackPointer--;
1344 }
1345 if (StackPointer >= 1 && StackPointer < MEMORY_SIZE) {
1346 Memory[StackPointer] = Flags;
1347 StackPointer--;
1348 }
1349 break;
1350 //------------------------------------------------ RTI (return from software interrupt)
1351 case 0x17: //RTI impl
1352 if (StackPointer >= 0 && StackPointer < (MEMORY_SIZE - 1)) {
1353 StackPointer++;
1354 Flags = Memory[StackPointer];
1355 }
1356 if (StackPointer >= 0 && StackPointer < (MEMORY_SIZE - 1)) {
1357 StackPointer++;
1358 Registers[REGISTER_F] = Memory[StackPointer];
1359 }
1360 if (StackPointer >= 0 && StackPointer < (MEMORY_SIZE - 1)) {
1361 StackPointer++;
1362 Registers[REGISTER_E] = Memory[StackPointer];
1363 }
1364 if (StackPointer >= 0 && StackPointer < (MEMORY_SIZE - 1)) {
1365 StackPointer++;
1366 Registers[REGISTER_D] = Memory[StackPointer];
1367 }
1368 if (StackPointer >= 0 && StackPointer < (MEMORY_SIZE - 1)) {
1369 StackPointer++;
1370 Registers[REGISTER_C] = Memory[StackPointer];
1371 }
1372 if (StackPointer >= 0 && StackPointer < (MEMORY_SIZE - 1)) {
1373 StackPointer++;
1374 Registers[REGISTER_B] = Memory[StackPointer];
1375 }
1376 if (StackPointer >= 0 && StackPointer < (MEMORY_SIZE - 1)) {
1377 StackPointer++;
1378 Registers[REGISTER_A] = Memory[StackPointer];
1379 }
1380 break;
1381 //------------------------------------------------ SEC (set carry flag)
1382 case 0x19: //SEC impl
1383 Flags = Flags | FLAG_C;
1384 break;
1385 //------------------------------------------------ CLC (clear carry flag)
1386 case 0x18: //CLC impl
1387 Flags = Flags & (0xFF - FLAG_C);
1388 break;
1389 //------------------------------------------------ STI (set interrupt flag)
1390 case 0x1B: //STI impl
1391 Flags = Flags | FLAG_I;
1392 break;
1393 //------------------------------------------------ CLI (clear interrupt flag)
1394 case 0x1A: //CLI impl
1395 Flags = Flags & (0xFF - FLAG_I);
1396 break;
1397 //------------------------------------------------ STV (set overflow flag)
1398 case 0x1C: //STV impl
1399 Flags = Flags | FLAG_V;
1400 break;
1401 //------------------------------------------------ CLV (clear overflow flag)
1402 case 0x1D: //CLV impl
1403 Flags = Flags & (0xFF - FLAG_V);
1404 break;
1405 }
1406}
1407
1408//LD function
1409void Group_2_Move(BYTE opcode) {
1410 BYTE destination = opcode >> 4; //top four bits point at one register....shift right to keep only top four
1411 BYTE source = opcode & 0x0F;//takes bottom four bits
1412 int destReg = 0, sourceReg = 0;
1413
1414 switch (destination) { //COMBO OF DEST AND SOURCE GIVE REGISTERS ADDRESSES TO FOR MEMORY ADRESSER AT BOTTOM
1415 case 0x02://top four bits from op code
1416 destReg = REGISTER_A;
1417 break;
1418 case 0x03:
1419 destReg = REGISTER_B;
1420 break;
1421 case 0x04:
1422 destReg = REGISTER_C;
1423 break;
1424 case 0x05:
1425 destReg = REGISTER_D;
1426 break;
1427 case 0x06:
1428 destReg = REGISTER_E;
1429 break;
1430 case 0x07:
1431 destReg = REGISTER_F;
1432 break;
1433 }
1434
1435 switch (source) {
1436 case 0x0A:
1437 sourceReg = REGISTER_A;
1438 break;
1439 case 0x0B:
1440 sourceReg = REGISTER_B;
1441 break;
1442 case 0x0C:
1443 sourceReg = REGISTER_C;
1444 break;
1445 case 0x0D:
1446 sourceReg = REGISTER_D;
1447 break;
1448 case 0x0E:
1449 sourceReg = REGISTER_E;
1450 break;
1451 case 0x0F:
1452 sourceReg = REGISTER_F;
1453 break;
1454 }
1455
1456 Registers[sourceReg] = Registers[destReg]; //assign source reg to dest reg
1457}
1458
1459void execute(BYTE opcode) {
1460 if (((opcode >= 0x2A) && (opcode <= 0x2F))
1461 || ((opcode >= 0x3A) && (opcode <= 0x3F))
1462 || ((opcode >= 0x4A) && (opcode <= 0x4F))
1463 || ((opcode >= 0x5A) && (opcode <= 0x5F))
1464 || ((opcode >= 0x6A) && (opcode <= 0x6F))
1465 || ((opcode >= 0x7A) && (opcode <= 0x7F)))
1466 {
1467 Group_2_Move(opcode);
1468 }
1469 else Group_1(opcode);
1470}
1471
1472void emulate() {
1473 BYTE opcode;
1474 int sanity = 0;
1475
1476 ProgramCounter = 0;
1477 halt = false;
1478 memory_in_range = true;
1479
1480 //printf(" A B C D E F X Y SP\n");
1481
1482 while ((!halt) && (memory_in_range)) {
1483 sanity++;
1484 if (sanity > 500) halt = true;
1485 // printf("%04X ", ProgramCounter); // Print current address
1486 opcode = fetch();
1487 execute(opcode);
1488 /*
1489 printf("%s ", opcode_mneumonics[opcode]); // Print current opcode
1490 printf("%02X ", Registers[REGISTER_A]);
1491 printf("%02X ", Registers[REGISTER_B]);
1492 printf("%02X ", Registers[REGISTER_C]);
1493 printf("%02X ", Registers[REGISTER_D]);
1494 printf("%02X ", Registers[REGISTER_E]);
1495 printf("%02X ", Registers[REGISTER_F]);
1496 printf("%02X ", Index_Registers[REGISTER_X]);
1497 printf("%02X ", Index_Registers[REGISTER_Y]);
1498 printf("%04X ", StackPointer); // Print Stack Pointer
1499
1500 if ((Flags & FLAG_I) == FLAG_I) printf("I = 1, ");
1501 else printf("I = 0, ");
1502
1503 if ((Flags & FLAG_V) == FLAG_V) printf("V = 1, ");
1504 else printf("V = 0, ");
1505
1506 if ((Flags & FLAG_N) == FLAG_N) printf("N = 1, ");
1507 else printf("N = 0, ");
1508
1509 if ((Flags & FLAG_Z) == FLAG_Z) printf("Z = 1, ");
1510 else printf("Z = 0, ");
1511
1512 if ((Flags & FLAG_C) == FLAG_C) printf("C = 1 ");
1513 else printf("C = 0 ");
1514
1515 printf("\n");*/
1516 }
1517 //printf("\n");
1518}
1519
1520
1521////////////////////////////////////////////////////////////////////////////////
1522// Emulator (End) //
1523////////////////////////////////////////////////////////////////////////////////
1524
1525void initialise_filenames() {
1526 int i;
1527
1528 for (i=0; i<MAX_FILENAME_SIZE; i++) {
1529 hex_file [i] = '\0';
1530 trc_file [i] = '\0';
1531 }
1532}
1533
1534int find_dot_position(char *filename) {
1535 int dot_position;
1536 int i;
1537 char chr;
1538
1539 dot_position = 0;
1540 i = 0;
1541 chr = filename[i];
1542
1543 while (chr != '\0') {
1544 if (chr == '.') dot_position = i;
1545
1546 i++;
1547 chr = filename[i];
1548 }
1549
1550 return dot_position;
1551}
1552
1553int find_end_position(char *filename) {
1554 int end_position;
1555 int i;
1556 char chr;
1557
1558 end_position = 0;
1559 i = 0;
1560 chr = filename[i];
1561
1562 while (chr != '\0') {
1563 end_position = i;
1564 i++;
1565 chr = filename[i];
1566 }
1567
1568 return end_position;
1569}
1570
1571bool file_exists(char *filename) {
1572 bool exists;
1573 FILE *ifp;
1574
1575 exists = false;
1576
1577 if ((ifp = fopen(filename, "r")) != NULL) {
1578 exists = true;
1579
1580 fclose(ifp);
1581 }
1582
1583 return exists;
1584}
1585
1586void create_file(char *filename) {
1587 FILE *ofp;
1588
1589 if ((ofp = fopen(filename, "w")) != NULL) fclose(ofp);
1590}
1591
1592bool getline(FILE *fp, char *buffer) {
1593 bool rc;
1594 bool collect;
1595 char c;
1596 int i;
1597
1598 rc = false;
1599 collect = true;
1600
1601 i = 0;
1602 while (collect) {
1603 c = getc(fp);
1604
1605 switch (c) {
1606 case EOF:
1607 if (i > 0) rc = true;
1608
1609 collect = false;
1610 break;
1611 case '\n':
1612 if (i > 0) {
1613 rc = true;
1614 collect = false;
1615 buffer[i] = '\0';
1616 }
1617 break;
1618 default:
1619 buffer[i] = c;
1620 i++;
1621 }
1622 }
1623
1624 return rc;
1625}
1626
1627void load_and_run(int args,_TCHAR** argv) {
1628 char chr;
1629 int ln;
1630 int dot_position;
1631 int end_position;
1632 long i;
1633 FILE *ifp;
1634 long address;
1635 long load_at;
1636 int code;
1637
1638 // Prompt for the .hex file
1639
1640 printf("\n");
1641 printf("Enter the hex filename (.hex): ");
1642
1643 if(args == 2) {
1644 ln = 0;
1645 chr = argv[1][ln];
1646 while (chr != '\0') {
1647 if (ln < MAX_FILENAME_SIZE) {
1648 hex_file [ln] = chr;
1649 trc_file [ln] = chr;
1650 ln++;
1651 }
1652 chr = argv[1][ln];
1653 }
1654 } else {
1655 ln = 0;
1656 chr = '\0';
1657 while (chr != '\n') {
1658 chr = getchar();
1659
1660 switch(chr) {
1661 case '\n':
1662 break;
1663 default:
1664 if (ln < MAX_FILENAME_SIZE) {
1665 hex_file [ln] = chr;
1666 trc_file [ln] = chr;
1667 ln++;
1668 }
1669 break;
1670 }
1671 }
1672 }
1673 // Tidy up the file names
1674
1675 dot_position = find_dot_position(hex_file);
1676 if (dot_position == 0) {
1677 end_position = find_end_position(hex_file);
1678
1679 hex_file[end_position + 1] = '.';
1680 hex_file[end_position + 2] = 'h';
1681 hex_file[end_position + 3] = 'e';
1682 hex_file[end_position + 4] = 'x';
1683 hex_file[end_position + 5] = '\0';
1684 } else {
1685 hex_file[dot_position + 0] = '.';
1686 hex_file[dot_position + 1] = 'h';
1687 hex_file[dot_position + 2] = 'e';
1688 hex_file[dot_position + 3] = 'x';
1689 hex_file[dot_position + 4] = '\0';
1690 }
1691
1692 dot_position = find_dot_position(trc_file);
1693 if (dot_position == 0) {
1694 end_position = find_end_position(trc_file);
1695
1696 trc_file[end_position + 1] = '.';
1697 trc_file[end_position + 2] = 't';
1698 trc_file[end_position + 3] = 'r';
1699 trc_file[end_position + 4] = 'c';
1700 trc_file[end_position + 5] = '\0';
1701 } else {
1702 trc_file[dot_position + 0] = '.';
1703 trc_file[dot_position + 1] = 't';
1704 trc_file[dot_position + 2] = 'r';
1705 trc_file[dot_position + 3] = 'c';
1706 trc_file[dot_position + 4] = '\0';
1707 }
1708
1709 if (file_exists(hex_file)) {
1710 // Clear Registers and Memory
1711 Registers[REGISTER_A] = 0;
1712 Registers[REGISTER_B] = 0;
1713 Registers[REGISTER_C] = 0;
1714 Registers[REGISTER_D] = 0;
1715 Registers[REGISTER_E] = 0;
1716 Registers[REGISTER_F] = 0;
1717 Index_Registers[REGISTER_X] = 0;
1718 Index_Registers[REGISTER_Y] = 0;
1719 Flags = 0;
1720 ProgramCounter = 0;
1721 StackPointer = 0;
1722
1723 for (i = 0; i < MEMORY_SIZE; i++) Memory[i] = 0x00;
1724
1725 // Load hex file
1726 if ((ifp = fopen(hex_file, "r")) != NULL) {
1727 printf("Loading file...\n\n");
1728
1729 load_at = 0;
1730
1731 while (getline(ifp, InputBuffer)) {
1732 if (sscanf(InputBuffer, "L=%x", &address) == 1) load_at = address;
1733 else if (sscanf(InputBuffer, "%x", &code) == 1) {
1734 if ((load_at >= 0) && (load_at <= MEMORY_SIZE)) Memory[load_at] = (BYTE)code;
1735
1736 load_at++;
1737 } else printf("ERROR> Failed to load instruction: %s \n", InputBuffer);
1738 }
1739
1740 fclose(ifp);
1741 }
1742
1743 emulate();
1744 } else {
1745 printf("\n");
1746 printf("ERROR> Input file %s does not exist!\n", hex_file);
1747 printf("\n");
1748 }
1749}
1750
1751void building(int args,_TCHAR** argv){
1752 char buffer[1024];
1753 load_and_run(args,argv);
1754 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",
1755 Memory[TEST_ADDRESS_1],
1756 Memory[TEST_ADDRESS_2],
1757 Memory[TEST_ADDRESS_3],
1758 Memory[TEST_ADDRESS_4],
1759 Memory[TEST_ADDRESS_5],
1760 Memory[TEST_ADDRESS_6],
1761 Memory[TEST_ADDRESS_7],
1762 Memory[TEST_ADDRESS_8],
1763 Memory[TEST_ADDRESS_9],
1764 Memory[TEST_ADDRESS_10],
1765 Memory[TEST_ADDRESS_11],
1766 Memory[TEST_ADDRESS_12]
1767 );
1768 sendto(sock, buffer, strlen(buffer), 0, (SOCKADDR *)&server_addr, sizeof(SOCKADDR));
1769}
1770
1771void test_and_mark() {
1772 char buffer[1024];
1773 bool testing_complete;
1774 int len = sizeof(SOCKADDR);
1775 char chr;
1776 int i;
1777 int j;
1778 bool end_of_program;
1779 long address;
1780 long load_at;
1781 int code;
1782 int mark;
1783 int passed;
1784
1785 printf("Automatic Testing and Marking\n");
1786 printf("\n");
1787
1788 testing_complete = false;
1789
1790 sprintf(buffer, "Test Student %s", STUDENT_NUMBER);
1791 sendto(sock, buffer, strlen(buffer), 0, (SOCKADDR *)&server_addr, sizeof(SOCKADDR));
1792
1793 while (!testing_complete) {
1794 memset(buffer, '\0', sizeof(buffer));
1795
1796 if (recvfrom(sock, buffer, sizeof(buffer)-1, 0, (SOCKADDR *)&client_addr, &len) != SOCKET_ERROR) {
1797 //printf("Incoming Data: %s \n", buffer);/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1798
1799 //if (strcmp(buffer, "Testing complete") == 1)
1800 if (sscanf(buffer, "Testing complete %d", &mark) == 1) {
1801 testing_complete = true;
1802 printf("Current mark = %d\n", mark);
1803 }else if (sscanf(buffer, "Tests passed %d", &passed) == 1) {
1804 //testing_complete = true;
1805 printf("Passed = %d\n", passed);
1806 } else if (strcmp(buffer, "Error") == 0) {
1807 printf("ERROR> Testing abnormally terminated\n");
1808 testing_complete = true;
1809 } else {
1810 // Clear Registers and Memory
1811 Registers[REGISTER_A] = 0;
1812 Registers[REGISTER_B] = 0;
1813 Registers[REGISTER_C] = 0;
1814 Registers[REGISTER_D] = 0;
1815 Registers[REGISTER_E] = 0;
1816 Registers[REGISTER_F] = 0;
1817 Index_Registers[REGISTER_X] = 0;
1818 Index_Registers[REGISTER_Y] = 0;
1819 Flags = 0;
1820 ProgramCounter = 0;
1821 StackPointer = 0;
1822 for (i = 0; i < MEMORY_SIZE; i++) Memory[i] = 0;
1823
1824 // Load hex file
1825 i = 0;
1826 j = 0;
1827 load_at = 0;
1828 end_of_program = false;
1829 FILE *ofp;
1830 fopen_s(&ofp ,"branch.txt", "a");
1831
1832 while (!end_of_program) {
1833 chr = buffer[i];
1834 switch (chr) {
1835 case '\0':
1836 end_of_program = true;
1837 case ',':
1838 if (sscanf(InputBuffer, "L=%x", &address) == 1) load_at = address;
1839 else if (sscanf(InputBuffer, "%x", &code) == 1) {
1840 if ((load_at >= 0) && (load_at <= MEMORY_SIZE)) {
1841 Memory[load_at] = (BYTE)code;
1842 fprintf(ofp, "%02X\n", (BYTE)code);
1843 }
1844 load_at++;
1845 } else printf("ERROR> Failed to load instruction: %s \n", InputBuffer);
1846
1847 j = 0;
1848 break;
1849 default:
1850 InputBuffer[j] = chr;
1851 j++;
1852 break;
1853 }
1854 i++;
1855 }
1856 fclose(ofp);
1857 // Emulate
1858
1859 if (load_at > 1) {
1860 emulate();
1861 // Send and store results
1862 sprintf(buffer, "%02X%02X %02X%02X %02X%02X %02X%02X %02X%02X %02X%02X",
1863 Memory[TEST_ADDRESS_1],
1864 Memory[TEST_ADDRESS_2],
1865 Memory[TEST_ADDRESS_3],
1866 Memory[TEST_ADDRESS_4],
1867 Memory[TEST_ADDRESS_5],
1868 Memory[TEST_ADDRESS_6],
1869 Memory[TEST_ADDRESS_7],
1870 Memory[TEST_ADDRESS_8],
1871 Memory[TEST_ADDRESS_9],
1872 Memory[TEST_ADDRESS_10],
1873 Memory[TEST_ADDRESS_11],
1874 Memory[TEST_ADDRESS_12]
1875 );
1876 sendto(sock, buffer, strlen(buffer), 0, (SOCKADDR *)&server_addr, sizeof(SOCKADDR));
1877 }
1878 }
1879 }
1880 }
1881}
1882
1883int _tmain(int argc, _TCHAR* argv[]) {
1884 char chr;
1885 char dummy;
1886
1887 printf("Microprocessor Emulator\n");
1888 printf("UWE Computer and Network Systems Assignment 1\n");
1889 printf("\n");
1890
1891 initialise_filenames();
1892
1893 if (WSAStartup(MAKEWORD(2, 2), &data) != 0) return(0);
1894
1895 sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Here we create our socket, which will be a UDP socket (SOCK_DGRAM).
1896 if (!sock) {
1897 //Creation failed!
1898 }
1899
1900 memset(&server_addr, 0, sizeof(SOCKADDR_IN));
1901 server_addr.sin_family = AF_INET;
1902 server_addr.sin_addr.s_addr = inet_addr(IP_ADDRESS_SERVER);
1903 server_addr.sin_port = htons(PORT_SERVER);
1904
1905 memset(&client_addr, 0, sizeof(SOCKADDR_IN));
1906 client_addr.sin_family = AF_INET;
1907 client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
1908 client_addr.sin_port = htons(PORT_CLIENT);
1909
1910 chr = '\0';
1911 while ((chr != 'e') && (chr != 'E')) {
1912 printf("\nPlease select option\n");
1913 printf("L - Load and run a hex file\n");
1914 printf("T - Have the server test and mark your emulator\n");
1915 printf("E - Exit\n");
1916 if(argc == 2){ building(argc,argv); exit(0);}
1917 printf("Enter option: ");
1918 chr = getchar();
1919 if (chr != 0x0A) dummy = getchar(); // read in the <CR>
1920
1921 printf("\n");
1922
1923 switch (chr) {
1924 case 'L': case 'l':
1925 load_and_run(argc,argv);
1926 break;
1927 case 'T': case 't':
1928 test_and_mark();
1929 break;
1930 }
1931 }
1932
1933 closesocket(sock);
1934 WSACleanup();
1935
1936 return 0;
1937}