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