1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498 |
- /* Simulator for TI MSP430 and MSP430X
- Copyright (C) 2013-2022 Free Software Foundation, Inc.
- Contributed by Red Hat.
- Based on sim/bfin/bfin-sim.c which was contributed by Analog Devices, Inc.
- 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 <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <inttypes.h>
- #include <unistd.h>
- #include <assert.h>
- #include "opcode/msp430-decode.h"
- #include "sim-main.h"
- #include "sim-signal.h"
- #include "sim-syscall.h"
- static sim_cia
- msp430_pc_fetch (SIM_CPU *cpu)
- {
- return cpu->state.regs[0];
- }
- static void
- msp430_pc_store (SIM_CPU *cpu, sim_cia newpc)
- {
- cpu->state.regs[0] = newpc;
- }
- static int
- msp430_reg_fetch (SIM_CPU *cpu, int regno, unsigned char *buf, int len)
- {
- if (0 <= regno && regno < 16)
- {
- if (len == 2)
- {
- int val = cpu->state.regs[regno];
- buf[0] = val & 0xff;
- buf[1] = (val >> 8) & 0xff;
- return 0;
- }
- else if (len == 4)
- {
- int val = cpu->state.regs[regno];
- buf[0] = val & 0xff;
- buf[1] = (val >> 8) & 0xff;
- buf[2] = (val >> 16) & 0x0f; /* Registers are only 20 bits wide. */
- buf[3] = 0;
- return 0;
- }
- else
- return -1;
- }
- else
- return -1;
- }
- static int
- msp430_reg_store (SIM_CPU *cpu, int regno, unsigned char *buf, int len)
- {
- if (0 <= regno && regno < 16)
- {
- if (len == 2)
- {
- cpu->state.regs[regno] = (buf[1] << 8) | buf[0];
- return len;
- }
- if (len == 4)
- {
- cpu->state.regs[regno] = ((buf[2] << 16) & 0xf0000)
- | (buf[1] << 8) | buf[0];
- return len;
- }
- }
- return -1;
- }
- static inline void
- msp430_initialize_cpu (SIM_DESC sd, SIM_CPU *cpu)
- {
- memset (&cpu->state, 0, sizeof (cpu->state));
- }
- SIM_DESC
- sim_open (SIM_OPEN_KIND kind,
- struct host_callback_struct *callback,
- struct bfd *abfd,
- char * const *argv)
- {
- SIM_DESC sd = sim_state_alloc (kind, callback);
- char c;
- /* Initialise the simulator. */
- /* Set default options before parsing user options. */
- current_target_byte_order = BFD_ENDIAN_LITTLE;
- if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
- {
- sim_state_free (sd);
- return 0;
- }
- if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
- {
- sim_state_free (sd);
- return 0;
- }
- if (sim_parse_args (sd, argv) != SIM_RC_OK)
- {
- sim_state_free (sd);
- return 0;
- }
- CPU_PC_FETCH (MSP430_CPU (sd)) = msp430_pc_fetch;
- CPU_PC_STORE (MSP430_CPU (sd)) = msp430_pc_store;
- CPU_REG_FETCH (MSP430_CPU (sd)) = msp430_reg_fetch;
- CPU_REG_STORE (MSP430_CPU (sd)) = msp430_reg_store;
- /* Allocate memory if none specified by user.
- Note - these values match the memory regions in the libgloss/msp430/msp430[xl]-sim.ld scripts. */
- if (sim_core_read_buffer (sd, MSP430_CPU (sd), read_map, &c, 0x2, 1) == 0)
- sim_do_commandf (sd, "memory-region 0,0x20"); /* Needed by the GDB testsuite. */
- if (sim_core_read_buffer (sd, MSP430_CPU (sd), read_map, &c, 0x500, 1) == 0)
- sim_do_commandf (sd, "memory-region 0x500,0xfac0"); /* RAM and/or ROM */
- if (sim_core_read_buffer (sd, MSP430_CPU (sd), read_map, &c, 0xfffe, 1) == 0)
- sim_do_commandf (sd, "memory-region 0xffc0,0x40"); /* VECTORS. */
- if (sim_core_read_buffer (sd, MSP430_CPU (sd), read_map, &c, 0x10000, 1) == 0)
- sim_do_commandf (sd, "memory-region 0x10000,0x80000"); /* HIGH FLASH RAM. */
- if (sim_core_read_buffer (sd, MSP430_CPU (sd), read_map, &c, 0x90000, 1) == 0)
- sim_do_commandf (sd, "memory-region 0x90000,0x70000"); /* HIGH ROM. */
- /* Check for/establish the a reference program image. */
- if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
- {
- sim_state_free (sd);
- return 0;
- }
- /* Establish any remaining configuration options. */
- if (sim_config (sd) != SIM_RC_OK)
- {
- sim_state_free (sd);
- return 0;
- }
- if (sim_post_argv_init (sd) != SIM_RC_OK)
- {
- sim_state_free (sd);
- return 0;
- }
- /* CPU specific initialization. */
- assert (MAX_NR_PROCESSORS == 1);
- msp430_initialize_cpu (sd, MSP430_CPU (sd));
- MSP430_CPU (sd)->state.cio_breakpoint = trace_sym_value (sd, "C$$IO$$");
- MSP430_CPU (sd)->state.cio_buffer = trace_sym_value (sd, "__CIOBUF__");
- if (MSP430_CPU (sd)->state.cio_buffer == -1)
- MSP430_CPU (sd)->state.cio_buffer = trace_sym_value (sd, "_CIOBUF_");
- return sd;
- }
- SIM_RC
- sim_create_inferior (SIM_DESC sd,
- struct bfd *abfd,
- char * const *argv,
- char * const *env)
- {
- unsigned char resetv[2];
- int c;
- int new_pc;
- /* Set the PC to the default reset vector if available. */
- c = sim_core_read_buffer (sd, MSP430_CPU (sd), read_map, resetv, 0xfffe, 2);
- new_pc = resetv[0] + 256 * resetv[1];
- /* If the reset vector isn't initialized, then use the ELF entry. */
- if (abfd != NULL && !new_pc)
- new_pc = bfd_get_start_address (abfd);
- sim_pc_set (MSP430_CPU (sd), new_pc);
- msp430_pc_store (MSP430_CPU (sd), new_pc);
- return SIM_RC_OK;
- }
- typedef struct
- {
- SIM_DESC sd;
- int gb_addr;
- } Get_Byte_Local_Data;
- static int
- msp430_getbyte (void *vld)
- {
- Get_Byte_Local_Data *ld = (Get_Byte_Local_Data *)vld;
- char buf[1];
- SIM_DESC sd = ld->sd;
- sim_core_read_buffer (sd, MSP430_CPU (sd), read_map, buf, ld->gb_addr, 1);
- ld->gb_addr ++;
- return buf[0];
- }
- #define REG(N) MSP430_CPU (sd)->state.regs[(N)]
- #define PC REG(MSR_PC)
- #define SP REG(MSR_SP)
- #define SR REG(MSR_SR)
- static const char *
- register_names[] =
- {
- "PC", "SP", "SR", "CG", "R4", "R5", "R6", "R7", "R8",
- "R9", "R10", "R11", "R12", "R13", "R14", "R15"
- };
- static void
- trace_reg_put (SIM_DESC sd, int n, unsigned int v)
- {
- TRACE_REGISTER (MSP430_CPU (sd), "PUT: %#x -> %s", v, register_names[n]);
- REG (n) = v;
- }
- static unsigned int
- trace_reg_get (SIM_DESC sd, int n)
- {
- TRACE_REGISTER (MSP430_CPU (sd), "GET: %s -> %#x", register_names[n], REG (n));
- return REG (n);
- }
- #define REG_PUT(N,V) trace_reg_put (sd, N, V)
- #define REG_GET(N) trace_reg_get (sd, N)
- /* Hardware multiply (and accumulate) support. */
- static unsigned int
- zero_ext (unsigned int v, unsigned int bits)
- {
- v &= ((1 << bits) - 1);
- return v;
- }
- static signed long long
- sign_ext (signed long long v, unsigned int bits)
- {
- signed long long sb = 1LL << (bits-1); /* Sign bit. */
- signed long long mb = (1LL << (bits-1)) - 1LL; /* Mantissa bits. */
- if (v & sb)
- v = v | ~mb;
- else
- v = v & mb;
- return v;
- }
- static int
- get_op (SIM_DESC sd, MSP430_Opcode_Decoded *opc, int n)
- {
- MSP430_Opcode_Operand *op = opc->op + n;
- int rv = 0;
- int addr;
- unsigned char buf[4];
- int incval = 0;
- switch (op->type)
- {
- case MSP430_Operand_Immediate:
- rv = op->addend;
- break;
- case MSP430_Operand_Register:
- rv = REG_GET (op->reg);
- break;
- case MSP430_Operand_Indirect:
- case MSP430_Operand_Indirect_Postinc:
- addr = op->addend;
- if (op->reg != MSR_None)
- {
- int reg = REG_GET (op->reg);
- int sign = opc->ofs_430x ? 20 : 16;
- /* Index values are signed. */
- if (addr & (1 << (sign - 1)))
- addr |= -(1 << sign);
- addr += reg;
- /* For MSP430 instructions the sum is limited to 16 bits if the
- address in the index register is less than 64k even if we are
- running on an MSP430X CPU. This is for MSP430 compatibility. */
- if (reg < 0x10000 && ! opc->ofs_430x)
- {
- if (addr >= 0x10000)
- fprintf (stderr, " XXX WRAPPING ADDRESS %x on read\n", addr);
- addr &= 0xffff;
- }
- }
- addr &= 0xfffff;
- switch (opc->size)
- {
- case 8:
- sim_core_read_buffer (sd, MSP430_CPU (sd), read_map, buf, addr, 1);
- rv = buf[0];
- break;
- case 16:
- sim_core_read_buffer (sd, MSP430_CPU (sd), read_map, buf, addr, 2);
- rv = buf[0] | (buf[1] << 8);
- break;
- case 20:
- case 32:
- sim_core_read_buffer (sd, MSP430_CPU (sd), read_map, buf, addr, 4);
- rv = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
- break;
- default:
- assert (! opc->size);
- break;
- }
- #if 0
- /* Hack - MSP430X5438 serial port status register. */
- if (addr == 0x5dd)
- rv = 2;
- #endif
- if ((addr >= 0x130 && addr <= 0x15B)
- || (addr >= 0x4C0 && addr <= 0x4EB))
- {
- switch (addr)
- {
- case 0x4CA:
- case 0x13A:
- switch (HWMULT (sd, hwmult_type))
- {
- case UNSIGN_MAC_32:
- case UNSIGN_32:
- rv = zero_ext (HWMULT (sd, hwmult_result), 16);
- break;
- case SIGN_MAC_32:
- case SIGN_32:
- rv = sign_ext (HWMULT (sd, hwmult_signed_result), 16);
- break;
- }
- break;
- case 0x4CC:
- case 0x13C:
- switch (HWMULT (sd, hwmult_type))
- {
- case UNSIGN_MAC_32:
- case UNSIGN_32:
- rv = zero_ext (HWMULT (sd, hwmult_result) >> 16, 16);
- break;
- case SIGN_MAC_32:
- case SIGN_32:
- rv = sign_ext (HWMULT (sd, hwmult_signed_result) >> 16, 16);
- break;
- }
- break;
- case 0x4CE:
- case 0x13E:
- switch (HWMULT (sd, hwmult_type))
- {
- case UNSIGN_32:
- rv = 0;
- break;
- case SIGN_32:
- rv = HWMULT (sd, hwmult_signed_result) < 0 ? -1 : 0;
- break;
- case UNSIGN_MAC_32:
- rv = 0; /* FIXME: Should be carry of last accumulate. */
- break;
- case SIGN_MAC_32:
- rv = HWMULT (sd, hwmult_signed_accumulator) < 0 ? -1 : 0;
- break;
- }
- break;
- case 0x4E4:
- case 0x154:
- rv = zero_ext (HWMULT (sd, hw32mult_result), 16);
- break;
- case 0x4E6:
- case 0x156:
- rv = zero_ext (HWMULT (sd, hw32mult_result) >> 16, 16);
- break;
- case 0x4E8:
- case 0x158:
- rv = zero_ext (HWMULT (sd, hw32mult_result) >> 32, 16);
- break;
- case 0x4EA:
- case 0x15A:
- switch (HWMULT (sd, hw32mult_type))
- {
- case UNSIGN_64: rv = zero_ext (HWMULT (sd, hw32mult_result) >> 48, 16); break;
- case SIGN_64: rv = sign_ext (HWMULT (sd, hw32mult_result) >> 48, 16); break;
- }
- break;
- default:
- fprintf (stderr, "unimplemented HW MULT read from %x!\n", addr);
- break;
- }
- }
- TRACE_MEMORY (MSP430_CPU (sd), "GET: [%#x].%d -> %#x", addr, opc->size,
- rv);
- break;
- default:
- fprintf (stderr, "invalid operand %d type %d\n", n, op->type);
- abort ();
- }
- switch (opc->size)
- {
- case 8:
- rv &= 0xff;
- incval = 1;
- break;
- case 16:
- rv &= 0xffff;
- incval = 2;
- break;
- case 20:
- rv &= 0xfffff;
- incval = 4;
- break;
- case 32:
- rv &= 0xffffffff;
- incval = 4;
- break;
- }
- if (op->type == MSP430_Operand_Indirect_Postinc)
- REG_PUT (op->reg, REG_GET (op->reg) + incval);
- return rv;
- }
- static int
- put_op (SIM_DESC sd, MSP430_Opcode_Decoded *opc, int n, int val)
- {
- MSP430_Opcode_Operand *op = opc->op + n;
- int rv = 0;
- int addr;
- unsigned char buf[4];
- int incval = 0;
- switch (opc->size)
- {
- case 8:
- val &= 0xff;
- break;
- case 16:
- val &= 0xffff;
- break;
- case 20:
- val &= 0xfffff;
- break;
- case 32:
- val &= 0xffffffff;
- break;
- }
- switch (op->type)
- {
- case MSP430_Operand_Register:
- REG (op->reg) = val;
- REG_PUT (op->reg, val);
- break;
- case MSP430_Operand_Indirect:
- case MSP430_Operand_Indirect_Postinc:
- addr = op->addend;
- if (op->reg != MSR_None)
- {
- int reg = REG_GET (op->reg);
- int sign = opc->ofs_430x ? 20 : 16;
- /* Index values are signed. */
- if (addr & (1 << (sign - 1)))
- addr |= -(1 << sign);
- addr += reg;
- /* For MSP430 instructions the sum is limited to 16 bits if the
- address in the index register is less than 64k even if we are
- running on an MSP430X CPU. This is for MSP430 compatibility. */
- if (reg < 0x10000 && ! opc->ofs_430x)
- {
- if (addr >= 0x10000)
- fprintf (stderr, " XXX WRAPPING ADDRESS %x on write\n", addr);
-
- addr &= 0xffff;
- }
- }
- addr &= 0xfffff;
- TRACE_MEMORY (MSP430_CPU (sd), "PUT: [%#x].%d <- %#x", addr, opc->size,
- val);
- #if 0
- /* Hack - MSP430X5438 serial port transmit register. */
- if (addr == 0x5ce)
- putchar (val);
- #endif
- if ((addr >= 0x130 && addr <= 0x15B)
- || (addr >= 0x4C0 && addr <= 0x4EB))
- {
- signed int a,b;
- /* Hardware Multiply emulation. */
- assert (opc->size == 16);
- switch (addr)
- {
- case 0x4C0:
- case 0x130:
- HWMULT (sd, hwmult_op1) = val;
- HWMULT (sd, hwmult_type) = UNSIGN_32;
- break;
- case 0x4C2:
- case 0x132:
- HWMULT (sd, hwmult_op1) = val;
- HWMULT (sd, hwmult_type) = SIGN_32;
- break;
- case 0x4C4:
- case 0x134:
- HWMULT (sd, hwmult_op1) = val;
- HWMULT (sd, hwmult_type) = UNSIGN_MAC_32;
- break;
- case 0x4C6:
- case 0x136:
- HWMULT (sd, hwmult_op1) = val;
- HWMULT (sd, hwmult_type) = SIGN_MAC_32;
- break;
- case 0x4C8:
- case 0x138:
- HWMULT (sd, hwmult_op2) = val;
- switch (HWMULT (sd, hwmult_type))
- {
- case UNSIGN_32:
- a = HWMULT (sd, hwmult_op1);
- b = HWMULT (sd, hwmult_op2);
- /* For unsigned 32-bit multiplication of 16-bit operands, an
- explicit cast is required to prevent any implicit
- sign-extension. */
- HWMULT (sd, hwmult_result) = (uint32_t) a * (uint32_t) b;
- HWMULT (sd, hwmult_signed_result) = a * b;
- HWMULT (sd, hwmult_accumulator) = HWMULT (sd, hwmult_signed_accumulator) = 0;
- break;
- case SIGN_32:
- a = sign_ext (HWMULT (sd, hwmult_op1), 16);
- b = sign_ext (HWMULT (sd, hwmult_op2), 16);
- HWMULT (sd, hwmult_signed_result) = a * b;
- HWMULT (sd, hwmult_result) = (uint32_t) a * (uint32_t) b;
- HWMULT (sd, hwmult_accumulator) = HWMULT (sd, hwmult_signed_accumulator) = 0;
- break;
- case UNSIGN_MAC_32:
- a = HWMULT (sd, hwmult_op1);
- b = HWMULT (sd, hwmult_op2);
- HWMULT (sd, hwmult_accumulator)
- += (uint32_t) a * (uint32_t) b;
- HWMULT (sd, hwmult_signed_accumulator) += a * b;
- HWMULT (sd, hwmult_result) = HWMULT (sd, hwmult_accumulator);
- HWMULT (sd, hwmult_signed_result) = HWMULT (sd, hwmult_signed_accumulator);
- break;
- case SIGN_MAC_32:
- a = sign_ext (HWMULT (sd, hwmult_op1), 16);
- b = sign_ext (HWMULT (sd, hwmult_op2), 16);
- HWMULT (sd, hwmult_accumulator)
- += (uint32_t) a * (uint32_t) b;
- HWMULT (sd, hwmult_signed_accumulator) += a * b;
- HWMULT (sd, hwmult_result) = HWMULT (sd, hwmult_accumulator);
- HWMULT (sd, hwmult_signed_result) = HWMULT (sd, hwmult_signed_accumulator);
- break;
- }
- break;
- case 0x4CA:
- case 0x13A:
- /* Copy into LOW result... */
- switch (HWMULT (sd, hwmult_type))
- {
- case UNSIGN_MAC_32:
- case UNSIGN_32:
- HWMULT (sd, hwmult_accumulator) = HWMULT (sd, hwmult_result) = zero_ext (val, 16);
- HWMULT (sd, hwmult_signed_accumulator) = sign_ext (val, 16);
- break;
- case SIGN_MAC_32:
- case SIGN_32:
- HWMULT (sd, hwmult_signed_accumulator) = HWMULT (sd, hwmult_result) = sign_ext (val, 16);
- HWMULT (sd, hwmult_accumulator) = zero_ext (val, 16);
- break;
- }
- break;
-
- case 0x4D0:
- case 0x140:
- HWMULT (sd, hw32mult_op1) = val;
- HWMULT (sd, hw32mult_type) = UNSIGN_64;
- break;
- case 0x4D2:
- case 0x142:
- HWMULT (sd, hw32mult_op1) = (HWMULT (sd, hw32mult_op1) & 0xFFFF) | (val << 16);
- break;
- case 0x4D4:
- case 0x144:
- HWMULT (sd, hw32mult_op1) = val;
- HWMULT (sd, hw32mult_type) = SIGN_64;
- break;
- case 0x4D6:
- case 0x146:
- HWMULT (sd, hw32mult_op1) = (HWMULT (sd, hw32mult_op1) & 0xFFFF) | (val << 16);
- break;
- case 0x4E0:
- case 0x150:
- HWMULT (sd, hw32mult_op2) = val;
- break;
- case 0x4E2:
- case 0x152:
- HWMULT (sd, hw32mult_op2) = (HWMULT (sd, hw32mult_op2) & 0xFFFF) | (val << 16);
- switch (HWMULT (sd, hw32mult_type))
- {
- case UNSIGN_64:
- HWMULT (sd, hw32mult_result)
- = (uint64_t) HWMULT (sd, hw32mult_op1)
- * (uint64_t) HWMULT (sd, hw32mult_op2);
- break;
- case SIGN_64:
- HWMULT (sd, hw32mult_result)
- = sign_ext (HWMULT (sd, hw32mult_op1), 32)
- * sign_ext (HWMULT (sd, hw32mult_op2), 32);
- break;
- }
- break;
- default:
- fprintf (stderr, "unimplemented HW MULT write to %x!\n", addr);
- break;
- }
- }
- switch (opc->size)
- {
- case 8:
- buf[0] = val;
- sim_core_write_buffer (sd, MSP430_CPU (sd), write_map, buf, addr, 1);
- break;
- case 16:
- buf[0] = val;
- buf[1] = val >> 8;
- sim_core_write_buffer (sd, MSP430_CPU (sd), write_map, buf, addr, 2);
- break;
- case 20:
- case 32:
- buf[0] = val;
- buf[1] = val >> 8;
- buf[2] = val >> 16;
- buf[3] = val >> 24;
- sim_core_write_buffer (sd, MSP430_CPU (sd), write_map, buf, addr, 4);
- break;
- default:
- assert (! opc->size);
- break;
- }
- break;
- default:
- fprintf (stderr, "invalid operand %d type %d\n", n, op->type);
- abort ();
- }
- switch (opc->size)
- {
- case 8:
- rv &= 0xff;
- incval = 1;
- break;
- case 16:
- rv &= 0xffff;
- incval = 2;
- break;
- case 20:
- rv &= 0xfffff;
- incval = 4;
- break;
- case 32:
- rv &= 0xffffffff;
- incval = 4;
- break;
- }
- if (op->type == MSP430_Operand_Indirect_Postinc)
- {
- int new_val = REG_GET (op->reg) + incval;
- /* SP is always word-aligned. */
- if (op->reg == MSR_SP && (new_val & 1))
- new_val ++;
- REG_PUT (op->reg, new_val);
- }
- return rv;
- }
- static void
- mem_put_val (SIM_DESC sd, int addr, int val, int bits)
- {
- MSP430_Opcode_Decoded opc;
- opc.size = bits;
- opc.op[0].type = MSP430_Operand_Indirect;
- opc.op[0].addend = addr;
- opc.op[0].reg = MSR_None;
- put_op (sd, &opc, 0, val);
- }
- static int
- mem_get_val (SIM_DESC sd, int addr, int bits)
- {
- MSP430_Opcode_Decoded opc;
- opc.size = bits;
- opc.op[0].type = MSP430_Operand_Indirect;
- opc.op[0].addend = addr;
- opc.op[0].reg = MSR_None;
- return get_op (sd, &opc, 0);
- }
- #define CIO_OPEN (0xF0)
- #define CIO_CLOSE (0xF1)
- #define CIO_READ (0xF2)
- #define CIO_WRITE (0xF3)
- #define CIO_LSEEK (0xF4)
- #define CIO_UNLINK (0xF5)
- #define CIO_GETENV (0xF6)
- #define CIO_RENAME (0xF7)
- #define CIO_GETTIME (0xF8)
- #define CIO_GETCLK (0xF9)
- #define CIO_SYNC (0xFF)
- #define CIO_I(n) (parms[(n)] + parms[(n)+1] * 256)
- #define CIO_L(n) (parms[(n)] + parms[(n)+1] * 256 \
- + parms[(n)+2] * 65536 + parms[(n)+3] * 16777216)
- static void
- msp430_cio (SIM_DESC sd)
- {
- /* A block of data at __CIOBUF__ describes the I/O operation to
- perform. */
- unsigned char raw_parms[13];
- unsigned char parms[8];
- long length;
- int command;
- unsigned char buffer[512];
- long ret_buflen = 0;
- long fd, addr, len, rv;
- sim_core_read_buffer (sd, MSP430_CPU (sd), 0, parms,
- MSP430_CPU (sd)->state.cio_buffer, 5);
- length = CIO_I (0);
- command = parms[2];
- sim_core_read_buffer (sd, MSP430_CPU (sd), 0, parms,
- MSP430_CPU (sd)->state.cio_buffer + 3, 8);
- sim_core_read_buffer (sd, MSP430_CPU (sd), 0, buffer,
- MSP430_CPU (sd)->state.cio_buffer + 11, length);
- switch (command)
- {
- case CIO_WRITE:
- fd = CIO_I (0);
- len = CIO_I (2);
- rv = write (fd, buffer, len);
- parms[0] = rv & 0xff;
- parms[1] = rv >> 8;
- break;
- }
- sim_core_write_buffer (sd, MSP430_CPU (sd), 0, parms,
- MSP430_CPU (sd)->state.cio_buffer + 4, 8);
- if (ret_buflen)
- sim_core_write_buffer (sd, MSP430_CPU (sd), 0, buffer,
- MSP430_CPU (sd)->state.cio_buffer + 12, ret_buflen);
- }
- #define SRC get_op (sd, opcode, 1)
- #define DSRC get_op (sd, opcode, 0)
- #define DEST(V) put_op (sd, opcode, 0, (V))
- #define DO_ALU(OP,SOP,MORE) \
- { \
- int s1 = DSRC; \
- int s2 = SRC; \
- int result = s1 OP s2 MORE; \
- TRACE_ALU (MSP430_CPU (sd), "ALU: %#x %s %#x %s = %#x", s1, SOP, \
- s2, #MORE, result); \
- DEST (result); \
- }
- #define SIGN (1 << (opcode->size - 1))
- #define POS(x) (((x) & SIGN) ? 0 : 1)
- #define NEG(x) (((x) & SIGN) ? 1 : 0)
- #define SX(v) sign_ext (v, opcode->size)
- #define ZX(v) zero_ext (v, opcode->size)
- static char *
- flags2string (int f)
- {
- static char buf[2][6];
- static int bi = 0;
- char *bp = buf[bi];
- bi = (bi + 1) % 2;
- bp[0] = f & MSP430_FLAG_V ? 'V' : '-';
- bp[1] = f & MSP430_FLAG_N ? 'N' : '-';
- bp[2] = f & MSP430_FLAG_Z ? 'Z' : '-';
- bp[3] = f & MSP430_FLAG_C ? 'C' : '-';
- bp[4] = 0;
- return bp;
- }
- /* Random number that won't show up in our usual logic. */
- #define MAGIC_OVERFLOW 0x55000F
- static void
- do_flags (SIM_DESC sd,
- MSP430_Opcode_Decoded *opcode,
- int vnz_val, /* Signed result. */
- int carry,
- int overflow)
- {
- int f = SR;
- int new_f = 0;
- int signbit = 1 << (opcode->size - 1);
- f &= ~opcode->flags_0;
- f &= ~opcode->flags_set;
- f |= opcode->flags_1;
- if (vnz_val & signbit)
- new_f |= MSP430_FLAG_N;
- if (! (vnz_val & ((signbit << 1) - 1)))
- new_f |= MSP430_FLAG_Z;
- if (overflow == MAGIC_OVERFLOW)
- {
- if (vnz_val != SX (vnz_val))
- new_f |= MSP430_FLAG_V;
- }
- else
- if (overflow)
- new_f |= MSP430_FLAG_V;
- if (carry)
- new_f |= MSP430_FLAG_C;
- new_f = f | (new_f & opcode->flags_set);
- if (SR != new_f)
- TRACE_ALU (MSP430_CPU (sd), "FLAGS: %s -> %s", flags2string (SR),
- flags2string (new_f));
- else
- TRACE_ALU (MSP430_CPU (sd), "FLAGS: %s", flags2string (new_f));
- SR = new_f;
- }
- #define FLAGS(vnz,c) do_flags (sd, opcode, vnz, c, MAGIC_OVERFLOW)
- #define FLAGSV(vnz,c,v) do_flags (sd, opcode, vnz, c, v)
- /* These two assume unsigned 16-bit (four digit) words.
- Mask off unwanted bits for byte operations. */
- static int
- bcd_to_binary (int v)
- {
- int r = ( ((v >> 0) & 0xf) * 1
- + ((v >> 4) & 0xf) * 10
- + ((v >> 8) & 0xf) * 100
- + ((v >> 12) & 0xf) * 1000);
- return r;
- }
- static int
- binary_to_bcd (int v)
- {
- int r = ( ((v / 1) % 10) << 0
- | ((v / 10) % 10) << 4
- | ((v / 100) % 10) << 8
- | ((v / 1000) % 10) << 12);
- return r;
- }
- static const char *
- cond_string (int cond)
- {
- switch (cond)
- {
- case MSC_nz:
- return "NZ";
- case MSC_z:
- return "Z";
- case MSC_nc:
- return "NC";
- case MSC_c:
- return "C";
- case MSC_n:
- return "N";
- case MSC_ge:
- return "GE";
- case MSC_l:
- return "L";
- case MSC_true:
- return "MP";
- default:
- return "??";
- }
- }
- /* Checks a CALL to address CALL_ADDR. If this is a special
- syscall address then the call is simulated and non-zero is
- returned. Otherwise 0 is returned. */
- static int
- maybe_perform_syscall (SIM_DESC sd, int call_addr)
- {
- if (call_addr == 0x00160)
- {
- int i;
- for (i = 0; i < 16; i++)
- {
- if (i % 4 == 0)
- fprintf (stderr, "\t");
- fprintf (stderr, "R%-2d %05x ", i, MSP430_CPU (sd)->state.regs[i]);
- if (i % 4 == 3)
- {
- int sp = SP + (3 - (i / 4)) * 2;
- unsigned char buf[2];
- sim_core_read_buffer (sd, MSP430_CPU (sd), read_map, buf, sp, 2);
- fprintf (stderr, "\tSP%+d: %04x", sp - SP,
- buf[0] + buf[1] * 256);
- if (i / 4 == 0)
- {
- int flags = SR;
- fprintf (stderr, flags & 0x100 ? " V" : " -");
- fprintf (stderr, flags & 0x004 ? "N" : "-");
- fprintf (stderr, flags & 0x002 ? "Z" : "-");
- fprintf (stderr, flags & 0x001 ? "C" : "-");
- }
- fprintf (stderr, "\n");
- }
- }
- return 1;
- }
- if ((call_addr & ~0x3f) == 0x00180)
- {
- /* Syscall! */
- int arg1, arg2, arg3, arg4;
- int syscall_num = call_addr & 0x3f;
- /* syscall_num == 2 is used for the variadic function "open".
- The arguments are set up differently for variadic functions.
- See slaa534.pdf distributed by TI. */
- if (syscall_num == 2)
- {
- arg1 = MSP430_CPU (sd)->state.regs[12];
- arg2 = mem_get_val (sd, SP, 16);
- arg3 = mem_get_val (sd, SP + 2, 16);
- arg4 = mem_get_val (sd, SP + 4, 16);
- }
- else
- {
- arg1 = MSP430_CPU (sd)->state.regs[12];
- arg2 = MSP430_CPU (sd)->state.regs[13];
- arg3 = MSP430_CPU (sd)->state.regs[14];
- arg4 = MSP430_CPU (sd)->state.regs[15];
- }
- MSP430_CPU (sd)->state.regs[12] = sim_syscall (MSP430_CPU (sd),
- syscall_num, arg1, arg2,
- arg3, arg4);
- return 1;
- }
- return 0;
- }
- static void
- msp430_step_once (SIM_DESC sd)
- {
- Get_Byte_Local_Data ld;
- unsigned char buf[100];
- int i;
- int opsize;
- unsigned int opcode_pc;
- MSP430_Opcode_Decoded opcode_buf;
- MSP430_Opcode_Decoded *opcode = &opcode_buf;
- int s1, s2, result;
- int u1 = 0, u2, uresult;
- int c = 0, reg;
- int sp;
- int carry_to_use;
- int n_repeats;
- int rept;
- int op_bytes = 0, op_bits;
- PC &= 0xfffff;
- opcode_pc = PC;
- if (opcode_pc < 0x10)
- {
- fprintf (stderr, "Fault: PC(%#x) is less than 0x10\n", opcode_pc);
- sim_engine_halt (sd, MSP430_CPU (sd), NULL,
- MSP430_CPU (sd)->state.regs[0],
- sim_exited, -1);
- return;
- }
- if (PC == MSP430_CPU (sd)->state.cio_breakpoint
- && STATE_OPEN_KIND (sd) != SIM_OPEN_DEBUG)
- msp430_cio (sd);
- ld.sd = sd;
- ld.gb_addr = PC;
- opsize = msp430_decode_opcode (MSP430_CPU (sd)->state.regs[0],
- opcode, msp430_getbyte, &ld);
- PC += opsize;
- if (opsize <= 0)
- {
- fprintf (stderr, "Fault: undecodable opcode at %#x\n", opcode_pc);
- sim_engine_halt (sd, MSP430_CPU (sd), NULL,
- MSP430_CPU (sd)->state.regs[0],
- sim_exited, -1);
- return;
- }
- if (opcode->repeat_reg)
- n_repeats = (MSP430_CPU (sd)->state.regs[opcode->repeats] & 0x000f) + 1;
- else
- n_repeats = opcode->repeats + 1;
- op_bits = opcode->size;
- switch (op_bits)
- {
- case 8:
- op_bytes = 1;
- break;
- case 16:
- op_bytes = 2;
- break;
- case 20:
- case 32:
- op_bytes = 4;
- break;
- }
- if (TRACE_ANY_P (MSP430_CPU (sd)))
- trace_prefix (sd, MSP430_CPU (sd), NULL_CIA, opcode_pc,
- TRACE_LINENUM_P (MSP430_CPU (sd)), NULL, 0, " ");
- TRACE_DISASM (MSP430_CPU (sd), opcode_pc);
- carry_to_use = 0;
- switch (opcode->id)
- {
- case MSO_unknown:
- break;
- /* Double-operand instructions. */
- case MSO_mov:
- if (opcode->n_bytes == 2
- && opcode->op[0].type == MSP430_Operand_Register
- && opcode->op[0].reg == MSR_CG
- && opcode->op[1].type == MSP430_Operand_Immediate
- && opcode->op[1].addend == 0
- /* A 16-bit write of #0 is a NOP; an 8-bit write is a BRK. */
- && opcode->size == 8)
- {
- /* This is the designated software breakpoint instruction. */
- PC -= opsize;
- sim_engine_halt (sd, MSP430_CPU (sd), NULL,
- MSP430_CPU (sd)->state.regs[0],
- sim_stopped, SIM_SIGTRAP);
- }
- else
- {
- /* Otherwise, do the move. */
- for (rept = 0; rept < n_repeats; rept ++)
- {
- DEST (SRC);
- }
- }
- break;
- case MSO_addc:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- carry_to_use = (SR & MSP430_FLAG_C) ? 1 : 0;
- u1 = DSRC;
- u2 = SRC;
- s1 = SX (u1);
- s2 = SX (u2);
- uresult = u1 + u2 + carry_to_use;
- result = s1 + s2 + carry_to_use;
- TRACE_ALU (MSP430_CPU (sd), "ADDC: %#x + %#x + %d = %#x",
- u1, u2, carry_to_use, uresult);
- DEST (result);
- FLAGS (result, uresult != ZX (uresult));
- }
- break;
- case MSO_add:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- u1 = DSRC;
- u2 = SRC;
- s1 = SX (u1);
- s2 = SX (u2);
- uresult = u1 + u2;
- result = s1 + s2;
- TRACE_ALU (MSP430_CPU (sd), "ADD: %#x + %#x = %#x",
- u1, u2, uresult);
- DEST (result);
- FLAGS (result, uresult != ZX (uresult));
- }
- break;
- case MSO_subc:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- carry_to_use = (SR & MSP430_FLAG_C) ? 1 : 0;
- u1 = DSRC;
- u2 = SRC;
- s1 = SX (u1);
- s2 = SX (u2);
- uresult = ZX (~u2) + u1 + carry_to_use;
- result = s1 - s2 + (carry_to_use - 1);
- TRACE_ALU (MSP430_CPU (sd), "SUBC: %#x - %#x + %d = %#x",
- u1, u2, carry_to_use, uresult);
- DEST (result);
- FLAGS (result, uresult != ZX (uresult));
- }
- break;
- case MSO_sub:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- u1 = DSRC;
- u2 = SRC;
- s1 = SX (u1);
- s2 = SX (u2);
- uresult = ZX (~u2) + u1 + 1;
- result = SX (uresult);
- TRACE_ALU (MSP430_CPU (sd), "SUB: %#x - %#x = %#x",
- u1, u2, uresult);
- DEST (result);
- FLAGS (result, uresult != ZX (uresult));
- }
- break;
- case MSO_cmp:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- u1 = DSRC;
- u2 = SRC;
- s1 = SX (u1);
- s2 = SX (u2);
- uresult = ZX (~u2) + u1 + 1;
- result = s1 - s2;
- TRACE_ALU (MSP430_CPU (sd), "CMP: %#x - %#x = %x",
- u1, u2, uresult);
- FLAGS (result, uresult != ZX (uresult));
- }
- break;
- case MSO_dadd:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- carry_to_use = (SR & MSP430_FLAG_C) ? 1 : 0;
- u1 = DSRC;
- u2 = SRC;
- uresult = bcd_to_binary (u1) + bcd_to_binary (u2) + carry_to_use;
- result = binary_to_bcd (uresult);
- TRACE_ALU (MSP430_CPU (sd), "DADD: %#x + %#x + %d = %#x",
- u1, u2, carry_to_use, result);
- DEST (result);
- FLAGS (result, uresult > ((opcode->size == 8) ? 99 : 9999));
- }
- break;
- case MSO_and:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- u1 = DSRC;
- u2 = SRC;
- uresult = u1 & u2;
- TRACE_ALU (MSP430_CPU (sd), "AND: %#x & %#x = %#x",
- u1, u2, uresult);
- DEST (uresult);
- FLAGS (uresult, uresult != 0);
- }
- break;
- case MSO_bit:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- u1 = DSRC;
- u2 = SRC;
- uresult = u1 & u2;
- TRACE_ALU (MSP430_CPU (sd), "BIT: %#x & %#x -> %#x",
- u1, u2, uresult);
- FLAGS (uresult, uresult != 0);
- }
- break;
- case MSO_bic:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- u1 = DSRC;
- u2 = SRC;
- uresult = u1 & ~ u2;
- TRACE_ALU (MSP430_CPU (sd), "BIC: %#x & ~ %#x = %#x",
- u1, u2, uresult);
- DEST (uresult);
- }
- break;
- case MSO_bis:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- u1 = DSRC;
- u2 = SRC;
- uresult = u1 | u2;
- TRACE_ALU (MSP430_CPU (sd), "BIS: %#x | %#x = %#x",
- u1, u2, uresult);
- DEST (uresult);
- }
- break;
- case MSO_xor:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- s1 = 1 << (opcode->size - 1);
- u1 = DSRC;
- u2 = SRC;
- uresult = u1 ^ u2;
- TRACE_ALU (MSP430_CPU (sd), "XOR: %#x & %#x = %#x",
- u1, u2, uresult);
- DEST (uresult);
- FLAGSV (uresult, uresult != 0, (u1 & s1) && (u2 & s1));
- }
- break;
- /* Single-operand instructions. Note: the decoder puts the same
- operand in SRC as in DEST, for our convenience. */
- case MSO_rrc:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- u1 = SRC;
- carry_to_use = u1 & 1;
- uresult = u1 >> 1;
- /* If the ZC bit of the opcode is set, it means we are synthesizing
- RRUX, so the carry bit must be ignored. */
- if (opcode->zc == 0 && (SR & MSP430_FLAG_C))
- uresult |= (1 << (opcode->size - 1));
- TRACE_ALU (MSP430_CPU (sd), "RRC: %#x >>= %#x",
- u1, uresult);
- DEST (uresult);
- FLAGS (uresult, carry_to_use);
- }
- break;
- case MSO_swpb:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- u1 = SRC;
- uresult = ((u1 >> 8) & 0x00ff) | ((u1 << 8) & 0xff00);
- TRACE_ALU (MSP430_CPU (sd), "SWPB: %#x -> %#x",
- u1, uresult);
- DEST (uresult);
- }
- break;
- case MSO_rra:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- u1 = SRC;
- c = u1 & 1;
- s1 = 1 << (opcode->size - 1);
- uresult = (u1 >> 1) | (u1 & s1);
- TRACE_ALU (MSP430_CPU (sd), "RRA: %#x >>= %#x",
- u1, uresult);
- DEST (uresult);
- FLAGS (uresult, c);
- }
- break;
- case MSO_rru:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- u1 = SRC;
- c = u1 & 1;
- uresult = (u1 >> 1);
- TRACE_ALU (MSP430_CPU (sd), "RRU: %#x >>= %#x",
- u1, uresult);
- DEST (uresult);
- FLAGS (uresult, c);
- }
- break;
- case MSO_sxt:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- u1 = SRC;
- if (u1 & 0x80)
- uresult = u1 | 0xfff00;
- else
- uresult = u1 & 0x000ff;
- TRACE_ALU (MSP430_CPU (sd), "SXT: %#x -> %#x",
- u1, uresult);
- DEST (uresult);
- FLAGS (uresult, c);
- }
- break;
- case MSO_push:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- int new_sp;
- new_sp = REG_GET (MSR_SP) - op_bytes;
- /* SP is always word-aligned. */
- if (new_sp & 1)
- new_sp --;
- REG_PUT (MSR_SP, new_sp);
- u1 = SRC;
- mem_put_val (sd, SP, u1, op_bits);
- if (opcode->op[1].type == MSP430_Operand_Register)
- opcode->op[1].reg --;
- }
- break;
- case MSO_pop:
- for (rept = 0; rept < n_repeats; rept ++)
- {
- int new_sp;
- u1 = mem_get_val (sd, SP, op_bits);
- DEST (u1);
- if (opcode->op[0].type == MSP430_Operand_Register)
- opcode->op[0].reg ++;
- new_sp = REG_GET (MSR_SP) + op_bytes;
- /* SP is always word-aligned. */
- if (new_sp & 1)
- new_sp ++;
- REG_PUT (MSR_SP, new_sp);
- }
- break;
- case MSO_call:
- u1 = SRC;
- if (maybe_perform_syscall (sd, u1))
- break;
- REG_PUT (MSR_SP, REG_GET (MSR_SP) - op_bytes);
- mem_put_val (sd, SP, PC, op_bits);
- TRACE_ALU (MSP430_CPU (sd), "CALL: func %#x ret %#x, sp %#x",
- u1, PC, SP);
- REG_PUT (MSR_PC, u1);
- break;
- case MSO_reti:
- u1 = mem_get_val (sd, SP, 16);
- SR = u1 & 0xFF;
- SP += 2;
- PC = mem_get_val (sd, SP, 16);
- SP += 2;
- /* Emulate the RETI action of the 20-bit CPUX architecure.
- This is safe for 16-bit CPU architectures as well, since the top
- 8-bits of SR will have been written to the stack here, and will
- have been read as 0. */
- PC |= (u1 & 0xF000) << 4;
- TRACE_ALU (MSP430_CPU (sd), "RETI: pc %#x sr %#x",
- PC, SR);
- break;
- /* Jumps. */
- case MSO_jmp:
- i = SRC;
- switch (opcode->cond)
- {
- case MSC_nz:
- u1 = (SR & MSP430_FLAG_Z) ? 0 : 1;
- break;
- case MSC_z:
- u1 = (SR & MSP430_FLAG_Z) ? 1 : 0;
- break;
- case MSC_nc:
- u1 = (SR & MSP430_FLAG_C) ? 0 : 1;
- break;
- case MSC_c:
- u1 = (SR & MSP430_FLAG_C) ? 1 : 0;
- break;
- case MSC_n:
- u1 = (SR & MSP430_FLAG_N) ? 1 : 0;
- break;
- case MSC_ge:
- u1 = (!!(SR & MSP430_FLAG_N) == !!(SR & MSP430_FLAG_V)) ? 1 : 0;
- break;
- case MSC_l:
- u1 = (!!(SR & MSP430_FLAG_N) == !!(SR & MSP430_FLAG_V)) ? 0 : 1;
- break;
- case MSC_true:
- u1 = 1;
- break;
- }
- if (u1)
- {
- TRACE_BRANCH (MSP430_CPU (sd), "J%s: pc %#x -> %#x sr %#x, taken",
- cond_string (opcode->cond), PC, i, SR);
- PC = i;
- if (PC == opcode_pc)
- exit (0);
- }
- else
- TRACE_BRANCH (MSP430_CPU (sd), "J%s: pc %#x to %#x sr %#x, not taken",
- cond_string (opcode->cond), PC, i, SR);
- break;
- default:
- fprintf (stderr, "error: unexpected opcode id %d\n", opcode->id);
- exit (1);
- }
- }
- void
- sim_engine_run (SIM_DESC sd,
- int next_cpu_nr,
- int nr_cpus,
- int siggnal)
- {
- while (1)
- {
- msp430_step_once (sd);
- if (sim_events_tick (sd))
- sim_events_process (sd);
- }
- }
|