8080-Emulator  0.1
An Intel 8080 emulator for Space Invaders
opcodes_8080.h
Go to the documentation of this file.
1 
9 #ifndef OPCODES_8080_H
10 #define OPCODES_8080_H
11 
12 #include <inttypes.h>
13 #include "cpu_8080.h"
14 #include "memory_8080.h"
15 
17 #define ILLEGAL_OP DEBUG_PRINT("%s\n", "Illegal OP!");
18 
23 typedef int (* OP_WRAP)(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code);
24 
29 typedef struct {
31  uint8_t cycle_count;
32  uint8_t size;
34 
45 uint8_t* ref_byte_reg(cpu_state* cpu ,uint8_t reg_identifier){
46  switch (reg_identifier)
47  {
48  case 0x0:
49  return &cpu->B;
50  case 0x01:
51  return &cpu->C;
52  case 0x02:
53  return &cpu->D;
54  case 0x03:
55  return &cpu->E;
56  case 0x04:
57  return &cpu->H;
58  case 0x05:
59  return &cpu->L;
60  case 0x06:
61  return (uint8_t *)mem_ref(&cpu->mem, cpu->HL);
62  case 0x07:
63  return &cpu->ACC;
64  default:
65  ILLEGAL_OP; // Will never reach here now.
66  return (uint8_t*)-1;
67  }
68 }
69 
80 uint16_t* ref_short_reg(cpu_state* cpu ,uint8_t reg_identifier){
81  switch (reg_identifier)
82  {
83  case 0x0:
84  return &cpu->BC;
85  case 0x01:
86  return &cpu->DE;
87  case 0x02:
88  return &cpu->HL;
89  case 0x03:
90  return &cpu->SP;
91  default:
92  return (uint16_t*)-1;
93  }
94 }
95 
103 uint8_t condition_check(cpu_state* cpu, condition_flags condition_identifier){
104  switch (condition_identifier)
105  {
106  case NZ_check:
107  if(!cpu->PSW.zero){
108  return 1;
109  }
110  return 0;
111  case Z_check:
112  if(cpu->PSW.zero){
113  return 1;
114  }
115  return 0;
116  case NC_check:
117  if(!cpu->PSW.carry){
118  return 1;
119  }
120  return 0;
121  case C_check:
122  if(cpu->PSW.carry){
123  return 1;
124  }
125  return 0;
126  case PO_check:
127  if(!cpu->PSW.parity){
128  return 1;
129  }
130  return 0;
131  case PE_check:
132  if(cpu->PSW.parity){
133  return 1;
134  }
135  return 0;
136  case P_check:
137  if(!cpu->PSW.sign){
138  return 1;
139  }
140  return 0;
141  case M_check:
142  if(cpu->PSW.sign){
143  return 1;
144  }
145  return 0;
146  default:
147  DEBUG_PRINT("%s\n", "Unknow Condition Code.");
148  ILLEGAL_OP;
149  exit(-2);
150  }
151 }
152 
160 void set_flags(cpu_state* cpu ,uint32_t final_state, uint8_t flags){
161  if(flags & SIGN_FLAG){
162  cpu->PSW.sign = (final_state & 0x80) ? 1:0;
163  }
164  if (flags & ZERO_FLAG){
165  cpu->PSW.zero = (final_state & 0xFF) == 0 ? 1:0;
166  }
167  if (flags & AUX_FLAG){
168  DEBUG_PRINT("%s\n", "AUX Flag is very specific to operation");
169  ILLEGAL_OP;
170  }
171  if (flags & PARITY_FLAG){
172  uint8_t pf = 1;
173  // checking only for the fist 8 bytes
174  uint8_t rr = final_state & 0xFF;
175  // using xor to toggle the parity flag
176  while(rr){
177  pf ^= (rr&1);
178  rr >>= 1;
179  }
180  cpu->PSW.parity = pf;
181  }
182  if (flags & CARRY_FLAG){
183  cpu->PSW.carry = (final_state & 0x100) ? 1 : 0;
184  }
185  return;
186 }
187 
199 void aux_flag_set_add(cpu_state* cpu, uint32_t base_val, uint32_t diff){
200  uint8_t xor = (base_val ^ diff) & 0x10; // basically if 0|1 -> 1 else 0
201  uint8_t summ = (base_val + diff) & 0x10; // xor + propagate
202  if( xor != summ ){
203  cpu->PSW.aux = 1;
204  } else {
205  cpu->PSW.aux = 0;
206  }
207 }
208 
217  uint8_t status = 0;
218  status |= psw.carry ? CARRY_FLAG : 0;
219  status |= psw.aux ? AUX_FLAG : 0;
220  status |= psw.sign ? SIGN_FLAG : 0;
221  status |= psw.zero ? ZERO_FLAG : 0;
222  status |= psw.parity ? PARITY_FLAG : 0;
223  return status;
224 }
225 
234  program_status_word new_status;
235  new_status.carry = status & CARRY_FLAG ? 1 : 0;
236  new_status.aux = status & AUX_FLAG ? 1 : 0;
237  new_status.sign = status & SIGN_FLAG ? 1 : 0;
238  new_status.zero = status & ZERO_FLAG ? 1 : 0;
239  new_status.parity = status & PARITY_FLAG ? 1 : 0;
240  return new_status;
241 }
242 
251 int UNDEFINED_OP_WRAP(UNUSED cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
252  DECOMPILE_PRINT(base_PC, "(%x)This Opcode has not been initialized.\n", op_code);
253  return -1;
254 }
255 
264 int NOP_WRAP(UNUSED cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
265  DECOMPILE_PRINT(base_PC, "%s\n", "NOP");
266  return 1;
267 }
268 
277 int LXI_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
278  uint8_t reg_patt = (0x30 & op_code) >> 4;
279  uint16_t imm_data = short_mem_read(&cpu->mem, base_PC+1);
280  uint16_t* target_dest = ref_short_reg(cpu, reg_patt);
281  *target_dest = imm_data;
282  DECOMPILE_PRINT(base_PC, "LXI REGP(%x), %x\n", reg_patt, imm_data);
283  return 1;
284 }
285 
296 int JMP_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
297  switch (op_code)
298  {
299  case 0xC3:
300  cpu->PC = short_mem_read(&cpu->mem, base_PC+1);
301  DECOMPILE_PRINT(base_PC, "JMP %x\n", cpu->PC);
302  break;
303  case 0xCB:
304  DEBUG_PRINT("%s\n", "UNINIMPLEMENTED.");
305  ILLEGAL_OP;
306  exit(-3);
307  default:
308  ILLEGAL_OP;
309  exit(-2);
310  }
311  return 1;
312 }
313 
322 int MVI_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
323  uint8_t reg_patt = (0x38 & op_code) >> 3;
324  uint8_t imm_data = mem_read(&cpu->mem, base_PC+1);
325  uint8_t* target_dest = ref_byte_reg(cpu, reg_patt);
326  *target_dest = imm_data;
327  DECOMPILE_PRINT(base_PC, "MVI REG(%x), %x\n", reg_patt, imm_data);
328  return 1;
329 }
330 
341 int CALL_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
342  switch (op_code)
343  {
344  case 0xCD:
345  cpu->SP -= 2;
346  short_mem_write(&cpu->mem, cpu->SP, cpu->PC); // Saving Return Addr
347  cpu->PC = short_mem_read(&cpu->mem, base_PC+1); // Reading the new PC
348  DECOMPILE_PRINT(base_PC, "CALL %x\n", cpu->PC ); // Logging
349  break;
350  default:
351  // There was CALL at 0x[D-F]D which didn't have stuff
352  // in the manual
353  ILLEGAL_OP;
354  break;
355  }
356  return 1;
357 }
358 
370 int LDAX_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
371  uint8_t reg_patt = (0x30 & op_code) >> 4;
372  if(reg_patt < 2){
373  uint16_t* target_dest = ref_short_reg(cpu, reg_patt);
374  cpu->ACC = mem_read(&cpu->mem, *target_dest);
375  DECOMPILE_PRINT(base_PC, "LDAX REGP(%x), %x\n", reg_patt, cpu->ACC);
376  } else {
377  ILLEGAL_OP;
378  exit(-2);
379  }
380  return 1;
381 }
382 
395 int MOV_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
396  uint8_t dest_reg_patt = (0x38 & op_code) >> 3;
397  uint8_t src_reg_patt = (0x07 & op_code);
398  uint8_t *dest_reg = ref_byte_reg(cpu, dest_reg_patt);
399  uint8_t *src_reg = ref_byte_reg(cpu, src_reg_patt);
400  *dest_reg = *src_reg;
401  DECOMPILE_PRINT(base_PC, "MOV REGDest(%x), REGSrc(%x)\n", dest_reg_patt, src_reg_patt);
402  return 1;
403 }
404 
414 int HLT_WRAP(UNUSED cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
415  DECOMPILE_PRINT(base_PC, "%s\n", "HLT");
416  cpu->halt = 1;
417  return 1;
418 }
419 
430 int INX_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
431  uint8_t reg_patt = (0x30 & op_code) >> 4;
432  uint16_t* target_dest = ref_short_reg(cpu, reg_patt);
433  *target_dest += 1;
434  DECOMPILE_PRINT(base_PC, "INX REGP(%x)\n", reg_patt);
435  return 1;
436 }
437 
447 int DCR_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
448  uint8_t target_reg = (op_code & 0x38) >> 3;
449  uint16_t target_data = *(ref_byte_reg(cpu, target_reg));
450  uint16_t base_data = target_data;
451  // Update The data
452  target_data -= 1;
453  *(ref_byte_reg(cpu, target_reg)) = (uint8_t)target_data;
454  // Update Flags
455  set_flags(cpu, target_data, SIGN_FLAG | ZERO_FLAG | PARITY_FLAG );
456  aux_flag_set_add(cpu, base_data, -1);
457  DECOMPILE_PRINT(base_PC, "DCR REG(%x)\n", target_reg);
458  return 1;
459 }
460 
469 int JCon_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
470  if(condition_check(cpu, (0x38 & op_code)>>3)){
471  cpu->PC = short_mem_read(&cpu->mem, base_PC+1);
472  }
473  DECOMPILE_PRINT(base_PC, "JMP Con(%x) %x\n", (0x38 & op_code)>>3,
474  short_mem_read(&cpu->mem, base_PC+1));
475  return 1;
476 }
477 
492 int RET_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
493  if(op_code == 0xC9){
494  cpu->PC = short_mem_read(&cpu->mem, cpu->SP);
495  cpu->SP += 2;
496  DECOMPILE_PRINT(base_PC, "%s\n", "RET");
497  } else {
498  ILLEGAL_OP;
499  exit(-2);
500  }
501  return 1;
502 }
503 
512 int RCon_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
513  DECOMPILE_PRINT(base_PC, "RET Cond(%x)\n", (op_code & 0x38) >> 3);
514  if(condition_check(cpu, (op_code & 0x38) >> 3)){
515  cpu->PC = short_mem_read(&cpu->mem, cpu->SP);
516  cpu->SP += 2;
517  }
518  return 1;
519 }
520 
529 int CMP_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
530  uint16_t acc_reg = cpu->ACC;
531  uint16_t compare_src = *(ref_byte_reg(cpu, (op_code & 0x07)));
532  // Perform Comparison
533  uint16_t diff = acc_reg - compare_src;
534  // Update Flags
535  set_flags(cpu, diff, SIGN_FLAG | ZERO_FLAG | PARITY_FLAG | CARRY_FLAG);
536  aux_flag_set_add(cpu, acc_reg, -compare_src);
537  DECOMPILE_PRINT(base_PC, "CMP REG(%x)\n", (op_code & 0x07));
538  return 1;
539 }
540 
549 int CPI_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
550  uint16_t acc_reg = cpu->ACC;
551  uint16_t compare_src = mem_read(&cpu->mem, base_PC+1);
552  // Perform Comparison
553  uint16_t diff = acc_reg - compare_src;
554  // Update Flags
555  set_flags(cpu, diff, SIGN_FLAG | ZERO_FLAG | PARITY_FLAG | CARRY_FLAG);
556  aux_flag_set_add(cpu, acc_reg, -compare_src);
557  DECOMPILE_PRINT(base_PC, "CPI %x\n", compare_src);
558  return 1;
559 }
560 
571 int PUSH_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
572  uint8_t reg_patt = (0x30 & op_code) >> 4;
573  // Swap out SP for PSW.
574  if(reg_patt == 0x3){
575  cpu->SP -= 2;
576  mem_write(&cpu->mem, cpu->SP, compress_PSW(cpu->PSW));
577  mem_write(&cpu->mem, cpu->SP+1, cpu->ACC);
578  DECOMPILE_PRINT(base_PC, "%s\n", "PUSH PSW");
579  } else {
580  uint16_t* target_dest = ref_short_reg(cpu, reg_patt);
581  cpu->SP -= 2;
582  short_mem_write(&cpu->mem, cpu->SP, *target_dest);
583  DECOMPILE_PRINT(base_PC, "PUSH REGP(%x)\n", reg_patt);
584  }
585  return 1;
586 }
587 
598 int POP_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
599  uint8_t reg_patt = (0x30 & op_code) >> 4;
600  // Swap out SP for PSW.
601  if(reg_patt == 0x3){
602  cpu->PSW = decompress_PSW(mem_read(&cpu->mem, cpu->SP));
603  cpu->ACC = mem_read(&cpu->mem, cpu->SP+1);
604  cpu->SP += 2;
605  DECOMPILE_PRINT(base_PC, "%s\n", "POP PSW");
606  } else {
607  uint16_t* target_dest = ref_short_reg(cpu, reg_patt);
608  *target_dest = short_mem_read(&cpu->mem, cpu->SP);
609  cpu->SP += 2;
610  DECOMPILE_PRINT(base_PC, "POP REGP(%x)\n", reg_patt);
611  }
612  return 1;
613 }
614 
627 int DAD_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
628  uint8_t reg_patt = (0x30 & op_code) >> 4;
629  uint16_t* target_dest = ref_short_reg(cpu, reg_patt);
630  uint32_t temp = cpu->HL;
631  temp += *target_dest;
632  // Update HL
633  cpu->HL = temp & 0xFFFF;
634  // Set Carry Flag
635  cpu->PSW.carry = (cpu->HL < temp) ? 1 : 0;
636  DECOMPILE_PRINT(base_PC, "DAD REG(%x)\n", reg_patt);
637  return 1;
638 }
639 
648 int XCHG_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
649  uint16_t temp = cpu->HL;
650  cpu->HL = cpu->DE;
651  cpu->DE = temp;
652  DECOMPILE_PRINT(base_PC, "%s\n", "XCHG");
653  return 1;
654 }
655 
664 int OUT_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
665  uint8_t port = mem_read(&cpu->mem, base_PC+1);
666  cpu->OUT_Func(port, cpu->ACC);
667  DECOMPILE_PRINT(base_PC, "OUT %x\n", port);
668  return 1;
669 }
670 
680 int IN_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
681  uint8_t port = mem_read(&cpu->mem, base_PC+1);
682  cpu->ACC = cpu->IN_Func(port);
683  DECOMPILE_PRINT(op_code, "IN %x\n", port);
684  return 1;
685 }
686 
695 int STAX_WRAP(cpu_state* cpu, UNUSED UNUSED uint16_t base_PC, uint8_t op_code){
696  uint8_t reg_patt = (0x30 & op_code) >> 4;
697  if(reg_patt < 2){
698  uint16_t* target_ref = ref_short_reg(cpu, reg_patt);
699  mem_write(&cpu->mem, *target_ref, cpu->ACC);
700  DECOMPILE_PRINT(base_PC, "STAX *(REGP(%x)), A\n", reg_patt);
701  } else {
702  ILLEGAL_OP;
703  exit(-2);
704  }
705  return 1;
706 }
707 
719 int ANA_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
720  uint8_t reg_patt = (0x07 & op_code);
721  uint8_t *target_reg = ref_byte_reg(cpu, reg_patt);
722  // Perform AND
723  uint8_t base_val = cpu->ACC;
724  uint8_t base_target = *target_reg;
725  cpu->ACC &= (*target_reg);
726  // Update Flags
727  set_flags(cpu, cpu->ACC, ALL_BUT_AUX_FLAG);
728  // https://www.quora.com/What-is-the-auxiliary-carry-set-when-ANA-R-instruction-is-executed-in-an-8085-CPU
729  cpu->PSW.aux = ((base_val | base_target) & 0x08) ? 1 : 0;
730  DECOMPILE_PRINT(base_PC, "ANA REG(%x)\n", reg_patt);
731  return 1;
732 }
733 
743 int LHLD_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
744  uint16_t target_addr = short_mem_read(&cpu->mem, base_PC+1);
745  cpu->HL = short_mem_read(&cpu->mem, target_addr);
746  DECOMPILE_PRINT(base_PC, "LHLD %x\n", target_addr);
747  return 1;
748 }
749 
759 int ANI_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
760  uint8_t target_data = mem_read(&cpu->mem, base_PC+1);
761  uint8_t base_val = cpu->ACC;
762  cpu->ACC &= target_data;
763  set_flags(cpu, cpu->ACC, ALL_BUT_AUX_FLAG);
764  // https://www.quora.com/What-is-the-auxiliary-carry-set-when-ANA-R-instruction-is-executed-in-an-8085-CPU
765  cpu->PSW.aux = ((base_val | target_data) & 0x08) ? 1 : 0;
766  DECOMPILE_PRINT(base_PC, "ANI %x\n", target_data);
767  return 1;
768 }
769 
778 int STA_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
779  uint16_t target_loc = short_mem_read(&cpu->mem, base_PC+1);
780  mem_write(&cpu->mem, target_loc, cpu->ACC);
781  DECOMPILE_PRINT(base_PC, "STA %x\n", target_loc);
782  return 1;
783 }
784 
793 int INR_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
794  uint8_t reg_patt = (op_code & 0x38) >> 3;
795  uint16_t target_data = *(ref_byte_reg(cpu, reg_patt));
796  uint16_t base_data = target_data;
797  // Update The data
798  target_data += 1;
799  *(ref_byte_reg(cpu, reg_patt)) = (uint8_t)target_data;
800  // Update Flags
801  set_flags(cpu, target_data, SIGN_FLAG | ZERO_FLAG | PARITY_FLAG );
802  aux_flag_set_add(cpu, base_data, +1);
803  DECOMPILE_PRINT(base_PC, "INR Reg(%x)\n", reg_patt);
804  return 1;
805 }
806 
817 int RRC_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
818  uint8_t lsb = 0x1 & cpu->ACC;
819  cpu->ACC >>= 1;
820  if(lsb){
821  cpu->ACC |= 0x80;
822  cpu->PSW.carry = 1;
823  } else {
824  cpu->PSW.carry = 0;
825  }
826  DECOMPILE_PRINT(base_PC, "%s\n", "RRC");
827  return 1;
828 }
829 
839 int LDA_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
840  uint16_t target_addr = short_mem_read(&cpu->mem, base_PC+1);
841  cpu->ACC = short_mem_read(&cpu->mem, target_addr);
842  DECOMPILE_PRINT(base_PC, "LDA %x\n", target_addr);
843  return 1;
844 }
845 
855 int XRA_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
856  uint8_t reg_patt = (op_code & 0x07);
857  uint8_t *target_reg = ref_byte_reg(cpu, reg_patt);
858  uint16_t temp = (*target_reg) ^ cpu->ACC;
859  cpu->ACC = temp;
860  // Setting flags
861  set_flags(cpu, temp, ALL_BUT_AUX_FLAG);
862  cpu->PSW.aux = 0;
863  DECOMPILE_PRINT(base_PC, "XRA Reg(%x)\n", reg_patt);
864  return 1;
865 }
866 
875 int EI_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
876  cpu->intt = 1;
877  DECOMPILE_PRINT(base_PC, "%s\n", "EI");
878  return 1;
879 }
880 
889 int DI_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
890  cpu->intt = 0;
891  DECOMPILE_PRINT(base_PC, "%s\n", "DI");
892  return 1;
893 }
894 
904 int SHLD_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
905  uint16_t target_addr = short_mem_read(&cpu->mem, base_PC+1);
906  short_mem_write(&cpu->mem, target_addr, cpu->HL);
907  DECOMPILE_PRINT(base_PC, "SHLD %x\n", target_addr);
908  return 1;
909 }
910 
919 int DCX_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
920  uint8_t reg_patt = (op_code & 0x30) >> 4;
921  uint16_t* target_reg = ref_short_reg(cpu, reg_patt);
922  (*target_reg)--;
923  DECOMPILE_PRINT(base_PC, "DCX REGP(%x)\n", reg_patt);
924  return 1;
925 }
926 
936 int RLC_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
937  uint8_t msb = (cpu->ACC & 0x80) ? 1 : 0;
938  cpu->ACC <<= 1;
939  if(msb){
940  cpu->ACC |= msb;
941  cpu->PSW.carry = 1;
942  } else {
943  cpu->PSW.carry = 0;
944  }
945  DECOMPILE_PRINT(base_PC, "%s\n", "RLC");
946  return 1;
947 }
948 
958 int RAL_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
959  uint8_t msb = (cpu->ACC & 0x80) ? 1 : 0;
960  cpu->ACC = (cpu->ACC << 1) | cpu->PSW.carry;
961  if(msb){
962  cpu->PSW.carry = 1;
963  } else {
964  cpu->PSW.carry = 0;
965  }
966  DECOMPILE_PRINT(base_PC, "%s\n", "RAL");
967  return 1;
968 }
969 
979 int RAR_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
980  uint8_t lsb = cpu->ACC & 0x01;
981  cpu->ACC = (cpu->ACC >> 1) | (cpu->PSW.carry ? 0x80 : 0x0);
982  if(lsb){
983  cpu->PSW.carry = 1;
984  } else {
985  cpu->PSW.carry = 0;
986  }
987  DECOMPILE_PRINT(base_PC, "%s\n", "RAR");
988  return 1;
989 }
990 
1004 int CCon_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
1005  if(condition_check(cpu, (0x38 & op_code)>>3)){
1006  cpu->SP -= 2;
1007  short_mem_write(&cpu->mem, cpu->SP, cpu->PC); // Saving Return Addr
1008  cpu->PC = short_mem_read(&cpu->mem, base_PC+1); // Reading the new PC
1009  }
1010  DECOMPILE_PRINT(base_PC, "CALL Con(%x) %x\n", (0x38 & op_code)>>3,
1011  short_mem_read(&cpu->mem, base_PC+1));
1012  return 1;
1013 }
1014 
1028 int SBI_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1029  uint8_t target_data = mem_read(&cpu->mem, base_PC+1);
1030  uint16_t temp = cpu->ACC;
1031  temp = temp - target_data - cpu->PSW.carry;
1032  // Set flags
1033  set_flags(cpu, temp, ALL_BUT_AUX_FLAG);
1034  aux_flag_set_add(cpu, cpu->ACC, -target_data - cpu->PSW.carry);
1035  cpu->ACC = temp;
1036  DECOMPILE_PRINT(base_PC, "SBI %x\n", target_data);
1037  return 1;
1038 }
1039 
1051 int ADD_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
1052  uint8_t reg_patt = (op_code & 0x07);
1053  uint16_t temp = *(ref_byte_reg(cpu, reg_patt));
1054  temp += cpu->ACC;
1055  // Set Flags
1056  set_flags(cpu, temp, ALL_BUT_AUX_FLAG);
1057  aux_flag_set_add(cpu, cpu->ACC, *(ref_byte_reg(cpu, reg_patt)));
1058  cpu->ACC = temp;
1059  DECOMPILE_PRINT(base_PC, "ADD REG(%x)\n", reg_patt);
1060  return 1;
1061 }
1062 
1075 int ADI_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1076  uint16_t temp = mem_read(&cpu->mem, base_PC+1);
1077  temp += cpu->ACC;
1078  // Set Flags
1079  set_flags(cpu, temp, ALL_BUT_AUX_FLAG);
1080  aux_flag_set_add(cpu, cpu->ACC, mem_read(&cpu->mem, base_PC+1));
1081  cpu->ACC = temp;
1082  DECOMPILE_PRINT(base_PC, "ADI %x\n", mem_read(&cpu->mem, base_PC+1));
1083  return 1;
1084 }
1085 
1098 int ADC_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
1099  uint8_t reg_patt = (op_code & 0x07);
1100  uint16_t temp = *(ref_byte_reg(cpu, reg_patt));
1101  temp += cpu->ACC + cpu->PSW.carry;
1102  // Set Flags
1103  set_flags(cpu, temp, ALL_BUT_AUX_FLAG);
1104  aux_flag_set_add(cpu, cpu->ACC, *(ref_byte_reg(cpu, reg_patt)) + cpu->PSW.carry);
1105  cpu->ACC = temp;
1106  DECOMPILE_PRINT(base_PC, "ADC REG(%x)\n", reg_patt);
1107  return 1;
1108 }
1109 
1122 int ACI_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1123  uint16_t temp = mem_read(&cpu->mem, base_PC+1);
1124  temp += cpu->ACC + cpu->PSW.carry;
1125  // Set Flags
1126  set_flags(cpu, temp, ALL_BUT_AUX_FLAG);
1127  aux_flag_set_add(cpu, cpu->ACC, mem_read(&cpu->mem, base_PC+1) + cpu->PSW.carry);
1128  cpu->ACC = temp;
1129  DECOMPILE_PRINT(base_PC, "ACI %x\n", mem_read(&cpu->mem, base_PC+1));
1130  return 1;
1131 }
1132 
1143 int SUB_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
1144  uint8_t reg_patt = (op_code & 0x07);
1145  uint16_t temp = cpu->ACC;
1146  temp -= *(ref_byte_reg(cpu, reg_patt));
1147  // Set Flags
1148  set_flags(cpu, temp, ALL_BUT_AUX_FLAG);
1149  aux_flag_set_add(cpu, cpu->ACC, - (*(ref_byte_reg(cpu, reg_patt))));
1150  cpu->ACC = temp;
1151  DECOMPILE_PRINT(base_PC, "SUB REG(%x)\n", reg_patt);
1152  return 1;
1153 }
1154 
1167 int SUI_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1168  uint16_t temp = cpu->ACC;
1169  temp -= mem_read(&cpu->mem, base_PC+1);
1170  // Set Flags
1171  set_flags(cpu, temp, ALL_BUT_AUX_FLAG);
1172  aux_flag_set_add(cpu, cpu->ACC, - (mem_read(&cpu->mem, base_PC+1)));
1173  cpu->ACC = temp;
1174  DECOMPILE_PRINT(base_PC, "SUI %x\n", mem_read(&cpu->mem, base_PC+1));
1175  return 1;
1176 }
1177 
1190 int SBB_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
1191  uint8_t reg_patt = (op_code & 0x07);
1192  uint16_t temp = cpu->ACC;
1193  temp -= (*(ref_byte_reg(cpu, reg_patt)) + cpu->PSW.carry);
1194  // Set Flags
1195  set_flags(cpu, temp, ALL_BUT_AUX_FLAG);
1196  aux_flag_set_add(cpu, cpu->ACC, - (*(ref_byte_reg(cpu, reg_patt))) - 1);
1197  cpu->ACC = temp;
1198  DECOMPILE_PRINT(base_PC, "SBB REG(%x)\n", reg_patt);
1199  return 1;
1200 }
1201 
1214 int ORA_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
1215  uint8_t reg_patt = (op_code & 0x07);
1216  uint8_t *target_reg = ref_byte_reg(cpu, reg_patt);
1217  uint16_t temp = (*target_reg) | cpu->ACC;
1218  cpu->ACC = temp;
1219  // Setting flags
1220  set_flags(cpu, temp, ALL_BUT_AUX_FLAG);
1221  cpu->PSW.aux = 0;
1222  DECOMPILE_PRINT(base_PC, "ORA Reg(%x)\n", reg_patt);
1223  return 1;
1224 }
1225 
1236 int XTHL_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1237  uint16_t temp = short_mem_read(&cpu->mem, cpu->SP);
1238  short_mem_write(&cpu->mem,cpu->SP,cpu->HL);
1239  cpu->HL = temp;
1240  DECOMPILE_PRINT(base_PC, "%s\n", "XTHL");
1241  return 1;
1242 }
1243 
1257 int PCHL_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1258  cpu->PC = cpu->HL;
1259  DECOMPILE_PRINT(base_PC, "%s\n", "PCHL");
1260  return 1;
1261 }
1262 
1276 int ORI_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1277  uint8_t target_data = mem_read(&cpu->mem, base_PC+1);
1278  cpu->ACC |= target_data;
1279  set_flags(cpu, cpu->ACC, ALL_BUT_AUX_FLAG);
1280  cpu->PSW.aux = 0;
1281  DECOMPILE_PRINT(base_PC, "ORI %x\n", target_data);
1282  return 1;
1283 }
1284 
1298 int XRI_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1299  uint8_t target_data = mem_read(&cpu->mem, base_PC+1);
1300  cpu->ACC ^= target_data;
1301  set_flags(cpu, cpu->ACC, ALL_BUT_AUX_FLAG);
1302  cpu->PSW.aux = 0;
1303  DECOMPILE_PRINT(base_PC, "XRI %x\n", target_data);
1304  return 1;
1305 }
1306 
1315 int CMA_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1316  cpu->ACC = ~(cpu->ACC);
1317  DECOMPILE_PRINT(base_PC, "%s\n", "CMA");
1318  return 1;
1319 }
1320 
1329 int CMC_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1330  cpu->PSW.carry = !(cpu->PSW.carry);
1331  DECOMPILE_PRINT(base_PC, "%s\n", "CMC");
1332  return 1;
1333 }
1334 
1343 int STC_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1344  cpu->PSW.carry = 1;
1345  DECOMPILE_PRINT(base_PC, "%s\n", "STC");
1346  return 1;
1347 }
1348 
1357 int DAA_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1358  if((cpu->ACC & 0xF) > 0x9 || cpu->PSW.aux){
1359  cpu->PSW.aux = 0;
1360  if(((cpu->ACC & 0xF) + 0x06) > 0xF){
1361  cpu->PSW.aux = 1;
1362  }
1363  if((cpu->ACC + 6) & 0x100){
1364  cpu->PSW.carry = 1;
1365  }
1366  cpu->ACC += 0x6;
1367  }
1368  if((cpu->ACC & 0xF0) >> 4 > 0x9 || cpu->PSW.carry == 1){
1369  if(((cpu->ACC >> 4) + 0x06) > 0xF){
1370  cpu->PSW.carry = 1;
1371  }
1372  cpu->ACC += 0x60;
1373  }
1374  DECOMPILE_PRINT(base_PC, "%s\n", "DAA");
1375  return 1;
1376 }
1377 
1390 int RST_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, uint8_t op_code){
1391  cpu->SP -= 2;
1392  short_mem_write(&cpu->mem, cpu->SP, cpu->PC); // Saving Return Addr
1393  // Generating new position
1394  uint16_t target_addr = ((op_code & 0x38) >> 3); // Generate new target Addr
1395  cpu->PC = target_addr * 8; // Writing New PC
1396  cpu->intt = 0; // Disable Interrupts when execing Intt
1397  // NOTE: This will be enabled by the INTT handler function.
1398  DECOMPILE_PRINT(base_PC, "RST %x\n", target_addr); // Logging
1399  return 1;
1400 }
1401 
1418 int SPHL_WRAP(cpu_state* cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code){
1419  uint16_t temp = cpu->HL;
1420  cpu->HL = short_mem_read(&cpu->mem, cpu->SP);
1421  short_mem_write(&cpu->mem, cpu->SP, temp);
1422  DECOMPILE_PRINT(base_PC, "%s\n", "SPHL");
1423  return 1;
1424 }
1425 
1434  [0x00] = {.target_func = NOP_WRAP, .cycle_count = 4, .size = 1}, // NOP Instruction
1435  [0x01] = {LXI_WRAP, 10, 3},
1436  [0x02] = {STAX_WRAP, 7, 1},
1437  [0x03] = {INX_WRAP, 5, 1},
1438  [0x04] = {INR_WRAP, 5, 1},
1439  [0x05] = {DCR_WRAP, 5, 1},
1440  [0x06] = {MVI_WRAP, 7, 2},
1441  [0x07] = {RLC_WRAP, 7, 1},
1442  [0x08] = {NOP_WRAP, 4, 1},
1443  [0x09] = {DAD_WRAP, 10, 1},
1444  [0x0A] = {LDAX_WRAP, 7, 1},
1445  [0x0B] = {DCX_WRAP, 5, 1},
1446  [0x0C] = {INR_WRAP, 5, 1},
1447  [0x0D] = {DCR_WRAP, 5, 1},
1448  [0x0E] = {MVI_WRAP, 7, 2},
1449  [0x0F] = {RRC_WRAP, 4, 1},
1450  [0x10] = {NOP_WRAP, 4, 1},
1451  [0x11] = {LXI_WRAP, 10, 3},
1452  [0x12] = {STAX_WRAP, 7, 1},
1453  [0x13] = {INX_WRAP, 5, 1},
1454  [0x14] = {INR_WRAP, 5, 1},
1455  [0x15] = {DCR_WRAP, 5, 1},
1456  [0x16] = {MVI_WRAP, 7, 2},
1457  [0x17] = {RAL_WRAP, 4, 1},
1458  [0x18] = {NOP_WRAP, 4, 1},
1459  [0x19] = {DAD_WRAP, 10, 1},
1460  [0x1A] = {LDAX_WRAP, 7, 1},
1461  [0x1B] = {DCX_WRAP, 5, 1},
1462  [0x1C] = {INR_WRAP, 5, 1},
1463  [0x1D] = {DCR_WRAP, 5, 1},
1464  [0x1E] = {MVI_WRAP, 7, 2},
1465  [0x1F] = {RAR_WRAP, 4, 1},
1466  [0x20] = {NOP_WRAP, 4, 1},
1467  [0x21] = {LXI_WRAP, 10, 3},
1468  [0x22] = {SHLD_WRAP, 16, 3},
1469  [0x23] = {INX_WRAP, 5, 1},
1470  [0x24] = {INR_WRAP, 5, 1},
1471  [0x25] = {DCR_WRAP, 5, 1},
1472  [0x26] = {MVI_WRAP, 7, 2},
1473  [0x27] = {DAA_WRAP, 4, 1},
1474  [0x28] = {NOP_WRAP, 4, 1},
1475  [0x29] = {DAD_WRAP, 10, 1},
1476  [0x2A] = {LHLD_WRAP, 16, 3},
1477  [0x2B] = {DCX_WRAP, 5, 1},
1478  [0x2C] = {INR_WRAP, 5, 1},
1479  [0x2D] = {DCR_WRAP, 5, 1},
1480  [0x2E] = {MVI_WRAP, 7, 2},
1481  [0x2F] = {CMA_WRAP, 4, 1},
1482  [0x30] = {NOP_WRAP, 4, 1},
1483  [0x31] = {LXI_WRAP, 10, 3},
1484  [0x32] = {STA_WRAP, 13, 3},
1485  [0x33] = {INX_WRAP, 5, 1},
1486  [0x34] = {INR_WRAP, 5, 1},
1487  [0x35] = {DCR_WRAP, 5, 1},
1488  [0x36] = {MVI_WRAP, 10, 2},
1489  [0x37] = {STC_WRAP, 4, 1},
1490  [0x38] = {NOP_WRAP, 4, 1},
1491  [0x39] = {DAD_WRAP, 10, 1},
1492  [0x3A] = {LDA_WRAP, 13, 3},
1493  [0x3B] = {DCX_WRAP, 5, 1},
1494  [0x3C] = {INR_WRAP, 5, 1},
1495  [0x3D] = {DCR_WRAP, 5, 1},
1496  [0x3E] = {MVI_WRAP, 7, 2},
1497  [0x3F] = {CMC_WRAP, 4, 1},
1498  [0x40] = {MOV_WRAP, 5, 1},
1499  [0x41] = {MOV_WRAP, 5, 1},
1500  [0x42] = {MOV_WRAP, 5, 1},
1501  [0x43] = {MOV_WRAP, 5, 1},
1502  [0x44] = {MOV_WRAP, 5, 1},
1503  [0x45] = {MOV_WRAP, 5, 1},
1504  [0x46] = {MOV_WRAP, 5, 1},
1505  [0x47] = {MOV_WRAP, 5, 1},
1506  [0x48] = {MOV_WRAP, 5, 1},
1507  [0x49] = {MOV_WRAP, 5, 1},
1508  [0x4A] = {MOV_WRAP, 5, 1},
1509  [0x4B] = {MOV_WRAP, 5, 1},
1510  [0x4C] = {MOV_WRAP, 5, 1},
1511  [0x4D] = {MOV_WRAP, 5, 1},
1512  [0x4E] = {MOV_WRAP, 5, 1},
1513  [0x4F] = {MOV_WRAP, 5, 1},
1514  [0x50] = {MOV_WRAP, 5, 1},
1515  [0x51] = {MOV_WRAP, 5, 1},
1516  [0x52] = {MOV_WRAP, 5, 1},
1517  [0x53] = {MOV_WRAP, 5, 1},
1518  [0x54] = {MOV_WRAP, 5, 1},
1519  [0x55] = {MOV_WRAP, 5, 1},
1520  [0x56] = {MOV_WRAP, 5, 1},
1521  [0x57] = {MOV_WRAP, 5, 1},
1522  [0x58] = {MOV_WRAP, 5, 1},
1523  [0x59] = {MOV_WRAP, 5, 1},
1524  [0x5A] = {MOV_WRAP, 5, 1},
1525  [0x5B] = {MOV_WRAP, 5, 1},
1526  [0x5C] = {MOV_WRAP, 5, 1},
1527  [0x5D] = {MOV_WRAP, 5, 1},
1528  [0x5E] = {MOV_WRAP, 5, 1},
1529  [0x5F] = {MOV_WRAP, 5, 1},
1530  [0x60] = {MOV_WRAP, 5, 1},
1531  [0x61] = {MOV_WRAP, 5, 1},
1532  [0x62] = {MOV_WRAP, 5, 1},
1533  [0x63] = {MOV_WRAP, 5, 1},
1534  [0x64] = {MOV_WRAP, 5, 1},
1535  [0x65] = {MOV_WRAP, 5, 1},
1536  [0x66] = {MOV_WRAP, 5, 1},
1537  [0x67] = {MOV_WRAP, 5, 1},
1538  [0x68] = {MOV_WRAP, 5, 1},
1539  [0x69] = {MOV_WRAP, 5, 1},
1540  [0x6A] = {MOV_WRAP, 5, 1},
1541  [0x6B] = {MOV_WRAP, 5, 1},
1542  [0x6C] = {MOV_WRAP, 5, 1},
1543  [0x6D] = {MOV_WRAP, 5, 1},
1544  [0x6E] = {MOV_WRAP, 5, 1},
1545  [0x6F] = {MOV_WRAP, 5, 1},
1546  [0x70] = {MOV_WRAP, 5, 1},
1547  [0x71] = {MOV_WRAP, 5, 1},
1548  [0x72] = {MOV_WRAP, 5, 1},
1549  [0x73] = {MOV_WRAP, 5, 1},
1550  [0x74] = {MOV_WRAP, 5, 1},
1551  [0x75] = {MOV_WRAP, 5, 1},
1552  [0x76] = {HLT_WRAP, 7, 1},
1553  [0x77] = {MOV_WRAP, 5, 1},
1554  [0x78] = {MOV_WRAP, 5, 1},
1555  [0x79] = {MOV_WRAP, 5, 1},
1556  [0x7A] = {MOV_WRAP, 5, 1},
1557  [0x7B] = {MOV_WRAP, 5, 1},
1558  [0x7C] = {MOV_WRAP, 5, 1},
1559  [0x7D] = {MOV_WRAP, 5, 1},
1560  [0x7E] = {MOV_WRAP, 5, 1},
1561  [0x7F] = {MOV_WRAP, 5, 1},
1562  [0x80] = {ADD_WRAP, 4, 1},
1563  [0x81] = {ADD_WRAP, 4, 1},
1564  [0x82] = {ADD_WRAP, 4, 1},
1565  [0x83] = {ADD_WRAP, 4, 1},
1566  [0x84] = {ADD_WRAP, 4, 1},
1567  [0x85] = {ADD_WRAP, 4, 1},
1568  [0x86] = {ADD_WRAP, 4, 1},
1569  [0x87] = {ADD_WRAP, 4, 1},
1570  [0x88] = {ADC_WRAP, 4, 1},
1571  [0x89] = {ADC_WRAP, 4, 1},
1572  [0x8A] = {ADC_WRAP, 4, 1},
1573  [0x8B] = {ADC_WRAP, 4, 1},
1574  [0x8C] = {ADC_WRAP, 4, 1},
1575  [0x8D] = {ADC_WRAP, 4, 1},
1576  [0x8E] = {ADC_WRAP, 4, 1},
1577  [0x8F] = {ADC_WRAP, 4, 1},
1578  [0x90] = {SUB_WRAP, 4, 1},
1579  [0x91] = {SUB_WRAP, 4, 1},
1580  [0x92] = {SUB_WRAP, 4, 1},
1581  [0x93] = {SUB_WRAP, 4, 1},
1582  [0x94] = {SUB_WRAP, 4, 1},
1583  [0x95] = {SUB_WRAP, 4, 1},
1584  [0x96] = {SUB_WRAP, 4, 1},
1585  [0x97] = {SUB_WRAP, 4, 1},
1586  [0x98] = {SBB_WRAP, 4, 1},
1587  [0x99] = {SBB_WRAP, 4, 1},
1588  [0x9A] = {SBB_WRAP, 4, 1},
1589  [0x9B] = {SBB_WRAP, 4, 1},
1590  [0x9C] = {SBB_WRAP, 4, 1},
1591  [0x9D] = {SBB_WRAP, 4, 1},
1592  [0x9E] = {SBB_WRAP, 4, 1},
1593  [0x9F] = {SBB_WRAP, 4, 1},
1594  [0xA0] = {ANA_WRAP, 4, 1},
1595  [0xA1] = {ANA_WRAP, 4, 1},
1596  [0xA2] = {ANA_WRAP, 4, 1},
1597  [0xA3] = {ANA_WRAP, 4, 1},
1598  [0xA4] = {ANA_WRAP, 4, 1},
1599  [0xA5] = {ANA_WRAP, 4, 1},
1600  [0xA6] = {ANA_WRAP, 4, 1},
1601  [0xA7] = {ANA_WRAP, 4, 1},
1602  [0xA8] = {XRA_WRAP, 4, 1},
1603  [0xA9] = {XRA_WRAP, 4, 1},
1604  [0xAA] = {XRA_WRAP, 4, 1},
1605  [0xAB] = {XRA_WRAP, 4, 1},
1606  [0xAC] = {XRA_WRAP, 4, 1},
1607  [0xAD] = {XRA_WRAP, 4, 1},
1608  [0xAE] = {XRA_WRAP, 4, 1},
1609  [0xAF] = {XRA_WRAP, 4, 1},
1610  [0xB0] = {ORA_WRAP, 4, 1},
1611  [0xB1] = {ORA_WRAP, 4, 1},
1612  [0xB2] = {ORA_WRAP, 4, 1},
1613  [0xB3] = {ORA_WRAP, 4, 1},
1614  [0xB4] = {ORA_WRAP, 4, 1},
1615  [0xB5] = {ORA_WRAP, 4, 1},
1616  [0xB6] = {ORA_WRAP, 4, 1},
1617  [0xB7] = {ORA_WRAP, 4, 1},
1618  [0xB8] = {CMP_WRAP, 4, 1},
1619  [0xB9] = {CMP_WRAP, 4, 1},
1620  [0xBA] = {CMP_WRAP, 4, 1},
1621  [0xBB] = {CMP_WRAP, 4, 1},
1622  [0xBC] = {CMP_WRAP, 4, 1},
1623  [0xBD] = {CMP_WRAP, 4, 1},
1624  [0xBE] = {CMP_WRAP, 4, 1},
1625  [0xBF] = {CMP_WRAP, 4, 1},
1626  [0xC0] = {RCon_WRAP, 11, 1},
1627  [0xC1] = {POP_WRAP, 10, 1},
1628  [0xC2] = {JCon_WRAP, 10, 3},
1629  [0xC3] = {JMP_WRAP, 10, 3},
1630  [0xC4] = {CCon_WRAP, 17, 3},
1631  [0xC5] = {PUSH_WRAP, 11, 1},
1632  [0xC6] = {ADI_WRAP, 7, 2},
1633  [0xC7] = {RST_WRAP, 11, 1},
1634  [0xC8] = {RCon_WRAP, 11, 1},
1635  [0xC9] = {RET_WRAP, 10, 1},
1636  [0xCA] = {JCon_WRAP, 10, 3},
1637  [0xCB] = {JMP_WRAP, 10, 3},
1638  [0xCC] = {CCon_WRAP, 17, 3},
1639  [0xCD] = {CALL_WRAP, 17, 3},
1640  [0xCE] = {ACI_WRAP, 7, 2},
1641  [0xCF] = {RST_WRAP, 11, 1},
1642  [0xD0] = {RCon_WRAP, 11, 1},
1643  [0xD1] = {POP_WRAP, 10, 1},
1644  [0xD2] = {JCon_WRAP, 10, 3},
1645  [0xD3] = {OUT_WRAP, 10, 2},
1646  [0xD4] = {CCon_WRAP, 17, 3},
1647  [0xD5] = {PUSH_WRAP, 11, 1},
1648  [0xD6] = {SUI_WRAP, 7, 2},
1649  [0xD7] = {RST_WRAP, 11, 1},
1650  [0xD8] = {RCon_WRAP, 11, 1},
1651  [0xD9] = {RET_WRAP, 10, 1},
1652  [0xDA] = {JCon_WRAP, 10, 3},
1653  [0xDB] = {IN_WRAP, 10, 2},
1654  [0xDC] = {CCon_WRAP, 17, 3},
1655  [0xDD] = {CALL_WRAP, 17, 3},
1656  [0xDE] = {SBI_WRAP, 7, 2},
1657  [0xDF] = {RST_WRAP, 11, 1},
1658  [0xE0] = {RCon_WRAP, 11, 1},
1659  [0xE1] = {POP_WRAP, 10, 1},
1660  [0xE2] = {JCon_WRAP, 10, 3},
1661  [0xE3] = {XTHL_WRAP, 18, 1},
1662  [0xE4] = {CCon_WRAP, 17, 3},
1663  [0xE5] = {PUSH_WRAP, 11, 1},
1664  [0xE6] = {ANI_WRAP, 7, 2},
1665  [0xE7] = {RST_WRAP, 11, 1},
1666  [0xE8] = {RCon_WRAP, 11, 1},
1667  [0xE9] = {PCHL_WRAP, 5, 1},
1668  [0xEA] = {JCon_WRAP, 10, 3},
1669  [0xEB] = {XCHG_WRAP, 5, 1},
1670  [0xEC] = {CCon_WRAP, 17, 3},
1671  [0xED] = {CALL_WRAP, 17, 3},
1672  [0xEE] = {XRI_WRAP, 7, 2},
1673  [0xEF] = {RST_WRAP, 11, 1},
1674  [0xF0] = {RCon_WRAP, 11, 1},
1675  [0xF1] = {POP_WRAP, 10, 1},
1676  [0xF2] = {JCon_WRAP, 10, 3},
1677  [0xF3] = {DI_WRAP, 4, 1},
1678  [0xF4] = {CCon_WRAP, 17, 3},
1679  [0xF5] = {PUSH_WRAP, 11, 1},
1680  [0xF6] = {ORI_WRAP, 7, 2},
1681  [0xF7] = {RST_WRAP, 11, 1},
1682  [0xF8] = {RCon_WRAP, 11, 1},
1683  [0xF9] = {SPHL_WRAP, 5, 1},
1684  [0xFA] = {JCon_WRAP, 10, 3},
1685  [0xFB] = {EI_WRAP, 4, 1},
1686  [0xFC] = {CCon_WRAP, 17, 3},
1687  [0xFD] = {CALL_WRAP, 17, 3},
1688  [0xFE] = {CPI_WRAP, 7, 2},
1689  [0xFF] = {RST_WRAP, 11, 1},
1690 };
1691 
1692 #endif
This file simulates and disassembles part of 8080 processor.
condition_flags
different condition checks for JMP, conditional OPS
Definition: cpu_8080.h:48
@ P_check
Definition: cpu_8080.h:55
@ NC_check
Definition: cpu_8080.h:51
@ PO_check
Definition: cpu_8080.h:53
@ NZ_check
Definition: cpu_8080.h:49
@ M_check
Definition: cpu_8080.h:56
@ C_check
Definition: cpu_8080.h:52
@ Z_check
Definition: cpu_8080.h:50
@ PE_check
Definition: cpu_8080.h:54
#define ALL_BUT_AUX_FLAG
All but the aux flag options.
Definition: cpu_8080.h:42
#define UNUSED
Definition: cpu_8080.h:16
#define DECOMPILE_PRINT(...)
Stub for when flag is not passed.
Definition: debug.h:75
#define DEBUG_PRINT(...)
Stub for when flag is not passed.
Definition: debug.h:49
Memory abstraction for 8080 cpu.
void mem_write(v_memory *mem, uint16_t offset, uint8_t val)
Lowest level memory write access abstraction. Typecasts the offset to void* + base to get the actual ...
Definition: memory_8080.c:26
uint16_t short_mem_read(v_memory *mem, uint16_t offset)
Wrapper over memory access primitives to read a byte off the base offset void* + base....
Definition: memory_8080.c:21
void * mem_ref(v_memory *mem, uint16_t offset)
plain reference to the memory location
Definition: memory_8080.c:12
uint8_t mem_read(v_memory *mem, uint16_t offset)
Lowest level memory read access abstraction. Typecasts the offset to void* + base to get the actual p...
Definition: memory_8080.c:16
void short_mem_write(v_memory *mem, uint16_t offset, uint16_t val)
Wrapper over memory access primitives to read a byte off the base offset void* + base....
Definition: memory_8080.c:31
int JMP_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(PC) (byte 3) (byte 2) – Control is transferred to the instruction whose address is specified in byte...
Definition: opcodes_8080.h:296
int RAR_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Rotate right through carry) (An) <– (An+l) ; (CY) <– (AO) ; (A7) <– (CY)
Definition: opcodes_8080.h:979
int ADC_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(Add Register with carry) (A) <– (A) + (r) + (CY) The content of register r and the content of the ca...
Definition: opcodes_8080.h:1098
int STA_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
*((byte 3)(byte 2)) = ACC
Definition: opcodes_8080.h:778
int HLT_WRAP(UNUSED cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
The processor is stopped. The registers and flags are unaffected.
Definition: opcodes_8080.h:414
int MOV_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
All different kinds of move operations:
Definition: opcodes_8080.h:395
int STAX_WRAP(cpu_state *cpu, UNUSED UNUSED uint16_t base_PC, uint8_t op_code)
Store *(RP) <- A.
Definition: opcodes_8080.h:695
int JCon_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
Conditional JMP statements.
Definition: opcodes_8080.h:469
int SPHL_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Exchange stack top with H and L) (L) <--> ((SP)); (H) <--> ((SP) + 1); The content of the L register...
Definition: opcodes_8080.h:1418
int DCR_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(Decrement Register) The content of register r is decremented by one.
Definition: opcodes_8080.h:447
#define ILLEGAL_OP
Definition: opcodes_8080.h:17
program_status_word decompress_PSW(uint8_t status)
Inflate the uint8_t into a program_status_word by using flag_bits as the mapping.
Definition: opcodes_8080.h:233
int XTHL_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Exchange stack top with Hand L) (L) <--> ((SP)) ; (H) <--> ((SP) + 1) ;
Definition: opcodes_8080.h:1236
int ACI_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Add immediate with carry) (A) <– (A) + (byte 2) + (CY) The content of the second byte of the instruc...
Definition: opcodes_8080.h:1122
int ORI_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(OR Immediate) (A) <– (A) V (byte 2) The content of the second byte of the instruction is inclusive-O...
Definition: opcodes_8080.h:1276
uint8_t compress_PSW(program_status_word psw)
Compress program_status_word into a uint8_t as per flag_bits.
Definition: opcodes_8080.h:216
uint8_t condition_check(cpu_state *cpu, condition_flags condition_identifier)
perform condition check on the cpu register state
Definition: opcodes_8080.h:103
int ANA_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(A) = (A) /\ (r) The content of register r is logically anded with the content of the accumulator....
Definition: opcodes_8080.h:719
uint8_t * ref_byte_reg(cpu_state *cpu, uint8_t reg_identifier)
The bit pattern designating one of the registers A,B,C,D,E,H,L (DDD=destination, SSS=source) 111 -> A...
Definition: opcodes_8080.h:45
int LHLD_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(L) <– ((byte 3)(byte 2)) (H) <– ((byte 3) (byte 2) + 1)
Definition: opcodes_8080.h:743
int CMA_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
Complement accumulator (A) <- (~A)
Definition: opcodes_8080.h:1315
int XRI_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Exclusive OR Immediate) (A) <– (A) ^ (byte 2) The content of the second byte of the instruction is e...
Definition: opcodes_8080.h:1298
int SHLD_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(L) --> ((byte 3)(byte 2)) (H) --> ((byte 3) (byte 2) + 1)
Definition: opcodes_8080.h:904
int RCon_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
Conditional version of RET_WRAP
Definition: opcodes_8080.h:512
int DAD_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(Add register pair to Hand L) (H) (L) ..- (H) (L) + (rh) (rl) The content of the register pair rp is ...
Definition: opcodes_8080.h:627
int CPI_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
Compare A with(-) (byte 2)
Definition: opcodes_8080.h:549
uint16_t * ref_short_reg(cpu_state *cpu, uint8_t reg_identifier)
The bit pattern designating one of the register pairs B,D,H,SP 00—11 -> B,D,H,SP. This function retur...
Definition: opcodes_8080.h:80
int CMP_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
Comparison operation.
Definition: opcodes_8080.h:529
int STC_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
Set Carry (CY) <- (1)
Definition: opcodes_8080.h:1343
int SUB_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(Subtract Register) (A) <– (A) - (r) The content of register r is subtracted from the content of the ...
Definition: opcodes_8080.h:1143
int INX_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(Increment register pair) (rh) (rl) <– (rh) (rl) + 1 The content of the register pair rp is increment...
Definition: opcodes_8080.h:430
int XCHG_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
Xchanges HL <--> DE.
Definition: opcodes_8080.h:648
int NOP_WRAP(UNUSED cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
Wrapper over No Op.
Definition: opcodes_8080.h:264
int PUSH_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
The content of content register, is moved into the memory whose address is specified by the SP....
Definition: opcodes_8080.h:571
int DAA_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Decimal Adjust Accumulator)
Definition: opcodes_8080.h:1357
int LXI_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
Load register pair immediate.
Definition: opcodes_8080.h:277
int ADD_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(Add Register) (A) <– (A) + (r) The content of register r is added to the content of the accumulator....
Definition: opcodes_8080.h:1051
int IN_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
Copies a byte of data from the PORT defined by byte(2) to ACC.
Definition: opcodes_8080.h:680
int DI_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
Disable Interrupts.
Definition: opcodes_8080.h:889
int RRC_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Rotate Right) (An) <- (An-1); (A7) <- A0 (Cy) <- (A0)
Definition: opcodes_8080.h:817
int POP_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
The content of the memory location, whose address is specified by the SP is pused into content Reg....
Definition: opcodes_8080.h:598
int(* OP_WRAP)(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
wrapping for all the CPU opcodes for emulation and easy calling.
Definition: opcodes_8080.h:23
int UNDEFINED_OP_WRAP(UNUSED cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
Undefined OPCODE Functor.
Definition: opcodes_8080.h:251
int RST_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(Restart) ((SP) - 1) <– (PCH); ((SP) - 2) <– (PCl); (SP) <– (SP) - 2; (PC) <– 8* (NNN);
Definition: opcodes_8080.h:1390
int XRA_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Exclusive OR Register) (A) = (A) ^ (r)
Definition: opcodes_8080.h:855
int LDAX_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
Load accumulator indirect: The content of the memory location, whose address is in the register pair ...
Definition: opcodes_8080.h:370
int ORA_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(OR Register) (A) <– (A) | (r) The content of register r is inclusive-OR'd with the content of the ac...
Definition: opcodes_8080.h:1214
int DCX_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(reg pair) = (reg pair) - 1
Definition: opcodes_8080.h:919
void aux_flag_set_add(cpu_state *cpu, uint32_t base_val, uint32_t diff)
sets the aux flag for all operations. Must convert all ops to a addition operation (compressed)....
Definition: opcodes_8080.h:199
int CALL_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
The current PC (pointer to next instruction) is move to the top of SP and the SP is decremented to ma...
Definition: opcodes_8080.h:341
int SUI_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Subtract immediate) (A) <– (A) - (byte 2) The content of the second byte of the instruction is subtr...
Definition: opcodes_8080.h:1167
int RET_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(Return) (PCl) ((SP)); (PCH) ((SP) + 1); (SP) (SP) + 2; The content of the memory location whose addr...
Definition: opcodes_8080.h:492
int PCHL_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Jump Hand l indirect - move Hand L to PC) (PCH) <– (H) (PCl) <– (l) The content of register H is mov...
Definition: opcodes_8080.h:1257
int RLC_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Rotate left) (An+l) <– (An) ; (AO) <– (A7); (CY) <– (A7)
Definition: opcodes_8080.h:936
instt_8080_op opcode_lookup[0x100]
A jump table indexed by an Intel 8080 instruction opcode, containing:
Definition: opcodes_8080.h:1433
int SBB_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(Subtract Register with borrow) (A) <– (A) - (r) - (CY) The content of register r and the content of ...
Definition: opcodes_8080.h:1190
int ANI_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(AND immediate) (A) = (A) & (byte 2)
Definition: opcodes_8080.h:759
int MVI_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
Move Immediate.
Definition: opcodes_8080.h:322
int EI_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
Enable Interrupts.
Definition: opcodes_8080.h:875
void set_flags(cpu_state *cpu, uint32_t final_state, uint8_t flags)
Set the flags PSW status.
Definition: opcodes_8080.h:160
int CCon_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
Ccondition addr (Condition call) If (CCC), ((SP) -1) (PCH) ((SP) - 2) (PCl) (SP) (SP) - 2 (PC) (byte ...
Definition: opcodes_8080.h:1004
int SBI_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Subtract immediate with borrow) (A) <– (A) - (byte 2) - (CY) The contents of the second byte of the ...
Definition: opcodes_8080.h:1028
int RAL_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Rotate left through carry) (An+1) <– (An) ; (CY) <– (A7) ; (AO) <– (CY)
Definition: opcodes_8080.h:958
int OUT_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
Copies a byte of data from ACC to PORT.
Definition: opcodes_8080.h:664
int ADI_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Add Immediate) (A) <– (A) + (byte 2) The content of the second byte of the instruction is added to t...
Definition: opcodes_8080.h:1075
int CMC_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
Complement carry (CY) <- (!CY)
Definition: opcodes_8080.h:1329
int LDA_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, UNUSED uint8_t op_code)
(Load Accumulator direct) (A) = *((byte 3)(byte 2))
Definition: opcodes_8080.h:839
int INR_WRAP(cpu_state *cpu, UNUSED uint16_t base_PC, uint8_t op_code)
(increment Reg) (r) <- (r) + 1
Definition: opcodes_8080.h:793
cpu_state: This structure keeps runtime state of all the registers in the CPU.
Definition: cpu_8080.h:63
uint16_t SP
Definition: cpu_8080.h:88
uint8_t(* IN_Func)(uint8_t)
Definition: cpu_8080.h:96
uint8_t D
Definition: cpu_8080.h:71
uint16_t BC
Definition: cpu_8080.h:76
uint8_t H
Definition: cpu_8080.h:73
uint8_t L
Definition: cpu_8080.h:72
uint8_t E
Definition: cpu_8080.h:70
uint16_t HL
Definition: cpu_8080.h:78
program_status_word PSW
Definition: cpu_8080.h:84
v_memory mem
Definition: cpu_8080.h:102
uint8_t ACC
Definition: cpu_8080.h:83
uint16_t DE
Definition: cpu_8080.h:77
uint8_t intt
Definition: cpu_8080.h:90
uint8_t B
Definition: cpu_8080.h:69
uint16_t PC
Definition: cpu_8080.h:89
uint8_t C
Definition: cpu_8080.h:68
a struct to define the meta data for intel 8080 opcode. Contains the binding to the functor and the c...
Definition: opcodes_8080.h:29
OP_WRAP target_func
Definition: opcodes_8080.h:30
uint8_t size
Definition: opcodes_8080.h:32
uint8_t cycle_count
Definition: opcodes_8080.h:31
program_status_word: An exdended PSW for easy checks and sets of PSW without flagging.
Definition: cpu_8080.h:22
uint8_t aux
Definition: cpu_8080.h:24
uint8_t zero
Definition: cpu_8080.h:26
uint8_t carry
Definition: cpu_8080.h:23
uint8_t sign
Definition: cpu_8080.h:25
uint8_t parity
Definition: cpu_8080.h:27