2 * Simulator of microcontrollers (p1516.cc)
4 * Copyright (C) 2020 Drotos Daniel
6 * To contact author send email to dr.dkdb@gmail.com
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
38 #include "brd_ctrlcl.h"
43 cl_pc_write::cl_pc_write(class cl_memory_cell
*acell
, class cl_uc
*the_uc
):
44 cl_memory_operator(acell
)
50 cl_pc_write::write(t_mem val
)
57 cl_p1516::cl_p1516(class cl_sim
*asim
):
71 reg_cell_var(&cF
, &F
, "F", "Flag register");
72 class cl_pc_write
*pcw
= new cl_pc_write(&cPC
, this);
74 cPC
.append_operator(pcw
);
79 cl_p1516::id_string(void)
94 cl_p1516::set_PC(t_addr addr
)
100 cl_p1516::mk_hw_elements(void)
103 cl_uc::mk_hw_elements();
105 add_hw(h
= new cl_dreg(this, 0, "dreg"));
108 add_hw(pa
= new cl_porto(this, 0xff00, "pa"));
110 add_hw(pb
= new cl_porto(this, 0xff01, "pb"));
112 add_hw(pc
= new cl_porto(this, 0xff02, "pc"));
114 add_hw(pd
= new cl_porto(this, 0xff03, "pd"));
117 add_hw(pi
= new cl_porti(this, 0xff20, "pi"));
119 add_hw(pj
= new cl_porti(this, 0xff10, "pj"));
122 add_hw(h
= new cl_timer(this, 0xff30, "timer"));
125 add_hw(h
= new cl_uart(this, 0, 0xff40));
128 add_hw(h
= new cl_clock(this, 0xff50, "clock"));
131 class cl_port_ui
*u
= new cl_port_ui(this, 0, "dport");
134 class cl_port_ui
*uo
= new cl_port_ui(this, 0, "oports");
137 class cl_port_ui
*ui
= new cl_port_ui(this, 0, "iports");
141 class cl_port_data d
;
184 d
.cell_in
= pi
->cfg_cell(port_pin
);
185 d
.keyset
= chars(" qwertyui12345678");
194 d
.cell_in
= pj
->cfg_cell(port_pin
);
195 d
.keyset
= chars(" asdfghjkzxcvbnm,");
202 add_hw(h
= new cl_n4(this, 0, "n4ddr"));
204 add_hw(h
= new cl_bool(this, 0, "boolean"));
206 add_hw(h
= new cl_logsys(this, 0, "logsys"));
209 add_hw(bc
= new cl_brd_ctrl(this, 0, "brd_ctrl"));
214 cl_p1516::make_memories(void)
216 class cl_address_space
*as
;
220 rom
= as
= new cl_address_space("rom"/*MEM_ROM_ID*/, 0, 0x20000, 32);
222 //printf("%f\n", dnow()-st);
223 address_spaces
->add(as
);
225 class cl_address_decoder
*ad
;
226 class cl_memory_chip
*chip
;
228 chip
= new cl_chip32("rom_chip", 0x20000, 32, 0);
232 ad
= new cl_address_decoder(as
= rom
, chip
, 0, /*0xfeff*/0x1ffff, 0);
234 as
->decoders
->add(ad
);
236 /*ad= new cl_address_decoder(as= rom, chip, 0x10000, 0x1ffff, 0x10000);
238 as->decoders->add(ad);
241 regs
= new cl_address_space("regs", 0, 16, 32);
243 for (i
= 0; i
<16; i
++)
245 RC
[i
]= regs
->get_cell(i
);
246 RC
[i
]->decode((t_mem
*)&R
[i
]);
248 address_spaces
->add(regs
);
254 d
.format("CPU register %d", i
);
255 vars
->add(n
, regs
, i
, d
);
261 cl_p1516::dis_tbl(void)
263 return(disass_p1516
);
267 cl_p1516::disassc(t_addr addr
, chars
*comment
)
269 chars work
= chars(), temp
= chars();
274 code
= rom
->get(addr
);
277 while ((code
& dis_tbl()[i
].mask
) != dis_tbl()[i
].code
&&
278 dis_tbl()[i
].mnemonic
)
280 if (dis_tbl()[i
].mnemonic
== NULL
)
282 return strdup("-- UNKNOWN/INVALID");
284 b
= dis_tbl()[i
].mnemonic
;
286 data
= (code
&0xf0000000)>>28;
287 if (((data
& 1) == 0) || (dis_tbl()[i
].branch
== 'M'))
293 case 0: work
.append("S"); break;
294 case 1: work
.append("C"); break;
295 case 2: work
.append("Z"); break;
296 case 3: work
.append("O"); break;
312 data
= (code
& 0x00f00000)>>20;
313 work
.appendf("r%d", data
);
316 data
= (code
& 0x000f0000)>>16;
317 work
.appendf("r%d", data
);
319 case 'R': // Ra in LD, ST
320 data
= (code
& 0x000f0000)>>16;
321 work
.appendf("r%d", data
);
325 addr_name(R
[data
], rom
, &n
);
326 comment
->format("; [0x%08x%s]= 0x%08x",
333 data
= (code
& 0x0000f000)>>12;
334 work
.appendf("r%d", data
);
337 data
= (code
& 0x0000ffff);
338 work
.appendf("0x0000%04x", data
);
339 addr_name(data
, rom
, &work
);
341 case 'O': // LDL0 -> jump
342 data
= (code
& 0x0000ffff);
343 work
.appendf("0x%04x", data
);
344 addr_name(data
, rom
, &work
);
347 data
= (code
& 0x0000ffff);
348 work
.appendf("0x....%04x", data
);
351 data
= (code
& 0x0000ffff);
352 work
.appendf("0x%04x....", data
);
355 data
= (code
& 0x07ffffff);
356 work
.appendf("0x%x", data
);
357 addr_name(data
, rom
, &work
);
363 if (comment
&& temp
.nempty())
364 comment
->append(temp
);
370 return strdup(work
.c_str());
374 cl_p1516::analyze_start(void)
376 class cl_var
*v
= new cl_var(".reset", rom
, 0, chars("Auto-generated by analyze"), -1, -1);
384 cl_p1516::analyze(t_addr addr
)
386 struct dis_entry
*de
;
389 while (!inst_at(addr
))
391 t_mem code
= rom
->read(addr
);
393 while ((code
& dis_tbl()[i
].mask
) != dis_tbl()[i
].code
&&
394 dis_tbl()[i
].mnemonic
)
397 if (de
->mnemonic
== NULL
)
403 case 'x': case '_': // non-followable
405 case 'M': // LDL0 r15,#imm
407 t_addr target
= rom
->read(addr
) & 0xffff;
408 analyze_jump(addr
, target
, de
->branch
);
412 addr
= rom
->validate_address(addr
+1);
417 cl_p1516::print_regs(class cl_console_base
*con
)
420 con
->dd_color("answer");
421 con
->dd_printf(" F= 0x%08x ", F
);
422 con
->dd_printf("O=%c ", (F
&O
)?'1':'0');
423 con
->dd_printf("C=%c ", (F
&C
)?'1':'0');
424 con
->dd_printf("Z=%c ", (F
&Z
)?'1':'0');
425 con
->dd_printf("S=%c ", (F
&S
)?'1':'0');
426 con
->dd_printf("\n");
427 for (i
= 0; i
<16; i
++)
429 if (i
<10) con
->dd_printf(" ");
430 con
->dd_printf("R%d= 0x%08x ", i
, R
[i
]);
431 if (i
<10) con
->dd_printf(" ");
432 con
->dd_printf("[R%d]= 0x%08x", i
, rom
->get(R
[i
]));
434 con
->dd_printf("\n");
438 print_disass(PC
, con
);
443 cl_p1516::cond(t_mem code
)
445 t_mem cond
= (code
& 0xf0000000) >> 28;
451 case 0: flag
= F
&S
; break;
452 case 1: flag
= F
&C
; break;
453 case 2: flag
= F
&Z
; break;
454 case 3: flag
= F
&O
; break;
465 cl_p1516::inst_ad(t_mem ra
, t_mem rb
, u32_t c
)
470 big
= (u64_t
)ra
+ (u64_t
)rb
+ (u64_t
)c
;
472 if (big
> 0xffffffff)
479 big
= (ra
& 0x7fffffff) + (rb
& 0x7fffffff) + c
;
480 if ((big
& 0x80000000) && !(F
&C
))
482 if (!(big
& 0x80000000) && (F
&C
))
489 cl_p1516::inst_alu(t_mem code
)
495 d
= (code
& 0x00f00000) >> 20;
496 a
= (code
& 0x000f0000) >> 16;
497 b
= (code
& 0x0000f000) >> 12;
498 Op
=(code
& 0x00000f80) >> 7;
503 RC
[d
]->W(inst_ad(R
[a
], R
[b
], 0));
506 RC
[d
]->W(inst_ad(R
[a
], R
[b
], (F
&C
)?1:0));
509 RC
[d
]->W(inst_ad(R
[a
], ~(R
[b
]), 1));
512 RC
[d
]->W(inst_ad(R
[a
], ~(R
[b
]), (F
&C
)?1:0));
516 RC
[d
]->W(inst_ad(R
[a
], 1, 0));
519 RC
[d
]->W(inst_ad(R
[a
], ~(1), 1));
523 RC
[d
]->W(R
[a
] & R
[b
]);
527 RC
[d
]->W(R
[a
] | R
[b
]);
531 RC
[d
]->W(R
[a
] ^ R
[b
]);
536 SET_C(R
[a
] & 0x80000000);
547 RC
[d
]->W(((i32_t
)(R
[a
])) >> 1);
552 c2
= (R
[a
] & 0x80000000)?1:0;
553 RC
[d
]->W((R
[a
]<<1) + c1
);
569 RC
[d
]->W(R
[a
] * R
[b
]);
571 SET_S(R
[d
] & 0x80000000);
574 big
= (u64_t
)R
[a
] * (u64_t
)R
[b
];
577 SET_S(R
[d
] & 0x80000000);
590 inst_ad(R
[a
], ~(R
[b
]), 1);
598 cl_p1516::exec_inst(void)
610 return(resBREAKPOINT
);
615 inst
= (code
& 0x0f000000) >> 24;
616 if (code
& 0x08000000)
619 t_addr data
= (code
& 0x07ffffff);
626 d
= (code
& 0x00f00000) >> 20;
627 a
= (code
& 0x000f0000) >> 16;
633 R
[d
]= rom
->read(R
[a
]);
637 rom
->write(R
[a
], R
[d
]);
643 case 4: // LDL0 Rd,data
644 RC
[d
]->W(code
& 0x0000ffff);
646 case 5: // LDL Rd,data
647 RC
[d
]->W((R
[d
] & 0xffff0000) | (code
& 0x0000ffff));
649 case 6: // LDH Rd,data
650 RC
[d
]->W((R
[d
] & 0x0000ffff) | (code
<< 16));
663 cl_p1516::btn_edge(int btn
, bool press
)
668 if ((btn
==1) && press
)
669 r2b_state
= r2b_alarmed
;
672 if ((btn
==1) && !press
)
674 if ((btn
==0) && press
)
677 r2b_state
= r2b_activated
;
681 if ((btn
==1) && !press
)
688 /* End of p1516.src/p1516.cc */