work in progress
[fw/sdcc] / sim / ucsim / xa.src / xa.cc
1 /*
2  * Simulator of microcontrollers (xa.cc)
3  *
4  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5  *
6  * Written by Karl Bongers karl@turbobit.com
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 <stdio.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35 #include "i_string.h"
36
37 // prj
38 #include "pobjcl.h"
39
40 // sim
41 #include "simcl.h"
42
43 // local
44 #include "xacl.h"
45 #include "glob.h"
46 #include "regsxa.h"
47
48
49 /*
50  * Base type of xa controllers
51  */
52
53 cl_xa::cl_xa(class cl_sim *asim):
54   cl_uc(asim)
55 {
56   type= CPU_XA;
57 }
58
59 int
60 cl_xa::init(void)
61 {
62   cl_uc::init(); /* Memories now exist */
63   ram= mem(MEM_XRAM);
64   rom= mem(MEM_ROM);
65
66   wmem_direct = (TYPE_UWORD *) &mem_direct[0];
67
68   /* initialize SP to 100H */
69   set_reg2(7*2, 0x100);
70
71   printf("The XA Simulator is in development, UNSTABLE, DEVELOPERS ONLY!\n");
72
73   return(0);
74 }
75
76 char *
77 cl_xa::id_string(void)
78 {
79   return("unspecified XA");
80 }
81
82
83 /*
84  * Making elements of the controller
85  */
86
87 t_addr
88 cl_xa::get_mem_size(enum mem_class type)
89 {
90   switch(type)
91     {
92     case MEM_ROM: return(0x10000);
93     case MEM_XRAM: return(0x10000);
94     default: return(0);
95     }
96  return(cl_uc::get_mem_size(type));
97 }
98
99 void
100 cl_xa::mk_hw_elements(void)
101 {
102   //class cl_base *o;
103   /* t_uc::mk_hw() does nothing */
104 }
105
106
107 /*
108  * Help command interpreter
109  */
110
111 struct dis_entry *
112 cl_xa::dis_tbl(void)
113 {
114   // this should be unused, we need to make main prog code
115   // independent of any array thing.
116   printf("ERROR - Using disass[] table in XA sim code!\n");
117   return(glob_disass_xa);
118 }
119
120 /*struct name_entry *
121 cl_xa::sfr_tbl(void)
122 {
123   return(0);
124 }*/
125
126 /*struct name_entry *
127 cl_xa::bit_tbl(void)
128 {
129   //FIXME
130   return(0);
131 }*/
132
133 int
134 cl_xa::inst_length(t_addr addr)
135 {
136   int len = 0;
137
138   get_disasm_info(addr, &len, NULL, NULL, NULL, NULL);
139
140   return len;
141 }
142
143 int
144 cl_xa::inst_branch(t_addr addr)
145 {
146   int b;
147
148   get_disasm_info(addr, NULL, &b, NULL, NULL, NULL);
149
150   return b;
151 }
152
153 int
154 cl_xa::longest_inst(void)
155 {
156   return 6;
157 }
158
159 /*--------------------------------------------------------------------
160 get_disasm_info -
161 |--------------------------------------------------------------------*/
162 int
163 cl_xa::get_disasm_info(t_addr addr,
164                        int *ret_len,
165                        int *ret_branch,
166                        int *immed_offset,
167                        int *parms,
168                        int *mnemonic)
169 {
170   uint code;
171   int len = 0;
172   int immed_n = 0;
173   int i;
174   int start_addr = addr;
175
176   code= get_mem(MEM_ROM, addr++);
177   if (code == 0x00) {
178     i= 0;
179     while (disass_xa[i].mnemonic != NOP)
180       i++;
181   } else {
182     len = 2;
183     code = (code << 8) | get_mem(MEM_ROM, addr++);
184     i= 0;
185     while ((code & disass_xa[i].mask) != disass_xa[i].code &&
186            disass_xa[i].mnemonic != BAD_OPCODE)
187       i++;
188   }
189
190   if (ret_len)
191     *ret_len = disass_xa[i].length;
192   if (ret_branch)
193    *ret_branch = disass_xa[i].branch;
194   if (immed_offset) {
195     if (immed_n > 0)
196          *immed_offset = immed_n;
197     else *immed_offset = (addr - start_addr);
198   }
199   if (parms) {
200     *parms = disass_xa[i].operands;
201   }
202   if (mnemonic) {
203     *mnemonic = disass_xa[i].mnemonic;
204   }
205
206   return code;
207 }
208
209 static char *w_reg_strs[] = {
210  "R0", "R1",
211  "R2", "R3",
212  "R4", "R5",
213  "R6", "R7",
214  "R8", "R9",
215  "R10", "R11",
216  "R12", "R13",
217  "R14", "R15"};
218
219 static char *b_reg_strs[] = {
220  "R0l", "R0h",
221  "R1l", "R1h",
222  "R2l", "R2h",
223  "R3l", "R3h",
224  "R4l", "R4h",
225  "R5l", "R5h",
226  "R6l", "R6h",
227  "R7l", "R7h"};
228
229 /*--------------------------------------------------------------------
230 disass -
231 |--------------------------------------------------------------------*/
232 char *
233 cl_xa::disass(t_addr addr, char *sep)
234 {
235   char work[256], parm_str[40];
236   char *buf, *p, *b;
237   int code;
238   int len = 0;
239   int immed_offset = 0;
240   int operands;
241   int mnemonic;
242   char **reg_strs;
243
244   p= work;
245
246   code = get_disasm_info(addr, &len, NULL, &immed_offset, &operands, &mnemonic);
247
248   if (mnemonic == BAD_OPCODE) {
249     buf= (char*)malloc(30);
250     strcpy(buf, "UNKNOWN/INVALID");
251     return(buf);
252   }
253
254   if (code & 0x0800)
255     reg_strs = w_reg_strs;
256   else
257     reg_strs = b_reg_strs;
258
259   switch(operands) {
260      // the repeating common parameter encoding for ADD, ADDC, SUB, AND...
261     case REG_REG :
262       sprintf(parm_str, "%s,%s",
263               reg_strs[((code >> 4) & 0xf)],
264               reg_strs[(code & 0xf)]);
265     break;
266     case REG_IREG :
267       sprintf(parm_str, "%s,[%s]",
268               reg_strs[((code >> 4) & 0xf)],
269               w_reg_strs[(code & 0xf)]);
270     break;
271     case IREG_REG :
272       sprintf(parm_str, "[%s],%s",
273               w_reg_strs[(code & 0x7)],
274               reg_strs[((code >> 4) & 0xf)] );
275     break;
276     case REG_IREGOFF8 :
277       sprintf(parm_str, "%s,[%s+%02d]",
278               reg_strs[((code >> 4) & 0xf)],
279               w_reg_strs[(code & 0x7)],
280               get_mem(MEM_ROM, addr+immed_offset));
281       ++immed_offset;
282     break;
283     case IREGOFF8_REG :
284       sprintf(parm_str, "[%s+%02d],%s",
285               w_reg_strs[(code & 0x7)],
286               get_mem(MEM_ROM, addr+immed_offset),
287               reg_strs[((code >> 4) & 0xf)] );
288       ++immed_offset;
289     break;
290     case REG_IREGOFF16 :
291       sprintf(parm_str, "%s,[%s+%04d]",
292               reg_strs[((code >> 4) & 0xf)],
293               w_reg_strs[(code & 0x7)],
294               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
295                      (get_mem(MEM_ROM, addr+immed_offset)<<8)) );
296       ++immed_offset;
297       ++immed_offset;
298     break;
299     case IREGOFF16_REG :
300       sprintf(parm_str, "[%s+%04d],%s",
301               w_reg_strs[(code & 0x7)],
302               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
303                      (get_mem(MEM_ROM, addr+immed_offset)<<8)),
304               reg_strs[((code >> 4) & 0xf)] );
305       ++immed_offset;
306       ++immed_offset;
307     break;
308     case REG_IREGINC :
309       sprintf(parm_str, "%s,[%s+]",
310               reg_strs[((code >> 4) & 0xf)],
311               w_reg_strs[(code & 0xf)]);
312     break;
313     case IREGINC_REG :
314       sprintf(parm_str, "[%s+],%s",
315               w_reg_strs[(code & 0x7)],
316               reg_strs[((code >> 4) & 0xf)] );
317     break;
318     case DIRECT_REG :
319       sprintf(parm_str, "0x%04x,%s",
320               ((code & 0x3) << 8) | get_mem(MEM_ROM, addr+immed_offset),
321               reg_strs[((code >> 4) & 0xf)] );
322       ++immed_offset;
323     break;
324     case REG_DIRECT :
325       sprintf(parm_str, "%s, @0x%04x",
326               reg_strs[((code >> 4) & 0xf)],
327               ((code & 0x3) << 8) | get_mem(MEM_ROM, addr+immed_offset) );
328       ++immed_offset;
329     break;
330     case REG_DATA8 :
331       sprintf(parm_str, "%s, #%02d",
332               b_reg_strs[((code >> 4) & 0xf)],
333               get_mem(MEM_ROM, addr+immed_offset) );
334       ++immed_offset;
335     break;
336     case REG_DATA16 :
337       sprintf(parm_str, "%s, #%04d",
338               reg_strs[((code >> 4) & 0xf)],
339               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
340                      (get_mem(MEM_ROM, addr+immed_offset)<<8)) );
341       ++immed_offset;
342       ++immed_offset;
343     break;
344     case IREG_DATA8 :
345       sprintf(parm_str, "[%s], 0x%02x",
346               w_reg_strs[((code >> 4) & 0x7)],
347               get_mem(MEM_ROM, addr+immed_offset) );
348       ++immed_offset;
349     break;
350     case IREG_DATA16 :
351       sprintf(parm_str, "[%s], 0x%04x",
352               w_reg_strs[((code >> 4) & 0x7)],
353               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
354                      (get_mem(MEM_ROM, addr+immed_offset)<<8)) );
355       ++immed_offset;
356       ++immed_offset;
357     break;
358     case IREGINC_DATA8 :
359       sprintf(parm_str, "[%s+], 0x%02x",
360               w_reg_strs[((code >> 4) & 0x7)],
361               get_mem(MEM_ROM, addr+immed_offset) );
362       ++immed_offset;
363     break;
364     case IREGINC_DATA16 :
365       sprintf(parm_str, "[%s+], 0x%04x",
366               w_reg_strs[((code >> 4) & 0x7)],
367               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
368                      (get_mem(MEM_ROM, addr+immed_offset)<<8)) );
369       ++immed_offset;
370       ++immed_offset;
371     break;
372     case IREGOFF8_DATA8 :
373       sprintf(parm_str, "[%s+%02d], 0x%02x",
374               w_reg_strs[((code >> 4) & 0x7)],
375               get_mem(MEM_ROM, addr+immed_offset),
376               get_mem(MEM_ROM, addr+immed_offset+1) );
377       immed_offset += 2;
378     break;
379     case IREGOFF8_DATA16 :
380       sprintf(parm_str, "[%s+%02d], 0x%04x",
381               w_reg_strs[((code >> 4) & 0x7)],
382               get_mem(MEM_ROM, addr+immed_offset),
383               (short)((get_mem(MEM_ROM, addr+immed_offset+2)) |
384                      (get_mem(MEM_ROM, addr+immed_offset+1)<<8)) );
385       immed_offset += 3;
386     break;
387     case IREGOFF16_DATA8 :
388       sprintf(parm_str, "[%s+%04d], 0x%02x",
389               w_reg_strs[((code >> 4) & 0x7)],
390               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
391                      (get_mem(MEM_ROM, addr+immed_offset+0)<<8)),
392               get_mem(MEM_ROM, addr+immed_offset+2) );
393       immed_offset += 3;
394     break;
395     case IREGOFF16_DATA16 :
396       sprintf(parm_str, "[%s+%04d], 0x%04x",
397               w_reg_strs[((code >> 4) & 0x7)],
398               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
399                      (get_mem(MEM_ROM, addr+immed_offset+0)<<8)),
400               (short)((get_mem(MEM_ROM, addr+immed_offset+3)) |
401                      (get_mem(MEM_ROM, addr+immed_offset+2)<<8)) );
402       immed_offset += 4;
403     break;
404     case DIRECT_DATA8 :
405       sprintf(parm_str, "0x%03x,#0x%02x",
406               ((code & 0x0070) << 4) | get_mem(MEM_ROM, addr+immed_offset),
407               get_mem(MEM_ROM, addr+immed_offset+1));
408       immed_offset += 3;
409     break;
410     case DIRECT_DATA16 :
411       sprintf(parm_str, "%0x03x,#0x%04x",
412               ((code & 0x0070) << 4) | get_mem(MEM_ROM, addr+immed_offset),
413               get_mem(MEM_ROM, addr+immed_offset+2) +
414               (get_mem(MEM_ROM, addr+immed_offset+1)<<8));
415       immed_offset += 3;
416     break;
417
418 // odd-ball ones
419     case NO_OPERANDS :  // for NOP
420       strcpy(parm_str, "");
421     break;
422     case C_BIT :
423       strcpy(parm_str, "C_BIT");
424     break;
425     case REG_DATA4 :
426       strcpy(parm_str, "REG_DATA4");
427     break;
428     case IREG_DATA4 :
429       strcpy(parm_str, "IREG_DATA4");
430     break;
431     case IREGINC_DATA4 :
432       strcpy(parm_str, "IREGINC_DATA4");
433     break;
434     case IREGOFF8_DATA4 :
435       strcpy(parm_str, "IREGOFF8_DATA4");
436     break;
437     case IREGOFF16_DATA4 :
438       strcpy(parm_str, "IREGOFF16_DATA4");
439     break;
440     case DIRECT_DATA4 :
441       strcpy(parm_str, "DIRECT_DATA4");
442     break;
443
444     case REG_ALONE :
445       sprintf(parm_str, "%s",
446               reg_strs[((code >> 4) & 0xf)] );
447     break;
448     case IREG_ALONE :
449       sprintf(parm_str, "[%s]",
450               reg_strs[((code >> 4) & 0xf)] );
451     break;
452     case ADDR24 :
453       strcpy(parm_str, "ADDR24");
454     break;
455     case REG_REL8 :
456       strcpy(parm_str, "REG_REL8");
457     break;
458     case DIRECT_REL8 :
459       strcpy(parm_str, "DIRECT_REL8");
460     break;
461
462     case REL8 :
463       //strcpy(parm_str, "REL8");
464       sprintf(parm_str, "0x%04x",
465               (get_mem(MEM_ROM, addr+1)*2+addr+len)&0xfffe);
466     break;
467     case REL16 :
468       //strcpy(parm_str, "REL16");
469       sprintf(parm_str, "0x%04x",
470               (((get_mem(MEM_ROM, addr+1)<<8) |
471               get_mem(MEM_ROM, addr+2))*2+addr+len)&0xfffe);
472     break;
473
474     default:
475       strcpy(parm_str, "???");
476     break;
477   }
478
479   sprintf(work, "%s %s",
480           op_mnemonic_str[ mnemonic ],
481           parm_str);
482
483   p= strchr(work, ' ');
484   if (!p)
485     {
486       buf= strdup(work);
487       return(buf);
488     }
489   if (sep == NULL)
490     buf= (char *)malloc(6+strlen(p)+1);
491   else
492     buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
493   for (p= work, b= buf; *p != ' '; p++, b++)
494     *b= *p;
495   p++;
496   *b= '\0';
497   if (sep == NULL)
498     {
499       while (strlen(buf) < 6)
500         strcat(buf, " ");
501     }
502   else
503     strcat(buf, sep);
504   strcat(buf, p);
505   return(buf);
506 }
507
508 /*--------------------------------------------------------------------
509  print_regs -
510 |--------------------------------------------------------------------*/
511 void
512 cl_xa::print_regs(class cl_console *con)
513 {
514   unsigned char flags;
515
516   flags = get_psw();
517   con->dd_printf("CA---VNZ  Flags: %02x ", flags);
518   con->dd_printf("R0:%04x R1:%04x R2:%04x R3:%04x\n",
519                  get_reg(1,0), get_reg(1,2), get_reg(1,4), get_reg(1,6));
520
521   con->dd_printf("%c%c---%c%c%c            ",
522          (flags & BIT_C)?'1':'0',
523          (flags & BIT_AC)?'1':'0',
524          (flags & BIT_V)?'1':'0',
525          (flags & BIT_N)?'1':'0',
526          (flags & BIT_Z)?'1':'0');
527
528   con->dd_printf("R4:%04x R5:%04x R6:%04x R7(SP):%04x ES:%04x  DS:%04x\n",
529             get_reg(1,8), get_reg(1,10), get_reg(1,12), get_reg(1,14), 0, 0);
530
531   print_disass(PC, con);
532 }
533
534
535 /*
536  * Execution
537  */
538
539 int
540 cl_xa::exec_inst(void)
541 {
542   t_mem code1;
543   uint code;
544   int i;
545   int operands;
546
547   if (fetch(&code1))
548     return(resBREAKPOINT);
549   tick(1);
550
551 /* the following lookups make for a slow simulation, we will
552   figure out how to make it fast later... */
553
554   /* scan to see if its a 1 byte-opcode */
555   code = (code1 << 8);
556   i= 0;
557   while ( ((code & disass_xa[i].mask) != disass_xa[i].code ||
558            ((disass_xa[i].mask & 0x00ff) != 0)) /* one byte op code */
559                     &&
560          disass_xa[i].mnemonic != BAD_OPCODE)
561     i++;
562
563   if (disass_xa[i].mnemonic == BAD_OPCODE) {
564     /* hit the end of the list, must be a 2 or more byte opcode */
565     /* fetch another code byte and search the list again */
566       //if (fetch(&code2))  ?not sure if break allowed in middle of opcode?
567       //  return(resBREAKPOINT);
568     code |= fetch();  /* add 2nd opcode */
569
570     i= 0;
571     while ((code & disass_xa[i].mask) != disass_xa[i].code &&
572            disass_xa[i].mnemonic != BAD_OPCODE)
573       i++;
574     /* we should have found the opcode by now, if not invalid entry at eol */
575   }
576
577   operands = (int)(disass_xa[i].operands);
578   switch (disass_xa[i].mnemonic)
579   {
580     case ADD:
581     return inst_ADD(code, operands);
582     case ADDC:
583     return inst_ADDC(code, operands);
584     case SUB:
585     return inst_SUB(code, operands);
586     case SUBB:
587     return inst_SUBB(code, operands);
588     case CMP:
589     return inst_CMP(code, operands);
590     case AND:
591     return inst_AND(code, operands);
592     case OR:
593     return inst_OR(code, operands);
594     case XOR:
595     return inst_XOR(code, operands);
596     case ADDS:
597     return inst_ADDS(code, operands);
598     case NEG:
599     return inst_NEG(code, operands);
600     case SEXT:
601     return inst_SEXT(code, operands);
602     case MUL:
603     return inst_MUL(code, operands);
604     case DIV_w :
605     case DIV_d :
606     case DIVU_b:
607     case DIVU_w:
608     case DIVU_d:
609     return inst_DIV(code, operands);
610     case DA:
611     return inst_DA(code, operands);
612     case ASL:
613     return inst_ASL(code, operands);
614     case ASR:
615     return inst_ASR(code, operands);
616     case LEA:
617     return inst_LEA(code, operands);
618     case CPL:
619     return inst_CPL(code, operands);
620     case LSR:
621     return inst_LSR(code, operands);
622     case NORM:
623     return inst_NORM(code, operands);
624     case RL:
625     return inst_RL(code, operands);
626     case RLC:
627     return inst_RLC(code, operands);
628     case RR:
629     return inst_RR(code, operands);
630     case RRC:
631     return inst_RRC(code, operands);
632     case MOVS:
633     return inst_MOVS(code, operands);
634     case MOVC:
635     return inst_MOVC(code, operands);
636     case MOVX:
637     return inst_MOVX(code, operands);
638     case PUSH:
639     return inst_PUSH(code, operands);
640     case POP:
641     return inst_POP(code, operands);
642     case XCH:
643     return inst_XCH(code, operands);
644     case SETB:
645     return inst_SETB(code, operands);
646     case CLR:
647     return inst_CLR(code, operands);
648     case MOV:
649     return inst_MOV(code, operands);
650     case ANL:
651     return inst_ANL(code, operands);
652     case ORL:
653     return inst_ORL(code, operands);
654     case BR:
655     return inst_BR(code, operands);
656     case JMP:
657     return inst_JMP(code, operands);
658     case CALL:
659     return inst_CALL(code, operands);
660     case RET:
661     return inst_RET(code, operands);
662     case Bcc:
663     return inst_Bcc(code, operands);
664     case JB:
665     return inst_JB(code, operands);
666     case JNB:
667     return inst_JNB(code, operands);
668     case CJNE:
669     return inst_CJNE(code, operands);
670     case DJNZ:
671     return inst_DJNZ(code, operands);
672     case JZ:
673     return inst_JZ(code, operands);
674     case JNZ:
675     return inst_JNZ(code, operands);
676     case NOP:
677     return inst_NOP(code, operands);
678     case BKPT:
679     return inst_BKPT(code, operands);
680     case TRAP:
681     return inst_TRAP(code, operands);
682     case RESET:
683     return inst_RESET(code, operands);
684     case BAD_OPCODE:
685     default:
686     break;
687   }
688
689   if (PC)
690     PC--;
691   else
692     PC= get_mem_size(MEM_ROM)-1;
693   //tick(-clock_per_cycle());
694   sim->stop(resINV_INST);
695   return(resINV_INST);
696 }
697
698
699 /* End of xa.src/xa.cc */