* sim/ucsim/cmd.src/info.cc, sim/ucsim/cmd.src/bp.cc,
[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
53 /*******************************************************************/
54
55
56 /*
57  * Base type of HC08 controllers
58  */
59
60 cl_hc08::cl_hc08(class cl_sim *asim):
61   cl_uc(asim)
62 {
63   type= CPU_HC08;
64 }
65
66 int
67 cl_hc08::init(void)
68 {
69   cl_uc::init(); /* Memories now exist */
70
71   xtal = 8000000;
72
73   rom= address_space(MEM_ROM_ID);
74 //  ram= mem(MEM_XRAM);
75   ram= rom;
76
77   // zero out ram(this is assumed in regression tests)
78   for (int i=0x80; i<0x8000; i++) {
79     ram->set((t_addr) i, 0);
80   }
81
82   return(0);
83 }
84
85
86 void
87 cl_hc08::reset(void)
88 {
89   cl_uc::reset();
90
91   regs.SP = 0xff;
92   regs.A = 0;
93   regs.X = 0;
94   regs.H = 0;
95   regs.P = 0x60;
96   regs.VECTOR = 1;
97
98 }
99
100
101 const char *
102 cl_hc08::id_string(void)
103 {
104   return("unspecified HC08");
105 }
106
107
108 /*
109  * Making elements of the controller
110  */
111 /*
112 t_addr
113 cl_hc08::get_mem_size(enum mem_class type)
114 {
115   switch(type)
116     {
117     case MEM_ROM: return(0x10000);
118     case MEM_XRAM: return(0x10000);
119     default: return(0);
120     }
121  return(cl_uc::get_mem_size(type));
122 }
123 */
124 void
125 cl_hc08::mk_hw_elements(void)
126 {
127   //class cl_base *o;
128   /* t_uc::mk_hw() does nothing */
129 }
130
131 void
132 cl_hc08::make_memories(void)
133 {
134   class cl_address_space *as;
135
136   as= new cl_address_space("rom", 0, 0x10000, 8);
137   as->init();
138   address_spaces->add(as);
139
140   class cl_address_decoder *ad;
141   class cl_memory_chip *chip;
142
143   chip= new cl_memory_chip("rom_chip", 0x10000, 8);
144   chip->init();
145   memchips->add(chip);
146   ad= new cl_address_decoder(as= address_space("rom"), chip, 0, 0xffff, 0);
147   ad->init();
148   as->decoders->add(ad);
149   ad->activate(0);
150 }
151
152
153 /*
154  * Help command interpreter
155  */
156
157 struct dis_entry *
158 cl_hc08::dis_tbl(void)
159 {
160   return(disass_hc08);
161 }
162
163 /*struct name_entry *
164 cl_hc08::sfr_tbl(void)
165 {
166   return(0);
167 }*/
168
169 /*struct name_entry *
170 cl_hc08::bit_tbl(void)
171 {
172   //FIXME
173   return(0);
174 }*/
175
176 int
177 cl_hc08::inst_length(t_addr addr)
178 {
179   int len = 0;
180
181   get_disasm_info(addr, &len, NULL, NULL);
182
183   return len;
184 }
185
186 int
187 cl_hc08::inst_branch(t_addr addr)
188 {
189   int b;
190
191   get_disasm_info(addr, NULL, &b, NULL);
192
193   return b;
194 }
195
196 int
197 cl_hc08::longest_inst(void)
198 {
199   return 4;
200 }
201
202
203 const char *
204 cl_hc08::get_disasm_info(t_addr addr,
205                         int *ret_len,
206                         int *ret_branch,
207                         int *immed_offset)
208 {
209   const char *b = NULL;
210   uint code;
211   int len = 0;
212   int immed_n = 0;
213   int i;
214   int start_addr = addr;
215   struct dis_entry *dis_e;
216
217   code= get_mem(MEM_ROM_ID, addr++);
218   dis_e = NULL;
219
220   switch(code) {
221     case 0x9e:  /* ESC code to sp relative op-codes */
222       code= get_mem(MEM_ROM_ID, addr++);
223       i= 0;
224       while ((code & disass_hc08_9e[i].mask) != disass_hc08_9e[i].code &&
225         disass_hc08_9e[i].mnemonic)
226         i++;
227       dis_e = &disass_hc08_9e[i];
228       b= disass_hc08_9e[i].mnemonic;
229       if (b != NULL)
230         len += (disass_hc08_9e[i].length + 1);
231     break;
232
233     default:
234       i= 0;
235       while ((code & disass_hc08[i].mask) != disass_hc08[i].code &&
236              disass_hc08[i].mnemonic)
237         i++;
238       dis_e = &disass_hc08[i];
239       b= disass_hc08[i].mnemonic;
240       if (b != NULL)
241         len += (disass_hc08[i].length);
242     break;
243   }
244
245   if (ret_branch) {
246     *ret_branch = dis_e->branch;
247   }
248
249   if (immed_offset) {
250     if (immed_n > 0)
251          *immed_offset = immed_n;
252     else *immed_offset = (addr - start_addr);
253   }
254
255   if (len == 0)
256     len = 1;
257
258   if (ret_len)
259     *ret_len = len;
260
261   return b;
262 }
263
264 const char *
265 cl_hc08::disass(t_addr addr, const char *sep)
266 {
267   char work[256], temp[20];
268   const char *b;
269   char *buf, *p, *t;
270   int len = 0;
271   int immed_offset = 0;
272
273   p= work;
274
275   b = get_disasm_info(addr, &len, NULL, &immed_offset);
276
277   if (b == NULL) {
278     buf= (char*)malloc(30);
279     strcpy(buf, "UNKNOWN/INVALID");
280     return(buf);
281   }
282
283   while (*b)
284     {
285       if (*b == '%')
286         {
287           b++;
288           switch (*(b++))
289             {
290             case 's': // s    signed byte immediate
291               sprintf(temp, "#%d", (char)get_mem(MEM_ROM_ID, addr+immed_offset));
292               ++immed_offset;
293               break;
294             case 'w': // w    word immediate operand
295               sprintf(temp, "#0x%04x",
296                  (uint)((get_mem(MEM_ROM_ID, addr+immed_offset)<<8) |
297                         (get_mem(MEM_ROM_ID, addr+immed_offset+1))) );
298               ++immed_offset;
299               ++immed_offset;
300               break;
301             case 'b': // b    byte immediate operand
302               sprintf(temp, "#0x%02x", (uint)get_mem(MEM_ROM_ID, addr+immed_offset));
303               ++immed_offset;
304               break;
305             case 'x': // x    extended addressing
306               sprintf(temp, "0x%04x",
307                  (uint)((get_mem(MEM_ROM_ID, addr+immed_offset)<<8) |
308                         (get_mem(MEM_ROM_ID, addr+immed_offset+1))) );
309               ++immed_offset;
310               ++immed_offset;
311               break;
312             case 'd': // d    direct addressing
313               sprintf(temp, "*0x%02x", (uint)get_mem(MEM_ROM_ID, addr+immed_offset));
314               ++immed_offset;
315               break;
316             case '2': // 2    word index offset
317               sprintf(temp, "0x%04x",
318                  (uint)((get_mem(MEM_ROM_ID, addr+immed_offset)<<8) |
319                         (get_mem(MEM_ROM_ID, addr+immed_offset+1))) );
320               ++immed_offset;
321               ++immed_offset;
322               break;
323             case '1': // b    byte index offset
324               sprintf(temp, "0x%02x", (uint)get_mem(MEM_ROM_ID, addr+immed_offset));
325               ++immed_offset;
326               break;
327             case 'p': // b    byte index offset
328               sprintf(temp, "0x%04x",
329                  addr+immed_offset+1
330                  +(char)get_mem(MEM_ROM_ID, addr+immed_offset));
331               ++immed_offset;
332               break;
333             default:
334               strcpy(temp, "?");
335               break;
336             }
337           t= temp;
338           while (*t)
339             *(p++)= *(t++);
340         }
341       else
342         *(p++)= *(b++);
343     }
344   *p= '\0';
345
346   p= strchr(work, ' ');
347   if (!p)
348     {
349       buf= strdup(work);
350       return(buf);
351     }
352   if (sep == NULL)
353     buf= (char *)malloc(6+strlen(p)+1);
354   else
355     buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
356   for (p= work, t= buf; *p != ' '; p++, t++)
357     *t= *p;
358   p++;
359   *t= '\0';
360   if (sep == NULL)
361     {
362       while (strlen(buf) < 6)
363         strcat(buf, " ");
364     }
365   else
366     strcat(buf, sep);
367   strcat(buf, p);
368   return(buf);
369 }
370
371
372 void
373 cl_hc08::print_regs(class cl_console_base *con)
374 {
375   con->dd_printf("V--HINZC  Flags= 0x%02x %3d %c  ",
376                  regs.P, regs.P, isprint(regs.P)?regs.P:'.');
377   con->dd_printf("A= 0x%02x %3d %c\n",
378                  regs.A, regs.A, isprint(regs.A)?regs.A:'.');
379   con->dd_printf("%c--%c%c%c%c%c  ",
380                  (regs.P&BIT_V)?'1':'0',
381                  (regs.P&BIT_H)?'1':'0',
382                  (regs.P&BIT_I)?'1':'0',
383                  (regs.P&BIT_N)?'1':'0',
384                  (regs.P&BIT_Z)?'1':'0',
385                  (regs.P&BIT_C)?'1':'0');
386   con->dd_printf("    H= 0x%02x %3d %c  ",
387                  regs.H, regs.H, isprint(regs.H)?regs.H:'.');
388   con->dd_printf("X= 0x%02x %3d %c\n",
389                  regs.X, regs.X, isprint(regs.X)?regs.X:'.');
390   con->dd_printf("SP= 0x%04x [SP+1]= %02x %3d %c\n",
391                  regs.SP, ram->get(regs.SP+1), ram->get(regs.SP+1),
392                  isprint(ram->get(regs.SP+1))?ram->get(regs.SP+1):'.');
393
394   print_disass(PC, con);
395 }
396
397 /*
398  * Execution
399  */
400
401 int
402 cl_hc08::exec_inst(void)
403 {
404   t_mem code;
405
406   if (regs.VECTOR) {
407     PC = get2(0xfffe);
408     regs.VECTOR = 0;
409     return(resGO);
410   }
411
412   if (fetch(&code))
413     return(resBREAKPOINT);
414   tick(1);
415   switch ((code >> 4) & 0xf) {
416     case 0x0: return(inst_bittestsetclear(code, false));
417     case 0x1: return(inst_bitsetclear(code, false));
418     case 0x2: return(inst_condbranch(code, false));
419     case 0x3:
420     case 0x4:
421     case 0x5:
422     case 0x6:
423     case 0x7:
424       switch (code & 0xf) {
425         case 0x0: return(inst_neg(code, false));
426         case 0x1: return(inst_cbeq(code, false));
427         case 0x2:
428           switch (code) {
429             case 0x42: return(inst_mul(code, false));
430             case 0x52: return(inst_div(code, false));
431             case 0x62: return(inst_nsa(code, false));
432             case 0x72: return(inst_daa(code, false));
433             default: return(resHALT);
434           }
435         case 0x3: return(inst_com(code, false));
436         case 0x4: return(inst_lsr(code, false));
437         case 0x5:
438           switch (code) {
439             case 0x35: return(inst_sthx(code, false));
440             case 0x45:
441             case 0x55: return(inst_ldhx(code, false));
442             case 0x65:
443             case 0x75: return(inst_cphx(code, false));
444             default: return(resHALT);
445           }
446         case 0x6: return(inst_ror(code, false));
447         case 0x7: return(inst_asr(code, false));
448         case 0x8: return(inst_lsl(code, false));
449         case 0x9: return(inst_rol(code, false));
450         case 0xa: return(inst_dec(code, false));
451         case 0xb: return(inst_dbnz(code, false));
452         case 0xc: return(inst_inc(code, false));
453         case 0xd: return(inst_tst(code, false));
454         case 0xe:
455           switch (code) {
456             case 0x4e:
457             case 0x5e:
458             case 0x6e:
459             case 0x7e: return(inst_mov(code, false));
460             default: return(resHALT);
461           }
462         case 0xf: return(inst_clr(code, false));
463         default: return(resHALT);
464       }
465     case 0x8:
466       switch (code & 0xf) {
467         case 0x0: return(inst_rti(code, false));
468         case 0x1: return(inst_rts(code, false));
469         case 0x3: return(inst_swi(code, false));
470         case 0x4:
471         case 0x5: return(inst_transfer(code, false));
472         case 0x6:
473         case 0x7:
474         case 0x8:
475         case 0x9:
476         case 0xa:
477         case 0xb: return(inst_pushpull(code, false));
478         case 0xc: return(inst_clrh(code, false));
479         case 0xe: return(inst_stop(code, false));
480         case 0xf: return(inst_wait(code, false));
481         default: return(resHALT);
482       }
483     case 0x9:
484       switch (code & 0xf) {
485         case 0x0:
486         case 0x1:
487         case 0x2:
488         case 0x3: return(inst_condbranch(code, false));
489         case 0x4:
490         case 0x5:
491         case 0x7:
492         case 0xf: return(inst_transfer(code, false));
493         case 0x8:
494         case 0x9:
495         case 0xa:
496         case 0xb: return(inst_setclearflags(code, false));
497         case 0xc: return(inst_rsp(code, false));
498         case 0xd: return(inst_nop(code, false));
499         case 0xe:
500           code = fetch();
501           switch ((code >> 4) & 0xf) {
502             case 0x6:
503               switch (code & 0xf) {
504                 case 0x0: return(inst_neg(code, true));
505                 case 0x1: return(inst_cbeq(code, true));
506                 case 0x3: return(inst_com(code, true));
507                 case 0x4: return(inst_lsr(code, true));
508                 case 0x6: return(inst_ror(code, true));
509                 case 0x7: return(inst_asr(code, true));
510                 case 0x8: return(inst_lsl(code, true));
511                 case 0x9: return(inst_rol(code, true));
512                 case 0xa: return(inst_dec(code, true));
513                 case 0xb: return(inst_dbnz(code, true));
514                 case 0xc: return(inst_inc(code, true));
515                 case 0xd: return(inst_tst(code, true));
516                 case 0xf: return(inst_clr(code, true));
517                 default: return(resHALT);
518               }
519             case 0xd:
520             case 0xe:
521               switch (code & 0xf) {
522                 case 0x0: return(inst_sub(code, true));
523                 case 0x1: return(inst_cmp(code, true));
524                 case 0x2: return(inst_sbc(code, true));
525                 case 0x3: return(inst_cpx(code, true));
526                 case 0x4: return(inst_and(code, true));
527                 case 0x5: return(inst_bit(code, true));
528                 case 0x6: return(inst_lda(code, true));
529                 case 0x7: return(inst_sta(code, true));
530                 case 0x8: return(inst_eor(code, true));
531                 case 0x9: return(inst_adc(code, true));
532                 case 0xa: return(inst_ora(code, true));
533                 case 0xb: return(inst_add(code, true));
534                 case 0xc: return(resHALT);
535                 case 0xd: putchar(regs.A); fflush(stdout); return(resGO);
536                 case 0xe: return(inst_ldx(code, true));
537                 case 0xf: return(inst_stx(code, true));
538                 default: return(resHALT);
539               }
540             default: return(resHALT);
541           }
542
543       }
544     case 0xa:
545     case 0xb:
546     case 0xc:
547     case 0xd:
548     case 0xe:
549     case 0xf:
550       switch (code & 0xf) {
551         case 0x0: return(inst_sub(code, false));
552         case 0x1: return(inst_cmp(code, false));
553         case 0x2: return(inst_sbc(code, false));
554         case 0x3: return(inst_cpx(code, false));
555         case 0x4: return(inst_and(code, false));
556         case 0x5: return(inst_bit(code, false));
557         case 0x6: return(inst_lda(code, false));
558         case 0x7:
559           if (code==0xa7)
560             return(inst_ais(code, false));
561           else
562             return(inst_sta(code, false));
563         case 0x8: return(inst_eor(code, false));
564         case 0x9: return(inst_adc(code, false));
565         case 0xa: return(inst_ora(code, false));
566         case 0xb: return(inst_add(code, false));
567         case 0xc:
568           if (code==0xac)
569             return(resHALT);
570           else
571             return(inst_jmp(code, false));
572         case 0xd:
573           if (code==0xad)
574             return(inst_bsr(code, false));
575           else
576             return(inst_jsr(code, false));
577         case 0xe: return(inst_ldx(code, false));
578         case 0xf:
579           if (code==0xaf)
580             return(inst_aix(code, false));
581           else
582             return(inst_stx(code, false));
583         default: return(resHALT);
584       }
585     default: return(resHALT);
586   }
587
588   /*if (PC)
589     PC--;
590   else
591   PC= get_mem_size(MEM_ROM_ID)-1;*/
592   PC= rom->inc_address(PC, -1);
593
594   sim->stop(resINV_INST);
595   return(resINV_INST);
596 }
597
598
599 /* End of hc08.src/hc08.cc */