#include "reg8051.h"
#include "cpu8051.h"
#include "memory.h"
+#include "psw.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
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);
+ stack_push16(pc);
cpu8051.pc = 0x0B;
cpu8051.active_priority = pri;
}
uint8_t GATE, uint32_t TimerCounter)
{
unsigned int tmp;
+ unsigned int prescaler;
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);
+ /* Mode 0, 8-bit timer "TH" with "TL" as 5-bit prescaler. */
+ prescaler = cpu8051_ReadD(tl);
+ prescaler++;
+ prescaler &= 0x1F; /* We keep only 5 bits */
+ cpu8051_WriteD(tl, prescaler);
+
+ if (prescaler == 0) {
+ /* If overflow, increment TH */
+ tmp = cpu8051_ReadD(th);
+ tmp++;
+ tmp &= 0xFF; /* We keep only 8 bits */
+
+ if (tmp == 0) /* If overflow set TF */
+ cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask);
+
+ cpu8051_WriteD(th, tmp);
+ }
break;
case 1:
/* Mode 1, 16-bits counter */
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));
+ cpu8051_WriteD(th, (tmp / 0x100));
+ cpu8051_WriteD(tl, (tmp & 0xFF));
break;
case 2:
/* Mode 2, 8-bits counter with Auto-Reload */
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();
}
/*
- * Addressing modes defined in the order as they appear in disasm.hpp
+ * Addressing modes defined in the order as they appear in disasm.h
* from table argstext[]
*/
#define ADDR11 0
sprintf(&text[len], ".%X", bit_address);
}
+/* Get instruction size from opcode */
+int
+cpu8051_get_instruction_size(unsigned char opcode)
+{
+ return InstSizesTbl[opcode];
+}
+
+/* Display instruction mnemonic. */
+void
+cpu8051_disasm_mnemonic(unsigned char OpCode, char *buf)
+{
+ sprintf(buf, "%s", InstTextTbl[InstTypesTbl[OpCode]]);
+}
+
+/* Disasm instruction arguments starting at address into a text string */
+void
+cpu8051_disasm_args(unsigned int address, char *buf)
+{
+ int len = 0;
+ char TextTmp[20];
+ unsigned char OpCode;
+ int ArgTblOfs;
+ int i;
+
+ OpCode = memory_read8(PGM_MEM_ID, address);
+ ArgTblOfs = OpCode << 2;
+ address++;
+
+ /*
+ * MOV direct, direct (OpCode 85h) is peculiar, the operands
+ * are inverted
+ */
+ if (OpCode == 0x85) {
+ cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, address + 1),
+ TextTmp);
+ len += sprintf(&buf[len], "%s,", TextTmp);
+ cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, address),
+ TextTmp);
+ len += sprintf(&buf[len], "%s", TextTmp);
+ address += 2;
+ return;
+ }
+
+ for (i = 1; i <= InstArgTbl[ArgTblOfs]; i++) {
+ switch (InstArgTbl[ArgTblOfs + i]) {
+ case ADDR11: {
+ len += sprintf(&buf[len],
+ "%.4XH", ((OpCode << 3) & 0xF00) +
+ (memory_read8(PGM_MEM_ID, address)));
+ address++;
+ break;
+ }
+ case ADDR16: {
+ len += sprintf(
+ &buf[len], "%.4XH",
+ ((memory_read8(PGM_MEM_ID, address) << 8) +
+ memory_read8(PGM_MEM_ID, address + 1)));
+ address += 2;
+ break;
+ }
+ case DIRECT: {
+ cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, address),
+ TextTmp);
+ len += sprintf(&buf[len], "%s", TextTmp);
+ address++;
+ break;
+ }
+ case BITADDR: {
+ cpu8051_IntMemBitInfo(
+ (memory_read8(PGM_MEM_ID, address) & 0xF8),
+ TextTmp);
+ len += sprintf(&buf[len], "%s.%X" , TextTmp,
+ (memory_read8(PGM_MEM_ID, address) & 7));
+ address++;
+ break;
+ }
+ case RELADDR: {
+ address++;
+ len += sprintf(&buf[len], "%.4XH", (address & 0xFF00) +
+ (((address & 0xFF) +
+ memory_read8(PGM_MEM_ID,
+ address - 1)) & 0xFF));
+ break;
+ }
+ case DATAIMM: {
+ len += sprintf(&buf[len], "#%.2XH",
+ memory_read8(PGM_MEM_ID, address));
+ address++;
+ break;
+ }
+ case DATA16: {
+ len += sprintf(&buf[len], "#%.4XH",
+ ((memory_read8(PGM_MEM_ID,
+ address) << 8) +
+ memory_read8(PGM_MEM_ID, address+1)));
+ address += 2;
+ break;
+ }
+ case CBITADDR: {
+ cpu8051_IntMemBitInfo((memory_read8(PGM_MEM_ID,
+ address) & 0xF8),
+ TextTmp);
+ len += sprintf(&buf[len], "/%s.%X", TextTmp,
+ (memory_read8(PGM_MEM_ID, address) & 7));
+ address++;
+ break;
+ }
+ default: {
+ len += sprintf(&buf[len], "%s",
+ ArgsTextTbl[InstArgTbl[ArgTblOfs + i]]);
+ }
+ }
+ if (i < InstArgTbl[ArgTblOfs])
+ len += sprintf(&buf[len], ",");
+ }
+}
+
/* Disasm one instruction at Address into a Text string */
int
cpu8051_Disasm(unsigned int Address, char *Text)
int InstSize;
int i;
+ /* Display address. */
+ len += sprintf(Text, " %.4X ", Address);
+
OpCode = memory_read8(PGM_MEM_ID, Address);
InstSize = InstSizesTbl[OpCode];
- len += sprintf(Text, " %.4X ", Address);
-
+ /* Display hex bytes. */
for (i = 0; i < InstSize; i++)
len += sprintf(&Text[len], " %.2X",
memory_read8(PGM_MEM_ID, Address + i));
Address++;
+ /* Padd remaining area with spaces. */
for (; len < 17;)
len += sprintf(&Text[len], " ");
+ /* Display instruction mnemonic. */
len += sprintf(&Text[len], "%s ",
InstTextTbl[InstTypesTbl[OpCode]]);
ArgTblOfs = OpCode << 2;
+ /* Padd remaining area with spaces. */
for (; len < 25;)
len += sprintf(&Text[len], " ");
+ /* Display instruction arguments. */
+
/*
* MOV direct, direct (OpCode 85h) is peculiar, the operands
* are inverted