1 /* 2 Copyright (C) 1998-2003 Scott Dattalo 3 2003 Mike Durian 4 This file is part of the libgpsim library of gpsim 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library; if not, see 18 <http://www.gnu.org/licenses/lgpl-2.1.html>. 19 */ 20 21 22 #ifndef SRC_INTCON_H_ 23 #define SRC_INTCON_H_ 24 25 #include <vector> 26 27 #include "gpsim_classes.h" 28 #include "registers.h" 29 #include "pic-ioports.h" 30 31 class IOCxF; 32 class PicPortGRegister; 33 class Processor; 34 class PIR_SET; 35 class RCON; 36 37 //--------------------------------------------------------- 38 // INTCON - Interrupt control register 39 40 class INTCON : public sfr_register 41 { 42 public: 43 unsigned int interrupt_trace = 0; 44 bool in_interrupt = false; 45 46 enum 47 { 48 RBIF = 1 << 0, 49 INTF = 1 << 1, 50 T0IF = 1 << 2, 51 RBIE = 1 << 3, 52 INTE = 1 << 4, 53 T0IE = 1 << 5, 54 XXIE = 1 << 6, // Processor dependent 55 PEIE = 1 << 6, 56 GIE = 1 << 7 57 }; 58 59 INTCON(Processor *pCpu, const char *pName, const char *pDesc); set_gie()60 virtual void set_gie() { put(value.get() | GIE); } 61 clear_gie()62 virtual void clear_gie() { put(value.get() & ~GIE); } 63 64 void set_T0IF(); 65 66 /* 67 // Bit 6 of intcon depends on the processor that's being simulated, 68 // This generic function will get called whenever interrupt flag upon 69 // which bit 6 enables becomes true. (e.g. for the c84, this 70 // routine is called when EEIF goes high.) 71 */ 72 virtual void peripheral_interrupt(bool hi_pri = false); 73 74 virtual void set_rbif(bool b); 75 set_intf(bool b)76 inline void set_intf(bool b) 77 { 78 bool current = (value.get() & INTF) == INTF; 79 80 if (b && !current) 81 { 82 put(value.get() | INTF); 83 } 84 85 if (!b && current) 86 { 87 put(value.get() & ~INTF); 88 } 89 } 90 set_t0if()91 inline void set_t0if() { put(value.get() | T0IF); } 92 set_rbie()93 inline void set_rbie() { put(value.get() | RBIE); } 94 set_inte()95 inline void set_inte() { put(value.get() | INTE); } 96 set_t0ie()97 inline void set_t0ie() { put(value.get() | T0IE); } 98 set_portGReg(PicPortGRegister * _portGReg)99 void set_portGReg(PicPortGRegister *_portGReg) { portGReg = _portGReg; } 100 virtual int check_peripheral_interrupt() = 0; 101 virtual void put(unsigned int new_value); 102 virtual void put_value(unsigned int new_value); aocxf_val(IOCxF *,unsigned int)103 virtual void aocxf_val(IOCxF *, unsigned int /* val */ ) {} 104 105 PicPortGRegister *portGReg = nullptr; 106 }; 107 108 109 //--------------------------------------------------------- 110 class INTCON2 : public sfr_register 111 { 112 public: 113 INTCON2(Processor *pCpu, const char *pName, const char *pDesc); 114 115 virtual void put_value(unsigned int new_value); 116 virtual void put(unsigned int new_value); 117 118 virtual bool assignBitSink(unsigned int bitPosition, BitSink *); 119 virtual bool releaseBitSink(unsigned int bitPosition, BitSink *); 120 121 enum 122 { 123 RBIP = 1 << 0, 124 INT3IP = 1 << 1, 125 TMR0IP = 1 << 2, 126 INTEDG3 = 1 << 3, 127 INTEDG2 = 1 << 4, 128 INTEDG1 = 1 << 5, 129 INTEDG0 = 1 << 6, 130 RBPU = 1 << 7 131 }; 132 133 private: 134 BitSink *m_bsRBPU = nullptr; 135 }; 136 137 138 class INTCON3 : public sfr_register 139 { 140 public: 141 INTCON3(Processor *pCpu, const char *pName, const char *pDesc); 142 143 virtual void put_value(unsigned int new_value); 144 virtual void put(unsigned int new_value); 145 set_int1f(bool b)146 inline void set_int1f(bool b) 147 { 148 bool current = (value.get() & INT1IF) == INT1IF; 149 150 if (b && !current) 151 { 152 put(value.get() | INT1IF); 153 } 154 155 if (!b && current) 156 { 157 put(value.get() & ~INT1IF); 158 } 159 } set_int2f(bool b)160 inline void set_int2f(bool b) 161 { 162 bool current = (value.get() & INT2IF) == INT2IF; 163 164 if (b && !current) 165 { 166 put(value.get() | INT2IF); 167 } 168 169 if (!b && current) 170 { 171 put(value.get() & ~INT2IF); 172 } 173 } set_int3f(bool b)174 inline void set_int3f(bool b) 175 { 176 bool current = (value.get() & INT3IF) == INT3IF; 177 178 if (b && !current) 179 { 180 put(value.get() | INT3IF); 181 } 182 183 if (!b && current) 184 { 185 put(value.get() & ~INT3IF); 186 } 187 } set_int1e()188 inline void set_int1e() { put(value.get() | INT1IE); } set_int2e()189 inline void set_int2e() { put(value.get() | INT2IE); } set_int3e()190 inline void set_int3e() { put(value.get() | INT3IE); } 191 enum 192 { 193 INT1IF = 1 << 0, 194 INT2IF = 1 << 1, 195 INT3IF = 1 << 2, 196 INT1IE = 1 << 3, 197 INT2IE = 1 << 4, 198 INT3IE = 1 << 5, 199 INT1IP = 1 << 6, 200 INT2IP = 1 << 7 201 }; 202 }; 203 204 205 // A 14-bit intcon with pir registers 206 class INTCON_14_PIR : public INTCON 207 { 208 public: 209 INTCON_14_PIR(Processor *pCpu, const char *pName, const char *pDesc); 210 211 virtual void put(unsigned int new_value); 212 virtual void put_value(unsigned int new_value); set_pir_set(PIR_SET * p)213 inline void set_pir_set(PIR_SET *p) { pir_set = p; } 214 215 virtual int check_peripheral_interrupt(); 216 virtual void set_rbif(bool b); set_gie()217 virtual void set_gie() { put_value(value.get() | GIE); } clear_gie()218 virtual void clear_gie() { put_value(value.get() & ~GIE); } 219 virtual void aocxf_val(IOCxF *, unsigned int val); 220 virtual void reset(RESET_TYPE r); 221 222 enum 223 { 224 IOCIF = 1 << 0, 225 INTF = 1 << 1, 226 T0IF = 1 << 2, 227 IOCIE = 1 << 3, 228 INTE = 1 << 4, 229 T0IE = 1 << 5, 230 PEIE = 1 << 6, 231 GIE = 1 << 7 232 }; 233 234 //private: 235 PIR_SET *pir_set = nullptr; 236 unsigned int write_mask; // Bits that instructions can modify 237 struct aocxf 238 { 239 struct IOCxF *ptr_iocxf; 240 unsigned int val; 241 }; 242 std::vector<aocxf> aocxf_list; 243 }; 244 245 246 247 //--------------------------------------------------------- 248 // INTCON_16 - Interrupt control register for the 16-bit core 249 250 class INTCON_16 : public INTCON 251 { 252 public: 253 INTCON_16(Processor *pCpu, const char *pName, const char *pDesc); 254 255 enum 256 { 257 GIEH = GIE, 258 GIEL = XXIE, 259 TMR0IE = T0IE, 260 INT0IE = INTE, 261 TMR0IF = T0IF, 262 INT0IF = INTF 263 }; 264 #define INTERRUPT_VECTOR_LO (0x18 >> 1) 265 #define INTERRUPT_VECTOR_HI (0x08 >> 1) 266 set_rcon(RCON * r)267 inline void set_rcon(RCON *r) { rcon = r; } set_intcon2(INTCON2 * ic)268 inline void set_intcon2(INTCON2 *ic) { intcon2 = ic; } set_pir_set(PIR_SET * p)269 inline void set_pir_set(PIR_SET *p) { pir_set = p; } 270 271 virtual void put(unsigned int new_value); 272 virtual void put_value(unsigned int new_value); 273 274 virtual void peripheral_interrupt(bool hi_pri = false); 275 virtual void general_interrupt(bool hi_pri = false); 276 277 void clear_gies(); 278 void set_gies(); 279 virtual int check_peripheral_interrupt(); get_interrupt_vector()280 unsigned int get_interrupt_vector() 281 { 282 return interrupt_vector; 283 } isHighPriorityInterrupt()284 bool isHighPriorityInterrupt() 285 { 286 return (interrupt_vector == INTERRUPT_VECTOR_HI); 287 } set_interrupt_vector(unsigned int new_int_vect)288 void set_interrupt_vector(unsigned int new_int_vect) 289 { 290 interrupt_vector = new_int_vect; 291 } 292 293 private: 294 unsigned int interrupt_vector = 0; // Starting address of the interrupt 295 RCON *rcon = nullptr; 296 INTCON2 *intcon2 = nullptr; 297 PIR_SET *pir_set = nullptr; 298 }; 299 300 301 #endif /* INTCON_H */ 302