Remove obsolescent macro AM_PROG_CC_C_O
[emu8051.git] / src / cpu8051.c
index b83175d..bf7bd99 100644 (file)
 #include "reg8051.h"
 #include "cpu8051.h"
 #include "memory.h"
+#include "psw.h"
+#include "timers.h"
 #include "disasm.h"
+#include "options.h"
 #include "instructions_8051.h"
 
+extern struct options_t options;
+
 /* Check if the address is a breakpoint */
 int
 IsBreakpoint(unsigned int address)
@@ -46,6 +51,16 @@ IsBreakpoint(unsigned int address)
        return 0;
 }
 
+/* Check if the address is a stop point */
+int
+IsStoppoint(unsigned int address)
+{
+       if ((options.stop_address != 0) && (options.stop_address == address))
+               return 1;
+       else
+               return 0;
+}
+
 /* Show Breakpoints list */
 void
 ShowBreakpoints(void)
@@ -95,6 +110,8 @@ ToggleBreakpoint(unsigned int address)
 void
 cpu8051_init(void)
 {
+       memory_init();
+
        cpu8051.pc = 0;
        cpu8051.clock = 0;
        cpu8051.active_priority = -1;
@@ -105,24 +122,20 @@ cpu8051_init(void)
 void
 cpu8051_Reset(void)
 {
-       int i;
-
        cpu8051.pc = 0;
        cpu8051.clock = 0;
        cpu8051.active_priority = -1;
 
-       /* Reset registers */
+       /* Clear IRAM and SFR. */
+       memory_clear(INT_MEM_ID);
 
-       for (i = 0; i < 256; i++) {
-               /* Clear  IRAM and SFR */
-               memory_write8(INT_MEM_ID, i, 0);
-       }
+       memory_sfr_write8(_P0_, 0xFF);
+       memory_sfr_write8(_P1_, 0xFF);
+       memory_sfr_write8(_P2_, 0xFF);
+       memory_sfr_write8(_P3_, 0xFF);
 
-       memory_write8(INT_MEM_ID, _P0_, 0xFF);
-       memory_write8(INT_MEM_ID, _P1_, 0xFF);
-       memory_write8(INT_MEM_ID, _P2_, 0xFF);
-       memory_write8(INT_MEM_ID, _P3_, 0xFF);
-       memory_write8(INT_MEM_ID, _SP_, 0x07);
+       /* The default value of SP (after system reset) is 07 */
+       memory_sfr_write8(_SP_, 0x07);
 }
 
 static void
@@ -210,16 +223,26 @@ cpu8051_ReadB(uint8_t bit_address)
        return BitValue;
 }
 
+static int
+cpu8051_interrupt_fire(int interrupt_no, int priority)
+{
+       if (cpu8051_ReadD(_IP_) & INTERRUPT_MASK(interrupt_no))
+               return priority;
+       else
+               return !priority;
+}
+
+static int
+cpu8051_interrupt_enabled(int interrupt_no)
+{
+       return (cpu8051_ReadD(_IE_) & INTERRUPT_MASK(interrupt_no)) ? 1 : 0;
+}
+
 static void
 cpu8051_process_interrupt(int pc, int pri)
 {
-       unsigned char SP;
-
-       SP = cpu8051_ReadD(_SP_);
-       cpu8051_WriteI(++SP, (cpu8051.pc & 0xFF));
-       cpu8051_WriteI(++SP, (cpu8051.pc >> 8));
-       cpu8051_WriteD(_SP_, SP);
-       cpu8051.pc = 0x0B;
+       stack_push16(cpu8051.pc);
+       cpu8051.pc = pc;
        cpu8051.active_priority = pri;
 }
 
@@ -233,20 +256,20 @@ cpu8051_CheckInterrupts(void)
        if ((cpu8051_ReadD(_IE_) & 0x80) == 0)
                return;
 
