version 0.2.39: fix of arith insts and start of re-structure
[fw/sdcc] / sim / ucsim / s51.src / uc89c51r.cc
1 /*
2  * Simulator of microcontrollers (uc89c51r.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 "uc89c51rcl.h"
34 #include "regs51.h"
35
36
37 t_uc89c51r::t_uc89c51r(int Itype, int Itech, class cl_sim *asim):
38   t_uc51r(Itype, Itech, asim)
39 {
40   it_sources->add_at(4, new cl_it_src(bmEC, CCON, bmCCF4, 0x0033, false,
41                                       "PCA module #4"));
42   it_sources->add_at(4, new cl_it_src(bmEC, CCON, bmCCF3, 0x0033, false,
43                                       "PCA module #3"));
44   it_sources->add_at(4, new cl_it_src(bmEC, CCON, bmCCF2, 0x0033, false,
45                                       "PCA module #2"));
46   it_sources->add_at(4, new cl_it_src(bmEC, CCON, bmCCF1, 0x0033, false,
47                                       "PCA module #1"));
48   it_sources->add_at(4, new cl_it_src(bmEC, CCON, bmCCF0, 0x0033, false,
49                                       "PCA module #0"));
50   it_sources->add_at(4, new cl_it_src(bmEC, CCON, bmCF, 0x0033, false,
51                                       "PCA counter"));
52 }
53
54
55 void
56 t_uc89c51r::reset(void)
57 {
58   t_uc51r::reset();
59   mem(MEM_SFR)->set_bit1(CCAPM0, bmECOM);
60   mem(MEM_SFR)->set_bit1(CCAPM1, bmECOM);
61   mem(MEM_SFR)->set_bit1(CCAPM2, bmECOM);
62   mem(MEM_SFR)->set_bit1(CCAPM3, bmECOM);
63   mem(MEM_SFR)->set_bit1(CCAPM4, bmECOM);
64   t0_overflows= 0;
65   dpl0= dph0= dpl1= dph1= 0;
66   set_mem(MEM_SFR, IPH, 0);
67 }
68
69 void
70 t_uc89c51r::proc_write(uchar *addr)
71 {
72   t_uc51r::proc_write(addr);
73
74   if (addr == &(/*MEM(MEM_SFR)*/sfr->umem8[CCAP0L]))
75     mem(MEM_SFR)->set_bit0(CCAPM0, bmECOM);
76   if (addr == &(/*MEM(MEM_SFR)*/sfr->umem8[CCAP0H]))
77     mem(MEM_SFR)->set_bit1(CCAPM0, bmECOM);
78
79   if (addr == &(/*MEM(MEM_SFR)*/sfr->umem8[CCAP1L]))
80     mem(MEM_SFR)->set_bit0(CCAPM1, bmECOM);
81   if (addr == &(/*MEM(MEM_SFR)*/sfr->umem8[CCAP1H]))
82     mem(MEM_SFR)->set_bit1(CCAPM1, bmECOM);
83
84   if (addr == &(/*MEM(MEM_SFR)*/sfr->umem8[CCAP2L]))
85     mem(MEM_SFR)->set_bit0(CCAPM2, bmECOM);
86   if (addr == &(/*MEM(MEM_SFR)*/sfr->umem8[CCAP2H]))
87     mem(MEM_SFR)->set_bit1(CCAPM2, bmECOM);
88
89   if (addr == &(/*MEM(MEM_SFR)*/sfr->umem8[CCAP3L]))
90     mem(MEM_SFR)->set_bit0(CCAPM3, bmECOM);
91   if (addr == &(/*MEM(MEM_SFR)*/sfr->umem8[CCAP3H]))
92     mem(MEM_SFR)->set_bit1(CCAPM3, bmECOM);
93
94   if (addr == &(/*MEM(MEM_SFR)*/sfr->umem8[CCAP4L]))
95     mem(MEM_SFR)->set_bit0(CCAPM4, bmECOM);
96   if (addr == &(/*MEM(MEM_SFR)*/sfr->umem8[CCAP4H]))
97     mem(MEM_SFR)->set_bit1(CCAPM4, bmECOM);
98
99   if (addr == &(/*MEM(MEM_SFR)*/sfr->umem8[AUXR]))
100     mem(MEM_SFR)->set_bit0(AUXR, 0x04);
101 }
102
103 uchar
104 t_uc89c51r::read(uchar *addr)
105 {
106   return(t_uc51r::read(addr));
107 }
108
109 int
110 t_uc89c51r::it_priority(uchar ie_mask)
111 {
112   uchar l, h;
113
114   l= get_mem(MEM_SFR, IP) & ie_mask;
115   h= get_mem(MEM_SFR, IPH) & ie_mask;
116   if (!h && !l)
117     return(0);
118   if (!h && l)
119     return(1);
120   if (h && !l)
121     return(2);
122   if (h && l)
123     return(3);
124   return(0);
125 }
126
127 void
128 t_uc89c51r::pre_inst(void)
129 {
130   if (get_mem(MEM_SFR, AUXR1) & bmDPS)
131     {
132       set_mem(MEM_SFR, DPL, dpl1);
133       set_mem(MEM_SFR, DPH, dph1);
134     }
135   else
136     {
137       set_mem(MEM_SFR, DPL, dpl0);
138       set_mem(MEM_SFR, DPH, dph0);
139     }
140 }
141
142 void
143 t_uc89c51r::post_inst(void)
144 {
145   if (get_mem(MEM_SFR, AUXR1) & bmDPS)
146     {
147       dpl1= get_mem(MEM_SFR, DPL);
148       dph1= get_mem(MEM_SFR, DPH);
149     }
150   else
151     {
152       dpl0= get_mem(MEM_SFR, DPL);
153       dph0= get_mem(MEM_SFR, DPH);
154     }
155 }
156
157
158 /*
159  * Simulating timers
160  *
161  * Calling inherited method to simulate timer #0, #1, #2 and then 
162  * simulating Programmable Counter Array
163  */
164
165 int
166 t_uc89c51r::do_timers(int cycles)
167 {
168   int res;
169
170   if ((res= t_uc51r::do_timers(cycles)) != resGO)
171     return(res);
172   return(do_pca(cycles));
173 }
174
175 int
176 t_uc89c51r::t0_overflow(void)
177 {
178   uchar cmod= get_mem(MEM_SFR, CMOD) & (bmCPS0|bmCPS1);
179
180   if (cmod == bmCPS1)
181     t0_overflows++;
182   return(0);
183 }
184
185
186 /*
187  * Simulating Programmable Counter Array
188  */
189
190 int
191 t_uc89c51r::do_pca(int cycles)
192 {
193   int ret= resGO;
194   uint ccon= get_mem(MEM_SFR, CCON);
195
196   if (!(ccon & bmCR))
197     return(resGO);
198   if (state == stIDLE &&
199       (ccon & bmCIDL))
200     return(resGO);
201
202   switch (get_mem(MEM_SFR, CMOD) & (bmCPS1|bmCPS0))
203     {
204     case 0:
205       ret= do_pca_counter(cycles);
206       break;
207     case bmCPS0:
208       ret= do_pca_counter(cycles*3);
209       break;
210     case bmCPS1:
211       ret= do_pca_counter(t0_overflows);
212       t0_overflows= 0;
213       break;
214     case (bmCPS0|bmCPS1):
215       if ((prev_p1 & bmECI) != 0 &
216           (get_mem(MEM_SFR, P1) & bmECI) == 0)
217         do_pca_counter(1);
218       break;
219     }
220   return(ret);
221 }
222
223 int
224 t_uc89c51r::do_pca_counter(int cycles)
225 {
226   while (cycles--)
227     {
228       if (/*++(MEM(MEM_SFR)[CL])*/sfr->add(CL, 1) == 0)
229         {
230           if (/*++(MEM(MEM_SFR)[CH])*/sfr->add(CH, 1) == 0)
231             {
232               /* CH,CL overflow */
233               mem(MEM_SFR)->set_bit1(CCON, bmCF);
234               do_pca_module(0);
235               do_pca_module(1);
236               do_pca_module(2);
237               do_pca_module(3);
238               do_pca_module(4);
239             }
240         }
241     }
242   return(resGO);
243 }
244
245 int
246 t_uc89c51r::do_pca_module(int nr)
247 {
248   uchar CCAPM[5]= {0xda, 0xdb, 0xdc, 0xdd, 0xde};
249   uchar CCAPL[5]= {0xea, 0xeb, 0xec, 0xed, 0xee};
250   uchar CCAPH[5]= {0xfa, 0xfb, 0xfc, 0xfd, 0xfe};
251   uchar bmCEX[5]= {bmCEX0, bmCEX1, bmCEX2, bmCEX3, bmCEX4};
252   uchar bmCCF[5]= {bmCCF0, bmCCF1, bmCCF2, bmCCF3, bmCCF4};
253   uchar ccapm= get_mem(MEM_SFR, CCAPM[nr]);
254   uint p1= get_mem(MEM_SFR, P1);
255
256   if (
257       ((ccapm & bmCAPP) &&
258        (prev_p1 & bmCEX[nr]) == 0 &&
259        (p1 & bmCEX[nr]) != 0)
260       ||
261       ((ccapm & bmCAPN) &&
262        (prev_p1 & bmCEX[nr]) != 0 &&
263        (p1 & bmCEX[nr]) == 0)
264       )
265     {
266       /* Capture */
267       //MEM(MEM_SFR)[CCAPL[nr]]= MEM(MEM_SFR)[CL];
268       sfr->set(CCAPL[nr], sfr->get(CL));
269       //MEM(MEM_SFR)[CCAPH[nr]]= MEM(MEM_SFR)[CH];
270       sfr->set(CCAPH[nr], sfr->get(CH));
271       mem(MEM_SFR)->set_bit1(CCON, bmCCF[nr]);
272     }
273
274   if (ccapm & bmECOM)
275     {
276       /* Comparator enabled */
277       /*if (MEM(MEM_SFR)[CL] == MEM(MEM_SFR)[CCAPL[nr]] &&
278         MEM(MEM_SFR)[CH] == MEM(MEM_SFR)[CCAPH[nr]])*/
279       if (sfr->get(CL) == sfr->get(CCAPL[nr]) &&
280           sfr->get(CH) == sfr->get(CCAPH[nr]))
281         {
282           /* Match */
283           if (nr == 4 &&
284               (/*MEM(MEM_SFR)[CMOD]*/sfr->get(CMOD) & bmWDTE))
285             {
286               reset();
287             }
288           mem(MEM_SFR)->set_bit1(CCON, bmCCF[nr]);
289           if (ccapm & bmTOG)
290             {
291               /* Toggle */
292               //MEM(MEM_SFR)[P1]^= bmCEX[nr];
293               sfr->set(P1, sfr->get(P1) ^ bmCEX[nr]);
294             }
295         }
296       if (ccapm & bmPWM)
297         {
298           /* PWM */
299           if (/*MEM(MEM_SFR)[CL]*/sfr->get(CL) == 0)
300             //MEM(MEM_SFR)[CCAPL[nr]]= MEM(MEM_SFR)[CCAPH[nr]];
301             sfr->set(CCAPL[nr], sfr->get(CCAPH[nr]));
302           if (/*MEM(MEM_SFR)[CL]*/sfr->get(CL) <
303               /*MEM(MEM_SFR)[CCAPL[nr]]*/sfr->get(CCAPL[nr]))
304             //MEM(MEM_SFR)[P1]&= ~(bmCEX[nr]);
305             sfr->set(P1, sfr->get(P1) & ~(bmCEX[nr]));
306           else
307             mem(MEM_SFR)->set_bit1(P1, bmCEX[nr]);
308         }
309     }
310
311   return(resGO);
312 }
313
314
315 /* End of s51.src/uc89c51r.cc */