2 * Simulator of microcontrollers (inst_arith.cc)
4 * Copyright (C) 2016 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
33 cl_tlcs::op_inc(u8_t data
)
36 reg
.raf
.f
&= ~(FLAG_S
|FLAG_Z
|FLAG_H
|FLAG_X
);
46 if ((n
& 0x0f) == 0x00)
55 cl_tlcs::inst_inc(cl_memory_cell
*cell
)
67 cl_tlcs::inst_incx(cl_memory_cell
*cell
)
69 if (reg
.raf
.f
& FLAG_X
)
82 cl_tlcs::op_dec(u8_t data
)
85 reg
.raf
.f
&= ~(FLAG_S
|FLAG_Z
|FLAG_H
|FLAG_X
);
96 if ((n
& 0x0f) == 0x00)
105 cl_tlcs::inst_dec(cl_memory_cell
*cell
)
107 u8_t d
= cell
->read();
117 cl_tlcs::inst_decx(cl_memory_cell
*cell
)
119 if (reg
.raf
.f
& FLAG_X
)
121 u8_t d
= cell
->read();
132 cl_tlcs::op_inc16(u16_t data
)
135 reg
.raf
.f
&= ~(FLAG_X
);
146 cl_tlcs::inst_inc16gg(u8_t gg
, t_addr addr
)
148 cl_address_space
*as
= nas
;
154 u8_t l
= as
->read(addr
);
155 u8_t h
= as
->read(addr
+1);
159 if (((int)d
+ 1) > 0xffff)
169 as
->write(addr
, d
& 0xff);
170 as
->write(addr
+1, d
>> 8);
179 cl_tlcs::inst_inc16(t_addr addr
)
181 return inst_inc16gg(0, addr
);
187 cl_tlcs::inst_inc16ix(u8_t ix
, t_addr addr
)
190 return inst_inc16gg(4, addr
);
191 else if ((ix
&3) == 1)
192 return inst_inc16gg(5, addr
);
193 return inst_inc16gg(0, addr
);
199 cl_tlcs::op_dec16(t_mem data
)
202 reg
.raf
.f
&= ~(FLAG_X
);
213 cl_tlcs::inst_dec16gg(u8_t gg
, t_addr addr
)
215 class cl_address_space
*as
= nas
;
221 u8_t l
= as
->read(addr
);
222 u8_t h
= as
->read(addr
+1);
226 if (((int)d
- 1) < 0)
236 as
->write(addr
, d
& 0xff);
237 as
->write(addr
+1, d
>> 8);
246 cl_tlcs::inst_dec16(t_addr addr
)
248 return inst_dec16gg(0, addr
);
254 cl_tlcs::inst_dec16ix(u8_t ix
, t_addr addr
)
257 return inst_dec16gg(4, addr
);
259 return inst_dec16gg(5, addr
);
260 return inst_dec16gg(0, addr
);
266 cl_tlcs::op_add8(u8_t d1
, u8_t d2
)
268 reg
.raf
.f
&= ~(FLAG_S
|FLAG_Z
|FLAG_H
|FLAG_X
|FLAG_V
|FLAG_N
|FLAG_C
);
271 int new_c
= 0, new_c6
;
273 if (((d1
& 0xf) + (d2
& 0xf)) > 0xf)
275 new_c6
= (((d1
&0x7f) + (d2
&0x7f)) > 0x7f)?1:0;
283 reg
.raf
.f
|= FLAG_X
|FLAG_C
;
295 cl_tlcs::op_add_a(u8_t d
)
297 return op_add8(reg
.raf
.a
, d
);
303 cl_tlcs::inst_add_a(class cl_memory_cell
*cell
)
305 reg
.raf
.a
= op_add_a((u8_t
)(cell
->read()));
313 cl_tlcs::op_adc8(u8_t d1
, u8_t d2
)
315 int oldc
= (reg
.raf
.f
&FLAG_C
)?1:0;
316 reg
.raf
.f
&= ~(FLAG_S
|FLAG_Z
|FLAG_H
|FLAG_X
|FLAG_V
|FLAG_N
|FLAG_C
);
318 int r
= d1
+ d2
+ oldc
;
319 int new_c
= 0, new_c6
;
321 if (((d1
& 0xf) + (d2
& 0xf) + oldc
) > 0xf)
323 new_c6
= (((d1
&0x7f) + (d2
&0x7f) + oldc
) > 0x7f)?1:0;
331 reg
.raf
.f
|= FLAG_X
|FLAG_C
;
343 cl_tlcs::inst_adc_a(u8_t d
)
345 reg
.raf
.a
= op_adc8(reg
.raf
.a
, d
);
352 cl_tlcs::inst_adc_a(class cl_memory_cell
*cell
)
355 return inst_adc_a((u8_t
)(cell
->read()));
361 cl_tlcs::op_sub8(u8_t d1
, u8_t d2
)
363 unsigned int op1
= (unsigned int)d1
;
364 unsigned int op2
= (unsigned int)d2
;
365 signed int res
= (signed char)d1
- (signed char)d2
;
368 reg
.raf
.f
&= ~(FLAG_H
|FLAG_V
|FLAG_C
|FLAG_Z
|FLAG_S
);
371 if ((op1
& 0xf) < (op2
& 0xf))
373 if ((res
< -128) || (res
> 127))
376 reg
.raf
.f
|= FLAG_C
|FLAG_X
;
379 //r= op_add8(d1, ~d2 + 1);
385 //reg.raf.f|= FLAG_N;
392 cl_tlcs::inst_sub_a(u8_t d
)
394 reg
.raf
.a
= op_sub8(reg
.raf
.a
, d
);
401 cl_tlcs::inst_sub_a(class cl_memory_cell
*cell
)
404 return inst_sub_a((u8_t
)(cell
->read()));
410 cl_tlcs::op_sbc8(u8_t d1
, u8_t d2
)
413 unsigned int op1
= (unsigned int)d1
;
414 unsigned int op2
= (unsigned int)d2
;
415 signed int res
= (signed char)d1
- (signed char)d2
;
417 if (reg
.raf
.f
& FLAG_C
)
422 reg
.raf
.f
&= ~(FLAG_H
|FLAG_V
|FLAG_C
|FLAG_S
|FLAG_Z
);
425 if ((op1
& 0xf) < (op2
& 0xf))
427 if ((res
< -128) || (res
> 127))
439 //r= op_adc8(d1, ~d2 + 1);
440 //reg.raf.f|= FLAG_N;
447 cl_tlcs::inst_sbc_a(u8_t d
)
449 reg
.raf
.a
= op_sbc8(reg
.raf
.a
, d
);
456 cl_tlcs::inst_sbc_a(class cl_memory_cell
*cell
)
459 return inst_sbc_a((u8_t
)(cell
->read()));
465 cl_tlcs::op_and8(u8_t d1
, u8_t d2
)
467 reg
.raf
.f
&= ~(FLAG_S
|FLAG_Z
|FLAG_X
|FLAG_N
|FLAG_C
);
483 cl_tlcs::inst_and_a(u8_t d
)
485 reg
.raf
.a
= op_and8(reg
.raf
.a
, d
);
492 cl_tlcs::inst_and_a(class cl_memory_cell
*cell
)
495 return inst_and_a((u8_t
)(cell
->read()));
501 cl_tlcs::op_xor8(u8_t d1
, u8_t d2
)
503 reg
.raf
.f
&= ~(FLAG_S
|FLAG_Z
|FLAG_H
|FLAG_X
|FLAG_N
|FLAG_C
);
518 cl_tlcs::inst_xor_a(u8_t d
)
520 reg
.raf
.a
= op_xor8(reg
.raf
.a
, d
);
527 cl_tlcs::inst_xor_a(class cl_memory_cell
*cell
)
530 return inst_xor_a((u8_t
)(cell
->read()));
536 cl_tlcs::op_or8(u8_t d1
, u8_t d2
)
538 reg
.raf
.f
&= ~(FLAG_S
|FLAG_Z
|FLAG_H
|FLAG_X
|FLAG_N
|FLAG_C
);
553 cl_tlcs::inst_or_a(u8_t d
)
555 reg
.raf
.a
= op_or8(reg
.raf
.a
, d
);
562 cl_tlcs::inst_or_a(class cl_memory_cell
*cell
)
565 return inst_or_a((u8_t
)(cell
->read()));
571 cl_tlcs::op_cp8(u8_t d1
, u8_t d2
)
573 u8_t r
= op_sub8(d1
, d2
);
581 cl_tlcs::op_cp_a(u8_t d
)
583 op_cp8(reg
.raf
.a
, d
);
590 cl_tlcs::op_cp_a(class cl_memory_cell
*cell
)
593 return op_cp_a((u8_t
)(cell
->read()));
599 cl_tlcs::op_add16(t_mem op1
, t_mem op2
)
604 reg
.raf
.f
&= ~(FLAG_S
|FLAG_Z
|FLAG_X
|FLAG_N
|FLAG_C
);
610 newc15
= (((d1
&0x7fff)+(d
&0x7fff)) > 0x7fff)?0x10000:0;
614 if ((r
& 0xffff) == 0)
617 reg
.raf
.f
|= FLAG_C
|FLAG_X
;
618 if (newc15
^ (r
&0x10000))
627 cl_tlcs::op_add_hl_a(t_addr addr
)
633 dh
= nas
->read(addr
+1);
637 return op_add16(reg
.hl
, d
);
643 cl_tlcs::op_add_hl_v(t_mem val
)
645 return op_add16(reg
.hl
, val
);
651 cl_tlcs::op_adc_hl_v(t_mem val
)
655 u16_t d
= dh
*256 + dl
;
656 int oldc
= (reg
.raf
.f
& FLAG_C
)?1:0;
658 return op_add_hl_v(d
+ oldc
);
664 cl_tlcs::op_adc_hl_a(t_addr addr
)
666 u8_t dl
= nas
->read(addr
);
667 u8_t dh
= nas
->read(addr
+1);
668 u16_t d
= dh
*256 + dl
;
669 int oldc
= (reg
.raf
.f
& FLAG_C
)?1:0;
672 return op_add_hl_v(d
+ oldc
);
678 cl_tlcs::op_sub16(t_mem d1
, t_mem d2
)
682 unsigned int op1
= (unsigned int)d1
;
683 unsigned int op2
= (unsigned int)d2
;
684 signed int res
= (i16_t
)d1
- (i16_t
)d2
;
686 reg
.raf
.f
&= ~(FLAG_C
|FLAG_V
|FLAG_Z
|FLAG_S
);
689 if ((res
< -32768) || (res
> 32767))
692 reg
.raf
.f
|= FLAG_C
|FLAG_X
;
707 cl_tlcs::op_sub_hl_v(t_mem val
)
709 return op_sub16(reg
.hl
, val
);
715 cl_tlcs::op_sub_hl_a(t_addr addr
)
717 u8_t dl
= nas
->read(addr
);
718 u8_t dh
= nas
->read(addr
+1);
719 u16_t d
= dh
*256 + dl
;
722 return op_sub16(reg
.hl
, d
);
728 cl_tlcs::op_sbc_hl_v(t_mem val
)
732 unsigned int op1
= (unsigned int)reg
.hl
;
733 unsigned int op2
= (unsigned int)val
;
734 signed int res
= (i16_t
)reg
.hl
- (i16_t
)val
;
736 if (reg
.raf
.f
& FLAG_C
)
741 reg
.raf
.f
&= ~(FLAG_C
|FLAG_V
|FLAG_Z
|FLAG_S
);
744 if ((op1
& 0xfff) < (op2
& 0xfff))
746 if ((res
< -32768) || (res
> 32767))
764 cl_tlcs::op_sbc_hl_a(t_addr addr
)
766 u8_t dl
= nas
->read(addr
);
767 u8_t dh
= nas
->read(addr
+1);
768 u16_t d
= dh
*256 + dl
;
771 return op_sbc_hl_v(d
);
777 cl_tlcs::op_and_hl_v(t_mem val
)
782 reg
.raf
.f
&= ~(FLAG_S
|FLAG_Z
|FLAG_X
|FLAG_N
|FLAG_C
);
797 cl_tlcs::op_and_hl_a(t_addr addr
)
799 u8_t dl
= nas
->read(addr
);
800 u8_t dh
= nas
->read(addr
+1);
801 u16_t d
= dh
*256 + dl
;
804 return op_and_hl_v(d
);
810 cl_tlcs::op_xor_hl_v(t_mem val
)
815 reg
.raf
.f
&= ~(FLAG_S
|FLAG_Z
|FLAG_H
|FLAG_X
|FLAG_N
|FLAG_C
);
829 cl_tlcs::op_xor_hl_a(t_addr addr
)
831 u8_t dl
= nas
->read(addr
);
832 u8_t dh
= nas
->read(addr
+1);
833 u16_t d
= dh
*256 + dl
;
836 return op_xor_hl_v(d
);
842 cl_tlcs::op_or_hl_v(t_mem val
)
847 reg
.raf
.f
&= ~(FLAG_S
|FLAG_Z
|FLAG_H
|FLAG_X
|FLAG_N
|FLAG_C
);
861 cl_tlcs::op_or_hl_a(t_addr addr
)
863 u8_t dl
= nas
->read(addr
);
864 u8_t dh
= nas
->read(addr
+1);
865 u16_t d
= dh
*256 + dl
;
868 return op_or_hl_v(d
);
872 /* End of tlcs/inst_arith.cc */