Imported Upstream version 2.9.0
[debian/cc1111] / sim / ucsim / avr.src / avr.cc
1 /*
2  * Simulator of microcontrollers (avr.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 "i_string.h"
34
35 // prj
36 #include "pobjcl.h"
37
38 // sim
39 #include "simcl.h"
40 #include "memcl.h"
41
42 // local
43 #include "portcl.h"
44 #include "avrcl.h"
45 #include "glob.h"
46 #include "regsavr.h"
47
48
49 /*
50  * Base type of AVR microcontrollers
51  */
52
53 cl_avr::cl_avr(class cl_sim *asim):
54   cl_uc(asim)
55 {
56   type= CPU_AVR;
57   sleep_executed= 0;
58 }
59
60 int
61 cl_avr::init(void)
62 {
63   cl_uc::init(); /* Memories now exist */
64   ram= address_space(MEM_IRAM_ID);
65   rom= address_space(MEM_ROM_ID);
66   return(0);
67 }
68
69 const char *
70 cl_avr::id_string(void)
71 {
72   return("unspecified AVR");
73 }
74
75
76 /*
77  * Making elements of the controller
78  */
79 /*
80 t_addr
81 cl_avr::get_mem_size(enum mem_class type)
82 {
83   switch(type)
84     {
85     case MEM_ROM: return(8*1024);
86     case MEM_IRAM: return(0x10000);
87     default: return(0);
88     }
89   //return(0);
90   //return(cl_uc::get_mem_size(type));
91 }
92 */
93 /*
94 int
95 cl_avr::get_mem_width(enum mem_class type)
96 {
97   if (type == MEM_ROM)
98     return(16);
99   return(cl_uc::get_mem_width(type));
100 }
101 */
102
103 void
104 cl_avr::mk_hw_elements(void)
105 {
106   class cl_base *o;
107   /* t_uc::mk_hw() does nothing */
108   hws->add(o= new cl_port(this));
109   o->init();
110 }
111
112
113 void
114 cl_avr::make_memories(void)
115 {
116   class cl_address_space *as;
117
118   rom= as= new cl_address_space(MEM_ROM_ID, 0, 0x10000, 16);
119   as->init();
120   address_spaces->add(as);
121   ram= as= new cl_address_space(MEM_IRAM_ID, 0, 0x10000, 8);
122   as->init();
123   address_spaces->add(as);
124
125   class cl_address_decoder *ad;
126   class cl_memory_chip *chip;
127
128   chip= new cl_memory_chip("rom_chip", 0x10000, 16);
129   chip->init();
130   memchips->add(chip);
131   ad= new cl_address_decoder(as= rom/*address_space(MEM_ROM_ID)*/,
132                              chip, 0, 0xffff, 0);
133   ad->init();
134   as->decoders->add(ad);
135   ad->activate(0);
136
137   chip= new cl_memory_chip("iram_chip", 0x80, 8);
138   chip->init();
139   memchips->add(chip);
140   ad= new cl_address_decoder(as= ram/*address_space(MEM_IRAM_ID)*/,
141                              chip, 0, 0x7f, 0);
142   ad->init();
143   as->decoders->add(ad);
144   ad->activate(0);
145 }
146
147
148 /*
149  * Help command interpreter
150  */
151
152 struct dis_entry *
153 cl_avr::dis_tbl(void)
154 {
155   return(disass_avr);
156 }
157
158 struct name_entry *
159 cl_avr::sfr_tbl(void)
160 {
161   return(sfr_tabl);
162 }
163
164 struct name_entry *
165 cl_avr::bit_tbl(void)
166 {
167   //FIXME
168   return(0);
169 }
170
171 const char *
172 cl_avr::disass(t_addr addr, const char *sep)
173 {
174   char work[256], temp[20];
175   const char *b;
176   char *buf, *p, *t;
177   uint code, data= 0;
178   int i;
179
180   p= work;
181
182   code= get_mem(MEM_ROM_ID, addr);
183   i= 0;
184   while ((code & dis_tbl()[i].mask) != dis_tbl()[i].code &&
185          dis_tbl()[i].mnemonic)
186     i++;
187   if (dis_tbl()[i].mnemonic == NULL)
188     {
189       buf= (char*)malloc(30);
190       strcpy(buf, "UNKNOWN/INVALID");
191       return(buf);
192     }
193   b= dis_tbl()[i].mnemonic;
194
195   while (*b)
196     {
197       if (*b == '%')
198         {
199           b++;
200           switch (*(b++))
201             {
202             case 'd': // Rd   .... ...d dddd ....  0<=d<=31
203               if (!get_name(data= (code&0x01f0)>>4, sfr_tbl(), temp))
204                 sprintf(temp, "r%d", data);
205               break;
206             case 'D': // Rd   .... .... dddd ....  16<=d<=31
207               if (!get_name(data= 16+((code&0xf0)>>4), sfr_tbl(), temp))
208                 sprintf(temp, "r%d", data);
209               break;
210             case 'K': // K    .... KKKK .... KKKK  0<=K<=255
211               sprintf(temp, "%d", ((code&0xf00)>>4)|(code&0xf));
212               break;
213             case 'r': // Rr   .... ..r. .... rrrr  0<=r<=31
214               if (!get_name(data= ((code&0x0200)>>5)|(code&0x000f),
215                             sfr_tbl(), temp))
216                 sprintf(temp, "r%d", data);
217               break;
218             case '2': // Rdl  .... .... ..dd ....  dl= {24,26,28,30}
219               if (!get_name(data= 24+(2*((code&0x0030)>>4)),
220                             sfr_tbl(), temp))
221                 sprintf(temp, "r%d", data);
222               break;
223             case '6': // K    .... .... KK.. KKKK  0<=K<=63
224               sprintf(temp, "%d", ((code&0xc0)>>2)|(code&0xf));
225               break;
226             case 's': // s    .... .... .sss ....  0<=s<=7
227               sprintf(temp, "%d", (code&0x70)>>4);
228               break;
229             case 'b': // b    .... .... .... .bbb  0<=b<=7
230               sprintf(temp, "%d", code&0x7);
231               break;
232             case 'k': // k    .... ..kk kkkk k...  -64<=k<=+63
233               {
234                 int k= (code&0x3f8)>>3;
235                 if (code&0x200)
236                   k|= -128;
237                 sprintf(temp, "0x%06x", k+1+(signed int)addr);
238                 break;
239               }
240             case 'A': // k    .... ...k kkkk ...k  0<=k<=64K
241                       //      kkkk kkkk kkkk kkkk  0<=k<=4M
242               sprintf(temp, "0x%06x",
243                       (((code&0x1f0)>>3)|(code&1))*0x10000+
244                       (uint)get_mem(MEM_ROM_ID, addr+1));
245               break;
246             case 'P': // P    .... .... pppp p...  0<=P<=31
247               data= (code&0xf8)>>3;
248               if (!get_name(data+0x20, sfr_tbl(), temp))
249                 sprintf(temp, "%d", data);
250               break;
251             case 'p': // P    .... .PP. .... PPPP  0<=P<=63
252               data= ((code&0x600)>>5)|(code&0xf);
253               if (!get_name(data+0x20, sfr_tbl(), temp))
254                 sprintf(temp, "%d", data);
255               break;
256             case 'q': // q    ..q. qq.. .... .qqq  0<=q<=63
257               sprintf(temp, "%d",
258                       ((code&0x2000)>>8)|((code&0xc00)>>7)|(code&7));
259               break;
260             case 'R': // k    SRAM address on second word 0<=k<=65535
261               sprintf(temp, "0x%06x", (uint)get_mem(MEM_ROM_ID, addr+1));
262               break;
263             case 'a': // k    .... kkkk kkkk kkkk  -2k<=k<=2k
264               {
265                 int k= code&0xfff;
266                 if (code&0x800)
267                   k|= -4096;
268                 sprintf(temp, "0x%06"_A_"x",
269                         rom->validate_address(k+1+(signed int)addr));
270                 break;
271               }
272             default:
273               strcpy(temp, "?");
274               break;
275             }
276           t= temp;
277           while (*t)
278             *(p++)= *(t++);
279         }
280       else
281         *(p++)= *(b++);
282     }
283   *p= '\0';
284
285   p= strchr(work, ' ');
286   if (!p)
287     {
288       buf= strdup(work);
289       return(buf);
290     }
291   if (sep == NULL)
292     buf= (char *)malloc(6+strlen(p)+1);
293   else
294     buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
295   for (p= work, t= buf; *p != ' '; p++, t++)
296     *t= *p;
297   p++;
298   *t= '\0';
299   if (sep == NULL)
300     {
301       while (strlen(buf) < 6)
302         strcat(buf, " ");
303     }
304   else
305     strcat(buf, sep);
306   strcat(buf, p);
307   return(buf);
308 }
309
310
311 void
312 cl_avr::print_regs(class cl_console_base *con)
313 {
314   uchar data, sreg= ram->get(SREG);
315   uint x, y, z;
316
317   ram->dump(0, 31, 16, con);
318
319   con->dd_printf("ITHSVNZC  SREG= 0x%02x %3d %c\n",
320                  sreg, sreg, isprint(sreg)?sreg:'.');
321   con->dd_printf("%c%c%c%c%c%c%c%c  ",
322                  (sreg&BIT_I)?'1':'0',
323                  (sreg&BIT_T)?'1':'0',
324                  (sreg&BIT_H)?'1':'0',
325                  (sreg&BIT_S)?'1':'0',
326                  (sreg&BIT_V)?'1':'0',
327                  (sreg&BIT_N)?'1':'0',
328                  (sreg&BIT_Z)?'1':'0',
329                  (sreg&BIT_C)?'1':'0');
330   con->dd_printf("SP  = 0x%06x\n", ram->get(SPH)*256+ram->get(SPL));
331
332   x= ram->get(XH)*256 + ram->get(XL);
333   data= ram->get(x);
334   con->dd_printf("X= 0x%04x [X]= 0x%02x %3d %c  ", x,
335                  data, data, isprint(data)?data:'.');
336   y= ram->get(YH)*256 + ram->get(YL);
337   data= ram->get(y);
338   con->dd_printf("Y= 0x%04x [Y]= 0x%02x %3d %c  ", y,
339                  data, data, isprint(data)?data:'.');
340   z= ram->get(ZH)*256 + ram->get(ZL);
341   data= ram->get(z);
342   con->dd_printf("Z= 0x%04x [Z]= 0x%02x %3d %c\n", z,
343                  data, data, isprint(data)?data:'.');
344
345   print_disass(PC, con);
346 }
347
348
349 /*
350  * Execution
351  */
352
353 int
354 cl_avr::exec_inst(void)
355 {
356   t_mem code;
357
358   instPC= PC;
359   if (fetch(&code))
360     return(resBREAKPOINT);
361   tick(1);
362   switch (code)
363     {
364     case 0x9419:
365       return(eijmp(code));
366     case 0x9519:
367       return(eicall(code));
368     case 0x9508: case 0x9528: case 0x9548: case 0x9568:
369       return(ret(code));
370     case 0x9518: case 0x9538: case 0x9558: case 0x9578:
371       return(reti(code));
372     case 0x95c8:
373       return(lpm(code));
374     case 0x95d8:
375       return(elpm(code)); // in some devices equal to lpm
376     case 0x95e8:
377       return(spm(code));
378     case 0x95f8:
379       return(espm(code));
380     case 0x9408:
381       return(sec(code));
382     case 0x9488:
383       return(clc(code));
384     case 0x9428:
385       return(sen(code));
386     case 0x94a8:
387       return(cln(code));
388     case 0x9418:
389       return(sez(code));
390     case 0x9498:
391       return(clz(code));
392     case 0x9478:
393      return(sei(code));
394     case 0x94f8:
395       return(cli(code));
396     case 0x9448:
397       return(ses(code));
398     case 0x94c8:
399       return(cls(code));
400     case 0x9438:
401       return(sev(code));
402     case 0x94b8:
403       return(clv(code));
404     case 0x9468:
405       return(set(code));
406     case 0x94e8:
407       return(clt(code));
408     case 0x9458:
409       return(seh(code));
410     case 0x94d8:
411       return(clh(code));
412     case 0x0000:
413       return(nop(code));
414     case 0x9588: case 0x9598:
415       return(sleep(code));
416     case 0x95a8: case 0x95b8:
417       return(wdr(code));
418     }
419   switch (code & 0xf000)
420     {
421     case 0x3000: return(cpi_Rd_K(code));
422     case 0x4000: return(sbci_Rd_K(code));
423     case 0x5000: return(subi_Rd_K(code));
424     case 0x6000: return(ori_Rd_K(code));
425     case 0x7000: return(andi_Rd_K(code));
426     case 0xc000: return(rjmp_k(code));
427     case 0xd000: return(rcall_k(code));
428     case 0xe000: return(ldi_Rd_K(code));
429     }
430   switch (code & 0xf000)
431     {
432     case 0x0000:
433       {
434         // 0x0...
435         switch (code & 0xfc00)
436           {
437           case 0x0000:
438             {
439               switch (code & 0xff00)
440                 {
441                 case 0x0100: return(movw_Rd_Rr(code));
442                 case 0x0200: return(muls_Rd_Rr(code));
443                 case 0x0300:
444                   {
445                     switch (code & 0xff88)
446                       {
447                       case 0x0300: return(mulsu_Rd_Rr(code));
448                       case 0x0308: return(fmul_Rd_Rr(code));
449                       case 0x0380: return(fmuls_Rd_Rr(code));
450                       case 0x0388: return(fmulsu_Rd_Rr(code));
451                       }
452                     break;
453                   }
454                   break;
455                 }
456               break;
457             }
458           case 0x0400: return(cpc_Rd_Rr(code));
459           case 0x0800: return(sbc_Rd_Rr(code));
460           case 0x0c00: return(add_Rd_Rr(code));
461           }
462         break;
463       }
464     case 0x1000:
465       {
466         // 0x1...
467         switch (code & 0xfc00)
468           {
469           case 0x1000: return(cpse_Rd_Rr(code));
470           case 0x1400: return(cp_Rd_Rr(code));
471           case 0x1800: return(sub_Rd_Rr(code));
472           case 0x1c00: return(adc_Rd_Rr(code));
473           }
474         break;
475       }
476     case 0x2000:
477       {
478         // 0x2...
479         switch (code & 0xfc00)
480           {
481           case 0x2000: return(and_Rd_Rr(code));
482           case 0x2400: return(eor_Rd_Rr(code));
483           case 0x2800: return(or_Rd_Rr(code));
484           case 0x2c00: return(mov_Rd_Rr(code));
485         }
486         break;
487       }
488     case 0x8000:
489       {
490         // 0x8...
491         switch (code &0xf208)
492           {
493           case 0x8000: return(ldd_Rd_Z_q(code));
494           case 0x8008: return(ldd_Rd_Y_q(code));
495           case 0x8200: return(std_Z_q_Rr(code));
496           case 0x8208: return(std_Y_q_Rr(code));
497           }
498         break;
499       }
500     case 0x9000:
501       {
502         // 0x9...
503         if ((code & 0xff0f) == 0x9509)
504           return(icall(code));
505         if ((code & 0xff0f) == 0x9409)
506           return(ijmp(code));
507         if ((code & 0xff00) == 0x9600)
508           return(adiw_Rdl_K(code));
509         if ((code & 0xff00) == 0x9700)
510           return(sbiw_Rdl_K(code));
511         switch (code & 0xfc00)
512           {
513           case 0x9000:
514             {
515               switch (code & 0xfe0f)
516                 {
517                 case 0x9000: return(lds_Rd_k(code));
518                 case 0x9001: return(ld_Rd_ZS(code));
519                 case 0x9002: return(ld_Rd_SZ(code));
520                 case 0x9004: return(lpm_Rd_Z(code));
521                 case 0x9005: return(lpm_Rd_ZS(code));
522                 case 0x9006: return(elpm_Rd_Z(code));
523                 case 0x9007: return(elpm_Rd_ZS(code));
524                 case 0x9009: return(ld_Rd_YS(code));
525                 case 0x900a: return(ld_Rd_SY(code));
526                 case 0x900c: return(ld_Rd_X(code));
527                 case 0x900d: return(ld_Rd_XS(code));
528                 case 0x900e: return(ld_Rd_SX(code));
529                 case 0x900f: return(pop_Rd(code));
530                 case 0x9200: return(sts_k_Rr(code));
531                 case 0x9201: return(st_ZS_Rr(code));
532                 case 0x9202: return(st_SZ_Rr(code));
533                 case 0x9209: return(st_YS_Rr(code));
534                 case 0x920a: return(st_SY_Rr(code));
535                 case 0x920c: return(st_X_Rr(code));
536                 case 0x920d: return(st_XS_Rr(code));
537                 case 0x920e: return(st_SX_Rr(code));
538                 case 0x920f: return(push_Rr(code));
539                 }
540               break;
541             }
542           case 0x9400:
543             {
544               switch (code & 0xfe0f)
545                 {
546                 case 0x9400: return(com_Rd(code));
547                 case 0x9401: return(neg_Rd(code));
548                 case 0x9402: return(swap_Rd(code));
549                 case 0x9403: return(inc_Rd(code));
550                 case 0x9405: return(asr_Rd(code));
551                 case 0x9406: return(lsr_Rd(code));
552                 case 0x9407: return(ror_Rd(code));
553                 case 0x940a: return(dec_Rd(code));
554                 case 0x940c: case 0x940d: return(jmp_k(code));
555                 case 0x940e: case 0x940f: return(call_k(code));
556                 }
557               break;
558             }
559           case 0x9800:
560             {
561               switch (code & 0xff00)
562                 {
563                 case 0x9800: return(cbi_A_b(code));
564                 case 0x9900: return(sbic_P_b(code));
565                 case 0x9a00: return(sbi_A_b(code));
566                 case 0x9b00: return(sbis_P_b(code));
567                 }
568               break;
569             }
570           case 0x9c00: return(mul_Rd_Rr(code));
571           }
572         break;
573       }
574     case 0xa000:
575       {
576         // 0xa...
577         switch (code &0xf208)
578           {
579           case 0xa000: return(ldd_Rd_Z_q(code));
580           case 0xa008: return(ldd_Rd_Y_q(code));
581           case 0xa200: return(std_Z_q_Rr(code));
582           case 0xa208: return(std_Y_q_Rr(code));
583           }
584         break;
585       }
586     case 0xb000:
587       {
588         // 0xb...
589         switch (code & 0xf800)
590           {
591           case 0xb000: return(in_Rd_A(code));
592           case 0xb800: return(out_A_Rr(code));
593           }
594         break;
595       }
596     case 0xe000:
597       {
598         // 0xe...
599         switch (code & 0xff0f)
600           {
601           case 0xef0f: return(ser_Rd(code));
602           }
603         break;
604       }
605     case 0xf000:
606       {
607         // 0xf...
608         switch (code & 0xfc00)
609           {
610           case 0xf000: return(brbs_s_k(code));
611           case 0xf400: return(brbc_s_k(code));
612           case 0xf800: case 0xfc00:
613             {
614               switch (code & 0xfe08)
615                 {
616                 case 0xf800: return(bld_Rd_b(code));
617                 case 0xfa00: return(bst_Rd_b(code));
618                 case 0xfc00: case 0xfc08: return(sbrc_Rr_b(code));
619                 case 0xfe00: case 0xfe08: return(sbrs_Rr_b(code));
620                 }
621               break;
622             }
623           }
624         break;
625       }
626     }
627   /*if (PC)
628     PC--;
629   else
630   PC= get_mem_size(MEM_ROM_ID)-1;*/
631   class cl_error_unknown_code *e= new cl_error_unknown_code(this);
632   error(e);
633   return(resGO);
634   PC= rom->inc_address(PC, -1);
635   //tick(-clock_per_cycle());
636   sim->stop(resINV_INST);
637   return(resINV_INST);
638 }
639
640
641 /*
642  */
643
644 int
645 cl_avr::push_data(t_mem data)
646 {
647   t_addr sp;
648   t_mem spl, sph;
649
650   spl= ram->read(SPL);
651   sph= ram->read(SPH);
652   sp= 0xffff & (256*sph + spl);
653   data= ram->write(sp, data);
654   sp= 0xffff & (sp-1);
655   spl= sp & 0xff;
656   sph= (sp>>8) & 0xff;
657   ram->write(SPL, spl);
658   ram->write(SPH, sph);
659   return(resGO);
660 }
661
662 int
663 cl_avr::push_addr(t_addr addr)
664 {
665   t_addr sp;
666   t_mem spl, sph, al, ah;
667
668   spl= ram->read(SPL);
669   sph= ram->read(SPH);
670   sp= 0xffff & (256*sph + spl);
671   al= addr & 0xff;
672   ah= (addr>>8) & 0xff;
673   ram->write(sp, ah);
674   sp= 0xffff & (sp-1);
675   ram->write(sp, al);
676   sp= 0xffff & (sp-1);
677   spl= sp & 0xff;
678   sph= (sp>>8) & 0xff;
679   ram->write(SPL, spl);
680   ram->write(SPH, sph);
681   return(resGO);
682 }
683
684 int
685 cl_avr::pop_data(t_mem *data)
686 {
687   t_addr sp;
688   t_mem spl, sph;
689
690   spl= ram->read(SPL);
691   sph= ram->read(SPH);
692   sp= 256*sph + spl;
693   sp= 0xffff & (sp+1);
694   *data= ram->read(sp);
695   spl= sp & 0xff;
696   sph= (sp>>8) & 0xff;
697   ram->write(SPL, spl);
698   ram->write(SPH, sph);
699
700   return(resGO);
701 }
702
703 int
704 cl_avr::pop_addr(t_addr *addr)
705 {
706   t_addr sp;
707   t_mem spl, sph, al, ah;
708
709   spl= ram->read(SPL);
710   sph= ram->read(SPH);
711   sp= 256*sph + spl;
712   sp= 0xffff & (sp+1);
713   al= ram->read(sp);
714   sp= 0xffff & (sp+1);
715   ah= ram->read(sp);
716   *addr= ah*256 + al;
717   spl= sp & 0xff;
718   sph= (sp>>8) & 0xff;
719   ram->write(SPL, spl);
720   ram->write(SPH, sph);
721
722   return(resGO);
723 }
724
725
726 /*
727  * Set Z, N, V, S bits of SREG after logic instructions and some others
728  */
729
730 void
731 cl_avr::set_zn0s(t_mem data)
732 {
733   t_mem sreg= ram->get(SREG) & ~BIT_V;
734   data= data&0xff;
735   if (!data)
736     sreg|= BIT_Z;
737   else
738     sreg&= ~BIT_Z;
739   if (data & 0x80)
740     sreg|= (BIT_N|BIT_S);
741   else
742     sreg&= ~(BIT_N|BIT_S);
743   ram->set(SREG, sreg);
744 }
745
746
747 /* End of avr.src/avr.cc */