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