1 /* rl78.c --- opcode semantics for stand-alone RL78 simulator.
3 Copyright (C) 2008-2012 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 opcode_size
= rl78_decode_opcode (pc
, &opcode
,
427 rl78_get_byte
, &rl78_data
);
432 trace_register_words
= opcode
.size
== RL78_Word
? 1 : 0;
434 /* Used by shfit/rotate instructions */
435 obits
= opcode
.size
== RL78_Word
? 16 : 8;
446 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
454 v
= a
+ b
+ get_carry ();
457 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
468 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
472 case RLO_branch_cond
:
473 case RLO_branch_cond_clear
:
474 tprintf ("BRANCH_COND: ");
475 if (!condition_true (opcode
.op
[1].condition
, GS ()))
477 tprintf (" false\n");
478 if (opcode
.op
[1].condition
== RL78_Condition_T
479 || opcode
.op
[1].condition
== RL78_Condition_F
)
485 if (opcode
.id
== RLO_branch_cond_clear
)
488 if (opcode
.op
[1].condition
== RL78_Condition_T
489 || opcode
.op
[1].condition
== RL78_Condition_F
)
490 CLOCKS (3); /* note: adds two clocks, total 5 clocks */
492 CLOCKS (2); /* note: adds one clock, total 4 clocks */
494 tprintf ("BRANCH: ");
498 tprintf (" => 0x%05x\n", pc
);
506 DO_RETURN (RL78_MAKE_HIT_BREAK ());
508 DO_RETURN (RL78_MAKE_EXITED (1));
513 a
= get_reg (RL78_Reg_SP
);
514 set_reg (RL78_Reg_SP
, a
- 4);
515 mem_put_psi ((a
- 4) | 0xf0000, pc
);
520 /* Enable this code to dump the arguments for each call. */
525 for (i
= 0; i
< 8; i
++)
526 printf (" %02x", mem_get_qi (0xf0000 | (a
+ i
)) & 0xff);
540 tprintf (" (%d)\n", v
);
544 a
= get_reg (RL78_Reg_AX
);
545 b
= get_reg (RL78_Reg_DE
);
546 tprintf (" %d / %d = ", a
, b
);
549 tprintf ("%d rem %d\n", 0xffff, a
);
550 set_reg (RL78_Reg_AX
, 0xffff);
551 set_reg (RL78_Reg_DE
, a
);
557 tprintf ("%d rem %d\n", v
, a
);
558 set_reg (RL78_Reg_AX
, v
);
559 set_reg (RL78_Reg_DE
, a
);
566 unsigned long bcax
, hlde
, quot
, rem
;
567 bcax
= get_reg (RL78_Reg_AX
) + 65536 * get_reg (RL78_Reg_BC
);
568 hlde
= get_reg (RL78_Reg_DE
) + 65536 * get_reg (RL78_Reg_HL
);
570 tprintf (" %lu / %lu = ", bcax
, hlde
);
573 tprintf ("%lu rem %lu\n", 0xffffLU
, bcax
);
574 set_reg (RL78_Reg_AX
, 0xffffLU
);
575 set_reg (RL78_Reg_BC
, 0xffffLU
);
576 set_reg (RL78_Reg_DE
, bcax
);
577 set_reg (RL78_Reg_HL
, bcax
>> 16);
583 tprintf ("%lu rem %lu\n", quot
, rem
);
584 set_reg (RL78_Reg_AX
, quot
);
585 set_reg (RL78_Reg_BC
, quot
>> 16);
586 set_reg (RL78_Reg_DE
, rem
);
587 set_reg (RL78_Reg_HL
, rem
>> 16);
595 DO_RETURN (RL78_MAKE_EXITED (get_reg (RL78_Reg_A
)));
607 a
= sign_ext (get_reg (RL78_Reg_AX
), 16);
608 b
= sign_ext (get_reg (RL78_Reg_BC
), 16);
609 v
= sign_ext (mem_get_si (MACR
), 32);
610 tprintf ("%08x %d + %d * %d = ", v
, v
, a
, b
);
611 v2
= sign_ext (v
+ a
* b
, 32);
612 tprintf ("%08x %d\n", v2
, v2
);
613 mem_put_si (MACR
, v2
);
614 a
= get_reg (RL78_Reg_PSW
);
624 set_reg (RL78_Reg_PSW
, a
);
630 a
= get_reg (RL78_Reg_AX
);
631 b
= get_reg (RL78_Reg_BC
);
632 u
= mem_get_si (MACR
);
633 tprintf ("%08x %u + %u * %u = ", u
, u
, a
, b
);
634 u2
= (u
+ (unsigned)a
* (unsigned)b
) & 0xffffffffUL
;
635 tprintf ("%08x %u\n", u2
, u2
);
636 mem_put_si (MACR
, u2
);
637 a
= get_reg (RL78_Reg_PSW
);
643 set_reg (RL78_Reg_PSW
, a
);
649 a
= get_reg (RL78_Reg_A
);
650 b
= get_reg (RL78_Reg_X
);
652 tprintf (" %d * %d = %d\n", a
, b
, v
);
653 set_reg (RL78_Reg_AX
, v
);
658 a
= sign_ext (get_reg (RL78_Reg_AX
), 16);
659 b
= sign_ext (get_reg (RL78_Reg_BC
), 16);
661 tprintf (" %d * %d = %d\n", a
, b
, v
);
662 set_reg (RL78_Reg_BC
, v
>> 16);
663 set_reg (RL78_Reg_AX
, v
);
669 a
= get_reg (RL78_Reg_AX
);
670 b
= get_reg (RL78_Reg_BC
);
672 tprintf (" %d * %d = %d\n", a
, b
, v
);
673 set_reg (RL78_Reg_BC
, v
>> 16);
674 set_reg (RL78_Reg_AX
, v
);
689 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
695 a
= get_reg (RL78_Reg_SP
);
696 v
= mem_get_psi (a
| 0xf0000);
699 set_reg (RL78_Reg_SP
, a
+ 4);
701 /* Enable this code to dump the return values for each return. */
706 for (i
= 0; i
< 8; i
++)
707 printf (" %02x", mem_get_qi (0xffef0 + i
) & 0xff);
717 a
= get_reg (RL78_Reg_SP
);
718 v
= mem_get_psi (a
| 0xf0000);
721 b
= mem_get_qi ((a
+ 3) | 0xf0000);
722 set_reg (RL78_Reg_PSW
, b
);
723 set_reg (RL78_Reg_SP
, a
+ 4);
728 tprintf ("ROL:"); /* d <<= s */
735 v
|= (b
>> (obits
- 1)) & 1;
736 set_carry ((b
>> (obits
- 1)) & 1);
743 tprintf ("ROLC:"); /* d <<= s */
751 set_carry ((b
>> (obits
- 1)) & 1);
758 tprintf ("ROR:"); /* d >>= s */
765 v
|= (b
& 1) << (obits
- 1);
773 tprintf ("RORC:"); /* d >>= s */
780 v
|= (get_carry () << (obits
- 1));
788 tprintf ("SAR:"); /* d >>= s */
795 v
|= b
& (1 << (obits
- 1));
805 b
= get_reg (RL78_Reg_PSW
);
806 b
&= ~(RL78_PSW_RBS1
| RL78_PSW_RBS0
);
811 set_reg (RL78_Reg_PSW
, b
);
816 tprintf ("SHL%d:", obits
); /* d <<= s */
823 tprintf ("b = 0x%x & 0x%x\n", b
, 1<<(obits
- 1));
824 set_carry (b
& (1<<(obits
- 1)));
831 tprintf ("SHR:"); /* d >>= s */
846 if (!condition_true (opcode
.op
[1].condition
, GS ()))
848 tprintf (" false\n");
853 opcode_size
= rl78_decode_opcode (pc
, &opcode
,
854 rl78_get_byte
, &rl78_data
);
856 tprintf (" skipped: %s\n", opcode
.syntax
);
861 DO_RETURN (RL78_MAKE_EXITED (get_reg (RL78_Reg_A
)));
862 DO_RETURN (RL78_MAKE_HIT_BREAK ());
871 tprintf ("%d (0x%x) - %d (0x%x) = %d (0x%x)\n", b
, b
, a
, a
, v
, v
);
872 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
880 v
= b
- a
- get_carry ();
883 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
902 if (opcode
.op
[0].type
== RL78_Operand_Indirect
)
907 tprintf ("Unknown opcode?\n");
908 DO_RETURN (RL78_MAKE_HIT_BREAK ());
912 process_clock_tick ();
914 return RL78_MAKE_STEPPED ();