7ce5ecdf111390e03da2c27a0fed60f1ed8fdbcb
[fw/sdcc] / sim / ucsim / s51.src / uc51r.cc
1 /*
2  * Simulator of microcontrollers (uc51r.cc)
3  *
4  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5  * 
6  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7  *
8  */
9
10 /* This file is part of microcontroller simulator: ucsim.
11
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING.  If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
27
28 #include "ddconfig.h"
29
30 #include <stdio.h>
31
32 // local
33 #include "uc51rcl.h"
34 #include "regs51.h"
35
36
37 /*
38  * Making an 8051r CPU object
39  */
40
41 t_uc51r::t_uc51r(int Itype, int Itech, class cl_sim *asim):
42   t_uc52(Itype, Itech, asim)
43 {
44   int i;
45
46   for (i= 0; i < ERAM_SIZE; i++)
47     ERAM[i]= 0;
48   clock_out= 0;
49 }
50
51
52 /*
53  * Resetting of the microcontroller
54  *
55  * Original method is extended with handling of WDT.
56  */
57
58 void
59 t_uc51r::reset(void)
60 {
61   t_uc52::reset();
62   WDT= -1; // Disable WDT
63   wdtrst= 0;
64   //MEM(MEM_SFR)[SADDR]= MEM(MEM_SFR)[SADEN]= 0;
65   sfr->set(SADDR, 0);
66   sfr->set(SADEN, 0);
67 }
68
69
70 /*
71  * Copying ERAM to XRAM and vice versa
72  *
73  * This two methods are used by command interpreter to make ERAM and
74  * beginning of XRAM to be equivalent.
75  */
76
77 void
78 t_uc51r::eram2xram(void)
79 {
80   int i;
81
82   for (i= 0; i < ERAM_SIZE; i++)
83     set_mem(MEM_XRAM, i, ERAM[i]);
84 }
85
86 void
87 t_uc51r::xram2eram(void)
88 {
89   int i;
90
91   for (i= 0; i < ERAM_SIZE; i++)
92     ERAM[i]= get_mem(MEM_XRAM, i);
93 }
94
95
96 /*
97  * Processing write operation of SFR
98  *
99  * Inherited method is extended with WDT handling.
100  */
101
102 void
103 t_uc51r::proc_write(uchar *addr)
104 {
105   t_uc52::proc_write(addr);
106   // Handling WDT
107   if (addr == &(/*MEM(MEM_SFR)*/sfr->umem8[WDTRST]))
108     {
109       if ((wdtrst == 0x1e) &&
110           (*addr == 0xe1))
111         {
112           WDT= 0;
113           sim->cmd->debug("%g sec (%d tick): Watchdog timer enabled/reset"
114                           " PC= 0x%06x\n",
115                           get_rtime(), ticks->ticks, PC);
116         }
117       wdtrst= *addr;
118     }
119 }
120
121
122 /*
123  * Simulating timers
124  *
125  * Calling inherited method to simulate timer #0 and #1 and then 
126  * simulating timer #2.
127  */
128
129 int
130 t_uc51r::do_timers(int cycles)
131 {
132   int res;
133
134   if ((res= t_uc51::do_timers(cycles)) != resGO)
135     return(res);
136   return(do_timer2(cycles));
137 }
138
139
140 /*
141  * Simulating timer 2
142  *
143  * It is something wrong: T2MOD is not implemented in 52?!
144  */
145
146 int
147 t_uc51r::do_timer2(int cycles)
148 {
149   bool nocount= DD_FALSE;
150   uint t2mod= get_mem(MEM_SFR, T2MOD);
151   uint t2con= get_mem(MEM_SFR, T2CON);
152   uint p1= get_mem(MEM_SFR, P1);
153
154   exf2it->activate();
155   if (!(t2con & bmTR2))
156     /* Timer OFF */
157     return(resGO);
158
159   if (t2mod & bmT2OE)
160     return(do_t2_clockout(cycles));
161
162   if (t2con & (bmRCLK | bmTCLK))
163     return(do_t2_baud(cycles));
164
165   /* Determining nr of input clocks */
166   if (!(t2con & bmTR2))
167     nocount= DD_TRUE; // Timer OFF
168   else
169     if (t2con & bmC_T2)
170       {
171         // Counter mode, falling edge on P1.0 (T2)
172         if ((prev_p1 & bmT2) &&
173             !(p1 & port_pins[1] & bmT2))
174           cycles= 1;
175         else
176           nocount= DD_TRUE;
177       }
178   /* Counting */
179   while (cycles--)
180     {
181       if (t2con & bmCP_RL2)
182         do_t2_capture(&cycles, nocount);
183       else
184         {
185           int overflow;
186           overflow= 0;
187           /* Auto-Relode mode */
188           if (t2mod & bmDCEN)
189             {
190               /* DCEN= 1 */
191               exf2it->deactivate();
192               if (nocount)
193                 cycles= 0;
194               else
195                 {
196                   if (p1 & port_pins[1] & bmT2EX)
197                     {
198                       // UP
199                       if (!/*++(MEM(MEM_SFR)[TL2])*/sfr->add(TL2, 1))
200                         if (!/*++(MEM(MEM_SFR)[TH2])*/sfr->add(TH2, 1))
201                           {
202                             overflow++;
203                             //MEM(MEM_SFR)[TH2]= MEM(MEM_SFR)[RCAP2H];
204                             sfr->set(TH2, sfr->get(RCAP2H));
205                             //MEM(MEM_SFR)[TL2]= MEM(MEM_SFR)[RCAP2L];
206                             sfr->set(TL2, sfr->get(RCAP2L));
207                             mem(MEM_SFR)->set_bit1(T2CON, bmTF2);
208                           }
209                     }
210                   else
211                     {
212                       // DOWN
213                       //MEM(MEM_SFR)[TL2]--;
214                       if (/*MEM(MEM_SFR)[TL2]*/sfr->add(TL2, -1) == 0xff)
215                         /*MEM(MEM_SFR)[TH2]--*/sfr->add(TH2, -1);
216                       /*if (MEM(MEM_SFR)[TH2] == MEM(MEM_SFR)[RCAP2H] &&
217                         MEM(MEM_SFR)[TL2] == MEM(MEM_SFR)[RCAP2L])*/
218                       if (sfr->get(TH2) == sfr->get(RCAP2H) &&
219                           sfr->get(TL2) == sfr->get(RCAP2L))
220                         {
221                           overflow++;
222                           //MEM(MEM_SFR)[TH2]= MEM(MEM_SFR)[TL2]= 0xff;
223                           sfr->set(TH2, 0xff);
224                           sfr->set(TL2, 0xff);
225                           mem(MEM_SFR)->set_bit1(T2CON, bmTF2);
226                         }
227                     }
228                   while (overflow--)
229                     //MEM(MEM_SFR)[P1]^= bmEXF2;
230                     sfr->set(P1, sfr->get(P1) ^ bmEXF2);
231                 }
232             }
233           else
234             /* DCEN= 0 */
235             do_t2_reload(&cycles, nocount);
236         }
237     }// while cycles
238
239   return(resGO);
240 }
241
242
243 /*
244  * Clock out mode of Timer #2
245  */
246
247 int
248 t_uc51r::do_t2_clockout(int cycles)
249 {
250   uint t2con= get_mem(MEM_SFR, T2CON);
251   uint p1= get_mem(MEM_SFR, P1);
252
253   /* Programmable Clock Out Mode */
254   if ((prev_p1 & bmT2EX) &&
255       !(p1 & port_pins[1] & bmT2EX) &&
256       (t2con & bmEXEN2))
257     mem(MEM_SFR)->set_bit1(T2CON, bmEXF2);
258   if (t2con & bmCP_RL2)
259     return(resGO);
260   if (t2con & bmC_T2)
261     {
262       if ((prev_p1 & bmT2) &&
263           !(p1 & port_pins[1] & bmT2))
264         cycles= 1;
265       else
266         cycles= 0;
267     }
268   else
269     cycles*= 6;
270   if (t2con & bmTR2)
271     while (cycles--)
272       {
273         if (!/*++(MEM(MEM_SFR)[TL2])*/sfr->add(TL2, 1))
274           if (!/*++(MEM(MEM_SFR)[TH2])*/sfr->add(TH2, 1))
275             {
276               //MEM(MEM_SFR)[TH2]= MEM(MEM_SFR)[RCAP2H];
277               sfr->set(TH2, sfr->get(RCAP2H));
278               //MEM(MEM_SFR)[TL2]= MEM(MEM_SFR)[RCAP2L];
279               sfr->set(TL2, sfr->get(RCAP2L));
280               clock_out++;
281               if (!(t2con & bmC_T2))
282                 {
283                   SET_BIT((clock_out&1), P1, bmT2);
284                 }
285             }
286       }
287   return(resGO);
288 }
289
290
291 /*
292  * Handling serial line
293  */
294
295 int
296 t_uc51r::serial_bit_cnt(int mode)
297 {
298   int divby= 12;
299   int *tr_src= 0, *rec_src= 0;
300
301   switch (mode)
302     {
303     case 0:
304       divby  = 12;
305       tr_src = &s_tr_tick;
306       rec_src= &s_rec_tick;
307       break;
308     case 1:
309     case 3:
310       divby  = (get_mem(MEM_SFR, PCON)&bmSMOD)?16:32;
311       tr_src = (get_mem(MEM_SFR, T2CON)&bmTCLK)?(&s_tr_t2):(&s_tr_t1);
312       rec_src= (get_mem(MEM_SFR, T2CON)&bmTCLK)?(&s_rec_t2):(&s_rec_t1);
313       break;
314     case 2:
315       divby  = (get_mem(MEM_SFR, PCON)&bmSMOD)?16:32;
316       tr_src = &s_tr_tick;
317       rec_src= &s_rec_tick;
318       break;
319     }
320   if (s_sending)
321     {
322       while (*tr_src >= divby)
323         {
324           (*tr_src)-= divby;
325           s_tr_bit++;
326         }
327     }
328   if (s_receiving)
329     {
330       while (*rec_src >= divby)
331         {
332           (*rec_src)-= divby;
333           s_rec_bit++;
334         }
335     }
336   return(0);
337 }
338
339 void
340 t_uc51r::received(int c)
341 {
342   uint br= get_mem(MEM_SFR, SADDR) | get_mem(MEM_SFR, SADEN);
343   int scon= get_mem(MEM_SFR, SCON);
344
345   if ((0 < scon >> 6) &&
346       (scon & bmSM2))
347     {
348       if (
349           /* Check for individual address */
350           ((get_mem(MEM_SFR, SADDR) & get_mem(MEM_SFR, SADEN)) ==
351           (c & get_mem(MEM_SFR, SADEN)))
352           ||
353           /* Check for broadcast address */
354           (br == (br & c))
355           )
356         mem(MEM_SFR)->set_bit1(SCON, bmRI);
357       return;
358     }
359   mem(MEM_SFR)->set_bit1(SCON, bmRI);
360 }
361
362
363 /*
364  * Handling WDT
365  */
366
367 int
368 t_uc51r::do_wdt(int cycles)
369 {
370   if (WDT >= 0)
371     {
372       WDT+= cycles;
373 fprintf(stderr,"WDT=%d\n",WDT);
374       if (WDT & ~(0x3fff))
375         {
376           sim->cmd->debug("%g sec (%d ticks): "
377                           "Watchdog timer resets the CPU, PC= 0x%06x\n",
378                           get_rtime(), ticks->ticks, PC);
379           reset();
380           return(resWDTRESET);
381         }
382     }
383   return(resGO);
384 }
385
386
387 /*
388  * 0xe0 1 24 MOVX A,@DPTR
389  *____________________________________________________________________________
390  *
391  */
392
393 int
394 t_uc51r::inst_movx_a_$dptr(uchar code)
395 {
396   if ((get_mem(MEM_SFR, AUXR) & bmEXTRAM) ||
397       /*MEM(MEM_SFR)[DPH]*/sfr->get(DPH))
398     /*MEM(MEM_SFR)[event_at.ws= ACC]= read_mem(MEM_XRAM,
399                                              event_at.rx=
400                                              MEM(MEM_SFR)[DPH]*256+
401                                              MEM(MEM_SFR)[DPL]);*/
402     sfr->set(event_at.ws= ACC, read_mem(MEM_XRAM,
403                                         event_at.rx=
404                                         /*MEM(MEM_SFR)[DPH]*/sfr->get(DPH)*256+
405                                         /*MEM(MEM_SFR)[DPL]*/sfr->get(DPL)));
406   else
407     //MEM(MEM_SFR)[event_at.ws= ACC]= ERAM[event_at.rx= MEM(MEM_SFR)[DPL]];
408     sfr->set(event_at.ws= ACC, ERAM[event_at.rx=
409                                    /*MEM(MEM_SFR)[DPL]*/sfr->get(DPL)]);
410   tick(1);
411   return(resGO);
412 }
413
414
415 /*
416  * 0xe2-0xe3 1 24 MOVX A,@Ri
417  *____________________________________________________________________________
418  *
419  */
420
421 int
422 t_uc51r::inst_movx_a_$ri(uchar code)
423 {
424   uchar *addr;
425   int res;
426
427   addr= get_indirect(*(get_reg(code & 0x01)), &res);
428   if (get_mem(MEM_SFR, AUXR) & bmEXTRAM)
429     /*MEM(MEM_SFR)[event_at.ws= ACC]=
430       read_mem(MEM_XRAM,
431       event_at.rx= (MEM(MEM_SFR)[P2]&port_pins[2])*256+*addr);*/
432     sfr->set(event_at.ws= ACC,
433              read_mem(MEM_XRAM,
434                       event_at.rx=
435                       (/*MEM(MEM_SFR)[P2]*/sfr->get(P2)&port_pins[2])*256+*addr));
436   else
437     //MEM(MEM_SFR)[event_at.ws= ACC]= ERAM[event_at.rx= *addr];
438     sfr->set(event_at.ws= ACC, ERAM[event_at.rx= *addr]);
439   tick(1);
440   return(res);
441 }
442
443
444 /*
445  * 0xf0 1 24 MOVX @DPTR,A
446  *____________________________________________________________________________
447  *
448  */
449
450 int
451 t_uc51r::inst_movx_$dptr_a(uchar code)
452 {
453   if ((get_mem(MEM_SFR, AUXR) & bmEXTRAM) ||
454       /*MEM(MEM_SFR)[DPH]*/sfr->get(DPH))
455     write_mem(MEM_XRAM,
456               event_at.wx= /*MEM(MEM_SFR)[DPH]*/sfr->get(DPH)*256 +
457                            /*MEM(MEM_SFR)[DPL]*/sfr->get(DPL),
458               /*MEM(MEM_SFR)[event_at.rs= ACC]*/sfr->get(event_at.rs= ACC));
459   else
460     ERAM[event_at.wx= /*MEM(MEM_SFR)[DPL]*/sfr->get(DPL)]=
461       /*MEM(MEM_SFR)[*/sfr->get(event_at.rs= ACC)/*]*/;
462   return(resGO);
463 }
464
465
466 /*
467  * 0xf2-0xf3 1 24 MOVX @Ri,A
468  *____________________________________________________________________________
469  *
470  */
471
472 int
473 t_uc51r::inst_movx_$ri_a(uchar code)
474 {
475   uchar *addr;
476   int res;
477
478   addr= get_indirect(event_at.wi= *(get_reg(code & 0x01)), &res);
479   if (get_mem(MEM_SFR, AUXR) & bmEXTRAM)
480     write_mem(MEM_XRAM,
481               event_at.wx=
482               (/*MEM(MEM_SFR)[P2]*/sfr->get(P2) & port_pins[2])*256 + *addr,
483               /*MEM(MEM_SFR)[ACC]*/sfr->get(ACC));
484   else
485     ERAM[event_at.wx= *addr]= /*MEM(MEM_SFR)[ACC]*/sfr->get(ACC);
486   tick(1);
487   return(res);
488 }
489
490
491 /* End of s51.src/uc51r.cc */