[ucsim-pdk] Multifpp support
[sdcc.git] / sdcc / sim / ucsim / pdk.src / pdk.cc
blob1712c30e369717fe241b2bc486b2aaae829d9809
1 /*
2 * Simulator of microcontrollers (pdk.cc)
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
8 */
10 /* This file is part of microcontroller simulator: ucsim.
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
28 //#include "ddconfig.h"
30 //#include <ctype.h>
31 //#include <stdarg.h> /* for va_list */
32 //#include <cassert>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 //#include "i_string.h"
38 // prj
39 #include "globals.h"
40 //#include "pobjcl.h"
42 // sim
43 //#include "simcl.h"
44 #include "dregcl.h"
46 // local
47 #include "glob.h"
48 #include "pdk16cl.h"
49 //#include "portcl.h"
50 //#include "regspdk.h"
52 /*******************************************************************/
54 cl_fppa::cl_fppa(int aid, class cl_pdk *the_puc, class cl_sim *asim):
55 cl_uc(asim)
57 id= aid;
58 puc= the_puc;
59 PCmask= 0xfff;
64 * Base type of PDK controllers
67 cl_fppa::cl_fppa(int aid, class cl_pdk *the_puc, struct cpu_entry *IType, class cl_sim *asim) : cl_uc(asim)
69 id= aid;
70 puc= the_puc;
71 type = IType;
74 int cl_fppa::init(void) {
75 cl_uc::init(); /* Memories now exist */
77 //set_xtal(8000000);
79 // rom = address_space(MEM_ROM_ID);
80 // ram = mem(MEM_XRAM);
81 // ram = rom;
83 // zero out ram(this is assumed in regression tests)
84 // for (int i = 0x0; i < 0x8000; i++) {
85 // ram->set((t_addr)i, 0);
86 // }
88 cA= new cl_cell8();
89 cA->init();
90 cA->decode(&rA);
92 return (0);
96 void
97 cl_fppa::act(void)
99 cSP->decode(&rSP);
100 cF ->decode(&rF);
103 void cl_fppa::reset(void) {
104 cl_uc::reset();
105 sp_most = 0x00;
107 PC = id;
108 rA = 0;
109 for (t_addr i = 0; i < io_size; ++i) {
110 store_io(i, 0);
114 void cl_fppa::mk_hw_elements(void)
116 // TODO: Add hardware stuff here.
117 class cl_hw *h;
118 cl_uc::mk_hw_elements();
120 add_hw(h= new cl_dreg(this, 0, "dreg"));
121 h->init();
124 void cl_fppa::make_memories(void)
126 class cl_address_space *as;
127 int rom_storage, ram_storage;
129 if (puc != NULL)
131 ram= puc->ram;
132 rom= puc->rom;
133 sfr= puc->sfr;
135 else
137 rom_storage = 0x1000;
138 ram_storage = 0x100;
139 rom = as = new cl_address_space("rom", 0, rom_storage, 16);
140 as->init();
141 address_spaces->add(as);
142 ram = as = new cl_address_space("ram", 0, ram_storage, 8);
143 as->init();
144 address_spaces->add(as);
145 sfr = as = new cl_address_space("regs8", 0, io_size + 1, 8);
146 as->init();
147 address_spaces->add(as);
149 class cl_address_decoder *ad;
150 class cl_memory_chip *chip;
152 chip = new cl_chip16("rom_chip", rom_storage, 16);
153 chip->init();
154 memchips->add(chip);
156 ad = new cl_address_decoder(as = rom, chip, 0, rom_storage-1, 0);
157 ad->init();
158 as->decoders->add(ad);
159 ad->activate(0);
161 chip = new cl_chip16("ram_chip", ram_storage, 8);
162 chip->init();
163 memchips->add(chip);
165 ad = new cl_address_decoder(as = ram, chip, 0, ram_storage-1, 0);
166 ad->init();
167 as->decoders->add(ad);
168 ad->activate(0);
170 chip = new cl_chip16("io_chip", io_size, 8);
171 chip->init();
172 memchips->add(chip);
174 ad = new cl_address_decoder(as = sfr, chip, 0, io_size-1, 0);
175 ad->init();
176 as->decoders->add(ad);
177 ad->activate(0);
179 // extra byte of the IO memory will point to the A register just for the debugger
180 sfr->get_cell(io_size)->decode(&(rA));
183 cSP= sfr->get_cell(2);
184 cF = sfr->get_cell(0);
185 act();
189 void
190 cl_fppa::build_cmdset(class cl_cmdset *cmdset)
192 if (puc == NULL)
193 cl_uc::build_cmdset(cmdset);
198 * Help command interpreter
201 struct dis_entry *cl_fppa::dis_tbl(void) {
202 switch (type->type) {
203 case CPU_PDK13:
204 return (disass_pdk_13);
205 case CPU_PDK14:
206 return (disass_pdk_14);
207 case CPU_PDK15:
208 return (disass_pdk_15);
209 default:
210 return NULL;//__builtin_unreachable();
215 int cl_fppa::inst_length(t_addr /*addr*/) {
216 return 1;
219 int cl_fppa::inst_branch(t_addr addr) {
220 int b;
222 get_disasm_info(addr, NULL, &b, NULL, NULL);
224 return b;
227 bool cl_fppa::is_call(t_addr addr) {
228 struct dis_entry *e;
230 get_disasm_info(addr, NULL, NULL, NULL, &e);
232 return e ? (e->is_call) : false;
235 int cl_fppa::longest_inst(void) { return 1; }
237 const char *cl_fppa::get_disasm_info(t_addr addr, int *ret_len, int *ret_branch,
238 int *immed_offset,
239 struct dis_entry **dentry) {
240 const char *b = NULL;
241 int immed_n = 0;
242 int start_addr = addr;
243 struct dis_entry *instructions;
245 switch (type->type) {
246 /* Dispatch to appropriate pdk port. */
247 case CPU_PDK13:
248 instructions = disass_pdk_13;
249 break;
251 case CPU_PDK14:
252 instructions = disass_pdk_14;
253 break;
255 case CPU_PDK15:
256 instructions = disass_pdk_15;
257 break;
259 default:
260 return "";//__builtin_unreachable();
263 uint code = rom->get(addr++);
264 int i = 0;
265 while ((code & instructions[i].mask) != instructions[i].code &&
266 instructions[i].mnemonic)
267 i++;
268 dis_entry *dis_e = &instructions[i];
269 b = instructions[i].mnemonic;
271 if (ret_branch) {
272 *ret_branch = dis_e->branch;
275 if (immed_offset) {
276 if (immed_n > 0)
277 *immed_offset = immed_n;
278 else
279 *immed_offset = (addr - start_addr);
282 if (ret_len) *ret_len = 1;
284 if (dentry) *dentry = dis_e;
286 return b;
289 char *cl_fppa::disass(t_addr addr)
291 chars work, temp;
292 const char *b;
293 int len = 0;
294 int immed_offset = 0;
295 struct dis_entry *dis_e;
296 bool first= true;
298 work= "";
300 b = get_disasm_info(addr, &len, NULL, &immed_offset, &dis_e);
302 if (b == NULL)
304 return (strdup("UNKNOWN/INVALID"));
307 while (*b)
309 if ((*b == ' ') && first)
311 first= false;
312 while (work.len() < 6) work.append(' ');
314 if (*b == '%')
316 temp= "";
317 b++;
318 uint code = rom->get(addr) & ~(uint)dis_e->mask;
319 switch (*(b++))
321 case 'k': // k immediate addressing
322 temp.format("#0x%x", code);
323 break;
324 case 'm': // m memory addressing
325 if (*b == 'n') {
326 switch (type->type) {
327 case CPU_PDK13:
328 code &= 0x0F;
329 break;
330 case CPU_PDK14:
331 code &= 0x3F;
332 break;
333 case CPU_PDK15:
334 code &= 0x7F;
335 break;
336 default:
337 ;//__builtin_unreachable();
339 ++b;
341 temp.format("0x%x", code);
342 break;
343 case 'i': // i IO addressing
344 // TODO: Maybe add pretty printing.
345 if (*b == 'n') {
346 switch (type->type) {
347 case CPU_PDK13:
348 code &= 0x1F;
349 break;
350 case CPU_PDK14:
351 code &= 0x3F;
352 break;
353 case CPU_PDK15:
354 code &= 0x7F;
355 break;
356 default:
357 ;//__builtin_unreachable();
360 ++b;
362 temp.format("[0x%x]", code);
363 break;
364 case 'n': // n N-bit addressing
365 uint n;
366 switch (type->type) {
367 case CPU_PDK13:
368 n = (code & 0xE0) >> 5;
369 break;
370 case CPU_PDK14:
371 n = (code & 0x1C0) >> 6;
372 break;
373 case CPU_PDK15:
374 n = (code & 0x380) >> 7;
375 break;
376 default:
377 n= 0;//__builtin_unreachable();
379 temp.format("#0x%x", n);
380 break;
381 default:
382 temp= "%?";
383 break;
385 work+= temp;
387 else
388 work+= *(b++);
391 return strdup(work.c_str());
394 void
395 cl_fppa::print_regs(class cl_console_base *con)
397 act();
398 con->dd_color("answer");
399 con->dd_printf("A = %02x %3u\n", rA, rA);
400 con->dd_printf(" OACZ\n");
401 con->dd_printf("F = %02x ", rF);
402 con->dd_printf("%d%d%d%d\n", fO, fA, fC, fZ);
403 con->dd_printf("SP= %02x\n", rSP);
404 print_disass(PC, con);
408 * Execution
411 int cl_fppa::exec_inst(void)
413 t_mem code;
415 act();
416 instPC= PC;
417 if (fetch(&code)) {
418 return (resBREAKPOINT);
420 tick(1);
422 int status = execute(code);
423 if (status == resINV_INST)
425 //PC = instPC;//rom->inc_address(PC, -1);
426 return (resINV_INST);
428 return (status);
432 void
433 cl_fppa::stack_check_overflow(void)
435 if (0)
437 class cl_stack_op *op;
438 op= new cl_stack_op(stack_push, instPC, rSP-1, rSP);
439 class cl_error_stack_overflow *e=
440 new cl_error_stack_overflow(op);
441 e->init();
442 error(e);
447 /****************************************************************************/
450 /* Set nr of active FPP */
452 t_mem
453 cl_act_cell::write(t_mem val)
455 val= puc->set_act(val);
456 return cl_pdk_cell::write(val);
459 /* Set nr of FPPs */
461 t_mem
462 cl_nuof_cell::write(t_mem val)
464 val= puc->set_nuof(val);
465 return cl_pdk_cell::write(val);
469 cl_fppen_op::cl_fppen_op(class cl_pdk *the_puc, class cl_memory_cell *acell):
470 cl_memory_operator(acell)
472 puc= the_puc;
475 t_mem
476 cl_fppen_op::write(t_mem val)
478 return puc->set_fppen(val);
483 * PDK uc
486 cl_pdk::cl_pdk(struct cpu_entry *IType, class cl_sim *asim):
487 cl_uc(asim)
489 int i;
490 type = IType;
491 for (i= 0; i<8; i++)
492 fpps[i]= NULL;
496 cl_pdk::init(void)
498 cl_uc::init();
499 class cl_fppen_op *op;
500 fpps[0]= mk_fppa(0);
502 cFPPEN= sfr->get_cell(1);
503 op= new cl_fppen_op(this, cFPPEN);
504 op->init();
505 cFPPEN->append_operator(op);
506 reg_cell_var(cFPPEN, &rFPPEN, "FPPEN", "FPP unit Enable Register");
507 mk_cvar(sfr->get_cell(0), "FLAG", "ACC Status Flag Register");
508 mk_cvar(sfr->get_cell(2), "SP", "Stack Pointer Register");
510 cact= new cl_act_cell(this);
511 reg_cell_var(cact, &act, "fpp", "ID of actual FPPA");
512 nuof_fpp= 1;
513 cnuof_fpp= new cl_nuof_cell(this);
514 reg_cell_var(cnuof_fpp, &nuof_fpp, "nuof_fpp", "Number of FPPs");
516 if (type->type == CPU_PDKX)
518 fpps[1]= mk_fppa(1);
519 fpps[2]= mk_fppa(2);
520 fpps[3]= mk_fppa(3);
521 fpps[4]= mk_fppa(4);
522 fpps[5]= mk_fppa(5);
523 fpps[6]= mk_fppa(6);
524 fpps[7]= mk_fppa(7);
525 nuof_fpp= 8;
528 act= 0;
529 rFPPEN= 1;
530 return 0;
533 const char *
534 cl_pdk::id_string(void)
536 switch (type->type)
538 case CPU_PDK13:
539 return("pdk13");
540 case CPU_PDK14:
541 return("pdk14");
542 case CPU_PDK15:
543 return("pdk15");
544 case CPU_PDK16:
545 return("pdk16");
546 default:
547 return("pdk");
551 void
552 cl_pdk::make_memories(void)
554 class cl_address_space *as;
555 class cl_address_decoder *ad;
556 class cl_memory_chip *chip;
557 int rom_size= 0x1000, ram_size=0x100;
559 rom = as = new cl_address_space("rom", 0, rom_size, 16);
560 as->init();
561 address_spaces->add(as);
562 ram = as = new cl_address_space("ram", 0, ram_size, 8);
563 as->init();
564 address_spaces->add(as);
565 sfr = as = new cl_address_space("regs8", 0, io_size + 1, 8);
566 as->init();
567 address_spaces->add(as);
569 chip = new cl_chip16("rom_chip", rom_size, 16);
570 chip->init();
571 memchips->add(chip);
573 ad = new cl_address_decoder(as = rom, chip, 0, rom_size-1, 0);
574 ad->init();
575 as->decoders->add(ad);
576 ad->activate(0);
578 chip = new cl_chip16("ram_chip", ram_size, 8);
579 chip->init();
580 memchips->add(chip);
582 ad = new cl_address_decoder(as = ram, chip, 0, ram_size-1, 0);
583 ad->init();
584 as->decoders->add(ad);
585 ad->activate(0);
587 chip = new cl_chip16("io_chip", io_size, 8);
588 chip->init();
589 memchips->add(chip);
591 ad = new cl_address_decoder(as = sfr, chip, 0, io_size-1, 0);
592 ad->init();
593 as->decoders->add(ad);
594 ad->activate(0);
597 class cl_fppa *
598 cl_pdk::mk_fppa(int id)
600 class cl_fppa *fppa;
601 switch (type->type)
603 case CPU_PDK13: fppa= new cl_fppa13(id, this, sim); break;
604 case CPU_PDK14: fppa= new cl_fppa14(id, this, sim); break;
605 case CPU_PDK15: fppa= new cl_fppa15(id, this, sim); break;
606 case CPU_PDK16: fppa= new cl_fppa16(id, this, sim); break;
607 case CPU_PDKX: fppa= new cl_fppa15(id, this, sim); break;
608 default: fppa= new cl_fppa14(id, this, sim); break;
610 fppa->init();
611 return fppa;
615 u8_t
616 cl_pdk::set_fppen(u8_t val)
618 int i;
619 u8_t m;
620 if (val == 0)
621 val= 1;
622 for (i=0, m=1; i<8; i++, m<<=1)
624 if (fpps[i] == NULL)
625 val&= ~m;
627 return val;
630 u8_t
631 cl_pdk::set_act(u8_t val)
633 if (val < nuof_fpp)
634 return val;
635 return 0;
638 u8_t
639 cl_pdk::set_nuof(u8_t val)
641 int i;
642 if (val > 8)
643 val= 8;
644 if (val<1)
645 val= 1;
646 for (i=0; i<8; i++)
648 if (i<val)
650 if (fpps[i] == NULL)
651 fpps[i]= mk_fppa(i);
652 else
653 fpps[i]->reset();
655 else
657 if (fpps[i] != NULL)
659 delete fpps[i];
660 fpps[i]= NULL;
664 if (rFPPEN == 0)
665 set_fppen(1);
666 else
667 set_fppen(rFPPEN);
668 return val;
673 cl_pdk::exec_inst(void)
675 while (!(rFPPEN & (1<<act)))
676 act= (act+1)%nuof_fpp;
677 fpps[act]->pre_inst();
678 int ret= fpps[act]->exec_inst();
679 fpps[act]->post_inst();
680 tick(inst_ticks= fpps[act]->inst_ticks);
681 if (rFPPEN != 1)
684 act= (act+1)%nuof_fpp;
685 while (!(rFPPEN & (1<<act)));
687 return ret;
691 void
692 cl_pdk::print_regs(class cl_console_base *con)
694 int i;
696 for (i= 0; i<nuof_fpp; i++)
698 //con->dd_color((i==act)?"result":"answer");
699 if (rFPPEN & (1<<i))
700 con->dd_cprintf("ui_run", "FPP%d:EN ", i);
701 else
702 con->dd_cprintf("ui_stop", "FPP%d:DIS ", i);
704 con->dd_printf("\n");
705 for (i= 0; i<nuof_fpp; i++)
707 con->dd_color((i==act)?"result":"answer");
708 con->dd_printf("A=%02x %3u ", fpps[i]->rA, fpps[i]->rA);
710 con->dd_printf("\n");
711 for (i= 0; i<nuof_fpp; i++)
713 con->dd_color((i==act)?"result":"answer");
714 con->dd_printf(" OACZ ");
716 con->dd_printf("\n");
717 for (i= 0; i<nuof_fpp; i++)
719 con->dd_color((i==act)?"result":"answer");
720 con->dd_printf("F=", fpps[i]->rF);
721 con->dd_printf("%d%d%d%d ",
722 ((fpps[i]->rF&BIT_OV)>>BITPOS_OV),
723 ((fpps[i]->rF&BIT_AC)>>BITPOS_AC),
724 ((fpps[i]->rF&BIT_C )>>BITPOS_C ),
725 ((fpps[i]->rF&BIT_Z )>>BITPOS_Z ));
727 con->dd_printf("\n");
728 for (i= 0; i<nuof_fpp; i++)
730 con->dd_color((i==act)?"result":"answer");
731 con->dd_printf("SP=%02x ", fpps[i]->rSP);
733 con->dd_printf("\n");
735 for (i=0; i<nuof_fpp; i++)
737 con->dd_color((i==act)?"result":"answer");
738 con->dd_printf("FPP%d: ", i);
739 fpps[0]->print_disass(fpps[i]->PC, con);
744 /* End of pdk.src/pdk.cc */