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 /*--------------------------------------------------------------------
160 get_disasm_info - Given an address, return information about the opcode
162 addr - address of opcode we want information on.
163 ret_len - return length of opcode.
164 ret_branch - return a character which indicates if we are
165 a branching opcode. Used by main app to implement "Next"
166 function which steps over functions.
167 immed_offset - return a number which represents the number of bytes
168 offset to where any immediate data is(tail end of opcode). Used
169 for printing disassembly.
170 operands - return a key indicating the form of the operands,
171 used for printing the disassembly.
172 mnemonic - return a key indicating the mnemonic of the instruction.
174 Return value: Return the operand code formed by either the single
175 byte opcode or 2 bytes of the opcode for multi-byte opcodes.
177 Note: Any of the return pointer parameters can be set to NULL to
178 indicate the caller does not want the information.
179 |--------------------------------------------------------------------*/
181 cl_xa::get_disasm_info(t_addr addr,
192 int start_addr = addr;
194 code= get_mem(MEM_ROM, addr++);
197 while (disass_xa[i].mnemonic != NOP)
201 code = (code << 8) | get_mem(MEM_ROM, addr++);
203 while ((code & disass_xa[i].mask) != disass_xa[i].code &&
204 disass_xa[i].mnemonic != BAD_OPCODE)
209 *ret_len = disass_xa[i].length;
211 *ret_branch = disass_xa[i].branch;
214 *immed_offset = immed_n;
215 else *immed_offset = (addr - start_addr);
218 *parms = disass_xa[i].operands;
221 *mnemonic = disass_xa[i].mnemonic;
227 static char *w_reg_strs[] = {
237 static char *b_reg_strs[] = {
247 /*--------------------------------------------------------------------
248 disass - Disassemble an opcode.
249 addr - address of opcode to disassemble/print.
250 sep - optionally points to string(tab) to use as separator.
251 |--------------------------------------------------------------------*/
253 cl_xa::disass(t_addr addr, char *sep)
255 char work[256], parm_str[40];
259 int immed_offset = 0;
266 code = get_disasm_info(addr, &len, NULL, &immed_offset, &operands, &mnemonic);
268 if (mnemonic == BAD_OPCODE) {
269 buf= (char*)malloc(30);
270 strcpy(buf, "UNKNOWN/INVALID");
275 reg_strs = w_reg_strs;
277 reg_strs = b_reg_strs;
280 // the repeating common parameter encoding for ADD, ADDC, SUB, AND...
282 sprintf(parm_str, "%s,%s",
283 reg_strs[((code >> 4) & 0xf)],
284 reg_strs[(code & 0xf)]);
287 sprintf(parm_str, "%s,[%s]",
288 reg_strs[((code >> 4) & 0xf)],
289 w_reg_strs[(code & 0xf)]);
292 sprintf(parm_str, "[%s],%s",
293 w_reg_strs[(code & 0x7)],
294 reg_strs[((code >> 4) & 0xf)] );
297 sprintf(parm_str, "%s,[%s+%02d]",
298 reg_strs[((code >> 4) & 0xf)],
299 w_reg_strs[(code & 0x7)],
300 get_mem(MEM_ROM, addr+immed_offset));
304 sprintf(parm_str, "[%s+%02d],%s",
305 w_reg_strs[(code & 0x7)],
306 get_mem(MEM_ROM, addr+immed_offset),
307 reg_strs[((code >> 4) & 0xf)] );
311 sprintf(parm_str, "%s,[%s+%04d]",
312 reg_strs[((code >> 4) & 0xf)],
313 w_reg_strs[(code & 0x7)],
314 (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
315 (get_mem(MEM_ROM, addr+immed_offset)<<8)) );
320 sprintf(parm_str, "[%s+%04d],%s",
321 w_reg_strs[(code & 0x7)],
322 (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
323 (get_mem(MEM_ROM, addr+immed_offset)<<8)),
324 reg_strs[((code >> 4) & 0xf)] );
329 sprintf(parm_str, "%s,[%s+]",
330 reg_strs[((code >> 4) & 0xf)],
331 w_reg_strs[(code & 0xf)]);
334 sprintf(parm_str, "[%s+],%s",
335 w_reg_strs[(code & 0x7)],
336 reg_strs[((code >> 4) & 0xf)] );
339 sprintf(parm_str, "0x%03x,%s",
340 ((code & 0x7) << 8) | get_mem(MEM_ROM, addr+immed_offset),
341 reg_strs[((code >> 4) & 0xf)] );
345 sprintf(parm_str, "%s,0x%03x",
346 reg_strs[((code >> 4) & 0xf)],
347 ((code & 0x7) << 8) + get_mem(MEM_ROM, addr+immed_offset) );
351 sprintf(parm_str, "%s,#0x%02x",
352 b_reg_strs[((code >> 4) & 0xf)],
353 get_mem(MEM_ROM, addr+immed_offset) );
357 sprintf(parm_str, "%s,#0x%04x",
358 reg_strs[((code >> 4) & 0xf)],
359 (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
360 (get_mem(MEM_ROM, addr+immed_offset)<<8)) );
365 sprintf(parm_str, "[%s], 0x%02x",
366 w_reg_strs[((code >> 4) & 0x7)],
367 get_mem(MEM_ROM, addr+immed_offset) );
371 sprintf(parm_str, "[%s], 0x%04x",
372 w_reg_strs[((code >> 4) & 0x7)],
373 (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
374 (get_mem(MEM_ROM, addr+immed_offset)<<8)) );
379 sprintf(parm_str, "[%s+], 0x%02x",
380 w_reg_strs[((code >> 4) & 0x7)],
381 get_mem(MEM_ROM, addr+immed_offset) );
384 case IREGINC_DATA16 :
385 sprintf(parm_str, "[%s+], 0x%04x",
386 w_reg_strs[((code >> 4) & 0x7)],
387 (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
388 (get_mem(MEM_ROM, addr+immed_offset)<<8)) );
392 case IREGOFF8_DATA8 :
393 sprintf(parm_str, "[%s+%02d], 0x%02x",
394 w_reg_strs[((code >> 4) & 0x7)],
395 get_mem(MEM_ROM, addr+immed_offset),
396 get_mem(MEM_ROM, addr+immed_offset+1) );
399 case IREGOFF8_DATA16 :
400 sprintf(parm_str, "[%s+%02d], 0x%04x",
401 w_reg_strs[((code >> 4) & 0x7)],
402 get_mem(MEM_ROM, addr+immed_offset),
403 (short)((get_mem(MEM_ROM, addr+immed_offset+2)) |
404 (get_mem(MEM_ROM, addr+immed_offset+1)<<8)) );
407 case IREGOFF16_DATA8 :
408 sprintf(parm_str, "[%s+%04d], 0x%02x",
409 w_reg_strs[((code >> 4) & 0x7)],
410 (short)((get_mem(MEM_ROM, addr+immed_offset+1)) |
411 (get_mem(MEM_ROM, addr+immed_offset+0)<<8)),
412 get_mem(MEM_ROM, addr+immed_offset+2) );
415 case IREGOFF16_DATA16 :
416 sprintf(parm_str, "[%s+%04d], 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+0)<<8)),
420 (short)((get_mem(MEM_ROM, addr+immed_offset+3)) |
421 (get_mem(MEM_ROM, addr+immed_offset+2)<<8)) );
425 sprintf(parm_str, "0x%03x,#0x%02x",
426 ((code & 0x0070) << 4) | get_mem(MEM_ROM, addr+immed_offset),
427 get_mem(MEM_ROM, addr+immed_offset+1));
431 sprintf(parm_str, "%0x03x,#0x%04x",
432 ((code & 0x0070) << 4) | get_mem(MEM_ROM, addr+immed_offset),
433 get_mem(MEM_ROM, addr+immed_offset+2) +
434 (get_mem(MEM_ROM, addr+immed_offset+1)<<8));
439 case NO_OPERANDS : // for NOP
440 strcpy(parm_str, "");
443 strcpy(parm_str, "C_BIT");
446 strcpy(parm_str, "REG_DATA4");
449 strcpy(parm_str, "IREG_DATA4");
452 strcpy(parm_str, "IREGINC_DATA4");
454 case IREGOFF8_DATA4 :
455 strcpy(parm_str, "IREGOFF8_DATA4");
457 case IREGOFF16_DATA4 :
458 strcpy(parm_str, "IREGOFF16_DATA4");
461 strcpy(parm_str, "DIRECT_DATA4");
464 sprintf(parm_str, "0x%03x",
465 ((code & 0x007) << 4) + get_mem(MEM_ROM, addr+2));
468 sprintf(parm_str, "%s",
469 reg_strs[((code >> 4) & 0xf)] );
472 sprintf(parm_str, "[%s]",
473 reg_strs[((code >> 4) & 0xf)] );
476 sprintf(parm_str, "0x%03x",
477 ((code&0x0003)<<8) + get_mem(MEM_ROM, addr+2));
480 sprintf(parm_str, "0x%03x,0x%04x",
481 ((code&0x0003)<<8) + get_mem(MEM_ROM, addr+2),
482 ((signed char)get_mem(MEM_ROM, addr+3)*2+addr+len)&0xfffe);
485 strcpy(parm_str, "ADDR24");
488 //strcpy(parm_str, "REG_REL8");
489 sprintf(parm_str, "%s,0x%04x",
490 reg_strs[(code>>4) & 0xf],
491 ((signed char)get_mem(MEM_ROM, addr+2)*2+addr+len)&0xfffe);
494 strcpy(parm_str, "DIRECT_REL8");
498 //strcpy(parm_str, "REL8");
499 sprintf(parm_str, "0x%04x",
500 ((signed char)get_mem(MEM_ROM, addr+1)*2+addr+len)&0xfffe);
503 //strcpy(parm_str, "REL16");
504 sprintf(parm_str, "0x%04x",
505 ((signed short)((get_mem(MEM_ROM, addr+1)<<8) + get_mem(MEM_ROM, addr+2))*2+addr+len)&0xfffe);
509 strcpy(parm_str, "RLIST");
512 case REG_DIRECT_REL8 :
513 sprintf(parm_str, "%s,0x%02x,0x%02x",
514 reg_strs[((code >> 4) & 0xf)],
515 ((code & 0x7) << 8) + get_mem(MEM_ROM, addr+immed_offset),
516 (get_mem(MEM_ROM, addr+immed_offset+1) * 2) & 0xfffe );
518 case REG_DATA8_REL8 :
519 sprintf(parm_str, "%s,#0x%04x,0x%02x",
520 reg_strs[((code >> 4) & 0xf)],
521 get_mem(MEM_ROM, addr+immed_offset),
522 (get_mem(MEM_ROM, addr+immed_offset+1) * 2) & 0xfffe );
524 case REG_DATA16_REL8 :
525 sprintf(parm_str, "%s,#0x%02x,0x%02x",
526 w_reg_strs[((code >> 4) & 0x7)*2],
527 get_mem(MEM_ROM, addr+immed_offset+1) +
528 (get_mem(MEM_ROM, addr+immed_offset+0)<<8),
529 (get_mem(MEM_ROM, addr+immed_offset+2) * 2) & 0xfffe );
531 case IREG_DATA8_REL8 :
532 sprintf(parm_str, "[%s],#0x%04x,0x%02x",
533 reg_strs[((code >> 4) & 0x7)],
534 get_mem(MEM_ROM, addr+immed_offset),
535 (get_mem(MEM_ROM, addr+immed_offset+1) * 2) & 0xfffe );
537 case IREG_DATA16_REL8 :
538 sprintf(parm_str, "[%s],#0x%02x,0x%02x",
539 w_reg_strs[((code >> 4) & 0x7)*2],
540 get_mem(MEM_ROM, addr+immed_offset+1) +
541 (get_mem(MEM_ROM, addr+immed_offset+0)<<8),
542 (get_mem(MEM_ROM, addr+immed_offset+2) * 2) & 0xfffe );
546 strcpy(parm_str, "???");
550 sprintf(work, "%s %s",
551 op_mnemonic_str[ mnemonic ],
554 p= strchr(work, ' ');
561 buf= (char *)malloc(6+strlen(p)+1);
563 buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
564 for (p= work, b= buf; *p != ' '; p++, b++)
570 while (strlen(buf) < 6)
579 /*--------------------------------------------------------------------
580 print_regs - Print the registers, flags and other useful information.
581 Used to print a status line while stepping through the code.
582 |--------------------------------------------------------------------*/
584 cl_xa::print_regs(class cl_console *con)
589 con->dd_printf("CA---VNZ Flags: %02x ", flags);
590 con->dd_printf("R0:%04x R1:%04x R2:%04x R3:%04x\n",
591 reg2(0), reg2(1), reg2(2), reg2(3));
593 con->dd_printf("%c%c---%c%c%c ",
594 (flags & BIT_C)?'1':'0',
595 (flags & BIT_AC)?'1':'0',
596 (flags & BIT_V)?'1':'0',
597 (flags & BIT_N)?'1':'0',
598 (flags & BIT_Z)?'1':'0');
600 con->dd_printf("R4:%04x R5:%04x R6:%04x R7(SP):%04x ES:%04x DS:%04x\n",
601 reg2(4), reg2(5), reg2(6), reg2(7), 0, 0);
603 print_disass(PC, con);
607 /*--------------------------------------------------------------------
608 exec_inst - Called to implement simulator execution of 1 instruction
609 at the current PC(program counter) address.
610 |--------------------------------------------------------------------*/
611 int cl_xa::exec_inst(void)
619 return(resBREAKPOINT);
622 /* the following lookups make for a slow simulation, we will
623 figure out how to make it fast later... */
625 /* scan to see if its a 1 byte-opcode */
628 while ( ((code & disass_xa[i].mask) != disass_xa[i].code ||
629 ((disass_xa[i].mask & 0x00ff) != 0)) /* one byte op code */
631 disass_xa[i].mnemonic != BAD_OPCODE)
634 if (disass_xa[i].mnemonic == BAD_OPCODE) {
635 /* hit the end of the list, must be a 2 or more byte opcode */
636 /* fetch another code byte and search the list again */
637 //if (fetch(&code2)) ?not sure if break allowed in middle of opcode?
638 // return(resBREAKPOINT);
639 code |= fetch(); /* add 2nd opcode */
642 while ((code & disass_xa[i].mask) != disass_xa[i].code &&
643 disass_xa[i].mnemonic != BAD_OPCODE)
645 /* we should have found the opcode by now, if not invalid entry at eol */
648 operands = (int)(disass_xa[i].operands);
649 switch (disass_xa[i].mnemonic)
652 return inst_ADD(code, operands);
654 return inst_ADDC(code, operands);
656 return inst_ADDS(code, operands);
658 return inst_AND(code, operands);
660 return inst_ANL(code, operands);
662 return inst_ASL(code, operands);
664 return inst_ASR(code, operands);
666 return inst_BCC(code, operands);
668 return inst_BCS(code, operands);
670 return inst_BEQ(code, operands);
672 return inst_BG(code, operands);
674 return inst_BGE(code, operands);
676 return inst_BGT(code, operands);
678 return inst_BKPT(code, operands);
680 return inst_BL(code, operands);
682 return inst_BLE(code, operands);
684 return inst_BLT(code, operands);
686 return inst_BMI(code, operands);
688 return inst_BNE(code, operands);
690 return inst_BNV(code, operands);
692 return inst_BOV(code, operands);
694 return inst_BPL(code, operands);
696 return inst_BR(code, operands);
698 return inst_CALL(code, operands);
700 return inst_CJNE(code, operands);
702 return inst_CLR(code, operands);
704 return inst_CMP(code, operands);
706 return inst_CPL(code, operands);
708 return inst_DA(code, operands);
714 return inst_DIV(code, operands);
716 return inst_DJNZ(code, operands);
718 return inst_FCALL(code, operands);
720 return inst_FJMP(code, operands);
722 return inst_JB(code, operands);
724 return inst_JBC(code, operands);
726 return inst_JMP(code, operands);
728 return inst_JNB(code, operands);
730 return inst_JNZ(code, operands);
732 return inst_JZ(code, operands);
734 return inst_LEA(code, operands);
736 return inst_LSR(code, operands);
738 return inst_MOV(code, operands);
740 return inst_MOVC(code, operands);
742 return inst_MOVS(code, operands);
744 return inst_MOVX(code, operands);
748 return inst_MUL(code, operands);
750 return inst_NEG(code, operands);
752 return inst_NOP(code, operands);
754 return inst_NORM(code, operands);
756 return inst_OR(code, operands);
758 return inst_ORL(code, operands);
761 return inst_POP(code, operands);
764 return inst_PUSH(code, operands);
766 return inst_RESET(code, operands);
768 return inst_RET(code, operands);
770 return inst_RETI(code, operands);
772 return inst_RL(code, operands);
774 return inst_RLC(code, operands);
776 return inst_RR(code, operands);
778 return inst_RRC(code, operands);
780 return inst_SETB(code, operands);
782 return inst_SEXT(code, operands);
784 return inst_SUB(code, operands);
786 return inst_SUBB(code, operands);
788 return inst_TRAP(code, operands);
790 return inst_XCH(code, operands);
792 return inst_XOR(code, operands);
802 PC= get_mem_size(MEM_ROM)-1;
803 //tick(-clock_per_cycle());
804 sim->stop(resINV_INST);
809 /* End of xa.src/xa.cc */