123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920 |
- /* Simulator for the FT32 processor
- Copyright (C) 2008-2022 Free Software Foundation, Inc.
- Contributed by FTDI <support@ftdichip.com>
- This file is part of 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 <fcntl.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include "bfd.h"
- #include "sim/callback.h"
- #include "libiberty.h"
- #include "sim/sim.h"
- #include "sim-main.h"
- #include "sim-options.h"
- #include "sim-signal.h"
- #include "opcode/ft32.h"
- /*
- * FT32 is a Harvard architecture: RAM and code occupy
- * different address spaces.
- *
- * sim and gdb model FT32 memory by adding 0x800000 to RAM
- * addresses. This means that sim/gdb can treat all addresses
- * similarly.
- *
- * The address space looks like:
- *
- * 00000 start of code memory
- * 3ffff end of code memory
- * 800000 start of RAM
- * 80ffff end of RAM
- */
- #define RAM_BIAS 0x800000 /* Bias added to RAM addresses. */
- static unsigned long
- ft32_extract_unsigned_integer (unsigned char *addr, int len)
- {
- unsigned long retval;
- unsigned char *p;
- unsigned char *startaddr = (unsigned char *) addr;
- unsigned char *endaddr = startaddr + len;
- /* Start at the most significant end of the integer, and work towards
- the least significant. */
- retval = 0;
- for (p = endaddr; p > startaddr;)
- retval = (retval << 8) | * -- p;
- return retval;
- }
- static void
- ft32_store_unsigned_integer (unsigned char *addr, int len, unsigned long val)
- {
- unsigned char *p;
- unsigned char *startaddr = (unsigned char *)addr;
- unsigned char *endaddr = startaddr + len;
- for (p = startaddr; p < endaddr; p++)
- {
- *p = val & 0xff;
- val >>= 8;
- }
- }
- /*
- * Align EA according to its size DW.
- * The FT32 ignores the low bit of a 16-bit addresss,
- * and the low two bits of a 32-bit address.
- */
- static uint32_t ft32_align (uint32_t dw, uint32_t ea)
- {
- switch (dw)
- {
- case 1:
- ea &= ~1;
- break;
- case 2:
- ea &= ~3;
- break;
- default:
- break;
- }
- return ea;
- }
- /* Read an item from memory address EA, sized DW. */
- static uint32_t
- ft32_read_item (SIM_DESC sd, int dw, uint32_t ea)
- {
- sim_cpu *cpu = STATE_CPU (sd, 0);
- address_word cia = CPU_PC_GET (cpu);
- uint8_t byte[4];
- uint32_t r;
- ea = ft32_align (dw, ea);
- switch (dw) {
- case 0:
- return sim_core_read_aligned_1 (cpu, cia, read_map, ea);
- case 1:
- return sim_core_read_aligned_2 (cpu, cia, read_map, ea);
- case 2:
- return sim_core_read_aligned_4 (cpu, cia, read_map, ea);
- default:
- abort ();
- }
- }
- /* Write item V to memory address EA, sized DW. */
- static void
- ft32_write_item (SIM_DESC sd, int dw, uint32_t ea, uint32_t v)
- {
- sim_cpu *cpu = STATE_CPU (sd, 0);
- address_word cia = CPU_PC_GET (cpu);
- uint8_t byte[4];
- ea = ft32_align (dw, ea);
- switch (dw) {
- case 0:
- sim_core_write_aligned_1 (cpu, cia, write_map, ea, v);
- break;
- case 1:
- sim_core_write_aligned_2 (cpu, cia, write_map, ea, v);
- break;
- case 2:
- sim_core_write_aligned_4 (cpu, cia, write_map, ea, v);
- break;
- default:
- abort ();
- }
- }
- #define ILLEGAL() \
- sim_engine_halt (sd, cpu, NULL, insnpc, sim_signalled, SIM_SIGILL)
- static uint32_t cpu_mem_read (SIM_DESC sd, uint32_t dw, uint32_t ea)
- {
- sim_cpu *cpu = STATE_CPU (sd, 0);
- uint32_t insnpc = cpu->state.pc;
- uint32_t r;
- uint8_t byte[4];
- ea &= 0x1ffff;
- if (ea & ~0xffff)
- {
- /* Simulate some IO devices */
- switch (ea)
- {
- case 0x10000:
- return getchar ();
- case 0x1fff4:
- /* Read the simulator cycle timer. */
- return cpu->state.cycles / 100;
- default:
- sim_io_eprintf (sd, "Illegal IO read address %08x, pc %#x\n",
- ea, insnpc);
- ILLEGAL ();
- }
- }
- return ft32_read_item (sd, dw, RAM_BIAS + ea);
- }
- static void cpu_mem_write (SIM_DESC sd, uint32_t dw, uint32_t ea, uint32_t d)
- {
- sim_cpu *cpu = STATE_CPU (sd, 0);
- ea &= 0x1ffff;
- if (ea & 0x10000)
- {
- /* Simulate some IO devices */
- switch (ea)
- {
- case 0x10000:
- /* Console output */
- putchar (d & 0xff);
- break;
- case 0x1fc80:
- /* Unlock the PM write port */
- cpu->state.pm_unlock = (d == 0x1337f7d1);
- break;
- case 0x1fc84:
- /* Set the PM write address register */
- cpu->state.pm_addr = d;
- break;
- case 0x1fc88:
- if (cpu->state.pm_unlock)
- {
- /* Write to PM. */
- ft32_write_item (sd, dw, cpu->state.pm_addr, d);
- cpu->state.pm_addr += 4;
- }
- break;
- case 0x1fffc:
- /* Normal exit. */
- sim_engine_halt (sd, cpu, NULL, cpu->state.pc, sim_exited, cpu->state.regs[0]);
- break;
- case 0x1fff8:
- sim_io_printf (sd, "Debug write %08x\n", d);
- break;
- default:
- sim_io_eprintf (sd, "Unknown IO write %08x to to %08x\n", d, ea);
- }
- }
- else
- ft32_write_item (sd, dw, RAM_BIAS + ea, d);
- }
- #define GET_BYTE(ea) cpu_mem_read (sd, 0, (ea))
- #define PUT_BYTE(ea, d) cpu_mem_write (sd, 0, (ea), (d))
- /* LSBS (n) is a mask of the least significant N bits. */
- #define LSBS(n) ((1U << (n)) - 1)
- static void ft32_push (SIM_DESC sd, uint32_t v)
- {
- sim_cpu *cpu = STATE_CPU (sd, 0);
- cpu->state.regs[FT32_HARD_SP] -= 4;
- cpu->state.regs[FT32_HARD_SP] &= 0xffff;
- cpu_mem_write (sd, 2, cpu->state.regs[FT32_HARD_SP], v);
- }
- static uint32_t ft32_pop (SIM_DESC sd)
- {
- sim_cpu *cpu = STATE_CPU (sd, 0);
- uint32_t r = cpu_mem_read (sd, 2, cpu->state.regs[FT32_HARD_SP]);
- cpu->state.regs[FT32_HARD_SP] += 4;
- cpu->state.regs[FT32_HARD_SP] &= 0xffff;
- return r;
- }
- /* Extract the low SIZ bits of N as an unsigned number. */
- static int nunsigned (int siz, int n)
- {
- return n & LSBS (siz);
- }
- /* Extract the low SIZ bits of N as a signed number. */
- static int nsigned (int siz, int n)
- {
- int shift = (sizeof (int) * 8) - siz;
- return (n << shift) >> shift;
- }
- /* Signed division N / D, matching hw behavior for (MIN_INT, -1). */
- static uint32_t ft32sdiv (uint32_t n, uint32_t d)
- {
- if (n == 0x80000000UL && d == 0xffffffffUL)
- return 0x80000000UL;
- else
- return (uint32_t)((int)n / (int)d);
- }
- /* Signed modulus N % D, matching hw behavior for (MIN_INT, -1). */
- static uint32_t ft32smod (uint32_t n, uint32_t d)
- {
- if (n == 0x80000000UL && d == 0xffffffffUL)
- return 0;
- else
- return (uint32_t)((int)n % (int)d);
- }
- /* Circular rotate right N by B bits. */
- static uint32_t ror (uint32_t n, uint32_t b)
- {
- b &= 31;
- return (n >> b) | (n << (32 - b));
- }
- /* Implement the BINS machine instruction.
- See FT32 Programmer's Reference for details. */
- static uint32_t bins (uint32_t d, uint32_t f, uint32_t len, uint32_t pos)
- {
- uint32_t bitmask = LSBS (len) << pos;
- return (d & ~bitmask) | ((f << pos) & bitmask);
- }
- /* Implement the FLIP machine instruction.
- See FT32 Programmer's Reference for details. */
- static uint32_t flip (uint32_t x, uint32_t b)
- {
- if (b & 1)
- x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
- if (b & 2)
- x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
- if (b & 4)
- x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
- if (b & 8)
- x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
- if (b & 16)
- x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16;
- return x;
- }
- static void
- step_once (SIM_DESC sd)
- {
- sim_cpu *cpu = STATE_CPU (sd, 0);
- address_word cia = CPU_PC_GET (cpu);
- uint32_t inst;
- uint32_t dw;
- uint32_t cb;
- uint32_t r_d;
- uint32_t cr;
- uint32_t cv;
- uint32_t bt;
- uint32_t r_1;
- uint32_t rimm;
- uint32_t r_2;
- uint32_t k20;
- uint32_t pa;
- uint32_t aa;
- uint32_t k16;
- uint32_t k15;
- uint32_t al;
- uint32_t r_1v;
- uint32_t rimmv;
- uint32_t bit_pos;
- uint32_t bit_len;
- uint32_t upper;
- uint32_t insnpc;
- unsigned int sc[2];
- int isize;
- inst = ft32_read_item (sd, 2, cpu->state.pc);
- cpu->state.cycles += 1;
- if ((STATE_ARCHITECTURE (sd)->mach == bfd_mach_ft32b)
- && ft32_decode_shortcode (cpu->state.pc, inst, sc))
- {
- if ((cpu->state.pc & 3) == 0)
- inst = sc[0];
- else
- inst = sc[1];
- isize = 2;
- }
- else
- isize = 4;
- /* Handle "call 8" (which is FT32's "break" equivalent) here. */
- if (inst == 0x00340002)
- {
- sim_engine_halt (sd, cpu, NULL,
- cpu->state.pc,
- sim_stopped, SIM_SIGTRAP);
- goto escape;
- }
- dw = (inst >> FT32_FLD_DW_BIT) & LSBS (FT32_FLD_DW_SIZ);
- cb = (inst >> FT32_FLD_CB_BIT) & LSBS (FT32_FLD_CB_SIZ);
- r_d = (inst >> FT32_FLD_R_D_BIT) & LSBS (FT32_FLD_R_D_SIZ);
- cr = (inst >> FT32_FLD_CR_BIT) & LSBS (FT32_FLD_CR_SIZ);
- cv = (inst >> FT32_FLD_CV_BIT) & LSBS (FT32_FLD_CV_SIZ);
- bt = (inst >> FT32_FLD_BT_BIT) & LSBS (FT32_FLD_BT_SIZ);
- r_1 = (inst >> FT32_FLD_R_1_BIT) & LSBS (FT32_FLD_R_1_SIZ);
- rimm = (inst >> FT32_FLD_RIMM_BIT) & LSBS (FT32_FLD_RIMM_SIZ);
- r_2 = (inst >> FT32_FLD_R_2_BIT) & LSBS (FT32_FLD_R_2_SIZ);
- k20 = nsigned (20, (inst >> FT32_FLD_K20_BIT) & LSBS (FT32_FLD_K20_SIZ));
- pa = (inst >> FT32_FLD_PA_BIT) & LSBS (FT32_FLD_PA_SIZ);
- aa = (inst >> FT32_FLD_AA_BIT) & LSBS (FT32_FLD_AA_SIZ);
- k16 = (inst >> FT32_FLD_K16_BIT) & LSBS (FT32_FLD_K16_SIZ);
- k15 = (inst >> FT32_FLD_K15_BIT) & LSBS (FT32_FLD_K15_SIZ);
- if (k15 & 0x80)
- k15 ^= 0x7f00;
- if (k15 & 0x4000)
- k15 -= 0x8000;
- al = (inst >> FT32_FLD_AL_BIT) & LSBS (FT32_FLD_AL_SIZ);
- r_1v = cpu->state.regs[r_1];
- rimmv = (rimm & 0x400) ? nsigned (10, rimm) : cpu->state.regs[rimm & 0x1f];
- bit_pos = rimmv & 31;
- bit_len = 0xf & (rimmv >> 5);
- if (bit_len == 0)
- bit_len = 16;
- upper = (inst >> 27);
- insnpc = cpu->state.pc;
- cpu->state.pc += isize;
- switch (upper)
- {
- case FT32_PAT_TOC:
- case FT32_PAT_TOCI:
- {
- int take = (cr == 3) || ((1 & (cpu->state.regs[28 + cr] >> cb)) == cv);
- if (take)
- {
- cpu->state.cycles += 1;
- if (bt)
- ft32_push (sd, cpu->state.pc); /* this is a call. */
- if (upper == FT32_PAT_TOC)
- cpu->state.pc = pa << 2;
- else
- cpu->state.pc = cpu->state.regs[r_2];
- if (cpu->state.pc == 0x8)
- goto escape;
- }
- }
- break;
- case FT32_PAT_ALUOP:
- case FT32_PAT_CMPOP:
- {
- uint32_t result;
- switch (al)
- {
- case 0x0: result = r_1v + rimmv; break;
- case 0x1: result = ror (r_1v, rimmv); break;
- case 0x2: result = r_1v - rimmv; break;
- case 0x3: result = (r_1v << 10) | (1023 & rimmv); break;
- case 0x4: result = r_1v & rimmv; break;
- case 0x5: result = r_1v | rimmv; break;
- case 0x6: result = r_1v ^ rimmv; break;
- case 0x7: result = ~(r_1v ^ rimmv); break;
- case 0x8: result = r_1v << rimmv; break;
- case 0x9: result = r_1v >> rimmv; break;
- case 0xa: result = (int32_t)r_1v >> rimmv; break;
- case 0xb: result = bins (r_1v, rimmv >> 10, bit_len, bit_pos); break;
- case 0xc: result = nsigned (bit_len, r_1v >> bit_pos); break;
- case 0xd: result = nunsigned (bit_len, r_1v >> bit_pos); break;
- case 0xe: result = flip (r_1v, rimmv); break;
- default:
- sim_io_eprintf (sd, "Unhandled alu %#x\n", al);
- ILLEGAL ();
- }
- if (upper == FT32_PAT_ALUOP)
- cpu->state.regs[r_d] = result;
- else
- {
- uint32_t dwmask = 0;
- int dwsiz = 0;
- int zero;
- int sign;
- int ahi;
- int bhi;
- int overflow;
- int carry;
- int bit;
- uint64_t ra;
- uint64_t rb;
- int above;
- int greater;
- int greatereq;
- switch (dw)
- {
- case 0: dwsiz = 7; dwmask = 0xffU; break;
- case 1: dwsiz = 15; dwmask = 0xffffU; break;
- case 2: dwsiz = 31; dwmask = 0xffffffffU; break;
- }
- zero = (0 == (result & dwmask));
- sign = 1 & (result >> dwsiz);
- ahi = 1 & (r_1v >> dwsiz);
- bhi = 1 & (rimmv >> dwsiz);
- overflow = (sign != ahi) & (ahi == !bhi);
- bit = (dwsiz + 1);
- ra = r_1v & dwmask;
- rb = rimmv & dwmask;
- switch (al)
- {
- case 0x0: carry = 1 & ((ra + rb) >> bit); break;
- case 0x2: carry = 1 & ((ra - rb) >> bit); break;
- default: carry = 0; break;
- }
- above = (!carry & !zero);
- greater = (sign == overflow) & !zero;
- greatereq = (sign == overflow);
- cpu->state.regs[r_d] = (
- (above << 6) |
- (greater << 5) |
- (greatereq << 4) |
- (sign << 3) |
- (overflow << 2) |
- (carry << 1) |
- (zero << 0));
- }
- }
- break;
- case FT32_PAT_LDK:
- cpu->state.regs[r_d] = k20;
- break;
- case FT32_PAT_LPM:
- cpu->state.regs[r_d] = ft32_read_item (sd, dw, pa << 2);
- cpu->state.cycles += 1;
- break;
- case FT32_PAT_LPMI:
- cpu->state.regs[r_d] = ft32_read_item (sd, dw, cpu->state.regs[r_1] + k15);
- cpu->state.cycles += 1;
- break;
- case FT32_PAT_STA:
- cpu_mem_write (sd, dw, aa, cpu->state.regs[r_d]);
- break;
- case FT32_PAT_STI:
- cpu_mem_write (sd, dw, cpu->state.regs[r_d] + k15, cpu->state.regs[r_1]);
- break;
- case FT32_PAT_LDA:
- cpu->state.regs[r_d] = cpu_mem_read (sd, dw, aa);
- cpu->state.cycles += 1;
- break;
- case FT32_PAT_LDI:
- cpu->state.regs[r_d] = cpu_mem_read (sd, dw, cpu->state.regs[r_1] + k15);
- cpu->state.cycles += 1;
- break;
- case FT32_PAT_EXA:
- {
- uint32_t tmp;
- tmp = cpu_mem_read (sd, dw, aa);
- cpu_mem_write (sd, dw, aa, cpu->state.regs[r_d]);
- cpu->state.regs[r_d] = tmp;
- cpu->state.cycles += 1;
- }
- break;
- case FT32_PAT_EXI:
- {
- uint32_t tmp;
- tmp = cpu_mem_read (sd, dw, cpu->state.regs[r_1] + k15);
- cpu_mem_write (sd, dw, cpu->state.regs[r_1] + k15, cpu->state.regs[r_d]);
- cpu->state.regs[r_d] = tmp;
- cpu->state.cycles += 1;
- }
- break;
- case FT32_PAT_PUSH:
- ft32_push (sd, r_1v);
- break;
- case FT32_PAT_LINK:
- ft32_push (sd, cpu->state.regs[r_d]);
- cpu->state.regs[r_d] = cpu->state.regs[FT32_HARD_SP];
- cpu->state.regs[FT32_HARD_SP] -= k16;
- cpu->state.regs[FT32_HARD_SP] &= 0xffff;
- break;
- case FT32_PAT_UNLINK:
- cpu->state.regs[FT32_HARD_SP] = cpu->state.regs[r_d];
- cpu->state.regs[FT32_HARD_SP] &= 0xffff;
- cpu->state.regs[r_d] = ft32_pop (sd);
- break;
- case FT32_PAT_POP:
- cpu->state.cycles += 1;
- cpu->state.regs[r_d] = ft32_pop (sd);
- break;
- case FT32_PAT_RETURN:
- cpu->state.pc = ft32_pop (sd);
- break;
- case FT32_PAT_FFUOP:
- switch (al)
- {
- case 0x0:
- cpu->state.regs[r_d] = r_1v / rimmv;
- break;
- case 0x1:
- cpu->state.regs[r_d] = r_1v % rimmv;
- break;
- case 0x2:
- cpu->state.regs[r_d] = ft32sdiv (r_1v, rimmv);
- break;
- case 0x3:
- cpu->state.regs[r_d] = ft32smod (r_1v, rimmv);
- break;
- case 0x4:
- {
- /* strcmp instruction. */
- uint32_t a = r_1v;
- uint32_t b = rimmv;
- uint32_t i = 0;
- while ((GET_BYTE (a + i) != 0) &&
- (GET_BYTE (a + i) == GET_BYTE (b + i)))
- i++;
- cpu->state.regs[r_d] = GET_BYTE (a + i) - GET_BYTE (b + i);
- }
- break;
- case 0x5:
- {
- /* memcpy instruction. */
- uint32_t src = r_1v;
- uint32_t dst = cpu->state.regs[r_d];
- uint32_t i;
- for (i = 0; i < (rimmv & 0x7fff); i++)
- PUT_BYTE (dst + i, GET_BYTE (src + i));
- }
- break;
- case 0x6:
- {
- /* strlen instruction. */
- uint32_t src = r_1v;
- uint32_t i;
- for (i = 0; GET_BYTE (src + i) != 0; i++)
- ;
- cpu->state.regs[r_d] = i;
- }
- break;
- case 0x7:
- {
- /* memset instruction. */
- uint32_t dst = cpu->state.regs[r_d];
- uint32_t i;
- for (i = 0; i < (rimmv & 0x7fff); i++)
- PUT_BYTE (dst + i, r_1v);
- }
- break;
- case 0x8:
- cpu->state.regs[r_d] = r_1v * rimmv;
- break;
- case 0x9:
- cpu->state.regs[r_d] = ((uint64_t)r_1v * (uint64_t)rimmv) >> 32;
- break;
- case 0xa:
- {
- /* stpcpy instruction. */
- uint32_t src = r_1v;
- uint32_t dst = cpu->state.regs[r_d];
- uint32_t i;
- for (i = 0; GET_BYTE (src + i) != 0; i++)
- PUT_BYTE (dst + i, GET_BYTE (src + i));
- PUT_BYTE (dst + i, 0);
- cpu->state.regs[r_d] = dst + i;
- }
- break;
- case 0xe:
- {
- /* streamout instruction. */
- uint32_t i;
- uint32_t src = cpu->state.regs[r_1];
- for (i = 0; i < rimmv; i += (1 << dw))
- {
- cpu_mem_write (sd,
- dw,
- cpu->state.regs[r_d],
- cpu_mem_read (sd, dw, src));
- src += (1 << dw);
- }
- }
- break;
- default:
- sim_io_eprintf (sd, "Unhandled ffu %#x at %08x\n", al, insnpc);
- ILLEGAL ();
- }
- break;
- default:
- sim_io_eprintf (sd, "Unhandled pattern %d at %08x\n", upper, insnpc);
- ILLEGAL ();
- }
- cpu->state.num_i++;
- escape:
- ;
- }
- void
- sim_engine_run (SIM_DESC sd,
- int next_cpu_nr, /* ignore */
- int nr_cpus, /* ignore */
- int siggnal) /* ignore */
- {
- sim_cpu *cpu;
- SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
- cpu = STATE_CPU (sd, 0);
- while (1)
- {
- step_once (sd);
- if (sim_events_tick (sd))
- sim_events_process (sd);
- }
- }
- static uint32_t *
- ft32_lookup_register (SIM_CPU *cpu, int nr)
- {
- /* Handle the register number translation here.
- * Sim registers are 0-31.
- * Other tools (gcc, gdb) use:
- * 0 - fp
- * 1 - sp
- * 2 - r0
- * 31 - cc
- */
- if ((nr < 0) || (nr > 32))
- {
- sim_io_eprintf (CPU_STATE (cpu), "unknown register %i\n", nr);
- abort ();
- }
- switch (nr)
- {
- case FT32_FP_REGNUM:
- return &cpu->state.regs[FT32_HARD_FP];
- case FT32_SP_REGNUM:
- return &cpu->state.regs[FT32_HARD_SP];
- case FT32_CC_REGNUM:
- return &cpu->state.regs[FT32_HARD_CC];
- case FT32_PC_REGNUM:
- return &cpu->state.pc;
- default:
- return &cpu->state.regs[nr - 2];
- }
- }
- static int
- ft32_reg_store (SIM_CPU *cpu,
- int rn,
- unsigned char *memory,
- int length)
- {
- if (0 <= rn && rn <= 32)
- {
- if (length == 4)
- *ft32_lookup_register (cpu, rn) = ft32_extract_unsigned_integer (memory, 4);
- return 4;
- }
- else
- return 0;
- }
- static int
- ft32_reg_fetch (SIM_CPU *cpu,
- int rn,
- unsigned char *memory,
- int length)
- {
- if (0 <= rn && rn <= 32)
- {
- if (length == 4)
- ft32_store_unsigned_integer (memory, 4, *ft32_lookup_register (cpu, rn));
- return 4;
- }
- else
- return 0;
- }
- static sim_cia
- ft32_pc_get (SIM_CPU *cpu)
- {
- return cpu->state.pc;
- }
- static void
- ft32_pc_set (SIM_CPU *cpu, sim_cia newpc)
- {
- cpu->state.pc = newpc;
- }
- /* Cover function of sim_state_free to free the cpu buffers as well. */
- static void
- free_state (SIM_DESC sd)
- {
- 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 * const *argv)
- {
- char c;
- size_t i;
- SIM_DESC sd = sim_state_alloc (kind, cb);
- /* Set default options before parsing user options. */
- current_alignment = STRICT_ALIGNMENT;
- current_target_byte_order = BFD_ENDIAN_LITTLE;
- /* The cpu data is kept in a separately allocated chunk of memory. */
- if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
- {
- free_state (sd);
- return 0;
- }
- if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
- {
- free_state (sd);
- return 0;
- }
- /* The parser will print an error message for us, so we silently return. */
- if (sim_parse_args (sd, argv) != SIM_RC_OK)
- {
- free_state (sd);
- return 0;
- }
- /* Allocate external memory if none specified by user.
- Use address 4 here in case the user wanted address 0 unmapped. */
- if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0)
- {
- sim_do_command (sd, "memory region 0x00000000,0x40000");
- sim_do_command (sd, "memory region 0x800000,0x10000");
- }
- /* Check for/establish the reference program image. */
- if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
- {
- free_state (sd);
- return 0;
- }
- /* Configure/verify the target byte order and other runtime
- configuration options. */
- if (sim_config (sd) != SIM_RC_OK)
- {
- free_state (sd);
- return 0;
- }
- if (sim_post_argv_init (sd) != SIM_RC_OK)
- {
- free_state (sd);
- return 0;
- }
- /* CPU specific initialization. */
- for (i = 0; i < MAX_NR_PROCESSORS; ++i)
- {
- SIM_CPU *cpu = STATE_CPU (sd, i);
- CPU_REG_FETCH (cpu) = ft32_reg_fetch;
- CPU_REG_STORE (cpu) = ft32_reg_store;
- CPU_PC_FETCH (cpu) = ft32_pc_get;
- CPU_PC_STORE (cpu) = ft32_pc_set;
- }
- return sd;
- }
- SIM_RC
- sim_create_inferior (SIM_DESC sd,
- struct bfd *abfd,
- char * const *argv,
- char * const *env)
- {
- uint32_t addr;
- sim_cpu *cpu = STATE_CPU (sd, 0);
- host_callback *cb = STATE_CALLBACK (sd);
- /* Set the PC. */
- if (abfd != NULL)
- addr = bfd_get_start_address (abfd);
- else
- addr = 0;
- /* Standalone mode (i.e. `run`) will take care of the argv for us in
- sim_open() -> sim_parse_args(). But in debug mode (i.e. 'target sim'
- with `gdb`), we need to handle it because the user can change the
- argv on the fly via gdb's 'run'. */
- if (STATE_PROG_ARGV (sd) != argv)
- {
- freeargv (STATE_PROG_ARGV (sd));
- STATE_PROG_ARGV (sd) = dupargv (argv);
- }
- if (STATE_PROG_ENVP (sd) != env)
- {
- freeargv (STATE_PROG_ENVP (sd));
- STATE_PROG_ENVP (sd) = dupargv (env);
- }
- cb->argv = STATE_PROG_ARGV (sd);
- cb->envp = STATE_PROG_ENVP (sd);
- cpu->state.regs[FT32_HARD_SP] = addr;
- cpu->state.num_i = 0;
- cpu->state.cycles = 0;
- cpu->state.next_tick_cycle = 100000;
- return SIM_RC_OK;
- }
|