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