* sim/ucsim/configure, sim/ucsim/cmd.src/newcmdcl.h,
[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 #ifdef HAVE_TERMIOS_H
34 #include <termios.h>
35 #endif
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 #include <fcntl.h>
40 #include <errno.h>
41 #include <sys/types.h>
42 #include <sys/time.h>
43 #if FD_HEADER_OK
44 # include HEADER_FD
45 #endif
46 #include "i_string.h"
47
48 // prj
49 #include "utils.h"
50 #include "globals.h"
51
52 // sim
53 #include "optioncl.h"
54
55 //cmd.src
56 #include "cmduccl.h"
57
58 // local
59 #include "uc51cl.h"
60 #include "glob.h"
61 #include "regs51.h"
62 #include "timer0cl.h"
63 #include "timer1cl.h"
64 #include "serialcl.h"
65 #include "portcl.h"
66 #include "interruptcl.h"
67 #include "types51.h"
68
69
70 /*
71  * Options of uc51
72  */
73
74 cl_irq_stop_option::cl_irq_stop_option(class cl_51core *the_uc51):
75   cl_optref(the_uc51)
76 {
77   uc51= the_uc51;
78 }
79
80 int
81 cl_irq_stop_option::init(void)
82 {
83   cl_optref::init();
84   create(uc51, bool_opt, "irq_stop", "Stop when IRQ accepted");
85   return(0);
86 }
87
88 void
89 cl_irq_stop_option::option_changed(void)
90 {
91   if (!uc51)
92     return;
93   bool b;
94   option->get_value(&b);
95   uc51->stop_at_it= b;
96 }
97
98
99 /*
100  * Making a new micro-controller and reset it
101  */
102
103 cl_51core::cl_51core(int Itype, int Itech, class cl_sim *asim):
104   cl_uc(asim)
105 {
106   type= Itype;
107   technology= Itech;
108
109   irq_stop_option= new cl_irq_stop_option(this);
110   stop_at_it= DD_FALSE;
111 }
112
113
114 /*
115  * Initializing. Virtual calls go here
116  * This method must be called first after object creation.
117  */
118
119 int
120 cl_51core::init(void)
121 {
122   irq_stop_option->init();
123   cl_uc::init();
124   set_name("mcs51_controller");
125   reset();
126   return(0);
127 }
128
129 static char id_string_51[100];
130
131 char *
132 cl_51core::id_string(void)
133 {
134   int i;
135
136   for (i= 0; cpus_51[i].type_str != NULL && cpus_51[i].type != type; i++) ;
137   sprintf(id_string_51, "%s %s",
138           cpus_51[i].type_str?cpus_51[i].type_str:"51",
139           (technology==CPU_HMOS)?"HMOS":"CMOS");
140   return(id_string_51);
141 }
142
143 void
144 cl_51core::mk_hw_elements(void)
145 {
146   class cl_hw *h;
147
148   acc= sfr->get_cell(ACC);
149   psw= sfr->get_cell(PSW);
150
151   hws->add(h= new cl_timer0(this, 0, "timer0"));
152   h->init();
153   hws->add(h= new cl_timer1(this, 1, "timer1"));
154   h->init();
155 #ifdef HAVE_TERMIOS_H
156   hws->add(h= new cl_serial(this));
157   h->init();
158 #endif
159   hws->add(h= new cl_port(this, 0));
160   h->init();
161   hws->add(h= new cl_port(this, 1));
162   h->init();
163   hws->add(h= new cl_port(this, 2));
164   h->init();
165   hws->add(h= new cl_port(this, 3));
166   h->init();
167   hws->add(interrupt= new cl_interrupt(this));
168   interrupt->init();
169   hws->add(h= new cl_uc51_dummy_hw(this));
170   h->init();
171   /*
172   acc= sfr->get_cell(ACC);
173   psw= sfr->get_cell(PSW);
174   */
175 }
176
177 void
178 cl_51core::build_cmdset(class cl_cmdset *cmdset)
179 {
180   class cl_cmd *cmd;
181   //class cl_super_cmd *super_cmd;
182   //class cl_cmdset *cset;
183
184   cl_uc::build_cmdset(cmdset);
185
186   cmdset->add(cmd= new cl_di_cmd("di", DD_TRUE,
187 "di [start [stop]]  Dump Internal RAM",
188 "long help of di"));
189   cmd->init();
190
191   cmdset->add(cmd= new cl_dx_cmd("dx", DD_TRUE,
192 "dx [start [stop]]  Dump External RAM",
193 "long help of dx"));
194   cmd->init();
195
196   cmdset->add(cmd= new cl_ds_cmd("ds", DD_TRUE,
197 "ds [start [stop]]  Dump SFR",
198 "long help of ds"));
199   cmd->init();
200 }
201
202 /*
203 class cl_m *
204 cl_51core::mk_mem(enum mem_class type, char *class_name)
205 {
206   class cl_address_space *m= cl_uc::mk_mem(type, class_name);
207   if (type == MEM_SFR)
208     sfr= m;
209   if (type == MEM_IRAM)
210     iram= m;
211   return(m);
212 }
213 */
214
215 void
216 cl_51core::make_memories(void)
217 {
218   class cl_address_space *as;
219
220   rom= as= new cl_address_space(MEM_ROM_ID/*"rom"*/, 0, 0x10000, 8);
221   as->init();
222   address_spaces->add(as);
223   iram= as= new cl_address_space(MEM_IRAM_ID/*"iram"*/, 0, 0x80, 8);
224   as->init();
225   address_spaces->add(as);
226   sfr= as= new cl_address_space(MEM_SFR_ID/*"sfr"*/, 0x80, 0x80, 8);
227   as->init();
228   address_spaces->add(as);
229   xram= as= new cl_address_space(MEM_XRAM_ID/*"xram"*/, 0, 0x10000, 8);
230   as->init();
231   address_spaces->add(as);
232
233   class cl_address_decoder *ad;
234   class cl_memory_chip *chip;
235
236   chip= new cl_memory_chip("rom_chip", 0x10000, 8/*, 0xff*/);
237   chip->init();
238   memchips->add(chip);
239   ad= new cl_address_decoder(as= rom/*address_space(MEM_ROM_ID)*/,
240                              chip, 0, 0xffff, 0);
241   ad->init();
242   as->decoders->add(ad);
243   ad->activate(0);
244
245   chip= new cl_memory_chip("iram_chip", 0x80, 8);
246   chip->init();
247   memchips->add(chip);
248   ad= new cl_address_decoder(as= iram/*address_space(MEM_IRAM_ID)*/,
249                              chip, 0, 0x7f, 0);
250   ad->init();
251   as->decoders->add(ad);
252   ad->activate(0);
253
254   chip= new cl_memory_chip("xram_chip", 0x10000, 8);
255   chip->init();
256   memchips->add(chip);
257   ad= new cl_address_decoder(as= xram/*address_space(MEM_XRAM_ID)*/,
258                              chip, 0, 0xffff, 0);
259   ad->init();
260   as->decoders->add(ad);
261   ad->activate(0);
262
263   chip= new cl_memory_chip("sfr_chip", 0x80, 8, 0);
264   chip->init();
265   memchips->add(chip);
266   ad= new cl_address_decoder(as= sfr/*address_space(MEM_SFR_ID)*/,
267                              chip, 0x80, 0xff, 0);
268   ad->init();
269   as->decoders->add(ad);
270   ad->activate(0);
271
272   acc= sfr->get_cell(ACC);
273   psw= sfr->get_cell(PSW);
274 }
275
276
277 /*
278  * Destroying the micro-controller object
279  */
280
281 cl_51core::~cl_51core(void)
282 {
283   /*
284   if (serial_out)
285     {
286       if (isatty(fileno(serial_out)))
287         tcsetattr(fileno(serial_out), TCSANOW, &saved_attributes_out);
288       fclose(serial_out);
289     }
290   if (serial_in)
291     {
292       if (isatty(fileno(serial_in)))
293         tcsetattr(fileno(serial_in), TCSANOW, &saved_attributes_in);
294       fclose(serial_in);
295     }
296   */
297   delete irq_stop_option;
298 }
299
300
301 /*
302  * Disassembling an instruction
303  */
304
305 struct dis_entry *
306 cl_51core::dis_tbl(void)
307 {
308   return(disass_51);
309 }
310
311 struct name_entry *
312 cl_51core::sfr_tbl(void)
313 {
314   return(sfr_tab51);
315 }
316
317 struct name_entry *
318 cl_51core::bit_tbl(void)
319 {
320   return(bit_tab51);
321 }
322
323 char *
324 cl_51core::disass(t_addr addr, char *sep)
325 {
326   char work[256], temp[20], c[2];
327   char *buf, *p, *b, *t;
328   t_mem code= rom->get(addr);
329
330   p= work;
331   b= dis_tbl()[code].mnemonic;
332   while (*b)
333     {
334       if (*b == '%')
335         {
336           b++;
337           switch (*(b++))
338             {
339             case 'A': // absolute address
340               sprintf(temp, "%04"_A_"x",
341                       t_addr((addr&0xf800)|
342                              (((code>>5)&0x07)*256 +
343                               rom->get(addr+1))));
344               break;
345             case 'l': // long address
346               sprintf(temp, "%04"_A_"x",
347                       t_addr(rom->get(addr+1)*256 +
348                              rom->get(addr+2)));
349               break;
350             case 'a': // addr8 (direct address) at 2nd byte
351               if (!get_name(rom->get(addr+1), sfr_tbl(), temp))
352                 sprintf(temp, "%02"_M_"x", rom->get(addr+1));
353               break;
354             case '8': // addr8 (direct address) at 3rd byte
355               if (!get_name(rom->get(addr+2), sfr_tbl(), temp))
356                 sprintf(temp, "%02"_M_"x", rom->get(addr+2));
357               //sprintf(temp, "%02"_M_"x", rom->get(addr+2));
358               break;
359             case 'b': // bitaddr at 2nd byte
360               {
361                 t_addr ba= rom->get(addr+1);
362                 if (get_name(ba, bit_tbl(), temp))
363                   break;
364                 if (get_name((ba<128)?((ba/8)+32):(ba&0xf8), sfr_tbl(), temp))
365                   {
366                     strcat(temp, ".");
367                     sprintf(c, "%1"_M_"d", ba & 0x07);
368                     strcat(temp, c);
369                     break;
370                   }
371                 sprintf(temp, "%02x.%"_M_"d", (ba<128)?((ba/8)+32):(ba&0xf8),
372                         ba & 0x07);
373                 break;
374               }
375             case 'r': // rel8 address at 2nd byte
376               sprintf(temp, "%04"_A_"x",
377                       t_addr(addr+2+(signed char)(rom->get(addr+1))));
378               break;
379             case 'R': // rel8 address at 3rd byte
380               sprintf(temp, "%04"_A_"x",
381                       t_addr(addr+3+(signed char)(rom->get(addr+2))));
382               break;
383             case 'd': // data8 at 2nd byte
384               sprintf(temp, "%02"_M_"x", rom->get(addr+1));
385               break;
386             case 'D': // data8 at 3rd byte
387               sprintf(temp, "%02"_M_"x", rom->get(addr+2));
388               break;
389             case '6': // data16 at 2nd(H)-3rd(L) byte
390               sprintf(temp, "%04"_A_"x",
391                       t_addr(rom->get(addr+1)*256 +
392                              rom->get(addr+2)));
393               break;
394             default:
395               strcpy(temp, "?");
396               break;
397             }
398           t= temp;
399           while (*t)
400             *(p++)= *(t++);
401         }
402       else
403         *(p++)= *(b++);
404     }
405   *p= '\0';
406
407   p= strchr(work, ' ');
408   if (!p)
409     {
410       buf= strdup(work);
411       return(buf);
412     }
413   if (sep == NULL)
414     buf= (char *)malloc(6+strlen(p)+1);
415   else
416     buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
417   for (p= work, b= buf; *p != ' '; p++, b++)
418     *b= *p;
419   p++;
420   *b= '\0';
421   if (sep == NULL)
422     {
423       while (strlen(buf) < 6)
424         strcat(buf, " ");
425     }
426   else
427     strcat(buf, sep);
428   strcat(buf, p);
429   return(buf);
430 }
431
432
433 void
434 cl_51core::print_regs(class cl_console *con)
435 {
436   t_addr start;
437   uchar data;
438
439   start= psw->get() & 0x18;
440   //dump_memory(iram, &start, start+7, 8, /*sim->cmd_out()*/con, sim);
441   iram->dump(start, start+7, 8, con);
442   start= psw->get() & 0x18;
443   data= iram->get(iram->get(start));
444   con->dd_printf("%06x %02x %c",
445               iram->get(start), data, isprint(data)?data:'.');
446
447   con->dd_printf("  ACC= 0x%02x %3d %c  B= 0x%02x", sfr->get(ACC), sfr->get(ACC),
448               isprint(sfr->get(ACC))?(sfr->get(ACC)):'.', sfr->get(B)); 
449   //eram2xram();
450   data= xram->get(sfr->get(DPH)*256+sfr->get(DPL));
451   con->dd_printf("   DPTR= 0x%02x%02x @DPTR= 0x%02x %3d %c\n", sfr->get(DPH),
452               sfr->get(DPL), data, data, isprint(data)?data:'.');
453
454   data= iram->get(iram->get(start+1));
455   con->dd_printf("%06x %02x %c", iram->get(start+1), data,
456               isprint(data)?data:'.');
457   data= psw->get();
458   con->dd_printf("  PSW= 0x%02x CY=%c AC=%c OV=%c P=%c\n", data,
459               (data&bmCY)?'1':'0', (data&bmAC)?'1':'0',
460               (data&bmOV)?'1':'0', (data&bmP)?'1':'0');
461
462   print_disass(PC, con);
463 }
464
465
466 /*
467  * Converting bit address into real memory
468  */
469
470 class cl_address_space *
471 cl_51core::bit2mem(t_addr bitaddr, t_addr *memaddr, t_mem *bitmask)
472 {
473   class cl_address_space *m;
474   t_addr ma;
475
476   bitaddr&= 0xff;
477   if (bitaddr < 128)
478     {
479       m= iram;
480       ma= bitaddr/8 + 0x20;
481     }
482   else
483     {
484       m= sfr;
485       ma= bitaddr & 0xf8;
486     }
487   if (memaddr)
488     *memaddr= ma;
489   if (bitmask)
490     *bitmask= 1 << (bitaddr & 0x7);
491   return(m);
492 }
493
494 t_addr
495 cl_51core::bit_address(class cl_memory *mem,
496                        t_addr mem_address, int bit_number)
497 {
498   if (bit_number < 0 ||
499       bit_number > 7 ||
500       mem_address < 0)
501     return(-1);
502   class cl_memory *sfrchip= memory("sfr_chip");
503   if (mem == sfrchip)
504     {
505       mem= sfr;
506       mem_address+= sfr->start_address;
507     }
508   if (mem == sfr)
509     {
510       if (mem_address < 128 ||
511           mem_address % 8 != 0 ||
512           mem_address > 255)
513         return(-1);
514       return(128 + (mem_address-128) + bit_number);
515     }
516   if (mem == iram)
517     {
518       if (mem_address < 0x20 ||
519           mem_address >= 0x20+32)
520         return(-1);
521       return((mem_address-0x20)*8 + bit_number);
522     }
523   return(-1);
524 }
525
526
527 /*
528  * Resetting the micro-controller
529  */
530
531 void
532 cl_51core::reset(void)
533 {
534   cl_uc::reset();
535
536   clear_sfr();
537
538   result= resGO;
539
540   //was_reti= DD_FALSE;
541 }
542
543
544 /*
545  * Setting up SFR area to reset value
546  */
547
548 void
549 cl_51core::clear_sfr(void)
550 {
551   int i;
552   
553   for (i= 0x80; i <= 0xff; i++)
554     sfr->set(i, 0);
555   sfr->/*set*/write(P0, 0xff);
556   sfr->/*set*/write(P1, 0xff);
557   sfr->/*set*/write(P2, 0xff);
558   sfr->/*set*/write(P3, 0xff);
559   prev_p1= /*port_pins[1] &*/ sfr->/*get*/read(P1);
560   prev_p3= /*port_pins[3] &*/ sfr->/*get*/read(P3);
561   sfr->write(ACC, 0);
562   sfr->write(B, 0);
563   sfr->write(PSW, 0);
564   sfr->write(SP, 7);
565   sfr->write(DPL, 0);
566   sfr->write(DPH, 0);
567   sfr->write(IP, 0);
568   sfr->write(IE, 0);
569   sfr->write(TMOD, 0);
570   sfr->write(TCON, 0);
571   sfr->write(TH0, 0);
572   sfr->write(TL0, 0);
573   sfr->write(TH1, 0);
574   sfr->write(TL1, 0);
575   sfr->write(SCON, 0);
576   sfr->write(PCON, 0);
577
578   sfr->set_nuof_writes(0);
579   sfr->set_nuof_reads(0);
580 }
581
582
583 /*
584  * Analyzing code and settig up instruction map
585  */
586
587 void
588 cl_51core::analyze(t_addr addr)
589 {
590   uint code;
591   struct dis_entry *tabl;
592
593   code= rom->get(addr);
594   tabl= &(dis_tbl()[code]);
595   while (!inst_at(addr) &&
596          code != 0xa5 /* break point */)
597     {
598       set_inst_at(addr);
599       switch (tabl->branch)
600         {
601         case 'a': // acall
602           analyze((addr & 0xf800)|
603                   ((rom->get(addr+1)&0x07)*256+
604                    rom->get(addr+2)));
605           analyze(addr+tabl->length);
606           break;
607         case 'A': // ajmp
608           addr= (addr & 0xf800)|
609             ((rom->get(addr+1) & 0x07)*256 + rom->get(addr+2));
610           break;
611         case 'l': // lcall
612           analyze(rom->get(addr+1)*256 + rom->get(addr+2));
613           analyze(addr+tabl->length);
614           break;
615         case 'L': // ljmp
616           addr= rom->get(addr+1)*256 + rom->get(addr+2);
617           break;
618         case 'r': // reljmp (2nd byte)
619           analyze(rom->validate_address(addr+(signed char)(rom->get(addr+1))));
620           analyze(addr+tabl->length);
621           break;
622         case 'R': // reljmp (3rd byte)
623           analyze(rom->validate_address(addr+(signed char)(rom->get(addr+2))));
624           analyze(addr+tabl->length);
625           break;
626         case 's': // sjmp
627           {
628             signed char target;
629             target= rom->get(addr+1);
630             addr+= 2;
631             addr= rom->validate_address(addr+target);
632             break;
633           }
634         case '_':
635           return;
636         default:
637           addr= rom->validate_address(addr+tabl->length);
638           break;
639         }
640       code= rom->get(addr);
641       tabl= &(dis_tbl()[code]);
642     }
643 }
644
645
646 /*
647  * Inform hardware elements that `cycles' machine cycles have elapsed
648  */
649
650 /*int
651 cl_51core::tick_hw(int cycles)
652 {
653   cl_uc::tick_hw(cycles);
654   //do_hardware(cycles);
655   return(0);
656 }*/
657
658 /*int
659 cl_51core::tick(int cycles)
660 {
661   cl_uc::tick(cycles);
662   //do_hardware(cycles);
663   return(0);
664 }*/
665
666
667 /*
668  * Correcting direct address
669  *
670  * This function returns address of addressed element which can be an IRAM
671  * or an SFR.
672  */
673
674 class cl_memory_cell *
675 cl_51core::get_direct(t_mem addr)
676 {
677   if (addr < sfr->start_address)
678     return(iram->get_cell(addr));
679   else
680     return(sfr->get_cell(addr));
681 }
682
683
684 /*
685  * Calculating address of specified register cell in IRAM
686  */
687
688 class cl_memory_cell *
689 cl_51core::get_reg(uchar regnum)
690 {
691   t_addr a= (psw->get() & (bmRS0|bmRS1)) | (regnum & 0x07);
692   return(iram->get_cell(a));
693 }
694
695
696 /*
697  * Fetching one instruction and executing it
698  */
699
700 int
701 cl_51core::exec_inst(void)
702 {
703   t_mem code;
704   int res= resGO;
705
706   //pr_inst();
707   instPC= PC;
708   if (fetch(&code))
709     return(resBREAKPOINT);
710   //tick_hw(1);
711   tick(1);
712   switch (code)
713     {
714     case 0x00: res= inst_nop(code); break;
715     case 0x01: case 0x21: case 0x41: case 0x61:
716     case 0x81: case 0xa1: case 0xc1: case 0xe1:res=inst_ajmp_addr(code);break;
717     case 0x02: res= inst_ljmp(code); break;
718     case 0x03: res= inst_rr(code); break;
719     case 0x04: res= inst_inc_a(code); break;
720     case 0x05: res= inst_inc_addr(code); break;
721     case 0x06: case 0x07: res= inst_inc_Sri(code); break;
722     case 0x08: case 0x09: case 0x0a: case 0x0b:
723     case 0x0c: case 0x0d: case 0x0e: case 0x0f: res= inst_inc_rn(code); break;
724     case 0x10: res= inst_jbc_bit_addr(code); break;
725     case 0x11: case 0x31: case 0x51: case 0x71:
726     case 0x91: case 0xb1: case 0xd1: case 0xf1:res=inst_acall_addr(code);break;
727     case 0x12: res= inst_lcall(code, 0, DD_FALSE); break;
728     case 0x13: res= inst_rrc(code); break;
729     case 0x14: res= inst_dec_a(code); break;
730     case 0x15: res= inst_dec_addr(code); break;
731     case 0x16: case 0x17: res= inst_dec_Sri(code); break;
732     case 0x18: case 0x19: case 0x1a: case 0x1b:
733     case 0x1c: case 0x1d: case 0x1e: case 0x1f: res= inst_dec_rn(code); break;
734     case 0x20: res= inst_jb_bit_addr(code); break;
735     case 0x22: res= inst_ret(code); break;
736     case 0x23: res= inst_rl(code); break;
737     case 0x24: res= inst_add_a_Sdata(code); break;
738     case 0x25: res= inst_add_a_addr(code); break;
739     case 0x26: case 0x27: res= inst_add_a_Sri(code); break;
740     case 0x28: case 0x29: case 0x2a: case 0x2b:
741     case 0x2c: case 0x2d: case 0x2e: case 0x2f:res= inst_add_a_rn(code);break;
742     case 0x30: res= inst_jnb_bit_addr(code); break;
743     case 0x32: res= inst_reti(code); break;
744     case 0x33: res= inst_rlc(code); break;
745     case 0x34: res= inst_addc_a_Sdata(code); break;
746     case 0x35: res= inst_addc_a_addr(code); break;
747     case 0x36: case 0x37: res= inst_addc_a_Sri(code); break;
748     case 0x38: case 0x39: case 0x3a: case 0x3b:
749     case 0x3c: case 0x3d: case 0x3e: case 0x3f:res= inst_addc_a_rn(code);break;
750     case 0x40: res= inst_jc_addr(code); break;
751     case 0x42: res= inst_orl_addr_a(code); break;
752     case 0x43: res= inst_orl_addr_Sdata(code); break;
753     case 0x44: res= inst_orl_a_Sdata(code); break;
754     case 0x45: res= inst_orl_a_addr(code); break;
755     case 0x46: case 0x47: res= inst_orl_a_Sri(code); break;
756     case 0x48: case 0x49: case 0x4a: case 0x4b:
757     case 0x4c: case 0x4d: case 0x4e: case 0x4f: res= inst_orl_a_rn(code);break;
758     case 0x50: res= inst_jnc_addr(code); break;
759     case 0x52: res= inst_anl_addr_a(code); break;
760     case 0x53: res= inst_anl_addr_Sdata(code); break;
761     case 0x54: res= inst_anl_a_Sdata(code); break;
762     case 0x55: res= inst_anl_a_addr(code); break;
763     case 0x56: case 0x57: res= inst_anl_a_Sri(code); break;
764     case 0x58: case 0x59: case 0x5a: case 0x5b:
765     case 0x5c: case 0x5d: case 0x5e: case 0x5f: res= inst_anl_a_rn(code);break;
766     case 0x60: res= inst_jz_addr(code); break;
767     case 0x62: res= inst_xrl_addr_a(code); break;
768     case 0x63: res= inst_xrl_addr_Sdata(code); break;
769     case 0x64: res= inst_xrl_a_Sdata(code); break;
770     case 0x65: res= inst_xrl_a_addr(code); break;
771     case 0x66: case 0x67: res= inst_xrl_a_Sri(code); break;
772     case 0x68: case 0x69: case 0x6a: case 0x6b:
773     case 0x6c: case 0x6d: case 0x6e: case 0x6f: res= inst_xrl_a_rn(code);break;
774     case 0x70: res= inst_jnz_addr(code); break;
775     case 0x72: res= inst_orl_c_bit(code); break;
776     case 0x73: res= inst_jmp_Sa_dptr(code); break;
777     case 0x74: res= inst_mov_a_Sdata(code); break;
778     case 0x75: res= inst_mov_addr_Sdata(code); break;
779     case 0x76: case 0x77: res= inst_mov_Sri_Sdata(code); break;
780     case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c:
781     case 0x7d: case 0x7e: case 0x7f: res=inst_mov_rn_Sdata(code); break;
782     case 0x80: res= inst_sjmp(code); break;
783     case 0x82: res= inst_anl_c_bit(code); break;
784     case 0x83: res= inst_movc_a_Sa_pc(code); break;
785     case 0x84: res= inst_div_ab(code); break;
786     case 0x85: res= inst_mov_addr_addr(code); break;
787     case 0x86: case 0x87: res= inst_mov_addr_Sri(code); break;
788     case 0x88: case 0x89: case 0x8a: case 0x8b:
789     case 0x8c: case 0x8d: case 0x8e: case 0x8f:res=inst_mov_addr_rn(code);break;
790     case 0x90: res= inst_mov_dptr_Sdata(code); break;
791     case 0x92: res= inst_mov_bit_c(code); break;
792     case 0x93: res= inst_movc_a_Sa_dptr(code); break;
793     case 0x94: res= inst_subb_a_Sdata(code); break;
794     case 0x95: res= inst_subb_a_addr(code); break;
795     case 0x96: case 0x97: res= inst_subb_a_Sri(code); break;
796     case 0x98: case 0x99: case 0x9a: case 0x9b:
797     case 0x9c: case 0x9d: case 0x9e: case 0x9f:res= inst_subb_a_rn(code);break;
798     case 0xa0: res= inst_orl_c_Sbit(code); break;
799     case 0xa2: res= inst_mov_c_bit(code); break;
800     case 0xa3: res= inst_inc_dptr(code); break;
801     case 0xa4: res= inst_mul_ab(code); break;
802     case 0xa5: res= inst_unknown(); break;
803     case 0xa6: case 0xa7: res= inst_mov_Sri_addr(code); break;
804     case 0xa8: case 0xa9: case 0xaa: case 0xab:
805     case 0xac: case 0xad: case 0xae: case 0xaf:res=inst_mov_rn_addr(code);break;
806     case 0xb0: res= inst_anl_c_Sbit(code); break;
807     case 0xb2: res= inst_cpl_bit(code); break;
808     case 0xb3: res= inst_cpl_c(code); break;
809     case 0xb4: res= inst_cjne_a_Sdata_addr(code); break;
810     case 0xb5: res= inst_cjne_a_addr_addr(code); break;
811     case 0xb6: case 0xb7: res= inst_cjne_Sri_Sdata_addr(code); break;
812     case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc:
813     case 0xbd: case 0xbe: case 0xbf: res=inst_cjne_rn_Sdata_addr(code); break;
814     case 0xc0: res= inst_push(code); break;
815     case 0xc2: res= inst_clr_bit(code); break;
816     case 0xc3: res= inst_clr_c(code); break;
817     case 0xc4: res= inst_swap(code); break;
818     case 0xc5: res= inst_xch_a_addr(code); break;
819     case 0xc6: case 0xc7: res= inst_xch_a_Sri(code); break;
820     case 0xc8: case 0xc9: case 0xca: case 0xcb:
821     case 0xcc: case 0xcd: case 0xce: case 0xcf: res= inst_xch_a_rn(code);break;
822     case 0xd0: res= inst_pop(code); break;
823     case 0xd2: res= inst_setb_bit(code); break;
824     case 0xd3: res= inst_setb_c(code); break;
825     case 0xd4: res= inst_da_a(code); break;
826     case 0xd5: res= inst_djnz_addr_addr(code); break;
827     case 0xd6: case 0xd7: res= inst_xchd_a_Sri(code); break;
828     case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc:
829     case 0xdd: case 0xde: case 0xdf: res=inst_djnz_rn_addr(code); break;
830     case 0xe0: res= inst_movx_a_Sdptr(code); break;
831     case 0xe2: case 0xe3: res= inst_movx_a_Sri(code); break;
832     case 0xe4: res= inst_clr_a(code); break;
833     case 0xe5: res= inst_mov_a_addr(code); break;
834     case 0xe6: case 0xe7: res= inst_mov_a_Sri(code); break;
835     case 0xe8: case 0xe9: case 0xea: case 0xeb:
836     case 0xec: case 0xed: case 0xee: case 0xef: res= inst_mov_a_rn(code);break;
837     case 0xf0: res= inst_movx_Sdptr_a(code); break;
838     case 0xf2: case 0xf3: res= inst_movx_Sri_a(code); break;
839     case 0xf4: res= inst_cpl_a(code); break;
840     case 0xf5: res= inst_mov_addr_a(code); break;
841     case 0xf6: case 0xf7: res= inst_mov_Sri_a(code); break;
842     case 0xf8: case 0xf9: case 0xfa: case 0xfb:
843     case 0xfc: case 0xfd: case 0xfe: case 0xff: res= inst_mov_rn_a(code);break;
844     default:
845       res= inst_unknown();
846       break;
847     }
848   //post_inst();
849   return(res);
850 }
851
852
853 /*
854  * Simulating execution of next instruction
855  *
856  * This is an endless loop if requested number of steps is negative.
857  * In this case execution is stopped if an instruction results other
858  * status than GO. Execution can be stopped if `cmd_in' is not NULL
859  * and there is input available on that file. It is usefull if the
860  * command console is on a terminal. If input is available then a
861  * complete line is read and dropped out because input is buffered
862  * (inp_avail will be TRUE if ENTER is pressed) and it can confuse
863  * command interepter.
864  */
865 //static class cl_console *c= NULL;
866 int
867 cl_51core::do_inst(int step)
868 {
869   result= resGO;
870   while ((result == resGO) &&
871          (state != stPD) &&
872          (step != 0))
873     {
874       if (step > 0)
875         step--;
876       if (state == stGO)
877         {
878           interrupt->was_reti= DD_FALSE;
879           pre_inst();
880           result= exec_inst();
881           post_inst();
882           /*
883           {
884             if (c)
885               print_regs(c);
886             else
887               {
888                 if (sim->app->get_commander()==NULL)
889                   printf("no commander PC=0x%x\n",PC);
890                 else
891                   if (sim->app->get_commander()->frozen_console==NULL)
892                     printf("no frozen console PC=0x%x\n",PC);
893                   else
894                     c= sim->app->get_commander()->frozen_console;
895                 if (c)
896                   print_regs(c);
897                 else
898                   printf("no console PC=0x%x\n",PC);
899               }
900           }
901           */
902           /*if (result == resGO)
903             result= check_events();*/
904         }
905       else
906         {
907           // tick hw in idle state
908           inst_ticks= 1;
909           post_inst();
910           tick(1);
911         }
912       if (result == resGO)
913         {
914           int res;
915           if ((res= do_interrupt()) != resGO)
916             result= res;
917           else
918             result= idle_pd();
919         }
920       if ((step < 0) &&
921           ((ticks->ticks % 100000) < 50))
922         {
923           if (sim->app->get_commander()->input_avail_on_frozen())
924             {
925               result= resUSER;
926             }
927           else
928             if (sim->app->get_commander()->input_avail())
929               break;
930         }
931       if (((result == resINTERRUPT) &&
932            stop_at_it) ||
933           result >= resSTOP)
934         {
935           sim->stop(result);
936           break;
937         }
938     }
939   if (state == stPD)
940     {
941       //FIXME: tick outsiders eg. watchdog
942       if (sim->app->get_commander()->input_avail_on_frozen())
943         {
944           //fprintf(stderr,"uc: inp avail in PD mode, user stop\n");
945           result= resUSER;
946           sim->stop(result); 
947         }
948     }
949   return(result);
950 }
951
952 /*void
953 cl_51core::post_inst(void)
954 {*/
955   //uint tcon= sfr->get(TCON);
956   //uint p3= sfr->read(P3);
957
958   //cl_uc::post_inst();
959   //set_p_flag();
960
961   // Setting up external interrupt request bits (IEx)
962   /*if ((tcon & bmIT0))
963     {
964       // IE0 edge triggered
965       if (p3_int0_edge)
966         {
967           // falling edge on INT0
968           sim->app->get_commander()->
969             debug("%g sec (%d clks): Falling edge detected on INT0 (P3.2)\n",
970                           get_rtime(), ticks->ticks);
971           sfr->set_bit1(TCON, bmIE0);
972           p3_int0_edge= 0;
973         }
974     }
975   else
976     {
977       // IE0 level triggered
978       if (p3 & bm_INT0)
979         sfr->set_bit0(TCON, bmIE0);
980       else
981         sfr->set_bit1(TCON, bmIE0);
982     }
983   if ((tcon & bmIT1))
984     {
985       // IE1 edge triggered
986       if (p3_int1_edge)
987         {
988           // falling edge on INT1
989           sfr->set_bit1(TCON, bmIE1);
990           p3_int1_edge= 0;
991         }
992     }
993   else
994     {
995       // IE1 level triggered
996       if (p3 & bm_INT1)
997         sfr->set_bit0(TCON, bmIE1);
998       else
999         sfr->set_bit1(TCON, bmIE1);
1000         }*/
1001   //prev_p3= p3 & port_pins[3];
1002   //prev_p1= p3 & port_pins[1];
1003 //}
1004
1005
1006 /*
1007  * Abstract method to handle WDT
1008  */
1009
1010 /*int
1011 cl_51core::do_wdt(int cycles)
1012 {
1013   return(resGO);
1014 }*/
1015
1016
1017 /*
1018  * Checking for interrupt requests and accept one if needed
1019  */
1020
1021 int
1022 cl_51core::do_interrupt(void)
1023 {
1024   int i, ie= 0;
1025
1026   if (interrupt->was_reti)
1027     {
1028       interrupt->was_reti= DD_FALSE;
1029       return(resGO);
1030     }
1031   if (!((ie= sfr->get(IE)) & bmEA))
1032     return(resGO);
1033   class it_level *il= (class it_level *)(it_levels->top()), *IL= 0;
1034   for (i= 0; i < it_sources->count; i++)
1035     {
1036       class cl_it_src *is= (class cl_it_src *)(it_sources->at(i));
1037       if (is->is_active() &&
1038           (ie & is->ie_mask) &&
1039           (sfr->get(is->src_reg) & is->src_mask))
1040         {
1041           int pr= it_priority(is->ie_mask);
1042           if (il->level >= 0 &&
1043               pr <= il->level)
1044             continue;
1045           if (state == stIDLE)
1046             {
1047               state= stGO;
1048               sfr->set_bit0(PCON, bmIDL);
1049               interrupt->was_reti= DD_TRUE;
1050               return(resGO);
1051             }
1052           if (is->clr_bit)
1053             sfr->set_bit0(is->src_reg, is->src_mask);
1054           sim->app->get_commander()->
1055             debug("%g sec (%d clks): Accepting interrupt `%s' PC= 0x%06x\n",
1056                           get_rtime(), ticks->ticks, object_name(is), PC);
1057           IL= new it_level(pr, is->addr, PC, is);
1058           return(accept_it(IL));
1059         }
1060     }
1061   return(resGO);
1062 }
1063
1064 int
1065 cl_51core::it_priority(uchar ie_mask)
1066 {
1067   if (sfr->get(IP) & ie_mask)
1068     return(1);
1069   return(0);
1070 }
1071
1072
1073 /*
1074  * Accept an interrupt
1075  */
1076
1077 int
1078 cl_51core::accept_it(class it_level *il)
1079 {
1080   state= stGO;
1081   sfr->set_bit0(PCON, bmIDL);
1082   it_levels->push(il);
1083   tick(1);
1084   int res= inst_lcall(0, il->addr, DD_TRUE);
1085   if (res != resGO)
1086     return(res);
1087   else
1088     return(resINTERRUPT);
1089 }
1090
1091
1092 /*
1093  * Checking if Idle or PowerDown mode should be activated
1094  */
1095
1096 int
1097 cl_51core::idle_pd(void)
1098 {
1099   uint pcon= sfr->get(PCON);
1100
1101   if (technology != CPU_CMOS)
1102     return(resGO);
1103   if (pcon & bmIDL)
1104     {
1105       if (state != stIDLE)
1106         sim->app->get_commander()->
1107           debug("%g sec (%d clks): CPU in Idle mode (PC=0x%x, PCON=0x%x)\n",
1108                 get_rtime(), ticks->ticks, PC, pcon);
1109       state= stIDLE;
1110       //was_reti= 1;
1111     }
1112   if (pcon & bmPD)
1113     {
1114       if (state != stPD)
1115         sim->app->get_commander()->
1116           debug("%g sec (%d clks): CPU in PowerDown mode\n",
1117                         get_rtime(), ticks->ticks);
1118       state= stPD;
1119     }
1120   return(resGO);
1121 }
1122
1123
1124 /*
1125  * Checking if EVENT break happened
1126  */
1127
1128 /*int
1129 cl_51core::check_events(void)
1130 {
1131   int i;
1132   class cl_ev_brk *eb;
1133
1134   if (!ebrk->count)
1135     return(resGO);
1136   for (i= 0; i < ebrk->count; i++)
1137     {
1138       eb= (class cl_ev_brk *)(ebrk->at(i));
1139       if (eb->match(&event_at))
1140         return(resBREAKPOINT);
1141     }
1142   return(resGO);
1143 }*/
1144
1145
1146 /*
1147  */
1148
1149 /*
1150 void
1151 cl_51core::mem_cell_changed(class cl_m *mem, t_addr addr)
1152 {
1153   if (mem == sfr)
1154     switch (addr)
1155       {
1156       case ACC: acc= mem->get_cell(ACC); break;
1157       case PSW: psw= mem->get_cell(PSW); break;
1158       }
1159   cl_uc::mem_cell_changed(mem, addr);
1160 }
1161 */
1162
1163
1164 /*
1165  * Simulating an unknown instruction
1166  *
1167  * Normally this function is called for unimplemented instructions, because
1168  * every instruction must be known!
1169  */
1170
1171 int
1172 cl_51core::inst_unknown(void)
1173 {
1174   //PC--;
1175   class cl_error_unknown_code *e= new cl_error_unknown_code(this);
1176   error(e);
1177   return(resGO);
1178 }
1179
1180
1181 /*
1182  * 0x00 1 12 NOP
1183  */
1184
1185 int
1186 cl_51core::inst_nop(uchar code)
1187 {
1188   return(resGO);
1189 }
1190
1191
1192 /*
1193  * 0xe4 1 12 CLR A
1194  */
1195
1196 int
1197 cl_51core::inst_clr_a(uchar code)
1198 {
1199   acc->write(0);
1200   return(resGO);
1201 }
1202
1203
1204 /*
1205  * 0xc4 1 1 SWAP A
1206  */
1207
1208 int
1209 cl_51core::inst_swap(uchar code)
1210 {
1211   uchar temp;
1212
1213   temp= (acc->read() >> 4) & 0x0f;
1214   sfr->write(ACC, (acc->get() << 4) | temp);
1215   return(resGO);
1216 }
1217
1218
1219 /*
1220  */
1221
1222 cl_uc51_dummy_hw::cl_uc51_dummy_hw(class cl_uc *auc):
1223   cl_hw(auc, HW_DUMMY, 0, "_51_dummy")
1224 {
1225   //uc51= (class cl_51core *)uc;
1226 }
1227
1228 int
1229 cl_uc51_dummy_hw::init(void)
1230 {
1231   class cl_address_space *sfr= uc->address_space(MEM_SFR_ID);
1232   if (!sfr)
1233     {
1234       fprintf(stderr, "No SFR to register %s[%d] into\n", id_string, id);
1235     }
1236   //acc= sfr->register_hw(ACC, this, 0);
1237   //sp = sfr->register_hw(SP , this, 0);
1238   use_cell(sfr, PSW, &cell_psw, wtd_restore);
1239   register_cell(sfr, ACC, &cell_acc, wtd_restore_write);
1240   register_cell(sfr, SP , &cell_sp , wtd_restore);
1241   //register_cell(sfr, PCON, &cell_pcon, wtd_restore);
1242   return(0);
1243 }
1244
1245 void
1246 cl_uc51_dummy_hw::write(class cl_memory_cell *cell, t_mem *val)
1247 {
1248   if (cell == cell_acc)
1249     {
1250       bool p;
1251       int i;
1252       uchar uc;
1253
1254       p = DD_FALSE;
1255       uc= *val;
1256       for (i= 0; i < 8; i++)
1257         {
1258           if (uc & 1)
1259             p= !p;
1260           uc>>= 1;
1261         }
1262       if (p)
1263         cell_psw->set_bit1(bmP);
1264       else
1265         cell_psw->set_bit0(bmP);
1266     }
1267   else if (cell == cell_sp)
1268     {
1269       if (*val > uc->sp_max)
1270         uc->sp_max= *val;
1271       uc->sp_avg= (uc->sp_avg+(*val))/2;
1272     }
1273   /*else if (cell == cell_pcon)
1274     {
1275       printf("PCON write 0x%x (PC=0x%x)\n", *val, uc->PC);
1276       uc->sim->stop(0);
1277       }*/
1278 }
1279
1280 /*void
1281 cl_uc51_dummy_hw::happen(class cl_hw *where, enum hw_event he, void *params)
1282 {
1283   struct ev_port_changed *ep= (struct ev_port_changed *)params;
1284
1285   if (where->cathegory == HW_PORT &&
1286       he == EV_PORT_CHANGED &&
1287       ep->id == 3)
1288     {
1289       t_mem p3o= ep->pins & ep->prev_value;
1290       t_mem p3n= ep->new_pins & ep->new_value;
1291       if ((p3o & bm_INT0) &&
1292           !(p3n & bm_INT0))
1293         uc51->p3_int0_edge++;
1294       if ((p3o & bm_INT1) &&
1295           !(p3n & bm_INT1))
1296         uc51->p3_int1_edge++;
1297     }
1298 }*/
1299
1300
1301 /* End of s51.src/uc51.cc */