/* * Simulator of microcontrollers (uc51.cc) * * Copyright (C) 1999,99 Drotos Daniel, Talker Bt. * * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu * */ /* This file is part of microcontroller simulator: ucsim. UCSIM is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. UCSIM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with UCSIM; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*@1@*/ #include "ddconfig.h" #include #include #include #include #include #include #include #include //#if FD_HEADER_OK //# include HEADER_FD //#endif #include "i_string.h" // prj #include "utils.h" #include "globals.h" // sim #include "optioncl.h" #include "iwrap.h" //cmd.src #include "cmd_uccl.h" // local #include "uc51cl.h" #include "glob.h" #include "regs51.h" #include "timer0cl.h" #include "timer1cl.h" #include "serialcl.h" #include "portcl.h" #include "interruptcl.h" #include "types51.h" /* * Names of SFR cells */ static struct name_entry sfr_tab51[]= { {CPU_F380, 0xc7, "P4"}, {CPU_251, 0x84, "DPXL"}, {CPU_251|CPU_DS390|CPU_DS390F, 0x93, "DPX"}, {CPU_251, 0xa8, "IE0"}, {CPU_251, 0xb7, "IPH0"}, {CPU_251, 0xb8, "IPL0"}, {CPU_251, 0xbd, "SPH"}, {CPU_251, 0xd1, "PSW1"}, {CPU_DS390|CPU_DS390F, 0x80, "P4"}, {CPU_ALL_DS3X0, 0x84, "DPL1"}, {CPU_ALL_DS3X0, 0x85, "DPH1"}, {CPU_ALL_DS3X0, 0x86, "DPS"}, {CPU_ALL_DS3X0, 0x8e, "CKCON"}, {CPU_DS390|CPU_DS390F, 0x91, "EXIF"}, {CPU_DS390|CPU_DS390F, 0x92, "P4CNT"}, {CPU_DS390|CPU_DS390F, 0x95, "DPX1"}, {CPU_DS390|CPU_DS390F, 0x96, "C0RMS0"}, {CPU_DS390|CPU_DS390F, 0x97, "C0RMS1"}, {CPU_DS390|CPU_DS390F, 0x98, "SCON0"}, {CPU_DS390|CPU_DS390F, 0x99, "SBUF0"}, {CPU_DS390|CPU_DS390F, 0x9b, "ESP"}, {CPU_DS390|CPU_DS390F, 0x9c, "AP"}, {CPU_DS390|CPU_DS390F, 0x9d, "ACON"}, {CPU_DS390|CPU_DS390F, 0x9e, "C0TMA0"}, {CPU_DS390|CPU_DS390F, 0x9f, "C0TMA1"}, {CPU_DS390|CPU_DS390F, 0xa1, "P5"}, {CPU_DS390|CPU_DS390F, 0xa2, "P5CNT"}, {CPU_DS390|CPU_DS390F, 0xa3, "C0C"}, {CPU_DS390|CPU_DS390F, 0xa4, "C0S"}, {CPU_DS390|CPU_DS390F, 0xa5, "C0IR"}, {CPU_DS390|CPU_DS390F, 0xa6, "C0TE"}, {CPU_DS390|CPU_DS390F, 0xa7, "C0RE"}, {CPU_DS390|CPU_DS390F, 0xa9, "SADDR0"}, {CPU_DS390|CPU_DS390F, 0xaa, "SADDR1"}, {CPU_DS390|CPU_DS390F, 0xab, "C0M1C"}, {CPU_DS390|CPU_DS390F, 0xac, "C0M2C"}, {CPU_DS390|CPU_DS390F, 0xad, "C0M3C"}, {CPU_DS390|CPU_DS390F, 0xae, "C0M4C"}, {CPU_DS390|CPU_DS390F, 0xaf, "C0M5C"}, {CPU_DS390|CPU_DS390F, 0xb3, "C0M6C"}, {CPU_DS390|CPU_DS390F, 0xb4, "C0M7C"}, {CPU_DS390|CPU_DS390F, 0xb5, "C0M8C"}, {CPU_DS390|CPU_DS390F, 0xb6, "C0M9C"}, {CPU_DS390|CPU_DS390F, 0xb7, "C0M10C"}, {CPU_DS390|CPU_DS390F, 0xb9, "SADEN0"}, {CPU_DS390|CPU_DS390F, 0xba, "SADEN1"}, {CPU_DS390|CPU_DS390F, 0xbb, "C0M11C"}, {CPU_DS390|CPU_DS390F, 0xbc, "C0M12C"}, {CPU_DS390|CPU_DS390F, 0xbd, "C0M13C"}, {CPU_DS390|CPU_DS390F, 0xbe, "C0M14C"}, {CPU_DS390|CPU_DS390F, 0xbf, "C0M15C"}, {CPU_DS390|CPU_DS390F, 0xc0, "SCON1"}, {CPU_DS390|CPU_DS390F, 0xc1, "SBUF1"}, {CPU_DS390|CPU_DS390F, 0xc4, "PMR"}, {CPU_DS390|CPU_DS390F, 0xc5, "STATUS"}, {CPU_DS390|CPU_DS390F, 0xc6, "MCON"}, {CPU_DS390|CPU_DS390F, 0xc7, "TA"}, {CPU_DS390|CPU_DS390F, 0xce, "COR"}, {CPU_DS390|CPU_DS390F, 0xd1, "MCNT0"}, {CPU_DS390|CPU_DS390F, 0xd2, "MCNT1"}, {CPU_DS390|CPU_DS390F, 0xd3, "MA"}, {CPU_DS390|CPU_DS390F, 0xd4, "MB"}, {CPU_DS390|CPU_DS390F, 0xd5, "MC"}, {CPU_DS390|CPU_DS390F, 0xd6, "C1RMS0"}, {CPU_DS390|CPU_DS390F, 0xd7, "C1RMS1"}, {CPU_DS390|CPU_DS390F, 0xd8, "WDCON"}, {CPU_DS390|CPU_DS390F, 0xde, "C1TMA0"}, {CPU_DS390|CPU_DS390F, 0xdf, "C1TMA1"}, {CPU_DS390|CPU_DS390F, 0xe3, "C1C"}, {CPU_DS390|CPU_DS390F, 0xe4, "C1S"}, {CPU_DS390|CPU_DS390F, 0xe5, "C11R"}, {CPU_DS390|CPU_DS390F, 0xe6, "C1TE"}, {CPU_DS390|CPU_DS390F, 0xe7, "C1RE"}, {CPU_DS390|CPU_DS390F, 0xe8, "EIE"}, {CPU_DS390|CPU_DS390F, 0xea, "MXAX"}, {CPU_DS390|CPU_DS390F, 0xeb, "C1M1C"}, {CPU_DS390|CPU_DS390F, 0xec, "C1M2C"}, {CPU_DS390|CPU_DS390F, 0xed, "C1M3C"}, {CPU_DS390|CPU_DS390F, 0xee, "C1M4C"}, {CPU_DS390|CPU_DS390F, 0xef, "C1M5C"}, {CPU_DS390|CPU_DS390F, 0xf3, "C1M6C"}, {CPU_DS390|CPU_DS390F, 0xf4, "C1M7C"}, {CPU_DS390|CPU_DS390F, 0xf5, "C1M8C"}, {CPU_DS390|CPU_DS390F, 0xf6, "C1M9C"}, {CPU_DS390|CPU_DS390F, 0xf7, "C1M10C"}, {CPU_DS390|CPU_DS390F, 0xfb, "C1M11C"}, {CPU_DS390|CPU_DS390F, 0xfc, "C1M12C"}, {CPU_DS390|CPU_DS390F, 0xfd, "C1M13C"}, {CPU_DS390|CPU_DS390F, 0xfe, "C1M14C"}, {CPU_DS390|CPU_DS390F, 0xff, "C1M15C"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x80, "P0"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x81, "SP"}, //{CPU_ALL_51|CPU_ALL_52|CPU_251, 0x82, "DPL"}, //{CPU_ALL_51|CPU_ALL_52|CPU_251, 0x83, "DPH"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x87, "PCON"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x88, "TCON"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x89, "TMOD"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x8a, "TL0"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x8b, "TL1"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x8c, "TH0"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x8d, "TH1"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x90, "P1"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x98, "SCON"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x99, "SBUF"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xa0, "P2"}, {CPU_ALL_51|CPU_ALL_52, 0xa8, "IE"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xb0, "P3"}, {CPU_ALL_51|CPU_ALL_52, 0xb8, "IP"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xd0, "PSW"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xe0, "ACC"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xf0, "B"}, {CPU_ALL_52|CPU_251, 0xc8, "T2CON"}, {CPU_ALL_52|CPU_251, 0xca, "RCAP2L"}, {CPU_ALL_52|CPU_251, 0xcb, "RCAP2H"}, {CPU_ALL_52|CPU_251, 0xcc, "TL2"}, {CPU_ALL_52|CPU_251, 0xcd, "TH2"}, {CPU_51R|CPU_89C51R, 0x8e, "AUXR"}, {CPU_51R|CPU_89C51R|CPU_251, 0xa6, "WDTRST"}, {CPU_51R|CPU_89C51R|CPU_251, 0xa9, "SADDR"}, {CPU_51R|CPU_89C51R, 0xb7, "IPH"}, {CPU_51R|CPU_89C51R|CPU_251, 0xb9, "SADEN"}, {CPU_51R|CPU_89C51R|CPU_251|\ CPU_DS390|CPU_DS390F, 0xc9, "T2MOD"}, /* fixme: isn't that CPU_ALL_52? */ {CPU_89C51R, 0xa2, "AUXR1"}, {CPU_89C51R|CPU_251, 0xd8, "CCON"}, {CPU_89C51R|CPU_251, 0xd9, "CMOD"}, {CPU_89C51R|CPU_251, 0xda, "CCAPM0"}, {CPU_89C51R|CPU_251, 0xdb, "CCAPM1"}, {CPU_89C51R|CPU_251, 0xdc, "CCAPM2"}, {CPU_89C51R|CPU_251, 0xdd, "CCAPM3"}, {CPU_89C51R|CPU_251, 0xde, "CCAPM4"}, {CPU_89C51R|CPU_251, 0xe9, "CL"}, {CPU_89C51R|CPU_251, 0xea, "CCAP0L"}, {CPU_89C51R|CPU_251, 0xeb, "CCAP1L"}, {CPU_89C51R|CPU_251, 0xec, "CCAP2L"}, {CPU_89C51R|CPU_251, 0xed, "CCAP3L"}, {CPU_89C51R|CPU_251, 0xee, "CCAP4L"}, {CPU_89C51R|CPU_251, 0xf9, "CH"}, {CPU_89C51R|CPU_251, 0xfa, "CCAP0H"}, {CPU_89C51R|CPU_251, 0xfb, "CCAP1H"}, {CPU_89C51R|CPU_251, 0xfc, "CCAP2H"}, {CPU_89C51R|CPU_251, 0xfd, "CCAP3H"}, {CPU_89C51R|CPU_251, 0xfe, "CCAP4H"}, {CPU_F380, 0x8e, "CKCON"}, {CPU_F380, 0x8f, "PSCTL"}, {CPU_F380, 0x91, "TMR3CN"}, {CPU_F380, 0x91, "TMR4CN"}, {CPU_F380, 0x92, "TMR3RLL"}, {CPU_F380, 0x92, "TMR4RLL"}, {CPU_F380, 0x93, "TMR3RLH"}, {CPU_F380, 0x93, "TMR4RLH"}, {CPU_F380, 0x94, "TMR3L"}, {CPU_F380, 0x94, "TMR4L"}, {CPU_F380, 0x95, "TMR3H"}, {CPU_F380, 0x95, "TMR4H"}, {CPU_F380, 0x96, "USB0ADR"}, {CPU_F380, 0x97, "USB0DAT"}, {CPU_F380, 0x9a, "CPT1CN"}, {CPU_F380, 0x9b, "CPT0CN"}, {CPU_F380, 0x9c, "CPT1MD"}, {CPU_F380, 0x9d, "CPT0MD"}, {CPU_F380, 0x9e, "CPT1MX"}, {CPU_F380, 0x9f, "CPT0MX"}, {CPU_F380, 0xa1, "SPI0CFG"}, {CPU_F380, 0xa2, "SPI0CKR"}, {CPU_F380, 0xa3, "SPI0DAT"}, {CPU_F380, 0xa4, "P0MDOUT"}, {CPU_F380, 0xa5, "P1MDOUT"}, {CPU_F380, 0xa6, "P2MDOUT"}, {CPU_F380, 0xa7, "P3MDOUT"}, {CPU_F380, 0xa9, "CLKSEL"}, {CPU_F380, 0xaa, "EMI0CN"}, {CPU_F380, 0xac, "SBCON1"}, {CPU_F380, 0xae, "P4MDOUT"}, {CPU_F380, 0xaf, "PFE0CN"}, {CPU_F380, 0xb1, "OSCXCN"}, {CPU_F380, 0xb2, "OSCICN"}, {CPU_F380, 0xb3, "OSCICL"}, {CPU_F380, 0xb4, "SBRLL1"}, {CPU_F380, 0xb5, "SBRLH1"}, {CPU_F380, 0xb6, "FLSCL"}, {CPU_F380, 0xb7, "FLKEY"}, {CPU_F380, 0xb9, "CLKMUL"}, {CPU_F380, 0xb9, "SMBTC"}, {CPU_F380, 0xba, "AMX0N"}, {CPU_F380, 0xbb, "AMX0P"}, {CPU_F380, 0xbc, "ADC0CF"}, {CPU_F380, 0xbd, "ADC0L"}, {CPU_F380, 0xbe, "ADC0H"}, {CPU_F380, 0xbf, "SFRPAGE"}, {CPU_F380, 0xc0, "SMB0CN"}, {CPU_F380, 0xc0, "SMB1CN"}, {CPU_F380, 0xc1, "SMB0CF"}, {CPU_F380, 0xc1, "SMB1CF"}, {CPU_F380, 0xc2, "SMB0DAT"}, {CPU_F380, 0xc2, "SMB1DAT"}, {CPU_F380, 0xc3, "ADC0GTL"}, {CPU_F380, 0xc4, "ADC0GTH"}, {CPU_F380, 0xc5, "ADC0LTL"}, {CPU_F380, 0xc6, "ADC0LTH"}, {CPU_F380, 0xc7, "P4"}, {CPU_F380, 0xd1, "REF0CN"}, {CPU_F380, 0xd2, "SCON1"}, {CPU_F380, 0xd3, "SBUF1"}, {CPU_F380, 0xd4, "P0SKIP"}, {CPU_F380, 0xd5, "P1SKIP"}, {CPU_F380, 0xd6, "P2SKIP"}, {CPU_F380, 0xd7, "USB0XCN"}, {CPU_F380, 0xd8, "PCA0CN"}, {CPU_F380, 0xd9, "PCA0MD"}, {CPU_F380, 0xda, "PCA0CPM0"}, {CPU_F380, 0xdb, "PCA0CPM1"}, {CPU_F380, 0xdc, "PCA0CPM2"}, {CPU_F380, 0xdd, "PCA0CPM3"}, {CPU_F380, 0xde, "PCA0CPM4"}, {CPU_F380, 0xdf, "P3SKIP"}, {CPU_F380, 0xe1, "XBR0"}, {CPU_F380, 0xe2, "XBR1"}, {CPU_F380, 0xe3, "XBR2"}, {CPU_F380, 0xe4, "IT01CF"}, {CPU_F380, 0xe4, "CKCON1"}, {CPU_F380, 0xe5, "SMOD1"}, {CPU_F380, 0xe6, "EIE1"}, {CPU_F380, 0xe7, "EIE2"}, {CPU_F380, 0xe8, "ADC0CN"}, {CPU_F380, 0xe9, "PCA0CPL1"}, {CPU_F380, 0xea, "PCA0CPH1"}, {CPU_F380, 0xeb, "PCA0CPL2"}, {CPU_F380, 0xec, "PCA0CPH2"}, {CPU_F380, 0xed, "PCA0CPL3"}, {CPU_F380, 0xee, "PCA0CPH3"}, {CPU_F380, 0xef, "RSTSRC"}, {CPU_F380, 0xf1, "P0MDIN"}, {CPU_F380, 0xf2, "P1MDIN"}, {CPU_F380, 0xf3, "P2MDIN"}, {CPU_F380, 0xf4, "P3MDIN"}, {CPU_F380, 0xf5, "P4MDIN"}, {CPU_F380, 0xf6, "EIP1"}, {CPU_F380, 0xf7, "EIP2"}, {CPU_F380, 0xf8, "SPI0CN"}, {CPU_F380, 0xf9, "PCA0L"}, {CPU_F380, 0xfa, "PCA0H"}, {CPU_F380, 0xfb, "PCA0CPL0"}, {CPU_F380, 0xfc, "PCA0CPH0"}, {CPU_F380, 0xfd, "PCA0CPL4"}, {CPU_F380, 0xfe, "PCA0CPH4"}, {CPU_F380, 0xff, "VDM0CN"}, {0, 0, NULL} }; /* * Names of bits */ static struct name_entry bit_tab51[]= { /* PSW */ {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xd7, "CY"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xd6, "AC"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xd5, "F0"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xd4, "RS1"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xd3, "RS0"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xd2, "OV"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xd1, "F1"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xd0, "P"}, /* TCON */ {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x8f, "TF1"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x8e, "TR1"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x8d, "TF0"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x8c, "TR0"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x8b, "IE1"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x8a, "IT1"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x89, "IE0"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x88, "IT0"}, /* IE */ {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xaf, "EA"}, {CPU_DS390|CPU_DS390F, 0xae, "ES1"}, {CPU_89C51R|CPU_251, 0xae, "EC"}, {CPU_ALL_52|CPU_251, 0xad, "ET2"}, {CPU_DS390|CPU_DS390F, 0xac, "ES0"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xac, "ES"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xab, "ET1"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xaa, "EX1"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xa9, "ET0"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0xa8, "EX0"}, /* IP */ {CPU_89C51R|CPU_251, 0xbe, "PPC"}, {CPU_DS390|CPU_DS390F, 0xbe, "PS1"}, {CPU_ALL_52, 0xbd, "PT2"}, {CPU_DS390|CPU_DS390F, 0xbc, "PS0"}, {CPU_ALL_51|CPU_ALL_52, 0xbc, "PS"}, {CPU_ALL_51|CPU_ALL_52, 0xbb, "PT1"}, {CPU_ALL_51|CPU_ALL_52, 0xba, "PX1"}, {CPU_ALL_51|CPU_ALL_52, 0xb9, "PT0"}, {CPU_ALL_51|CPU_ALL_52, 0xb8, "PX0"}, /* IPL0 */ {CPU_251, 0xbe, "IPL0.6"}, {CPU_251, 0xbd, "IPL0.5"}, {CPU_251, 0xbc, "IPL0.4"}, {CPU_251, 0xbb, "IPL0.3"}, {CPU_251, 0xba, "IPL0.2"}, {CPU_251, 0xb9, "IPL0.1"}, {CPU_251, 0xb8, "IPL0.0"}, /* SCON */ {CPU_DS390|CPU_DS390F, 0x9f, "SM0/FE_0"}, {CPU_DS390|CPU_DS390F, 0x9e, "SM1_0"}, {CPU_DS390|CPU_DS390F, 0x9d, "SM2_0"}, {CPU_DS390|CPU_DS390F, 0x9c, "REN_0"}, {CPU_DS390|CPU_DS390F, 0x9b, "TB8_0"}, {CPU_DS390|CPU_DS390F, 0x9a, "RB8_0"}, {CPU_DS390|CPU_DS390F, 0x99, "TI_0"}, {CPU_DS390|CPU_DS390F, 0x98, "RI_0"}, {CPU_51R|CPU_89C51R|CPU_251, 0x9f, "FE/SM0"}, {CPU_ALL_51|CPU_ALL_52, 0x9f, "SM0"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x9e, "SM1"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x9d, "SM2"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x9c, "REN"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x9b, "TB8"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x9a, "RB8"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x99, "TI"}, {CPU_ALL_51|CPU_ALL_52|CPU_251, 0x98, "RI"}, /* SCON 1 */ {CPU_DS390|CPU_DS390F, 0xc7, "SM0/FE_1"}, {CPU_DS390|CPU_DS390F, 0xc6, "SM1_1"}, {CPU_DS390|CPU_DS390F, 0xc5, "SM2_1"}, {CPU_DS390|CPU_DS390F, 0xc4, "REN_1"}, {CPU_DS390|CPU_DS390F, 0xc3, "TB8_1"}, {CPU_DS390|CPU_DS390F, 0xc2, "RB8_1"}, {CPU_DS390|CPU_DS390F, 0xc1, "TI_1"}, {CPU_DS390|CPU_DS390F, 0xc0, "RI_1"}, /* T2CON */ {CPU_ALL_52|CPU_251, 0xcf, "TF2"}, {CPU_ALL_52|CPU_251, 0xce, "EXF2"}, {CPU_ALL_52|CPU_251, 0xcd, "RCLK"}, {CPU_ALL_52|CPU_251, 0xcc, "TCLK"}, {CPU_ALL_52|CPU_251, 0xcb, "EXEN2"}, {CPU_ALL_52|CPU_251, 0xca, "TR2"}, {CPU_ALL_52|CPU_251, 0xc9, "C/T2"}, {CPU_ALL_52|CPU_251, 0xc8, "CP/RL2"}, /* CCON */ {CPU_89C51R|CPU_251, 0xdf, "CF"}, {CPU_89C51R|CPU_251, 0xde, "CR"}, {CPU_89C51R|CPU_251, 0xdc, "CCF4"}, {CPU_89C51R|CPU_251, 0xdb, "CCF3"}, {CPU_89C51R|CPU_251, 0xda, "CCF2"}, {CPU_89C51R|CPU_251, 0xd9, "CCF1"}, {CPU_89C51R|CPU_251, 0xd8, "CCF0"}, /* P1 */ {CPU_89C51R|CPU_251, 0x97, "CEX4"}, {CPU_89C51R|CPU_251, 0x96, "CEX3"}, {CPU_89C51R|CPU_251, 0x95, "CEX2"}, {CPU_89C51R|CPU_251, 0x94, "CEX1"}, {CPU_89C51R|CPU_251, 0x93, "CEX0"}, {CPU_89C51R|CPU_251, 0x92, "EXI"}, {CPU_89C51R|CPU_251, 0x91, "T2EX"}, {CPU_89C51R|CPU_251, 0x90, "T2"}, /* WDCON */ {CPU_DS390|CPU_DS390F, 0xdf, "SMOD_1"}, {CPU_DS390|CPU_DS390F, 0xde, "POR,"}, {CPU_DS390|CPU_DS390F, 0xdd, "EPF1"}, {CPU_DS390|CPU_DS390F, 0xdc, "PF1"}, {CPU_DS390|CPU_DS390F, 0xdb, "WDIF"}, {CPU_DS390|CPU_DS390F, 0xda, "WTRF"}, {CPU_DS390|CPU_DS390F, 0xd9, "EWT"}, {CPU_DS390|CPU_DS390F, 0xd8, "RWT"}, /* EIE */ {CPU_DS390|CPU_DS390F, 0xef, "CANBIE"}, {CPU_DS390|CPU_DS390F, 0xee, "C0IE"}, {CPU_DS390|CPU_DS390F, 0xed, "C1IE"}, {CPU_DS390|CPU_DS390F, 0xec, "EWDI"}, {CPU_DS390|CPU_DS390F, 0xeb, "EX5"}, {CPU_DS390|CPU_DS390F, 0xea, "EX4"}, {CPU_DS390|CPU_DS390F, 0xe9, "EX3"}, {CPU_DS390|CPU_DS390F, 0xe8, "EX2"}, /* EIP */ {CPU_DS390|CPU_DS390F, 0xef, "CANBIP"}, {CPU_DS390|CPU_DS390F, 0xee, "C0IP"}, {CPU_DS390|CPU_DS390F, 0xed, "C1IP"}, {CPU_DS390|CPU_DS390F, 0xec, "PWDI"}, {CPU_DS390|CPU_DS390F, 0xeb, "PX5"}, {CPU_DS390|CPU_DS390F, 0xea, "PX4"}, {CPU_DS390|CPU_DS390F, 0xe9, "PX3"}, {CPU_DS390|CPU_DS390F, 0xe8, "PX2"}, {0, 0, NULL} }; /* * Options of uc51 */ cl_irq_stop_option::cl_irq_stop_option(class cl_51core *the_uc51): cl_optref(the_uc51) { uc51= the_uc51; } int cl_irq_stop_option::init(void) { cl_optref::init(); create(uc51, bool_opt, "irq_stop", "Stop when IRQ accepted"); return(0); } void cl_irq_stop_option::option_changed(void) { if (!uc51) return; bool b; option->get_value(&b); uc51->stop_at_it= b; } instruction_wrapper_fn itab51[256]; /* * Making a new micro-controller and reset it */ cl_51core::cl_51core(struct cpu_entry *Itype, class cl_sim *asim): cl_uc(asim) { type= Itype; irq_stop_option= new cl_irq_stop_option(this); stop_at_it= false; } /* * Initializing. Virtual calls go here * This method must be called first after object creation. */ int cl_51core::init(void) { fill_def_wrappers(itab51); itab51[0x89]= itab51[0x88]; itab51[0x8a]= itab51[0x88]; itab51[0x8b]= itab51[0x88]; itab51[0x8c]= itab51[0x88]; itab51[0x8d]= itab51[0x88]; itab51[0x8e]= itab51[0x88]; itab51[0x8f]= itab51[0x88]; itab51[0xf9]= itab51[0xf8]; itab51[0xfa]= itab51[0xf8]; itab51[0xfb]= itab51[0xf8]; itab51[0xfc]= itab51[0xf8]; itab51[0xfd]= itab51[0xf8]; itab51[0xfe]= itab51[0xf8]; itab51[0xff]= itab51[0xf8]; itab51[0x21]= itab51[0x01]; itab51[0x41]= itab51[0x01]; itab51[0x61]= itab51[0x01]; itab51[0x81]= itab51[0x01]; itab51[0xa1]= itab51[0x01]; itab51[0xc1]= itab51[0x01]; itab51[0xe1]= itab51[0x01]; itab51[0x07]= itab51[0x06]; itab51[0x09]= itab51[0x08]; itab51[0x0a]= itab51[0x08]; itab51[0x0b]= itab51[0x08]; itab51[0x0c]= itab51[0x08]; itab51[0x0d]= itab51[0x08]; itab51[0x0e]= itab51[0x08]; itab51[0x0f]= itab51[0x08]; itab51[0x31]= itab51[0x11]; itab51[0x51]= itab51[0x11]; itab51[0x71]= itab51[0x11]; itab51[0x91]= itab51[0x11]; itab51[0xb1]= itab51[0x11]; itab51[0xd1]= itab51[0x11]; itab51[0xf1]= itab51[0x11]; itab51[0x17]= itab51[0x16]; itab51[0x19]= itab51[0x18]; itab51[0x1a]= itab51[0x18]; itab51[0x1b]= itab51[0x18]; itab51[0x1c]= itab51[0x18]; itab51[0x1d]= itab51[0x18]; itab51[0x1e]= itab51[0x18]; itab51[0x1f]= itab51[0x18]; itab51[0x29]= itab51[0x28]; itab51[0x2a]= itab51[0x28]; itab51[0x2b]= itab51[0x28]; itab51[0x2c]= itab51[0x28]; itab51[0x2d]= itab51[0x28]; itab51[0x2e]= itab51[0x28]; itab51[0x2f]= itab51[0x28]; itab51[0x27]= itab51[0x26]; itab51[0x37]= itab51[0x36]; itab51[0x39]= itab51[0x38]; itab51[0x3a]= itab51[0x38]; itab51[0x3b]= itab51[0x38]; itab51[0x3c]= itab51[0x38]; itab51[0x3d]= itab51[0x38]; itab51[0x3e]= itab51[0x38]; itab51[0x3f]= itab51[0x38]; itab51[0x47]= itab51[0x46]; itab51[0x49]= itab51[0x48]; itab51[0x4a]= itab51[0x48]; itab51[0x4b]= itab51[0x48]; itab51[0x4c]= itab51[0x48]; itab51[0x4d]= itab51[0x48]; itab51[0x4e]= itab51[0x48]; itab51[0x4f]= itab51[0x48]; itab51[0x97]= itab51[0x96]; itab51[0x99]= itab51[0x98]; itab51[0x9a]= itab51[0x98]; itab51[0x9b]= itab51[0x98]; itab51[0x9c]= itab51[0x98]; itab51[0x9d]= itab51[0x98]; itab51[0x9e]= itab51[0x98]; itab51[0x9f]= itab51[0x98]; itab51[0xb7]= itab51[0xb6]; itab51[0xb9]= itab51[0xb8]; itab51[0xba]= itab51[0xb8]; itab51[0xbb]= itab51[0xb8]; itab51[0xbc]= itab51[0xb8]; itab51[0xbd]= itab51[0xb8]; itab51[0xbe]= itab51[0xb8]; itab51[0xbf]= itab51[0xb8]; itab51[0xd9]= itab51[0xd8]; itab51[0xda]= itab51[0xd8]; itab51[0xdb]= itab51[0xd8]; itab51[0xdc]= itab51[0xd8]; itab51[0xdd]= itab51[0xd8]; itab51[0xde]= itab51[0xd8]; itab51[0xdf]= itab51[0xd8]; itab51[0x57]= itab51[0x56]; itab51[0x59]= itab51[0x58]; itab51[0x5a]= itab51[0x58]; itab51[0x5b]= itab51[0x58]; itab51[0x5c]= itab51[0x58]; itab51[0x5d]= itab51[0x58]; itab51[0x5e]= itab51[0x58]; itab51[0x5f]= itab51[0x58]; itab51[0x67]= itab51[0x66]; itab51[0x69]= itab51[0x68]; itab51[0x6a]= itab51[0x68]; itab51[0x6b]= itab51[0x68]; itab51[0x6c]= itab51[0x68]; itab51[0x6d]= itab51[0x68]; itab51[0x6e]= itab51[0x68]; itab51[0x6f]= itab51[0x68]; itab51[0x77]= itab51[0x76]; itab51[0x79]= itab51[0x78]; itab51[0x7a]= itab51[0x78]; itab51[0x7b]= itab51[0x78]; itab51[0x7c]= itab51[0x78]; itab51[0x7d]= itab51[0x78]; itab51[0x7e]= itab51[0x78]; itab51[0x7f]= itab51[0x78]; itab51[0x87]= itab51[0x86]; itab51[0xa7]= itab51[0xa6]; itab51[0xa9]= itab51[0xa8]; itab51[0xaa]= itab51[0xa8]; itab51[0xab]= itab51[0xa8]; itab51[0xac]= itab51[0xa8]; itab51[0xad]= itab51[0xa8]; itab51[0xae]= itab51[0xa8]; itab51[0xaf]= itab51[0xa8]; itab51[0xc7]= itab51[0xc6]; itab51[0xc9]= itab51[0xc8]; itab51[0xca]= itab51[0xc8]; itab51[0xcb]= itab51[0xc8]; itab51[0xcc]= itab51[0xc8]; itab51[0xcd]= itab51[0xc8]; itab51[0xce]= itab51[0xc8]; itab51[0xcf]= itab51[0xc8]; itab51[0xd7]= itab51[0xd6]; itab51[0xe3]= itab51[0xe2]; itab51[0xe7]= itab51[0xe6]; itab51[0xe9]= itab51[0xe8]; itab51[0xea]= itab51[0xe8]; itab51[0xeb]= itab51[0xe8]; itab51[0xec]= itab51[0xe8]; itab51[0xed]= itab51[0xe8]; itab51[0xee]= itab51[0xe8]; itab51[0xef]= itab51[0xe8]; itab51[0xf3]= itab51[0xf2]; itab51[0xf7]= itab51[0xf6]; irq_stop_option->init(); dptr= 0; cl_uc::init(); decode_dptr(); set_name("mcs51_controller"); reset(); make_vars(); return(0); } static char id_string_51[100]; char * cl_51core::id_string(void) { int i; for (i= 0; (cpus_51[i].type_str != NULL) && (cpus_51[i].type != type->type); i++) ; sprintf(id_string_51, "%s %s", cpus_51[i].type_str?cpus_51[i].type_str:"51", (type->subtype & CPU_HMOS)?"HMOS":"CMOS"); return(id_string_51); } void cl_51core::make_cpu_hw(void) { cpu= new cl_uc51_cpu(this); cpu->init(); } void cl_51core::mk_hw_elements(void) { cl_uc::mk_hw_elements(); class cl_hw *h; acc= sfr->get_cell(ACC); psw= sfr->get_cell(PSW); add_hw(h= new cl_timer0(this, 0, "timer0")); h->init(); add_hw(h= new cl_timer1(this, 1, "timer1")); h->init(); add_hw(h= new cl_serial(this)); h->init(); class cl_port_ui *d; add_hw(d= new cl_port_ui(this, 0, "dport")); d->init(); class cl_port *p0, *p1, *p2, *p3; add_hw(p0= new cl_port(this, 0)); p0->init(); add_hw(p1= new cl_port(this, 1)); p1->init(); add_hw(p2= new cl_port(this, 2)); p2->init(); add_hw(p3= new cl_port(this, 3)); p3->init(); class cl_port_data pd; pd.init(); pd.cell_dir= NULL; pd.set_name("P0"); pd.cell_p = p0->cell_p; pd.cell_in = p0->cell_in; pd.keyset = chars(keysets[0]); pd.basx = 1; pd.basy = 4; d->add_port(&pd, 0); pd.set_name("P1"); pd.cell_p = p1->cell_p; pd.cell_in = p1->cell_in; pd.keyset = chars(keysets[1]); pd.basx = 20; pd.basy = 4; d->add_port(&pd, 1); pd.set_name("P2"); pd.cell_p = p2->cell_p; pd.cell_in = p2->cell_in; pd.keyset = chars(keysets[2]); pd.basx = 40; pd.basy = 4; d->add_port(&pd, 2); pd.set_name("P3"); pd.cell_p = p3->cell_p; pd.cell_in = p3->cell_in; pd.keyset = chars(keysets[3]); pd.basx = 60; pd.basy = 4; d->add_port(&pd, 3); add_hw(interrupt= new cl_interrupt(this)); interrupt->init(); } void cl_51core::build_cmdset(class cl_cmdset *cmdset) { class cl_cmd *cmd; //class cl_super_cmd *super_cmd; //class cl_cmdset *cset; cl_uc::build_cmdset(cmdset); cmdset->add(cmd= new cl_di_cmd("di", true)); cmd->init(); cmdset->add(cmd= new cl_dx_cmd("dx", true)); cmd->init(); cmdset->add(cmd= new cl_ds_cmd("ds", true)); cmd->init(); } void cl_51core::make_memories(void) { make_address_spaces(); make_chips(); acc= sfr->get_cell(ACC); psw= sfr->get_cell(PSW); decode_regs(); decode_rom(); decode_iram(); decode_sfr(); decode_xram(); decode_bits(); } void cl_51core::make_address_spaces(void) { rom= new cl_address_space("rom", 0, 0x10000, 8); rom->init(); address_spaces->add(rom); iram= new cl_address_space("iram", 0, 0x80, 8); iram->init(); address_spaces->add(iram); sfr= new cl_address_space("sfr", 0x80, 0x80, 8); sfr->init(); address_spaces->add(sfr); xram= new cl_address_space("xram", 0, 0x10000, 8); xram->init(); address_spaces->add(xram); regs= new cl_address_space("regs", 0, 8, 8); regs->init(); address_spaces->add(regs); bits= new cl_address_space("bits", 0, 0x100, 1); bits->init(); address_spaces->add(bits); dptr= new cl_address_space("dptr", 0, 2, 8); dptr->init(); address_spaces->add(dptr); } void cl_51core::make_chips(void) { rom_chip= new cl_memory_chip("rom_chip", 0x10000, 8, 0/*, 0xff*/); rom_chip->init(); memchips->add(rom_chip); iram_chip= new cl_memory_chip("iram_chip", 0x100, 8); iram_chip->init(); memchips->add(iram_chip); xram_chip= new cl_memory_chip("xram_chip", 0x10000, 8); xram_chip->init(); memchips->add(xram_chip); sfr_chip= new cl_memory_chip("sfr_chip", 0x80, 8); sfr_chip->init(); memchips->add(sfr_chip); } void cl_51core::decode_rom(void) { class cl_address_decoder *ad; ad= new cl_address_decoder(rom, rom_chip, 0, 0xffff, 0); ad->init(); ad->set_name("def_rom_decoder"); rom->decoders->add(ad); ad->activate(0); } void cl_51core::decode_regs(void) { int i; cl_banker *b= new cl_banker(sfr, 0xd0, 0x18, //0, regs, 0, 7); b->init(); b->set_name("def_regs_banker"); regs->decoders->add(b); b->add_bank(0, memory("iram_chip"), 0); b->add_bank(1, memory("iram_chip"), 8); b->add_bank(2, memory("iram_chip"), 16); b->add_bank(3, memory("iram_chip"), 24); psw->write(0); for (i= 0; i < 8; i++) R[i]= regs->get_cell(i); } void cl_51core::decode_bits(void) { class cl_address_decoder *ad; ad= new cl_bander(bits, 0, 127, iram_chip, 32, 8, 1); ad->init(); ad->set_name("def_bits_bander_0-7f"); bits->decoders->add(ad); ad->activate(0); ad= new cl_bander(bits, 128, 255, sfr_chip, 0, 8, 8); ad->init(); ad->set_name("def_bits_bander_80-ff"); bits->decoders->add(ad); ad->activate(0); } void cl_51core::decode_iram(void) { class cl_address_decoder *ad; ad= new cl_address_decoder(iram, iram_chip, 0, 0x7f, 0); ad->init(); ad->set_name("def_iram_decoder"); iram->decoders->add(ad); ad->activate(0); } void cl_51core::decode_sfr(void) { class cl_address_decoder *ad; ad= new cl_address_decoder(sfr, sfr_chip, 0x80, 0xff, 0); ad->init(); ad->set_name("def_sfr_decoder"); sfr->decoders->add(ad); ad->activate(0); } void cl_51core::decode_xram(void) { class cl_address_decoder *ad; ad= new cl_address_decoder(xram, xram_chip, 0, 0xffff, 0); ad->init(); ad->set_name("def_xram_decoder"); xram->decoders->add(ad); ad->activate(0); } void cl_51core::decode_dptr(void) { class cl_address_decoder *ad; t_mem adps= 0, mdps, dpl1, dph1, mdpc, adpc; class cl_banker *banker; dptr->undecode_area(NULL, 0, 1, NULL); if (cpu) { adps= cpu->cfg_get(uc51cpu_aof_mdps); mdps= cpu->cfg_get(uc51cpu_mask_mdps); dpl1= cpu->cfg_get(uc51cpu_aof_mdps1l); dph1= cpu->cfg_get(uc51cpu_aof_mdps1h); adpc= cpu->cfg_get(uc51cpu_aof_mdpc); mdpc= cpu->cfg_get(uc51cpu_mask_mdpc); if ((adps > 0x7f) && (dpl1 > 0x7f) && (dph1 > 0x7f)) { // multi DPTR sfr style //printf("MDPS %x %x %x %x\n", adps, mdps, dpl1, dph1); banker= new cl_banker(sfr, adps, mdps, //0, dptr, 0, 0); banker->init(); dptr->decoders->add(banker); banker->add_bank(0, memory("sfr_chip"), DPL-0x80); banker->add_bank(1, memory("sfr_chip"), dpl1-0x80); banker->activate(0); banker= new cl_banker(sfr, adps, mdps, //0, dptr, 1, 1); banker->init(); dptr->decoders->add(banker); banker->add_bank(0, memory("sfr_chip"), DPH-0x80); banker->add_bank(1, memory("sfr_chip"), dph1-0x80); banker->activate(0); sfr->write(adps, sfr->get(adps)); } else if (adpc > 0x7f) { // multi DPTR chip style adps=0x80; class cl_memory_chip *dptr_chip= (cl_memory_chip*)memory("dptr_chip"); if (dptr_chip == 0) { dptr_chip= new cl_memory_chip("dptr_chip", 3*8, 8); dptr_chip->init(); memchips->add(dptr_chip); } if (dptr_chip && (mdpc != 0)) { int a, m= mdpc; //printf("MDPC %x %x\n", adpc, mdpc); while ((m&1) == 0) m>>= 1; banker= new cl_banker(sfr, adpc, mdpc, //0, dptr, 0, 1); banker->init(); dptr->decoders->add(banker); for (a= 0; a <= m; a++) banker->add_bank(a, dptr_chip, a*2); banker->activate(0); banker= new cl_banker(sfr, adpc, mdpc, //0, sfr, DPL, DPH); banker->init(); sfr->decoders->add(banker); for (a= 0; a <= m; a++) banker->add_bank(a, dptr_chip, a*2); banker->activate(0); sfr->write(adpc, sfr->get(adpc)); } } else adps= 0; } if (adps == 0) { //printf("DPTR\n"); ad= new cl_address_decoder(dptr, sfr_chip, 0, 1, DPL-0x80); ad->init(); dptr->decoders->add(ad); ad->activate(0); } cl_var *v; vars->add(v= new cl_var(chars("dpl"), dptr, 0, "")); v->init(); vars->add(v= new cl_var(chars("DPL"), dptr, 0, "")); v->init(); vars->add(v= new cl_var(chars("dph"), dptr, 1, "")); v->init(); vars->add(v= new cl_var(chars("DPH"), dptr, 1, "")); v->init(); } void cl_51core::make_vars(void) { cl_var *v; vars->add(v= new cl_var(cchars("R0"), regs, 0, "")); v->init(); vars->add(v= new cl_var(cchars("R1"), regs, 1, "")); v->init(); vars->add(v= new cl_var(cchars("R2"), regs, 2, "")); v->init(); vars->add(v= new cl_var(cchars("R3"), regs, 3, "")); v->init(); vars->add(v= new cl_var(cchars("R4"), regs, 4, "")); v->init(); vars->add(v= new cl_var(cchars("R5"), regs, 5, "")); v->init(); vars->add(v= new cl_var(cchars("R6"), regs, 6, "")); v->init(); vars->add(v= new cl_var(cchars("R7"), regs, 7, "")); v->init(); int i; for (i= 0; sfr_tab51[i].name != NULL; i++) { if (type->type & sfr_tab51[i].cpu_type) { vars->add(v= new cl_var(chars(sfr_tab51[i].name), sfr, sfr_tab51[i].addr, "")); v->init(); } } for (i= 0; bit_tab51[i].name != NULL; i++) { if (type->type & bit_tab51[i].cpu_type) { vars->add(v= new cl_var(chars(bit_tab51[i].name), bits, bit_tab51[i].addr, "")); v->init(); } } } /* * Destroying the micro-controller object */ cl_51core::~cl_51core(void) { delete irq_stop_option; } /* * Disassembling an instruction */ struct dis_entry * cl_51core::dis_tbl(void) { return(disass_51); } struct name_entry * cl_51core::bit_tbl(void) { return(bit_tab51); } char * cl_51core::disass(t_addr addr, const char *sep) { char work[256], temp[200]/*, c[2]*/; char *buf, *p, *t, *s; const char *b; t_mem code= rom->get(addr); p= work; b= dis_tbl()[code].mnemonic; while (*b) { if (*b == '%') { b++; switch (*(b++)) { case 'A': // absolute address sprintf(temp, "%04x", /*t_addr*/int((addr&0xf800)| (((code>>5)&0x07)*256 + rom->get(addr+1)))); break; case 'l': // long address sprintf(temp, "%04x", /*t_addr*/int(rom->get(addr+1)*256 + rom->get(addr+2))); break; case 'a': // addr8 (direct address) at 2nd byte daddr_name(rom->get(addr+1), temp); break; case '8': // addr8 (direct address) at 3rd byte daddr_name(rom->get(addr+2), temp); break; case 'b': // bitaddr at 2nd byte { t_addr ba= rom->get(addr+1); /*if (get_name(ba, bit_tbl(), temp)) break; if (ba<128) addr_name((ba/8)+32,iram,temp); else addr_name(ba&0xf8,sfr,temp); strcat(temp, "."); sprintf(c, "%1d", (int)(ba & 0x07)); strcat(temp, c);*/ baddr_name(ba, temp); break; } case 'r': // rel8 address at 2nd byte sprintf(temp, "%04x", /*t_addr*/int(addr+2+(signed char)(rom->get(addr+1)))); break; case 'R': // rel8 address at 3rd byte sprintf(temp, "%04x", /*t_addr*/int(addr+3+(signed char)(rom->get(addr+2)))); break; case 'd': // data8 at 2nd byte sprintf(temp, "%02x", (int)rom->get(addr+1)); break; case 'D': // data8 at 3rd byte sprintf(temp, "%02x", (int)rom->get(addr+2)); break; case '6': // data16 at 2nd(H)-3rd(L) byte sprintf(temp, "%04x", /*t_addr*/int(rom->get(addr+1)*256 + rom->get(addr+2))); break; default: strcpy(temp, "?"); break; } t= temp; while (*t) *(p++)= *(t++); } else *(p++)= *(b++); } *p= '\0'; p= strchr(work, ' '); if (!p) { buf= strdup(work); return(buf); } if (sep == NULL) buf= (char *)malloc(6+strlen(p)+1); else buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1); for (p= work, s= buf; *p != ' '; p++, s++) *s= *p; p++; *s= '\0'; if (sep == NULL) { while (strlen(buf) < 6) strcat(buf, " "); } else strcat(buf, sep); strcat(buf, p); return(buf); } void cl_51core::print_regs(class cl_console_base *con) { t_addr start; t_mem data; t_mem dp; // show regs start= psw->get() & 0x18; con->dd_printf(" R0 R1 R2 R3 R4 R5 R6 R7\n"); iram->dump(start, start+7, 8, con/*->get_fout()*/); con->dd_color("answer"); // show indirectly addressed IRAM and some basic regs data= iram->get(iram->get(start)); con->dd_printf("@R0 %02x %c", data, isprint(data) ? data : '.'); con->dd_printf(" ACC= 0x%02x %3d %c B= 0x%02x\n", sfr->get(ACC), sfr->get(ACC), isprint(sfr->get(ACC))?(sfr->get(ACC)):'.', sfr->get(B)); data= iram->get(iram->get(start+1)); con->dd_printf("@R1 %02x %c", data, isprint(data) ? data : '.'); data= psw->get(); con->dd_printf(" PSW= 0x%02x CY=%c AC=%c OV=%c P=%c\n", data, (data&bmCY)?'1':'0', (data&bmAC)?'1':'0', (data&bmOV)?'1':'0', (data&bmP)?'1':'0'); /* show stack pointer */ start = sfr->get (SP); con->dd_printf ("SP ", start); iram->dump (start, start - 7, 8, con/*->get_fout()*/); con->dd_color("answer"); // show DPTR(s) if (dptr) { int act; int mask; int i; if (cpu && (cpu->cfg_get(uc51cpu_aof_mdpc) > 0x7f)) { // multi DPTR chip style act= sfr->get(cpu->cfg_get(uc51cpu_aof_mdpc)); mask= cpu->cfg_get(uc51cpu_mask_mdpc); while ((mask&1) == 0) { act>>= 1; mask>>= 1; } act&= mask; class cl_memory *dptr_chip= memory("dptr_chip"); if (dptr_chip) { for (i= 0; i <= mask; i++) { int a= i*dptr->get_size(); dp= 0; int di; for (di= dptr->get_size()-1; di >= 0; di--) dp= (dp*256) + dptr_chip->get(a+di); con->dd_printf(" %cDPTR%d= ", (i==act)?'*':' ', i); con->dd_printf(xram->addr_format, dp); data= xram->read(dp); con->dd_printf(" @DPTR%d= ", i); con->dd_printf("0x%02x %3d %c\n", data, data, isprint(data)?data:'.'); } } } else if (cpu && (cpu->cfg_get(uc51cpu_aof_mdps) > 0x7f)) { // multi DPTR sfr style act= sfr->get(cpu->cfg_get(uc51cpu_aof_mdps)); mask= cpu->cfg_get(uc51cpu_mask_mdps); while ((mask&1) == 0) { act>>= 1; mask>>= 1; } act&= mask; i= 0; dp= (sfr_chip->get(DPL-0x80) + sfr_chip->get(DPH-0x80) * 256) & 0xffff; con->dd_printf(" %cDPTR%d= ", (i==act)?'*':' ', i); con->dd_printf(xram->addr_format, dp); data= xram->read(dp); con->dd_printf(" @DPTR%d= ", i); con->dd_printf("0x%02x %3d %c\n", data, data, isprint(data)?data:'.'); i= 1; dp= sfr_chip->get(cpu->cfg_get(uc51cpu_aof_mdps1l) - 0x80) + sfr_chip->get(cpu->cfg_get(uc51cpu_aof_mdps1h) - 0x80) * 256; con->dd_printf(" %cDPTR%d= ", (i==act)?'*':' ', i); con->dd_printf(xram->addr_format, dp); data= xram->read(dp); con->dd_printf(" @DPTR%d= ", i); con->dd_printf("0x%02x %3d %c\n", data, data, isprint(data)?data:'.'); } else { // non-multi DPTR int a= dptr->get_size(); dp= 0; int di; chars f=""; for (di= a-1; di >= 0; di--) { dp= (dp*256) + dptr->get(di); } f.format("0x%%0%dx",a*2); data= xram->get(dp); con->dd_printf(" DPTR= "); con->dd_printf(/*xram->addr_format*/(char*)f, dp); con->dd_printf(" @DPTR= 0x%02x %3d %c\n", data, data, isprint(data)?data:'.'); } } else { // no dptr address space, read SFR directly data= xram->get(sfr->read(DPH)*256+sfr->read(DPL)); con->dd_printf(" DPTR= 0x%02x%02x @DPTR= 0x%02x %3d %c\n", sfr->get(DPH), sfr->get(DPL), data, data, isprint(data)?data:'.'); } print_disass(PC, con); } /* * Converting bit address into real memory */ class cl_address_space * cl_51core::bit2mem(t_addr bitaddr, t_addr *memaddr, t_mem *bitmask) { class cl_address_space *m; t_addr ma; bitaddr&= 0xff; if (bitaddr < 128) { m= iram; ma= bitaddr/8 + 0x20; } else { m= sfr; ma= bitaddr & 0xf8; } if (memaddr) *memaddr= ma; if (bitmask) *bitmask= 1 << (bitaddr & 0x7); return(m); } t_addr cl_51core::bit_address(class cl_memory *mem, t_addr mem_address, int bit_number) { if (bit_number < 0 || bit_number > 7 || mem_address < 0) return(-1); class cl_memory *sfrchip= memory("sfr_chip"); if (mem == sfrchip) { mem= sfr; mem_address+= sfr->start_address; } if (mem == sfr) { if (mem_address < 128 || mem_address % 8 != 0 || mem_address > 255) return(-1); return(128 + (mem_address-128) + bit_number); } if (mem == iram) { if (mem_address < 0x20 || mem_address >= 0x20+32) return(-1); return((mem_address-0x20)*8 + bit_number); } return(-1); } /* Get name of directly addressed iram/sfr cell */ void cl_51core::daddr_name(t_addr addr, char *buf) { if (!buf) return; if (addr < 128) { // register? if (addr_name(addr, regs, buf)) return; // variale? if (addr_name(addr, iram, buf)) return; } else { // dptr? if (addr_name(addr-0x82, dptr, buf)) return; // sfr? if (addr_name(addr, sfr, buf)) return; } unsigned int a= addr; sprintf(buf, "%02x", a); } /* Get name of a bit cell */ void cl_51core::baddr_name(t_addr addr, char *buf) { t_addr ma; if (!buf) return; if (addr_name(addr, bits, buf)) return; if (addr < 128) ma= 32+(addr/8); else ma= addr&0xf8; daddr_name(ma, buf); chars c= chars("", "%s.%d", buf, (int)(addr & 7)); strcpy(buf, (char*)c); } /* * Resetting the micro-controller */ void cl_51core::reset(void) { cl_uc::reset(); clear_sfr(); result= resGO; //was_reti= false; } /* * Setting up SFR area to reset value */ void cl_51core::clear_sfr(void) { int i; for (i= 0x80; i <= 0xff; i++) sfr->set(i, 0); sfr->/*set*/write(P0, 0xff); sfr->/*set*/write(P1, 0xff); sfr->/*set*/write(P2, 0xff); sfr->/*set*/write(P3, 0xff); prev_p1= /*port_pins[1] &*/ sfr->/*get*/read(P1); prev_p3= /*port_pins[3] &*/ sfr->/*get*/read(P3); sfr->write(ACC, 0); sfr->write(B, 0); sfr->write(PSW, 0); sfr->write(SP, 7); sfr->write(DPL, 0); sfr->write(DPH, 0); sfr->write(IP, 0); sfr->write(IE, 0); sfr->write(TMOD, 0); sfr->write(TCON, 0); sfr->write(TH0, 0); sfr->write(TL0, 0); sfr->write(TH1, 0); sfr->write(TL1, 0); sfr->write(SCON, 0); sfr->write(PCON, 0); sfr->set_nuof_writes(0); sfr->set_nuof_reads(0); } /* * Analyzing code and settig up instruction map */ void cl_51core::analyze(t_addr addr) { uint code; struct dis_entry *tabl; code= rom->get(addr); tabl= &(dis_tbl()[code]); while (!inst_at(addr) && code != 0xa5 /* break point */) { set_inst_at(addr); switch (tabl->branch) { case 'a': // acall analyze((addr & 0xf800)| ((rom->get(addr+1)&0x07)*256+ rom->get(addr+2))); analyze(addr+tabl->length); break; case 'A': // ajmp addr= (addr & 0xf800)| ((rom->get(addr+1) & 0x07)*256 + rom->get(addr+2)); break; case 'l': // lcall analyze(rom->get(addr+1)*256 + rom->get(addr+2)); analyze(addr+tabl->length); break; case 'L': // ljmp addr= rom->get(addr+1)*256 + rom->get(addr+2); break; case 'r': // reljmp (2nd byte) analyze(rom->validate_address(addr+(signed char)(rom->get(addr+1)))); analyze(addr+tabl->length); break; case 'R': // reljmp (3rd byte) analyze(rom->validate_address(addr+(signed char)(rom->get(addr+2)))); analyze(addr+tabl->length); break; case 's': // sjmp { signed char target; target= rom->get(addr+1); addr+= 2; addr= rom->validate_address(addr+target); break; } case '_': return; default: addr= rom->validate_address(addr+tabl->length); break; } code= rom->get(addr); tabl= &(dis_tbl()[code]); } } /* * Inform hardware elements that `cycles' machine cycles have elapsed */ /*int cl_51core::tick_hw(int cycles) { cl_uc::tick_hw(cycles); //do_hardware(cycles); return(0); }*/ /*int cl_51core::tick(int cycles) { cl_uc::tick(cycles); //do_hardware(cycles); return(0); }*/ /* * Correcting direct address * * This function returns address of addressed element which can be an IRAM * or an SFR. */ class cl_memory_cell * cl_51core::get_direct(t_mem addr) { if (addr < sfr->start_address) return(iram->get_cell(addr)); else return(sfr->get_cell(addr)); } /* * Fetching one instruction and executing it */ int cl_51core::exec_inst(void) { t_mem code; int res= resGO; if ((res= exec_inst_tab(itab51)) != resNOT_DONE) return res; instPC= PC; if (fetch(&code)) return(resBREAKPOINT); tick(1); res= inst_unknown(); return(res); } /* * Simulating execution of next instruction * * This is an endless loop if requested number of steps is negative. * In this case execution is stopped if an instruction results other * status than GO. Execution can be stopped if `cmd_in' is not NULL * and there is input available on that file. It is usefull if the * command console is on a terminal. If input is available then a * complete line is read and dropped out because input is buffered * (inp_avail will be TRUE if ENTER is pressed) and it can confuse * command interepter. */ //static class cl_console *c= NULL; int cl_51core::do_inst(int step) { result= resGO; while ((result == resGO) && (state != stPD) && (step != 0)) { if (step > 0) step--; if (state == stGO) { interrupt->was_reti= false; pre_inst(); result= exec_inst(); post_inst(); } else { // tick hw in idle state inst_ticks= 1; post_inst(); tick(1); } if (result == resGO) { int res; if ((res= do_interrupt()) != resGO) result= res; else result= idle_pd(); } if (((result == resINTERRUPT) && stop_at_it) || result >= resSTOP) { sim->stop(result); break; } } if (state == stPD) { //FIXME: tick outsiders eg. watchdog } return(result); } /* * Abstract method to handle WDT */ /*int cl_51core::do_wdt(int cycles) { return(resGO); }*/ /* * Checking for interrupt requests and accept one if needed */ int cl_51core::do_interrupt(void) { int i, ie= 0; if (interrupt->was_reti) { interrupt->was_reti= false; return(resGO); } if (!((ie= sfr->get(IE)) & bmEA)) return(resGO); class it_level *il= (class it_level *)(it_levels->top()), *IL= 0; for (i= 0; i < it_sources->count; i++) { class cl_it_src *is= (class cl_it_src *)(it_sources->at(i)); if (is->is_active() && is->enabled() && is->pending()) { int pr= priority_of(is->ie_mask); if (il->level >= 0 && pr <= il->level) continue; if (state == stIDLE) { state= stGO; sfr->set_bit0(PCON, bmIDL); interrupt->was_reti= true; return(resGO); } is->clear(); sim->app->get_commander()-> debug("%g sec (%d clks): Accepting interrupt `%s' PC= 0x%06x\n", get_rtime(), ticks->ticks, object_name(is), PC); IL= new it_level(pr, is->addr, PC, is); return(accept_it(IL)); } } return(resGO); } int cl_51core::priority_of(uchar nuof_it) { if (sfr->get(IP) & /*ie_mask*/nuof_it) return(1); return(0); } /* * Accept an interrupt */ int cl_51core::accept_it(class it_level *il) { state= stGO; sfr->set_bit0(PCON, bmIDL); it_levels->push(il); tick(1); int res= inst_lcall(0, il->addr, true); if (res != resGO) return(res); else return(resINTERRUPT); } /* check if interrupts are enabled (globally) */ bool cl_51core::it_enabled(void) { return sfr->get(IE) & bmEA; } /* * Checking if Idle or PowerDown mode should be activated */ int cl_51core::idle_pd(void) { uint pcon= sfr->get(PCON); if (!(type->subtype & CPU_CMOS)) return(resGO); if (pcon & bmIDL) { if (state != stIDLE) sim->app->get_commander()-> debug("%g sec (%d clks): CPU in Idle mode (PC=0x%x, PCON=0x%x)\n", get_rtime(), ticks->ticks, PC, pcon); state= stIDLE; //was_reti= 1; } if (pcon & bmPD) { if (state != stPD) sim->app->get_commander()-> debug("%g sec (%d clks): CPU in PowerDown mode\n", get_rtime(), ticks->ticks); state= stPD; } return(resGO); } /* * Simulating an unknown instruction * * Normally this function is called for unimplemented instructions, because * every instruction must be known! */ int cl_51core::inst_unknown(void) { //PC--; class cl_error_unknown_code *e= new cl_error_unknown_code(this); error(e); return(resGO); } /* * 0x00 1 12 NOP */ int cl_51core::instruction_00/*inst_nop*/(t_mem/*uchar*/ code) { return(resGO); } /* * 0xe4 1 12 CLR A */ int cl_51core::instruction_e4/*inst_clr_a*/(t_mem/*uchar*/ code) { acc->write(0); return(resGO); } /* * 0xc4 1 1 SWAP A */ int cl_51core::instruction_c4/*inst_swap*/(t_mem/*uchar*/ code) { uchar temp; temp= (acc->read() >> 4) & 0x0f; sfr->write(ACC, (acc->get() << 4) | temp); return(resGO); } /* */ cl_uc51_cpu::cl_uc51_cpu(class cl_uc *auc): cl_hw(auc, HW_CPU/*DUMMY*/, 0, "cpu") { } int cl_uc51_cpu::init(void) { class cl_address_space *sfr= uc->address_space(MEM_SFR_ID), *bas= uc->address_space("bits"); int i; cl_hw::init(); if (!sfr) { fprintf(stderr, "No SFR to register %s[%d] into\n", id_string, id); } cell_psw= sfr->get_cell(PSW);//use_cell(sfr, PSW); cell_acc= register_cell(sfr, ACC); cell_sp= register_cell(sfr, SP); for (i= 0; i < 8; i++) acc_bits[i]= register_cell(bas, ACC+i); cl_var *v; uc->vars->add(v= new cl_var(cchars("cpu_aof_mdps"), cfg, uc51cpu_aof_mdps, cfg_help(uc51cpu_aof_mdps))); v->init(); uc->vars->add(v= new cl_var(cchars("cpu_mask_mdps"), cfg, uc51cpu_mask_mdps, cfg_help(uc51cpu_mask_mdps))); v->init(); uc->vars->add(v= new cl_var(cchars("cpu_aof_mdps1l"), cfg, uc51cpu_aof_mdps1l, cfg_help(uc51cpu_aof_mdps1l))); v->init(); uc->vars->add(v= new cl_var(cchars("cpu_aof_mdps1h"), cfg, uc51cpu_aof_mdps1h, cfg_help(uc51cpu_aof_mdps1h))); v->init(); uc->vars->add(v= new cl_var(cchars("cpu_aof_mdpc"), cfg, uc51cpu_aof_mdpc, cfg_help(uc51cpu_aof_mdpc))); v->init(); uc->vars->add(v= new cl_var(cchars("cpu_mask_mdpc"), cfg, uc51cpu_mask_mdpc, cfg_help(uc51cpu_mask_mdpc))); v->init(); return(0); } char * cl_uc51_cpu::cfg_help(t_addr addr) { switch (addr) { case uc51cpu_aof_mdps: return (char*)"Address of multi_DPTR_sfr selector, WR selects this style of multi_DPTR (int, RW)"; case uc51cpu_mask_mdps: return (char*)"Mask in multi_DPTR_srf selector (int, RW)"; case uc51cpu_aof_mdps1l: return (char*)"Address of multi_DPTR_sfr DPL1 (int, RW)"; case uc51cpu_aof_mdps1h: return (char*)"Address of multi_DPTR_sfr DPH1 (int, RW)"; case uc51cpu_aof_mdpc: return (char*)"Address of multi_DPTR_chip selector, WR selects this stlye of multi_DPTR (int, RW)"; case uc51cpu_mask_mdpc: return (char*)"Mask in multi_DPTR_chip selector (int, RW)"; } return (char*)"Not used"; } void cl_uc51_cpu::write(class cl_memory_cell *cell, t_mem *val) { if (conf(cell, val)) return; if (cell == cell_sp) { if (*val > uc->sp_max) uc->sp_max= *val; uc->sp_avg= (uc->sp_avg+(*val))/2; } else { bool p; int i; uchar uc, n= *val; if (cell != cell_acc) { cell->set(*val); n= cell_acc->get(); } p = false; uc= n; for (i= 0; i < 8; i++) { if (uc & 1) p= !p; uc>>= 1; } if (p) cell_psw->set_bit1(bmP); else cell_psw->set_bit0(bmP); } /*else if (cell == cell_pcon) { printf("PCON write 0x%x (PC=0x%x)\n", *val, uc->PC); uc->sim->stop(0); }*/ } t_mem cl_uc51_cpu::conf_op(cl_memory_cell *cell, t_addr addr, t_mem *val) { if (val) cell->set(*val); switch ((enum uc51cpu_cfg)addr) { case uc51cpu_aof_mdps: // addr of multi_DPTR_sfr selector if (val) ((cl_51core *)uc)->decode_dptr(); break; case uc51cpu_mask_mdps: // mask in mutli_DPTR_sfr selector break; case uc51cpu_aof_mdps1l: // addr of multi_DPTR_sfr DPL1 break; case uc51cpu_aof_mdps1h: // addr of multi_DPTR_sfr DPH1 break; case uc51cpu_aof_mdpc: // addr of multi_DPTR_chip selector if (val) ((cl_51core *)uc)->decode_dptr(); break; case uc51cpu_mask_mdpc: // mask in multi_DPTR_chip selector break; case uc51cpu_nuof: break; } return cell->get(); } /* End of s51.src/uc51.cc */