aboutsummaryrefslogtreecommitdiff
path: root/sim/avr/interp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/avr/interp.c')
-rw-r--r--sim/avr/interp.c1565
1 files changed, 734 insertions, 831 deletions
diff --git a/sim/avr/interp.c b/sim/avr/interp.c
index 0df5155..d169935 100644
--- a/sim/avr/interp.c
+++ b/sim/avr/interp.c
@@ -23,12 +23,12 @@
#include <string.h>
#endif
#include "bfd.h"
-#include "gdb/callback.h"
-#include "gdb/signals.h"
#include "libiberty.h"
#include "gdb/remote-sim.h"
-#include "dis-asm.h"
-#include "sim-utils.h"
+
+#include "sim-main.h"
+#include "sim-base.h"
+#include "sim-options.h"
/* As AVR is a 8/16 bits processor, define handy types. */
typedef unsigned short int word;
@@ -36,13 +36,8 @@ typedef signed short int sword;
typedef unsigned char byte;
typedef signed char sbyte;
-/* Debug flag to display instructions and registers. */
-static int tracing = 0;
-static int lock_step = 0;
-static int verbose;
-
/* The only real register. */
-static unsigned int pc;
+unsigned int pc;
/* We update a cycle counter. */
static unsigned int cycles = 0;
@@ -50,15 +45,6 @@ static unsigned int cycles = 0;
/* If true, the pc needs more than 2 bytes. */
static int avr_pc22;
-static struct bfd *cur_bfd;
-
-static enum sim_stop cpu_exception;
-static int cpu_signal;
-
-static SIM_OPEN_KIND sim_kind;
-static char *myname;
-static host_callback *callback;
-
/* Max size of I space (which is always flash on avr). */
#define MAX_AVR_FLASH (128 * 1024)
#define PC_MASK (MAX_AVR_FLASH - 1)
@@ -237,14 +223,10 @@ struct avr_insn_cell
};
/* I&D memories. */
+/* TODO: Should be moved to SIM_CPU. */
static struct avr_insn_cell flash[MAX_AVR_FLASH];
static byte sram[MAX_AVR_SRAM];
-void
-sim_size (int s)
-{
-}
-
/* Sign extend a value. */
static int sign_ext (word val, int nb_bits)
{
@@ -747,61 +729,8 @@ decode (unsigned int pc)
break;
}
}
- sim_cb_eprintf (callback,
- "Unhandled instruction at pc=0x%x, op=%04x\n", pc * 2, op1);
- return OP_bad;
-}
-
-/* Disassemble an instruction. */
-
-static int
-disasm_read_memory (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length,
- struct disassemble_info *info)
-{
- int res;
-
- res = sim_read (NULL, memaddr, myaddr, length);
- if (res != length)
- return -1;
- return 0;
-}
-
-/* Memory error support for an opcodes disassembler. */
-
-static void
-disasm_perror_memory (int status, bfd_vma memaddr,
- struct disassemble_info *info)
-{
- if (status != -1)
- /* Can't happen. */
- info->fprintf_func (info->stream, "Unknown error %d.", status);
- else
- /* Actually, address between memaddr and memaddr + len was
- out of bounds. */
- info->fprintf_func (info->stream,
- "Address 0x%x is out of bounds.",
- (int) memaddr);
-}
-static void
-disassemble_insn (SIM_DESC sd, SIM_ADDR pc)
-{
- struct disassemble_info disasm_info;
- int len;
- int i;
-
- INIT_DISASSEMBLE_INFO (disasm_info, callback, sim_cb_eprintf);
-
- disasm_info.arch = bfd_get_arch (cur_bfd);
- disasm_info.mach = bfd_get_mach (cur_bfd);
- disasm_info.endian = BFD_ENDIAN_LITTLE;
- disasm_info.read_memory_func = disasm_read_memory;
- disasm_info.memory_error_func = disasm_perror_memory;
-
- len = print_insn_avr (pc << 1, &disasm_info);
- len = len / 2;
- for (i = 0; i < len; i++)
- sim_cb_eprintf (callback, " %04x", flash[pc + i].op);
+ return OP_bad;
}
static void
@@ -862,37 +791,27 @@ gen_mul (unsigned int res)
cycles++;
}
-void
-sim_resume (SIM_DESC sd, int step, int signal)
+static void
+step_once (SIM_CPU *cpu)
{
unsigned int ipc;
- if (step)
- {
- cpu_exception = sim_stopped;
- cpu_signal = GDB_SIGNAL_TRAP;
- }
- else
- cpu_exception = sim_running;
-
- do
- {
- int code;
- word op;
- byte res;
- byte r, d, vd;
-
- again:
- code = flash[pc].code;
- op = flash[pc].op;
+ int code;
+ word op;
+ byte res;
+ byte r, d, vd;
+ again:
+ code = flash[pc].code;
+ op = flash[pc].op;
- if ((tracing || lock_step) && code != OP_unknown)
+#if 0
+ if (tracing && code != OP_unknown)
{
if (verbose > 0) {
int flags;
int i;
-
+
sim_cb_eprintf (callback, "R00-07:");
for (i = 0; i < 8; i++)
sim_cb_eprintf (callback, " %02x", sram[i]);
@@ -916,709 +835,701 @@ sim_resume (SIM_DESC sd, int step, int signal)
sim_cb_eprintf (callback, "\n");
}
- if (lock_step && !tracing)
+ if (!tracing)
sim_cb_eprintf (callback, "%06x: %04x\n", 2 * pc, flash[pc].op);
else
{
sim_cb_eprintf (callback, "pc=0x%06x insn=0x%04x code=%d r=%d\n",
2 * pc, flash[pc].op, code, flash[pc].r);
- disassemble_insn (sd, pc);
+ disassemble_insn (CPU_STATE (cpu), pc);
sim_cb_eprintf (callback, "\n");
}
}
+#endif
- ipc = pc;
- pc = (pc + 1) & PC_MASK;
- cycles++;
+ ipc = pc;
+ pc = (pc + 1) & PC_MASK;
+ cycles++;
- switch (code)
+ switch (code)
+ {
+ case OP_unknown:
+ flash[ipc].code = decode(ipc);
+ pc = ipc;
+ cycles--;
+ goto again;
+
+ case OP_nop:
+ break;
+
+ case OP_jmp:
+ /* 2 words instruction, but we don't care about the pc. */
+ pc = ((flash[ipc].r << 16) | flash[ipc + 1].op) & PC_MASK;
+ cycles += 2;
+ break;
+
+ case OP_eijmp:
+ pc = ((sram[EIND] << 16) | read_word (REGZ)) & PC_MASK;
+ cycles += 2;
+ break;
+
+ case OP_ijmp:
+ pc = read_word (REGZ) & PC_MASK;
+ cycles += 1;
+ break;
+
+ case OP_call:
+ /* 2 words instruction. */
+ pc++;
+ do_call ((flash[ipc].r << 16) | flash[ipc + 1].op);
+ break;
+
+ case OP_eicall:
+ do_call ((sram[EIND] << 16) | read_word (REGZ));
+ break;
+
+ case OP_icall:
+ do_call (read_word (REGZ));
+ break;
+
+ case OP_rcall:
+ do_call (pc + sign_ext (op & 0xfff, 12));
+ break;
+
+ case OP_reti:
+ sram[SREG] |= SREG_I;
+ /* Fall through */
+ case OP_ret:
{
- case OP_unknown:
- flash[ipc].code = decode(ipc);
- pc = ipc;
- cycles--;
- goto again;
- break;
-
- case OP_nop:
- break;
-
- case OP_jmp:
- /* 2 words instruction, but we don't care about the pc. */
- pc = ((flash[ipc].r << 16) | flash[ipc + 1].op) & PC_MASK;
- cycles += 2;
- break;
-
- case OP_eijmp:
- pc = ((sram[EIND] << 16) | read_word (REGZ)) & PC_MASK;
- cycles += 2;
- break;
-
- case OP_ijmp:
- pc = read_word (REGZ) & PC_MASK;
- cycles += 1;
- break;
-
- case OP_call:
- /* 2 words instruction. */
- pc++;
- do_call ((flash[ipc].r << 16) | flash[ipc + 1].op);
- break;
-
- case OP_eicall:
- do_call ((sram[EIND] << 16) | read_word (REGZ));
- break;
-
- case OP_icall:
- do_call (read_word (REGZ));
- break;
-
- case OP_rcall:
- do_call (pc + sign_ext (op & 0xfff, 12));
- break;
-
- case OP_reti:
- sram[SREG] |= SREG_I;
- /* Fall through */
- case OP_ret:
- {
- unsigned int sp = read_word (REG_SP);
- if (avr_pc22)
- {
- pc = sram[++sp] << 16;
- cycles++;
- }
- else
- pc = 0;
- pc |= sram[++sp] << 8;
- pc |= sram[++sp];
- write_word (REG_SP, sp);
- }
- cycles += 3;
- break;
-
- case OP_break:
- /* Stop on this address. */
- cpu_exception = sim_stopped;
- cpu_signal = GDB_SIGNAL_TRAP;
- pc = ipc;
- break;
-
- case OP_bld:
- d = get_d (op);
- r = flash[ipc].r;
- if (sram[SREG] & SREG_T)
- sram[d] |= r;
- else
- sram[d] &= ~r;
- break;
-
- case OP_bst:
- if (sram[get_d (op)] & flash[ipc].r)
- sram[SREG] |= SREG_T;
+ unsigned int sp = read_word (REG_SP);
+ if (avr_pc22)
+ {
+ pc = sram[++sp] << 16;
+ cycles++;
+ }
else
- sram[SREG] &= ~SREG_T;
- break;
-
- case OP_sbrc:
- case OP_sbrs:
- if (((sram[get_d (op)] & flash[ipc].r) == 0) ^ ((op & 0x0200) != 0))
- {
- int l = get_insn_length(pc);
- pc += l;
- cycles += l;
- }
- break;
-
- case OP_push:
- {
- unsigned int sp = read_word (REG_SP);
- sram[sp--] = sram[get_d (op)];
- write_word (REG_SP, sp);
- }
- cycles++;
- break;
-
- case OP_pop:
+ pc = 0;
+ pc |= sram[++sp] << 8;
+ pc |= sram[++sp];
+ write_word (REG_SP, sp);
+ }
+ cycles += 3;
+ break;
+
+ case OP_break:
+ /* Stop on this address. */
+ sim_engine_halt (CPU_STATE (cpu), cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
+ pc = ipc;
+ break;
+
+ case OP_bld:
+ d = get_d (op);
+ r = flash[ipc].r;
+ if (sram[SREG] & SREG_T)
+ sram[d] |= r;
+ else
+ sram[d] &= ~r;
+ break;
+
+ case OP_bst:
+ if (sram[get_d (op)] & flash[ipc].r)
+ sram[SREG] |= SREG_T;
+ else
+ sram[SREG] &= ~SREG_T;
+ break;
+
+ case OP_sbrc:
+ case OP_sbrs:
+ if (((sram[get_d (op)] & flash[ipc].r) == 0) ^ ((op & 0x0200) != 0))
{
- unsigned int sp = read_word (REG_SP);
- sram[get_d (op)] = sram[++sp];
- write_word (REG_SP, sp);
+ int l = get_insn_length(pc);
+ pc += l;
+ cycles += l;
}
- cycles++;
- break;
-
- case OP_bclr:
- sram[SREG] &= ~(1 << ((op >> 4) & 0x7));
- break;
-
- case OP_bset:
- sram[SREG] |= 1 << ((op >> 4) & 0x7);
- break;
-
- case OP_rjmp:
- pc = (pc + sign_ext (op & 0xfff, 12)) & PC_MASK;
- cycles++;
- break;
-
- case OP_eor:
- d = get_d (op);
- res = sram[d] ^ sram[get_r (op)];
- sram[d] = res;
- update_flags_logic (res);
- break;
-
- case OP_and:
- d = get_d (op);
- res = sram[d] & sram[get_r (op)];
- sram[d] = res;
- update_flags_logic (res);
- break;
-
- case OP_andi:
- d = get_d16 (op);
- res = sram[d] & get_K (op);
- sram[d] = res;
- update_flags_logic (res);
- break;
+ break;
- case OP_or:
- d = get_d (op);
- res = sram[d] | sram[get_r (op)];
- sram[d] = res;
- update_flags_logic (res);
- break;
-
- case OP_ori:
- d = get_d16 (op);
- res = sram[d] | get_K (op);
- sram[d] = res;
- update_flags_logic (res);
- break;
+ case OP_push:
+ {
+ unsigned int sp = read_word (REG_SP);
+ sram[sp--] = sram[get_d (op)];
+ write_word (REG_SP, sp);
+ }
+ cycles++;
+ break;
- case OP_com:
- d = get_d (op);
- res = ~sram[d];
- sram[d] = res;
- update_flags_logic (res);
+ case OP_pop:
+ {
+ unsigned int sp = read_word (REG_SP);
+ sram[get_d (op)] = sram[++sp];
+ write_word (REG_SP, sp);
+ }
+ cycles++;
+ break;
+
+ case OP_bclr:
+ sram[SREG] &= ~(1 << ((op >> 4) & 0x7));
+ break;
+
+ case OP_bset:
+ sram[SREG] |= 1 << ((op >> 4) & 0x7);
+ break;
+
+ case OP_rjmp:
+ pc = (pc + sign_ext (op & 0xfff, 12)) & PC_MASK;
+ cycles++;
+ break;
+
+ case OP_eor:
+ d = get_d (op);
+ res = sram[d] ^ sram[get_r (op)];
+ sram[d] = res;
+ update_flags_logic (res);
+ break;
+
+ case OP_and:
+ d = get_d (op);
+ res = sram[d] & sram[get_r (op)];
+ sram[d] = res;
+ update_flags_logic (res);
+ break;
+
+ case OP_andi:
+ d = get_d16 (op);
+ res = sram[d] & get_K (op);
+ sram[d] = res;
+ update_flags_logic (res);
+ break;
+
+ case OP_or:
+ d = get_d (op);
+ res = sram[d] | sram[get_r (op)];
+ sram[d] = res;
+ update_flags_logic (res);
+ break;
+
+ case OP_ori:
+ d = get_d16 (op);
+ res = sram[d] | get_K (op);
+ sram[d] = res;
+ update_flags_logic (res);
+ break;
+
+ case OP_com:
+ d = get_d (op);
+ res = ~sram[d];
+ sram[d] = res;
+ update_flags_logic (res);
+ sram[SREG] |= SREG_C;
+ break;
+
+ case OP_swap:
+ d = get_d (op);
+ vd = sram[d];
+ sram[d] = (vd >> 4) | (vd << 4);
+ break;
+
+ case OP_neg:
+ d = get_d (op);
+ vd = sram[d];
+ res = -vd;
+ sram[d] = res;
+ sram[SREG] &= ~(SREG_H | SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
+ if (res == 0)
+ sram[SREG] |= SREG_Z;
+ else
sram[SREG] |= SREG_C;
- break;
-
- case OP_swap:
- d = get_d (op);
- vd = sram[d];
- sram[d] = (vd >> 4) | (vd << 4);
- break;
-
- case OP_neg:
- d = get_d (op);
- vd = sram[d];
- res = -vd;
- sram[d] = res;
- sram[SREG] &= ~(SREG_H | SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
- if (res == 0)
- sram[SREG] |= SREG_Z;
- else
- sram[SREG] |= SREG_C;
- if (res == 0x80)
- sram[SREG] |= SREG_V | SREG_N;
- else if (res & 0x80)
- sram[SREG] |= SREG_N | SREG_S;
- if ((res | vd) & 0x08)
- sram[SREG] |= SREG_H;
- break;
-
- case OP_inc:
- d = get_d (op);
- res = sram[d] + 1;
- sram[d] = res;
- sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
- if (res == 0x80)
- sram[SREG] |= SREG_V | SREG_N;
- else if (res & 0x80)
- sram[SREG] |= SREG_N | SREG_S;
- else if (res == 0)
- sram[SREG] |= SREG_Z;
- break;
-
- case OP_dec:
- d = get_d (op);
- res = sram[d] - 1;
- sram[d] = res;
- sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
- if (res == 0x7f)
- sram[SREG] |= SREG_V | SREG_S;
- else if (res & 0x80)
- sram[SREG] |= SREG_N | SREG_S;
- else if (res == 0)
- sram[SREG] |= SREG_Z;
- break;
-
- case OP_lsr:
- case OP_asr:
- d = get_d (op);
- vd = sram[d];
- res = (vd >> 1) | (vd & flash[ipc].r);
- sram[d] = res;
- sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
- if (vd & 1)
- sram[SREG] |= SREG_C | SREG_S;
- if (res & 0x80)
- sram[SREG] |= SREG_N;
- if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_C))
- sram[SREG] |= SREG_V;
- if (res == 0)
- sram[SREG] |= SREG_Z;
- break;
-
- case OP_ror:
- d = get_d (op);
- vd = sram[d];
- res = vd >> 1 | (sram[SREG] << 7);
- sram[d] = res;
- sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
- if (vd & 1)
- sram[SREG] |= SREG_C | SREG_S;
- if (res & 0x80)
- sram[SREG] |= SREG_N;
- if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_C))
- sram[SREG] |= SREG_V;
- if (res == 0)
- sram[SREG] |= SREG_Z;
- break;
-
- case OP_mul:
- gen_mul ((word)sram[get_r (op)] * (word)sram[get_d (op)]);
- break;
-
- case OP_muls:
- gen_mul((sword)(sbyte)sram[get_r16 (op)]
- * (sword)(sbyte)sram[get_d16 (op)]);
- break;
-
- case OP_mulsu:
- gen_mul ((sword)(word)sram[get_r16_23 (op)]
- * (sword)(sbyte)sram[get_d16_23 (op)]);
- break;
-
- case OP_fmul:
- gen_mul(((word)sram[get_r16_23 (op)]
- * (word)sram[get_d16_23 (op)]) << 1);
- break;
-
- case OP_fmuls:
- gen_mul(((sword)(sbyte)sram[get_r16_23 (op)]
- * (sword)(sbyte)sram[get_d16_23 (op)]) << 1);
- break;
-
- case OP_fmulsu:
- gen_mul(((sword)(word)sram[get_r16_23 (op)]
- * (sword)(sbyte)sram[get_d16_23 (op)]) << 1);
- break;
-
- case OP_adc:
- case OP_add:
- r = sram[get_r (op)];
- d = get_d (op);
- vd = sram[d];
- res = r + vd + (sram[SREG] & flash[ipc].r);
- sram[d] = res;
- update_flags_add (res, vd, r);
- break;
-
- case OP_sub:
+ if (res == 0x80)
+ sram[SREG] |= SREG_V | SREG_N;
+ else if (res & 0x80)
+ sram[SREG] |= SREG_N | SREG_S;
+ if ((res | vd) & 0x08)
+ sram[SREG] |= SREG_H;
+ break;
+
+ case OP_inc:
+ d = get_d (op);
+ res = sram[d] + 1;
+ sram[d] = res;
+ sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
+ if (res == 0x80)
+ sram[SREG] |= SREG_V | SREG_N;
+ else if (res & 0x80)
+ sram[SREG] |= SREG_N | SREG_S;
+ else if (res == 0)
+ sram[SREG] |= SREG_Z;
+ break;
+
+ case OP_dec:
+ d = get_d (op);
+ res = sram[d] - 1;
+ sram[d] = res;
+ sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
+ if (res == 0x7f)
+ sram[SREG] |= SREG_V | SREG_S;
+ else if (res & 0x80)
+ sram[SREG] |= SREG_N | SREG_S;
+ else if (res == 0)
+ sram[SREG] |= SREG_Z;
+ break;
+
+ case OP_lsr:
+ case OP_asr:
+ d = get_d (op);
+ vd = sram[d];
+ res = (vd >> 1) | (vd & flash[ipc].r);
+ sram[d] = res;
+ sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
+ if (vd & 1)
+ sram[SREG] |= SREG_C | SREG_S;
+ if (res & 0x80)
+ sram[SREG] |= SREG_N;
+ if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_C))
+ sram[SREG] |= SREG_V;
+ if (res == 0)
+ sram[SREG] |= SREG_Z;
+ break;
+
+ case OP_ror:
+ d = get_d (op);
+ vd = sram[d];
+ res = vd >> 1 | (sram[SREG] << 7);
+ sram[d] = res;
+ sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
+ if (vd & 1)
+ sram[SREG] |= SREG_C | SREG_S;
+ if (res & 0x80)
+ sram[SREG] |= SREG_N;
+ if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_C))
+ sram[SREG] |= SREG_V;
+ if (res == 0)
+ sram[SREG] |= SREG_Z;
+ break;
+
+ case OP_mul:
+ gen_mul ((word)sram[get_r (op)] * (word)sram[get_d (op)]);
+ break;
+
+ case OP_muls:
+ gen_mul ((sword)(sbyte)sram[get_r16 (op)]
+ * (sword)(sbyte)sram[get_d16 (op)]);
+ break;
+
+ case OP_mulsu:
+ gen_mul ((sword)(word)sram[get_r16_23 (op)]
+ * (sword)(sbyte)sram[get_d16_23 (op)]);
+ break;
+
+ case OP_fmul:
+ gen_mul (((word)sram[get_r16_23 (op)]
+ * (word)sram[get_d16_23 (op)]) << 1);
+ break;
+
+ case OP_fmuls:
+ gen_mul (((sword)(sbyte)sram[get_r16_23 (op)]
+ * (sword)(sbyte)sram[get_d16_23 (op)]) << 1);
+ break;
+
+ case OP_fmulsu:
+ gen_mul (((sword)(word)sram[get_r16_23 (op)]
+ * (sword)(sbyte)sram[get_d16_23 (op)]) << 1);
+ break;
+
+ case OP_adc:
+ case OP_add:
+ r = sram[get_r (op)];
+ d = get_d (op);
+ vd = sram[d];
+ res = r + vd + (sram[SREG] & flash[ipc].r);
+ sram[d] = res;
+ update_flags_add (res, vd, r);
+ break;
+
+ case OP_sub:
+ d = get_d (op);
+ vd = sram[d];
+ r = sram[get_r (op)];
+ res = vd - r;
+ sram[d] = res;
+ update_flags_sub (res, vd, r);
+ if (res == 0)
+ sram[SREG] |= SREG_Z;
+ break;
+
+ case OP_sbc:
+ {
+ byte old = sram[SREG];
d = get_d (op);
vd = sram[d];
r = sram[get_r (op)];
- res = vd - r;
+ res = vd - r - (old & SREG_C);
sram[d] = res;
update_flags_sub (res, vd, r);
- if (res == 0)
+ if (res == 0 && (old & SREG_Z))
sram[SREG] |= SREG_Z;
- break;
-
- case OP_sbc:
- {
- byte old = sram[SREG];
- d = get_d (op);
- vd = sram[d];
- r = sram[get_r (op)];
- res = vd - r - (old & SREG_C);
- sram[d] = res;
- update_flags_sub (res, vd, r);
- if (res == 0 && (old & SREG_Z))
- sram[SREG] |= SREG_Z;
- }
- break;
+ }
+ break;
+
+ case OP_subi:
+ d = get_d16 (op);
+ vd = sram[d];
+ r = get_K (op);
+ res = vd - r;
+ sram[d] = res;
+ update_flags_sub (res, vd, r);
+ if (res == 0)
+ sram[SREG] |= SREG_Z;
+ break;
+
+ case OP_sbci:
+ {
+ byte old = sram[SREG];
- case OP_subi:
d = get_d16 (op);
vd = sram[d];
r = get_K (op);
- res = vd - r;
+ res = vd - r - (old & SREG_C);
sram[d] = res;
update_flags_sub (res, vd, r);
- if (res == 0)
+ if (res == 0 && (old & SREG_Z))
sram[SREG] |= SREG_Z;
- break;
-
- case OP_sbci:
+ }
+ break;
+
+ case OP_mov:
+ sram[get_d (op)] = sram[get_r (op)];
+ break;
+
+ case OP_movw:
+ d = (op & 0xf0) >> 3;
+ r = (op & 0x0f) << 1;
+ sram[d] = sram[r];
+ sram[d + 1] = sram[r + 1];
+ break;
+
+ case OP_out:
+ d = get_A (op) + 0x20;
+ res = sram[get_d (op)];
+ sram[d] = res;
+ if (d == STDIO_PORT)
+ putchar (res);
+ else if (d == EXIT_PORT)
+ sim_engine_halt (CPU_STATE (cpu), cpu, NULL, pc, sim_exited, 0);
+ else if (d == ABORT_PORT)
+ sim_engine_halt (CPU_STATE (cpu), cpu, NULL, pc, sim_exited, 1);
+ break;
+
+ case OP_in:
+ d = get_A (op) + 0x20;
+ sram[get_d (op)] = sram[d];
+ break;
+
+ case OP_cbi:
+ d = get_biA (op) + 0x20;
+ sram[d] &= ~(1 << get_b(op));
+ break;
+
+ case OP_sbi:
+ d = get_biA (op) + 0x20;
+ sram[d] |= 1 << get_b(op);
+ break;
+
+ case OP_sbic:
+ if (!(sram[get_biA (op) + 0x20] & 1 << get_b(op)))
{
- byte old = sram[SREG];
-
- d = get_d16 (op);
- vd = sram[d];
- r = get_K (op);
- res = vd - r - (old & SREG_C);
- sram[d] = res;
- update_flags_sub (res, vd, r);
- if (res == 0 && (old & SREG_Z))
- sram[SREG] |= SREG_Z;
+ int l = get_insn_length(pc);
+ pc += l;
+ cycles += l;
}
- break;
-
- case OP_mov:
- sram[get_d (op)] = sram[get_r (op)];
- break;
-
- case OP_movw:
- d = (op & 0xf0) >> 3;
- r = (op & 0x0f) << 1;
- sram[d] = sram[r];
- sram[d + 1] = sram[r + 1];
- break;
-
- case OP_out:
- d = get_A (op) + 0x20;
- res = sram[get_d (op)];
- sram[d] = res;
- if (d == STDIO_PORT)
- putchar (res);
- else if (d == EXIT_PORT)
- {
- cpu_exception = sim_exited;
- cpu_signal = 0;
- return;
- }
- else if (d == ABORT_PORT)
- {
- cpu_exception = sim_exited;
- cpu_signal = 1;
- return;
- }
- break;
-
- case OP_in:
- d = get_A (op) + 0x20;
- sram[get_d (op)] = sram[d];
- break;
-
- case OP_cbi:
- d = get_biA (op) + 0x20;
- sram[d] &= ~(1 << get_b(op));
- break;
-
- case OP_sbi:
- d = get_biA (op) + 0x20;
- sram[d] |= 1 << get_b(op);
- break;
-
- case OP_sbic:
- if (!(sram[get_biA (op) + 0x20] & 1 << get_b(op)))
- {
- int l = get_insn_length(pc);
- pc += l;
- cycles += l;
- }
- break;
-
- case OP_sbis:
- if (sram[get_biA (op) + 0x20] & 1 << get_b(op))
- {
- int l = get_insn_length(pc);
- pc += l;
- cycles += l;
- }
- break;
-
- case OP_ldi:
- res = get_K (op);
- d = get_d16 (op);
- sram[d] = res;
- break;
-
- case OP_lds:
- sram[get_d (op)] = sram[flash[pc].op];
- pc++;
- cycles++;
- break;
-
- case OP_sts:
- sram[flash[pc].op] = sram[get_d (op)];
- pc++;
- cycles++;
- break;
-
- case OP_cpse:
- if (sram[get_r (op)] == sram[get_d (op)])
- {
- int l = get_insn_length(pc);
- pc += l;
- cycles += l;
- }
- break;
+ break;
- case OP_cp:
- r = sram[get_r (op)];
+ case OP_sbis:
+ if (sram[get_biA (op) + 0x20] & 1 << get_b(op))
+ {
+ int l = get_insn_length(pc);
+ pc += l;
+ cycles += l;
+ }
+ break;
+
+ case OP_ldi:
+ res = get_K (op);
+ d = get_d16 (op);
+ sram[d] = res;
+ break;
+
+ case OP_lds:
+ sram[get_d (op)] = sram[flash[pc].op];
+ pc++;
+ cycles++;
+ break;
+
+ case OP_sts:
+ sram[flash[pc].op] = sram[get_d (op)];
+ pc++;
+ cycles++;
+ break;
+
+ case OP_cpse:
+ if (sram[get_r (op)] == sram[get_d (op)])
+ {
+ int l = get_insn_length(pc);
+ pc += l;
+ cycles += l;
+ }
+ break;
+
+ case OP_cp:
+ r = sram[get_r (op)];
+ d = sram[get_d (op)];
+ res = d - r;
+ update_flags_sub (res, d, r);
+ if (res == 0)
+ sram[SREG] |= SREG_Z;
+ break;
+
+ case OP_cpi:
+ r = get_K (op);
+ d = sram[get_d16 (op)];
+ res = d - r;
+ update_flags_sub (res, d, r);
+ if (res == 0)
+ sram[SREG] |= SREG_Z;
+ break;
+
+ case OP_cpc:
+ {
+ byte old = sram[SREG];
d = sram[get_d (op)];
- res = d - r;
+ r = sram[get_r (op)];
+ res = d - r - (old & SREG_C);
update_flags_sub (res, d, r);
- if (res == 0)
+ if (res == 0 && (old & SREG_Z))
sram[SREG] |= SREG_Z;
- break;
+ }
+ break;
- case OP_cpi:
- r = get_K (op);
- d = sram[get_d16 (op)];
- res = d - r;
- update_flags_sub (res, d, r);
- if (res == 0)
- sram[SREG] |= SREG_Z;
- break;
+ case OP_brbc:
+ if (!(sram[SREG] & flash[ipc].r))
+ {
+ pc = (pc + get_k (op)) & PC_MASK;
+ cycles++;
+ }
+ break;
- case OP_cpc:
+ case OP_brbs:
+ if (sram[SREG] & flash[ipc].r)
{
- byte old = sram[SREG];
- d = sram[get_d (op)];
- r = sram[get_r (op)];
- res = d - r - (old & SREG_C);
- update_flags_sub (res, d, r);
- if (res == 0 && (old & SREG_Z))
- sram[SREG] |= SREG_Z;
+ pc = (pc + get_k (op)) & PC_MASK;
+ cycles++;
}
- break;
+ break;
+
+ case OP_lpm:
+ sram[0] = get_lpm (read_word (REGZ));
+ cycles += 2;
+ break;
+
+ case OP_lpm_Z:
+ sram[get_d (op)] = get_lpm (read_word (REGZ));
+ cycles += 2;
+ break;
+
+ case OP_lpm_inc_Z:
+ sram[get_d (op)] = get_lpm (read_word_post_inc (REGZ));
+ cycles += 2;
+ break;
+
+ case OP_elpm:
+ sram[0] = get_lpm (get_z ());
+ cycles += 2;
+ break;
+
+ case OP_elpm_Z:
+ sram[get_d (op)] = get_lpm (get_z ());
+ cycles += 2;
+ break;
+
+ case OP_elpm_inc_Z:
+ {
+ unsigned int z = get_z ();
- case OP_brbc:
- if (!(sram[SREG] & flash[ipc].r))
- {
- pc = (pc + get_k (op)) & PC_MASK;
- cycles++;
- }
- break;
+ sram[get_d (op)] = get_lpm (z);
+ z++;
+ sram[REGZ_LO] = z;
+ sram[REGZ_HI] = z >> 8;
+ sram[RAMPZ] = z >> 16;
+ }
+ cycles += 2;
+ break;
+
+ case OP_ld_Z_inc:
+ sram[get_d (op)] = sram[read_word_post_inc (REGZ) & SRAM_MASK];
+ cycles++;
+ break;
+
+ case OP_ld_dec_Z:
+ sram[get_d (op)] = sram[read_word_pre_dec (REGZ) & SRAM_MASK];
+ cycles++;
+ break;
+
+ case OP_ld_X_inc:
+ sram[get_d (op)] = sram[read_word_post_inc (REGX) & SRAM_MASK];
+ cycles++;
+ break;
+
+ case OP_ld_dec_X:
+ sram[get_d (op)] = sram[read_word_pre_dec (REGX) & SRAM_MASK];
+ cycles++;
+ break;
+
+ case OP_ld_Y_inc:
+ sram[get_d (op)] = sram[read_word_post_inc (REGY) & SRAM_MASK];
+ cycles++;
+ break;
+
+ case OP_ld_dec_Y:
+ sram[get_d (op)] = sram[read_word_pre_dec (REGY) & SRAM_MASK];
+ cycles++;
+ break;
+
+ case OP_st_X:
+ sram[read_word (REGX) & SRAM_MASK] = sram[get_d (op)];
+ cycles++;
+ break;
+
+ case OP_st_X_inc:
+ sram[read_word_post_inc (REGX) & SRAM_MASK] = sram[get_d (op)];
+ cycles++;
+ break;
+
+ case OP_st_dec_X:
+ sram[read_word_pre_dec (REGX) & SRAM_MASK] = sram[get_d (op)];
+ cycles++;
+ break;
+
+ case OP_st_Z_inc:
+ sram[read_word_post_inc (REGZ) & SRAM_MASK] = sram[get_d (op)];
+ cycles++;
+ break;
+
+ case OP_st_dec_Z:
+ sram[read_word_pre_dec (REGZ) & SRAM_MASK] = sram[get_d (op)];
+ cycles++;
+ break;
+
+ case OP_st_Y_inc:
+ sram[read_word_post_inc (REGY) & SRAM_MASK] = sram[get_d (op)];
+ cycles++;
+ break;
+
+ case OP_st_dec_Y:
+ sram[read_word_pre_dec (REGY) & SRAM_MASK] = sram[get_d (op)];
+ cycles++;
+ break;
+
+ case OP_std_Y:
+ sram[read_word (REGY) + flash[ipc].r] = sram[get_d (op)];
+ cycles++;
+ break;
+
+ case OP_std_Z:
+ sram[read_word (REGZ) + flash[ipc].r] = sram[get_d (op)];
+ cycles++;
+ break;
+
+ case OP_ldd_Z:
+ sram[get_d (op)] = sram[read_word (REGZ) + flash[ipc].r];
+ cycles++;
+ break;
+
+ case OP_ldd_Y:
+ sram[get_d (op)] = sram[read_word (REGY) + flash[ipc].r];
+ cycles++;
+ break;
+
+ case OP_ld_X:
+ sram[get_d (op)] = sram[read_word (REGX) & SRAM_MASK];
+ cycles++;
+ break;
+
+ case OP_sbiw:
+ {
+ word wk = get_k6 (op);
+ word wres;
+ word wr;
- case OP_brbs:
- if (sram[SREG] & flash[ipc].r)
- {
- pc = (pc + get_k (op)) & PC_MASK;
- cycles++;
- }
- break;
-
- case OP_lpm:
- sram[0] = get_lpm (read_word (REGZ));
- cycles += 2;
- break;
-
- case OP_lpm_Z:
- sram[get_d (op)] = get_lpm (read_word (REGZ));
- cycles += 2;
- break;
-
- case OP_lpm_inc_Z:
- sram[get_d (op)] = get_lpm (read_word_post_inc (REGZ));
- cycles += 2;
- break;
-
- case OP_elpm:
- sram[0] = get_lpm (get_z ());
- cycles += 2;
- break;
-
- case OP_elpm_Z:
- sram[get_d (op)] = get_lpm (get_z ());
- cycles += 2;
- break;
-
- case OP_elpm_inc_Z:
- {
- unsigned int z = get_z ();
+ d = get_d24 (op);
+ wr = read_word (d);
+ wres = wr - wk;
- sram[get_d (op)] = get_lpm (z);
- z++;
- sram[REGZ_LO] = z;
- sram[REGZ_HI] = z >> 8;
- sram[RAMPZ] = z >> 16;
- }
- cycles += 2;
- break;
-
- case OP_ld_Z_inc:
- sram[get_d (op)] = sram[read_word_post_inc (REGZ) & SRAM_MASK];
- cycles++;
- break;
-
- case OP_ld_dec_Z:
- sram[get_d (op)] = sram[read_word_pre_dec (REGZ) & SRAM_MASK];
- cycles++;
- break;
-
- case OP_ld_X_inc:
- sram[get_d (op)] = sram[read_word_post_inc (REGX) & SRAM_MASK];
- cycles++;
- break;
-
- case OP_ld_dec_X:
- sram[get_d (op)] = sram[read_word_pre_dec (REGX) & SRAM_MASK];
- cycles++;
- break;
-
- case OP_ld_Y_inc:
- sram[get_d (op)] = sram[read_word_post_inc (REGY) & SRAM_MASK];
- cycles++;
- break;
-
- case OP_ld_dec_Y:
- sram[get_d (op)] = sram[read_word_pre_dec (REGY) & SRAM_MASK];
- cycles++;
- break;
-
- case OP_st_X:
- sram[read_word (REGX) & SRAM_MASK] = sram[get_d (op)];
- cycles++;
- break;
-
- case OP_st_X_inc:
- sram[read_word_post_inc (REGX) & SRAM_MASK] = sram[get_d (op)];
- cycles++;
- break;
-
- case OP_st_dec_X:
- sram[read_word_pre_dec (REGX) & SRAM_MASK] = sram[get_d (op)];
- cycles++;
- break;
-
- case OP_st_Z_inc:
- sram[read_word_post_inc (REGZ) & SRAM_MASK] = sram[get_d (op)];
- cycles++;
- break;
-
- case OP_st_dec_Z:
- sram[read_word_pre_dec (REGZ) & SRAM_MASK] = sram[get_d (op)];
- cycles++;
- break;
-
- case OP_st_Y_inc:
- sram[read_word_post_inc (REGY) & SRAM_MASK] = sram[get_d (op)];
- cycles++;
- break;
-
- case OP_st_dec_Y:
- sram[read_word_pre_dec (REGY) & SRAM_MASK] = sram[get_d (op)];
- cycles++;
- break;
-
- case OP_std_Y:
- sram[read_word (REGY) + flash[ipc].r] = sram[get_d (op)];
- cycles++;
- break;
-
- case OP_std_Z:
- sram[read_word (REGZ) + flash[ipc].r] = sram[get_d (op)];
- cycles++;
- break;
-
- case OP_ldd_Z:
- sram[get_d (op)] = sram[read_word (REGZ) + flash[ipc].r];
- cycles++;
- break;
-
- case OP_ldd_Y:
- sram[get_d (op)] = sram[read_word (REGY) + flash[ipc].r];
- cycles++;
- break;
-
- case OP_ld_X:
- sram[get_d (op)] = sram[read_word (REGX) & SRAM_MASK];
- cycles++;
- break;
-
- case OP_sbiw:
- {
- word wk = get_k6 (op);
- word wres;
- word wr;
-
- d = get_d24 (op);
- wr = read_word (d);
- wres = wr - wk;
-
- sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
- if (wres == 0)
- sram[SREG] |= SREG_Z;
- if (wres & 0x8000)
- sram[SREG] |= SREG_N;
- if (wres & ~wr & 0x8000)
- sram[SREG] |= SREG_C;
- if (~wres & wr & 0x8000)
- sram[SREG] |= SREG_V;
- if (((~wres & wr) ^ wres) & 0x8000)
- sram[SREG] |= SREG_S;
- write_word (d, wres);
- }
- cycles++;
- break;
+ sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
+ if (wres == 0)
+ sram[SREG] |= SREG_Z;
+ if (wres & 0x8000)
+ sram[SREG] |= SREG_N;
+ if (wres & ~wr & 0x8000)
+ sram[SREG] |= SREG_C;
+ if (~wres & wr & 0x8000)
+ sram[SREG] |= SREG_V;
+ if (((~wres & wr) ^ wres) & 0x8000)
+ sram[SREG] |= SREG_S;
+ write_word (d, wres);
+ }
+ cycles++;
+ break;
- case OP_adiw:
- {
- word wk = get_k6 (op);
- word wres;
- word wr;
-
- d = get_d24 (op);
- wr = read_word (d);
- wres = wr + wk;
-
- sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
- if (wres == 0)
- sram[SREG] |= SREG_Z;
- if (wres & 0x8000)
- sram[SREG] |= SREG_N;
- if (~wres & wr & 0x8000)
- sram[SREG] |= SREG_C;
- if (wres & ~wr & 0x8000)
- sram[SREG] |= SREG_V;
- if (((wres & ~wr) ^ wres) & 0x8000)
- sram[SREG] |= SREG_S;
- write_word (d, wres);
- }
- cycles++;
- break;
-
- case OP_bad:
- sim_cb_eprintf (callback, "Bad instruction at pc=0x%x\n", ipc * 2);
- return;
-
- default:
- sim_cb_eprintf (callback,
- "Unhandled instruction at pc=0x%x, code=%d\n",
- 2 * ipc, code);
- return;
+ case OP_adiw:
+ {
+ word wk = get_k6 (op);
+ word wres;
+ word wr;
+
+ d = get_d24 (op);
+ wr = read_word (d);
+ wres = wr + wk;
+
+ sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
+ if (wres == 0)
+ sram[SREG] |= SREG_Z;
+ if (wres & 0x8000)
+ sram[SREG] |= SREG_N;
+ if (~wres & wr & 0x8000)
+ sram[SREG] |= SREG_C;
+ if (wres & ~wr & 0x8000)
+ sram[SREG] |= SREG_V;
+ if (((wres & ~wr) ^ wres) & 0x8000)
+ sram[SREG] |= SREG_S;
+ write_word (d, wres);
}
- }
- while (cpu_exception == sim_running);
-}
+ cycles++;
+ break;
+ case OP_bad:
+ sim_engine_halt (CPU_STATE (cpu), cpu, NULL, pc, sim_signalled, SIM_SIGILL);
-int
-sim_trace (SIM_DESC sd)
+ default:
+ sim_engine_halt (CPU_STATE (cpu), cpu, NULL, pc, sim_signalled, SIM_SIGILL);
+ }
+}
+
+void
+sim_engine_run (SIM_DESC sd,
+ int next_cpu_nr, /* ignore */
+ int nr_cpus, /* ignore */
+ int siggnal) /* ignore */
{
- tracing = 1;
-
- sim_resume (sd, 0, 0);
+ SIM_CPU *cpu;
+
+ SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
+
+ cpu = STATE_CPU (sd, 0);
- tracing = 0;
-
- return 1;
+ while (1)
+ {
+ step_once (cpu);
+ if (sim_events_tick (sd))
+ sim_events_process (sd);
+ }
}
int
@@ -1752,104 +1663,96 @@ sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
return 0;
}
-void
-sim_stop_reason (SIM_DESC sd, enum sim_stop * reason, int *sigrc)
-{
- *reason = cpu_exception;
- *sigrc = cpu_signal;
-}
-
-int
-sim_stop (SIM_DESC sd)
-{
- cpu_exception = sim_stopped;
- cpu_signal = GDB_SIGNAL_INT;
- return 1;
-}
-
-void
-sim_info (SIM_DESC sd, int verbose)
+static void
+free_state (SIM_DESC sd)
{
- callback->printf_filtered
- (callback, "\n\n# cycles %10u\n", cycles);
+ if (STATE_MODULES (sd) != NULL)
+ sim_module_uninstall (sd);
+ sim_cpu_free_all (sd);
+ sim_state_free (sd);
}
SIM_DESC
sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
{
- myname = argv[0];
- callback = cb;
-
- cur_bfd = abfd;
+ SIM_DESC sd = sim_state_alloc (kind, cb);
+ SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
- /* Fudge our descriptor for now. */
- return (SIM_DESC) 1;
-}
+ /* The cpu data is kept in a separately allocated chunk of memory. */
+ if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
+ {
+ free_state (sd);
+ return 0;
+ }
-void
-sim_close (SIM_DESC sd, int quitting)
-{
- /* nothing to do */
-}
+ STATE_WATCHPOINTS (sd)->pc = &pc;
+ STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (pc);
-SIM_RC
-sim_load (SIM_DESC sd, const char *prog, bfd *abfd, int from_tty)
-{
- bfd *prog_bfd;
+ if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
+ {
+ free_state (sd);
+ return 0;
+ }
- /* Clear all the memory. */
- memset (sram, 0, sizeof (sram));
- memset (flash, 0, sizeof (flash));
+ /* getopt will print the error message so we just have to exit if this fails.
+ FIXME: Hmmm... in the case of gdb we need getopt to call
+ print_filtered. */
+ if (sim_parse_args (sd, argv) != SIM_RC_OK)
+ {
+ free_state (sd);
+ return 0;
+ }
- prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
- sim_kind == SIM_OPEN_DEBUG,
- 0, sim_write);
- if (prog_bfd == NULL)
- return SIM_RC_FAIL;
+ /* Check for/establish the a reference program image. */
+ if (sim_analyze_program (sd,
+ (STATE_PROG_ARGV (sd) != NULL
+ ? *STATE_PROG_ARGV (sd)
+ : NULL), abfd) != SIM_RC_OK)
+ {
+ free_state (sd);
+ return 0;
+ }
- avr_pc22 = (bfd_get_mach (prog_bfd) >= bfd_mach_avr6);
+ /* Configure/verify the target byte order and other runtime
+ configuration options. */
+ if (sim_config (sd) != SIM_RC_OK)
+ {
+ sim_module_uninstall (sd);
+ return 0;
+ }
- if (abfd != NULL)
- cur_bfd = abfd;
+ if (sim_post_argv_init (sd) != SIM_RC_OK)
+ {
+ /* Uninstall the modules to avoid memory leaks,
+ file descriptor leaks, etc. */
+ sim_module_uninstall (sd);
+ return 0;
+ }
- return SIM_RC_OK;
-}
+ /* Clear all the memory. */
+ memset (sram, 0, sizeof (sram));
+ memset (flash, 0, sizeof (flash));
-SIM_RC
-sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env)
-{
- /* Set the initial register set. */
- pc = 0;
-
- return SIM_RC_OK;
+ return sd;
}
void
-sim_do_command (SIM_DESC sd, const char *cmd)
+sim_close (SIM_DESC sd, int quitting)
{
- /* Nothing there yet; it's all an error. */
-
- if (cmd == NULL)
- return;
-
- if (strcmp (cmd, "verbose") == 0)
- verbose = 2;
- else if (strcmp (cmd, "trace") == 0)
- tracing = 1;
- else
- sim_cb_eprintf (callback,
- "Error: \"%s\" is not a valid avr simulator command.\n",
- cmd);
+ sim_module_uninstall (sd);
}
-void
-sim_set_callbacks (host_callback *ptr)
+SIM_RC
+sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char **argv, char **env)
{
- callback = ptr;
-}
+ /* Set the PC. */
+ if (abfd != NULL)
+ pc = bfd_get_start_address (abfd);
+ else
+ pc = 0;
-char **
-sim_complete_command (SIM_DESC sd, const char *text, const char *word)
-{
- return NULL;
+ if (abfd != NULL)
+ avr_pc22 = (bfd_get_mach (abfd) >= bfd_mach_avr6);
+
+ return SIM_RC_OK;
}