da7ed0fc6d74b42a279bd22124bcf800f7e86fae
[fw/sdcc] / sim / ucsim / xa.src / xa.cc
1 /*
2  * Simulator of microcontrollers (xa.cc)
3  *
4  * Copyright (C) 1999,2002 Drotos Daniel, Talker Bt.
5  *
6  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7  * Other contributors include:
8  *   Karl Bongers karl@turbobit.com,
9  *   Johan Knol johan.knol@iduna.nl
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  * Base type of xa controllers
50  */
51
52 cl_xa::cl_xa(class cl_sim *asim):
53   cl_uc(asim)
54 {
55   type= CPU_XA;
56 }
57
58 int
59 cl_xa::init(void)
60 {
61   cl_uc::init(); /* Memories now exist */
62   ram= mem(MEM_XRAM);
63   rom= mem(MEM_ROM);
64
65   /* set SCR to osc/4, native XA mode, flat 24 */
66   set_scr(0);
67   /* initialize SP to 100H */
68   set_reg2(7, 0x100);
69   /* set PSW from reset vector */
70   set_psw(getcode2(0));
71   /* set PC from reset vector */
72   PC = getcode2(2);
73
74   printf("The XA Simulator is in development, UNSTABLE, DEVELOPERS ONLY!\n");
75
76   return(0);
77 }
78
79 class cl_mem *
80 cl_xa::mk_mem(enum mem_class type, char *class_name)
81 {
82   class cl_mem *m= cl_uc::mk_mem(type, class_name);
83   if (type == MEM_SFR)
84     sfr= m;
85   if (type == MEM_IRAM)
86     iram= m;
87   return(m);
88 }
89
90 char *
91 cl_xa::id_string(void)
92 {
93   return("unspecified XA");
94 }
95
96
97 /*
98  * Making elements of the controller
99  */
100
101 t_addr
102 cl_xa::get_mem_size(enum mem_class type)
103 {
104   switch(type)
105     {
106     case MEM_IRAM: return(0x2000);
107     case MEM_SFR: return(0x2000);
108     case MEM_ROM: return(0x10000);
109     case MEM_XRAM: return(0x10000);
110     default: return(0);
111     }
112  return(cl_uc::get_mem_size(type));
113 }
114
115 void
116 cl_xa::mk_hw_elements(void)
117 {
118   //class cl_base *o;
119   /* t_uc::mk_hw() does nothing */
120 }
121
122
123 /*
124  * Help command interpreter
125  */
126
127 struct dis_entry *
128 cl_xa::dis_tbl(void)
129 {
130   // this should be unused, we need to make main prog code
131   // independent of any array thing.
132   printf("ERROR - Using disass[] table in XA sim code!\n");
133   return(glob_disass_xa);
134 }
135
136 struct name_entry *cl_xa::sfr_tbl(void)
137 {
138   return(sfr_tabXA51);
139 }
140
141 struct name_entry *cl_xa::bit_tbl(void)
142 {
143   return(bit_tabXA51);
144 }
145
146 int
147 cl_xa::inst_length(t_addr addr)
148 {
149   int len = 0;
150
151   get_disasm_info(addr, &len, NULL, NULL, NULL, NULL);
152
153   return len;
154 }
155
156 int
157 cl_xa::inst_branch(t_addr addr)
158 {
159   int b;
160
161   get_disasm_info(addr, NULL, &b, NULL, NULL, NULL);
162
163   return b;
164 }
165
166 int
167 cl_xa::longest_inst(void)
168 {
169   return 6;
170 }
171
172 static char dir_name[64];
173 char *cl_xa::get_dir_name(short addr) {
174   if (!get_name(addr, sfr_tbl(), dir_name)) {
175     sprintf (dir_name, "0x%03x", addr);
176   }
177   return dir_name;
178 }
179
180 static char bit_name[64];
181 char *cl_xa::get_bit_name(short addr) {
182   if (!get_name(addr, bit_tbl(), bit_name)) {
183     sprintf (bit_name, "0x%03x", addr);
184   }
185   return bit_name;
186 }
187
188 /*--------------------------------------------------------------------
189 get_disasm_info - Given an address, return information about the opcode
190   which resides there.
191   addr - address of opcode we want information on.
192   ret_len - return length of opcode.
193   ret_branch - return a character which indicates if we are
194     a branching opcode.  Used by main app to implement "Next"
195     function which steps over functions.
196   immed_offset - return a number which represents the number of bytes
197     offset to where any immediate data is(tail end of opcode).  Used
198     for printing disassembly.
199   operands - return a key indicating the form of the operands,
200     used for printing the disassembly.
201   mnemonic - return a key indicating the mnemonic of the instruction.
202
203   Return value: Return the operand code formed by either the single
204   byte opcode or 2 bytes of the opcode for multi-byte opcodes.
205
206   Note: Any of the return pointer parameters can be set to NULL to
207     indicate the caller does not want the information.
208 |--------------------------------------------------------------------*/
209 int
210 cl_xa::get_disasm_info(t_addr addr,
211                        int *ret_len,
212                        int *ret_branch,
213                        int *immed_offset,
214                        int *parms,
215                        int *mnemonic)
216 {
217   uint code;
218   int len = 0;
219   int immed_n = 0;
220   int i;
221   int start_addr = addr;
222
223   code= get_mem(MEM_ROM, addr++);
224   if (code == 0x00) {
225     i= 0;
226     while (disass_xa[i].mnemonic != NOP)
227       i++;
228   } else {
229     len = 2;
230     code = (code << 8) | get_mem(MEM_ROM, addr++);
231     i= 0;
232     while ((code & disass_xa[i].mask) != disass_xa[i].code &&
233            disass_xa[i].mnemonic != BAD_OPCODE)
234       i++;
235   }
236
237   if (ret_len)
238     *ret_len = disass_xa[i].length;
239   if (ret_branch)
240    *ret_branch = disass_xa[i].branch;
241   if (immed_offset) {
242     if (immed_n > 0)
243          *immed_offset = immed_n;
244     else *immed_offset = (addr - start_addr);
245   }
246   if (parms) {
247     *parms = disass_xa[i].operands;
248   }
249   if (mnemonic) {
250     *mnemonic = disass_xa[i].mnemonic;
251   }
252
253   return code;
254 }
255
256 static char *w_reg_strs[] = {
257  "R0", "R1",
258  "R2", "R3",
259  "R4", "R5",
260  "R6", "R7",
261  "R8", "R9",
262  "R10", "R11",
263  "R12", "R13",
264  "R14", "R15"};
265
266 static char *b_reg_strs[] = {
267  "R0l", "R0h",
268  "R1l", "R1h",
269  "R2l", "R2h",
270  "R3l", "R3h",
271  "R4l", "R4h",
272  "R5l", "R5h",
273  "R6l", "R6h",
274  "R7l", "R7h"};
275
276 /*--------------------------------------------------------------------
277 disass - Disassemble an opcode.
278     addr - address of opcode to disassemble/print.
279     sep - optionally points to string(tab) to use as separator.
280 |--------------------------------------------------------------------*/
281 char *
282 cl_xa::disass(t_addr addr, char *sep)
283 {
284   char work[256], parm_str[40];
285   char *buf, *p, *b;
286   int code;
287   int len = 0;
288   int immed_offset = 0;
289   int operands;
290   int mnemonic;
291   char **reg_strs;
292
293   p= work;
294
295   code = get_disasm_info(addr, &len, NULL, &immed_offset, &operands, &mnemonic);
296
297   if (mnemonic == BAD_OPCODE) {
298     buf= (char*)malloc(30);
299     strcpy(buf, "UNKNOWN/INVALID");
300     return(buf);
301   }
302
303   if (code & 0x0800)
304     reg_strs = w_reg_strs;
305   else
306     reg_strs = b_reg_strs;
307
308   switch(operands) {
309      // the repeating common parameter encoding for ADD, ADDC, SUB, AND...
310     case REG_REG :
311       sprintf(parm_str, "%s,%s",
312               reg_strs[((code >> 4) & 0xf)],
313               reg_strs[(code & 0xf)]);
314     break;
315     case REG_IREG :
316       sprintf(parm_str, "%s,[%s]",
317               reg_strs[((code >> 4) & 0xf)],
318               w_reg_strs[(code & 0xf)]);
319     break;
320     case IREG_REG :
321       sprintf(parm_str, "[%s],%s",
322               w_reg_strs[(code & 0x7)],
323               reg_strs[((code >> 4) & 0xf)] );
324     break;
325     case REG_IREGOFF8 :
326       sprintf(parm_str, "%s,[%s+%02x]",
327               reg_strs[((code >> 4) & 0xf)],
328               w_reg_strs[(code & 0x7)],
329               get_mem(MEM_ROM, addr+immed_offset));
330       ++immed_offset;
331     break;
332     case IREGOFF8_REG :
333       sprintf(parm_str, "[%s+%02x],%s",
334               w_reg_strs[(code & 0x7)],
335               get_mem(MEM_ROM, addr+immed_offset),
336               reg_strs[((code >> 4) & 0xf)] );
337       ++immed_offset;
338     break;
339     case REG_IREGOFF16 :
340       sprintf(parm_str, "%s,[%s+%04x]",
341               reg_strs[((code >> 4) & 0xf)],
342               w_reg_strs[(code & 0x7)],
343               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
344                      (get_mem(MEM_ROM, addr+immed_offset)<<8)) );
345       ++immed_offset;
346       ++immed_offset;
347     break;
348     case IREGOFF16_REG :
349       sprintf(parm_str, "[%s+%04x],%s",
350               w_reg_strs[(code & 0x7)],
351               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
352                      (get_mem(MEM_ROM, addr+immed_offset)<<8)),
353               reg_strs[((code >> 4) & 0xf)] );
354       ++immed_offset;
355       ++immed_offset;
356     break;
357     case REG_IREGINC :
358       sprintf(parm_str, "%s,[%s+]",
359               reg_strs[((code >> 4) & 0xf)],
360               w_reg_strs[(code & 0xf)]);
361     break;
362     case IREGINC_REG :
363       sprintf(parm_str, "[%s+],%s",
364               w_reg_strs[(code & 0x7)],
365               reg_strs[((code >> 4) & 0xf)] );
366     break;
367     case DIRECT_REG :
368       sprintf(parm_str, "%s,%s",
369               get_dir_name(((code & 0x7) << 8) | 
370                            get_mem(MEM_ROM, addr+immed_offset)),
371               reg_strs[((code >> 4) & 0xf)] );
372       ++immed_offset;
373     break;
374     case REG_DIRECT :
375       sprintf(parm_str, "%s,%s",
376               reg_strs[((code >> 4) & 0xf)], 
377               get_dir_name(((code & 0x7) << 8) | 
378                            get_mem(MEM_ROM, addr+immed_offset)));
379       ++immed_offset;
380     break;
381     case REG_DATA8 :
382       sprintf(parm_str, "%s,#0x%02x",
383               b_reg_strs[((code >> 4) & 0xf)],
384               get_mem(MEM_ROM, addr+immed_offset) );
385       ++immed_offset;
386     break;
387     case REG_DATA16 :
388       sprintf(parm_str, "%s,#0x%04x",
389               reg_strs[((code >> 4) & 0xf)],
390               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
391                      (get_mem(MEM_ROM, addr+immed_offset)<<8)) );
392       ++immed_offset;
393       ++immed_offset;
394     break;
395     case IREG_DATA8 :
396       sprintf(parm_str, "[%s], 0x%02x",
397               w_reg_strs[((code >> 4) & 0x7)],
398               get_mem(MEM_ROM, addr+immed_offset) );
399       ++immed_offset;
400     break;
401     case IREG_DATA16 :
402       sprintf(parm_str, "[%s], 0x%04x",
403               w_reg_strs[((code >> 4) & 0x7)],
404               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
405                      (get_mem(MEM_ROM, addr+immed_offset)<<8)) );
406       ++immed_offset;
407       ++immed_offset;
408     break;
409     case IREGINC_DATA8 :
410       sprintf(parm_str, "[%s+], 0x%02x",
411               w_reg_strs[((code >> 4) & 0x7)],
412               get_mem(MEM_ROM, addr+immed_offset) );
413       ++immed_offset;
414     break;
415     case IREGINC_DATA16 :
416       sprintf(parm_str, "[%s+], 0x%04x",
417               w_reg_strs[((code >> 4) & 0x7)],
418               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
419                      (get_mem(MEM_ROM, addr+immed_offset)<<8)) );
420       ++immed_offset;
421       ++immed_offset;
422     break;
423     case IREGOFF8_DATA8 :
424       sprintf(parm_str, "[%s+%02x], 0x%02x",
425               w_reg_strs[((code >> 4) & 0x7)],
426               get_mem(MEM_ROM, addr+immed_offset),
427               get_mem(MEM_ROM, addr+immed_offset+1) );
428       immed_offset += 2;
429     break;
430     case IREGOFF8_DATA16 :
431       sprintf(parm_str, "[%s+%02x], 0x%04x",
432               w_reg_strs[((code >> 4) & 0x7)],
433               get_mem(MEM_ROM, addr+immed_offset),
434               (short)((get_mem(MEM_ROM, addr+immed_offset+2)) |
435                      (get_mem(MEM_ROM, addr+immed_offset+1)<<8)) );
436       immed_offset += 3;
437     break;
438     case IREGOFF16_DATA8 :
439       sprintf(parm_str, "[%s+%04x], 0x%02x",
440               w_reg_strs[((code >> 4) & 0x7)],
441               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
442                      (get_mem(MEM_ROM, addr+immed_offset+0)<<8)),
443               get_mem(MEM_ROM, addr+immed_offset+2) );
444       immed_offset += 3;
445     break;
446     case IREGOFF16_DATA16 :
447       sprintf(parm_str, "[%s+%04x], 0x%04x",
448               w_reg_strs[((code >> 4) & 0x7)],
449               (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
450                      (get_mem(MEM_ROM, addr+immed_offset+0)<<8)),
451               (short)((get_mem(MEM_ROM, addr+immed_offset+3)) |
452                      (get_mem(MEM_ROM, addr+immed_offset+2)<<8)) );
453       immed_offset += 4;
454     break;
455     case DIRECT_DATA8 :
456       sprintf(parm_str, "%s,#0x%02x",
457               get_dir_name(((code & 0x0070) << 4) | 
458                            get_mem(MEM_ROM, addr+immed_offset)),
459               get_mem(MEM_ROM, addr+immed_offset+1));
460       immed_offset += 3;
461     break;
462     case DIRECT_DATA16 :
463       sprintf(parm_str, "%s,#0x%04x",
464               get_dir_name(((code & 0x0070) << 4) | 
465                            get_mem(MEM_ROM, addr+immed_offset)),
466               get_mem(MEM_ROM, addr+immed_offset+2) +
467               (get_mem(MEM_ROM, addr+immed_offset+1)<<8));
468       immed_offset += 3;
469     break;
470
471 // odd-ball ones
472     case NO_OPERANDS :  // for NOP
473       strcpy(parm_str, "");
474     break;
475     case CY_BIT :
476       sprintf(parm_str, "C,%s", 
477              get_bit_name(((code&0x0003)<<8) + get_mem(MEM_ROM, addr+2)));
478     break;
479     case BIT_CY :
480       sprintf(parm_str, "%s,C", 
481               get_bit_name(((code&0x0003)<<8) + get_mem(MEM_ROM, addr+2)));
482     break;
483     case REG_DATA4 :
484       strcpy(parm_str, "REG_DATA4");
485     break;
486     case REG_DATA5 :
487       strcpy(parm_str, "REG_DATA5");
488     break;
489     case IREG_DATA4 :
490       strcpy(parm_str, "IREG_DATA4");
491     break;
492     case IREGINC_DATA4 :
493       strcpy(parm_str, "IREGINC_DATA4");
494     break;
495     case IREGOFF8_DATA4 :
496       strcpy(parm_str, "IREGOFF8_DATA4");
497     break;
498     case IREGOFF16_DATA4 :
499       strcpy(parm_str, "IREGOFF16_DATA4");
500     break;
501     case DIRECT_DATA4 :
502       sprintf(parm_str, "%s,#0x%x",
503               get_dir_name(((code & 0x70)<<4) |
504                            get_mem(MEM_ROM, addr+2)),
505               code&0x0f);
506     break;
507     case DIRECT :
508       sprintf(parm_str, "%s",
509               get_dir_name(((code & 0x007) << 4) + 
510                            get_mem(MEM_ROM, addr+2)));
511     break;
512     case REG :
513       sprintf(parm_str, "%s",
514               reg_strs[((code >> 4) & 0xf)] );
515     break;
516     case IREG :
517       sprintf(parm_str, "[%s]",
518               reg_strs[((code >> 4) & 0xf)] );
519     break;
520     case BIT_ALONE :
521       sprintf(parm_str, "%s",
522               get_bit_name(((code&0x0003)<<8) + get_mem(MEM_ROM, addr+2)));
523     break;
524     case BIT_REL8 :
525       sprintf(parm_str, "%s,0x%04x",
526               get_bit_name((code&0x0003)<<8) + get_mem(MEM_ROM, addr+2),
527               ((signed char)get_mem(MEM_ROM, addr+3)*2+addr+len)&0xfffe);
528     break;
529     case DATA4:
530       sprintf(parm_str, "#0x%02x", code&0x0f);
531       break;
532     case ADDR24 :
533       sprintf(parm_str, "0x%06x", 
534              (get_mem(MEM_ROM, addr+3)<<16) + 
535              (get_mem(MEM_ROM, addr+1)<<8) + 
536              get_mem(MEM_ROM, addr+2));
537       break;
538     break;
539     case REG_REL8 :
540       sprintf(parm_str, "%s,0x%04x",
541               reg_strs[(code>>4) & 0xf],
542               ((signed char)get_mem(MEM_ROM, addr+2)*2+addr+len)&0xfffe);
543     break;
544     case DIRECT_REL8 :
545       sprintf(parm_str, "%s,0x%04x",
546               get_dir_name(((code&0x07)<<8) +
547                            get_mem(MEM_ROM, addr+2)),
548               ((signed char)get_mem(MEM_ROM, addr+2)*2+addr+len)&0xfffe);
549     break;
550     case REG_USP:
551       sprintf(parm_str, "REG_USP");
552     break;
553     case USP_REG:
554       sprintf(parm_str, "USP_REG");
555     break;
556     case REL8 :
557       sprintf(parm_str, "0x%04x",
558               ((signed char)get_mem(MEM_ROM, addr+1)*2+addr+len)&0xfffe);
559     break;
560     case REL16 :
561       sprintf(parm_str, "0x%04x",
562               ((signed short)((get_mem(MEM_ROM, addr+1)<<8) + get_mem(MEM_ROM, addr+2))*2+addr+len)&0xfffe);
563     break;
564
565     case RLIST : {
566       /* TODO: the list should be comma reperated
567          and maybe for POP the list should be reversed */
568       unsigned char rlist=code&0xff;
569       parm_str[0]='\0';
570       if (code&0x0800) { // word list
571         if (code&0x4000) { // R8-R15
572           if (rlist&0x80) strcat (parm_str, "R15 ");
573           if (rlist&0x40) strcat (parm_str, "R14");
574           if (rlist&0x20) strcat (parm_str, "R13 ");
575           if (rlist&0x10) strcat (parm_str, "R12 ");
576           if (rlist&0x08) strcat (parm_str, "R11 ");
577           if (rlist&0x04) strcat (parm_str, "R10 ");
578           if (rlist&0x02) strcat (parm_str, "R9 ");
579           if (rlist&0x01) strcat (parm_str, "R8 ");
580         } else { // R7-R0
581           if (rlist&0x80) strcat (parm_str, "R7 ");
582           if (rlist&0x40) strcat (parm_str, "R6 ");
583           if (rlist&0x20) strcat (parm_str, "R5 ");
584           if (rlist&0x10) strcat (parm_str, "R4 ");
585           if (rlist&0x08) strcat (parm_str, "R3 ");
586           if (rlist&0x04) strcat (parm_str, "R2 ");
587           if (rlist&0x02) strcat (parm_str, "R1 ");
588           if (rlist&0x01) strcat (parm_str, "R0 ");
589         }
590       } else { // byte list
591         if (code&0x4000) { //R7h-R4l
592           if (rlist&0x80) strcat (parm_str, "R7h ");
593           if (rlist&0x40) strcat (parm_str, "R7l ");
594           if (rlist&0x20) strcat (parm_str, "R6h ");
595           if (rlist&0x10) strcat (parm_str, "R6l ");
596           if (rlist&0x08) strcat (parm_str, "R5h ");
597           if (rlist&0x04) strcat (parm_str, "R5l ");
598           if (rlist&0x02) strcat (parm_str, "R4h ");
599           if (rlist&0x01) strcat (parm_str, "R4l ");
600         } else { // R3h-R0l
601           if (rlist&0x80) strcat (parm_str, "R3h ");
602           if (rlist&0x40) strcat (parm_str, "R3l ");
603           if (rlist&0x20) strcat (parm_str, "R2h ");
604           if (rlist&0x10) strcat (parm_str, "R2l ");
605           if (rlist&0x08) strcat (parm_str, "R1h ");
606           if (rlist&0x04) strcat (parm_str, "R1l ");
607           if (rlist&0x02) strcat (parm_str, "R0h ");
608           if (rlist&0x01) strcat (parm_str, "R0l ");
609         }
610       }
611     }
612     break;
613
614     case REG_DIRECT_REL8 :
615       sprintf(parm_str, "%s,%s,0x%02x",
616               reg_strs[((code >> 4) & 0xf)],
617               get_dir_name(((code & 0x7) << 8) + 
618                            get_mem(MEM_ROM, addr+immed_offset)),
619               ((signed char) get_mem(MEM_ROM, addr+immed_offset+1) * 2) & 0xfffe );
620     break;
621     case REG_DATA8_REL8 :
622       sprintf(parm_str, "%s,#0x%02x,0x%02x",
623               reg_strs[((code >> 4) & 0xf)],
624               get_mem(MEM_ROM, addr+immed_offset+1),
625               ((signed char)get_mem(MEM_ROM, addr+immed_offset) * 2) & 0xfffe );
626     break;
627     case REG_DATA16_REL8 :
628       sprintf(parm_str, "%s,#0x%04x,0x%02x",
629               w_reg_strs[(code >> 4) & 0xf],
630               get_mem(MEM_ROM, addr+immed_offset+2) +
631                  (get_mem(MEM_ROM, addr+immed_offset+1)<<8),
632               ((signed char)get_mem(MEM_ROM, addr+immed_offset) * 2) & 0xfffe );
633     break;
634     case IREG_DATA8_REL8 :
635       sprintf(parm_str, "[%s],#0x%02x,0x%02x",
636               reg_strs[((code >> 4) & 0x7)],
637               get_mem(MEM_ROM, addr+immed_offset+1),
638               ((signed char)get_mem(MEM_ROM, addr+immed_offset) * 2) & 0xfffe );
639     break;
640     case IREG_DATA16_REL8 :
641       sprintf(parm_str, "[%s],#0x%04x,0x%02x",
642               w_reg_strs[(code >> 4) & 0x7],
643               get_mem(MEM_ROM, addr+immed_offset+2) +
644                 (get_mem(MEM_ROM, addr+immed_offset+1)<<8),
645               ((signed char)get_mem(MEM_ROM, addr+immed_offset) * 2) & 0xfffe );
646     break;
647
648     case A_APLUSDPTR :
649       strcpy(parm_str, "A, [A+DPTR]");
650     break;
651
652     case A_APLUSPC :
653       strcpy(parm_str, "A, [A+PC]");
654     break;
655
656     case REG_REGOFF8 :
657       sprintf(parm_str, "%s,%s+0x%02x", 
658               w_reg_strs[(code >> 4) & 0x7],
659               w_reg_strs[code & 0x7],
660               get_mem(MEM_ROM, addr+immed_offset));
661       break;
662
663     case REG_REGOFF16 :
664       sprintf(parm_str, "%s,%s+0x%02x", 
665               w_reg_strs[(code >> 4) & 0x7],
666               w_reg_strs[code & 0x7],
667               get_mem(MEM_ROM, addr+immed_offset+1) +
668                 (get_mem(MEM_ROM, addr+immed_offset+0)<<8));
669       break;
670
671     case A_PLUSDPTR :
672       strcpy(parm_str, "[A+DPTR]");
673       break;
674
675     case IIREG :
676       sprintf(parm_str, "[[%s]]",
677               w_reg_strs[(code & 0x7)]);
678       break;
679
680     default:
681       strcpy(parm_str, "???");
682     break;
683   }
684
685   sprintf(work, "%s %s",
686           op_mnemonic_str[ mnemonic ],
687           parm_str);
688
689   p= strchr(work, ' ');
690   if (!p)
691     {
692       buf= strdup(work);
693       return(buf);
694     }
695   if (sep == NULL)
696     buf= (char *)malloc(6+strlen(p)+1);
697   else
698     buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
699
700   for (p= work, b= buf; *p != ' '; p++, b++)
701     *b= *p;
702   p++;
703   *b= '\0';
704   if (sep == NULL)
705     {
706       while (strlen(buf) < 6)
707         strcat(buf, " ");
708     }
709   else
710     strcat(buf, sep);
711   strcat(buf, p);
712   return(buf);
713 }
714
715 /*--------------------------------------------------------------------
716  print_regs - Print the registers, flags and other useful information.
717    Used to print a status line while stepping through the code.
718 |--------------------------------------------------------------------*/
719 void
720 cl_xa::print_regs(class cl_console *con)
721 {
722   unsigned char flags;
723
724   flags = get_psw();
725   con->dd_printf("CA---VNZ | ", flags);
726   con->dd_printf("R0:%04x R1:%04x R2:%04x R3:%04x\n",
727                  reg2(0), reg2(1), reg2(2), reg2(3));
728
729   con->dd_printf("%c%c---%c%c%c | ",
730          (flags & BIT_C)?'1':'0',
731          (flags & BIT_AC)?'1':'0',
732          (flags & BIT_V)?'1':'0',
733          (flags & BIT_N)?'1':'0',
734          (flags & BIT_Z)?'1':'0');
735
736   con->dd_printf("R4:%04x R5:%04x R6:%04x SP:%04x ES:%04x  DS:%04x\n",
737                  reg2(4), reg2(5), reg2(6), reg2(7), 0, 0);
738
739   print_disass(PC, con);
740 }
741
742
743 /*--------------------------------------------------------------------
744  exec_inst - Called to implement simulator execution of 1 instruction
745    at the current PC(program counter) address.
746 |--------------------------------------------------------------------*/
747 int cl_xa::exec_inst(void)
748 {
749   t_mem code1;
750   uint code;
751   int i;
752   int operands;
753
754   if (fetch(&code1))
755     return(resBREAKPOINT);
756   tick(1);
757
758 /* the following lookups make for a slow simulation, we will
759   figure out how to make it fast later... */
760
761   /* scan to see if its a 1 byte-opcode */
762   code = (code1 << 8);
763   i= 0;
764   while ( ((code & disass_xa[i].mask) != disass_xa[i].code ||
765           (!disass_xa[i].is1byte)) /* not a one byte op code */
766                     &&
767          disass_xa[i].mnemonic != BAD_OPCODE)
768     i++;
769
770   if (disass_xa[i].mnemonic == BAD_OPCODE) {
771     /* hit the end of the list, must be a 2 or more byte opcode */
772     /* fetch another code byte and search the list again */
773       //if (fetch(&code2))  ?not sure if break allowed in middle of opcode?
774       //  return(resBREAKPOINT);
775     code |= fetch();  /* add 2nd opcode */
776
777     i= 0;
778     while ((code & disass_xa[i].mask) != disass_xa[i].code &&
779            disass_xa[i].mnemonic != BAD_OPCODE)
780       i++;
781     /* we should have found the opcode by now, if not invalid entry at eol */
782   }
783
784   operands = (int)(disass_xa[i].operands);
785   switch (disass_xa[i].mnemonic)
786   {
787     case ADD:
788     return inst_ADD(code, operands);
789     case ADDC:
790     return inst_ADDC(code, operands);
791     case ADDS:
792     return inst_ADDS(code, operands);
793     case AND:
794     return inst_AND(code, operands);
795     case ANL:
796     return inst_ANL(code, operands);
797     case ASL:
798     return inst_ASL(code, operands);
799     case ASR:
800     return inst_ASR(code, operands);
801     case BCC:
802     return inst_BCC(code, operands);
803     case BCS:
804     return inst_BCS(code, operands);
805     case BEQ:
806     return inst_BEQ(code, operands);
807     case BG:
808     return inst_BG(code, operands);
809     case BGE:
810     return inst_BGE(code, operands);
811     case BGT:
812     return inst_BGT(code, operands);
813     case BKPT:
814     return inst_BKPT(code, operands);
815     case BL:
816     return inst_BL(code, operands);
817     case BLE:
818     return inst_BLE(code, operands);
819     case BLT:
820     return inst_BLT(code, operands);
821     case BMI:
822     return inst_BMI(code, operands);
823     case BNE:
824     return inst_BNE(code, operands);
825     case BNV:
826     return inst_BNV(code, operands);
827     case BOV:
828     return inst_BOV(code, operands);
829     case BPL:
830     return inst_BPL(code, operands);
831     case BR:
832     return inst_BR(code, operands);
833     case CALL:
834     return inst_CALL(code, operands);
835     case CJNE:
836     return inst_CJNE(code, operands);
837     case CLR:
838     return inst_CLR(code, operands);
839     case CMP:
840     return inst_CMP(code, operands);
841     case CPL:
842     return inst_CPL(code, operands);
843     case DA:
844     return inst_DA(code, operands);
845     case DIV_w :
846     case DIV_d :
847     case DIVU_b:
848     case DIVU_w:
849     case DIVU_d:
850     return inst_DIV(code, operands);
851     case DJNZ:
852     return inst_DJNZ(code, operands);
853     case FCALL:
854     return inst_FCALL(code, operands);
855     case FJMP:
856     return inst_FJMP(code, operands);
857     case JB:
858     return inst_JB(code, operands);
859     case JBC:
860     return inst_JBC(code, operands);
861     case JMP:
862     return inst_JMP(code, operands);
863     case JNB:
864     return inst_JNB(code, operands);
865     case JNZ:
866     return inst_JNZ(code, operands);
867     case JZ:
868     return inst_JZ(code, operands);
869     case LEA:
870     return inst_LEA(code, operands);
871     case LSR:
872     return inst_LSR(code, operands);
873     case MOV:
874     return inst_MOV(code, operands);
875     case MOVC:
876     return inst_MOVC(code, operands);
877     case MOVS:
878     return inst_MOVS(code, operands);
879     case MOVX:
880     return inst_MOVX(code, operands);
881     case MUL_w:
882     case MULU_b:
883     case MULU_w:
884     return inst_MUL(code, operands);
885     case NEG:
886     return inst_NEG(code, operands);
887     case NOP:
888     return inst_NOP(code, operands);
889     case NORM:
890     return inst_NORM(code, operands);
891     case OR:
892     return inst_OR(code, operands);
893     case ORL:
894     return inst_ORL(code, operands);
895     case POP:
896     case POPU:
897     return inst_POP(code, operands);
898     case PUSH:
899     case PUSHU:
900     return inst_PUSH(code, operands);
901     case RESET:
902     return inst_RESET(code, operands);
903     case RET:
904     return inst_RET(code, operands);
905     case RETI:
906     return inst_RETI(code, operands);
907     case RL:
908     return inst_RL(code, operands);
909     case RLC:
910     return inst_RLC(code, operands);
911     case RR:
912     return inst_RR(code, operands);
913     case RRC:
914     return inst_RRC(code, operands);
915     case SETB:
916     return inst_SETB(code, operands);
917     case SEXT:
918     return inst_SEXT(code, operands);
919     case SUB:
920     return inst_SUB(code, operands);
921     case SUBB:
922     return inst_SUBB(code, operands);
923     case TRAP:
924     return inst_TRAP(code, operands);
925     case XCH:
926     return inst_XCH(code, operands);
927     case XOR:
928     return inst_XOR(code, operands);
929
930     case BAD_OPCODE:
931     default:
932     break;
933   }
934
935   if (PC)
936     PC--;
937   else
938     PC= get_mem_size(MEM_ROM)-1;
939   //tick(-clock_per_cycle());
940   sim->stop(resINV_INST);
941   return(resINV_INST);
942 }
943
944
945 /* End of xa.src/xa.cc */