2 * Simulator of microcontrollers (xa.cc)
4 * Copyright (C) 1999,2002 Drotos Daniel, Talker Bt.
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7 * Other contributors include:
8 * Karl Bongers karl@turbobit.com,
12 /* This file is part of microcontroller simulator: ucsim.
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.
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.
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
50 * Base type of xa controllers
53 cl_xa::cl_xa(class cl_sim *asim):
62 cl_uc::init(); /* Memories now exist */
66 wmem_direct = (TYPE_UWORD *) &mem_direct[0];
68 /* initialize SP to 100H */
71 printf("The XA Simulator is in development, UNSTABLE, DEVELOPERS ONLY!\n");
77 cl_xa::id_string(void)
79 return("unspecified XA");
84 * Making elements of the controller
88 cl_xa::get_mem_size(enum mem_class type)
92 case MEM_ROM: return(0x10000);
93 case MEM_XRAM: return(0x10000);
96 return(cl_uc::get_mem_size(type));
100 cl_xa::mk_hw_elements(void)
103 /* t_uc::mk_hw() does nothing */
108 * Help command interpreter
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);
120 /*struct name_entry *
126 /*struct name_entry *
134 cl_xa::inst_length(t_addr addr)
138 get_disasm_info(addr, &len, NULL, NULL, NULL, NULL);
144 cl_xa::inst_branch(t_addr addr)
148 get_disasm_info(addr, NULL, &b, NULL, NULL, NULL);
154 cl_xa::longest_inst(void)
159 /*--------------------------------------------------------------------
161 |--------------------------------------------------------------------*/
163 cl_xa::get_disasm_info(t_addr addr,
174 int start_addr = addr;
176 code= get_mem(MEM_ROM, addr++);
179 while (disass_xa[i].mnemonic != NOP)
183 code = (code << 8) | get_mem(MEM_ROM, addr++);
185 while ((code & disass_xa[i].mask) != disass_xa[i].code &&
186 disass_xa[i].mnemonic != BAD_OPCODE)
191 *ret_len = disass_xa[i].length;
193 *ret_branch = disass_xa[i].branch;
196 *immed_offset = immed_n;
197 else *immed_offset = (addr - start_addr);
200 *parms = disass_xa[i].operands;
203 *mnemonic = disass_xa[i].mnemonic;
209 static char *w_reg_strs[] = {
219 static char *b_reg_strs[] = {
229 /*--------------------------------------------------------------------
231 |--------------------------------------------------------------------*/
233 cl_xa::disass(t_addr addr, char *sep)
235 char work[256], parm_str[40];
239 int immed_offset = 0;
246 code = get_disasm_info(addr, &len, NULL, &immed_offset, &operands, &mnemonic);
248 if (mnemonic == BAD_OPCODE) {
249 buf= (char*)malloc(30);
250 strcpy(buf, "UNKNOWN/INVALID");
255 reg_strs = w_reg_strs;
257 reg_strs = b_reg_strs;
260 // the repeating common parameter encoding for ADD, ADDC, SUB, AND...
262 sprintf(parm_str, "%s,%s",
263 reg_strs[((code >> 4) & 0xf)],
264 reg_strs[(code & 0xf)]);
267 sprintf(parm_str, "%s,[%s]",
268 reg_strs[((code >> 4) & 0xf)],
269 w_reg_strs[(code & 0xf)]);
272 sprintf(parm_str, "[%s],%s",
273 w_reg_strs[(code & 0x7)],
274 reg_strs[((code >> 4) & 0xf)] );
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));
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)] );
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)) );
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)] );
309 sprintf(parm_str, "%s,[%s+]",
310 reg_strs[((code >> 4) & 0xf)],
311 w_reg_strs[(code & 0xf)]);
314 sprintf(parm_str, "[%s+],%s",
315 w_reg_strs[(code & 0x7)],
316 reg_strs[((code >> 4) & 0xf)] );
319 sprintf(parm_str, "0x%03x,%s",
320 ((code & 0x7) << 8) | get_mem(MEM_ROM, addr+immed_offset),
321 reg_strs[((code >> 4) & 0xf)] );
325 sprintf(parm_str, "%s,0x%03x",
326 reg_strs[((code >> 4) & 0xf)],
327 ((code & 0x7) << 8) + get_mem(MEM_ROM, addr+immed_offset) );
331 sprintf(parm_str, "%s,#0x%02x",
332 b_reg_strs[((code >> 4) & 0xf)],
333 get_mem(MEM_ROM, addr+immed_offset) );
337 sprintf(parm_str, "%s,#0x%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)) );
345 sprintf(parm_str, "[%s], 0x%02x",
346 w_reg_strs[((code >> 4) & 0x7)],
347 get_mem(MEM_ROM, addr+immed_offset) );
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)) );
359 sprintf(parm_str, "[%s+], 0x%02x",
360 w_reg_strs[((code >> 4) & 0x7)],
361 get_mem(MEM_ROM, addr+immed_offset) );
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)) );
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) );
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)) );
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) );
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)) );
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));
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));
419 case NO_OPERANDS : // for NOP
420 strcpy(parm_str, "");
423 strcpy(parm_str, "C_BIT");
426 strcpy(parm_str, "REG_DATA4");
429 strcpy(parm_str, "IREG_DATA4");
432 strcpy(parm_str, "IREGINC_DATA4");
434 case IREGOFF8_DATA4 :
435 strcpy(parm_str, "IREGOFF8_DATA4");
437 case IREGOFF16_DATA4 :
438 strcpy(parm_str, "IREGOFF16_DATA4");
441 strcpy(parm_str, "DIRECT_DATA4");
444 sprintf(parm_str, "0x%03x",
445 ((code & 0x007) << 4) + get_mem(MEM_ROM, addr+2));
448 sprintf(parm_str, "%s",
449 reg_strs[((code >> 4) & 0xf)] );
452 sprintf(parm_str, "[%s]",
453 reg_strs[((code >> 4) & 0xf)] );
456 sprintf(parm_str, "0x%03x",
457 ((code&0x0003)<<8) + get_mem(MEM_ROM, addr+2));
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);
465 strcpy(parm_str, "ADDR24");
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);
474 strcpy(parm_str, "DIRECT_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);
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);
489 strcpy(parm_str, "RLIST");
492 case REG_DIRECT_REL8 :
493 sprintf(parm_str, "%s,0x%02x,0x%02x",
494 reg_strs[((code >> 4) & 0xf)],
495 ((code & 0x7) << 8) + get_mem(MEM_ROM, addr+immed_offset),
496 (get_mem(MEM_ROM, addr+immed_offset+1) * 2) & 0xfffe );
498 case REG_DATA8_REL8 :
499 sprintf(parm_str, "%s,#0x%04x,0x%02x",
500 reg_strs[((code >> 4) & 0xf)],
501 get_mem(MEM_ROM, addr+immed_offset),
502 (get_mem(MEM_ROM, addr+immed_offset+1) * 2) & 0xfffe );
504 case REG_DATA16_REL8 :
505 sprintf(parm_str, "%s,#0x%02x,0x%02x",
506 w_reg_strs[((code >> 4) & 0x7)*2],
507 get_mem(MEM_ROM, addr+immed_offset+1) +
508 (get_mem(MEM_ROM, addr+immed_offset+0)<<8),
509 (get_mem(MEM_ROM, addr+immed_offset+2) * 2) & 0xfffe );
511 case IREG_DATA8_REL8 :
512 sprintf(parm_str, "[%s],#0x%04x,0x%02x",
513 reg_strs[((code >> 4) & 0x7)],
514 get_mem(MEM_ROM, addr+immed_offset),
515 (get_mem(MEM_ROM, addr+immed_offset+1) * 2) & 0xfffe );
517 case IREG_DATA16_REL8 :
518 sprintf(parm_str, "[%s],#0x%02x,0x%02x",
519 w_reg_strs[((code >> 4) & 0x7)*2],
520 get_mem(MEM_ROM, addr+immed_offset+1) +
521 (get_mem(MEM_ROM, addr+immed_offset+0)<<8),
522 (get_mem(MEM_ROM, addr+immed_offset+2) * 2) & 0xfffe );
526 strcpy(parm_str, "???");
530 sprintf(work, "%s %s",
531 op_mnemonic_str[ mnemonic ],
534 p= strchr(work, ' ');
541 buf= (char *)malloc(6+strlen(p)+1);
543 buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
544 for (p= work, b= buf; *p != ' '; p++, b++)
550 while (strlen(buf) < 6)
559 /*--------------------------------------------------------------------
561 |--------------------------------------------------------------------*/
563 cl_xa::print_regs(class cl_console *con)
568 con->dd_printf("CA---VNZ Flags: %02x ", flags);
569 con->dd_printf("R0:%04x R1:%04x R2:%04x R3:%04x\n",
570 get_reg(1,0), get_reg(1,2), get_reg(1,4), get_reg(1,6));
572 con->dd_printf("%c%c---%c%c%c ",
573 (flags & BIT_C)?'1':'0',
574 (flags & BIT_AC)?'1':'0',
575 (flags & BIT_V)?'1':'0',
576 (flags & BIT_N)?'1':'0',
577 (flags & BIT_Z)?'1':'0');
579 con->dd_printf("R4:%04x R5:%04x R6:%04x R7(SP):%04x ES:%04x DS:%04x\n",
580 get_reg(1,8), get_reg(1,10), get_reg(1,12), get_reg(1,14), 0, 0);
582 print_disass(PC, con);
591 cl_xa::exec_inst(void)
599 return(resBREAKPOINT);
602 /* the following lookups make for a slow simulation, we will
603 figure out how to make it fast later... */
605 /* scan to see if its a 1 byte-opcode */
608 while ( ((code & disass_xa[i].mask) != disass_xa[i].code ||
609 ((disass_xa[i].mask & 0x00ff) != 0)) /* one byte op code */
611 disass_xa[i].mnemonic != BAD_OPCODE)
614 if (disass_xa[i].mnemonic == BAD_OPCODE) {
615 /* hit the end of the list, must be a 2 or more byte opcode */
616 /* fetch another code byte and search the list again */
617 //if (fetch(&code2)) ?not sure if break allowed in middle of opcode?
618 // return(resBREAKPOINT);
619 code |= fetch(); /* add 2nd opcode */
622 while ((code & disass_xa[i].mask) != disass_xa[i].code &&
623 disass_xa[i].mnemonic != BAD_OPCODE)
625 /* we should have found the opcode by now, if not invalid entry at eol */
628 operands = (int)(disass_xa[i].operands);
629 switch (disass_xa[i].mnemonic)
632 return inst_ADD(code, operands);
634 return inst_ADDC(code, operands);
636 return inst_SUB(code, operands);
638 return inst_SUBB(code, operands);
640 return inst_CMP(code, operands);
642 return inst_AND(code, operands);
644 return inst_OR(code, operands);
646 return inst_XOR(code, operands);
648 return inst_ADDS(code, operands);
650 return inst_NEG(code, operands);
652 return inst_SEXT(code, operands);
654 return inst_MUL(code, operands);
660 return inst_DIV(code, operands);
662 return inst_DA(code, operands);
664 return inst_ASL(code, operands);
666 return inst_ASR(code, operands);
668 return inst_LEA(code, operands);
670 return inst_CPL(code, operands);
672 return inst_LSR(code, operands);
674 return inst_NORM(code, operands);
676 return inst_RL(code, operands);
678 return inst_RLC(code, operands);
680 return inst_RR(code, operands);
682 return inst_RRC(code, operands);
684 return inst_MOVS(code, operands);
686 return inst_MOVC(code, operands);
688 return inst_MOVX(code, operands);
690 return inst_PUSH(code, operands);
692 return inst_POP(code, operands);
694 return inst_XCH(code, operands);
696 return inst_SETB(code, operands);
698 return inst_CLR(code, operands);
700 return inst_MOV(code, operands);
702 return inst_ANL(code, operands);
704 return inst_ORL(code, operands);
706 return inst_BEQ(code, operands);
708 return inst_BR(code, operands);
710 return inst_JMP(code, operands);
712 return inst_CALL(code, operands);
714 return inst_RET(code, operands);
716 return inst_Bcc(code, operands);
718 return inst_JB(code, operands);
720 return inst_JNB(code, operands);
722 return inst_CJNE(code, operands);
724 return inst_DJNZ(code, operands);
726 return inst_JZ(code, operands);
728 return inst_JNZ(code, operands);
730 return inst_NOP(code, operands);
732 return inst_BKPT(code, operands);
734 return inst_TRAP(code, operands);
736 return inst_RESET(code, operands);
745 PC= get_mem_size(MEM_ROM)-1;
746 //tick(-clock_per_cycle());
747 sim->stop(resINV_INST);
752 /* End of xa.src/xa.cc */