123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924 |
- /* rl78.c --- opcode semantics for stand-alone RL78 simulator.
- Copyright (C) 2008-2022 Free Software Foundation, Inc.
- Contributed by Red Hat, Inc.
- This file is part of the GNU simulators.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /* This must come before any other includes. */
- #include "defs.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <time.h>
- #include "opcode/rl78.h"
- #include "cpu.h"
- #include "mem.h"
- extern int skip_init;
- static int opcode_pc = 0;
- jmp_buf decode_jmp_buf;
- #define DO_RETURN(x) longjmp (decode_jmp_buf, x)
- #define tprintf if (trace) printf
- #define WILD_JUMP_CHECK(new_pc) \
- do { \
- if (new_pc == 0 || new_pc > 0xfffff) \
- { \
- pc = opcode_pc; \
- fprintf (stderr, "Wild jump to 0x%x from 0x%x!\n", new_pc, pc); \
- DO_RETURN (RL78_MAKE_HIT_BREAK ()); \
- } \
- } while (0)
- typedef struct {
- unsigned long dpc;
- } RL78_Data;
- static int
- rl78_get_byte (void *vdata)
- {
- RL78_Data *rl78_data = (RL78_Data *)vdata;
- int rv = mem_get_pc (rl78_data->dpc);
- rl78_data->dpc ++;
- return rv;
- }
- static int
- op_addr (const RL78_Opcode_Operand *o, int for_data)
- {
- int v = o->addend;
- if (o->reg != RL78_Reg_None)
- v += get_reg (o->reg);
- if (o->reg2 != RL78_Reg_None)
- v += get_reg (o->reg2);
- if (o->use_es)
- v |= (get_reg (RL78_Reg_ES) & 0xf) << 16;
- else if (for_data)
- v |= 0xf0000;
- v &= 0xfffff;
- return v;
- }
- static int
- get_op (const RL78_Opcode_Decoded *rd, int i, int for_data)
- {
- int v, r;
- const RL78_Opcode_Operand *o = rd->op + i;
- switch (o->type)
- {
- case RL78_Operand_None:
- /* condition code does this. */
- v = 0;
- break;
- case RL78_Operand_Immediate:
- tprintf (" #");
- v = o->addend;
- break;
- case RL78_Operand_Register:
- tprintf (" %s=", reg_names[o->reg]);
- v = get_reg (o->reg);
- break;
-
- case RL78_Operand_Bit:
- tprintf (" %s.%d=", reg_names[o->reg], o->bit_number);
- v = get_reg (o->reg);
- v = (v & (1 << o->bit_number)) ? 1 : 0;
- break;
- case RL78_Operand_Indirect:
- v = op_addr (o, for_data);
- tprintf (" [0x%x]=", v);
- if (rd->size == RL78_Word)
- v = mem_get_hi (v);
- else
- v = mem_get_qi (v);
- break;
- case RL78_Operand_BitIndirect:
- v = op_addr (o, for_data);
- tprintf (" [0x%x].%d=", v, o->bit_number);
- v = (mem_get_qi (v) & (1 << o->bit_number)) ? 1 : 0;
- break;
- case RL78_Operand_PreDec:
- r = get_reg (o->reg);
- tprintf (" [--%s]", reg_names[o->reg]);
- if (rd->size == RL78_Word)
- {
- r -= 2;
- v = mem_get_hi (r | 0xf0000);
- }
- else
- {
- r -= 1;
- v = mem_get_qi (r | 0xf0000);
- }
- set_reg (o->reg, r);
- break;
-
- case RL78_Operand_PostInc:
- tprintf (" [%s++]", reg_names[o->reg]);
- r = get_reg (o->reg);
- if (rd->size == RL78_Word)
- {
- v = mem_get_hi (r | 0xf0000);
- r += 2;
- }
- else
- {
- v = mem_get_qi (r | 0xf0000);
- r += 1;
- }
- set_reg (o->reg, r);
- break;
-
- default:
- abort ();
- }
- tprintf ("%d", v);
- return v;
- }
- static void
- put_op (const RL78_Opcode_Decoded *rd, int i, int for_data, int v)
- {
- int r, a;
- const RL78_Opcode_Operand *o = rd->op + i;
- tprintf (" -> ");
- switch (o->type)
- {
- case RL78_Operand_Register:
- tprintf ("%s", reg_names[o->reg]);
- set_reg (o->reg, v);
- break;
-
- case RL78_Operand_Bit:
- tprintf ("%s.%d", reg_names[o->reg], o->bit_number);
- r = get_reg (o->reg);
- if (v)
- r |= (1 << o->bit_number);
- else
- r &= ~(1 << o->bit_number);
- set_reg (o->reg, r);
- break;
- case RL78_Operand_Indirect:
- r = op_addr (o, for_data);
- tprintf ("[0x%x]", r);
- if (rd->size == RL78_Word)
- mem_put_hi (r, v);
- else
- mem_put_qi (r, v);
- break;
- case RL78_Operand_BitIndirect:
- a = op_addr (o, for_data);
- tprintf ("[0x%x].%d", a, o->bit_number);
- r = mem_get_qi (a);
- if (v)
- r |= (1 << o->bit_number);
- else
- r &= ~(1 << o->bit_number);
- mem_put_qi (a, r);
- break;
- case RL78_Operand_PreDec:
- r = get_reg (o->reg);
- tprintf ("[--%s]", reg_names[o->reg]);
- if (rd->size == RL78_Word)
- {
- r -= 2;
- set_reg (o->reg, r);
- mem_put_hi (r | 0xf0000, v);
- }
- else
- {
- r -= 1;
- set_reg (o->reg, r);
- mem_put_qi (r | 0xf0000, v);
- }
- break;
-
- case RL78_Operand_PostInc:
- tprintf ("[%s++]", reg_names[o->reg]);
- r = get_reg (o->reg);
- if (rd->size == RL78_Word)
- {
- mem_put_hi (r | 0xf0000, v);
- r += 2;
- }
- else
- {
- mem_put_qi (r | 0xf0000, v);
- r += 1;
- }
- set_reg (o->reg, r);
- break;
- default:
- abort ();
- }
- tprintf ("\n");
- }
- static void
- op_flags (int before, int after, int mask, RL78_Size size)
- {
- int vmask, cmask, amask, avmask;
- int psw;
- if (size == RL78_Word)
- {
- cmask = 0x10000;
- vmask = 0xffff;
- amask = 0x100;
- avmask = 0x0ff;
- }
- else
- {
- cmask = 0x100;
- vmask = 0xff;
- amask = 0x10;
- avmask = 0x0f;
- }
- psw = get_reg (RL78_Reg_PSW);
- psw &= ~mask;
- if (mask & RL78_PSW_CY)
- {
- if ((after & cmask) != (before & cmask))
- psw |= RL78_PSW_CY;
- }
- if (mask & RL78_PSW_AC)
- {
- if ((after & amask) != (before & amask)
- && (after & avmask) < (before & avmask))
- psw |= RL78_PSW_AC;
- }
- if (mask & RL78_PSW_Z)
- {
- if (! (after & vmask))
- psw |= RL78_PSW_Z;
- }
- set_reg (RL78_Reg_PSW, psw);
- }
- #define FLAGS(before,after) if (opcode.flags) op_flags (before, after, opcode.flags, opcode.size)
- #define PD(x) put_op (&opcode, 0, 1, x)
- #define PS(x) put_op (&opcode, 1, 1, x)
- #define GD() get_op (&opcode, 0, 1)
- #define GS() get_op (&opcode, 1, 1)
- #define GPC() gpc (&opcode, 0)
- static int
- gpc (RL78_Opcode_Decoded *opcode, int idx)
- {
- int a = get_op (opcode, 0, 1);
- if (opcode->op[idx].type == RL78_Operand_Register)
- a =(a & 0x0ffff) | ((get_reg (RL78_Reg_CS) & 0x0f) << 16);
- else
- a &= 0xfffff;
- return a;
- }
- static int
- get_carry (void)
- {
- return (get_reg (RL78_Reg_PSW) & RL78_PSW_CY) ? 1 : 0;
- }
- static void
- set_carry (int c)
- {
- int p = get_reg (RL78_Reg_PSW);
- tprintf ("set_carry (%d)\n", c ? 1 : 0);
- if (c)
- p |= RL78_PSW_CY;
- else
- p &= ~RL78_PSW_CY;
- set_reg (RL78_Reg_PSW, p);
- }
- /* We simulate timer TM00 in interval mode, no clearing, with
- interrupts. I.e. it's a cycle counter. */
- unsigned int counts_per_insn[0x100000];
- int pending_clocks = 0;
- long long total_clocks = 0;
- #define TCR0 0xf0180
- #define MK1 0xfffe6
- static void
- process_clock_tick (void)
- {
- unsigned short cnt;
- unsigned short ivect;
- unsigned short mask;
- unsigned char psw;
- int save_trace;
- save_trace = trace;
- trace = 0;
- pending_clocks ++;
- counts_per_insn[opcode_pc] += pending_clocks;
- total_clocks += pending_clocks;
- while (pending_clocks)
- {
- pending_clocks --;
- cnt = mem_get_hi (TCR0);
- cnt --;
- mem_put_hi (TCR0, cnt);
- if (cnt != 0xffff)
- continue;
- /* overflow. */
- psw = get_reg (RL78_Reg_PSW);
- ivect = mem_get_hi (0x0002c);
- mask = mem_get_hi (MK1);
- if ((psw & RL78_PSW_IE)
- && (ivect != 0)
- && !(mask & 0x0010))
- {
- unsigned short sp = get_reg (RL78_Reg_SP);
- set_reg (RL78_Reg_SP, sp - 4);
- sp --;
- mem_put_qi (sp | 0xf0000, psw);
- sp -= 3;
- mem_put_psi (sp | 0xf0000, pc);
- psw &= ~RL78_PSW_IE;
- set_reg (RL78_Reg_PSW, psw);
- pc = ivect;
- /* Spec says 9-14 clocks */
- pending_clocks += 9;
- }
- }
- trace = save_trace;
- }
- void
- dump_counts_per_insn (const char * filename)
- {
- int i;
- FILE *f;
- f = fopen (filename, "w");
- if (!f)
- {
- perror (filename);
- return;
- }
- for (i = 0; i < 0x100000; i ++)
- {
- if (counts_per_insn[i])
- fprintf (f, "%05x %d\n", i, counts_per_insn[i]);
- }
- fclose (f);
- }
- static void
- CLOCKS (int n)
- {
- pending_clocks += n - 1;
- }
- int
- decode_opcode (void)
- {
- RL78_Data rl78_data;
- RL78_Opcode_Decoded opcode;
- int opcode_size;
- int a, b, v, v2;
- unsigned int u, u2;
- int obits;
- RL78_Dis_Isa isa;
- isa = (rl78_g10_mode ? RL78_ISA_G10
- : g14_multiply ? RL78_ISA_G14
- : g13_multiply ? RL78_ISA_G13
- : RL78_ISA_DEFAULT);
- rl78_data.dpc = pc;
- opcode_size = rl78_decode_opcode (pc, &opcode,
- rl78_get_byte, &rl78_data, isa);
- opcode_pc = pc;
- pc += opcode_size;
- trace_register_words = opcode.size == RL78_Word ? 1 : 0;
- /* Used by shfit/rotate instructions */
- obits = opcode.size == RL78_Word ? 16 : 8;
- switch (opcode.id)
- {
- case RLO_add:
- tprintf ("ADD: ");
- a = GS ();
- b = GD ();
- v = a + b;
- FLAGS (b, v);
- PD (v);
- if (opcode.op[0].type == RL78_Operand_Indirect)
- CLOCKS (2);
- break;
- case RLO_addc:
- tprintf ("ADDC: ");
- a = GS ();
- b = GD ();
- v = a + b + get_carry ();
- FLAGS (b, v);
- PD (v);
- if (opcode.op[0].type == RL78_Operand_Indirect)
- CLOCKS (2);
- break;
- case RLO_and:
- tprintf ("AND: ");
- a = GS ();
- b = GD ();
- v = a & b;
- FLAGS (b, v);
- PD (v);
- if (opcode.op[0].type == RL78_Operand_Indirect)
- CLOCKS (2);
- break;
- case RLO_branch_cond:
- case RLO_branch_cond_clear:
- tprintf ("BRANCH_COND: ");
- if (!condition_true (opcode.op[1].condition, GS ()))
- {
- tprintf (" false\n");
- if (opcode.op[1].condition == RL78_Condition_T
- || opcode.op[1].condition == RL78_Condition_F)
- CLOCKS (3);
- else
- CLOCKS (2);
- break;
- }
- if (opcode.id == RLO_branch_cond_clear)
- PS (0);
- tprintf (" ");
- if (opcode.op[1].condition == RL78_Condition_T
- || opcode.op[1].condition == RL78_Condition_F)
- CLOCKS (3); /* note: adds two clocks, total 5 clocks */
- else
- CLOCKS (2); /* note: adds one clock, total 4 clocks */
- case RLO_branch:
- tprintf ("BRANCH: ");
- v = GPC ();
- WILD_JUMP_CHECK (v);
- pc = v;
- tprintf (" => 0x%05x\n", pc);
- CLOCKS (3);
- break;
- case RLO_break:
- tprintf ("BRK: ");
- CLOCKS (5);
- if (rl78_in_gdb)
- DO_RETURN (RL78_MAKE_HIT_BREAK ());
- else
- DO_RETURN (RL78_MAKE_EXITED (1));
- break;
- case RLO_call:
- tprintf ("CALL: ");
- a = get_reg (RL78_Reg_SP);
- set_reg (RL78_Reg_SP, a - 4);
- mem_put_psi ((a - 4) | 0xf0000, pc);
- v = GPC ();
- WILD_JUMP_CHECK (v);
- pc = v;
- #if 0
- /* Enable this code to dump the arguments for each call. */
- if (trace)
- {
- int i;
- skip_init ++;
- for (i = 0; i < 8; i ++)
- printf (" %02x", mem_get_qi (0xf0000 | (a + i)) & 0xff);
- skip_init --;
- }
- #endif
- tprintf ("\n");
- CLOCKS (3);
- break;
- case RLO_cmp:
- tprintf ("CMP: ");
- a = GD ();
- b = GS ();
- v = a - b;
- FLAGS (b, v);
- tprintf (" (%d)\n", v);
- break;
- case RLO_divhu:
- a = get_reg (RL78_Reg_AX);
- b = get_reg (RL78_Reg_DE);
- tprintf (" %d / %d = ", a, b);
- if (b == 0)
- {
- tprintf ("%d rem %d\n", 0xffff, a);
- set_reg (RL78_Reg_AX, 0xffff);
- set_reg (RL78_Reg_DE, a);
- }
- else
- {
- v = a / b;
- a = a % b;
- tprintf ("%d rem %d\n", v, a);
- set_reg (RL78_Reg_AX, v);
- set_reg (RL78_Reg_DE, a);
- }
- CLOCKS (9);
- break;
- case RLO_divwu:
- {
- unsigned long bcax, hlde, quot, rem;
- bcax = get_reg (RL78_Reg_AX) + 65536 * get_reg (RL78_Reg_BC);
- hlde = get_reg (RL78_Reg_DE) + 65536 * get_reg (RL78_Reg_HL);
- tprintf (" %lu / %lu = ", bcax, hlde);
- if (hlde == 0)
- {
- tprintf ("%lu rem %lu\n", 0xffffLU, bcax);
- set_reg (RL78_Reg_AX, 0xffffLU);
- set_reg (RL78_Reg_BC, 0xffffLU);
- set_reg (RL78_Reg_DE, bcax);
- set_reg (RL78_Reg_HL, bcax >> 16);
- }
- else
- {
- quot = bcax / hlde;
- rem = bcax % hlde;
- tprintf ("%lu rem %lu\n", quot, rem);
- set_reg (RL78_Reg_AX, quot);
- set_reg (RL78_Reg_BC, quot >> 16);
- set_reg (RL78_Reg_DE, rem);
- set_reg (RL78_Reg_HL, rem >> 16);
- }
- }
- CLOCKS (17);
- break;
- case RLO_halt:
- tprintf ("HALT.\n");
- DO_RETURN (RL78_MAKE_EXITED (get_reg (RL78_Reg_A)));
- case RLO_mov:
- tprintf ("MOV: ");
- a = GS ();
- FLAGS (a, a);
- PD (a);
- break;
- #define MACR 0xffff0
- case RLO_mach:
- tprintf ("MACH:");
- a = sign_ext (get_reg (RL78_Reg_AX), 16);
- b = sign_ext (get_reg (RL78_Reg_BC), 16);
- v = sign_ext (mem_get_si (MACR), 32);
- tprintf ("%08x %d + %d * %d = ", v, v, a, b);
- v2 = sign_ext (v + a * b, 32);
- tprintf ("%08x %d\n", v2, v2);
- mem_put_si (MACR, v2);
- a = get_reg (RL78_Reg_PSW);
- v ^= v2;
- if (v & (1<<31))
- a |= RL78_PSW_CY;
- else
- a &= ~RL78_PSW_CY;
- if (v2 & (1 << 31))
- a |= RL78_PSW_AC;
- else
- a &= ~RL78_PSW_AC;
- set_reg (RL78_Reg_PSW, a);
- CLOCKS (3);
- break;
- case RLO_machu:
- tprintf ("MACHU:");
- a = get_reg (RL78_Reg_AX);
- b = get_reg (RL78_Reg_BC);
- u = mem_get_si (MACR);
- tprintf ("%08x %u + %u * %u = ", u, u, a, b);
- u2 = (u + (unsigned)a * (unsigned)b) & 0xffffffffUL;
- tprintf ("%08x %u\n", u2, u2);
- mem_put_si (MACR, u2);
- a = get_reg (RL78_Reg_PSW);
- if (u2 < u)
- a |= RL78_PSW_CY;
- else
- a &= ~RL78_PSW_CY;
- a &= ~RL78_PSW_AC;
- set_reg (RL78_Reg_PSW, a);
- CLOCKS (3);
- break;
- case RLO_mulu:
- tprintf ("MULU:");
- a = get_reg (RL78_Reg_A);
- b = get_reg (RL78_Reg_X);
- v = a * b;
- tprintf (" %d * %d = %d\n", a, b, v);
- set_reg (RL78_Reg_AX, v);
- break;
- case RLO_mulh:
- tprintf ("MUL:");
- a = sign_ext (get_reg (RL78_Reg_AX), 16);
- b = sign_ext (get_reg (RL78_Reg_BC), 16);
- v = a * b;
- tprintf (" %d * %d = %d\n", a, b, v);
- set_reg (RL78_Reg_BC, v >> 16);
- set_reg (RL78_Reg_AX, v);
- CLOCKS (2);
- break;
- case RLO_mulhu:
- tprintf ("MULHU:");
- a = get_reg (RL78_Reg_AX);
- b = get_reg (RL78_Reg_BC);
- v = a * b;
- tprintf (" %d * %d = %d\n", a, b, v);
- set_reg (RL78_Reg_BC, v >> 16);
- set_reg (RL78_Reg_AX, v);
- CLOCKS (2);
- break;
- case RLO_nop:
- tprintf ("NOP.\n");
- break;
- case RLO_or:
- tprintf ("OR:");
- a = GS ();
- b = GD ();
- v = a | b;
- FLAGS (b, v);
- PD (v);
- if (opcode.op[0].type == RL78_Operand_Indirect)
- CLOCKS (2);
- break;
- case RLO_ret:
- tprintf ("RET: ");
- a = get_reg (RL78_Reg_SP);
- v = mem_get_psi (a | 0xf0000);
- WILD_JUMP_CHECK (v);
- pc = v;
- set_reg (RL78_Reg_SP, a + 4);
- #if 0
- /* Enable this code to dump the return values for each return. */
- if (trace)
- {
- int i;
- skip_init ++;
- for (i = 0; i < 8; i ++)
- printf (" %02x", mem_get_qi (0xffef0 + i) & 0xff);
- skip_init --;
- }
- #endif
- tprintf ("\n");
- CLOCKS (6);
- break;
- case RLO_reti:
- tprintf ("RETI: ");
- a = get_reg (RL78_Reg_SP);
- v = mem_get_psi (a | 0xf0000);
- WILD_JUMP_CHECK (v);
- pc = v;
- b = mem_get_qi ((a + 3) | 0xf0000);
- set_reg (RL78_Reg_PSW, b);
- set_reg (RL78_Reg_SP, a + 4);
- tprintf ("\n");
- break;
- case RLO_rol:
- tprintf ("ROL:"); /* d <<= s */
- a = GS ();
- b = GD ();
- v = b;
- while (a --)
- {
- v = b << 1;
- v |= (b >> (obits - 1)) & 1;
- set_carry ((b >> (obits - 1)) & 1);
- b = v;
- }
- PD (v);
- break;
- case RLO_rolc:
- tprintf ("ROLC:"); /* d <<= s */
- a = GS ();
- b = GD ();
- v = b;
- while (a --)
- {
- v = b << 1;
- v |= get_carry ();
- set_carry ((b >> (obits - 1)) & 1);
- b = v;
- }
- PD (v);
- break;
- case RLO_ror:
- tprintf ("ROR:"); /* d >>= s */
- a = GS ();
- b = GD ();
- v = b;
- while (a --)
- {
- v = b >> 1;
- v |= (b & 1) << (obits - 1);
- set_carry (b & 1);
- b = v;
- }
- PD (v);
- break;
- case RLO_rorc:
- tprintf ("RORC:"); /* d >>= s */
- a = GS ();
- b = GD ();
- v = b;
- while (a --)
- {
- v = b >> 1;
- v |= (get_carry () << (obits - 1));
- set_carry (b & 1);
- b = v;
- }
- PD (v);
- break;
- case RLO_sar:
- tprintf ("SAR:"); /* d >>= s */
- a = GS ();
- b = GD ();
- v = b;
- while (a --)
- {
- v = b >> 1;
- v |= b & (1 << (obits - 1));
- set_carry (b & 1);
- b = v;
- }
- PD (v);
- break;
- case RLO_sel:
- tprintf ("SEL:");
- a = GS ();
- b = get_reg (RL78_Reg_PSW);
- b &= ~(RL78_PSW_RBS1 | RL78_PSW_RBS0);
- if (a & 1)
- b |= RL78_PSW_RBS0;
- if (a & 2)
- b |= RL78_PSW_RBS1;
- set_reg (RL78_Reg_PSW, b);
- tprintf ("\n");
- break;
- case RLO_shl:
- tprintf ("SHL%d:", obits); /* d <<= s */
- a = GS ();
- b = GD ();
- v = b;
- while (a --)
- {
- v = b << 1;
- tprintf ("b = 0x%x & 0x%x\n", b, 1<<(obits - 1));
- set_carry (b & (1<<(obits - 1)));
- b = v;
- }
- PD (v);
- break;
- case RLO_shr:
- tprintf ("SHR:"); /* d >>= s */
- a = GS ();
- b = GD ();
- v = b;
- while (a --)
- {
- v = b >> 1;
- set_carry (b & 1);
- b = v;
- }
- PD (v);
- break;
- case RLO_skip:
- tprintf ("SKIP: ");
- if (!condition_true (opcode.op[1].condition, GS ()))
- {
- tprintf (" false\n");
- break;
- }
- rl78_data.dpc = pc;
- opcode_size = rl78_decode_opcode (pc, &opcode,
- rl78_get_byte, &rl78_data, isa);
- pc += opcode_size;
- tprintf (" skipped: %s\n", opcode.syntax);
- break;
- case RLO_stop:
- tprintf ("STOP.\n");
- DO_RETURN (RL78_MAKE_EXITED (get_reg (RL78_Reg_A)));
- DO_RETURN (RL78_MAKE_HIT_BREAK ());
- case RLO_sub:
- tprintf ("SUB: ");
- a = GS ();
- b = GD ();
- v = b - a;
- FLAGS (b, v);
- PD (v);
- tprintf ("%d (0x%x) - %d (0x%x) = %d (0x%x)\n", b, b, a, a, v, v);
- if (opcode.op[0].type == RL78_Operand_Indirect)
- CLOCKS (2);
- break;
- case RLO_subc:
- tprintf ("SUBC: ");
- a = GS ();
- b = GD ();
- v = b - a - get_carry ();
- FLAGS (b, v);
- PD (v);
- if (opcode.op[0].type == RL78_Operand_Indirect)
- CLOCKS (2);
- break;
- case RLO_xch:
- tprintf ("XCH: ");
- a = GS ();
- b = GD ();
- PD (a);
- PS (b);
- break;
- case RLO_xor:
- tprintf ("XOR:");
- a = GS ();
- b = GD ();
- v = a ^ b;
- FLAGS (b, v);
- PD (v);
- if (opcode.op[0].type == RL78_Operand_Indirect)
- CLOCKS (2);
- break;
- default:
- tprintf ("Unknown opcode?\n");
- DO_RETURN (RL78_MAKE_HIT_BREAK ());
- }
- if (timer_enabled)
- process_clock_tick ();
- return RL78_MAKE_STEPPED ();
- }
|