#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)
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)
void
cpu8051_init(void)
{
+ memory_init();
+
cpu8051.pc = 0;
cpu8051.clock = 0;
cpu8051.active_priority = -1;
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 nad 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
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;
}
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);
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;
}
}
-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)
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++;
}
}
return InstSizesTbl[opcode];
}
-/* Display instruction menmonic. */
+/* Display instruction mnemonic. */
void
cpu8051_disasm_mnemonic(unsigned char OpCode, char *buf)
{
for (; len < 17;)
len += sprintf(&Text[len], " ");
- /* Display instruction menmonic. */
+ /* Display instruction mnemonic. */
len += sprintf(&Text[len], "%s ",
InstTextTbl[InstTypesTbl[OpCode]]);
ArgTblOfs = OpCode << 2;