-       for (i = 1; i >= 0; i--) {
+       for (i = INTERRUPT_PRIORITY_HIGH; i >= INTERRUPT_PRIORITY_LOW; i--) {
                if (cpu8051.active_priority < i) {
                        /* Interrupt timer 0 */
-                       if ((cpu8051_ReadD(_IE_) & 0x02) &&
-                           ((cpu8051_ReadD(_IP_ & 0x02) ? i : !i) &&
-                            (cpu8051_ReadD(_TCON_) & 0x20))) {
+                       if (cpu8051_interrupt_enabled(INTERRUPT_1) &&
+                           cpu8051_interrupt_fire(INTERRUPT_1, i) &&
+                            (cpu8051_ReadD(_TCON_) & 0x20)) {
                                cpu8051_WriteD(_TCON_,
                                               cpu8051_ReadD(_TCON_) & 0xDF);
                                cpu8051_process_interrupt(0x0B, i);
                                return;
                        }
                        /* Interrupt timer 1 */
-                       if ((cpu8051_ReadD(_IE_) & 0x08) &&
-                           ((cpu8051_ReadD(_IP_) & 0x08) ? i : !i) &&
+                       if (cpu8051_interrupt_enabled(INTERRUPT_3) &&
+                           cpu8051_interrupt_fire(INTERRUPT_3, i) &&
                            (cpu8051_ReadD(_TCON_) & 0x80)) {
                                cpu8051_WriteD(_TCON_,
                                               cpu8051_ReadD(_TCON_) & 0x7F);
@@ -254,15 +277,15 @@ cpu8051_CheckInterrupts(void)
                                return;
                        }
                        /* Serial Interrupts */
-                       if ((cpu8051_ReadD(_IE_) & 0x10) &&
-                           ((cpu8051_ReadD(_IP_) & 0x10) ? i : !i) &&
+                       if (cpu8051_interrupt_enabled(INTERRUPT_4) &&
+                           cpu8051_interrupt_fire(INTERRUPT_4, i) &&
                            (cpu8051_ReadD(_SCON_) & 0x03)) {
                                cpu8051_process_interrupt(0x23, i);
                                return;
                        }
                        /* Interrupt timer 2 */
-                       if ((cpu8051_ReadD(_IE_) & 0x20) &&
-                           ((cpu8051_ReadD(_IP_) & 0x20) ? i : !i) &&
+                       if (cpu8051_interrupt_enabled(INTERRUPT_5) &&
+                           cpu8051_interrupt_fire(INTERRUPT_5, i) &&
                            (cpu8051_ReadD(_T2CON_) & 0x80)) {
                                cpu8051_process_interrupt(0x2B, i);
                                return;
@@ -271,104 +294,6 @@ cpu8051_CheckInterrupts(void)
        }
 }
 
-static void
-process_timer(uint8_t tl, uint8_t th, uint8_t tf_mask, uint8_t TR, uint8_t mode,
-             uint8_t GATE, uint32_t TimerCounter)
-{
-       unsigned int tmp;
-
-       switch (mode) {
-       case 0:
-               /* Mode 0, 13-bits counter. */
-               tmp = cpu8051_ReadD(th) * 0x100 + cpu8051_ReadD(tl);
-               tmp++;
-               tmp &= 0x1FFF; /* We keep only 13 bits */
-
-               if (tmp == 0)  /* If overflow set TF0 */
-                       cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask);
-               cpu8051_WriteD(_TH0_, tmp / 0x100);
-               cpu8051_WriteD(_TL0_, tmp & 0xFF);
-               break;
-       case 1:
-               /* Mode 1, 16-bits counter */
-               tmp = cpu8051_ReadD(th) * 0x100 + cpu8051_ReadD(tl);
-               tmp++;
-               tmp &= 0xFFFF; /* We keep only 16 bits */
-               if (tmp == 0) /* If overflow set TF0 */
-                       cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask);
-               cpu8051_WriteD(_TH0_, (tmp / 0x100));
-               cpu8051_WriteD(_TL0_, (tmp & 0xFF));
-               break;
-       case 2:
-               /* Mode 2, 8-bits counter with Auto-Reload */
-               tmp = cpu8051_ReadD(tl);
-               tmp++;
-               tmp &= 0xFF;
-               if (tmp == 0) {
-                       /* If overflow -> reload and set TF0 */
-                       cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask);
-                       cpu8051_WriteD(tl, cpu8051_ReadD(th));
-               } else
-                       cpu8051_WriteD(tl, tmp);
-               break;
-       case 3:
-               /* Mode 3 : inactive mode for timer 1 */
-               if (tl == _TL0_) {
-                       /* TL0 and TH0 are 2 independents 8-bits timers. */
-                       if (TR && !GATE && !TimerCounter) {
-                               tmp = cpu8051_ReadD(tl);
-                               tmp++;
-                               tmp &= 0xFF;
-                               if (tmp == 0) /* If TL0 overflow set TF0 */
-                                       cpu8051_WriteD(_TCON_,
-                                                      cpu8051_ReadD(_TCON_) |
-                                                      tf_mask);
-                               cpu8051_WriteD(tl, tmp);
-                       } /* TH0 utilise TR1 et TF1. */
-                       TR = cpu8051_ReadD(_TCON_) & 0x40;
-                       if (TR) {
-                               tmp = cpu8051_ReadD(th);
-                               tmp++;
-                               tmp &= 0xFF;
-                               if (tmp == 0) /* If TH0 overflow set TF1 */
-                                       cpu8051_WriteD(_TCON_,
-                                                      cpu8051_ReadD(_TCON_) |
-                                                      0x80);
-                               cpu8051_WriteD(_TH0_, tmp);
-                       }
-               }
-               break;
-       }
-}
-
-/* Run timers */
-static void
-cpu8051_DoTimers(void)
-{
-       unsigned int TR;
-       unsigned int MODE;
-       unsigned int GATE;
-       unsigned int TimerCounter;
-
-       /* Timer 0 */
-       TR = cpu8051_ReadD(_TCON_) & 0x10;
-       MODE = cpu8051_ReadD(_TMOD_) & 0x03;
-       GATE = cpu8051_ReadD(_TMOD_) & 0x08;
-       TimerCounter = cpu8051_ReadD(_TMOD_) & 0x04;
-
-       if ((TR && !GATE && !TimerCounter) || (MODE == 3))
-               process_timer(_TL0_, _TH0_, 0x20, TR, MODE, GATE, TimerCounter);
-
-       /* Timer 1 */
-       TR = cpu8051_ReadD(_TCON_) & 0x40;
-       MODE = (cpu8051_ReadD(_TMOD_) & 0x30) >> 4 ;
-       GATE = cpu8051_ReadD(_TMOD_) & 0x80;
-       TimerCounter = cpu8051_ReadD(_TMOD_) & 0x40;
-
-       if (TR && !GATE && !TimerCounter)
-               process_timer(_TL1_, _TH1_, 0x80, TR, MODE, GATE, TimerCounter);
-}
-
 /* Execute at address cpu8051.pc from PGMMem */
 void
 cpu8051_Exec(void)
@@ -381,9 +306,15 @@ cpu8051_Exec(void)
        cpu8051.pc++;
        insttiming = (*opcode_table[opcode])(); /* Function callback. */
 
+       /*
+        * Parity bit (p): is automatically set or cleared in each machine
+        * cycle to establish even parity in the accumulator.
+        */
+       psw_compute_parity_bit();
+
        for (i = 0; i < insttiming; i++) {
                cpu8051_CheckInterrupts();
-               cpu8051_DoTimers();
+               timers_check();
                cpu8051.clock++;
        }
 }
@@ -479,7 +410,7 @@ cpu8051_get_instruction_size(unsigned char opcode)
        return InstSizesTbl[opcode];
 }
 
-/* Display instruction menmonic. */
+/* Display instruction mnemonic. */
 void
 cpu8051_disasm_mnemonic(unsigned char OpCode, char *buf)
 {
@@ -617,7 +548,7 @@ cpu8051_Disasm(unsigned int Address, char *Text)
        for (; len < 17;)
                len += sprintf(&Text[len], " ");
 
-       /* Display instruction menmonic. */
+       /* Display instruction mnemonic. */
        len += sprintf(&Text[len], "%s ",
                              InstTextTbl[InstTypesTbl[OpCode]]);
        ArgTblOfs = OpCode << 2;