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