2 * Simulator of microcontrollers (xa.cc)
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
6 * Written by Karl Bongers karl@turbobit.com
8 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
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,#%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");
493 strcpy(parm_str, "???");
497 sprintf(work, "%s %s",
498 op_mnemonic_str[ mnemonic ],
501 p= strchr(work, ' ');
508 buf= (char *)malloc(6+strlen(p)+1);
510 buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
511 for (p= work, b= buf; *p != ' '; p++, b++)
517 while (strlen(buf) < 6)
526 /*--------------------------------------------------------------------
528 |--------------------------------------------------------------------*/
530 cl_xa::print_regs(class cl_console *con)
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));
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');
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);
549 print_disass(PC, con);
558 cl_xa::exec_inst(void)
566 return(resBREAKPOINT);
569 /* the following lookups make for a slow simulation, we will
570 figure out how to make it fast later... */
572 /* scan to see if its a 1 byte-opcode */
575 while ( ((code & disass_xa[i].mask) != disass_xa[i].code ||
576 ((disass_xa[i].mask & 0x00ff) != 0)) /* one byte op code */
578 disass_xa[i].mnemonic != BAD_OPCODE)
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 */
589 while ((code & disass_xa[i].mask) != disass_xa[i].code &&
590 disass_xa[i].mnemonic != BAD_OPCODE)
592 /* we should have found the opcode by now, if not invalid entry at eol */
595 operands = (int)(disass_xa[i].operands);
596 switch (disass_xa[i].mnemonic)
599 return inst_ADD(code, operands);
601 return inst_ADDC(code, operands);
603 return inst_SUB(code, operands);
605 return inst_SUBB(code, operands);
607 return inst_CMP(code, operands);
609 return inst_AND(code, operands);
611 return inst_OR(code, operands);
613 return inst_XOR(code, operands);
615 return inst_ADDS(code, operands);
617 return inst_NEG(code, operands);
619 return inst_SEXT(code, operands);
621 return inst_MUL(code, operands);
627 return inst_DIV(code, operands);
629 return inst_DA(code, operands);
631 return inst_ASL(code, operands);
633 return inst_ASR(code, operands);
635 return inst_LEA(code, operands);
637 return inst_CPL(code, operands);
639 return inst_LSR(code, operands);
641 return inst_NORM(code, operands);
643 return inst_RL(code, operands);
645 return inst_RLC(code, operands);
647 return inst_RR(code, operands);
649 return inst_RRC(code, operands);
651 return inst_MOVS(code, operands);
653 return inst_MOVC(code, operands);
655 return inst_MOVX(code, operands);
657 return inst_PUSH(code, operands);
659 return inst_POP(code, operands);
661 return inst_XCH(code, operands);
663 return inst_SETB(code, operands);
665 return inst_CLR(code, operands);
667 return inst_MOV(code, operands);
669 return inst_ANL(code, operands);
671 return inst_ORL(code, operands);
673 return inst_BR(code, operands);
675 return inst_JMP(code, operands);
677 return inst_CALL(code, operands);
679 return inst_RET(code, operands);
681 return inst_Bcc(code, operands);
683 return inst_JB(code, operands);
685 return inst_JNB(code, operands);
687 return inst_CJNE(code, operands);
689 return inst_DJNZ(code, operands);
691 return inst_JZ(code, operands);
693 return inst_JNZ(code, operands);
695 return inst_NOP(code, operands);
697 return inst_BKPT(code, operands);
699 return inst_TRAP(code, operands);
701 return inst_RESET(code, operands);
710 PC= get_mem_size(MEM_ROM)-1;
711 //tick(-clock_per_cycle());
712 sim->stop(resINV_INST);
717 /* End of xa.src/xa.cc */