1 /* rl78.c --- opcode semantics for stand-alone RL78 simulator.
3 Copyright (C) 2008-2023 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/>.
22 /* This must come before any other includes. */
32 #include "opcode/rl78.h"
37 static int opcode_pc
= 0;
39 jmp_buf decode_jmp_buf
;
40 #define DO_RETURN(x) longjmp (decode_jmp_buf, x)
42 #define tprintf if (trace) printf
44 #define WILD_JUMP_CHECK(new_pc) \
46 if (new_pc == 0 || new_pc > 0xfffff) \
49 fprintf (stderr, "Wild jump to 0x%x from 0x%x!\n", new_pc, pc); \
50 DO_RETURN (RL78_MAKE_HIT_BREAK ()); \
59 rl78_get_byte (void *vdata
)
61 RL78_Data
*rl78_data
= (RL78_Data
*)vdata
;
62 int rv
= mem_get_pc (rl78_data
->dpc
);
68 op_addr (const RL78_Opcode_Operand
*o
, int for_data
)
71 if (o
->reg
!= RL78_Reg_None
)
72 v
+= get_reg (o
->reg
);
73 if (o
->reg2
!= RL78_Reg_None
)
74 v
+= get_reg (o
->reg2
);
76 v
|= (get_reg (RL78_Reg_ES
) & 0xf) << 16;
84 get_op (const RL78_Opcode_Decoded
*rd
, int i
, int for_data
)
87 const RL78_Opcode_Operand
*o
= rd
->op
+ i
;
91 case RL78_Operand_None
:
92 /* condition code does this. */
96 case RL78_Operand_Immediate
:
101 case RL78_Operand_Register
:
102 tprintf (" %s=", reg_names
[o
->reg
]);
103 v
= get_reg (o
->reg
);
106 case RL78_Operand_Bit
:
107 tprintf (" %s.%d=", reg_names
[o
->reg
], o
->bit_number
);
108 v
= get_reg (o
->reg
);
109 v
= (v
& (1 << o
->bit_number
)) ? 1 : 0;
112 case RL78_Operand_Indirect
:
113 v
= op_addr (o
, for_data
);
114 tprintf (" [0x%x]=", v
);
115 if (rd
->size
== RL78_Word
)
121 case RL78_Operand_BitIndirect
:
122 v
= op_addr (o
, for_data
);
123 tprintf (" [0x%x].%d=", v
, o
->bit_number
);
124 v
= (mem_get_qi (v
) & (1 << o
->bit_number
)) ? 1 : 0;
127 case RL78_Operand_PreDec
:
128 r
= get_reg (o
->reg
);
129 tprintf (" [--%s]", reg_names
[o
->reg
]);
130 if (rd
->size
== RL78_Word
)
133 v
= mem_get_hi (r
| 0xf0000);
138 v
= mem_get_qi (r
| 0xf0000);
143 case RL78_Operand_PostInc
:
144 tprintf (" [%s++]", reg_names
[o
->reg
]);
145 r
= get_reg (o
->reg
);
146 if (rd
->size
== RL78_Word
)
148 v
= mem_get_hi (r
| 0xf0000);
153 v
= mem_get_qi (r
| 0xf0000);
167 put_op (const RL78_Opcode_Decoded
*rd
, int i
, int for_data
, int v
)
170 const RL78_Opcode_Operand
*o
= rd
->op
+ i
;
176 case RL78_Operand_Register
:
177 tprintf ("%s", reg_names
[o
->reg
]);
181 case RL78_Operand_Bit
:
182 tprintf ("%s.%d", reg_names
[o
->reg
], o
->bit_number
);
183 r
= get_reg (o
->reg
);
185 r
|= (1 << o
->bit_number
);
187 r
&= ~(1 << o
->bit_number
);
191 case RL78_Operand_Indirect
:
192 r
= op_addr (o
, for_data
);
193 tprintf ("[0x%x]", r
);
194 if (rd
->size
== RL78_Word
)
200 case RL78_Operand_BitIndirect
:
201 a
= op_addr (o
, for_data
);
202 tprintf ("[0x%x].%d", a
, o
->bit_number
);
205 r
|= (1 << o
->bit_number
);
207 r
&= ~(1 << o
->bit_number
);
211 case RL78_Operand_PreDec
:
212 r
= get_reg (o
->reg
);
213 tprintf ("[--%s]", reg_names
[o
->reg
]);
214 if (rd
->size
== RL78_Word
)
218 mem_put_hi (r
| 0xf0000, v
);
224 mem_put_qi (r
| 0xf0000, v
);
228 case RL78_Operand_PostInc
:
229 tprintf ("[%s++]", reg_names
[o
->reg
]);
230 r
= get_reg (o
->reg
);
231 if (rd
->size
== RL78_Word
)
233 mem_put_hi (r
| 0xf0000, v
);
238 mem_put_qi (r
| 0xf0000, v
);
251 op_flags (int before
, int after
, int mask
, RL78_Size size
)
253 int vmask
, cmask
, amask
, avmask
;
256 if (size
== RL78_Word
)
271 psw
= get_reg (RL78_Reg_PSW
);
274 if (mask
& RL78_PSW_CY
)
276 if ((after
& cmask
) != (before
& cmask
))
279 if (mask
& RL78_PSW_AC
)
281 if ((after
& amask
) != (before
& amask
)
282 && (after
& avmask
) < (before
& avmask
))
285 if (mask
& RL78_PSW_Z
)
287 if (! (after
& vmask
))
291 set_reg (RL78_Reg_PSW
, psw
);
294 #define FLAGS(before,after) if (opcode.flags) op_flags (before, after, opcode.flags, opcode.size)
296 #define PD(x) put_op (&opcode, 0, 1, x)
297 #define PS(x) put_op (&opcode, 1, 1, x)
298 #define GD() get_op (&opcode, 0, 1)
299 #define GS() get_op (&opcode, 1, 1)
301 #define GPC() gpc (&opcode, 0)
303 gpc (RL78_Opcode_Decoded
*opcode
, int idx
)
305 int a
= get_op (opcode
, 0, 1);
306 if (opcode
->op
[idx
].type
== RL78_Operand_Register
)
307 a
=(a
& 0x0ffff) | ((get_reg (RL78_Reg_CS
) & 0x0f) << 16);
316 return (get_reg (RL78_Reg_PSW
) & RL78_PSW_CY
) ? 1 : 0;
322 int p
= get_reg (RL78_Reg_PSW
);
323 tprintf ("set_carry (%d)\n", c
? 1 : 0);
328 set_reg (RL78_Reg_PSW
, p
);
331 /* We simulate timer TM00 in interval mode, no clearing, with
332 interrupts. I.e. it's a cycle counter. */
334 unsigned int counts_per_insn
[0x100000];
336 int pending_clocks
= 0;
337 long long total_clocks
= 0;
342 process_clock_tick (void)
345 unsigned short ivect
;
355 counts_per_insn
[opcode_pc
] += pending_clocks
;
356 total_clocks
+= pending_clocks
;
358 while (pending_clocks
)
361 cnt
= mem_get_hi (TCR0
);
363 mem_put_hi (TCR0
, cnt
);
368 psw
= get_reg (RL78_Reg_PSW
);
369 ivect
= mem_get_hi (0x0002c);
370 mask
= mem_get_hi (MK1
);
372 if ((psw
& RL78_PSW_IE
)
376 unsigned short sp
= get_reg (RL78_Reg_SP
);
377 set_reg (RL78_Reg_SP
, sp
- 4);
379 mem_put_qi (sp
| 0xf0000, psw
);
381 mem_put_psi (sp
| 0xf0000, pc
);
383 set_reg (RL78_Reg_PSW
, psw
);
385 /* Spec says 9-14 clocks */
394 dump_counts_per_insn (const char * filename
)
398 f
= fopen (filename
, "w");
404 for (i
= 0; i
< 0x100000; i
++)
406 if (counts_per_insn
[i
])
407 fprintf (f
, "%05x %d\n", i
, counts_per_insn
[i
]);
415 pending_clocks
+= n
- 1;
422 RL78_Opcode_Decoded opcode
;
429 isa
= (rl78_g10_mode
? RL78_ISA_G10
430 : g14_multiply
? RL78_ISA_G14
431 : g13_multiply
? RL78_ISA_G13
435 opcode_size
= rl78_decode_opcode (pc
, &opcode
,
436 rl78_get_byte
, &rl78_data
, isa
);
441 trace_register_words
= opcode
.size
== RL78_Word
? 1 : 0;
443 /* Used by shfit/rotate instructions */
444 obits
= opcode
.size
== RL78_Word
? 16 : 8;
455 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
463 v
= a
+ b
+ get_carry ();
466 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
477 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
481 case RLO_branch_cond
:
482 case RLO_branch_cond_clear
:
483 tprintf ("BRANCH_COND: ");
484 if (!condition_true (opcode
.op
[1].condition
, GS ()))
486 tprintf (" false\n");
487 if (opcode
.op
[1].condition
== RL78_Condition_T
488 || opcode
.op
[1].condition
== RL78_Condition_F
)
494 if (opcode
.id
== RLO_branch_cond_clear
)
497 if (opcode
.op
[1].condition
== RL78_Condition_T
498 || opcode
.op
[1].condition
== RL78_Condition_F
)
499 CLOCKS (3); /* note: adds two clocks, total 5 clocks */
501 CLOCKS (2); /* note: adds one clock, total 4 clocks */
503 tprintf ("BRANCH: ");
507 tprintf (" => 0x%05x\n", pc
);
515 DO_RETURN (RL78_MAKE_HIT_BREAK ());
517 DO_RETURN (RL78_MAKE_EXITED (1));
522 a
= get_reg (RL78_Reg_SP
);
523 set_reg (RL78_Reg_SP
, a
- 4);
524 mem_put_psi ((a
- 4) | 0xf0000, pc
);
529 /* Enable this code to dump the arguments for each call. */
534 for (i
= 0; i
< 8; i
++)
535 printf (" %02x", mem_get_qi (0xf0000 | (a
+ i
)) & 0xff);
549 tprintf (" (%d)\n", v
);
553 a
= get_reg (RL78_Reg_AX
);
554 b
= get_reg (RL78_Reg_DE
);
555 tprintf (" %d / %d = ", a
, b
);
558 tprintf ("%d rem %d\n", 0xffff, a
);
559 set_reg (RL78_Reg_AX
, 0xffff);
560 set_reg (RL78_Reg_DE
, a
);
566 tprintf ("%d rem %d\n", v
, a
);
567 set_reg (RL78_Reg_AX
, v
);
568 set_reg (RL78_Reg_DE
, a
);
575 unsigned long bcax
, hlde
, quot
, rem
;
576 bcax
= get_reg (RL78_Reg_AX
) + 65536 * get_reg (RL78_Reg_BC
);
577 hlde
= get_reg (RL78_Reg_DE
) + 65536 * get_reg (RL78_Reg_HL
);
579 tprintf (" %lu / %lu = ", bcax
, hlde
);
582 tprintf ("%lu rem %lu\n", 0xffffLU
, bcax
);
583 set_reg (RL78_Reg_AX
, 0xffffLU
);
584 set_reg (RL78_Reg_BC
, 0xffffLU
);
585 set_reg (RL78_Reg_DE
, bcax
);
586 set_reg (RL78_Reg_HL
, bcax
>> 16);
592 tprintf ("%lu rem %lu\n", quot
, rem
);
593 set_reg (RL78_Reg_AX
, quot
);
594 set_reg (RL78_Reg_BC
, quot
>> 16);
595 set_reg (RL78_Reg_DE
, rem
);
596 set_reg (RL78_Reg_HL
, rem
>> 16);
604 DO_RETURN (RL78_MAKE_EXITED (get_reg (RL78_Reg_A
)));
616 a
= sign_ext (get_reg (RL78_Reg_AX
), 16);
617 b
= sign_ext (get_reg (RL78_Reg_BC
), 16);
618 v
= sign_ext (mem_get_si (MACR
), 32);
619 tprintf ("%08x %d + %d * %d = ", v
, v
, a
, b
);
620 v2
= sign_ext (v
+ a
* b
, 32);
621 tprintf ("%08x %d\n", v2
, v2
);
622 mem_put_si (MACR
, v2
);
623 a
= get_reg (RL78_Reg_PSW
);
633 set_reg (RL78_Reg_PSW
, a
);
639 a
= get_reg (RL78_Reg_AX
);
640 b
= get_reg (RL78_Reg_BC
);
641 u
= mem_get_si (MACR
);
642 tprintf ("%08x %u + %u * %u = ", u
, u
, a
, b
);
643 u2
= (u
+ (unsigned)a
* (unsigned)b
) & 0xffffffffUL
;
644 tprintf ("%08x %u\n", u2
, u2
);
645 mem_put_si (MACR
, u2
);
646 a
= get_reg (RL78_Reg_PSW
);
652 set_reg (RL78_Reg_PSW
, a
);
658 a
= get_reg (RL78_Reg_A
);
659 b
= get_reg (RL78_Reg_X
);
661 tprintf (" %d * %d = %d\n", a
, b
, v
);
662 set_reg (RL78_Reg_AX
, v
);
667 a
= sign_ext (get_reg (RL78_Reg_AX
), 16);
668 b
= sign_ext (get_reg (RL78_Reg_BC
), 16);
670 tprintf (" %d * %d = %d\n", a
, b
, v
);
671 set_reg (RL78_Reg_BC
, v
>> 16);
672 set_reg (RL78_Reg_AX
, v
);
678 a
= get_reg (RL78_Reg_AX
);
679 b
= get_reg (RL78_Reg_BC
);
681 tprintf (" %d * %d = %d\n", a
, b
, v
);
682 set_reg (RL78_Reg_BC
, v
>> 16);
683 set_reg (RL78_Reg_AX
, v
);
698 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
704 a
= get_reg (RL78_Reg_SP
);
705 v
= mem_get_psi (a
| 0xf0000);
708 set_reg (RL78_Reg_SP
, a
+ 4);
710 /* Enable this code to dump the return values for each return. */
715 for (i
= 0; i
< 8; i
++)
716 printf (" %02x", mem_get_qi (0xffef0 + i
) & 0xff);
726 a
= get_reg (RL78_Reg_SP
);
727 v
= mem_get_psi (a
| 0xf0000);
730 b
= mem_get_qi ((a
+ 3) | 0xf0000);
731 set_reg (RL78_Reg_PSW
, b
);
732 set_reg (RL78_Reg_SP
, a
+ 4);
737 tprintf ("ROL:"); /* d <<= s */
744 v
|= (b
>> (obits
- 1)) & 1;
745 set_carry ((b
>> (obits
- 1)) & 1);
752 tprintf ("ROLC:"); /* d <<= s */
760 set_carry ((b
>> (obits
- 1)) & 1);
767 tprintf ("ROR:"); /* d >>= s */
774 v
|= (b
& 1) << (obits
- 1);
782 tprintf ("RORC:"); /* d >>= s */
789 v
|= (get_carry () << (obits
- 1));
797 tprintf ("SAR:"); /* d >>= s */
804 v
|= b
& (1 << (obits
- 1));
814 b
= get_reg (RL78_Reg_PSW
);
815 b
&= ~(RL78_PSW_RBS1
| RL78_PSW_RBS0
);
820 set_reg (RL78_Reg_PSW
, b
);
825 tprintf ("SHL%d:", obits
); /* d <<= s */
832 tprintf ("b = 0x%x & 0x%x\n", b
, 1<<(obits
- 1));
833 set_carry (b
& (1<<(obits
- 1)));
840 tprintf ("SHR:"); /* d >>= s */
855 if (!condition_true (opcode
.op
[1].condition
, GS ()))
857 tprintf (" false\n");
862 opcode_size
= rl78_decode_opcode (pc
, &opcode
,
863 rl78_get_byte
, &rl78_data
, isa
);
865 tprintf (" skipped: %s\n", opcode
.syntax
);
870 DO_RETURN (RL78_MAKE_EXITED (get_reg (RL78_Reg_A
)));
871 DO_RETURN (RL78_MAKE_HIT_BREAK ());
880 tprintf ("%d (0x%x) - %d (0x%x) = %d (0x%x)\n", b
, b
, a
, a
, v
, v
);
881 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
889 v
= b
- a
- get_carry ();
892 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
911 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
916 tprintf ("Unknown opcode?\n");
917 DO_RETURN (RL78_MAKE_HIT_BREAK ());
921 process_clock_tick ();
923 return RL78_MAKE_STEPPED ();