06af92c95137d473c77925c8e743054b8e5191a9
[fw/sdcc] / sim / ucsim / hc08.src / hc08.cc
1 /*
2  * Simulator of microcontrollers (hc08.cc)
3  *
4  * some hc08 code base from Karl Bongers karl@turbobit.com
5  * 
6  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
7  * 
8  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
9  *
10  */
11
12 /* This file is part of microcontroller simulator: ucsim.
13
14 UCSIM is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 UCSIM is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with UCSIM; see the file COPYING.  If not, write to the Free
26 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
27 02111-1307, USA. */
28 /*@1@*/
29
30 #include "ddconfig.h"
31
32 #include <stdarg.h> /* for va_list */
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include "i_string.h"
37
38 // prj
39 #include "pobjcl.h"
40
41 // sim
42 #include "simcl.h"
43
44 // local
45 #include "hc08cl.h"
46 #include "glob.h"
47 #include "regshc08.h"
48 #include "hc08mac.h"
49
50 #define uint32 t_addr
51 #define uint8 unsigned char
52 #define int8 char
53
54 const bool TRUE = 1;
55 const bool FALSE = 0;
56
57 /*******************************************************************/
58
59
60 /*
61  * Base type of HC08 controllers
62  */
63
64 cl_hc08::cl_hc08(class cl_sim *asim):
65   cl_uc(asim)
66 {
67   type= CPU_HC08;
68 }
69
70 int
71 cl_hc08::init(void)
72 {
73   cl_uc::init(); /* Memories now exist */
74
75   xtal = 8000000;
76
77   rom= mem(MEM_ROM);
78 //  ram= mem(MEM_XRAM);
79   ram= rom;
80
81   // zero out ram(this is assumed in regression tests)
82   for (int i=0x80; i<0x8000; i++) {
83     ram->set((t_addr) i, 0);
84   }
85
86   return(0);
87 }
88
89
90 void
91 cl_hc08::reset(void)
92 {
93   cl_uc::reset();
94
95   regs.SP = 0xff;
96   regs.A = 0;
97   regs.X = 0;
98   regs.H = 0;
99   regs.P = 0x60;
100   regs.VECTOR = 1;
101
102 }
103
104
105 char *
106 cl_hc08::id_string(void)
107 {
108   return("unspecified HC08");
109 }
110
111
112 /*
113  * Making elements of the controller
114  */
115
116 t_addr
117 cl_hc08::get_mem_size(enum mem_class type)
118 {
119   switch(type)
120     {
121     case MEM_ROM: return(0x10000);
122     case MEM_XRAM: return(0x10000);
123     default: return(0);
124     }
125  return(cl_uc::get_mem_size(type));
126 }
127
128 void
129 cl_hc08::mk_hw_elements(void)
130 {
131   //class cl_base *o;
132   /* t_uc::mk_hw() does nothing */
133 }
134
135
136 /*
137  * Help command interpreter
138  */
139
140 struct dis_entry *
141 cl_hc08::dis_tbl(void)
142 {
143   return(disass_hc08);
144 }
145
146 /*struct name_entry *
147 cl_hc08::sfr_tbl(void)
148 {
149   return(0);
150 }*/
151
152 /*struct name_entry *
153 cl_hc08::bit_tbl(void)
154 {
155   //FIXME
156   return(0);
157 }*/
158
159 int
160 cl_hc08::inst_length(t_addr addr)
161 {
162   int len = 0;
163   char *s;
164
165   s = get_disasm_info(addr, &len, NULL, NULL);
166
167   return len;
168 }
169
170 int
171 cl_hc08::inst_branch(t_addr addr)
172 {
173   int b;
174   char *s;
175
176   s = get_disasm_info(addr, NULL, &b, NULL);
177
178   return b;
179 }
180
181 int
182 cl_hc08::longest_inst(void)
183 {
184   return 4;
185 }
186
187
188 char *
189 cl_hc08::get_disasm_info(t_addr addr,
190                         int *ret_len,
191                         int *ret_branch,
192                         int *immed_offset)
193 {
194   char *b = NULL;
195   uint code;
196   int len = 0;
197   int immed_n = 0;
198   int i;
199   int start_addr = addr;
200   struct dis_entry *dis_e;
201
202   code= get_mem(MEM_ROM, addr++);
203   dis_e = NULL;
204
205   switch(code) {
206     case 0x9e:  /* ESC code to sp relative op-codes */
207       code= get_mem(MEM_ROM, addr++);
208       i= 0;
209       while ((code & disass_hc08_9e[i].mask) != disass_hc08_9e[i].code &&
210         disass_hc08_9e[i].mnemonic)
211         i++;
212       dis_e = &disass_hc08_9e[i];
213       b= disass_hc08_9e[i].mnemonic;
214       if (b != NULL)
215         len += (disass_hc08_9e[i].length + 1);
216     break;
217
218     default:
219       i= 0;
220       while ((code & disass_hc08[i].mask) != disass_hc08[i].code &&
221              disass_hc08[i].mnemonic)
222         i++;
223       dis_e = &disass_hc08[i];
224       b= disass_hc08[i].mnemonic;
225       if (b != NULL)
226         len += (disass_hc08[i].length);
227     break;
228   }
229
230   if (ret_branch) {
231     *ret_branch = dis_e->branch;
232   }
233
234   if (immed_offset) {
235     if (immed_n > 0)
236          *immed_offset = immed_n;
237     else *immed_offset = (addr - start_addr);
238   }
239
240   if (len == 0)
241     len = 1;
242
243   if (ret_len)
244     *ret_len = len;
245
246   return b;
247 }
248
249 char *
250 cl_hc08::disass(t_addr addr, char *sep)
251 {
252   char work[256], temp[20];
253   char *buf, *p, *b, *t;
254   int len = 0;
255   int immed_offset = 0;
256
257   p= work;
258
259   b = get_disasm_info(addr, &len, NULL, &immed_offset);
260   
261   if (b == NULL) {
262     buf= (char*)malloc(30);
263     strcpy(buf, "UNKNOWN/INVALID");
264     return(buf);
265   }
266
267   while (*b)
268     {
269       if (*b == '%')
270         {
271           b++;
272           switch (*(b++))
273             {
274             case 's': // s    signed byte immediate
275               sprintf(temp, "#%d", (char)get_mem(MEM_ROM, addr+immed_offset));
276               ++immed_offset;
277               break;
278             case 'w': // w    word immediate operand
279               sprintf(temp, "#0x%04x",
280                  (uint)((get_mem(MEM_ROM, addr+immed_offset)<<8) |
281                         (get_mem(MEM_ROM, addr+immed_offset+1))) );
282               ++immed_offset;
283               ++immed_offset;
284               break;
285             case 'b': // b    byte immediate operand
286               sprintf(temp, "#0x%02x", (uint)get_mem(MEM_ROM, addr+immed_offset));
287               ++immed_offset;
288               break;
289             case 'x': // x    extended addressing
290               sprintf(temp, "0x%04x",
291                  (uint)((get_mem(MEM_ROM, addr+immed_offset)<<8) |
292                         (get_mem(MEM_ROM, addr+immed_offset+1))) );
293               ++immed_offset;
294               ++immed_offset;
295               break;
296             case 'd': // d    direct addressing
297               sprintf(temp, "*0x%02x", (uint)get_mem(MEM_ROM, addr+immed_offset));
298               ++immed_offset;
299               break;
300             case '2': // 2    word index offset
301               sprintf(temp, "0x%04x",
302                  (uint)((get_mem(MEM_ROM, addr+immed_offset)<<8) |
303                         (get_mem(MEM_ROM, addr+immed_offset+1))) );
304               ++immed_offset;
305               ++immed_offset;
306               break;
307             case '1': // b    byte index offset
308               sprintf(temp, "0x%02x", (uint)get_mem(MEM_ROM, addr+immed_offset));
309               ++immed_offset;
310               break;
311             case 'p': // b    byte index offset
312               sprintf(temp, "0x%04x",
313                  addr+immed_offset+1
314                  +(char)get_mem(MEM_ROM, addr+immed_offset));
315               ++immed_offset;
316               break;
317             default:
318               strcpy(temp, "?");
319               break;
320             }
321           t= temp;
322           while (*t)
323             *(p++)= *(t++);
324         }
325       else
326         *(p++)= *(b++);
327     }
328   *p= '\0';
329
330   p= strchr(work, ' ');
331   if (!p)
332     {
333       buf= strdup(work);
334       return(buf);
335     }
336   if (sep == NULL)
337     buf= (char *)malloc(6+strlen(p)+1);
338   else
339     buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
340   for (p= work, b= buf; *p != ' '; p++, b++)
341     *b= *p;
342   p++;
343   *b= '\0';
344   if (sep == NULL)
345     {
346       while (strlen(buf) < 6)
347         strcat(buf, " ");
348     }
349   else
350     strcat(buf, sep);
351   strcat(buf, p);
352   return(buf);
353 }
354
355
356 void
357 cl_hc08::print_regs(class cl_console *con)
358 {
359   con->dd_printf("V--HINZC  Flags= 0x%02x %3d %c  ",
360                  regs.P, regs.P, isprint(regs.P)?regs.P:'.');
361   con->dd_printf("A= 0x%02x %3d %c\n",
362                  regs.A, regs.A, isprint(regs.A)?regs.A:'.');
363   con->dd_printf("%c--%c%c%c%c%c  ",
364                  (regs.P&BIT_V)?'1':'0',
365                  (regs.P&BIT_H)?'1':'0',
366                  (regs.P&BIT_I)?'1':'0',
367                  (regs.P&BIT_N)?'1':'0',
368                  (regs.P&BIT_Z)?'1':'0',
369                  (regs.P&BIT_C)?'1':'0');
370   con->dd_printf("    H= 0x%02x %3d %c  ",
371                  regs.H, regs.H, isprint(regs.H)?regs.H:'.');
372   con->dd_printf("X= 0x%02x %3d %c\n",
373                  regs.X, regs.X, isprint(regs.X)?regs.X:'.');
374   con->dd_printf("SP= 0x%04x [SP+1]= %02x %3d %c\n",
375                  regs.SP, ram->get(regs.SP+1), ram->get(regs.SP+1),
376                  isprint(ram->get(regs.SP+1))?ram->get(regs.SP+1):'.');
377   
378   print_disass(PC, con);
379 }
380
381 /*
382  * Execution
383  */
384
385 int
386 cl_hc08::exec_inst(void)
387 {
388   t_mem code;
389
390   if (regs.VECTOR) {
391     PC = get2(0xfffe);
392     regs.VECTOR = 0;
393     return(resGO);
394   }
395
396   if (fetch(&code))
397     return(resBREAKPOINT);
398   tick(1);
399   switch ((code >> 4) & 0xf) {
400     case 0x0: return(inst_bittestsetclear(code, FALSE));
401     case 0x1: return(inst_bitsetclear(code, FALSE));
402     case 0x2: return(inst_condbranch(code, FALSE));
403     case 0x3:
404     case 0x4:
405     case 0x5:
406     case 0x6:
407     case 0x7:
408       switch (code & 0xf) {
409         case 0x0: return(inst_neg(code, FALSE));
410         case 0x1: return(inst_cbeq(code, FALSE));
411         case 0x2:
412           switch (code) {
413             case 0x42: return(inst_mul(code, FALSE));
414             case 0x52: return(inst_div(code, FALSE));
415             case 0x62: return(inst_nsa(code, FALSE));
416             case 0x72: return(inst_daa(code, FALSE));
417             default: return(resHALT);
418           }
419         case 0x3: return(inst_com(code, FALSE));
420         case 0x4: return(inst_lsr(code, FALSE));
421         case 0x5:
422           switch (code) {
423             case 0x35: return(inst_sthx(code, FALSE));
424             case 0x45:
425             case 0x55: return(inst_ldhx(code, FALSE));
426             case 0x65:
427             case 0x75: return(inst_cphx(code, FALSE));
428             default: return(resHALT);
429           }
430         case 0x6: return(inst_ror(code, FALSE));
431         case 0x7: return(inst_asr(code, FALSE));
432         case 0x8: return(inst_lsl(code, FALSE));
433         case 0x9: return(inst_rol(code, FALSE));
434         case 0xa: return(inst_dec(code, FALSE));
435         case 0xb: return(inst_dbnz(code, FALSE));
436         case 0xc: return(inst_inc(code, FALSE));
437         case 0xd: return(inst_tst(code, FALSE));
438         case 0xe:
439           switch (code) {
440             case 0x4e:
441             case 0x5e:
442             case 0x6e:
443             case 0x7e: return(inst_mov(code, FALSE));
444             default: return(resHALT);
445           }
446         case 0xf: return(inst_clr(code, FALSE));
447         default: return(resHALT);
448       }
449     case 0x8:
450       switch (code & 0xf) {
451         case 0x0: return(inst_rti(code, FALSE));
452         case 0x1: return(inst_rts(code, FALSE));
453         case 0x3: return(inst_swi(code, FALSE));
454         case 0x4:
455         case 0x5: return(inst_transfer(code, FALSE));
456         case 0x6:
457         case 0x7:
458         case 0x8:
459         case 0x9:
460         case 0xa:
461         case 0xb: return(inst_pushpull(code, FALSE));
462         case 0xc: return(inst_clrh(code, FALSE));
463         case 0xe: return(inst_stop(code, FALSE));
464         case 0xf: return(inst_wait(code, FALSE));
465         default: return(resHALT);
466       }
467     case 0x9:
468       switch (code & 0xf) {
469         case 0x0:
470         case 0x1:
471         case 0x2:
472         case 0x3: return(inst_condbranch(code, FALSE));
473         case 0x4:
474         case 0x5:
475         case 0x7:
476         case 0xf: return(inst_transfer(code, FALSE));
477         case 0x8:
478         case 0x9:
479         case 0xa:
480         case 0xb: return(inst_setclearflags(code, FALSE));
481         case 0xc: return(inst_rsp(code, FALSE));
482         case 0xd: return(inst_nop(code, FALSE));
483         case 0xe:
484           code = fetch();
485           switch ((code >> 4) & 0xf) {
486             case 0x6:
487               switch (code & 0xf) {
488                 case 0x0: return(inst_neg(code, TRUE));
489                 case 0x1: return(inst_cbeq(code, TRUE));
490                 case 0x3: return(inst_com(code, TRUE));
491                 case 0x4: return(inst_lsr(code, TRUE));
492                 case 0x6: return(inst_ror(code, TRUE));
493                 case 0x7: return(inst_asr(code, TRUE));
494                 case 0x8: return(inst_lsl(code, TRUE));
495                 case 0x9: return(inst_rol(code, TRUE));
496                 case 0xa: return(inst_dec(code, TRUE));
497                 case 0xb: return(inst_dbnz(code, TRUE));
498                 case 0xc: return(inst_inc(code, TRUE));
499                 case 0xd: return(inst_tst(code, TRUE));
500                 case 0xf: return(inst_clr(code, TRUE));
501                 default: return(resHALT);
502               }
503             case 0xd:
504             case 0xe:
505               switch (code & 0xf) {
506                 case 0x0: return(inst_sub(code, TRUE));
507                 case 0x1: return(inst_cmp(code, TRUE));
508                 case 0x2: return(inst_sbc(code, TRUE));
509                 case 0x3: return(inst_cpx(code, TRUE));
510                 case 0x4: return(inst_and(code, TRUE));
511                 case 0x5: return(inst_bit(code, TRUE));
512                 case 0x6: return(inst_lda(code, TRUE));
513                 case 0x7: return(inst_sta(code, TRUE));
514                 case 0x8: return(inst_eor(code, TRUE));
515                 case 0x9: return(inst_adc(code, TRUE));
516                 case 0xa: return(inst_ora(code, TRUE));
517                 case 0xb: return(inst_add(code, TRUE));
518                 case 0xc: return(resHALT);
519                 case 0xd: putchar(regs.A); fflush(stdout); return(resGO);
520                 case 0xe: return(inst_ldx(code, TRUE));
521                 case 0xf: return(inst_stx(code, TRUE));
522                 default: return(resHALT);
523               }
524             default: return(resHALT);
525           }
526               
527       }
528     case 0xa:
529     case 0xb:
530     case 0xc:
531     case 0xd:
532     case 0xe:
533     case 0xf:
534       switch (code & 0xf) {
535         case 0x0: return(inst_sub(code, FALSE));
536         case 0x1: return(inst_cmp(code, FALSE));
537         case 0x2: return(inst_sbc(code, FALSE));
538         case 0x3: return(inst_cpx(code, FALSE));
539         case 0x4: return(inst_and(code, FALSE));
540         case 0x5: return(inst_bit(code, FALSE));
541         case 0x6: return(inst_lda(code, FALSE));
542         case 0x7:
543           if (code==0xa7)
544             return(inst_ais(code, FALSE));
545           else
546             return(inst_sta(code, FALSE));
547         case 0x8: return(inst_eor(code, FALSE));
548         case 0x9: return(inst_adc(code, FALSE));
549         case 0xa: return(inst_ora(code, FALSE));
550         case 0xb: return(inst_add(code, FALSE));
551         case 0xc:
552           if (code==0xac)
553             return(resHALT);
554           else
555             return(inst_jmp(code, FALSE));
556         case 0xd:
557           if (code==0xad)
558             return(inst_bsr(code, FALSE));
559           else
560             return(inst_jsr(code, FALSE));
561         case 0xe: return(inst_ldx(code, FALSE));
562         case 0xf:
563           if (code==0xaf)
564             return(inst_aix(code, FALSE));
565           else
566             return(inst_stx(code, FALSE));
567         default: return(resHALT);
568       }
569     default: return(resHALT);
570   }
571
572   if (PC)
573     PC--;
574   else
575     PC= get_mem_size(MEM_ROM)-1;
576
577   sim->stop(resINV_INST);
578   return(resINV_INST);
579 }
580
581
582 /* End of hc08.src/hc08.cc */