added a few opcodes
[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%03x,%s",
320               ((code & 0x7) << 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%03x",
326               reg_strs[((code >> 4) & 0xf)],
327               ((code & 0x7) << 8) + get_mem(MEM_ROM, addr+immed_offset) );
328       ++immed_offset;
329     break;
330     case REG_DATA8 :
331       sprintf(parm_str, "%s,#0x%02x",
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,#%04x",
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     case DIRECT_ALONE :
444       sprintf(parm_str, "0x%03x",
445               ((code & 0x007) << 4) + get_mem(MEM_ROM, addr+2));
446     break;
447     case REG_ALONE :
448       sprintf(parm_str, "%s",
449               reg_strs[((code >> 4) & 0xf)] );
450     break;
451     case IREG_ALONE :
452       sprintf(parm_str, "[%s]",
453               reg_strs[((code >> 4) & 0xf)] );
454     break;
455     case BIT_ALONE :
456       sprintf(parm_str, "0x%03x",
457               ((code&0x0003)<<8) + get_mem(MEM_ROM, addr+2));
458     break;
459     case BIT_REL8 :
460       sprintf(parm_str, "0x%03x,0x%04x",
461               ((code&0x0003)<<8) + get_mem(MEM_ROM, addr+2),
462               ((signed char)get_mem(MEM_ROM, addr+3)*2+addr+len)&0xfffe);
463     break;
464     case ADDR24 :
465       strcpy(parm_str, "ADDR24");
466     break;
467     case REG_REL8 :
468       //strcpy(parm_str, "REG_REL8");
469       sprintf(parm_str, "%s,0x%04x",
470               reg_strs[(code>>4) & 0xf],
471               ((signed char)get_mem(MEM_ROM, addr+2)*2+addr+len)&0xfffe);
472     break;
473     case DIRECT_REL8 :
474       strcpy(parm_str, "DIRECT_REL8");
475     break;
476
477     case REL8 :
478       //strcpy(parm_str, "REL8");
479       sprintf(parm_str, "0x%04x",
480               ((signed char)get_mem(MEM_ROM, addr+1)*2+addr+len)&0xfffe);
481     break;
482     case REL16 :
483       //strcpy(parm_str, "REL16");
484       sprintf(parm_str, "0x%04x",
485               ((signed short)((get_mem(MEM_ROM, addr+1)<<8) + get_mem(MEM_ROM, addr+2))*2+addr+len)&0xfffe);
486     break;
487
488     case RLIST :
489       strcpy(parm_str, "RLIST");
490     break;
491
492     default:
493       strcpy(parm_str, "???");
494     break;
495   }
496
497   sprintf(work, "%s %s",
498           op_mnemonic_str[ mnemonic ],
499           parm_str);
500
501   p= strchr(work, ' ');
502   if (!p)
503     {
504       buf= strdup(work);
505       return(buf);
506     }
507   if (sep == NULL)
508     buf= (char *)malloc(6+strlen(p)+1);
509   else
510     buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
511   for (p= work, b= buf; *p != ' '; p++, b++)
512     *b= *p;
513   p++;
514   *b= '\0';
515   if (sep == NULL)
516     {
517       while (strlen(buf) < 6)
518         strcat(buf, " ");
519     }
520   else
521     strcat(buf, sep);
522   strcat(buf, p);
523   return(buf);
524 }
525
526 /*--------------------------------------------------------------------
527  print_regs -
528 |--------------------------------------------------------------------*/
529 void
530 cl_xa::print_regs(class cl_console *con)
531 {
532   unsigned char flags;
533
534   flags = get_psw();
535   con->dd_printf("CA---VNZ  Flags: %02x ", flags);
536   con->dd_printf("R0:%04x R1:%04x R2:%04x R3:%04x\n",
537                  get_reg(1,0), get_reg(1,2), get_reg(1,4), get_reg(1,6));
538
539   con->dd_printf("%c%c---%c%c%c            ",
540          (flags & BIT_C)?'1':'0',
541          (flags & BIT_AC)?'1':'0',
542          (flags & BIT_V)?'1':'0',
543          (flags & BIT_N)?'1':'0',
544          (flags & BIT_Z)?'1':'0');
545
546   con->dd_printf("R4:%04x R5:%04x R6:%04x R7(SP):%04x ES:%04x  DS:%04x\n",
547             get_reg(1,8), get_reg(1,10), get_reg(1,12), get_reg(1,14), 0, 0);
548
549   print_disass(PC, con);
550 }
551
552
553 /*
554  * Execution
555  */
556
557 int
558 cl_xa::exec_inst(void)
559 {
560   t_mem code1;
561   uint code;
562   int i;
563   int operands;
564
565   if (fetch(&code1))
566     return(resBREAKPOINT);
567   tick(1);
568
569 /* the following lookups make for a slow simulation, we will
570   figure out how to make it fast later... */
571
572   /* scan to see if its a 1 byte-opcode */
573   code = (code1 << 8);
574   i= 0;
575   while ( ((code & disass_xa[i].mask) != disass_xa[i].code ||
576            ((disass_xa[i].mask & 0x00ff) != 0)) /* one byte op code */
577                     &&
578          disass_xa[i].mnemonic != BAD_OPCODE)
579     i++;
580
581   if (disass_xa[i].mnemonic == BAD_OPCODE) {
582     /* hit the end of the list, must be a 2 or more byte opcode */
583     /* fetch another code byte and search the list again */
584       //if (fetch(&code2))  ?not sure if break allowed in middle of opcode?
585       //  return(resBREAKPOINT);
586     code |= fetch();  /* add 2nd opcode */
587
588     i= 0;
589     while ((code & disass_xa[i].mask) != disass_xa[i].code &&
590            disass_xa[i].mnemonic != BAD_OPCODE)
591       i++;
592     /* we should have found the opcode by now, if not invalid entry at eol */
593   }
594
595   operands = (int)(disass_xa[i].operands);
596   switch (disass_xa[i].mnemonic)
597   {
598     case ADD:
599     return inst_ADD(code, operands);
600     case ADDC:
601     return inst_ADDC(code, operands);
602     case SUB:
603     return inst_SUB(code, operands);
604     case SUBB:
605     return inst_SUBB(code, operands);
606     case CMP:
607     return inst_CMP(code, operands);
608     case AND:
609     return inst_AND(code, operands);
610     case OR:
611     return inst_OR(code, operands);
612     case XOR:
613     return inst_XOR(code, operands);
614     case ADDS:
615     return inst_ADDS(code, operands);
616     case NEG:
617     return inst_NEG(code, operands);
618     case SEXT:
619     return inst_SEXT(code, operands);
620     case MUL:
621     return inst_MUL(code, operands);
622     case DIV_w :
623     case DIV_d :
624     case DIVU_b:
625     case DIVU_w:
626     case DIVU_d:
627     return inst_DIV(code, operands);
628     case DA:
629     return inst_DA(code, operands);
630     case ASL:
631     return inst_ASL(code, operands);
632     case ASR:
633     return inst_ASR(code, operands);
634     case LEA:
635     return inst_LEA(code, operands);
636     case CPL:
637     return inst_CPL(code, operands);
638     case LSR:
639     return inst_LSR(code, operands);
640     case NORM:
641     return inst_NORM(code, operands);
642     case RL:
643     return inst_RL(code, operands);
644     case RLC:
645     return inst_RLC(code, operands);
646     case RR:
647     return inst_RR(code, operands);
648     case RRC:
649     return inst_RRC(code, operands);
650     case MOVS:
651     return inst_MOVS(code, operands);
652     case MOVC:
653     return inst_MOVC(code, operands);
654     case MOVX:
655     return inst_MOVX(code, operands);
656     case PUSH:
657     return inst_PUSH(code, operands);
658     case POP:
659     return inst_POP(code, operands);
660     case XCH:
661     return inst_XCH(code, operands);
662     case SETB:
663     return inst_SETB(code, operands);
664     case CLR:
665     return inst_CLR(code, operands);
666     case MOV:
667     return inst_MOV(code, operands);
668     case ANL:
669     return inst_ANL(code, operands);
670     case ORL:
671     return inst_ORL(code, operands);
672     case BR:
673     return inst_BR(code, operands);
674     case JMP:
675     return inst_JMP(code, operands);
676     case CALL:
677     return inst_CALL(code, operands);
678     case RET:
679     return inst_RET(code, operands);
680     case BCC:
681     return inst_Bcc(code, operands);
682     case JB:
683     return inst_JB(code, operands);
684     case JNB:
685     return inst_JNB(code, operands);
686     case CJNE:
687     return inst_CJNE(code, operands);
688     case DJNZ:
689     return inst_DJNZ(code, operands);
690     case JZ:
691     return inst_JZ(code, operands);
692     case JNZ:
693     return inst_JNZ(code, operands);
694     case NOP:
695     return inst_NOP(code, operands);
696     case BKPT:
697     return inst_BKPT(code, operands);
698     case TRAP:
699     return inst_TRAP(code, operands);
700     case RESET:
701     return inst_RESET(code, operands);
702     case BAD_OPCODE:
703     default:
704     break;
705   }
706
707   if (PC)
708     PC--;
709   else
710     PC= get_mem_size(MEM_ROM)-1;
711   //tick(-clock_per_cycle());
712   sim->stop(resINV_INST);
713   return(resINV_INST);
714 }
715
716
717 /* End of xa.src/xa.cc */