ucsim-0.2.37-pre3 into cvs
[fw/sdcc] / sim / ucsim / s51.src / uc51.cc
1 /*
2  * Simulator of microcontrollers (uc51.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 #include <stdlib.h>
32 #include <ctype.h>
33 #include <termios.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <errno.h>
37 #include <sys/types.h>
38 #include <sys/time.h>
39 #if FD_HEADER_OK
40 # include HEADER_FD
41 #endif
42 #include "i_string.h"
43
44 // sim
45 #include "optioncl.h"
46
47 // local
48 #include "uc51cl.h"
49 #include "glob.h"
50 #include "regs51.h"
51 #include "dump.h"
52 #include "timer0cl.h"
53 #include "timer1cl.h"
54 #include "serialcl.h"
55 #include "portcl.h"
56 #include "interruptcl.h"
57
58
59 /*
60  * Making a new micro-controller and reset it
61  */
62
63 t_uc51::t_uc51(int Itype, int Itech, class cl_sim *asim):
64   cl_uc(asim)
65 {
66   int i;
67   struct termios tattr;
68   
69   type= Itype;
70   technology= Itech;
71
72   debug= asim->get_iarg('V', 0);
73   stop_at_it= FALSE;
74   options->add(new cl_bool_opt(&debug, "verbose", "Verbose flag."));
75   options->add(new cl_bool_opt(&stop_at_it, "stopit",
76                                "Stop if interrupt accepted."));
77   options->add(new cl_cons_debug_opt(asim, "debug",
78                                      "Debug messages appears on this console."));
79
80   serial_in = (FILE*)asim->get_parg(0, "Ser_in");
81   serial_out= (FILE*)asim->get_parg(0, "Ser_out");
82   if (serial_in)
83     {
84       // making `serial' unbuffered
85       if (setvbuf(serial_in, NULL, _IONBF, 0))
86         perror("Unbuffer serial input channel");
87       // setting O_NONBLOCK
88       if ((i= fcntl(fileno(serial_in), F_GETFL, 0)) < 0)
89         perror("Get flags of serial input");
90       i|= O_NONBLOCK;
91       if (fcntl(fileno(serial_in), F_SETFL, i) < 0)
92         perror("Set flags of serial input");
93       // switching terminal to noncanonical mode
94       if (isatty(fileno(serial_in)))
95         {
96           tcgetattr(fileno(serial_in), &saved_attributes_in);
97           tcgetattr(fileno(serial_in), &tattr);
98           tattr.c_lflag&= ~(ICANON|ECHO);
99           tattr.c_cc[VMIN] = 1;
100           tattr.c_cc[VTIME]= 0;
101           tcsetattr(fileno(serial_in), TCSAFLUSH, &tattr);
102         }
103       else
104         fprintf(stderr, "Warning: serial input interface connected to a "
105                 "non-terminal file.\n");
106     }
107   if (serial_out)
108     {
109       // making `serial' unbuffered
110       if (setvbuf(serial_out, NULL, _IONBF, 0))
111         perror("Unbuffer serial output channel");
112       // setting O_NONBLOCK
113       if ((i= fcntl(fileno(serial_out), F_GETFL, 0)) < 0)
114         perror("Get flags of serial output");
115       i|= O_NONBLOCK;
116       if (fcntl(fileno(serial_out), F_SETFL, i) < 0)
117         perror("Set flags of serial output");
118       // switching terminal to noncanonical mode
119       if (isatty(fileno(serial_out)))
120         {
121           tcgetattr(fileno(serial_out), &saved_attributes_out);
122           tcgetattr(fileno(serial_out), &tattr);
123           tattr.c_lflag&= ~(ICANON|ECHO);
124           tattr.c_cc[VMIN] = 1;
125           tattr.c_cc[VTIME]= 0;
126           tcsetattr(fileno(serial_out), TCSAFLUSH, &tattr);
127         }
128       else
129         fprintf(stderr, "Warning: serial output interface connected to a "
130                 "non-terminal file.\n");
131     }
132
133   for (i= 0; i < 4; i++)
134     port_pins[i]= 0xff;
135   it_sources->add(new cl_it_src(bmEX0, TCON, bmIE0, 0x0003, true,
136                                 "external #0"));
137   it_sources->add(new cl_it_src(bmET0, TCON, bmTF0, 0x000b, true,
138                                 "timer #0"));
139   it_sources->add(new cl_it_src(bmEX1, TCON, bmIE1, 0x0013, true,
140                                 "external #1"));
141   it_sources->add(new cl_it_src(bmET1, TCON, bmTF1, 0x001b, true,
142                                 "timer #1"));
143   it_sources->add(new cl_it_src(bmES , SCON, bmTI , 0x0023, false,
144                                 "serial transmit"));
145   it_sources->add(new cl_it_src(bmES , SCON, bmRI , 0x0023, false,
146                                 "serial receive"));
147 }
148
149
150 /*
151  * Initializing. Virtual calls go here
152  * This method must be called first after object creation.
153  */
154
155 int
156 t_uc51::init(void)
157 {
158   cl_uc::init();
159   reset();
160   return(0);
161 }
162
163 static char id_string_51[100];
164
165 char *
166 t_uc51::id_string(void)
167 {
168   int i;
169
170   for (i= 0; cpus_51[i].type_str != NULL && cpus_51[i].type != type; i++) ;
171   sprintf(id_string_51, "%s %s",
172           cpus_51[i].type_str?cpus_51[i].type_str:"51",
173           (technology==CPU_HMOS)?"HMOS":"CMOS");
174   return(id_string_51);
175 }
176
177 void
178 t_uc51::mk_hw_elements(void)
179 {
180   class cl_hw *h;
181
182   hws->add(h= new cl_timer0(this));
183   h->init();
184   hws->add(h= new cl_timer1(this));
185   h->init();
186   hws->add(h= new cl_serial(this));
187   h->init();
188   hws->add(h= new cl_port(this, 0));
189   h->init();
190   hws->add(h= new cl_port(this, 1));
191   h->init();
192   hws->add(h= new cl_port(this, 2));
193   h->init();
194   hws->add(h= new cl_port(this, 3));
195   h->init();
196   hws->add(h= new cl_interrupt(this));
197   h->init();
198 }
199
200 class cl_mem *
201 t_uc51::mk_mem(enum mem_class type)
202 {
203   class cl_mem *m= cl_uc::mk_mem(type);
204   if (type == MEM_SFR)
205     sfr= m;
206   if (type == MEM_IRAM)
207     iram= m;
208   return(m);
209 }
210
211
212 /*
213  * Destroying the micro-controller object
214  */
215
216 t_uc51::~t_uc51(void)
217 {
218   if (serial_out)
219     {
220       if (isatty(fileno(serial_out)))
221         tcsetattr(fileno(serial_out), TCSANOW, &saved_attributes_out);
222       fclose(serial_out);
223     }
224   if (serial_in)
225     {
226       if (isatty(fileno(serial_in)))
227         tcsetattr(fileno(serial_in), TCSANOW, &saved_attributes_in);
228       fclose(serial_in);
229     }
230 }
231
232
233 /*
234  * Writing data to EROM
235  */
236
237 void
238 t_uc51::write_rom(uint addr, ulong data)
239 {
240   if (addr < EROM_SIZE)
241     set_mem(MEM_ROM, addr, data);
242 }
243
244
245 /*
246  * Disassembling an instruction
247  */
248
249 struct dis_entry *
250 t_uc51::dis_tbl(void)
251 {
252   return(disass_51);
253 }
254
255 struct name_entry *
256 t_uc51::sfr_tbl(void)
257 {
258   return(sfr_tab51);
259 }
260
261 struct name_entry *
262 t_uc51::bit_tbl(void)
263 {
264   return(bit_tab51);
265 }
266
267 char *
268 t_uc51::disass(uint addr, char *sep)
269 {
270   char work[256], temp[20], c[2];
271   char *buf, *p, *b, *t;
272   uint code= get_mem(MEM_ROM, addr);
273
274   p= work;
275   b= dis_tbl()[code].mnemonic;
276   while (*b)
277     {
278       if (*b == '%')
279         {
280           b++;
281           switch (*(b++))
282             {
283             case 'A': // absolute address
284               sprintf(temp, "%04lx",
285                       (addr&0xf800)|
286                       (((code>>5)&0x07)*256 +
287                        get_mem(MEM_ROM, addr+1)));
288               break;
289             case 'l': // long address
290               sprintf(temp, "%04lx",
291                       get_mem(MEM_ROM, addr+1)*256 + get_mem(MEM_ROM, addr+2));
292               break;
293             case 'a': // addr8 (direct address) at 2nd byte
294               if (!get_name(get_mem(MEM_ROM, addr+1), sfr_tbl(), temp))
295                 sprintf(temp, "%02lx", get_mem(MEM_ROM, addr+1));
296               break;
297             case '8': // addr8 (direct address) at 3rd byte
298               if (!get_name(get_mem(MEM_ROM, addr+2), sfr_tbl(), temp))
299                 sprintf(temp, "%02lx", get_mem(MEM_ROM, addr+1));
300               sprintf(temp, "%02lx", get_mem(MEM_ROM, addr+2));
301               break;
302             case 'b': // bitaddr at 2nd byte
303               if (get_name(get_mem(MEM_ROM, addr+1), bit_tbl(), temp))
304                 break;
305               if (get_name(get_bitidx(get_mem(MEM_ROM, addr+1)),
306                            sfr_tbl(), temp))
307                 {
308                   strcat(temp, ".");
309                   sprintf(c, "%1ld", get_mem(MEM_ROM, addr+1)&0x07);
310                   strcat(temp, c);
311                   break;
312                 }
313               sprintf(temp, "%02x.%ld",
314                       get_bitidx(get_mem(MEM_ROM, addr+1)),
315                       get_mem(MEM_ROM, addr+1)&0x07);
316               break;
317             case 'r': // rel8 address at 2nd byte
318               sprintf(temp, "%04x",
319                       addr+2+(signed char)(get_mem(MEM_ROM, addr+1)));
320               break;
321             case 'R': // rel8 address at 3rd byte
322               sprintf(temp, "%04x",
323                       addr+3+(signed char)(get_mem(MEM_ROM, addr+2)));
324               break;
325             case 'd': // data8 at 2nd byte
326               sprintf(temp, "%02lx", get_mem(MEM_ROM, addr+1));
327               break;
328             case 'D': // data8 at 3rd byte
329               sprintf(temp, "%02lx", get_mem(MEM_ROM, addr+2));
330               break;
331             case '6': // data16 at 2nd(H)-3rd(L) byte
332               sprintf(temp, "%04lx",
333                       get_mem(MEM_ROM, addr+1)*256 + get_mem(MEM_ROM, addr+2));
334               break;
335             default:
336               strcpy(temp, "?");
337               break;
338             }
339           t= temp;
340           while (*t)
341             *(p++)= *(t++);
342         }
343       else
344         *(p++)= *(b++);
345     }
346   *p= '\0';
347
348   p= strchr(work, ' ');
349   if (!p)
350     {
351       buf= strdup(work);
352       return(buf);
353     }
354   if (sep == NULL)
355     buf= (char *)malloc(6+strlen(p)+1);
356   else
357     buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
358   for (p= work, b= buf; *p != ' '; p++, b++)
359     *b= *p;
360   p++;
361   *b= '\0';
362   if (sep == NULL)
363     {
364       while (strlen(buf) < 6)
365         strcat(buf, " ");
366     }
367   else
368     strcat(buf, sep);
369   strcat(buf, p);
370   return(buf);
371 }
372
373 void
374 t_uc51::print_disass(uint addr, class cl_console *con)
375 {
376   char *dis;
377   class cl_brk *b;
378   int i;
379   uint code= get_mem(MEM_ROM, addr);
380
381   b  = fbrk_at(addr);
382   dis= disass(addr, NULL);
383   if (b)
384     con->printf("%c", (b->perm == brkFIX)?'F':'D');
385   else
386     con->printf(" ");
387   con->printf("%c %06x %02x",
388               inst_at(addr)?' ':'*',
389               addr, code);
390   for (i= 1; i < inst_length(code); i++)
391     con->printf(" %02x", get_mem(MEM_ROM, addr+i));
392   while (i < 3)
393     {
394       con->printf("   ");
395       i++;
396     }
397   con->printf(" %s\n", dis);
398   free(dis);
399 }
400
401 void
402 t_uc51::print_regs(class cl_console *con)
403 {
404   t_addr start;
405   uchar data;
406
407   start= sfr->get(PSW) & 0x18;
408   dump_memory(iram, &start, start+7, 8, sim->cmd_out(), sim);
409   start= sfr->get(PSW) & 0x18;
410   data= iram->get(iram->get(start));
411   con->printf("%06x %02x %c",
412               iram->get(start), data, isprint(data)?data:'.');
413
414   con->printf("  ACC= 0x%02x %3d %c  B= 0x%02x", sfr->get(ACC), sfr->get(ACC),
415               isprint(sfr->get(ACC))?(sfr->get(ACC)):'.', sfr->get(B)); 
416   eram2xram();
417   data= get_mem(MEM_XRAM, sfr->get(DPH)*256+sfr->get(DPL));
418   con->printf("   DPTR= 0x%02x%02x @DPTR= 0x%02x %3d %c\n", sfr->get(DPH),
419               sfr->get(DPL), data, data, isprint(data)?data:'.');
420
421   data= iram->get(iram->get(start+1));
422   con->printf("%06x %02x %c", iram->get(start+1), data,
423               isprint(data)?data:'.');
424   data= sfr->get(PSW);
425   con->printf("  PSW= 0x%02x CY=%c AC=%c OV=%c P=%c\n", data,
426               (data&bmCY)?'1':'0', (data&bmAC)?'1':'0',
427               (data&bmOV)?'1':'0', (data&bmP)?'1':'0');
428
429   print_disass(PC, con);
430 }
431
432
433 /*
434  * Resetting the micro-controller
435  */
436
437 void
438 t_uc51::reset(void)
439 {
440   cl_uc::reset();
441
442   clear_sfr();
443
444   result= resGO;
445
446   was_reti= FALSE;
447
448   s_tr_t1    = 0;
449   s_rec_t1   = 0;
450   s_tr_tick  = 0;
451   s_rec_tick = 0;
452   s_in       = 0;
453   s_out      = 0;
454   s_sending  = FALSE;
455   s_receiving= FALSE;
456   s_rec_bit  = 0;
457   s_tr_bit   = 0;
458 }
459
460
461 /*
462  * Setting up SFR area to reset value
463  */
464
465 void
466 t_uc51::clear_sfr(void)
467 {
468   int i;
469   
470   for (i= 0; i < SFR_SIZE; i++)
471     sfr->set(i, 0);
472   sfr->set(P0, 0xff);
473   sfr->set(P1, 0xff);
474   sfr->set(P2, 0xff);
475   sfr->set(P3, 0xff);
476   sfr->set(SP, 7);
477   prev_p1= port_pins[1] & sfr->get(P1);
478   prev_p3= port_pins[3] & sfr->get(P3);
479 }
480
481
482 /*
483  * Analyzing code and settig up instruction map
484  */
485
486 void
487 t_uc51::analyze(uint addr)
488 {
489   uint code;
490   struct dis_entry *tabl;
491
492   code= get_mem(MEM_ROM, addr);
493   tabl= &(dis_tbl()[code]);
494   while (!inst_at(addr) &&
495          code != 0xa5 /* break point */)
496     {
497       set_inst_at(addr);
498       switch (tabl->branch)
499         {
500         case 'a': // acall
501           analyze((addr & 0xf800)|
502                   ((get_mem(MEM_ROM, addr+1)&0x07)*256+
503                    get_mem(MEM_ROM, addr+2)));
504           analyze(addr+tabl->length);
505           break;
506         case 'A': // ajmp
507           addr= (addr & 0xf800)|
508             ((get_mem(MEM_ROM, addr+1) & 0x07)*256 + get_mem(MEM_ROM, addr+2));
509           break;
510         case 'l': // lcall
511           analyze(get_mem(MEM_ROM, addr+1)*256 + get_mem(MEM_ROM, addr+2));
512           analyze(addr+tabl->length);
513           break;
514         case 'L': // ljmp
515           addr= get_mem(MEM_ROM, addr+1)*256 + get_mem(MEM_ROM, addr+2);
516           break;
517         case 'r': // reljmp (2nd byte)
518           analyze((addr + (signed char)(get_mem(MEM_ROM, addr+1))) &
519                   (EROM_SIZE - 1));
520           analyze(addr+tabl->length);
521           break;
522         case 'R': // reljmp (3rd byte)
523           analyze((addr+
524                    (signed char)(get_mem(MEM_ROM, addr+2)))&(EROM_SIZE-1));
525           analyze(addr+tabl->length);
526           break;
527         case 's': // sjmp
528           {
529             signed char target;
530             target= get_mem(MEM_ROM, addr+1);
531             addr+= 2;
532             addr= (addr+target)&(EROM_SIZE-1);
533             break;
534           }
535         case '_':
536           return;
537         default:
538           addr= (addr+tabl->length) & (EROM_SIZE - 1);
539           break;
540         }
541       code= get_mem(MEM_ROM, addr);
542       tabl= &(dis_tbl()[code]);
543     }
544 }
545
546
547 /*
548  * Inform hardware elements that `cycles' machine cycles have elapsed
549  */
550
551 int
552 t_uc51::tick(int cycles)
553 {
554   int l;
555
556   cl_uc::tick(cycles);
557   do_hardware(cycles);
558   s_tr_tick+= (l= cycles * clock_per_cycle());
559   s_rec_tick+= l;
560   return(0);
561 }
562
563
564 /*
565  * Correcting direct address
566  *
567  * This function returns address of addressed element which can be an IRAM
568  * or an SFR.
569  */
570
571 uchar *
572 t_uc51::get_direct(t_mem addr, t_addr *ev_i, t_addr *ev_s)
573 {
574   if (addr < SFR_START)
575     return(&(MEM(MEM_IRAM)[*ev_i= addr]));
576   else
577     return(&(MEM(MEM_SFR)[*ev_s= addr]));
578 }
579
580 /*
581  * Calculating address of indirectly addressed IRAM cell
582  * If CPU is 8051 and addr is over 127, it must be illegal!
583  */
584
585 uchar *
586 t_uc51::get_indirect(uchar addr, int *res)
587 {
588   if (addr >= SFR_START)
589     *res= resINV_ADDR;
590   else
591     *res= resGO;
592   return(&(MEM(MEM_IRAM)[addr]));
593 }
594
595
596 /*
597  * Calculating address of specified register cell in IRAM
598  */
599
600 uchar *
601 t_uc51::get_reg(uchar regnum)
602 {
603   return(&(MEM(MEM_IRAM)[(sfr->get(PSW) & (bmRS0|bmRS1)) |
604                         (regnum & 0x07)]));
605 }
606
607 uchar *
608 t_uc51::get_reg(uchar regnum, t_addr *event)
609 {
610   return(&(MEM(MEM_IRAM)[*event= (sfr->get(PSW) & (bmRS0|bmRS1)) |
611                         (regnum & 0x07)]));
612 }
613
614
615 /*
616  * Calculating address of IRAM or SFR cell which contains addressed bit
617  * Next function returns index of cell which contains addressed bit.
618  */
619
620 uchar *
621 t_uc51::get_bit(uchar bitaddr)
622 {
623   if (bitaddr < 128)
624     return(&(MEM(MEM_IRAM)[(bitaddr/8)+32]));
625   return(&(MEM(MEM_SFR)[bitaddr & 0xf8]));
626 }
627
628 uchar *
629 t_uc51::get_bit(uchar bitaddr, t_addr *ev_i, t_addr *ev_s)
630 {
631   if (bitaddr < 128)
632     return(&(MEM(MEM_IRAM)[*ev_i= (bitaddr/8)+32]));
633   return(&(MEM(MEM_SFR)[*ev_s= bitaddr & 0xf8]));
634 }
635
636 uchar
637 t_uc51::get_bitidx(uchar bitaddr)
638 {
639   if (bitaddr < 128)
640     return((bitaddr/8)+32);
641   return(bitaddr & 0xf8);
642 }
643
644
645 /*
646  * Processing write operation to IRAM
647  *
648  * It starts serial transmition if address is in SFR and it is
649  * SBUF. Effect on IE is also checked.
650  */
651
652 void
653 t_uc51::proc_write(uchar *addr)
654 {
655   if (addr == &((sfr->umem8)[SBUF]))
656     {
657       s_out= sfr->get(SBUF);
658       s_sending= TRUE;
659       s_tr_bit = 0;
660       s_tr_tick= 0;
661       s_tr_t1  = 0;
662     }
663   if (addr == &((sfr->umem8)[IE]))
664     was_reti= TRUE;
665 }
666
667 void
668 t_uc51::proc_write_sp(uchar val)
669 {
670   if (val > sp_max)
671     sp_max= val;
672   sp_avg= (sp_avg+val)/2;
673 }
674
675
676 /*
677  * Reading IRAM or SFR, but if address points to a port, it reads
678  * port pins instead of port latches
679  */
680
681 uchar
682 t_uc51::read(uchar *addr)
683 {
684   if (addr == &(MEM(MEM_SFR)[P0]))
685     return(get_mem(MEM_SFR, P0) & port_pins[0]);
686   if (addr == &(MEM(MEM_SFR)[P1]))
687     return(get_mem(MEM_SFR, P1) & port_pins[1]);
688   if (addr == &(MEM(MEM_SFR)[P2]))
689     return(get_mem(MEM_SFR, P2) & port_pins[2]);
690   if (addr == &(MEM(MEM_SFR)[P3]))
691     return(get_mem(MEM_SFR, P3) & port_pins[3]);
692   return(*addr);
693 }
694
695
696 /*
697  * Fetching one instruction and executing it
698  */
699
700 void
701 t_uc51::pre_inst(void)
702 {
703   event_at.wi= (t_addr)-1;
704   event_at.ri= (t_addr)-1;
705   event_at.wx= (t_addr)-1;
706   event_at.rx= (t_addr)-1;
707   event_at.ws= (t_addr)-1;
708   event_at.rs= (t_addr)-1;
709   event_at.rc= (t_addr)-1;
710 }
711
712 int
713 t_uc51::exec_inst(void)
714 {
715   ulong code;
716   int res;
717
718   //pr_inst();
719   if (fetch(&code))
720     return(resBREAKPOINT);
721   tick(1);
722   switch (code)
723     {
724     case 0x00: res= inst_nop(code); break;
725     case 0x01: case 0x21: case 0x41: case 0x61:
726     case 0x81: case 0xa1: case 0xc1: case 0xe1:res=inst_ajmp_addr(code);break;
727     case 0x02: res= inst_ljmp(code); break;
728     case 0x03: res= inst_rr(code); break;
729     case 0x04: res= inst_inc_a(code); break;
730     case 0x05: res= inst_inc_addr(code); break;
731     case 0x06: case 0x07: res= inst_inc_$ri(code); break;
732     case 0x08: case 0x09: case 0x0a: case 0x0b:
733     case 0x0c: case 0x0d: case 0x0e: case 0x0f: res= inst_inc_rn(code); break;
734     case 0x10: res= inst_jbc_bit_addr(code); break;
735     case 0x11: case 0x31: case 0x51: case 0x71:
736     case 0x91: case 0xb1: case 0xd1: case 0xf1:res=inst_acall_addr(code);break;
737     case 0x12: res= inst_lcall(code, 0); break;
738     case 0x13: res= inst_rrc(code); break;
739     case 0x14: res= inst_dec_a(code); break;
740     case 0x15: res= inst_dec_addr(code); break;
741     case 0x16: case 0x17: res= inst_dec_$ri(code); break;
742     case 0x18: case 0x19: case 0x1a: case 0x1b:
743     case 0x1c: case 0x1d: case 0x1e: case 0x1f: res= inst_dec_rn(code); break;
744     case 0x20: res= inst_jb_bit_addr(code); break;
745     case 0x22: res= inst_ret(code); break;
746     case 0x23: res= inst_rl(code); break;
747     case 0x24: res= inst_add_a_$data(code); break;
748     case 0x25: res= inst_add_a_addr(code); break;
749     case 0x26: case 0x27: res= inst_add_a_$ri(code); break;
750     case 0x28: case 0x29: case 0x2a: case 0x2b:
751     case 0x2c: case 0x2d: case 0x2e: case 0x2f:res= inst_add_a_rn(code);break;
752     case 0x30: res= inst_jnb_bit_addr(code); break;
753     case 0x32: res= inst_reti(code); break;
754     case 0x33: res= inst_rlc(code); break;
755     case 0x34: res= inst_addc_a_$data(code); break;
756     case 0x35: res= inst_addc_a_addr(code); break;
757     case 0x36: case 0x37: res= inst_addc_a_$ri(code); break;
758     case 0x38: case 0x39: case 0x3a: case 0x3b:
759     case 0x3c: case 0x3d: case 0x3e: case 0x3f:res= inst_addc_a_rn(code);break;
760     case 0x40: res= inst_jc_addr(code); break;
761     case 0x42: res= inst_orl_addr_a(code); break;
762     case 0x43: res= inst_orl_addr_$data(code); break;
763     case 0x44: res= inst_orl_a_$data(code); break;
764     case 0x45: res= inst_orl_a_addr(code); break;
765     case 0x46: case 0x47: res= inst_orl_a_$ri(code); break;
766     case 0x48: case 0x49: case 0x4a: case 0x4b:
767     case 0x4c: case 0x4d: case 0x4e: case 0x4f: res= inst_orl_a_rn(code);break;
768     case 0x50: res= inst_jnc_addr(code); break;
769     case 0x52: res= inst_anl_addr_a(code); break;
770     case 0x53: res= inst_anl_addr_$data(code); break;
771     case 0x54: res= inst_anl_a_$data(code); break;
772     case 0x55: res= inst_anl_a_addr(code); break;
773     case 0x56: case 0x57: res= inst_anl_a_$ri(code); break;
774     case 0x58: case 0x59: case 0x5a: case 0x5b:
775     case 0x5c: case 0x5d: case 0x5e: case 0x5f: res= inst_anl_a_rn(code);break;
776     case 0x60: res= inst_jz_addr(code); break;
777     case 0x62: res= inst_xrl_addr_a(code); break;
778     case 0x63: res= inst_xrl_addr_$data(code); break;
779     case 0x64: res= inst_xrl_a_$data(code); break;
780     case 0x65: res= inst_xrl_a_addr(code); break;
781     case 0x66: case 0x67: res= inst_xrl_a_$ri(code); break;
782     case 0x68: case 0x69: case 0x6a: case 0x6b:
783     case 0x6c: case 0x6d: case 0x6e: case 0x6f: res= inst_xrl_a_rn(code);break;
784     case 0x70: res= inst_jnz_addr(code); break;
785     case 0x72: res= inst_orl_c_bit(code); break;
786     case 0x73: res= inst_jmp_$a_dptr(code); break;
787     case 0x74: res= inst_mov_a_$data(code); break;
788     case 0x75: res= inst_mov_addr_$data(code); break;
789     case 0x76: case 0x77: res= inst_mov_$ri_$data(code); break;
790     case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c:
791     case 0x7d: case 0x7e: case 0x7f: res=inst_mov_rn_$data(code); break;
792     case 0x80: res= inst_sjmp(code); break;
793     case 0x82: res= inst_anl_c_bit(code); break;
794     case 0x83: res= inst_movc_a_$a_pc(code); break;
795     case 0x84: res= inst_div_ab(code); break;
796     case 0x85: res= inst_mov_addr_addr(code); break;
797     case 0x86: case 0x87: res= inst_mov_addr_$ri(code); break;
798     case 0x88: case 0x89: case 0x8a: case 0x8b:
799     case 0x8c: case 0x8d: case 0x8e: case 0x8f:res=inst_mov_addr_rn(code);break;
800     case 0x90: res= inst_mov_dptr_$data(code); break;
801     case 0x92: res= inst_mov_bit_c(code); break;
802     case 0x93: res= inst_movc_a_$a_dptr(code); break;
803     case 0x94: res= inst_subb_a_$data(code); break;
804     case 0x95: res= inst_subb_a_addr(code); break;
805     case 0x96: case 0x97: res= inst_subb_a_$ri(code); break;
806     case 0x98: case 0x99: case 0x9a: case 0x9b:
807     case 0x9c: case 0x9d: case 0x9e: case 0x9f:res= inst_subb_a_rn(code);break;
808     case 0xa2: res= inst_mov_c_bit(code); break;
809     case 0xa3: res= inst_inc_dptr(code); break;
810     case 0xa4: res= inst_mul_ab(code); break;
811     case 0xa5: res= inst_unknown(code); break;
812     case 0xa6: case 0xa7: res= inst_mov_$ri_addr(code); break;
813     case 0xa8: case 0xa9: case 0xaa: case 0xab:
814     case 0xac: case 0xad: case 0xae: case 0xaf:res=inst_mov_rn_addr(code);break;
815     case 0xb0: res= inst_anl_c_$bit(code); break;
816     case 0xb2: res= inst_cpl_bit(code); break;
817     case 0xb3: res= inst_cpl_c(code); break;
818     case 0xb4: res= inst_cjne_a_$data_addr(code); break;
819     case 0xb5: res= inst_cjne_a_addr_addr(code); break;
820     case 0xb6: case 0xb7: res= inst_cjne_$ri_$data_addr(code); break;
821     case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc:
822     case 0xbd: case 0xbe: case 0xbf: res=inst_cjne_rn_$data_addr(code); break;
823     case 0xc0: res= inst_push(code); break;
824     case 0xc2: res= inst_clr_bit(code); break;
825     case 0xc3: res= inst_clr_c(code); break;
826     case 0xc4: res= inst_swap(code); break;
827     case 0xc5: res= inst_xch_a_addr(code); break;
828     case 0xc6: case 0xc7: res= inst_xch_a_$ri(code); break;
829     case 0xc8: case 0xc9: case 0xca: case 0xcb:
830     case 0xcc: case 0xcd: case 0xce: case 0xcf: res= inst_xch_a_rn(code);break;
831     case 0xd0: res= inst_pop(code); break;
832     case 0xd2: res= inst_setb_bit(code); break;
833     case 0xd3: res= inst_setb_c(code); break;
834     case 0xd4: res= inst_da_a(code); break;
835     case 0xd5: res= inst_djnz_addr_addr(code); break;
836     case 0xd6: case 0xd7: res= inst_xchd_a_$ri(code); break;
837     case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc:
838     case 0xdd: case 0xde: case 0xdf: res=inst_djnz_rn_addr(code); break;
839     case 0xe0: res= inst_movx_a_$dptr(code); break;
840     case 0xe2: case 0xe3: res= inst_movx_a_$ri(code); break;
841     case 0xe4: res= inst_clr_a(code); break;
842     case 0xe5: res= inst_mov_a_addr(code); break;
843     case 0xe6: case 0xe7: res= inst_mov_a_$ri(code); break;
844     case 0xe8: case 0xe9: case 0xea: case 0xeb:
845     case 0xec: case 0xed: case 0xee: case 0xef: res= inst_mov_a_rn(code);break;
846     case 0xf0: res= inst_movx_$dptr_a(code); break;
847     case 0xf2: case 0xf3: res= inst_movx_$ri_a(code); break;
848     case 0xf4: res= inst_cpl_a(code); break;
849     case 0xf5: res= inst_mov_addr_a(code); break;
850     case 0xf6: case 0xf7: res= inst_mov_$ri_a(code); break;
851     case 0xf8: case 0xf9: case 0xfa: case 0xfb:
852     case 0xfc: case 0xfd: case 0xfe: case 0xff: res= inst_mov_rn_a(code);break;
853     default:
854       res= inst_unknown(code);
855       break;
856     }
857   //post_inst();
858   return(res);
859 }
860
861
862 /*
863  * Simulating execution of next instruction
864  *
865  * This is an endless loop if requested number of steps is negative.
866  * In this case execution is stopped if an instruction results other
867  * status than GO. Execution can be stopped if `cmd_in' is not NULL
868  * and there is input available on that file. It is usefull if the
869  * command console is on a terminal. If input is available then a
870  * complete line is read and dropped out because input is buffered
871  * (inp_avail will be TRUE if ENTER is pressed) and it can confuse
872  * command interepter.
873  */
874
875 int
876 t_uc51::do_inst(int step)
877 {
878   result= resGO;
879   while ((result == resGO) &&
880          (state != stPD) &&
881          (step != 0))
882     {
883       if (step > 0)
884         step--;
885       if (state == stGO)
886         {
887           was_reti= FALSE;
888           pre_inst();
889           result= exec_inst();
890           post_inst();
891           if (result == resGO)
892             result= check_events();
893         }
894       else
895         {
896           // tick hw in idle state
897           post_inst();
898           tick(1);
899         }
900       if (result == resGO)
901         {
902           int res;
903           if ((res= do_interrupt()) != resGO)
904             result= res;
905           else
906             result= idle_pd();
907         }
908       if ((step < 0) &&
909           ((ticks->ticks % 100000) < 50))
910         {
911           if (sim->cmd->input_avail_on_frozen())
912             {
913               result= resUSER;
914             }
915           else
916             if (sim->cmd->input_avail())
917               break;
918         }
919       if (((result == resINTERRUPT) &&
920            stop_at_it) ||
921           result >= resSTOP)
922         {
923           sim->stop(result);
924           break;
925         }
926     }
927   if (state == stPD)
928     {
929       //FIXME: tick outsiders eg. watchdog
930       if (sim->cmd->input_avail_on_frozen())
931         {
932           //fprintf(stderr,"uc: inp avail in PD mode, user stop\n");
933           result= resUSER;
934           sim->stop(result); 
935         }
936     }
937   return(result);
938 }
939
940 void
941 t_uc51::post_inst(void)
942 {
943   uint tcon= sfr->get(TCON);
944   uint p3= sfr->get(P3);
945
946   set_p_flag();
947
948   // Read of SBUF must be serial input data
949   sfr->set(SBUF, s_in);
950
951   // Setting up external interrupt request bits (IEx)
952   if ((tcon & bmIT0))
953     {
954       // IE0 edge triggered
955       if ((prev_p3 & bm_INT0) &&
956           !(p3 & port_pins[3] & bm_INT0))
957         // falling edge on INT0
958         {
959           sim->cmd->debug("%g sec (%d clks): "
960                           "Falling edge detected on INT0 (P3.2)\n",
961                           get_rtime(), ticks->ticks);
962           sfr->set_bit1(TCON, bmIE0);
963         }
964     }
965   else
966     {
967       // IE0 level triggered
968       if (p3 & port_pins[3] & bm_INT0)
969         sfr->set_bit0(TCON, bmIE0);
970       else
971         sfr->set_bit1(TCON, bmIE0);
972     }
973   if ((tcon & bmIT1))
974     {
975       // IE1 edge triggered
976       if ((prev_p3 & bm_INT1) &&
977           !(p3 & port_pins[3] & bm_INT1))
978         // falling edge on INT1
979         sfr->set_bit1(TCON, bmIE1);
980     }
981   else
982     {
983       // IE1 level triggered
984       if (p3 & port_pins[3] & bm_INT1)
985         sfr->set_bit0(TCON, bmIE1);
986       else
987         sfr->set_bit1(TCON, bmIE1);
988     }
989   prev_p3= p3 & port_pins[3];
990   prev_p1= p3 & port_pins[1];
991 }
992
993
994 /*
995  * Setting up parity flag
996  */
997
998 void
999 t_uc51::set_p_flag(void)
1000 {
1001   bool p;
1002   int i;
1003   uchar uc;
1004
1005   p = FALSE;
1006   uc= sfr->get(ACC);
1007   for (i= 0; i < 8; i++)
1008     {
1009       if (uc & 1)
1010         p= !p;
1011       uc>>= 1;
1012     }
1013   SET_BIT(p, PSW, bmP);
1014 }
1015
1016 /*
1017  * Simulating hardware elements
1018  */
1019
1020 int
1021 t_uc51::do_hardware(int cycles)
1022 {
1023   int res;
1024
1025   if ((res= do_timers(cycles)) != resGO)
1026     return(res);
1027   if ((res= do_serial(cycles)) != resGO)
1028     return(res);
1029   return(do_wdt(cycles));
1030 }
1031
1032
1033 /*
1034  *
1035  */
1036
1037 int
1038 t_uc51::serial_bit_cnt(int mode)
1039 {
1040   int /*mode,*/ divby= 12;
1041   int *tr_src= 0, *rec_src= 0;
1042
1043   //mode= sfr->get(SCON) >> 6;
1044   switch (mode)
1045     {
1046     case 0:
1047       divby  = 12;
1048       tr_src = &s_tr_tick;
1049       rec_src= &s_rec_tick;
1050       break;
1051     case 1:
1052     case 3:
1053       divby  = (sfr->get(PCON)&bmSMOD)?16:32;
1054       tr_src = &s_tr_t1;
1055       rec_src= &s_rec_t1;
1056       break;
1057     case 2:
1058       divby  = (sfr->get(PCON)&bmSMOD)?16:32;
1059       tr_src = &s_tr_tick;
1060       rec_src= &s_rec_tick;
1061       break;
1062     }
1063   if (s_sending)
1064     {
1065       while (*tr_src >= divby)
1066         {
1067           (*tr_src)-= divby;
1068           s_tr_bit++;
1069         }
1070     }
1071   if (s_receiving)
1072     {
1073       while (*rec_src >= divby)
1074         {
1075           (*rec_src)-= divby;
1076           s_rec_bit++;
1077         }
1078     }
1079   return(0);
1080 }
1081
1082
1083 /*
1084  * Simulating serial line
1085  */
1086
1087 int
1088 t_uc51::do_serial(int cycles)
1089 {
1090   int mode, bits= 8;
1091   char c;
1092   uint scon= sfr->get(SCON);
1093
1094   mode= scon >> 6;
1095   switch (mode)
1096     {
1097     case 0:
1098       bits= 8;
1099       break;
1100     case 1:
1101       bits= 10;
1102       break;
1103     case 2:
1104     case 3:
1105       bits= 11;
1106       break;
1107     }
1108   serial_bit_cnt(mode);
1109   if (s_sending &&
1110       (s_tr_bit >= bits))
1111     {
1112       s_sending= FALSE;
1113       sfr->set_bit1(SCON, bmTI);
1114       if (serial_out)
1115         {
1116           putc(s_out, serial_out);
1117           fflush(serial_out);
1118         }
1119       s_tr_bit-= bits;
1120     }
1121   if ((scon & bmREN) &&
1122       serial_in &&
1123       !s_receiving)
1124     {
1125       fd_set set; static struct timeval timeout= {0,0};
1126       FD_ZERO(&set);
1127       FD_SET(fileno(serial_in), &set);
1128       int i= select(fileno(serial_in)+1, &set, NULL, NULL, &timeout);
1129       if (i > 0 &&
1130           FD_ISSET(fileno(serial_in), &set))
1131         {
1132           s_receiving= TRUE;
1133           s_rec_bit= 0;
1134           s_rec_tick= s_rec_t1= 0;
1135         }
1136     }
1137   if (s_receiving &&
1138       (s_rec_bit >= bits))
1139     {
1140       if (::read(fileno(serial_in), &c, 1) == 1)
1141         {
1142           s_in= c;
1143           sfr->set(SBUF, s_in);
1144           received(c);
1145         }
1146       s_receiving= FALSE;
1147       s_rec_bit-= bits;
1148     }
1149   return(resGO);
1150 }
1151
1152 void
1153 t_uc51::received(int c)
1154 {
1155   sfr->set_bit1(SCON, bmRI);
1156 }
1157
1158
1159 /*
1160  * Simulating timers
1161  */
1162
1163 int
1164 t_uc51::do_timers(int cycles)
1165 {
1166   int res;
1167
1168   if ((res= do_timer0(cycles)) != resGO)
1169     return(res);
1170   return(do_timer1(cycles));
1171 }
1172
1173
1174 /*
1175  * Simulating timer 0
1176  */
1177
1178 int
1179 t_uc51::do_timer0(int cycles)
1180 {
1181   uint tmod= sfr->get(TMOD);
1182   uint tcon= sfr->get(TCON);
1183   uint p3= sfr->get(P3);
1184
1185   if (((tmod & bmGATE0) &&
1186        (p3 & port_pins[3] & bm_INT0)) ||
1187       (tcon & bmTR0))
1188     {
1189       if (!(tmod & bmC_T0) ||
1190           ((prev_p3 & bmT0) &&
1191            !(p3 & port_pins[3] & bmT0)))
1192         {
1193           if (!(tmod & bmM00) &&
1194               !(tmod & bmM10))
1195             {
1196               if (tmod & bmC_T0)
1197                 cycles= 1;
1198               while (cycles--)
1199                 {
1200                   // mod 0, TH= 8 bit t/c, TL= 5 bit precounter
1201                   (MEM(MEM_SFR)[TL0])++;
1202                   if (sfr->get(TL0) > 0x1f)
1203                     {
1204                       sfr->set_bit0(TL0, ~0x1f);
1205                       if (!++(MEM(MEM_SFR)[TH0]))
1206                         {
1207                           sfr->set_bit1(TCON, bmTF0);
1208                           t0_overflow();
1209                         }
1210                     }
1211                 }
1212             }
1213           else if ((tmod & bmM00) &&
1214                    !(tmod & bmM10))
1215             {
1216               if (tmod & bmC_T0)
1217                 cycles= 1;
1218               while (cycles--)
1219                 {
1220                   // mod 1 TH+TL= 16 bit t/c
1221                   if (!++(MEM(MEM_SFR)[TL0]))
1222                     {
1223                       if (!++(MEM(MEM_SFR)[TH0]))
1224                         {
1225                           sfr->set_bit1(TCON, bmTF0);
1226                           t0_overflow();
1227                         }
1228                     }
1229                 }
1230             }
1231           else if (!(tmod & bmM00) &&
1232                    (tmod & bmM10))
1233             {
1234               if (tmod & bmC_T0)
1235                 cycles= 1;
1236               while (cycles--)
1237                 {
1238                   // mod 2 TL= 8 bit t/c auto reload from TH
1239                   if (!++(MEM(MEM_SFR)[TL0]))
1240                     {
1241                       sfr->set(TL0, sfr->get(TH0));
1242                       sfr->set_bit1(TCON, bmTF0);
1243                       t0_overflow();
1244                     }
1245                 }
1246             }
1247           else
1248             {
1249               // mod 3 TL= 8 bit t/c
1250               //       TH= 8 bit timer controlled with T1's bits
1251               if (!++(MEM(MEM_SFR)[TL0]))
1252                 {
1253                   sfr->set_bit1(TCON, bmTF0);
1254                   t0_overflow();
1255                 }
1256             }
1257         }
1258     }
1259   if ((tmod & bmM00) &&
1260       (tmod & bmM10))
1261     {
1262       if (((tmod & bmGATE1) &&
1263            (p3 & port_pins[3] & bm_INT1)) ||
1264           (tcon & bmTR1))
1265         {
1266           if (!++(MEM(MEM_SFR)[TH0]))
1267             {
1268               sfr->set_bit1(TCON, bmTF1);
1269               s_tr_t1++;
1270               s_rec_t1++;
1271               t0_overflow();
1272             }
1273         }
1274     }
1275   return(resGO);
1276 }
1277
1278 /*
1279  * Called every time when T0 overflows
1280  */
1281
1282 int
1283 t_uc51::t0_overflow(void)
1284 {
1285   return(0);
1286 }
1287
1288
1289 /*
1290  * Simulating timer 1
1291  */
1292
1293 int
1294 t_uc51::do_timer1(int cycles)
1295 {
1296   uint tmod= sfr->get(TMOD);
1297   uint tcon= sfr->get(TCON);
1298   uint p3= sfr->get(P3);
1299
1300   if (((tmod & bmGATE1) &&
1301        (p3 & port_pins[3] & bm_INT1)) ||
1302       (tcon & bmTR1))
1303     {
1304       if (!(tmod & bmC_T1) ||
1305           ((prev_p3 & bmT1) &&
1306            !(p3 & port_pins[3] & bmT1)))
1307         {
1308           if (!(tmod & bmM01) &&
1309               !(tmod & bmM11))
1310             {
1311               if (tmod & bmC_T0)
1312                 cycles= 1;
1313               while (cycles--)
1314                 {
1315                   // mod 0, TH= 8 bit t/c, TL= 5 bit precounter
1316                   if (++(MEM(MEM_SFR)[TL1]) > 0x1f)
1317                     {
1318                       sfr->set_bit0(TL1, ~0x1f);
1319                       if (!++(MEM(MEM_SFR)[TH1]))
1320                         {
1321                           sfr->set_bit1(TCON, bmTF1);
1322                           s_tr_t1++;
1323                           s_rec_t1++;
1324                         }
1325                     }
1326                 }
1327             }
1328           else if ((tmod & bmM01) &&
1329                    !(tmod & bmM11))
1330             {
1331               if (tmod & bmC_T0)
1332                 cycles= 1;
1333               while (cycles--)
1334                 {
1335                   // mod 1 TH+TL= 16 bit t/c
1336                   if (!++(MEM(MEM_SFR)[TL1]))
1337                     if (!++(MEM(MEM_SFR)[TH1]))
1338                       {
1339                         sfr->set_bit1(TCON, bmTF1);
1340                         s_tr_t1++;
1341                         s_rec_t1++;
1342                       }
1343                 }
1344             }
1345           else if (!(tmod & bmM01) &&
1346                    (tmod & bmM11))
1347             {
1348               if (tmod & bmC_T1)
1349                 cycles= 1;
1350               while (cycles--)
1351                 {
1352                   // mod 2 TL= 8 bit t/c auto reload from TH
1353                   if (!++(MEM(MEM_SFR)[TL1]))
1354                     {
1355                       sfr->set(TL1, sfr->get(TH1));
1356                       sfr->set_bit1(TCON, bmTF1);
1357                       s_tr_t1++;
1358                       s_rec_t1++;
1359                     }
1360                 }
1361             }
1362           else
1363             // mod 3 stop
1364             ;
1365         }
1366     }
1367   return(resGO);
1368 }
1369
1370
1371 /*
1372  * Abstract method to handle WDT
1373  */
1374
1375 int
1376 t_uc51::do_wdt(int cycles)
1377 {
1378   return(resGO);
1379 }
1380
1381
1382 /*
1383  * Checking for interrupt requests and accept one if needed
1384  */
1385
1386 int
1387 t_uc51::do_interrupt(void)
1388 {
1389   int i, ie= 0;
1390
1391   if (was_reti)
1392     {
1393       was_reti= FALSE;
1394       return(resGO);
1395     }
1396   if (!((ie= sfr->get(IE)) & bmEA))
1397     return(resGO);
1398   class it_level *il= (class it_level *)(it_levels->top()), *IL= 0;
1399   for (i= 0; i < it_sources->count; i++)
1400     {
1401       class cl_it_src *is= (class cl_it_src *)(it_sources->at(i));
1402       if (is->is_active() &&
1403           (ie & is->ie_mask) &&
1404           (sfr->get(is->src_reg) & is->src_mask))
1405         {
1406           int pr= it_priority(is->ie_mask);
1407           if (il->level >= 0 &&
1408               pr <= il->level)
1409             continue;
1410           if (state == stIDLE)
1411             {
1412               state= stGO;
1413               sfr->set_bit0(PCON, bmIDL);
1414               was_reti= 1;
1415               return(resGO);
1416             }
1417           if (is->clr_bit)
1418             sfr->set_bit0(is->src_reg, is->src_mask);
1419           sim->cmd->debug("%g sec (%d clks): "
1420                           "Accepting interrupt `%s' PC= 0x%06x\n",
1421                           get_rtime(), ticks->ticks, is->name, PC);
1422           IL= new it_level(pr, is->addr, PC, is);
1423           return(accept_it(IL));
1424         }
1425     }
1426   return(resGO);
1427 }
1428
1429 int
1430 t_uc51::it_priority(uchar ie_mask)
1431 {
1432   if (sfr->get(IP) & ie_mask)
1433     return(1);
1434   return(0);
1435 }
1436
1437
1438 /*
1439  * Accept an interrupt
1440  */
1441
1442 int
1443 t_uc51::accept_it(class it_level *il)
1444 {
1445   state= stGO;
1446   sfr->set_bit0(PCON, bmIDL);
1447   it_levels->push(il);
1448   tick(1);
1449   int res= inst_lcall(0, il->addr);
1450   if (res != resGO)
1451     return(res);
1452   else
1453     return(resINTERRUPT);
1454 }
1455
1456
1457 /*
1458  * Checking if Idle or PowerDown mode should be activated
1459  */
1460
1461 int
1462 t_uc51::idle_pd(void)
1463 {
1464   uint pcon= sfr->get(PCON);
1465
1466   if (technology != CPU_CMOS)
1467     return(resGO);
1468   if (pcon & bmIDL)
1469     {
1470       if (state != stIDLE)
1471         sim->cmd->debug("%g sec (%d clks): CPU in Idle mode\n",
1472                         get_rtime(), ticks->ticks);
1473       state= stIDLE;
1474       //was_reti= 1;
1475     }
1476   if (pcon & bmPD)
1477     {
1478       if (state != stPD)
1479         sim->cmd->debug("%g sec (%d clks): CPU in PowerDown mode\n",
1480                         get_rtime(), ticks->ticks);
1481       state= stPD;
1482     }
1483   return(resGO);
1484 }
1485
1486
1487 /*
1488  * Checking if EVENT break happened
1489  */
1490
1491 int
1492 t_uc51::check_events(void)
1493 {
1494   int i;
1495   class cl_ev_brk *eb;
1496
1497   if (!ebrk->count)
1498     return(resGO);
1499   for (i= 0; i < ebrk->count; i++)
1500     {
1501       eb= (class cl_ev_brk *)(ebrk->at(i));
1502       if (eb->match(&event_at))
1503         return(resBREAKPOINT);
1504     }
1505   return(resGO);
1506 }
1507
1508
1509 /*
1510  * Simulating an unknown instruction
1511  *
1512  * Normally this function is called for unimplemented instructions, because
1513  * every instruction must be known!
1514  */
1515
1516 int
1517 t_uc51::inst_unknown(uchar code)
1518 {
1519   PC--;
1520   if (1)//debug)// && sim->cmd_out())
1521     sim->cmd->debug("Unknown instruction %02x at %06x\n", code, PC);
1522   return(resHALT);
1523 }
1524
1525
1526 /*
1527  * 0x00 1 12 NOP
1528  */
1529
1530 int
1531 t_uc51::inst_nop(uchar code)
1532 {
1533   return(resGO);
1534 }
1535
1536
1537 /*
1538  * 0xe4 1 12 CLR A
1539  */
1540
1541 int
1542 t_uc51::inst_clr_a(uchar code)
1543 {
1544   ulong d= 0;
1545
1546   sfr->write(ACC, &d);
1547   return(resGO);
1548 }
1549
1550
1551 /*
1552  * 0xc4 1 1 SWAP A
1553  */
1554
1555 int
1556 t_uc51::inst_swap(uchar code)
1557 {
1558   uchar temp;
1559
1560   temp= (sfr->read(ACC) >> 4) & 0x0f;
1561   sfr->set(ACC, (sfr->get(ACC) << 4) | temp);
1562   return(resGO);
1563 }
1564
1565
1566 /* End of s51.src/uc51.cc */