Advertisement
Guest User

Intel 8080 emulator

a guest
Apr 8th, 2018
469
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 16.25 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4.  
  5. //prototype external functions
  6. uint8_t i8080_read(uint16_t addr);
  7. void i8080_write(uint16_t addr, uint8_t value);
  8. uint8_t i8080_inport(uint8_t port);
  9. void i8080_outport(uint8_t port, uint8_t value);
  10. //end external functions
  11.  
  12. #define reg16_PSW (((uint16_t)reg8[A] << 8) | (uint16_t)reg8[FLAGS])
  13. #define reg16_BC (((uint16_t)reg8[B] << 8) | (uint16_t)reg8[C])
  14. #define reg16_DE (((uint16_t)reg8[D] << 8) | (uint16_t)reg8[E])
  15. #define reg16_HL (((uint16_t)reg8[H] << 8) | (uint16_t)reg8[L])
  16.  
  17. uint8_t reg8[9], INTE = 0;
  18. uint16_t reg_SP, reg_PC;
  19.  
  20. #define B 0
  21. #define C 1
  22. #define D 2
  23. #define E 3
  24. #define H 4
  25. #define L 5
  26. #define M 6
  27. #define A 7
  28. #define FLAGS 8
  29.  
  30. #define set_S() reg8[FLAGS] |= 0x80
  31. #define set_Z() reg8[FLAGS] |= 0x40
  32. #define set_AC() reg8[FLAGS] |= 0x10
  33. #define set_P() reg8[FLAGS] |= 0x04
  34. #define set_C() reg8[FLAGS] |= 0x01
  35. #define clear_S() reg8[FLAGS] &= 0x7F
  36. #define clear_Z() reg8[FLAGS] &= 0xBF
  37. #define clear_AC() reg8[FLAGS] &= 0xEF
  38. #define clear_P() reg8[FLAGS] &= 0xFB
  39. #define clear_C() reg8[FLAGS] &= 0xFE
  40. #define test_S() (reg8[FLAGS] & 0x80)
  41. #define test_Z() (reg8[FLAGS] & 0x40)
  42. #define test_AC() (reg8[FLAGS] & 0x10)
  43. #define test_P() (reg8[FLAGS] & 0x04)
  44. #define test_C() (reg8[FLAGS] & 0x01)
  45.  
  46. static const uint8_t parity[0x100] = {
  47.     1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
  48.     0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
  49.     0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
  50.     1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
  51.     0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
  52.     1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
  53.     1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
  54.     0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
  55. };
  56.  
  57. uint16_t read_RP(uint8_t rp) {
  58.     switch (rp) {
  59.         case 0x00:
  60.             return reg16_BC;
  61.         case 0x01:
  62.             return reg16_DE;
  63.         case 0x02:
  64.             return reg16_HL;
  65.         case 0x03:
  66.             return reg_SP;
  67.     }
  68.     return 0;
  69. }
  70.  
  71. uint16_t read_RP_PUSHPOP(uint8_t rp) {
  72.     switch (rp) {
  73.         case 0x00:
  74.             return reg16_BC;
  75.         case 0x01:
  76.             return reg16_DE;
  77.         case 0x02:
  78.             return reg16_HL;
  79.         case 0x03:
  80.             return reg16_PSW;
  81.     }
  82.     return 0;
  83. }
  84.  
  85. void write_RP(uint8_t rp, uint8_t lb, uint8_t hb) {
  86.     switch (rp) {
  87.         case 0x00:
  88.             reg8[C] = lb;
  89.             reg8[B] = hb;
  90.             break;
  91.         case 0x01:
  92.             reg8[E] = lb;
  93.             reg8[D] = hb;
  94.             break;
  95.         case 0x02:
  96.             reg8[L] = lb;
  97.             reg8[H] = hb;
  98.             break;
  99.         case 0x03:
  100.             reg_SP = (uint16_t)lb | ((uint16_t)hb << 8);
  101.             break;
  102.     }
  103. }
  104.  
  105. void write16_RP(uint8_t rp, uint16_t value) {
  106.     switch (rp) {
  107.         case 0x00:
  108.             reg8[C] = value & 0x00FF;
  109.             reg8[B] = value >> 8;
  110.             break;
  111.         case 0x01:
  112.             reg8[E] = value & 0x00FF;
  113.             reg8[D] = value >> 8;
  114.             break;
  115.         case 0x02:
  116.             reg8[L] = value & 0x00FF;
  117.             reg8[H] = value >> 8;
  118.             break;
  119.         case 0x03:
  120.             reg_SP = value;
  121.             break;
  122.     }
  123. }
  124.  
  125. void write16_RP_PUSHPOP(uint8_t rp, uint16_t value) {
  126.     switch (rp) {
  127.         case 0x00:
  128.             reg8[C] = value & 0x00FF;
  129.             reg8[B] = value >> 8;
  130.             break;
  131.         case 0x01:
  132.             reg8[E] = value & 0x00FF;
  133.             reg8[D] = value >> 8;
  134.             break;
  135.         case 0x02:
  136.             reg8[L] = value & 0x00FF;
  137.             reg8[H] = value >> 8;
  138.             break;
  139.         case 0x03:
  140.             reg8[FLAGS] = value & 0x00FF;
  141.             reg8[A] = value >> 8;
  142.             break;
  143.     }
  144. }
  145.  
  146. void calc_SZP(uint8_t value) {
  147.     if (value == 0) set_Z(); else clear_Z();
  148.     if (value & 0x80) set_S(); else clear_S();
  149.     if (parity[value]) set_P(); else clear_P();
  150. }
  151.  
  152. void calc_AC(uint8_t val1, uint8_t val2) {
  153.     if (((val1 & 7) + (val2 & 7)) & 0xF0) set_AC(); else clear_AC();
  154. }
  155.  
  156. void calc_subAC(int8_t val1, uint8_t val2) {
  157.     if (((val1 & 7) - (val2 & 7)) & 0xF0) set_AC(); else clear_AC();
  158. }
  159.  
  160. uint8_t test_cond(uint8_t code) {
  161.     switch (code) {
  162.         case 0: //Z not set
  163.             if (!test_Z()) return 1; else return 0;
  164.         case 1: //Z set
  165.             if (test_Z()) return 1; else return 0;
  166.         case 2: //C not set
  167.             if (!test_C()) return 1; else return 0;
  168.         case 3: //C set
  169.             if (test_C()) return 1; else return 0;
  170.         case 4: //P not set
  171.             if (!test_P()) return 1; else return 0;
  172.         case 5: //P set
  173.             if (test_P()) return 1; else return 0;
  174.         case 6: //S not set
  175.             if (!test_S()) return 1; else return 0;
  176.         case 7: //S set
  177.             if (test_S()) return 1; else return 0;
  178.     }
  179.     return 0;
  180. }
  181.  
  182. void i8080_push(uint16_t value) {
  183.     i8080_write(--reg_SP, value >> 8);
  184.     i8080_write(--reg_SP, (uint8_t)value);
  185. }
  186.  
  187. uint16_t i8080_pop() {
  188.     uint16_t temp;
  189.     temp = i8080_read(reg_SP++);
  190.     temp |= (uint16_t)i8080_read(reg_SP++) << 8;
  191.     return temp;
  192. }
  193.  
  194. void i8080_interrupt(uint8_t n) {
  195.     if (!INTE) return;
  196.     i8080_push(reg_PC);
  197.     reg_PC = (uint16_t)n << 3;
  198.     INTE = 0;
  199. }
  200.  
  201. void i8080_jump(uint16_t addr) {
  202.     reg_PC = addr;
  203. }
  204.  
  205. void i8080_reset() {
  206.     reg_PC = reg_SP = 0x0000;
  207.     reg8[FLAGS] = 0x02;
  208. }
  209.  
  210. void write_reg8(uint8_t reg, uint8_t value) {
  211.     if (reg == M) {
  212.         i8080_write(reg16_HL, value);
  213.     } else {
  214.         reg8[reg] = value;
  215.     }
  216. }
  217.  
  218. uint8_t read_reg8(uint8_t reg) {
  219.     if (reg == M) {
  220.         return i8080_read(reg16_HL);
  221.     } else {
  222.         return reg8[reg];
  223.     }
  224. }
  225.  
  226. void i8080_exec(int cycles) {
  227.     uint8_t opcode, temp8, reg;
  228.     uint16_t temp16;
  229.     uint32_t temp32;
  230.  
  231.     while (cycles--) {
  232.         opcode = i8080_read(reg_PC++);
  233.  
  234.         if ((opcode & 0xC0) == 0x40) { //MOV D,S - move register to register
  235.             write_reg8((opcode >> 3) & 7, read_reg8(opcode & 7));
  236.         }
  237.         else if ((opcode & 0xC7) == 0x06) { //MVI D,# - move immediate to register
  238.             write_reg8((opcode >> 3) & 7, i8080_read(reg_PC++));
  239.         }
  240.         else if ((opcode & 0xCF) == 0x01) { //LXI RP,# - load register pair immediate
  241.             temp8 = (opcode >> 4) & 3;
  242.             write_RP(temp8, i8080_read(reg_PC), i8080_read(reg_PC + 1));
  243.             reg_PC += 2;
  244.         }
  245.         else if (opcode == 0x3A) { //LDA a - load A from memory
  246.             temp16 = (uint16_t)i8080_read(reg_PC) | ((uint16_t)i8080_read(reg_PC+1)<<8);
  247.             reg8[A] = i8080_read(temp16);
  248.             reg_PC += 2;
  249.         }
  250.         else if (opcode == 0x32) { //STA a - store A to memory
  251.             temp16 = (uint16_t)i8080_read(reg_PC) | ((uint16_t)i8080_read(reg_PC+1)<<8);
  252.             i8080_write(temp16, reg8[A]);
  253.             reg_PC += 2;
  254.         }
  255.         else if (opcode == 0x2A) { //LHLD a - load H:L from memory
  256.             temp16 = (uint16_t)i8080_read(reg_PC) | ((uint16_t)i8080_read(reg_PC+1)<<8);
  257.             reg8[L] = i8080_read(temp16++);
  258.             reg8[H] = i8080_read(temp16);
  259.             reg_PC += 2;
  260.         }
  261.         else if (opcode == 0x22) { //SHLD a - store H:L to memory
  262.             temp16 = (uint16_t)i8080_read(reg_PC) | ((uint16_t)i8080_read(reg_PC+1)<<8);
  263.             i8080_write(temp16++, reg8[L]);
  264.             i8080_write(temp16, reg8[H]);
  265.             reg_PC += 2;
  266.         }
  267.         else if ((opcode & 0xEF) == 0x0A) { //LDAX RP - load A indirect through BC or DE
  268.             reg8[A] = i8080_read(((opcode >> 4) & 1) ? reg16_DE : reg16_BC);
  269.         }
  270.         else if ((opcode & 0xEF) == 0x02) { //STAX RP - store A indirect through BC or DE
  271.             i8080_write(((opcode >> 4) & 1) ? reg16_DE : reg16_BC, reg8[A]);
  272.         }
  273.         else if (opcode == 0xEB) { //XCHG - exchange DE and HL content
  274.             temp8 = reg8[D];
  275.             reg8[D] = reg8[H];
  276.             reg8[H] = temp8;
  277.             temp8 = reg8[E];
  278.             reg8[E] = reg8[L];
  279.             reg8[L] = temp8;
  280.         }
  281.         else if ((opcode & 0xF8) == 0x80) { //ADD S - add register or memory to A
  282.             temp8 = read_reg8(opcode & 7); //reg8[opcode & 7];
  283.             temp16 = (uint16_t)reg8[A] + (uint16_t)temp8;
  284.             if (temp16 & 0xFF00) set_C(); else clear_C();
  285.             calc_AC(reg8[A], temp8);
  286.             calc_SZP((uint8_t)temp16);
  287.             reg8[A] = (uint8_t)temp16;
  288.         }
  289.         else if (opcode == 0xC6) { //ADI # - add immediate to A
  290.             temp8 = i8080_read(reg_PC++);
  291.             temp16 = (uint16_t)reg8[A] + (uint16_t)temp8;
  292.             if (temp16 & 0xFF00) set_C(); else clear_C();
  293.             calc_AC(reg8[A], temp8);
  294.             calc_SZP((uint8_t)temp16);
  295.             reg8[A] = (uint8_t)temp16;
  296.         }
  297.         else if ((opcode & 0xF8) == 0x88) { //ADC S - add register or memory to A with carry
  298.             temp8 = read_reg8(opcode & 7); //reg8[opcode & 7] + (test_C() ? 1 : 0);
  299.             temp16 = (uint16_t)reg8[A] + (uint16_t)temp8 + (uint16_t)(test_C() ? 1 : 0);
  300.             if (temp16 & 0xFF00) set_C(); else clear_C();
  301.             calc_AC(reg8[A], temp8);
  302.             calc_SZP((uint8_t)temp16);
  303.             reg8[A] = (uint8_t)temp16;
  304.         }
  305.         else if (opcode == 0xCE) { //ACI # - add immediate to A with carry
  306.             temp8 = i8080_read(reg_PC++);
  307.             temp16 = (uint16_t)reg8[A] + (uint16_t)temp8 + (uint16_t)(test_C() ? 1 : 0);
  308.             if (temp16 & 0xFF00) set_C(); else clear_C();
  309.             calc_AC(reg8[A], temp8);
  310.             calc_SZP((uint8_t)temp16);
  311.             reg8[A] = (uint8_t)temp16;
  312.         }
  313.         else if ((opcode & 0xF8) == 0x90) { //SUB S - subtract register or memory from A
  314.             temp8 = read_reg8(opcode & 7); //reg8[opcode & 7];
  315.             temp16 = (uint16_t)reg8[A] - (uint16_t)temp8;
  316.             if (temp16 & 0xFF00) set_C(); else clear_C();
  317.             calc_subAC(reg8[A], temp8);
  318.             calc_SZP((uint8_t)temp16);
  319.             reg8[A] = (uint8_t)temp16;
  320.         }
  321.         else if (opcode == 0xD6) { //SUI # - subtract immediate from A
  322.             temp8 = i8080_read(reg_PC++);
  323.             temp16 = (uint16_t)reg8[A] - (uint16_t)temp8;
  324.             if (temp16 & 0xFF00) set_C(); else clear_C();
  325.             calc_subAC(reg8[A], temp8);
  326.             calc_SZP((uint8_t)temp16);
  327.             reg8[A] = (uint8_t)temp16;
  328.         }
  329.         else if ((opcode & 0xF8) == 0x98) { //SBB S - subtract register or memory from A with borrow
  330.             temp8 = read_reg8(opcode & 7); //reg8[opcode & 7] + (test_C() ? 1 : 0);
  331.             temp16 = (uint16_t)reg8[A] - (uint16_t)temp8 - (uint16_t)(test_C() ? 1 : 0);
  332.             if (temp16 & 0xFF00) set_C(); else clear_C();
  333.             calc_subAC(reg8[A], temp8);
  334.             calc_SZP((uint8_t)temp16);
  335.             reg8[A] = (uint8_t)temp16;
  336.         }
  337.         else if (opcode == 0xDE) { //SBI # - subtract immediate from A with borrow
  338.             temp8 = i8080_read(reg_PC++);
  339.             temp16 = (uint16_t)reg8[A] - (uint16_t)temp8 - (uint16_t)(test_C() ? 1 : 0);
  340.             if (temp16 & 0xFF00) set_C(); else clear_C();
  341.             calc_subAC(reg8[A], temp8);
  342.             calc_SZP((uint8_t)temp16);
  343.             reg8[A] = (uint8_t)temp16;
  344.         }
  345.         else if ((opcode & 0xC7) == 0x04) { //INR D - increment register
  346.             reg = (opcode >> 3) & 7;
  347.             temp8 = read_reg8(reg); //reg8[reg];
  348.             calc_AC(temp8, 1);
  349.             calc_SZP(temp8 + 1);
  350.             write_reg8(reg, temp8 + 1); //reg8[reg]++;
  351.         }
  352.         else if ((opcode & 0xC7) == 0x05) { //DCR D - decrement register
  353.             reg = (opcode >> 3) & 7;
  354.             temp8 = read_reg8(reg); //reg8[reg];
  355.             calc_subAC(temp8, 1);
  356.             calc_SZP(temp8 - 1);
  357.             write_reg8(reg, temp8 - 1); //reg8[reg]--;
  358.         }
  359.         else if ((opcode & 0xCF) == 0x03) { //INX RP - increment register pair
  360.             reg = (opcode >> 4) & 3;
  361.             write16_RP(reg, read_RP(reg) + 1);
  362.         }
  363.         else if ((opcode & 0xCF) == 0x0B) { //DCX RP - decrement register pair
  364.             reg = (opcode >> 4) & 3;
  365.             write16_RP(reg, read_RP(reg) - 1);
  366.         }
  367.         else if ((opcode & 0xCF) == 0x09) { //DAD RP - add register pair to HL
  368.             reg = (opcode >> 4) & 3;
  369.             temp32 = (uint32_t)reg16_HL + (uint32_t)read_RP(reg);
  370.             write16_RP(2, (uint16_t)temp32);
  371.             if (temp32 & 0xFFFF0000) set_C(); else clear_C();
  372.         }
  373.         else if (opcode == 0x27) { //DAA - decimal adjust accumulator
  374.             temp16 = reg8[A];
  375.             if (((temp16 & 0x0F) > 0x09) || test_AC()) {
  376.                 if (((temp16 & 0x0F) + 0x06) & 0xF0) set_AC(); else clear_AC();
  377.                 temp16 += 0x06;
  378.             }
  379.             if (((temp16 & 0xF0) > 0x90) || test_C()) {
  380.                 if ((temp16 + 0x60) & 0xFF00) set_C(); else clear_C();
  381.                 temp16 += 0x60;
  382.             }
  383.             calc_SZP((uint8_t)temp16);
  384.             reg8[A] = (uint8_t)temp16;
  385.         }
  386.         else if ((opcode & 0xF8) == 0xA0) { //ANA S - AND register with A
  387.             reg8[A] &= read_reg8(opcode & 7); //reg8[opcode & 7];
  388.             clear_C();
  389.             calc_SZP(reg8[A]);
  390.         }
  391.         else if (opcode == 0xE6) { //ANI # - AND immediate with A
  392.             reg8[A] &= i8080_read(reg_PC++);
  393.             clear_C();
  394.             calc_SZP(reg8[A]);
  395.         }
  396.         else if ((opcode & 0xF8) == 0xB0) { //ORA S - OR register with A
  397.             reg8[A] |= read_reg8(opcode & 7); //reg8[opcode & 7];
  398.             clear_C();
  399.             calc_SZP(reg8[A]);
  400.         }
  401.         else if (opcode == 0xF6) { //ORI # - OR immediate with A
  402.             reg8[A] |= i8080_read(reg_PC++);
  403.             clear_C();
  404.             calc_SZP(reg8[A]);
  405.         }
  406.         else if ((opcode & 0xF8) == 0xA8) { //XRA S - XOR register with A
  407.             reg8[A] ^= read_reg8(opcode & 7); //reg8[opcode & 7];
  408.             clear_C();
  409.             calc_SZP(reg8[A]);
  410.         }
  411.         else if (opcode == 0xEE) { //XRI # - XOR immediate with A
  412.             reg8[A] ^= i8080_read(reg_PC++);
  413.             clear_C();
  414.             calc_SZP(reg8[A]);
  415.         }
  416.         else if ((opcode & 0xF8) == 0xB8) { //CMP S - compare register with A
  417.             temp8 = read_reg8(opcode & 7); //reg8[opcode & 7];
  418.             temp16 = (uint16_t)reg8[A] - (uint16_t)temp8;
  419.             if (temp16 & 0xFF00) set_C(); else clear_C();
  420.             calc_subAC(reg8[A], temp8);
  421.             calc_SZP((uint8_t)temp16);
  422.         }
  423.         else if (opcode == 0xFE) { //CPI # - compare immediate with A
  424.             temp8 = i8080_read(reg_PC++);
  425.             temp16 = (uint16_t)reg8[A] - (uint16_t)temp8;
  426.             if (temp16 & 0xFF00) set_C(); else clear_C();
  427.             calc_subAC(reg8[A], temp8);
  428.             calc_SZP((uint8_t)temp16);
  429.         }
  430.         else if (opcode == 0x07) { //RLC - rotate A left
  431.             if (reg8[A] & 0x80) set_C(); else clear_C();
  432.             reg8[A] = (reg8[A] >> 7) | (reg8[A] << 1);
  433.         }
  434.         else if (opcode == 0x0F) { //RRC - rotate A right
  435.             if (reg8[A] & 0x01) set_C(); else clear_C();
  436.             reg8[A] = (reg8[A] << 7) | (reg8[A] >> 1);
  437.         }
  438.         else if (opcode == 0x17) { //RAL - rotate A left through carry
  439.             temp8 = test_C();
  440.             if (reg8[A] & 0x80) set_C(); else clear_C();
  441.             reg8[A] = (reg8[A] << 1) | temp8; //TODO: did i do this right??
  442.         }
  443.         else if (opcode == 0x1F) { //RAR - rotate A right through carry
  444.             temp8 = test_C();
  445.             if (reg8[A] & 0x01) set_C(); else clear_C();
  446.             reg8[A] = (reg8[A] >> 1) | (temp8 << 7); //TODO: did i do this right??
  447.         }
  448.         else if (opcode == 0x2F) { //CMA - compliment A
  449.             reg8[A] = ~reg8[A];
  450.         }
  451.         else if (opcode == 0x3F) { //CMC - compliment carry flag
  452.             reg8[FLAGS] ^= 1;
  453.         }
  454.         else if (opcode == 0x37) { //STC - set carry flag
  455.             set_C();
  456.         }
  457.         else if (opcode == 0xC3) { //JMP a - unconditional jump
  458.             temp16 = (uint16_t)i8080_read(reg_PC) | (((uint16_t)i8080_read(reg_PC + 1)) << 8);
  459.             reg_PC = temp16;
  460.         }
  461.         else if ((opcode & 0xC7) == 0xC2) { //Jccc a - conditional jump
  462.             temp16 = (uint16_t)i8080_read(reg_PC) | (((uint16_t)i8080_read(reg_PC + 1)) << 8);
  463.             if (test_cond((opcode >> 3) & 7)) reg_PC = temp16; else reg_PC += 2;
  464.         }
  465.         else if (opcode == 0xCD) { //CALL a - unconditional call
  466.             temp16 = (uint16_t)i8080_read(reg_PC) | (((uint16_t)i8080_read(reg_PC + 1)) << 8);
  467.             i8080_push(reg_PC + 2);
  468.             reg_PC = temp16;
  469.         }
  470.         else if ((opcode & 0xC7) == 0xC4) { //Cccc a - conditional call
  471.             temp16 = (uint16_t)i8080_read(reg_PC) | (((uint16_t)i8080_read(reg_PC + 1)) << 8);
  472.             if (test_cond((opcode >> 3) & 7)) {
  473.                 i8080_push(reg_PC + 2);
  474.                 reg_PC = temp16;
  475.             } else {
  476.                 reg_PC += 2;
  477.             }
  478.         }
  479.         else if (opcode == 0xC9) { //RET - unconditional return
  480.             reg_PC = i8080_pop();
  481.         }
  482.         else if ((opcode & 0xC7) == 0xC0) { //Rccc - conditional return
  483.             if (test_cond((opcode >> 3) & 7)) reg_PC = i8080_pop();
  484.         }
  485.         else if (opcode == 0xC7) { //RST n - restart (call n*8)
  486.             i8080_push(reg_PC);
  487.             reg_PC = (uint16_t)((opcode >> 3) & 7) << 3;
  488.         }
  489.         else if (opcode == 0xE9) { //PCHL - jump to address in H:L
  490.             reg_PC = reg16_HL;
  491.         }
  492.         else if ((opcode & 0xCF) == 0xC5) { //PUSH RP - push register pair on the stack
  493.             reg = (opcode >> 4) & 3;
  494.             i8080_push(read_RP_PUSHPOP(reg));
  495.         }
  496.         else if ((opcode & 0xCF) == 0xC1) { //POP RP - pop register pair from the stack
  497.             reg = (opcode >> 4) & 3;
  498.             write16_RP_PUSHPOP(reg, i8080_pop());
  499.         }
  500.         else if (opcode == 0xE3) { //XTHL - swap H:L with top word on stack
  501.             temp16 = i8080_pop();
  502.             i8080_push(reg16_HL);
  503.             write16_RP(2, temp16);
  504.         }
  505.         else if (opcode == 0xF9) { //SPHL - set SP to content of HL
  506.             reg_SP = reg16_HL;
  507.         }
  508.         else if (opcode == 0xDB) { //IN p - read input port into A
  509.             reg8[A] = i8080_inport(i8080_read(reg_PC++));
  510.         }
  511.         else if (opcode == 0xD3) { //OUT p - write A to output port
  512.             i8080_outport(i8080_read(reg_PC++), reg8[A]);
  513.         }
  514.         else if (opcode == 0xFB) { //EI - enable interrupts
  515.             INTE = 1;
  516.         }
  517.         else if (opcode == 0xF3) { //DI - disbale interrupts
  518.             INTE = 0;
  519.         }
  520.         else if (opcode == 0x76) { //HLT - halt processor
  521.             reg_PC--;
  522.         }
  523.         else if (opcode == 0x00) { //NOP - no operation
  524.         }
  525.         else {
  526.             printf("UNRECOGNIZED INSTRUCTION @ %04Xh: %02X\n", reg_PC - 1, opcode);
  527.             exit(0);
  528.         }
  529.  
  530.     }
  531. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement