1 /* rl78.c --- opcode semantics for stand-alone RL78 simulator.
3 Copyright (C) 2008-2019 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
6 This file is part of the GNU simulators.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #include "opcode/rl78.h"
35 static int opcode_pc
= 0;
37 jmp_buf decode_jmp_buf
;
38 #define DO_RETURN(x) longjmp (decode_jmp_buf, x)
40 #define tprintf if (trace) printf
42 #define WILD_JUMP_CHECK(new_pc) \
44 if (new_pc == 0 || new_pc > 0xfffff) \
47 fprintf (stderr, "Wild jump to 0x%x from 0x%x!\n", new_pc, pc); \
48 DO_RETURN (RL78_MAKE_HIT_BREAK ()); \
57 rl78_get_byte (void *vdata
)
59 RL78_Data
*rl78_data
= (RL78_Data
*)vdata
;
60 int rv
= mem_get_pc (rl78_data
->dpc
);
66 op_addr (const RL78_Opcode_Operand
*o
, int for_data
)
69 if (o
->reg
!= RL78_Reg_None
)
70 v
+= get_reg (o
->reg
);
71 if (o
->reg2
!= RL78_Reg_None
)
72 v
+= get_reg (o
->reg2
);
74 v
|= (get_reg (RL78_Reg_ES
) & 0xf) << 16;
82 get_op (const RL78_Opcode_Decoded
*rd
, int i
, int for_data
)
85 const RL78_Opcode_Operand
*o
= rd
->op
+ i
;
89 case RL78_Operand_None
:
90 /* condition code does this. */
94 case RL78_Operand_Immediate
:
99 case RL78_Operand_Register
:
100 tprintf (" %s=", reg_names
[o
->reg
]);
101 v
= get_reg (o
->reg
);
104 case RL78_Operand_Bit
:
105 tprintf (" %s.%d=", reg_names
[o
->reg
], o
->bit_number
);
106 v
= get_reg (o
->reg
);
107 v
= (v
& (1 << o
->bit_number
)) ? 1 : 0;
110 case RL78_Operand_Indirect
:
111 v
= op_addr (o
, for_data
);
112 tprintf (" [0x%x]=", v
);
113 if (rd
->size
== RL78_Word
)
119 case RL78_Operand_BitIndirect
:
120 v
= op_addr (o
, for_data
);
121 tprintf (" [0x%x].%d=", v
, o
->bit_number
);
122 v
= (mem_get_qi (v
) & (1 << o
->bit_number
)) ? 1 : 0;
125 case RL78_Operand_PreDec
:
126 r
= get_reg (o
->reg
);
127 tprintf (" [--%s]", reg_names
[o
->reg
]);
128 if (rd
->size
== RL78_Word
)
131 v
= mem_get_hi (r
| 0xf0000);
136 v
= mem_get_qi (r
| 0xf0000);
141 case RL78_Operand_PostInc
:
142 tprintf (" [%s++]", reg_names
[o
->reg
]);
143 r
= get_reg (o
->reg
);
144 if (rd
->size
== RL78_Word
)
146 v
= mem_get_hi (r
| 0xf0000);
151 v
= mem_get_qi (r
| 0xf0000);
165 put_op (const RL78_Opcode_Decoded
*rd
, int i
, int for_data
, int v
)
168 const RL78_Opcode_Operand
*o
= rd
->op
+ i
;
174 case RL78_Operand_Register
:
175 tprintf ("%s", reg_names
[o
->reg
]);
179 case RL78_Operand_Bit
:
180 tprintf ("%s.%d", reg_names
[o
->reg
], o
->bit_number
);
181 r
= get_reg (o
->reg
);
183 r
|= (1 << o
->bit_number
);
185 r
&= ~(1 << o
->bit_number
);
189 case RL78_Operand_Indirect
:
190 r
= op_addr (o
, for_data
);
191 tprintf ("[0x%x]", r
);
192 if (rd
->size
== RL78_Word
)
198 case RL78_Operand_BitIndirect
:
199 a
= op_addr (o
, for_data
);
200 tprintf ("[0x%x].%d", a
, o
->bit_number
);
203 r
|= (1 << o
->bit_number
);
205 r
&= ~(1 << o
->bit_number
);
209 case RL78_Operand_PreDec
:
210 r
= get_reg (o
->reg
);
211 tprintf ("[--%s]", reg_names
[o
->reg
]);
212 if (rd
->size
== RL78_Word
)
216 mem_put_hi (r
| 0xf0000, v
);
222 mem_put_qi (r
| 0xf0000, v
);
226 case RL78_Operand_PostInc
:
227 tprintf ("[%s++]", reg_names
[o
->reg
]);
228 r
= get_reg (o
->reg
);
229 if (rd
->size
== RL78_Word
)
231 mem_put_hi (r
| 0xf0000, v
);
236 mem_put_qi (r
| 0xf0000, v
);
249 op_flags (int before
, int after
, int mask
, RL78_Size size
)
251 int vmask
, cmask
, amask
, avmask
;
253 if (size
== RL78_Word
)
268 int psw
= get_reg (RL78_Reg_PSW
);
271 if (mask
& RL78_PSW_CY
)
273 if ((after
& cmask
) != (before
& cmask
))
276 if (mask
& RL78_PSW_AC
)
278 if ((after
& amask
) != (before
& amask
)
279 && (after
& avmask
) < (before
& avmask
))
282 if (mask
& RL78_PSW_Z
)
284 if (! (after
& vmask
))
288 set_reg (RL78_Reg_PSW
, psw
);
291 #define FLAGS(before,after) if (opcode.flags) op_flags (before, after, opcode.flags, opcode.size)
293 #define PD(x) put_op (&opcode, 0, 1, x)
294 #define PS(x) put_op (&opcode, 1, 1, x)
295 #define GD() get_op (&opcode, 0, 1)
296 #define GS() get_op (&opcode, 1, 1)
298 #define GPC() gpc (&opcode, 0)
300 gpc (RL78_Opcode_Decoded
*opcode
, int idx
)
302 int a
= get_op (opcode
, 0, 1);
303 if (opcode
->op
[idx
].type
== RL78_Operand_Register
)
304 a
=(a
& 0x0ffff) | ((get_reg (RL78_Reg_CS
) & 0x0f) << 16);
313 return (get_reg (RL78_Reg_PSW
) & RL78_PSW_CY
) ? 1 : 0;
319 int p
= get_reg (RL78_Reg_PSW
);
320 tprintf ("set_carry (%d)\n", c
? 1 : 0);
325 set_reg (RL78_Reg_PSW
, p
);
328 /* We simulate timer TM00 in interval mode, no clearing, with
329 interrupts. I.e. it's a cycle counter. */
331 unsigned int counts_per_insn
[0x100000];
333 int pending_clocks
= 0;
334 long long total_clocks
= 0;
339 process_clock_tick (void)
342 unsigned short ivect
;
352 counts_per_insn
[opcode_pc
] += pending_clocks
;
353 total_clocks
+= pending_clocks
;
355 while (pending_clocks
)
358 cnt
= mem_get_hi (TCR0
);
360 mem_put_hi (TCR0
, cnt
);
365 psw
= get_reg (RL78_Reg_PSW
);
366 ivect
= mem_get_hi (0x0002c);
367 mask
= mem_get_hi (MK1
);
369 if ((psw
& RL78_PSW_IE
)
373 unsigned short sp
= get_reg (RL78_Reg_SP
);
374 set_reg (RL78_Reg_SP
, sp
- 4);
376 mem_put_qi (sp
| 0xf0000, psw
);
378 mem_put_psi (sp
| 0xf0000, pc
);
380 set_reg (RL78_Reg_PSW
, psw
);
382 /* Spec says 9-14 clocks */
391 dump_counts_per_insn (const char * filename
)
395 f
= fopen (filename
, "w");
401 for (i
= 0; i
< 0x100000; i
++)
403 if (counts_per_insn
[i
])
404 fprintf (f
, "%05x %d\n", i
, counts_per_insn
[i
]);
412 pending_clocks
+= n
- 1;
419 RL78_Opcode_Decoded opcode
;
426 isa
= (rl78_g10_mode
? RL78_ISA_G10
427 : g14_multiply
? RL78_ISA_G14
428 : g13_multiply
? RL78_ISA_G13
432 opcode_size
= rl78_decode_opcode (pc
, &opcode
,
433 rl78_get_byte
, &rl78_data
, isa
);
438 trace_register_words
= opcode
.size
== RL78_Word
? 1 : 0;
440 /* Used by shfit/rotate instructions */
441 obits
= opcode
.size
== RL78_Word
? 16 : 8;
452 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
460 v
= a
+ b
+ get_carry ();
463 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
474 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
478 case RLO_branch_cond
:
479 case RLO_branch_cond_clear
:
480 tprintf ("BRANCH_COND: ");
481 if (!condition_true (opcode
.op
[1].condition
, GS ()))
483 tprintf (" false\n");
484 if (opcode
.op
[1].condition
== RL78_Condition_T
485 || opcode
.op
[1].condition
== RL78_Condition_F
)
491 if (opcode
.id
== RLO_branch_cond_clear
)
494 if (opcode
.op
[1].condition
== RL78_Condition_T
495 || opcode
.op
[1].condition
== RL78_Condition_F
)
496 CLOCKS (3); /* note: adds two clocks, total 5 clocks */
498 CLOCKS (2); /* note: adds one clock, total 4 clocks */
500 tprintf ("BRANCH: ");
504 tprintf (" => 0x%05x\n", pc
);
512 DO_RETURN (RL78_MAKE_HIT_BREAK ());
514 DO_RETURN (RL78_MAKE_EXITED (1));
519 a
= get_reg (RL78_Reg_SP
);
520 set_reg (RL78_Reg_SP
, a
- 4);
521 mem_put_psi ((a
- 4) | 0xf0000, pc
);
526 /* Enable this code to dump the arguments for each call. */
531 for (i
= 0; i
< 8; i
++)
532 printf (" %02x", mem_get_qi (0xf0000 | (a
+ i
)) & 0xff);
546 tprintf (" (%d)\n", v
);
550 a
= get_reg (RL78_Reg_AX
);
551 b
= get_reg (RL78_Reg_DE
);
552 tprintf (" %d / %d = ", a
, b
);
555 tprintf ("%d rem %d\n", 0xffff, a
);
556 set_reg (RL78_Reg_AX
, 0xffff);
557 set_reg (RL78_Reg_DE
, a
);
563 tprintf ("%d rem %d\n", v
, a
);
564 set_reg (RL78_Reg_AX
, v
);
565 set_reg (RL78_Reg_DE
, a
);
572 unsigned long bcax
, hlde
, quot
, rem
;
573 bcax
= get_reg (RL78_Reg_AX
) + 65536 * get_reg (RL78_Reg_BC
);
574 hlde
= get_reg (RL78_Reg_DE
) + 65536 * get_reg (RL78_Reg_HL
);
576 tprintf (" %lu / %lu = ", bcax
, hlde
);
579 tprintf ("%lu rem %lu\n", 0xffffLU
, bcax
);
580 set_reg (RL78_Reg_AX
, 0xffffLU
);
581 set_reg (RL78_Reg_BC
, 0xffffLU
);
582 set_reg (RL78_Reg_DE
, bcax
);
583 set_reg (RL78_Reg_HL
, bcax
>> 16);
589 tprintf ("%lu rem %lu\n", quot
, rem
);
590 set_reg (RL78_Reg_AX
, quot
);
591 set_reg (RL78_Reg_BC
, quot
>> 16);
592 set_reg (RL78_Reg_DE
, rem
);
593 set_reg (RL78_Reg_HL
, rem
>> 16);
601 DO_RETURN (RL78_MAKE_EXITED (get_reg (RL78_Reg_A
)));
613 a
= sign_ext (get_reg (RL78_Reg_AX
), 16);
614 b
= sign_ext (get_reg (RL78_Reg_BC
), 16);
615 v
= sign_ext (mem_get_si (MACR
), 32);
616 tprintf ("%08x %d + %d * %d = ", v
, v
, a
, b
);
617 v2
= sign_ext (v
+ a
* b
, 32);
618 tprintf ("%08x %d\n", v2
, v2
);
619 mem_put_si (MACR
, v2
);
620 a
= get_reg (RL78_Reg_PSW
);
630 set_reg (RL78_Reg_PSW
, a
);
636 a
= get_reg (RL78_Reg_AX
);
637 b
= get_reg (RL78_Reg_BC
);
638 u
= mem_get_si (MACR
);
639 tprintf ("%08x %u + %u * %u = ", u
, u
, a
, b
);
640 u2
= (u
+ (unsigned)a
* (unsigned)b
) & 0xffffffffUL
;
641 tprintf ("%08x %u\n", u2
, u2
);
642 mem_put_si (MACR
, u2
);
643 a
= get_reg (RL78_Reg_PSW
);
649 set_reg (RL78_Reg_PSW
, a
);
655 a
= get_reg (RL78_Reg_A
);
656 b
= get_reg (RL78_Reg_X
);
658 tprintf (" %d * %d = %d\n", a
, b
, v
);
659 set_reg (RL78_Reg_AX
, v
);
664 a
= sign_ext (get_reg (RL78_Reg_AX
), 16);
665 b
= sign_ext (get_reg (RL78_Reg_BC
), 16);
667 tprintf (" %d * %d = %d\n", a
, b
, v
);
668 set_reg (RL78_Reg_BC
, v
>> 16);
669 set_reg (RL78_Reg_AX
, v
);
675 a
= get_reg (RL78_Reg_AX
);
676 b
= get_reg (RL78_Reg_BC
);
678 tprintf (" %d * %d = %d\n", a
, b
, v
);
679 set_reg (RL78_Reg_BC
, v
>> 16);
680 set_reg (RL78_Reg_AX
, v
);
695 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
701 a
= get_reg (RL78_Reg_SP
);
702 v
= mem_get_psi (a
| 0xf0000);
705 set_reg (RL78_Reg_SP
, a
+ 4);
707 /* Enable this code to dump the return values for each return. */
712 for (i
= 0; i
< 8; i
++)
713 printf (" %02x", mem_get_qi (0xffef0 + i
) & 0xff);
723 a
= get_reg (RL78_Reg_SP
);
724 v
= mem_get_psi (a
| 0xf0000);
727 b
= mem_get_qi ((a
+ 3) | 0xf0000);
728 set_reg (RL78_Reg_PSW
, b
);
729 set_reg (RL78_Reg_SP
, a
+ 4);
734 tprintf ("ROL:"); /* d <<= s */
741 v
|= (b
>> (obits
- 1)) & 1;
742 set_carry ((b
>> (obits
- 1)) & 1);
749 tprintf ("ROLC:"); /* d <<= s */
757 set_carry ((b
>> (obits
- 1)) & 1);
764 tprintf ("ROR:"); /* d >>= s */
771 v
|= (b
& 1) << (obits
- 1);
779 tprintf ("RORC:"); /* d >>= s */
786 v
|= (get_carry () << (obits
- 1));
794 tprintf ("SAR:"); /* d >>= s */
801 v
|= b
& (1 << (obits
- 1));
811 b
= get_reg (RL78_Reg_PSW
);
812 b
&= ~(RL78_PSW_RBS1
| RL78_PSW_RBS0
);
817 set_reg (RL78_Reg_PSW
, b
);
822 tprintf ("SHL%d:", obits
); /* d <<= s */
829 tprintf ("b = 0x%x & 0x%x\n", b
, 1<<(obits
- 1));
830 set_carry (b
& (1<<(obits
- 1)));
837 tprintf ("SHR:"); /* d >>= s */
852 if (!condition_true (opcode
.op
[1].condition
, GS ()))
854 tprintf (" false\n");
859 opcode_size
= rl78_decode_opcode (pc
, &opcode
,
860 rl78_get_byte
, &rl78_data
, isa
);
862 tprintf (" skipped: %s\n", opcode
.syntax
);
867 DO_RETURN (RL78_MAKE_EXITED (get_reg (RL78_Reg_A
)));
868 DO_RETURN (RL78_MAKE_HIT_BREAK ());
877 tprintf ("%d (0x%x) - %d (0x%x) = %d (0x%x)\n", b
, b
, a
, a
, v
, v
);
878 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
886 v
= b
- a
- get_carry ();
889 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
908 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
913 tprintf ("Unknown opcode?\n");
914 DO_RETURN (RL78_MAKE_HIT_BREAK ());
918 process_clock_tick ();
920 return RL78_MAKE_STEPPED ();