* sim/ucsim/hc08.src/hc08mac.h: removed faulty and unused add_u16_disp
[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 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   char *s;
181
182   s = get_disasm_info(addr, &len, NULL, NULL);
183
184   return len;
185 }
186
187 int
188 cl_hc08::inst_branch(t_addr addr)
189 {
190   int b;
191   char *s;
192
193   s = get_disasm_info(addr, NULL, &b, NULL);
194
195   return b;
196 }
197
198 int
199 cl_hc08::longest_inst(void)
200 {
201   return 4;
202 }
203
204
205 char *
206 cl_hc08::get_disasm_info(t_addr addr,
207                         int *ret_len,
208                         int *ret_branch,
209                         int *immed_offset)
210 {
211   char *b = NULL;
212   uint code;
213   int len = 0;
214   int immed_n = 0;
215   int i;
216   int start_addr = addr;
217   struct dis_entry *dis_e;
218
219   code= get_mem(MEM_ROM_ID, addr++);
220   dis_e = NULL;
221
222   switch(code) {
223     case 0x9e:  /* ESC code to sp relative op-codes */
224       code= get_mem(MEM_ROM_ID, addr++);
225       i= 0;
226       while ((code & disass_hc08_9e[i].mask) != disass_hc08_9e[i].code &&
227         disass_hc08_9e[i].mnemonic)
228         i++;
229       dis_e = &disass_hc08_9e[i];
230       b= disass_hc08_9e[i].mnemonic;
231       if (b != NULL)
232         len += (disass_hc08_9e[i].length + 1);
233     break;
234
235     default:
236       i= 0;
237       while ((code & disass_hc08[i].mask) != disass_hc08[i].code &&
238              disass_hc08[i].mnemonic)
239         i++;
240       dis_e = &disass_hc08[i];
241       b= disass_hc08[i].mnemonic;
242       if (b != NULL)
243         len += (disass_hc08[i].length);
244     break;
245   }
246
247   if (ret_branch) {
248     *ret_branch = dis_e->branch;
249   }
250
251   if (immed_offset) {
252     if (immed_n > 0)
253          *immed_offset = immed_n;
254     else *immed_offset = (addr - start_addr);
255   }
256
257   if (len == 0)
258     len = 1;
259
260   if (ret_len)
261     *ret_len = len;
262
263   return b;
264 }
265
266 char *
267 cl_hc08::disass(t_addr addr, char *sep)
268 {
269   char work[256], temp[20];
270   char *buf, *p, *b, *t;
271   int len = 0;
272   int immed_offset = 0;
273
274   p= work;
275
276   b = get_disasm_info(addr, &len, NULL, &immed_offset);
277   
278   if (b == NULL) {
279     buf= (char*)malloc(30);
280     strcpy(buf, "UNKNOWN/INVALID");
281     return(buf);
282   }
283
284   while (*b)
285     {
286       if (*b == '%')
287         {
288           b++;
289           switch (*(b++))
290             {
291             case 's': // s    signed byte immediate
292               sprintf(temp, "#%d", (char)get_mem(MEM_ROM_ID, addr+immed_offset));
293               ++immed_offset;
294               break;
295             case 'w': // w    word immediate operand
296               sprintf(temp, "#0x%04x",
297                  (uint)((get_mem(MEM_ROM_ID, addr+immed_offset)<<8) |
298                         (get_mem(MEM_ROM_ID, addr+immed_offset+1))) );
299               ++immed_offset;
300               ++immed_offset;
301               break;
302             case 'b': // b    byte immediate operand
303               sprintf(temp, "#0x%02x", (uint)get_mem(MEM_ROM_ID, addr+immed_offset));
304               ++immed_offset;
305               break;
306             case 'x': // x    extended addressing
307               sprintf(temp, "0x%04x",
308                  (uint)((get_mem(MEM_ROM_ID, addr+immed_offset)<<8) |
309                         (get_mem(MEM_ROM_ID, addr+immed_offset+1))) );
310               ++immed_offset;
311               ++immed_offset;
312               break;
313             case 'd': // d    direct addressing
314               sprintf(temp, "*0x%02x", (uint)get_mem(MEM_ROM_ID, addr+immed_offset));
315               ++immed_offset;
316               break;
317             case '2': // 2    word index offset
318               sprintf(temp, "0x%04x",
319                  (uint)((get_mem(MEM_ROM_ID, addr+immed_offset)<<8) |
320                         (get_mem(MEM_ROM_ID, addr+immed_offset+1))) );
321               ++immed_offset;
322               ++immed_offset;
323               break;
324             case '1': // b    byte index offset
325               sprintf(temp, "0x%02x", (uint)get_mem(MEM_ROM_ID, addr+immed_offset));
326               ++immed_offset;
327               break;
328             case 'p': // b    byte index offset
329               sprintf(temp, "0x%04x",
330                  addr+immed_offset+1
331                  +(char)get_mem(MEM_ROM_ID, addr+immed_offset));
332               ++immed_offset;
333               break;
334             default:
335               strcpy(temp, "?");
336               break;
337             }
338           t= temp;
339           while (*t)
340             *(p++)= *(t++);
341         }
342       else
343         *(p++)= *(b++);
344     }
345   *p= '\0';
346
347   p= strchr(work, ' ');
348   if (!p)
349     {
350       buf= strdup(work);
351       return(buf);
352     }
353   if (sep == NULL)
354     buf= (char *)malloc(6+strlen(p)+1);
355   else
356     buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
357   for (p= work, b= buf; *p != ' '; p++, b++)
358     *b= *p;
359   p++;
360   *b= '\0';
361   if (sep == NULL)
362     {
363       while (strlen(buf) < 6)
364         strcat(buf, " ");
365     }
366   else
367     strcat(buf, sep);
368   strcat(buf, p);
369   return(buf);
370 }
371
372
373 void
374 cl_hc08::print_regs(class cl_console *con)
375 {
376   con->dd_printf("V--HINZC  Flags= 0x%02x %3d %c  ",
377                  regs.P, regs.P, isprint(regs.P)?regs.P:'.');
378   con->dd_printf("A= 0x%02x %3d %c\n",
379                  regs.A, regs.A, isprint(regs.A)?regs.A:'.');
380   con->dd_printf("%c--%c%c%c%c%c  ",
381                  (regs.P&BIT_V)?'1':'0',
382                  (regs.P&BIT_H)?'1':'0',
383                  (regs.P&BIT_I)?'1':'0',
384                  (regs.P&BIT_N)?'1':'0',
385                  (regs.P&BIT_Z)?'1':'0',
386                  (regs.P&BIT_C)?'1':'0');
387   con->dd_printf("    H= 0x%02x %3d %c  ",
388                  regs.H, regs.H, isprint(regs.H)?regs.H:'.');
389   con->dd_printf("X= 0x%02x %3d %c\n",
390                  regs.X, regs.X, isprint(regs.X)?regs.X:'.');
391   con->dd_printf("SP= 0x%04x [SP+1]= %02x %3d %c\n",
392                  regs.SP, ram->get(regs.SP+1), ram->get(regs.SP+1),
393                  isprint(ram->get(regs.SP+1))?ram->get(regs.SP+1):'.');
394   
395   print_disass(PC, con);
396 }
397
398 /*
399  * Execution
400  */
401
402 int
403 cl_hc08::exec_inst(void)
404 {
405   t_mem code;
406
407   if (regs.VECTOR) {
408     PC = get2(0xfffe);
409     regs.VECTOR = 0;
410     return(resGO);
411   }
412
413   if (fetch(&code))
414     return(resBREAKPOINT);
415   tick(1);
416   switch ((code >> 4) & 0xf) {
417     case 0x0: return(inst_bittestsetclear(code, false));
418     case 0x1: return(inst_bitsetclear(code, false));
419     case 0x2: return(inst_condbranch(code, false));
420     case 0x3:
421     case 0x4:
422     case 0x5:
423     case 0x6:
424     case 0x7:
425       switch (code & 0xf) {
426         case 0x0: return(inst_neg(code, false));
427         case 0x1: return(inst_cbeq(code, false));
428         case 0x2:
429           switch (code) {
430             case 0x42: return(inst_mul(code, false));
431             case 0x52: return(inst_div(code, false));
432             case 0x62: return(inst_nsa(code, false));
433             case 0x72: return(inst_daa(code, false));
434             default: return(resHALT);
435           }
436         case 0x3: return(inst_com(code, false));
437         case 0x4: return(inst_lsr(code, false));
438         case 0x5:
439           switch (code) {
440             case 0x35: return(inst_sthx(code, false));
441             case 0x45:
442             case 0x55: return(inst_ldhx(code, false));
443             case 0x65:
444             case 0x75: return(inst_cphx(code, false));
445             default: return(resHALT);
446           }
447         case 0x6: return(inst_ror(code, false));
448         case 0x7: return(inst_asr(code, false));
449         case 0x8: return(inst_lsl(code, false));
450         case 0x9: return(inst_rol(code, false));
451         case 0xa: return(inst_dec(code, false));
452         case 0xb: return(inst_dbnz(code, false));
453         case 0xc: return(inst_inc(code, false));
454         case 0xd: return(inst_tst(code, false));
455         case 0xe:
456           switch (code) {
457             case 0x4e:
458             case 0x5e:
459             case 0x6e:
460             case 0x7e: return(inst_mov(code, false));
461             default: return(resHALT);
462           }
463         case 0xf: return(inst_clr(code, false));
464         default: return(resHALT);
465       }
466     case 0x8:
467       switch (code & 0xf) {
468         case 0x0: return(inst_rti(code, false));
469         case 0x1: return(inst_rts(code, false));
470         case 0x3: return(inst_swi(code, false));
471         case 0x4:
472         case 0x5: return(inst_transfer(code, false));
473         case 0x6:
474         case 0x7:
475         case 0x8:
476         case 0x9:
477         case 0xa:
478         case 0xb: return(inst_pushpull(code, false));
479         case 0xc: return(inst_clrh(code, false));
480         case 0xe: return(inst_stop(code, false));
481         case 0xf: return(inst_wait(code, false));
482         default: return(resHALT);
483       }
484     case 0x9:
485       switch (code & 0xf) {
486         case 0x0:
487         case 0x1:
488         case 0x2:
489         case 0x3: return(inst_condbranch(code, false));
490         case 0x4:
491         case 0x5:
492         case 0x7:
493         case 0xf: return(inst_transfer(code, false));
494         case 0x8:
495         case 0x9:
496         case 0xa:
497         case 0xb: return(inst_setclearflags(code, false));
498         case 0xc: return(inst_rsp(code, false));
499         case 0xd: return(inst_nop(code, false));
500         case 0xe:
501           code = fetch();
502           switch ((code >> 4) & 0xf) {
503             case 0x6:
504               switch (code & 0xf) {
505                 case 0x0: return(inst_neg(code, true));
506                 case 0x1: return(inst_cbeq(code, true));
507                 case 0x3: return(inst_com(code, true));
508                 case 0x4: return(inst_lsr(code, true));
509                 case 0x6: return(inst_ror(code, true));
510                 case 0x7: return(inst_asr(code, true));
511                 case 0x8: return(inst_lsl(code, true));
512                 case 0x9: return(inst_rol(code, true));
513                 case 0xa: return(inst_dec(code, true));
514                 case 0xb: return(inst_dbnz(code, true));
515                 case 0xc: return(inst_inc(code, true));
516                 case 0xd: return(inst_tst(code, true));
517                 case 0xf: return(inst_clr(code, true));
518                 default: return(resHALT);
519               }
520             case 0xd:
521             case 0xe:
522               switch (code & 0xf) {
523                 case 0x0: return(inst_sub(code, true));
524                 case 0x1: return(inst_cmp(code, true));
525                 case 0x2: return(inst_sbc(code, true));
526                 case 0x3: return(inst_cpx(code, true));
527                 case 0x4: return(inst_and(code, true));
528                 case 0x5: return(inst_bit(code, true));
529                 case 0x6: return(inst_lda(code, true));
530                 case 0x7: return(inst_sta(code, true));
531                 case 0x8: return(inst_eor(code, true));
532                 case 0x9: return(inst_adc(code, true));
533                 case 0xa: return(inst_ora(code, true));
534                 case 0xb: return(inst_add(code, true));
535                 case 0xc: return(resHALT);
536                 case 0xd: putchar(regs.A); fflush(stdout); return(resGO);
537                 case 0xe: return(inst_ldx(code, true));
538                 case 0xf: return(inst_stx(code, true));
539                 default: return(resHALT);
540               }
541             default: return(resHALT);
542           }
543               
544       }
545     case 0xa:
546     case 0xb:
547     case 0xc:
548     case 0xd:
549     case 0xe:
550     case 0xf:
551       switch (code & 0xf) {
552         case 0x0: return(inst_sub(code, false));
553         case 0x1: return(inst_cmp(code, false));
554         case 0x2: return(inst_sbc(code, false));
555         case 0x3: return(inst_cpx(code, false));
556         case 0x4: return(inst_and(code, false));
557         case 0x5: return(inst_bit(code, false));
558         case 0x6: return(inst_lda(code, false));
559         case 0x7:
560           if (code==0xa7)
561             return(inst_ais(code, false));
562           else
563             return(inst_sta(code, false));
564         case 0x8: return(inst_eor(code, false));
565         case 0x9: return(inst_adc(code, false));
566         case 0xa: return(inst_ora(code, false));
567         case 0xb: return(inst_add(code, false));
568         case 0xc:
569           if (code==0xac)
570             return(resHALT);
571           else
572             return(inst_jmp(code, false));
573         case 0xd:
574           if (code==0xad)
575             return(inst_bsr(code, false));
576           else
577             return(inst_jsr(code, false));
578         case 0xe: return(inst_ldx(code, false));
579         case 0xf:
580           if (code==0xaf)
581             return(inst_aix(code, false));
582           else
583             return(inst_stx(code, false));
584         default: return(resHALT);
585       }
586     default: return(resHALT);
587   }
588
589   /*if (PC)
590     PC--;
591   else
592   PC= get_mem_size(MEM_ROM_ID)-1;*/
593   PC= rom->inc_address(PC, -1);
594
595   sim->stop(resINV_INST);
596   return(resINV_INST);
597 }
598
599
600 /* End of hc08.src/hc08.cc */