1 /* rl78.c --- opcode semantics for stand-alone RL78 simulator.
3 Copyright (C) 2008-2021 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
;
254 if (size
== RL78_Word
)
269 psw
= get_reg (RL78_Reg_PSW
);
272 if (mask
& RL78_PSW_CY
)
274 if ((after
& cmask
) != (before
& cmask
))
277 if (mask
& RL78_PSW_AC
)
279 if ((after
& amask
) != (before
& amask
)
280 && (after
& avmask
) < (before
& avmask
))
283 if (mask
& RL78_PSW_Z
)
285 if (! (after
& vmask
))
289 set_reg (RL78_Reg_PSW
, psw
);
292 #define FLAGS(before,after) if (opcode.flags) op_flags (before, after, opcode.flags, opcode.size)
294 #define PD(x) put_op (&opcode, 0, 1, x)
295 #define PS(x) put_op (&opcode, 1, 1, x)
296 #define GD() get_op (&opcode, 0, 1)
297 #define GS() get_op (&opcode, 1, 1)
299 #define GPC() gpc (&opcode, 0)
301 gpc (RL78_Opcode_Decoded
*opcode
, int idx
)
303 int a
= get_op (opcode
, 0, 1);
304 if (opcode
->op
[idx
].type
== RL78_Operand_Register
)
305 a
=(a
& 0x0ffff) | ((get_reg (RL78_Reg_CS
) & 0x0f) << 16);
314 return (get_reg (RL78_Reg_PSW
) & RL78_PSW_CY
) ? 1 : 0;
320 int p
= get_reg (RL78_Reg_PSW
);
321 tprintf ("set_carry (%d)\n", c
? 1 : 0);
326 set_reg (RL78_Reg_PSW
, p
);
329 /* We simulate timer TM00 in interval mode, no clearing, with
330 interrupts. I.e. it's a cycle counter. */
332 unsigned int counts_per_insn
[0x100000];
334 int pending_clocks
= 0;
335 long long total_clocks
= 0;
340 process_clock_tick (void)
343 unsigned short ivect
;
353 counts_per_insn
[opcode_pc
] += pending_clocks
;
354 total_clocks
+= pending_clocks
;
356 while (pending_clocks
)
359 cnt
= mem_get_hi (TCR0
);
361 mem_put_hi (TCR0
, cnt
);
366 psw
= get_reg (RL78_Reg_PSW
);
367 ivect
= mem_get_hi (0x0002c);
368 mask
= mem_get_hi (MK1
);
370 if ((psw
& RL78_PSW_IE
)
374 unsigned short sp
= get_reg (RL78_Reg_SP
);
375 set_reg (RL78_Reg_SP
, sp
- 4);
377 mem_put_qi (sp
| 0xf0000, psw
);
379 mem_put_psi (sp
| 0xf0000, pc
);
381 set_reg (RL78_Reg_PSW
, psw
);
383 /* Spec says 9-14 clocks */
392 dump_counts_per_insn (const char * filename
)
396 f
= fopen (filename
, "w");
402 for (i
= 0; i
< 0x100000; i
++)
404 if (counts_per_insn
[i
])
405 fprintf (f
, "%05x %d\n", i
, counts_per_insn
[i
]);
413 pending_clocks
+= n
- 1;
420 RL78_Opcode_Decoded opcode
;
427 isa
= (rl78_g10_mode
? RL78_ISA_G10
428 : g14_multiply
? RL78_ISA_G14
429 : g13_multiply
? RL78_ISA_G13
433 opcode_size
= rl78_decode_opcode (pc
, &opcode
,
434 rl78_get_byte
, &rl78_data
, isa
);
439 trace_register_words
= opcode
.size
== RL78_Word
? 1 : 0;
441 /* Used by shfit/rotate instructions */
442 obits
= opcode
.size
== RL78_Word
? 16 : 8;
453 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
461 v
= a
+ b
+ get_carry ();
464 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
475 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
479 case RLO_branch_cond
:
480 case RLO_branch_cond_clear
:
481 tprintf ("BRANCH_COND: ");
482 if (!condition_true (opcode
.op
[1].condition
, GS ()))
484 tprintf (" false\n");
485 if (opcode
.op
[1].condition
== RL78_Condition_T
486 || opcode
.op
[1].condition
== RL78_Condition_F
)
492 if (opcode
.id
== RLO_branch_cond_clear
)
495 if (opcode
.op
[1].condition
== RL78_Condition_T
496 || opcode
.op
[1].condition
== RL78_Condition_F
)
497 CLOCKS (3); /* note: adds two clocks, total 5 clocks */
499 CLOCKS (2); /* note: adds one clock, total 4 clocks */
501 tprintf ("BRANCH: ");
505 tprintf (" => 0x%05x\n", pc
);
513 DO_RETURN (RL78_MAKE_HIT_BREAK ());
515 DO_RETURN (RL78_MAKE_EXITED (1));
520 a
= get_reg (RL78_Reg_SP
);
521 set_reg (RL78_Reg_SP
, a
- 4);
522 mem_put_psi ((a
- 4) | 0xf0000, pc
);
527 /* Enable this code to dump the arguments for each call. */
532 for (i
= 0; i
< 8; i
++)
533 printf (" %02x", mem_get_qi (0xf0000 | (a
+ i
)) & 0xff);
547 tprintf (" (%d)\n", v
);
551 a
= get_reg (RL78_Reg_AX
);
552 b
= get_reg (RL78_Reg_DE
);
553 tprintf (" %d / %d = ", a
, b
);
556 tprintf ("%d rem %d\n", 0xffff, a
);
557 set_reg (RL78_Reg_AX
, 0xffff);
558 set_reg (RL78_Reg_DE
, a
);
564 tprintf ("%d rem %d\n", v
, a
);
565 set_reg (RL78_Reg_AX
, v
);
566 set_reg (RL78_Reg_DE
, a
);
573 unsigned long bcax
, hlde
, quot
, rem
;
574 bcax
= get_reg (RL78_Reg_AX
) + 65536 * get_reg (RL78_Reg_BC
);
575 hlde
= get_reg (RL78_Reg_DE
) + 65536 * get_reg (RL78_Reg_HL
);
577 tprintf (" %lu / %lu = ", bcax
, hlde
);
580 tprintf ("%lu rem %lu\n", 0xffffLU
, bcax
);
581 set_reg (RL78_Reg_AX
, 0xffffLU
);
582 set_reg (RL78_Reg_BC
, 0xffffLU
);
583 set_reg (RL78_Reg_DE
, bcax
);
584 set_reg (RL78_Reg_HL
, bcax
>> 16);
590 tprintf ("%lu rem %lu\n", quot
, rem
);
591 set_reg (RL78_Reg_AX
, quot
);
592 set_reg (RL78_Reg_BC
, quot
>> 16);
593 set_reg (RL78_Reg_DE
, rem
);
594 set_reg (RL78_Reg_HL
, rem
>> 16);
602 DO_RETURN (RL78_MAKE_EXITED (get_reg (RL78_Reg_A
)));
614 a
= sign_ext (get_reg (RL78_Reg_AX
), 16);
615 b
= sign_ext (get_reg (RL78_Reg_BC
), 16);
616 v
= sign_ext (mem_get_si (MACR
), 32);
617 tprintf ("%08x %d + %d * %d = ", v
, v
, a
, b
);
618 v2
= sign_ext (v
+ a
* b
, 32);
619 tprintf ("%08x %d\n", v2
, v2
);
620 mem_put_si (MACR
, v2
);
621 a
= get_reg (RL78_Reg_PSW
);
631 set_reg (RL78_Reg_PSW
, a
);
637 a
= get_reg (RL78_Reg_AX
);
638 b
= get_reg (RL78_Reg_BC
);
639 u
= mem_get_si (MACR
);
640 tprintf ("%08x %u + %u * %u = ", u
, u
, a
, b
);
641 u2
= (u
+ (unsigned)a
* (unsigned)b
) & 0xffffffffUL
;
642 tprintf ("%08x %u\n", u2
, u2
);
643 mem_put_si (MACR
, u2
);
644 a
= get_reg (RL78_Reg_PSW
);
650 set_reg (RL78_Reg_PSW
, a
);
656 a
= get_reg (RL78_Reg_A
);
657 b
= get_reg (RL78_Reg_X
);
659 tprintf (" %d * %d = %d\n", a
, b
, v
);
660 set_reg (RL78_Reg_AX
, v
);
665 a
= sign_ext (get_reg (RL78_Reg_AX
), 16);
666 b
= sign_ext (get_reg (RL78_Reg_BC
), 16);
668 tprintf (" %d * %d = %d\n", a
, b
, v
);
669 set_reg (RL78_Reg_BC
, v
>> 16);
670 set_reg (RL78_Reg_AX
, v
);
676 a
= get_reg (RL78_Reg_AX
);
677 b
= get_reg (RL78_Reg_BC
);
679 tprintf (" %d * %d = %d\n", a
, b
, v
);
680 set_reg (RL78_Reg_BC
, v
>> 16);
681 set_reg (RL78_Reg_AX
, v
);
696 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
702 a
= get_reg (RL78_Reg_SP
);
703 v
= mem_get_psi (a
| 0xf0000);
706 set_reg (RL78_Reg_SP
, a
+ 4);
708 /* Enable this code to dump the return values for each return. */
713 for (i
= 0; i
< 8; i
++)
714 printf (" %02x", mem_get_qi (0xffef0 + i
) & 0xff);
724 a
= get_reg (RL78_Reg_SP
);
725 v
= mem_get_psi (a
| 0xf0000);
728 b
= mem_get_qi ((a
+ 3) | 0xf0000);
729 set_reg (RL78_Reg_PSW
, b
);
730 set_reg (RL78_Reg_SP
, a
+ 4);
735 tprintf ("ROL:"); /* d <<= s */
742 v
|= (b
>> (obits
- 1)) & 1;
743 set_carry ((b
>> (obits
- 1)) & 1);
750 tprintf ("ROLC:"); /* d <<= s */
758 set_carry ((b
>> (obits
- 1)) & 1);
765 tprintf ("ROR:"); /* d >>= s */
772 v
|= (b
& 1) << (obits
- 1);
780 tprintf ("RORC:"); /* d >>= s */
787 v
|= (get_carry () << (obits
- 1));
795 tprintf ("SAR:"); /* d >>= s */
802 v
|= b
& (1 << (obits
- 1));
812 b
= get_reg (RL78_Reg_PSW
);
813 b
&= ~(RL78_PSW_RBS1
| RL78_PSW_RBS0
);
818 set_reg (RL78_Reg_PSW
, b
);
823 tprintf ("SHL%d:", obits
); /* d <<= s */
830 tprintf ("b = 0x%x & 0x%x\n", b
, 1<<(obits
- 1));
831 set_carry (b
& (1<<(obits
- 1)));
838 tprintf ("SHR:"); /* d >>= s */
853 if (!condition_true (opcode
.op
[1].condition
, GS ()))
855 tprintf (" false\n");
860 opcode_size
= rl78_decode_opcode (pc
, &opcode
,
861 rl78_get_byte
, &rl78_data
, isa
);
863 tprintf (" skipped: %s\n", opcode
.syntax
);
868 DO_RETURN (RL78_MAKE_EXITED (get_reg (RL78_Reg_A
)));
869 DO_RETURN (RL78_MAKE_HIT_BREAK ());
878 tprintf ("%d (0x%x) - %d (0x%x) = %d (0x%x)\n", b
, b
, a
, a
, v
, v
);
879 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
887 v
= b
- a
- get_carry ();
890 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
909 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
914 tprintf ("Unknown opcode?\n");
915 DO_RETURN (RL78_MAKE_HIT_BREAK ());
919 process_clock_tick ();
921 return RL78_MAKE_STEPPED ();