version 0.2.39: fix of arith insts and start of re-structure
[fw/sdcc] / sim / ucsim / s51.src / arith.cc
1 /*
2  * Simulator of microcontrollers (arith.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 "uc51cl.h"
34 #include "regs51.h"
35
36
37 /*
38  * 0x03 1 12 RR A
39  *____________________________________________________________________________
40  *
41  */
42
43 int
44 t_uc51::inst_rr(uchar code)
45 {
46   uchar acc;
47
48   acc= sfr->read(event_at.ws= event_at.rs= ACC); 
49   if (acc & 0x01)
50     sfr->set(ACC, (acc >> 1) | 0x80);
51   else
52     sfr->set(ACC, acc >> 1);
53   return(resGO);
54 }
55
56
57 /*
58  * 0x13 1 12 RRC A
59  *____________________________________________________________________________
60  *
61  */
62
63 int
64 t_uc51::inst_rrc(uchar code)
65 {
66   bool cy;
67   uchar acc;
68
69   cy= SFR_GET_C;
70   SET_C((acc= sfr->read(ACC)) & 0x01);
71   event_at.ws= event_at.rs= ACC;
72   acc>>= 1;
73   if (cy)
74     acc|= 0x80;
75   sfr->set(ACC, acc);
76   return(resGO);
77 }
78
79
80 /*
81  * 0x23 1 12 RL A
82  *____________________________________________________________________________
83  *
84  */
85
86 int
87 t_uc51::inst_rl(uchar code)
88 {
89   uchar acc;
90
91   acc= sfr->read(event_at.ws= event_at.rs= ACC);
92   if (acc & 0x80)
93     sfr->set(ACC, (acc << 1 ) | 0x01);
94   else
95     sfr->set(ACC, acc << 1);
96   return(resGO);
97 }
98
99
100 /*
101  * 0x24 2 12 ADD A,#data
102  *____________________________________________________________________________
103  *
104  */
105
106 int
107 t_uc51::inst_add_a_$data(uchar code)
108 {
109   uchar data, acc;
110   bool newC, newA, c6;
111
112   data= fetch();
113   acc = sfr->get(ACC);
114   newC= (((uint)acc+(uint)(data)) > 255)?0x80:0;
115   newA= ((acc&0x0f)+(data&0x0f)) & 0xf0;
116   c6  = ((acc&0x7f)+(data&0x7f)) & 0x80;
117   event_at.ws= ACC;
118   sfr->set(ACC, acc+data);
119   SET_C(newC);
120   SET_BIT(newC ^ c6, PSW, bmOV);
121   SET_BIT(newA, PSW, bmAC);
122   return(resGO);
123 }
124
125
126 /*
127  * 0x25 2 12 ADD A,addr
128  *____________________________________________________________________________
129  *
130  */
131
132 int
133 t_uc51::inst_add_a_addr(uchar code)
134 {
135   uchar data, acc;
136   bool newC, newA, c6;
137
138   data= read(get_direct(fetch(), &event_at.ri, &event_at.rs));
139   acc = sfr->get(ACC);
140   newC= (((uint)acc+(uint)(data)) > 255)?0x80:0;
141   newA= ((acc&0x0f)+(data&0x0f)) & 0xf0;
142   c6  = ((acc&0x7f)+(data&0x7f)) & 0x80;
143   event_at.ws= ACC;
144   sfr->set(ACC, acc+data);
145   SET_C(newC);
146   SET_BIT(newC ^ c6, PSW, bmOV);
147   SET_BIT(newA, PSW, bmAC);
148   return(resGO);
149 }
150
151
152 /*
153  * 0x26-0x27 1 12 ADD A,@Ri
154  *____________________________________________________________________________
155  *
156  */
157
158 int
159 t_uc51::inst_add_a_$ri(uchar code)
160 {
161   uchar data, *addr, acc;
162   bool newC, newA, c6;
163   int res;
164
165   addr= get_indirect(event_at.ri= *(get_reg(code & 0x01)), &res);
166   acc = sfr->get(ACC);
167   data= *addr;
168   newC= (((uint)acc+(uint)data) > 255)?0x80:0;
169   newA= ((acc&0x0f)+(data&0x0f)) & 0xf0;
170   c6  = ((acc&0x7f)+(data&0x7f)) & 0x80;
171   event_at.ws= ACC;
172   sfr->set(ACC, acc+data);
173   SET_C(newC);
174   SET_BIT(newC ^ c6, PSW, bmOV);
175   SET_BIT(newA, PSW, bmAC);
176   return(res);
177 }
178
179
180 /*
181  * 0x28-0x2f 1 12 ADD A,Rn
182  *____________________________________________________________________________
183  *
184  */
185
186 int
187 t_uc51::inst_add_a_rn(uchar code)
188 {
189   uchar data, acc;
190   bool newC, newA, c6;
191
192   data= *(get_reg(code & 0x07, &event_at.ri));
193   acc = sfr->get(ACC);
194   newC= (((uint)acc+(uint)data) > 255)?0x80:0;
195   newA= ((acc&0x0f)+(data&0x0f)) & 0xf0;
196   c6  = ((acc&0x7f)+(data&0x7f)) & 0x80;
197   event_at.ws= ACC;
198   sfr->set(ACC, acc+data);
199   SET_C(newC);
200   SET_BIT(newC ^ c6, PSW, bmOV);
201   SET_BIT(newA, PSW, bmAC);
202   return(resGO);
203 }
204
205
206 /*
207  * 0x33 1 12 RLC A
208  *____________________________________________________________________________
209  *
210  */
211
212 int
213 t_uc51::inst_rlc(uchar code)
214 {
215   bool cy;
216   uchar acc;
217
218   cy= SFR_GET_C;
219   SET_C((acc= sfr->get(event_at.rs= ACC)) & 0x80);
220   acc<<= 1;
221   if (cy)
222     acc|= 0x01;
223   sfr->set(event_at.ws= ACC, acc);
224   return(resGO);
225 }
226
227
228 /*
229  * 0x34 2 12 ADDC A,#data
230  *____________________________________________________________________________
231  *
232  */
233
234 int
235 t_uc51::inst_addc_a_$data(uchar code)
236 {
237   uchar data, acc;
238   bool orgC, newC, newA, c6;
239
240   data= fetch();
241   acc = sfr->get(ACC);
242   newC= (((uint)acc+(uint)data+((orgC= SFR_GET_C)?1:0)) > 255)?0x80:0;
243   newA= ((acc&0x0f)+(data&0x0f)+(orgC?1:0)) & 0xf0;
244   c6  = ((acc&0x7f)+(data&0x7f)+(orgC?1:0)) & 0x80;
245   sfr->set(event_at.ws= ACC, acc + data + (orgC?1:0));
246   SET_C(newC);
247   SET_BIT(newC ^ c6, PSW, bmOV);
248   SET_BIT(newA, PSW, bmAC);
249   return(resGO);
250 }
251
252
253 /*
254  * 0x35 2 12 ADDC A,addr
255  *____________________________________________________________________________
256  *
257  */
258
259 int
260 t_uc51::inst_addc_a_addr(uchar code)
261 {
262   uchar data, acc;
263   bool orgC, newC, newA, c6;
264
265   data= read(get_direct(fetch(), &event_at.ri, &event_at.rs));
266   acc = sfr->get(ACC);
267   newC= (((uint)acc+(uint)data+((orgC= SFR_GET_C)?1:0)) > 255)?0x80:0;
268   newA= ((acc&0x0f)+(data&0x0f)+(orgC?1:0)) & 0xf0;
269   c6  = ((acc&0x7f)+(data&0x7f)+(orgC?1:0)) & 0x80;
270   sfr->set(event_at.ws= ACC, acc + data + (orgC?1:0));
271   SET_C(newC);
272   SET_BIT(newC ^ c6, PSW, bmOV);
273   SET_BIT(newA, PSW, bmAC);
274   return(resGO);
275 }
276
277
278 /*
279  * 0x36-0x37 1 12 ADDC A,@Ri
280  *____________________________________________________________________________
281  *
282  */
283
284 int
285 t_uc51::inst_addc_a_$ri(uchar code)
286 {
287   uchar data, *addr, acc;
288   bool orgC, newC, newA, c6;
289   int res;
290
291   addr= get_indirect(event_at.ri= *(get_reg(code & 0x01)), &res);
292   acc = sfr->get(ACC);
293   data= *addr;
294   newC= (((uint)acc+(uint)data+((orgC= SFR_GET_C)?1:0)) > 255)?0x80:0;
295   newA= ((acc&0x0f)+(data&0x0f)+(orgC?1:0)) & 0xf0;
296   c6  = ((acc&0x7f)+(data&0x7f)+(orgC?1:0)) & 0x80;
297   sfr->set(event_at.ws= ACC, acc + data + (orgC?1:0));
298   SET_C(newC);
299   SET_BIT(newC ^ c6, PSW, bmOV);
300   SET_BIT(newA, PSW, bmAC);
301   return(res);
302 }
303
304
305 /*
306  * 0x38-0x3f 1 12 ADDC A,Rn
307  *____________________________________________________________________________
308  *
309  */
310
311 int
312 t_uc51::inst_addc_a_rn(uchar code)
313 {
314   uchar data, acc;
315   bool orgC, newC, newA, c6;
316
317   data= *(get_reg(code & 0x07, &event_at.ri));
318   acc = sfr->get(ACC);
319   newC= (((uint)acc+(uint)data+((orgC= SFR_GET_C)?1:0)) > 255)?0x80:0;
320   newA= ((acc&0x0f)+(data&0x0f)+(orgC?1:0)) & 0xf0;
321   c6  = ((acc&0x7f)+(data&0x7f)+(orgC?1:0)) & 0x80;
322   sfr->set(event_at.ws= ACC, acc + data + (orgC?1:0));
323   SET_C(newC);
324   SET_BIT(newC ^ c6, PSW, bmOV);
325   SET_BIT(newA, PSW, bmAC);
326   return(resGO);
327 }
328
329
330 /*
331  * 0x84 1 48 DIV AB
332  *____________________________________________________________________________
333  *
334  */
335
336 int
337 t_uc51::inst_div_ab(uchar code)
338 {
339   uchar temp, psw, b, acc;
340
341   psw= sfr->get(PSW);
342   psw&= ~bmCY;
343   if (!(b= sfr->get(event_at.rs= B)))
344     psw|= bmOV;
345   else
346     {
347       psw&= ~bmOV;
348       temp= (acc= sfr->get(ACC)) / b;
349       sfr->set(B, acc % b);
350       sfr->set(event_at.ws= ACC, temp);
351     }
352   sfr->set(PSW, psw);
353   tick(3);
354   return(resGO);
355 }
356
357
358 /*
359  * 0x94 2 12 SUBB A,#data
360  *____________________________________________________________________________
361  *
362  */
363
364 int
365 t_uc51::inst_subb_a_$data(uchar code)
366 {
367   uchar data, acc, result, psw, c;
368
369   data= fetch();
370   acc = sfr->get(ACC);
371   result= acc-data;
372   psw= sfr->get(PSW);
373   if ((c= (psw & bmCY)?1:0))
374     result--;
375   sfr->set(event_at.ws= ACC, result);
376   sfr->set(PSW,
377            (psw & ~(bmCY|bmOV|bmAC)) |
378            (((unsigned int)acc < (unsigned int)(data+c))?bmCY:0) |
379            (((acc<0x80 && data>0x7f && result>0x7f) ||
380              (acc>0x7f && data<0x80 && result<0x80))?bmOV:0) |
381            (((acc&0x0f) < ((data+c)&0x0f) ||
382              (c && ((data&0x0f)==0x0f)))?bmAC:0));
383   return(resGO);
384 }
385
386
387 /*
388  * 0x95 2 12 SUBB A,addr
389  *____________________________________________________________________________
390  *
391  */
392
393 int
394 t_uc51::inst_subb_a_addr(uchar code)
395 {
396   uchar *addr, data, acc, result, psw,c ;
397
398   addr= get_direct(fetch(), &event_at.ri, &event_at.rs);
399   acc = sfr->get(ACC);
400   data= read(addr);
401   result= acc-data;
402   psw= sfr->get(PSW);
403   if ((c= (psw & bmCY)?1:0))
404     result--;
405   sfr->set(event_at.ws= ACC, result);
406   sfr->set(PSW,
407            (psw & ~(bmCY|bmOV|bmAC)) |
408            (((unsigned int)acc < (unsigned int)(data+c))?bmCY:0) |
409            (((acc<0x80 && data>0x7f && result>0x7f) ||
410              (acc>0x7f && data<0x80 && result<0x80))?bmOV:0) |
411            (((acc&0x0f) < ((data+c)&0x0f) ||
412              (c && ((data&0x0f)==0x0f)))?bmAC:0));
413   return(resGO);
414 }
415
416
417 /*
418  * 0x96-0x97 1 12 SUBB A,@Ri
419  *____________________________________________________________________________
420  *
421  */
422
423 int
424 t_uc51::inst_subb_a_$ri(uchar code)
425 {
426   uchar data, acc, result, psw, c;
427   int res;
428
429   data= *(get_indirect(event_at.ri= *(get_reg(code & 0x01)), &res));
430   acc = sfr->get(ACC);
431   result= acc-data;
432   psw= sfr->get(PSW);
433   if ((c= (psw & bmCY)?1:0))
434     result--;
435   sfr->set(event_at.ws= ACC, result);
436   sfr->set(PSW,
437            (psw & ~(bmCY|bmOV|bmAC)) |
438            (((unsigned int)acc < (unsigned int)(data+c))?bmCY:0) |
439            (((acc<0x80 && data>0x7f && result>0x7f) ||
440              (acc>0x7f && data<0x80 && result<0x80))?bmOV:0) |
441            (((acc&0x0f) < ((data+c)&0x0f) ||
442              (c && ((data&0x0f)==0x0f)))?bmAC:0));
443   return(res);
444 }
445
446
447 /*
448  * 0x98-0x9f 1 12 SUBB A,Rn
449  *____________________________________________________________________________
450  *
451  */
452
453 int
454 t_uc51::inst_subb_a_rn(uchar code)
455 {
456   uchar data, acc, result, psw, c;
457
458   data= *(get_reg(code & 0x07, &event_at.ri));
459   acc = sfr->get(ACC);
460   result= acc-data;
461   psw= sfr->get(PSW);
462   if ((c= (psw & bmCY)?1:0))
463     result--;
464   sfr->set(event_at.ws= ACC, result);
465   sfr->set(PSW,
466            (psw & ~(bmCY|bmOV|bmAC)) |
467            (((unsigned int)acc < (unsigned int)(data+c))?bmCY:0) |
468            (((acc<0x80 && data>0x7f && result>0x7f) ||
469              (acc>0x7f && data<0x80 && result<0x80))?bmOV:0) |
470            (((acc&0x0f) < ((data+c)&0x0f) ||
471              (c && ((data&0x0f)==0x0f)))?bmAC:0));
472   return(resGO);
473 }
474
475
476 /*
477  * 0xa4 1 48 MUL AB
478  *____________________________________________________________________________
479  *
480  */
481
482 int
483 t_uc51::inst_mul_ab(uchar code)
484 {
485   uint temp, psw, acc, b;
486
487   psw= sfr->get(PSW);
488   psw&= ~bmCY;
489   temp= (acc= sfr->get(ACC)) * (b= sfr->get(B));
490   sfr->set(event_at.ws= ACC, temp & 0xff);
491   sfr->set(event_at.rs= B, (temp >> 8) & 0xff);
492   SET_BIT(sfr->get(B), PSW, bmOV);
493   SET_BIT(0, PSW, bmCY);
494   tick(3);
495   return(resGO);
496 }
497
498
499 /*
500  * 0xd4 1 12 DA A
501  *____________________________________________________________________________
502  *
503  */
504
505 int
506 t_uc51::inst_da_a(uchar code)
507 {
508   uchar acc, psw;
509
510   acc= sfr->get(ACC);
511   psw= sfr->get(PSW);
512   event_at.ws= ACC;
513   if ((acc & 0x0f) > 9 ||
514       (psw & bmAC))
515     {
516       if (((uint)acc+(uint)0x06) > 255)
517         psw|= bmCY;
518       acc+= 0x06;
519     }
520   if ((acc & 0xf0) > 0x90 ||
521       (psw & bmCY))
522     {
523       if (((uint)acc+(uint)0x60) > 255)
524         psw|= bmCY;
525       acc+= 0x60;
526     }
527   sfr->set(ACC, acc);
528   sfr->set(PSW, psw);
529   return(resGO);
530 }
531
532
533 /* End of s51.src/arith.cc */