diff options
author | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:35:26 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:35:26 +0000 |
commit | c906108c21474dfb4ed285bcc0ac6fe02cd400cc (patch) | |
tree | a0015aa5cedc19ccbab307251353a41722a3ae13 /sim/mips | |
parent | cd946cff9ede3f30935803403f06f6ed30cad136 (diff) | |
download | gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.zip gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.tar.gz gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.tar.bz2 |
Initial creation of sourceware repositorygdb-4_18-branchpoint
Diffstat (limited to 'sim/mips')
-rw-r--r-- | sim/mips/ChangeLog | 2046 | ||||
-rw-r--r-- | sim/mips/Makefile.in | 293 | ||||
-rw-r--r-- | sim/mips/acconfig.h | 15 | ||||
-rw-r--r-- | sim/mips/config.in | 174 | ||||
-rwxr-xr-x | sim/mips/configure | 4890 | ||||
-rw-r--r-- | sim/mips/configure.in | 170 | ||||
-rw-r--r-- | sim/mips/dv-tx3904cpu.c | 246 | ||||
-rw-r--r-- | sim/mips/dv-tx3904irc.c | 413 | ||||
-rw-r--r-- | sim/mips/dv-tx3904sio.c | 621 | ||||
-rw-r--r-- | sim/mips/dv-tx3904tmr.c | 698 | ||||
-rw-r--r-- | sim/mips/interp.c | 3228 | ||||
-rw-r--r-- | sim/mips/m16.dc | 25 | ||||
-rw-r--r-- | sim/mips/m16.igen | 1236 | ||||
-rw-r--r-- | sim/mips/m16run.c | 74 | ||||
-rw-r--r-- | sim/mips/mips.dc | 16 | ||||
-rw-r--r-- | sim/mips/mips.igen | 3895 | ||||
-rw-r--r-- | sim/mips/sim-main.c | 579 | ||||
-rw-r--r-- | sim/mips/sim-main.h | 785 | ||||
-rw-r--r-- | sim/mips/tconfig.in | 31 | ||||
-rw-r--r-- | sim/mips/tx.igen | 41 | ||||
-rw-r--r-- | sim/mips/vr.igen | 78 |
21 files changed, 19554 insertions, 0 deletions
diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog new file mode 100644 index 0000000..bb8ac40 --- /dev/null +++ b/sim/mips/ChangeLog @@ -0,0 +1,2046 @@ +1999-02-05 Frank Ch. Eigler <fche@cygnus.com> + + * dv-tx3904sio.c (tx3904sio_tickle): After a polled I/O from the + CPU, start periodic background I/O polls. + (tx3904sio_poll): New function: periodic I/O poller. + +1998-12-30 Frank Ch. Eigler <fche@cygnus.com> + + * mips.igen (BREAK): Call signal_exception instead of sim_engine_halt. + +Tue Dec 29 16:03:53 1998 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * configure.in, configure (mips64vr5*-*-*): Added missing ;; in + case statement. + +1998-12-29 Frank Ch. Eigler <fche@cygnus.com> + + * interp.c (sim_open): Allocate jm3904 memory in smaller chunks. + (load_word): Call SIM_CORE_SIGNAL hook on error. + (signal_exception): Call SIM_CPU_EXCEPTION_TRIGGER hook before + starting. For exception dispatching, pass PC instead of NULL_CIA. + (decode_coproc): Use COP0_BADVADDR to store faulting address. + * sim-main.h (COP0_BADVADDR): Define. + (SIM_CORE_SIGNAL): Define hook to call mips_core_signal. + (SIM_CPU_EXCEPTION*): Define hooks to call mips_cpu_exception*(). + (_sim_cpu): Add exc_* fields to store register value snapshots. + * mips.igen (*): Replace memory-related SignalException* calls + with references to SIM_CORE_SIGNAL hook. + + * dv-tx3904irc.c (tx3904irc_port_event): printf format warning + fix. + * sim-main.c (*): Minor warning cleanups. + +1998-12-24 Gavin Romig-Koch <gavin@cygnus.com> + + * m16.igen (DADDIU5): Correct type-o. + +Mon Dec 21 10:34:48 1998 Andrew Cagney <cagney@chook> + + * mips.igen (do_ddiv, do_ddivu): Pacify GCC. Update hi/lo via tmp + variables. + +Wed Dec 16 18:20:28 1998 Andrew Cagney <cagney@chook> + + * Makefile.in (SIM_EXTRA_CFLAGS): No longer need to add .../newlib + to include path. + (interp.o): Add dependency on itable.h + (oengine.c, gencode): Delete remaining references. + (BUILT_SRC_FROM_GEN): Clean up. + +1998-12-16 Gavin Romig-Koch <gavin@cygnus.com> + + * vr4run.c: New. + * Makefile.in (SIM_HACK_OBJ,HACK_OBJS,HACK_GEN_SRCS,libhack.a, + tmp-hack,tmp-m32-hack,tmp-m16-hack,tmp-itable-hack, + tmp-run-hack) : New. + * m16.igen (LD,DADDIU,DADDUI5,DADJSP,DADDIUSP,DADDI,DADDU,DSUBU, + DSLL,DSRL,DSRA,DSLLV,DSRAV,DMULT,DMULTU,DDIV,DDIVU,JALX32,JALX): + Drop the "64" qualifier to get the HACK generator working. + Use IMMEDIATE rather than IMMED. Use SHAMT rather than SHIFT. + * mips.igen (do_daddiu,do_ddiv,do_divu): Remove the 64-only + qualifier to get the hack generator working. + (do_dsll,do_dsllv,do_dsra,do_dsrl,do_dsrlv): New. + (DSLL): Use do_dsll. + (DSLLV): Use do_dsllv. + (DSRA): Use do_dsra. + (DSRL): Use do_dsrl. + (DSRLV): Use do_dsrlv. + (BC1): Move *vr4100 to get the HACK generator working. + (CxC1, DMxC1, MxC1,MACCU,MACCHI,MACCHIU): Rename to + get the HACK generator working. + (MACC) Rename to get the HACK generator working. + (DMACC,MACCS,DMACCS): Add the 64. + +1998-12-12 Gavin Romig-Koch <gavin@cygnus.com> + + * mips.igen (BC1): Renamed to BC1a and BC1b to avoid conflicts. + * sim-main.h (SizeFGR): Handle TARGET_ENABLE_FR. + +1998-12-11 Gavin Romig-Koch <gavin@cygnus.com> + + * mips/interp.c (DEBUG): Cleanups. + +1998-12-10 Frank Ch. Eigler <fche@cygnus.com> + + * dv-tx3904sio.c (tx3904sio_io_read_buffer): Endianness fixes. + (tx3904sio_tickle): fflush after a stdout character output. + +1998-12-03 Frank Ch. Eigler <fche@cygnus.com> + + * interp.c (sim_close): Uninstall modules. + +Wed Nov 25 13:41:03 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h, interp.c (sim_monitor): Change to global + function. + +Wed Nov 25 17:33:24 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure.in (vr4100): Only include vr4100 instructions in + simulator. + * configure: Re-generate. + * m16.igen (*): Tag all mips16 instructions as also being vr4100. + +Mon Nov 23 18:20:36 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (SIM_CFLAGS): Do not define WITH_IGEN. + * sim-main.h, sim-main.c, interp.c: Delete #if WITH_IGEN keeping + true alternative. + + * configure.in (sim_default_gen, sim_use_gen): Replace with + sim_gen. + (--enable-sim-igen): Delete config option. Always using IGEN. + * configure: Re-generate. + + * Makefile.in (gencode): Kill, kill, kill. + * gencode.c: Ditto. + +Mon Nov 23 18:07:36 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure.in: Configure mips64vr4100-elf nee mips64vr41* as a 64 + bit mips16 igen simulator. + * configure: Re-generate. + + * mips.igen (check_div_hilo, check_mult_hilo, check_mf_hilo): Mark + as part of vr4100 ISA. + * vr.igen: Mark all instructions as 64 bit only. + +Mon Nov 23 17:07:37 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (get_cell, sim_monitor, fetch_str, CoProcPresent): + Pacify GCC. + +Mon Nov 23 13:23:40 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure.in: Configure mips-lsi-elf nee mips*lsi* as a + mipsIII/mips16 igen simulator. Fix sim_gen VS sim_igen typos. + * configure: Re-generate. + + * m16.igen (BREAK): Define breakpoint instruction. + (JALX32): Mark instruction as mips16 and not r3900. + * mips.igen (C.cond.fmt): Fix typo in instruction format. + + * sim-main.h (PENDING_FILL): Wrap C statements in do/while. + +Sat Nov 7 09:54:38 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * gencode.c (build_instruction - BREAK): For MIPS16, handle BREAK + insn as a debug breakpoint. + + * sim-main.h (PENDING_SLOT_BIT): Fix, was incorrectly defined as + pending.slot_size. + (PENDING_SCHED): Clean up trace statement. + (PENDING_SCHED): Increment PENDING_IN and PENDING_TOTAL. + (PENDING_FILL): Delay write by only one cycle. + (PENDING_FILL): For FSRs, write fmt_uninterpreted to FPR_STATE. + + * sim-main.c (pending_tick): Clean up trace statements. Add trace + of pending writes. + (pending_tick): Fix sizes in switch statements, 4 & 8 instead of + 32 & 64. + (pending_tick): Move incrementing of index to FOR statement. + (pending_tick): Only update PENDING_OUT after a write has occured. + + * configure.in: Add explicit mips-lsi-* target. Use gencode to + build simulator. + * configure: Re-generate. + + * interp.c (sim_engine_run OLD): Delete explicit call to + PENDING_TICK. Now called via ENGINE_ISSUE_PREFIX_HOOK. + +Sat Oct 30 09:49:10 1998 Frank Ch. Eigler <fche@cygnus.com> + + * dv-tx3904cpu.c (deliver_tx3904cpu_interrupt): Add dummy + interrupt level number to match changed SignalExceptionInterrupt + macro. + +Fri Oct 9 18:02:25 1998 Doug Evans <devans@canuck.cygnus.com> + + * interp.c: #include "itable.h" if WITH_IGEN. + (get_insn_name): New function. + (sim_open): Initialize CPU_INSN_NAME,CPU_MAX_INSNS. + * sim-main.h (MAX_INSNS,INSN_NAME): Delete. + +Mon Sep 14 12:36:44 1998 Frank Ch. Eigler <fche@cygnus.com> + + * configure: Rebuilt to inhale new common/aclocal.m4. + +Tue Sep 1 15:39:18 1998 Frank Ch. Eigler <fche@cygnus.com> + + * dv-tx3904sio.c: Include sim-assert.h. + +Tue Aug 25 12:49:46 1998 Frank Ch. Eigler <fche@cygnus.com> + + * dv-tx3904sio.c: New file: tx3904 serial I/O module. + * configure.in: Add dv-tx3904sio, dv-sockser for tx39 target. + Reorganize target-specific sim-hardware checks. + * configure: rebuilt. + * interp.c (sim_open): For tx39 target boards, set + OPERATING_ENVIRONMENT, add tx3904sio devices. + * tconfig.in: For tx39 target, set SIM_HANDLES_LMA for loading + ROM executables. Install dv-sockser into sim-modules list. + + * dv-tx3904irc.c: Compiler warning clean-up. + * dv-tx3904tmr.c: Compiler warning clean-up. Remove particularly + frequent hw-trace messages. + +Fri Jul 31 18:14:16 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * vr.igen (MulAcc): Identify as a vr4100 specific function. + +Sat Jul 25 16:03:14 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (IGEN_INCLUDE): Add vr.igen. + + * vr.igen: New file. + (MAC/MADD16, DMAC/DMADD16): Implement using code from gencode.c. + * mips.igen: Define vr4100 model. Include vr.igen. +Mon Jun 29 09:21:07 1998 Gavin Koch <gavin@cygnus.com> + + * mips.igen (check_mf_hilo): Correct check. + +Wed Jun 17 12:20:49 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (interrupt_event): Add prototype. + + * dv-tx3904tmr.c (tx3904tmr_io_write_buffer): Delete unused + register_ptr, register_value. + (deliver_tx3904tmr_tick): Fix types passed to printf fmt. + + * sim-main.h (tracefh): Make extern. + +Tue Jun 16 14:39:00 1998 Frank Ch. Eigler <fche@cygnus.com> + + * dv-tx3904tmr.c: Deschedule timer event after dispatching. + Reduce unnecessarily high timer event frequency. + * dv-tx3904cpu.c: Ditto for interrupt event. + +Wed Jun 10 13:22:32 1998 Frank Ch. Eigler <fche@cygnus.com> + + * interp.c (decode_coproc): For TX39, add stub COP0 register #7, + to allay warnings. + (interrupt_event): Made non-static. + + * dv-tx3904tmr.c (deliver_tx3904tmr_tick): Correct accidental + interchange of configuration values for external vs. internal + clock dividers. + +Tue Jun 9 12:46:24 1998 Ian Carmichael <iancarm@cygnus.com> + + * mips.igen (BREAK): Moved code to here for + simulator-reserved break instructions. + * gencode.c (build_instruction): Ditto. + * interp.c (signal_exception): Code moved from here. Non- + reserved instructions now use exception vector, rather + than halting sim. + * sim-main.h: Moved magic constants to here. + +Tue Jun 9 12:29:50 1998 Frank Ch. Eigler <fche@cygnus.com> + + * dv-tx3904cpu.c (deliver_*_interrupt,*_port_event): Set the CAUSE + register upon non-zero interrupt event level, clear upon zero + event value. + * dv-tx3904irc.c (*_port_event): Handle deactivated interrupt signal + by passing zero event value. + (*_io_{read,write}_buffer): Endianness fixes. + * dv-tx3904tmr.c (*_io_{read,write}_buffer): Endianness fixes. + (deliver_*_tick): Reduce sim event interval to 75% of count interval. + + * interp.c (sim_open): Added jmr3904pal board type that adds PAL-based + serial I/O and timer module at base address 0xFFFF0000. + +Tue Jun 9 11:52:29 1998 Gavin Koch <gavin@cygnus.com> + + * mips.igen (SWC1) : Correct the handling of ReverseEndian + and BigEndianCPU. + +Tue Jun 9 11:40:57 1998 Gavin Koch <gavin@cygnus.com> + + * configure.in (mips_fpu_bitsize) : Set this correctly for 32-bit mips + parts. + * configure: Update. + +Thu Jun 4 15:37:33 1998 Frank Ch. Eigler <fche@cygnus.com> + + * dv-tx3904tmr.c: New file - implements tx3904 timer. + * dv-tx3904{irc,cpu}.c: Mild reformatting. + * configure.in: Include tx3904tmr in hw_device list. + * configure: Rebuilt. + * interp.c (sim_open): Instantiate three timer instances. + Fix address typo of tx3904irc instance. + +Tue Jun 2 15:48:02 1998 Ian Carmichael <iancarm@cygnus.com> + + * interp.c (signal_exception): SystemCall exception now uses + the exception vector. + +Mon Jun 1 18:18:26 1998 Frank Ch. Eigler <fche@cygnus.com> + + * interp.c (decode_coproc): For TX39, add stub COP0 register #3, + to allay warnings. + +Fri May 29 11:40:39 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure.in (sim_igen_filter): Match mips*tx39 not mipst*tx39. + +Mon May 25 20:47:45 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * dv-tx3904cpu.c, dv-tx3904irc.c: Rename *_callback to *_method. + + * dv-tx3904cpu.c, dv-tx3904irc.c: Include hw-main.h and + sim-main.h. Declare a struct hw_descriptor instead of struct + hw_device_descriptor. + +Mon May 25 12:41:38 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * mips.igen (do_store_left, do_load_left): Compute nr of left and + right bits and then re-align left hand bytes to correct byte + lanes. Fix incorrect computation in do_store_left when loading + bytes from second word. + +Fri May 22 13:34:20 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure.in (SIM_AC_OPTION_HARDWARE): Only enable when tx3904. + * interp.c (sim_open): Only create a device tree when HW is + enabled. + + * dv-tx3904irc.c (tx3904irc_finish): Pacify GCC. + * interp.c (signal_exception): Ditto. + +Thu May 21 14:24:11 1998 Gavin Koch <gavin@cygnus.com> + + * gencode.c: Mark BEGEZALL as LIKELY. + +Thu May 21 18:57:19 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (ALU32_END): Sign extend 32 bit results. + * mips.igen (ADD, SUB, ADDI, DADD, DSUB): Trace. + +Mon May 18 18:22:42 1998 Frank Ch. Eigler <fche@cygnus.com> + + * configure.in (SIM_AC_OPTION_HARDWARE): Added common hardware + modules. Recognize TX39 target with "mips*tx39" pattern. + * configure: Rebuilt. + * sim-main.h (*): Added many macros defining bits in + TX39 control registers. + (SignalInterrupt): Send actual PC instead of NULL. + (SignalNMIReset): New exception type. + * interp.c (board): New variable for future use to identify + a particular board being simulated. + (mips_option_handler,mips_options): Added "--board" option. + (interrupt_event): Send actual PC. + (sim_open): Make memory layout conditional on board setting. + (signal_exception): Initial implementation of hardware interrupt + handling. Accept another break instruction variant for simulator + exit. + (decode_coproc): Implement RFE instruction for TX39. + (mips.igen): Decode RFE instruction as such. + * configure.in (tx3904cpu,tx3904irc): Added devices for tx3904. + * interp.c: Define "jmr3904" and "jmr3904debug" board types and + bbegin to implement memory map. + * dv-tx3904cpu.c: New file. + * dv-tx3904irc.c: New file. + +Wed May 13 14:40:11 1998 Gavin Koch <gavin@cygnus.com> + + * mips.igen (check_mt_hilo): Create a separate r3900 version. + +Wed May 13 14:11:46 1998 Gavin Koch <gavin@cygnus.com> + + * tx.igen (madd,maddu): Replace calls to check_op_hilo + with calls to check_div_hilo. + +Wed May 13 09:59:27 1998 Gavin Koch <gavin@cygnus.com> + + * mips/mips.igen (check_op_hilo,check_mult_hilo,check_div_hilo): + Replace check_op_hilo with check_mult_hilo and check_div_hilo. + Add special r3900 version of do_mult_hilo. + (do_dmultx,do_mult,do_multu): Replace calls to check_op_hilo + with calls to check_mult_hilo. + (do_ddiv,do_ddivu,do_div,do_divu): Replace calls to check_op_hilo + with calls to check_div_hilo. + +Tue May 12 15:22:11 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure.in (SUBTARGET_R3900): Define for mipstx39 target. + Document a replacement. + +Fri May 8 17:48:19 1998 Ian Carmichael <iancarm@cygnus.com> + + * interp.c (sim_monitor): Make mon_printf work. + +Wed May 6 19:42:19 1998 Doug Evans <devans@canuck.cygnus.com> + + * sim-main.h (INSN_NAME): New arg `cpu'. + +Tue Apr 28 18:33:31 1998 Geoffrey Noer <noer@cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sun Apr 26 15:31:55 1998 Tom Tromey <tromey@creche> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Sun Apr 26 15:20:01 1998 Tom Tromey <tromey@cygnus.com> + + * acconfig.h: New file. + * configure.in: Reverted change of Apr 24; use sinclude again. + +Fri Apr 24 14:16:40 1998 Tom Tromey <tromey@creche> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Fri Apr 24 11:19:20 1998 Tom Tromey <tromey@cygnus.com> + + * configure.in: Don't call sinclude. + +Fri Apr 24 11:35:01 1998 Andrew Cagney <cagney@chook.cygnus.com> + + * mips.igen (do_store_left): Pass 0 not NULL to store_memory. + +Tue Apr 21 11:59:50 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * mips.igen (ERET): Implement. + + * interp.c (decode_coproc): Return sign-extended EPC. + + * mips.igen (ANDI, LUI, MFC0): Add tracing code. + + * interp.c (signal_exception): Do not ignore Trap. + (signal_exception): On TRAP, restart at exception address. + (HALT_INSTRUCTION, HALT_INSTRUCTION_MASK): Define. + (signal_exception): Update. + (sim_open): Patch V_COMMON interrupt vector with an abort sequence + so that TRAP instructions are caught. + +Mon Apr 20 11:26:55 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (struct hilo_access, struct hilo_history): Define, + contains HI/LO access history. + (struct _sim_cpu): Make hiaccess and loaccess of type hilo_access. + (HIACCESS, LOACCESS): Delete, replace with + (HIHISTORY, LOHISTORY): New macros. + (CHECKHILO): Delete all, moved to mips.igen + + * gencode.c (build_instruction): Do not generate checks for + correct HI/LO register usage. + + * interp.c (old_engine_run): Delete checks for correct HI/LO + register usage. + + * mips.igen (check_mt_hilo, check_mf_hilo, check_op_hilo, + check_mf_cycles): New functions. + (do_mfhi, do_mflo, "mthi", "mtlo", do_ddiv, do_ddivu, do_div, + do_divu, domultx, do_mult, do_multu): Use. + + * tx.igen ("madd", "maddu"): Use. + +Wed Apr 15 18:31:54 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * mips.igen (DSRAV): Use function do_dsrav. + (SRAV): Use new function do_srav. + + * m16.igen (BEQZ, BNEZ): Compare GPR[TRX] not GPR[RX]. + (B): Sign extend 11 bit immediate. + (EXT-B*): Shift 16 bit immediate left by 1. + (ADDIU*): Don't sign extend immediate value. + +Wed Apr 15 10:32:15 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * m16run.c (sim_engine_run): Restore CIA after handling an event. + + * sim-main.h (DELAY_SLOT, NULLIFY_NEXT_INSTRUCTION): For IGEN, use + functions. + + * mips.igen (delayslot32, nullify_next_insn): New functions. + (m16.igen): Always include. + (do_*): Add more tracing. + + * m16.igen (delayslot16): Add NIA argument, could be called by a + 32 bit MIPS16 instruction. + + * interp.c (ifetch16): Move function from here. + * sim-main.c (ifetch16): To here. + + * sim-main.c (ifetch16, ifetch32): Update to match current + implementations of LH, LW. + (signal_exception): Don't print out incorrect hex value of illegal + instruction. + +Wed Apr 15 00:17:25 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * m16run.c (sim_engine_run): Use IMEM16 and IMEM32 to fetch an + instruction. + + * m16.igen: Implement MIPS16 instructions. + + * mips.igen (do_addiu, do_addu, do_and, do_daddiu, do_daddu, + do_ddiv, do_ddivu, do_div, do_divu, do_dmultx, do_dmultu, do_srav, + do_dsubu, do_mfhi, do_mflo, do_mult, do_multu, do_nor, do_or, + do_sll, do_sllv, do_slt, do_slti, do_sltiu, do_sltu, do_sra, + do_srl, do_srlv, do_subu, do_xor, do_xori): New functions. Move + bodies of corresponding code from 32 bit insn to these. Also used + by MIPS16 versions of functions. + + * sim-main.h (RAIDX, T8IDX, T8, SPIDX): Define. + (IMEM16): Drop NR argument from macro. + +Sat Apr 4 22:39:50 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (SIM_OBJS): Add sim-main.o. + + * sim-main.h (address_translation, load_memory, store_memory, + cache_op, sync_operation, prefetch, ifetch32, pending_tick): Mark + as INLINE_SIM_MAIN. + (pr_addr, pr_uword64): Declare. + (sim-main.c): Include when H_REVEALS_MODULE_P. + + * interp.c (address_translation, load_memory, store_memory, + cache_op, sync_operation, prefetch, ifetch32, pending_tick): Move + from here. + * sim-main.c: To here. Fix compilation problems. + + * configure.in: Enable inlining. + * configure: Re-config. + +Sat Apr 4 20:36:25 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Fri Apr 3 04:32:35 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * mips.igen: Include tx.igen. + * Makefile.in (IGEN_INCLUDE): Add tx.igen. + * tx.igen: New file, contains MADD and MADDU. + + * interp.c (load_memory): When shifting bytes, use LOADDRMASK not + the hardwired constant `7'. + (store_memory): Ditto. + (LOADDRMASK): Move definition to sim-main.h. + + mips.igen (MTC0): Enable for r3900. + (ADDU): Add trace. + + mips.igen (do_load_byte): Delete. + (do_load, do_store, do_load_left, do_load_write, do_store_left, + do_store_right): New functions. + (SW*, LW*, SD*, LD*, SH, LH, SB, LB): Use. + + configure.in: Let the tx39 use igen again. + configure: Update. + +Thu Apr 2 10:59:39 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_monitor): get_mem_info returns a 4 byte quantity, + not an address sized quantity. Return zero for cache sizes. + +Wed Apr 1 23:47:53 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * mips.igen (r3900): r3900 does not support 64 bit integer + operations. + +Mon Mar 30 14:46:05 1998 Gavin Koch <gavin@cygnus.com> + + * configure.in (mipstx39*-*-*): Use gencode simulator rather + than igen one. + * configure : Rebuild. + +Fri Mar 27 16:15:52 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Fri Mar 27 15:01:50 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (mips_option_handler): Iterate over MAX_NR_PROCESSORS. + +Wed Mar 25 16:44:27 1998 Ian Carmichael <iancarm@cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Regenerated to track ../common/aclocal.m4 changes. + +Wed Mar 25 12:35:29 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Mar 25 10:05:46 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (Max, Min): Comment out functions. Not yet used. + +Wed Mar 18 12:38:12 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Mar 17 19:05:20 1998 Frank Ch. Eigler <fche@cygnus.com> + + * Makefile.in (MIPS_EXTRA_LIBS, SIM_EXTRA_LIBS): Added + configurable settings for stand-alone simulator. + + * configure.in: Added X11 search, just in case. + + * configure: Regenerated. + +Wed Mar 11 14:09:10 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_write, sim_read, load_memory, store_memory): + Replace sim_core_*_map with read_map, write_map, exec_map resp. + +Tue Mar 3 13:58:43 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (GETFCC): Return an unsigned value. + +Tue Mar 3 13:21:37 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * mips.igen (DIV): Fix check for -1 / MIN_INT. + (DADD): Result destination is RD not RT. + +Fri Feb 27 13:49:49 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (HIACCESS, LOACCESS): Always define. + + * mdmx.igen (Maxi, Mini): Rename Max, Min. + + * interp.c (sim_info): Delete. + +Fri Feb 27 18:41:01 1998 Doug Evans <devans@canuck.cygnus.com> + + * interp.c (DECLARE_OPTION_HANDLER): Use it. + (mips_option_handler): New argument `cpu'. + (sim_open): Update call to sim_add_option_table. + +Wed Feb 25 18:56:22 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * mips.igen (CxC1): Add tracing. + +Fri Feb 20 17:43:21 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (Max, Min): Declare. + + * interp.c (Max, Min): New functions. + + * mips.igen (BC1): Add tracing. + +Thu Feb 19 14:50:00 1998 John Metzler <jmetzler@cygnus.com> + + * interp.c Added memory map for stack in vr4100 + +Thu Feb 19 10:21:21 1998 Gavin Koch <gavin@cygnus.com> + + * interp.c (load_memory): Add missing "break"'s. + +Tue Feb 17 12:45:35 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_store_register, sim_fetch_register): Pass in + length parameter. Return -1. + +Tue Feb 10 11:57:40 1998 Ian Carmichael <iancarm@cygnus.com> + + * interp.c: Added hardware init hook, fixed warnings. + +Sat Feb 7 17:16:20 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (itable.h itable.c): Depend on SIM_@sim_gen@_ALL. + +Tue Feb 3 11:36:02 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (ifetch16): New function. + + * sim-main.h (IMEM32): Rename IMEM. + (IMEM16_IMMED): Define. + (IMEM16): Define. + (DELAY_SLOT): Update. + + * m16run.c (sim_engine_run): New file. + + * m16.igen: All instructions except LB. + (LB): Call do_load_byte. + * mips.igen (do_load_byte): New function. + (LB): Call do_load_byte. + + * mips.igen: Move spec for insn bit size and high bit from here. + * Makefile.in (tmp-igen, tmp-m16): To here. + + * m16.dc: New file, decode mips16 instructions. + + * Makefile.in (SIM_NO_ALL): Define. + (tmp-m16): Generate both 16 bit and 32 bit simulator engines. + +Tue Feb 3 11:28:00 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure.in (mips_fpu_bitsize): For tx39, restrict floating + point unit to 32 bit registers. + * configure: Re-generate. + +Sun Feb 1 15:47:14 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure.in (sim_use_gen): Make IGEN the default simulator + generator for generic 32 and 64 bit mips targets. + * configure: Re-generate. + +Sun Feb 1 16:52:37 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (SizeFGR): Determine from floating-point and not gpr + bitsize. + + * interp.c (sim_fetch_register, sim_store_register): Read/write + FGR from correct location. + (sim_open): Set size of FGR's according to + WITH_TARGET_FLOATING_POINT_BITSIZE. + + * sim-main.h (FGR): Store floating point registers in a separate + array. + +Sun Feb 1 16:47:51 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Feb 3 00:10:50 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (ColdReset): Call PENDING_INVALIDATE. + + * sim-main.h (ENGINE_ISSUE_PREFIX_HOOK): Call PENDING_TICK. + + * interp.c (pending_tick): New function. Deliver pending writes. + + * sim-main.h (PENDING_FILL, PENDING_TICK, PENDING_SCHED, + PENDING_BIT, PENDING_INVALIDATE): Re-write pipeline code so that + it can handle mixed sized quantites and single bits. + +Mon Feb 2 17:43:15 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (oengine.h): Do not include when building with IGEN. + (sim_open): Replace GPRLEN by WITH_TARGET_WORD_BITSIZE. + (sim_info): Ditto for PROCESSOR_64BIT. + (sim_monitor): Replace ut_reg with unsigned_word. + (*): Ditto for t_reg. + (LOADDRMASK): Define. + (sim_open): Remove defunct check that host FP is IEEE compliant, + using software to emulate floating point. + (value_fpr, ...): Always compile, was conditional on HASFPU. + +Sun Feb 1 11:15:29 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (sim_state): Make the cpu array MAX_NR_PROCESSORS in + size. + + * interp.c (SD, CPU): Define. + (mips_option_handler): Set flags in each CPU. + (interrupt_event): Assume CPU 0 is the one being iterrupted. + (sim_close): Do not clear STATE, deleted anyway. + (sim_write, sim_read): Assume CPU zero's vm should be used for + data transfers. + (sim_create_inferior): Set the PC for all processors. + (sim_monitor, store_word, load_word, mips16_entry): Add cpu + argument. + (mips16_entry): Pass correct nr of args to store_word, load_word. + (ColdReset): Cold reset all cpu's. + (signal_exception): Pass cpu to sim_monitor & mips16_entry. + (sim_monitor, load_memory, store_memory, signal_exception): Use + `CPU' instead of STATE_CPU. + + + * sim-main.h: Replace uses of STATE_CPU with CPU. Replace sd with + SD or CPU_. + + * sim-main.h (signal_exception): Add sim_cpu arg. + (SignalException*): Pass both SD and CPU to signal_exception. + * interp.c (signal_exception): Update. + + * sim-main.h (value_fpr, store_fpr, dotrace, ifetch32), interp.c: + Ditto + (sync_operation, prefetch, cache_op, store_memory, load_memory, + address_translation): Ditto + (decode_coproc, cop_lw, cop_ld, cop_sw, cop_sd): Ditto. + +Sat Jan 31 18:15:41 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sat Jan 31 14:49:24 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_engine_run): Add `nr_cpus' argument. + + * mips.igen (model): Map processor names onto BFD name. + + * sim-main.h (CPU_CIA): Delete. + (SET_CIA, GET_CIA): Define + +Wed Jan 21 16:16:27 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (GPR_SET): Define, used by igen when zeroing a + regiser. + + * configure.in (default_endian): Configure a big-endian simulator + by default. + * configure: Re-generate. + +Mon Jan 19 22:26:29 1998 Doug Evans <devans@seba> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Jan 5 20:38:54 1998 Mark Alexander <marka@cygnus.com> + + * interp.c (sim_monitor): Handle Densan monitor outbyte + and inbyte functions. + +1997-12-29 Felix Lee <flee@cygnus.com> + + * interp.c (sim_engine_run): msvc cpp barfs on #if (a==b!=c). + +Wed Dec 17 14:48:20 1997 Jeffrey A Law (law@cygnus.com) + + * Makefile.in (tmp-igen): Arrange for $zero to always be + reset to zero after every instruction. + +Mon Dec 15 23:17:11 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Wed Dec 10 17:10:45 1997 Jeffrey A Law (law@cygnus.com) + + * mips.igen (MSUB): Fix to work like MADD. + * gencode.c (MSUB): Similarly. + +Thu Dec 4 09:21:05 1997 Doug Evans <devans@canuck.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Nov 26 11:00:23 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * mips.igen (LWC1): Correct assembler - lwc1 not swc1. + +Sun Nov 23 01:45:20 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (sim-fpu.h): Include. + + * interp.c (convert, SquareRoot, Recip, Divide, Multiply, Sub, + Add, Negate, AbsoluteValue, Equal, Less, Infinity, NaN): Rewrite + using host independant sim_fpu module. + +Thu Nov 20 19:56:22 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (signal_exception): Report internal errors with SIGABRT + not SIGQUIT. + + * sim-main.h (C0_CONFIG): New register. + (signal.h): No longer include. + + * interp.c (decode_coproc): Allow access C0_CONFIG to register. + +Tue Nov 18 15:33:48 1997 Doug Evans <devans@canuck.cygnus.com> + + * Makefile.in (SIM_OBJS): Use $(SIM_NEW_COMMON_OBJS). + +Fri Nov 14 11:56:48 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * mips.igen: Tag vr5000 instructions. + (ANDI): Was missing mipsIV model, fix assembler syntax. + (do_c_cond_fmt): New function. + (C.cond.fmt): Handle mips I-III which do not support CC field + separatly. + (bc1): Handle mips IV which do not have a delaed FCC separatly. + (SDR): Mask paddr when BigEndianMem, not the converse as specified + in IV3.2 spec. + (DMULT, DMULTU): Force use of hosts 64bit multiplication. Handle + vr5000 which saves LO in a GPR separatly. + + * configure.in (enable-sim-igen): For vr5000, select vr5000 + specific instructions. + * configure: Re-generate. + +Wed Nov 12 14:42:52 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (SIM_OBJS): Add sim-fpu module. + + * interp.c (store_fpr), sim-main.h: Add separate fmt_uninterpreted_32 and + fmt_uninterpreted_64 bit cases to switch. Convert to + fmt_formatted, + + * sim-main.h (ENGINE_ISSUE_PREFIX_HOOK): Define, + + * mips.igen (SWR): Mask paddr when BigEndianMem, not the converse + as specified in IV3.2 spec. + (MTC1, DMTC1): Call StoreFPR to store the GPR in the FPR. + +Tue Nov 11 12:38:23 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * mips.igen: Delay slot branches add OFFSET to NIA not CIA. + (MFC0, MTC0, SWC1, LWC1, SDC1, LDC1): Implement. + (MTC1, MFC1, DMTC1, DMFC1, CFC1, CTC1): Implement separate non + PENDING_FILL versions of instructions. Simplify. + (X): New function. + (MULT, MULTU): Implement separate RD==0 and RD!=0 versions of + instructions. + (BEQZ, ..., SLT, SLTI, TLT, TLE, TLI, ...): Explicitly cast GPR to + a signed value. + (MTHI, MFHI): Disable code checking HI-LO. + + * sim-main.h (dotrace,tracefh), interp.c: Make dotrace & tracefh + global. + (NULLIFY_NEXT_INSTRUCTION): Call dotrace. + +Thu Nov 6 16:36:35 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * gencode.c (build_mips16_operands): Replace IPC with cia. + + * interp.c (sim_monitor, signal_exception, cache_op, store_fpr, + value_fpr, cop_ld, cop_lw, cop_sw, cop_sd, decode_coproc): Replace + IPC to `cia'. + (UndefinedResult): Replace function with macro/function + combination. + (sim_engine_run): Don't save PC in IPC. + + * sim-main.h (IPC): Delete. + + + * interp.c (signal_exception, store_word, load_word, + address_translation, load_memory, store_memory, cache_op, + prefetch, sync_operation, ifetch, value_fpr, store_fpr, convert, + cop_lw, cop_ld, cop_sw, cop_sd, decode_coproc, sim_monitor): Add + current instruction address - cia - argument. + (sim_read, sim_write): Call address_translation directly. + (sim_engine_run): Rename variable vaddr to cia. + (signal_exception): Pass cia to sim_monitor + + * sim-main.h (SignalException, LoadWord, StoreWord, CacheOp, + Prefetch, SyncOperation, ValueFPR, StoreFPR, Convert, COP_LW, + COP_LD, COP_SW, COP_SD, DecodeCoproc): Update. + + * sim-main.h (SignalExceptionSimulatorFault): Delete definition. + * interp.c (sim_open): Replace SignalExceptionSimulatorFault with + SIM_ASSERT. + + * interp.c (signal_exception): Pass restart address to + sim_engine_restart. + + * Makefile.in (semantics.o, engine.o, support.o, itable.o, + idecode.o): Add dependency. + + * sim-main.h (SIM_ENGINE_HALT_HOOK, SIM_ENGINE_RESUME_HOOK): + Delete definitions + (DELAY_SLOT): Update NIA not PC with branch address. + (NULLIFY_NEXT_INSTRUCTION): Set NIA to instruction after next. + + * mips.igen: Use CIA not PC in branch calculations. + (illegal): Call SignalException. + (BEQ, ADDIU): Fix assembler. + +Wed Nov 5 12:19:56 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * m16.igen (JALX): Was missing. + + * configure.in (enable-sim-igen): New configuration option. + * configure: Re-generate. + + * sim-main.h (MAX_INSNS, INSN_NAME): Define. + + * interp.c (load_memory, store_memory): Delete parameter RAW. + (sim_read, sim_write): Use sim_core_{read,write}_buffer directly + bypassing {load,store}_memory. + + * sim-main.h (ByteSwapMem): Delete definition. + + * Makefile.in (SIM_OBJS): Add sim-memopt module. + + * interp.c (sim_do_command, sim_commands): Delete mips specific + commands. Handled by module sim-options. + + * sim-main.h (SIM_HAVE_FLATMEM): Undefine, use sim-core.o module. + (WITH_MODULO_MEMORY): Define. + + * interp.c (sim_info): Delete code printing memory size. + + * interp.c (mips_size): Nee sim_size, delete function. + (power2): Delete. + (monitor, monitor_base, monitor_size): Delete global variables. + (sim_open, sim_close): Delete code creating monitor and other + memory regions. Use sim-memopts module, via sim_do_commandf, to + manage memory regions. + (load_memory, store_memory): Use sim-core for memory model. + + * interp.c (address_translation): Delete all memory map code + except line forcing 32 bit addresses. + +Wed Nov 5 11:21:11 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (WITH_TRACE): Delete definition. Enables common + trace options. + + * interp.c (logfh, logfile): Delete globals. + (sim_open, sim_close): Delete code opening & closing log file. + (mips_option_handler): Delete -l and -n options. + (OPTION mips_options): Ditto. + + * interp.c (OPTION mips_options): Rename option trace to dinero. + (mips_option_handler): Update. + +Wed Nov 5 09:35:59 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (fetch_str): New function. + (sim_monitor): Rewrite using sim_read & sim_write. + (sim_open): Check magic number. + (sim_open): Write monitor vectors into memory using sim_write. + (MONITOR_BASE, MONITOR_SIZE, MEM_SIZE): Define. + (sim_read, sim_write): Simplify - transfer data one byte at a + time. + (load_memory, store_memory): Clarify meaning of parameter RAW. + + * sim-main.h (isHOST): Defete definition. + (isTARGET): Mark as depreciated. + (address_translation): Delete parameter HOST. + + * interp.c (address_translation): Delete parameter HOST. + +Wed Oct 29 11:13:56 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * mips.igen: + + * Makefile.in (IGEN_INCLUDE): Files included by mips.igen. + (tmp-igen, tmp-m16): Depend on IGEN_INCLUDE. + +Tue Oct 28 11:06:47 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * mips.igen: Add model filter field to records. + +Mon Oct 27 17:53:59 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (SIM_NO_CFLAGS): Define. Define WITH_IGEN=0. + + interp.c (sim_engine_run): Do not compile function sim_engine_run + when WITH_IGEN == 1. + + * configure.in (sim_igen_flags, sim_m16_flags): Set according to + target architecture. + + Makefile.in (tmp-igen, tmp-m16): Drop -F and -M options to + igen. Replace with configuration variables sim_igen_flags / + sim_m16_flags. + + * m16.igen: New file. Copy mips16 insns here. + * mips.igen: From here. + +Mon Oct 27 13:53:59 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (SIM_NO_OBJ): Define, move SIM_M16_OBJ, SIM_IGEN_OBJ + to top. + (tmp-igen, tmp-m16): Pass -I srcdir to igen. + +Sat Oct 25 16:51:40 1997 Gavin Koch <gavin@cygnus.com> + + * gencode.c (build_instruction): Follow sim_write's lead in using + BigEndianMem instead of !ByteSwapMem. + +Fri Oct 24 17:41:49 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * configure.in (sim_gen): Dependent on target, select type of + generator. Always select old style generator. + + configure: Re-generate. + + Makefile.in (tmp-igen, tmp-m16, clean-m16, clean-igen): New + targets. + (SIM_M16_CFLAGS, SIM_M16_ALL, SIM_M16_OBJ, BUILT_SRC_FROM_M16, + SIM_IGEN_CFLAGS, SIM_IGEN_ALL, SIM_IGEN_OBJ, BUILT_SRC_FROM_IGEN, + IGEN_TRACE, IGEN_INSN, IGEN_DC): Define + (SIM_EXTRA_CFLAGS, SIM_EXTRA_ALL, SIM_OBJS): Add member + SIM_@sim_gen@_*, set by autoconf. + +Wed Oct 22 12:52:06 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (NULLIFY_NEXT_INSTRUCTION, DELAY_SLOT): Define. + + * interp.c (ColdReset): Remove #ifdef HASFPU, check + CURRENT_FLOATING_POINT instead. + + * interp.c (ifetch32): New function. Fetch 32 bit instruction. + (address_translation): Raise exception InstructionFetch when + translation fails and isINSTRUCTION. + + * interp.c (sim_open, sim_write, sim_monitor, store_word, + sim_engine_run): Change type of of vaddr and paddr to + address_word. + (address_translation, prefetch, load_memory, store_memory, + cache_op): Change type of vAddr and pAddr to address_word. + + * gencode.c (build_instruction): Change type of vaddr and paddr to + address_word. + +Mon Oct 20 15:29:04 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (ALU64_END, ALU32_END): Use ALU*_OVERFLOW_RESULT + macro to obtain result of ALU op. + +Tue Oct 21 17:39:14 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_info): Call profile_print. + +Mon Oct 20 13:31:20 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (SIM_OBJS): Add sim-profile.o module. + + * sim-main.h (WITH_PROFILE): Do not define, defined in + common/sim-config.h. Use sim-profile module. + (simPROFILE): Delete defintion. + + * interp.c (PROFILE): Delete definition. + (mips_option_handler): Delete 'p', 'y' and 'x' profile options. + (sim_close): Delete code writing profile histogram. + (mips_set_profile, mips_set_profile_size, writeout16, writeout32): + Delete. + (sim_engine_run): Delete code profiling the PC. + +Mon Oct 20 13:31:20 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (SIGNEXTEND): Force type of result to unsigned_word. + + * interp.c (sim_monitor): Make register pointers of type + unsigned_word*. + + * sim-main.h: Make registers of type unsigned_word not + signed_word. + +Thu Oct 16 10:31:39 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sync_operation): Rename from SyncOperation, make + global, add SD argument. + (prefetch): Rename from Prefetch, make global, add SD argument. + (decode_coproc): Make global. + + * sim-main.h (SyncOperation, DecodeCoproc, Pefetch): Define. + + * gencode.c (build_instruction): Generate DecodeCoproc not + decode_coproc calls. + + * interp.c (SETFCC, GETFCC, PREVCOC1): Move to sim-main.h + (SizeFGR): Move to sim-main.h + (simHALTEX, simHALTIN, simTRACE, simPROFILE, simDELAYSLOT, + simSIGINT, simJALDELAYSLOT): Move to sim-main.h + (FP_FLAGS, FP_ENABLE, FP_CAUSE, IR, UF, OF, DZ, IO, UO): Move to + sim-main.h. + (FP_FS, FP_MASK_RM, FP_SH_RM, FP_RM_NEAREST, FP_RM_TOPINF, + FP_RM_TOMINF, GETRM): Move to sim-main.h. + (Uncached, CachedNoncoherent, CachedCoherent, Cached, + isINSTRUCTION, ..., AccessLength_BYTE, ...): Move to sim-main.h. + (UserMode, BigEndianMem, ByteSwapMem, ReverseEndian, + BigEndianCPU, status_KSU_mask, ...). Moved to sim-main.h + + * sim-main.h (ALU32_END, ALU64_END): Define. When overflow raise + exception. + (sim-alu.h): Include. + (NULLIFY_NIA, NULL_CIA, CPU_CIA): Define. + (sim_cia): Typedef to instruction_address. + +Thu Oct 16 10:31:41 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (interp.o): Rename generated file engine.c to + oengine.c. + + * interp.c: Update. + +Thu Oct 16 10:31:40 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * gencode.c (build_instruction): Use FPR_STATE not fpr_state. + +Thu Oct 16 10:31:39 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * gencode.c (build_instruction): For "FPSQRT", output correct + number of arguments to Recip. + +Tue Oct 14 17:38:18 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (interp.o): Depends on sim-main.h + + * interp.c (mips16_entry, ColdReset,dotrace): Add SD argument. Use GPR not registers. + + * sim-main.h (sim_cpu): Add registers, register_widths, fpr_state, + ipc, dspc, pending_*, hiaccess, loaccess, state, dsstate fields. + (REGISTERS, REGISTER_WIDTHS, FPR_STATE, IPC, DSPC, PENDING_*, + STATE, DSSTATE): Define + (GPR, FGRIDX, ..): Define. + + * interp.c (registers, register_widths, fpr_state, ipc, dspc, + pending_*, hiaccess, loaccess, state, dsstate): Delete globals. + (GPR, FGRIDX, ...): Delete macros. + + * interp.c: Update names to match defines from sim-main.h + +Tue Oct 14 15:11:45 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_monitor): Add SD argument. + (sim_warning): Delete. Replace calls with calls to + sim_io_eprintf. + (sim_error): Delete. Replace calls with sim_io_error. + (open_trace, writeout32, writeout16, getnum): Add SD argument. + (mips_set_profile): Rename from sim_set_profile. Add SD argument. + (mips_set_profile_size): Rename from sim_set_profile_size. Add SD + argument. + (mips_size): Rename from sim_size. Add SD argument. + + * interp.c (simulator): Delete global variable. + (callback): Delete global variable. + (mips_option_handler, sim_open, sim_write, sim_read, + sim_store_register, sim_fetch_register, sim_info, sim_do_command, + sim_size,sim_monitor): Use sim_io_* not callback->*. + (sim_open): ZALLOC simulator struct. + (PROFILE): Do not define. + +Tue Oct 14 13:35:48 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_open), support.h: Replace CHECKSIM macro found in + support.h with corresponding code. + + * sim-main.h (word64, uword64), support.h: Move definition to + sim-main.h. + (WORD64LO, WORD64HI, SET64LO, SET64HI, WORD64, UWORD64): Ditto. + + * support.h: Delete + * Makefile.in: Update dependencies + * interp.c: Do not include. + +Tue Oct 14 13:35:48 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (address_translation, load_memory, store_memory, + cache_op): Rename to from AddressTranslation et.al., make global, + add SD argument + + * sim-main.h (AddressTranslation, LoadMemory, StoreMemory, + CacheOp): Define. + + * interp.c (SignalException): Rename to signal_exception, make + global. + + * interp.c (Interrupt, ...): Move definitions to sim-main.h. + + * sim-main.h (SignalException, SignalExceptionInterrupt, + SignalExceptionInstructionFetch, SignalExceptionAddressStore, + SignalExceptionAddressLoad, SignalExceptionSimulatorFault, + SignalExceptionIntegerOverflow, SignalExceptionCoProcessorUnusable): + Define. + + * interp.c, support.h: Use. + +Tue Oct 14 13:19:20 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (ValueFPR, StoreFPR), sim-main.h: Make global, rename + to value_fpr / store_fpr. Add SD argument. + (NaN, Infinity, Less, Equal, AbsoluteValue, Negate, Add, Sub, + Multiply, Divide, Recip, SquareRoot, Convert): Make global. + + * sim-main.h (ValueFPR, StoreFPR): Define. + +Tue Oct 14 13:06:55 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_engine_run): Check consistency between configure + WITH_TARGET_WORD_BITSIZE and WITH_FLOATING_POINT and gensim GPRLEN + and HASFPU. + + * configure.in (mips_bitsize): Configure WITH_TARGET_WORD_BITSIZE. + (mips_fpu): Configure WITH_FLOATING_POINT. + (mips_endian): Configure WITH_TARGET_ENDIAN. + * configure: Update. + +Fri Oct 3 09:28:00 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Sep 29 14:45:00 1997 Bob Manson <manson@charmed.cygnus.com> + + * configure: Regenerated. + +Fri Sep 26 12:48:18 1997 Mark Alexander <marka@cygnus.com> + + * interp.c: Allow Debug, DEPC, and EPC registers to be examined in GDB. + +Thu Sep 25 11:15:22 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * gencode.c (print_igen_insn_models): Assume certain architectures + include all mips* instructions. + (print_igen_insn_format): Use data_size==-1 as marker for MIPS16 + instruction. + + * Makefile.in (tmp.igen): Add target. Generate igen input from + gencode file. + + * gencode.c (FEATURE_IGEN): Define. + (main): Add --igen option. Generate output in igen format. + (process_instructions): Format output according to igen option. + (print_igen_insn_format): New function. + (print_igen_insn_models): New function. + (process_instructions): Only issue warnings and ignore + instructions when no FEATURE_IGEN. + +Wed Sep 24 17:38:57 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (COP_SD, COP_LD): Add UNUSED to pacify GCC for some + MIPS targets. + +Tue Sep 23 11:04:38 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Sep 23 10:19:51 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (SIM_ALIGNMENT, SIM_ENDIAN, SIM_HOSTENDIAN, + SIM_RESERVED_BITS): Delete, moved to common. + (SIM_EXTRA_CFLAGS): Update. + +Mon Sep 22 11:46:20 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * configure.in: Configure non-strict memory alignment. + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Fri Sep 19 17:45:25 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sat Sep 20 14:07:28 1997 Gavin Koch <gavin@cygnus.com> + + * gencode.c (SDBBP,DERET): Added (3900) insns. + (RFE): Turn on for 3900. + * interp.c (DebugBreakPoint,DEPC,Debug,Debug_*): Added. + (dsstate): Made global. + (SUBTARGET_R3900): Added. + (CANCELDELAYSLOT): New. + (SignalException): Ignore SystemCall rather than ignore and + terminate. Add DebugBreakPoint handling. + (decode_coproc): New insns RFE, DERET; and new registers Debug + and DEPC protected by SUBTARGET_R3900. + (sim_engine_run): Use CANCELDELAYSLOT rather than clearing + bits explicitly. + * Makefile.in,configure.in: Add mips subtarget option. + * configure: Update. + +Fri Sep 19 09:33:27 1997 Gavin Koch <gavin@cygnus.com> + + * gencode.c: Add r3900 (tx39). + + +Tue Sep 16 15:52:04 1997 Gavin Koch <gavin@cygnus.com> + + * gencode.c (build_instruction): Don't need to subtract 4 for + JALR, just 2. + +Tue Sep 16 11:32:28 1997 Gavin Koch <gavin@cygnus.com> + + * interp.c: Correct some HASFPU problems. + +Mon Sep 15 17:36:15 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Fri Sep 12 12:01:39 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (mips_options): Fix samples option short form, should + be `x'. + +Thu Sep 11 09:35:29 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_info): Enable info code. Was just returning. + +Tue Sep 9 17:30:57 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (decode_coproc): Clarify warning about unsuported MTC0, + MFC0. + +Tue Sep 9 16:28:28 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * gencode.c (build_instruction): Use SIGNED64 for 64 bit + constants. + (build_instruction): Ditto for LL. + +Thu Sep 4 17:21:23 1997 Doug Evans <dje@seba> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Aug 27 18:13:22 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Wed Aug 27 14:12:27 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_open): Add call to sim_analyze_program, update + call to sim_config. + +Tue Aug 26 10:40:07 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_kill): Delete. + (sim_create_inferior): Add ABFD argument. Set PC from same. + (sim_load): Move code initializing trap handlers from here. + (sim_open): To here. + (sim_load): Delete, use sim-hload.c. + + * Makefile.in (SIM_OBJS): Add sim-hload.o module. + +Mon Aug 25 17:50:22 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Mon Aug 25 15:59:48 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_open): Add ABFD argument. + (sim_load): Move call to sim_config from here. + (sim_open): To here. Check return status. + +Fri Jul 25 15:00:45 1997 Gavin Koch <gavin@cygnus.com> + + * gencode.c (build_instruction): Two arg MADD should + not assign result to $0. + +Thu Jun 26 12:13:17 1997 Angela Marie Thomas (angela@cygnus.com) + + * sim/mips/configure: Change default_sim_endian to 0 (bi-endian) + * sim/mips/configure.in: Regenerate. + +Wed Jul 9 10:29:21 1997 Andrew Cagney <cagney@critters.cygnus.com> + + * interp.c (SUB_REG_UW, SUB_REG_SW, SUB_REG_*): Use more explicit + signed8, unsigned8 et.al. types. + + * interp.c (SUB_REG_FETCH): Handle both little and big endian + hosts when selecting subreg. + +Wed Jul 2 11:54:10 1997 Jeffrey A Law (law@cygnus.com) + + * interp.c (sim_engine_run): Reset the ZERO register to zero + regardless of FEATURE_WARN_ZERO. + * gencode.c (FEATURE_WARNINGS): Remove FEATURE_WARN_ZERO. + +Wed Jun 4 10:43:14 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (decode_coproc): Implement MTC0 N, CAUSE. + (SignalException): For BreakPoints ignore any mode bits and just + save the PC. + (SignalException): Always set the CAUSE register. + +Tue Jun 3 05:00:33 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (SignalException): Clear the simDELAYSLOT flag when an + exception has been taken. + + * interp.c: Implement the ERET and mt/f sr instructions. + +Sat May 31 00:44:16 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (SignalException): Don't bother restarting an + interrupt. + +Fri May 30 23:41:48 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (SignalException): Really take an interrupt. + (interrupt_event): Only deliver interrupts when enabled. + +Tue May 27 20:08:06 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_info): Only print info when verbose. + (sim_info) Use sim_io_printf for output. + +Tue May 27 14:22:23 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (CoProcPresent): Add UNUSED attribute - not used by all + mips architectures. + +Tue May 27 14:22:23 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_do_command): Check for common commands if a + simulator specific command fails. + +Thu May 22 09:32:03 1997 Gavin Koch <gavin@cygnus.com> + + * interp.c (sim_engine_run): ifdef out uses of simSTOP, simSTEP + and simBE when DEBUG is defined. + +Wed May 21 09:08:10 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (interrupt_event): New function. Pass exception event + onto exception handler. + + * configure.in: Check for stdlib.h. + * configure: Regenerate. + + * gencode.c (build_instruction): Add UNUSED attribute to tempS + variable declaration. + (build_instruction): Initialize memval1. + (build_instruction): Add UNUSED attribute to byte, bigend, + reverse. + (build_operands): Ditto. + + * interp.c: Fix GCC warnings. + (sim_get_quit_code): Delete. + + * configure.in: Add INLINE, ENDIAN, HOSTENDIAN and WARNINGS. + * Makefile.in: Ditto. + * configure: Re-generate. + + * Makefile.in (SIM_OBJS): Add sim-watch.o module. + +Tue May 20 15:08:56 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (mips_option_handler): New function parse argumes using + sim-options. + (myname): Replace with STATE_MY_NAME. + (sim_open): Delete check for host endianness - performed by + sim_config. + (simHOSTBE, simBE): Delete, replaced by sim-endian flags. + (sim_open): Move much of the initialization from here. + (sim_load): To here. After the image has been loaded and + endianness set. + (sim_open): Move ColdReset from here. + (sim_create_inferior): To here. + (sim_open): Make FP check less dependant on host endianness. + + * Makefile.in (SIM_RUN_OBJS): Set to nrun.o - use new version or + run. + * interp.c (sim_set_callbacks): Delete. + + * interp.c (membank, membank_base, membank_size): Replace with + STATE_MEMORY, STATE_MEM_SIZE, STATE_MEM_BASE. + (sim_open): Remove call to callback->init. gdb/run do this. + + * interp.c: Update + + * sim-main.h (SIM_HAVE_FLATMEM): Define. + + * interp.c (big_endian_p): Delete, replaced by + current_target_byte_order. + +Tue May 20 13:55:00 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (host_read_long, host_read_word, host_swap_word, + host_swap_long): Delete. Using common sim-endian. + (sim_fetch_register, sim_store_register): Use H2T. + (pipeline_ticks): Delete. Handled by sim-events. + (sim_info): Update. + (sim_engine_run): Update. + +Tue May 20 13:42:03 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_stop_reason): Move code determining simEXCEPTION + reason from here. + (SignalException): To here. Signal using sim_engine_halt. + (sim_stop_reason): Delete, moved to common. + +Tue May 20 10:19:48 1997 Andrew Cagney <cagney@b2.cygnus.com> + + * interp.c (sim_open): Add callback argument. + (sim_set_callbacks): Delete SIM_DESC argument. + (sim_size): Ditto. + +Mon May 19 18:20:38 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (SIM_OBJS): Add common modules. + + * interp.c (sim_set_callbacks): Also set SD callback. + (set_endianness, xfer_*, swap_*): Delete. + (host_read_word, host_read_long, host_swap_word, host_swap_long): + Change to functions using sim-endian macros. + (control_c, sim_stop): Delete, use common version. + (simulate): Convert into. + (sim_engine_run): This function. + (sim_resume): Delete. + + * interp.c (simulation): New variable - the simulator object. + (sim_kind): Delete global - merged into simulation. + (sim_load): Cleanup. Move PC assignment from here. + (sim_create_inferior): To here. + + * sim-main.h: New file. + * interp.c (sim-main.h): Include. + +Thu Apr 24 00:39:51 1997 Doug Evans <dje@canuck.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Apr 23 17:32:19 1997 Doug Evans <dje@canuck.cygnus.com> + + * tconfig.in (SIM_HAVE_BIENDIAN): Define. + +Mon Apr 21 17:16:13 1997 Gavin Koch <gavin@cygnus.com> + + * gencode.c (build_instruction): DIV instructions: check + for division by zero and integer overflow before using + host's division operation. + +Thu Apr 17 03:18:14 1997 Doug Evans <dje@canuck.cygnus.com> + + * Makefile.in (SIM_OBJS): Add sim-load.o. + * interp.c: #include bfd.h. + (target_byte_order): Delete. + (sim_kind, myname, big_endian_p): New static locals. + (sim_open): Set sim_kind, myname. Move call to set_endianness to + after argument parsing. Recognize -E arg, set endianness accordingly. + (sim_load): Return SIM_RC. New arg abfd. Call sim_load_file to + load file into simulator. Set PC from bfd. + (sim_create_inferior): Return SIM_RC. Delete arg start_address. + (set_endianness): Use big_endian_p instead of target_byte_order. + +Wed Apr 16 17:55:37 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * interp.c (sim_size): Delete prototype - conflicts with + definition in remote-sim.h. Correct definition. + +Mon Apr 7 15:45:02 1997 Andrew Cagney <cagney@kremvax.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Wed Apr 2 15:06:28 1997 Doug Evans <dje@canuck.cygnus.com> + + * interp.c (sim_open): New arg `kind'. + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Apr 2 14:34:19 1997 Andrew Cagney <cagney@kremvax.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Mar 25 11:38:22 1997 Doug Evans <dje@canuck.cygnus.com> + + * interp.c (sim_open): Set optind to 0 before calling getopt. + +Wed Mar 19 01:14:00 1997 Andrew Cagney <cagney@kremvax.cygnus.com> + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Mar 17 10:52:59 1997 Gavin Koch <gavin@cetus.cygnus.com> + + * interp.c : Replace uses of pr_addr with pr_uword64 + where the bit length is always 64 independent of SIM_ADDR. + (pr_uword64) : added. + +Mon Mar 17 15:10:07 1997 Andrew Cagney <cagney@kremvax.cygnus.com> + + * configure: Re-generate. + +Fri Mar 14 10:34:11 1997 Michael Meissner <meissner@cygnus.com> + + * configure: Regenerate to track ../common/aclocal.m4 changes. + +Thu Mar 13 12:51:36 1997 Doug Evans <dje@canuck.cygnus.com> + + * interp.c (sim_open): New SIM_DESC result. Argument is now + in argv form. + (other sim_*): New SIM_DESC argument. + +Mon Feb 24 22:47:14 1997 Dawn Perchik <dawn@cygnus.com> + + * interp.c: Fix printing of addresses for non-64-bit targets. + (pr_addr): Add function to print address based on size. + +Wed Feb 19 14:42:09 1997 Mark Alexander <marka@cygnus.com> + + * interp.c (simopen): Add support for LSI MiniRISC PMON vectors. + +Thu Feb 13 14:08:30 1997 Ian Lance Taylor <ian@cygnus.com> + + * gencode.c (build_mips16_operands): Correct computation of base + address for extended PC relative instruction. + +Thu Feb 6 17:16:15 1997 Ian Lance Taylor <ian@cygnus.com> + + * interp.c (mips16_entry): Add support for floating point cases. + (SignalException): Pass floating point cases to mips16_entry. + (ValueFPR): Don't restrict fmt_single and fmt_word to even + registers. + (StoreFPR): Likewise. Also, don't clobber fpr + 1 for fmt_single + or fmt_word. + (COP_LW): Pass fmt_word rather than fmt_uninterpreted to StoreFPR, + and then set the state to fmt_uninterpreted. + (COP_SW): Temporarily set the state to fmt_word while calling + ValueFPR. + +Tue Feb 4 16:48:25 1997 Ian Lance Taylor <ian@cygnus.com> + + * gencode.c (build_instruction): The high order may be set in the + comparison flags at any ISA level, not just ISA 4. + +Tue Feb 4 13:33:30 1997 Doug Evans <dje@canuck.cygnus.com> + + * Makefile.in (@COMMON_MAKEFILE_FRAG): Use + COMMON_{PRE,POST}_CONFIG_FRAG instead. + * configure.in: sinclude ../common/aclocal.m4. + * configure: Regenerated. + +Fri Jan 31 11:11:45 1997 Ian Lance Taylor <ian@cygnus.com> + + * configure: Rebuild after change to aclocal.m4. + +Thu Jan 23 11:46:23 1997 Stu Grossman (grossman@critters.cygnus.com) + + * configure configure.in Makefile.in: Update to new configure + scheme which is more compatible with WinGDB builds. + * configure.in: Improve comment on how to run autoconf. + * configure: Re-run autoconf to get new ../common/aclocal.m4. + * Makefile.in: Use autoconf substitution to install common + makefile fragment. + +Wed Jan 8 12:39:03 1997 Jim Wilson <wilson@cygnus.com> + + * gencode.c (build_instruction): Use BigEndianCPU instead of + ByteSwapMem. + +Thu Jan 02 22:23:04 1997 Mark Alexander <marka@cygnus.com> + + * interp.c (sim_monitor): Make output to stdout visible in + wingdb's I/O log window. + +Tue Dec 31 07:04:00 1996 Mark Alexander <marka@cygnus.com> + + * support.h: Undo previous change to SIGTRAP + and SIGQUIT values. + +Mon Dec 30 17:36:06 1996 Ian Lance Taylor <ian@cygnus.com> + + * interp.c (store_word, load_word): New static functions. + (mips16_entry): New static function. + (SignalException): Look for mips16 entry and exit instructions. + (simulate): Use the correct index when setting fpr_state after + doing a pending move. + +Sun Dec 29 09:37:18 1996 Mark Alexander <marka@cygnus.com> + + * interp.c: Fix byte-swapping code throughout to work on + both little- and big-endian hosts. + +Sun Dec 29 09:18:32 1996 Mark Alexander <marka@cygnus.com> + + * support.h: Make definitions of SIGTRAP and SIGQUIT consistent + with gdb/config/i386/xm-windows.h. + +Fri Dec 27 22:48:51 1996 Mark Alexander <marka@cygnus.com> + + * gencode.c (build_instruction): Work around MSVC++ code gen bug + that messes up arithmetic shifts. + +Fri Dec 20 11:04:05 1996 Stu Grossman (grossman@critters.cygnus.com) + + * support.h: Use _WIN32 instead of __WIN32__. Also add defs for + SIGTRAP and SIGQUIT for _WIN32. + +Thu Dec 19 14:07:27 1996 Ian Lance Taylor <ian@cygnus.com> + + * gencode.c (build_instruction) [MUL]: Cast operands to word64, to + force a 64 bit multiplication. + (build_instruction) [OR]: In mips16 mode, don't do anything if the + destination register is 0, since that is the default mips16 nop + instruction. + +Mon Dec 16 14:59:38 1996 Ian Lance Taylor <ian@cygnus.com> + + * gencode.c (MIPS16_DECODE): SWRASP is I8, not RI. + (build_endian_shift): Don't check proc64. + (build_instruction): Always set memval to uword64. Cast op2 to + uword64 when shifting it left in memory instructions. Always use + the same code for stores--don't special case proc64. + + * gencode.c (build_mips16_operands): Fix base PC value for PC + relative operands. + (build_instruction): Call JALDELAYSLOT rather than DELAYSLOT for a + jal instruction. + * interp.c (simJALDELAYSLOT): Define. + (JALDELAYSLOT): Define. + (INDELAYSLOT, INJALDELAYSLOT): Define. + (simulate): Clear simJALDELAYSLOT when simDELAYSLOT is cleared. + +Tue Dec 24 22:11:20 1996 Angela Marie Thomas (angela@cygnus.com) + + * interp.c (sim_open): add flush_cache as a PMON routine + (sim_monitor): handle flush_cache by ignoring it + +Wed Dec 11 13:53:51 1996 Jim Wilson <wilson@cygnus.com> + + * gencode.c (build_instruction): Use !ByteSwapMem instead of + BigEndianMem. + * interp.c (CONFIG, config_EP_{mask,shift,D,DxxDxx, config_BE): Delete. + (BigEndianMem): Rename to ByteSwapMem and change sense. + (BigEndianCPU, sim_write, LoadMemory, StoreMemory): Change + BigEndianMem references to !ByteSwapMem. + (set_endianness): New function, with prototype. + (sim_open): Call set_endianness. + (sim_info): Use simBE instead of BigEndianMem. + (xfer_direct_word, xfer_direct_long, swap_direct_word, + swap_direct_long, xfer_big_word, xfer_big_long, xfer_little_word, + xfer_little_long, swap_word, swap_long): Delete unnecessary MSC_VER + ifdefs, keeping the prototype declaration. + (swap_word): Rewrite correctly. + (ColdReset): Delete references to CONFIG. Delete endianness related + code; moved to set_endianness. + +Tue Dec 10 11:32:04 1996 Jim Wilson <wilson@cygnus.com> + + * gencode.c (build_instruction, case JUMP): Truncate PC to 32 bits. + * interp.c (CHECKHILO): Define away. + (simSIGINT): New macro. + (membank_size): Increase from 1MB to 2MB. + (control_c): New function. + (sim_resume): Rename parameter signal to signal_number. Add local + variable prev. Call signal before and after simulate. + (sim_stop_reason): Add simSIGINT support. + (sim_warning, sim_error, dotrace, SignalException): Define as stdarg + functions always. + (sim_warning): Delete call to SignalException. Do call printf_filtered + if logfh is NULL. + (AddressTranslation): Add #ifdef DEBUG around debugging message and + a call to sim_warning. + +Wed Nov 27 11:53:50 1996 Ian Lance Taylor <ian@cygnus.com> + + * gencode.c (process_instructions): If ! proc64, skip DOUBLEWORD + 16 bit instructions. + +Tue Nov 26 11:53:12 1996 Ian Lance Taylor <ian@cygnus.com> + + Add support for mips16 (16 bit MIPS implementation): + * gencode.c (inst_type): Add mips16 instruction encoding types. + (GETDATASIZEINSN): Define. + (MIPS_DECODE): Add REG flag to dsllv, dsrav, and dsrlv. Add + jalx. Add LEFT flag to mfhi and mflo. Add RIGHT flag to mthi and + mtlo. + (MIPS16_DECODE): New table, for mips16 instructions. + (bitmap_val): New static function. + (struct mips16_op): Define. + (mips16_op_table): New table, for mips16 operands. + (build_mips16_operands): New static function. + (process_instructions): If PC is odd, decode a mips16 + instruction. Break out instruction handling into new + build_instruction function. + (build_instruction): New static function, broken out of + process_instructions. Check modifiers rather than flags for SHIFT + bit count and m[ft]{hi,lo} direction. + (usage): Pass program name to fprintf. + (main): Remove unused variable this_option_optind. Change + ``*loptarg++'' to ``loptarg++''. + (my_strtoul): Parenthesize && within ||. + * interp.c (LoadMemory): Accept a halfword pAddr if vAddr is odd. + (simulate): If PC is odd, fetch a 16 bit instruction, and + increment PC by 2 rather than 4. + * configure.in: Add case for mips16*-*-*. + * configure: Rebuild. + +Fri Nov 22 08:49:36 1996 Mark Alexander <marka@cygnus.com> + + * interp.c: Allow -t to enable tracing in standalone simulator. + Fix garbage output in trace file and error messages. + +Wed Nov 20 01:54:37 1996 Doug Evans <dje@canuck.cygnus.com> + + * Makefile.in: Delete stuff moved to ../common/Make-common.in. + (SIM_{OBJS,EXTRA_CFLAGS,EXTRA_CLEAN}): Define. + * configure.in: Simplify using macros in ../common/aclocal.m4. + * configure: Regenerated. + * tconfig.in: New file. + +Tue Nov 12 13:34:00 1996 Dawn Perchik <dawn@cygnus.com> + + * interp.c: Fix bugs in 64-bit port. + Use ansi function declarations for msvc compiler. + Initialize and test file pointer in trace code. + Prevent duplicate definition of LAST_EMED_REGNUM. + +Tue Oct 15 11:07:06 1996 Mark Alexander <marka@cygnus.com> + + * interp.c (xfer_big_long): Prevent unwanted sign extension. + +Thu Sep 26 17:35:00 1996 James G. Smith <jsmith@cygnus.co.uk> + + * interp.c (SignalException): Check for explicit terminating + breakpoint value. + * gencode.c: Pass instruction value through SignalException() + calls for Trap, Breakpoint and Syscall. + +Thu Sep 26 11:35:17 1996 James G. Smith <jsmith@cygnus.co.uk> + + * interp.c (SquareRoot): Add HAVE_SQRT check to ensure sqrt() is + only used on those hosts that provide it. + * configure.in: Add sqrt() to list of functions to be checked for. + * config.in: Re-generated. + * configure: Re-generated. + +Fri Sep 20 15:47:12 1996 Ian Lance Taylor <ian@cygnus.com> + + * gencode.c (process_instructions): Call build_endian_shift when + expanding STORE RIGHT, to fix swr. + * support.h (SIGNEXTEND): If the sign bit is not set, explicitly + clear the high bits. + * interp.c (Convert): Fix fmt_single to fmt_long to not truncate. + Fix float to int conversions to produce signed values. + +Thu Sep 19 15:34:17 1996 Ian Lance Taylor <ian@cygnus.com> + + * gencode.c (MIPS_DECODE): Set UNSIGNED for multu instruction. + (process_instructions): Correct handling of nor instruction. + Correct shift count for 32 bit shift instructions. Correct sign + extension for arithmetic shifts to not shift the number of bits in + the type. Fix 64 bit multiply high word calculation. Fix 32 bit + unsigned multiply. Fix ldxc1 and friends to use coprocessor 1. + Fix madd. + * interp.c (CHECKHILO): Don't set HIACCESS, LOACCESS, or HLPC. + It's OK to have a mult follow a mult. What's not OK is to have a + mult follow an mfhi. + (Convert): Comment out incorrect rounding code. + +Mon Sep 16 11:38:16 1996 James G. Smith <jsmith@cygnus.co.uk> + + * interp.c (sim_monitor): Improved monitor printf + simulation. Tidied up simulator warnings, and added "--log" option + for directing warning message output. + * gencode.c: Use sim_warning() rather than WARNING macro. + +Thu Aug 22 15:03:12 1996 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (gencode): Depend upon gencode.o, getopt.o, and + getopt1.o, rather than on gencode.c. Link objects together. + Don't link against -liberty. + (gencode.o, getopt.o, getopt1.o): New targets. + * gencode.c: Include <ctype.h> and "ansidecl.h". + (AND): Undefine after including "ansidecl.h". + (ULONG_MAX): Define if not defined. + (OP_*): Don't define macros; now defined in opcode/mips.h. + (main): Call my_strtoul rather than strtoul. + (my_strtoul): New static function. + +Wed Jul 17 18:12:38 1996 Stu Grossman (grossman@critters.cygnus.com) + + * gencode.c (process_instructions): Generate word64 and uword64 + instead of `long long' and `unsigned long long' data types. + * interp.c: #include sysdep.h to get signals, and define default + for SIGBUS. + * (Convert): Work around for Visual-C++ compiler bug with type + conversion. + * support.h: Make things compile under Visual-C++ by using + __int64 instead of `long long'. Change many refs to long long + into word64/uword64 typedefs. + +Wed Jun 26 12:24:55 1996 Jason Molenda (crash@godzilla.cygnus.co.jp) + + * Makefile.in (bindir, libdir, datadir, mandir, infodir, includedir, + INSTALL_PROGRAM, INSTALL_DATA): Use autoconf-set values. + (docdir): Removed. + * configure.in (AC_PREREQ): autoconf 2.5 or higher. + (AC_PROG_INSTALL): Added. + (AC_PROG_CC): Moved to before configure.host call. + * configure: Rebuilt. + +Wed Jun 5 08:28:13 1996 James G. Smith <jsmith@cygnus.co.uk> + + * configure.in: Define @SIMCONF@ depending on mips target. + * configure: Rebuild. + * Makefile.in (run): Add @SIMCONF@ to control simulator + construction. + * gencode.c: Change LOADDRMASK to 64bit memory model only. + * interp.c: Remove some debugging, provide more detailed error + messages, update memory accesses to use LOADDRMASK. + +Mon Jun 3 11:55:03 1996 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Add calls to AC_CONFIG_HEADER, AC_CHECK_HEADERS, + AC_CHECK_LIB, and AC_CHECK_FUNCS. Change AC_OUTPUT to set + stamp-h. + * configure: Rebuild. + * config.in: New file, generated by autoheader. + * interp.c: Include "config.h". Include <stdlib.h>, <string.h>, + and <strings.h> if they exist. Replace #ifdef sun with #ifdef + HAVE_ANINT and HAVE_AINT, as appropriate. + * Makefile.in (run): Use @LIBS@ rather than -lm. + (interp.o): Depend upon config.h. + (Makefile): Just rebuild Makefile. + (clean): Remove stamp-h. + (mostlyclean): Make the same as clean, not as distclean. + (config.h, stamp-h): New targets. + +Fri May 10 00:41:17 1996 James G. Smith <jsmith@cygnus.co.uk> + + * interp.c (ColdReset): Fix boolean test. Make all simulator + globals static. + +Wed May 8 15:12:58 1996 James G. Smith <jsmith@cygnus.co.uk> + + * interp.c (xfer_direct_word, xfer_direct_long, + swap_direct_word, swap_direct_long, xfer_big_word, + xfer_big_long, xfer_little_word, xfer_little_long, + swap_word,swap_long): Added. + * interp.c (ColdReset): Provide function indirection to + host<->simulated_target transfer routines. + * interp.c (sim_store_register, sim_fetch_register): Updated to + make use of indirected transfer routines. + +Fri Apr 19 15:48:24 1996 James G. Smith <jsmith@cygnus.co.uk> + + * gencode.c (process_instructions): Ensure FP ABS instruction + recognised. + * interp.c (AbsoluteValue): Add routine. Also provide simple PMON + system call support. + +Wed Apr 10 09:51:38 1996 James G. Smith <jsmith@cygnus.co.uk> + + * interp.c (sim_do_command): Complain if callback structure not + initialised. + +Thu Mar 28 13:50:51 1996 James G. Smith <jsmith@cygnus.co.uk> + + * interp.c (Convert): Provide round-to-nearest and round-to-zero + support for Sun hosts. + * Makefile.in (gencode): Ensure the host compiler and libraries + used for cross-hosted build. + +Wed Mar 27 14:42:12 1996 James G. Smith <jsmith@cygnus.co.uk> + + * interp.c, gencode.c: Some more (TODO) tidying. + +Thu Mar 7 11:19:33 1996 James G. Smith <jsmith@cygnus.co.uk> + + * gencode.c, interp.c: Replaced explicit long long references with + WORD64HI, WORD64LO, SET64HI and SET64LO macro calls. + * support.h (SET64LO, SET64HI): Macros added. + +Wed Feb 21 12:16:21 1996 Ian Lance Taylor <ian@cygnus.com> + + * configure: Regenerate with autoconf 2.7. + +Tue Jan 30 08:48:18 1996 Fred Fish <fnf@cygnus.com> + + * interp.c (LoadMemory): Enclose text following #endif in /* */. + * support.h: Remove superfluous "1" from #if. + * support.h (CHECKSIM): Remove stray 'a' at end of line. + +Mon Dec 4 11:44:40 1995 Jamie Smith <jsmith@cygnus.com> + + * interp.c (StoreFPR): Control UndefinedResult() call on + WARN_RESULT manifest. + +Fri Dec 1 16:37:19 1995 James G. Smith <jsmith@cygnus.co.uk> + + * gencode.c: Tidied instruction decoding, and added FP instruction + support. + + * interp.c: Added dineroIII, and BSD profiling support. Also + run-time FP handling. + +Sun Oct 22 00:57:18 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk> + + * Changelog, Makefile.in, README.Cygnus, configure, configure.in, + gencode.c, interp.c, support.h: created. diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in new file mode 100644 index 0000000..3e4bd5f --- /dev/null +++ b/sim/mips/Makefile.in @@ -0,0 +1,293 @@ +# Makefile template for Configure for the MIPS simulator. +# Written by Cygnus Support. + +## COMMON_PRE_CONFIG_FRAG + +srcdir=@srcdir@ +srcroot=$(srcdir)/../../ + +# Object files created by various simulator generators. + + +SIM_IGEN_OBJ = \ + support.o \ + itable.o \ + semantics.o \ + idecode.o \ + icache.o \ + @mips_igen_engine@ \ + irun.o \ + + +SIM_M16_OBJ = \ + m16_support.o \ + m16_semantics.o \ + m16_idecode.o \ + m16_icache.o \ + \ + m32_support.o \ + m32_semantics.o \ + m32_idecode.o \ + m32_icache.o \ + \ + itable.o \ + m16run.o \ + + +MIPS_EXTRA_OBJS = @mips_extra_objs@ +MIPS_EXTRA_LIBS = @mips_extra_libs@ + +SIM_OBJS = \ + $(SIM_@sim_gen@_OBJ) \ + $(SIM_NEW_COMMON_OBJS) \ + $(MIPS_EXTRA_OBJS) \ + interp.o \ + sim-main.o \ + sim-hload.o \ + sim-engine.o \ + sim-stop.o \ + sim-resume.o \ + sim-reason.o \ + + +# List of flags to always pass to $(CC). +SIM_SUBTARGET=@SIM_SUBTARGET@ +SIM_EXTRA_CFLAGS = $(SIM_SUBTARGET) + +SIM_EXTRA_CLEAN = clean-extra + +SIM_EXTRA_ALL = $(SIM_@sim_gen@_ALL) + +SIM_EXTRA_LIBS = $(MIPS_EXTRA_LIBS) + +# List of main object files for `run'. +SIM_RUN_OBJS = nrun.o + + + +## COMMON_POST_CONFIG_FRAG + +interp.o: $(srcdir)/interp.c config.h sim-main.h itable.h + + +../igen/igen: + cd ../igen && $(MAKE) + +IGEN_TRACE= # -G omit-line-numbers # -G trace-rule-selection -G trace-rule-rejection -G trace-entries # -G trace-all +IGEN_INSN=$(srcdir)/mips.igen +IGEN_DC=$(srcdir)/mips.dc +M16_DC=$(srcdir)/m16.dc +IGEN_INCLUDE=\ + $(srcdir)/m16.igen \ + $(srcdir)/tx.igen \ + $(srcdir)/vr.igen \ + +# NB: Since these can be built by a number of generators, care +# must be taken to ensure that they are only dependant on +# one of those generators. +BUILT_SRC_FROM_GEN = \ + itable.h \ + itable.c \ + +SIM_IGEN_ALL = tmp-igen +SIM_M16_ALL = tmp-m16 + +$(BUILT_SRC_FROM_GEN): $(SIM_@sim_gen@_ALL) + + + +BUILT_SRC_FROM_IGEN = \ + icache.h \ + icache.c \ + idecode.h \ + idecode.c \ + semantics.h \ + semantics.c \ + model.h \ + model.c \ + support.h \ + support.c \ + engine.h \ + engine.c \ + irun.c \ + +$(BUILT_SRC_FROM_IGEN): tmp-igen + +tmp-igen: $(IGEN_INSN) $(IGEN_DC) ../igen/igen $(IGEN_INCLUDE) + cd ../igen && $(MAKE) + ../igen/igen \ + $(IGEN_TRACE) \ + -I $(srcdir) \ + -Werror \ + -Wnodiscard \ + @sim_igen_flags@ \ + -G gen-direct-access \ + -G gen-zero-r0 \ + -B 32 \ + -H 31 \ + -i $(IGEN_INSN) \ + -o $(IGEN_DC) \ + -x \ + -n icache.h -hc tmp-icache.h \ + -n icache.c -c tmp-icache.c \ + -n semantics.h -hs tmp-semantics.h \ + -n semantics.c -s tmp-semantics.c \ + -n idecode.h -hd tmp-idecode.h \ + -n idecode.c -d tmp-idecode.c \ + -n model.h -hm tmp-model.h \ + -n model.c -m tmp-model.c \ + -n support.h -hf tmp-support.h \ + -n support.c -f tmp-support.c \ + -n itable.h -ht tmp-itable.h \ + -n itable.c -t tmp-itable.c \ + -n engine.h -he tmp-engine.h \ + -n engine.c -e tmp-engine.c \ + -n irun.c -r tmp-irun.c + $(srcdir)/../../move-if-change tmp-icache.h icache.h + $(srcdir)/../../move-if-change tmp-icache.c icache.c + $(srcdir)/../../move-if-change tmp-idecode.h idecode.h + $(srcdir)/../../move-if-change tmp-idecode.c idecode.c + $(srcdir)/../../move-if-change tmp-semantics.h semantics.h + $(srcdir)/../../move-if-change tmp-semantics.c semantics.c + $(srcdir)/../../move-if-change tmp-model.h model.h + $(srcdir)/../../move-if-change tmp-model.c model.c + $(srcdir)/../../move-if-change tmp-support.h support.h + $(srcdir)/../../move-if-change tmp-support.c support.c + $(srcdir)/../../move-if-change tmp-itable.h itable.h + $(srcdir)/../../move-if-change tmp-itable.c itable.c + $(srcdir)/../../move-if-change tmp-engine.h engine.h + $(srcdir)/../../move-if-change tmp-engine.c engine.c + $(srcdir)/../../move-if-change tmp-irun.c irun.c + touch tmp-igen + +semantics.o: sim-main.h semantics.c $(SIM_EXTRA_DEPS) +engine.o: sim-main.h engine.c $(SIM_EXTRA_DEPS) +support.o: sim-main.h support.c $(SIM_EXTRA_DEPS) +idecode.o: sim-main.h idecode.c $(SIM_EXTRA_DEPS) +itable.o: sim-main.h itable.c $(SIM_EXTRA_DEPS) + + + + +BUILT_SRC_FROM_M16 = \ + m16_icache.h \ + m16_icache.c \ + m16_idecode.h \ + m16_idecode.c \ + m16_semantics.h \ + m16_semantics.c \ + m16_model.h \ + m16_model.c \ + m16_support.h \ + m16_support.c \ + \ + m32_icache.h \ + m32_icache.c \ + m32_idecode.h \ + m32_idecode.c \ + m32_semantics.h \ + m32_semantics.c \ + m32_model.h \ + m32_model.c \ + m32_support.h \ + m32_support.c \ + +$(BUILT_SRC_FROM_M16): tmp-m16 + +tmp-m16: $(IGEN_INSN) $(IGEN_DC) ../igen/igen $(IGEN_INCLUDE) + cd ../igen && $(MAKE) + ../igen/igen \ + $(IGEN_TRACE) \ + -I $(srcdir) \ + -Werror \ + -Wnodiscard \ + @sim_m16_flags@ \ + -G gen-direct-access \ + -G gen-zero-r0 \ + -B 16 \ + -H 15 \ + -i $(IGEN_INSN) \ + -o $(M16_DC) \ + -P m16_ \ + -x \ + -n m16_icache.h -hc tmp-icache.h \ + -n m16_icache.c -c tmp-icache.c \ + -n m16_semantics.h -hs tmp-semantics.h \ + -n m16_semantics.c -s tmp-semantics.c \ + -n m16_idecode.h -hd tmp-idecode.h \ + -n m16_idecode.c -d tmp-idecode.c \ + -n m16_model.h -hm tmp-model.h \ + -n m16_model.c -m tmp-model.c \ + -n m16_support.h -hf tmp-support.h \ + -n m16_support.c -f tmp-support.c \ + # + $(srcdir)/../../move-if-change tmp-icache.h m16_icache.h + $(srcdir)/../../move-if-change tmp-icache.c m16_icache.c + $(srcdir)/../../move-if-change tmp-idecode.h m16_idecode.h + $(srcdir)/../../move-if-change tmp-idecode.c m16_idecode.c + $(srcdir)/../../move-if-change tmp-semantics.h m16_semantics.h + $(srcdir)/../../move-if-change tmp-semantics.c m16_semantics.c + $(srcdir)/../../move-if-change tmp-model.h m16_model.h + $(srcdir)/../../move-if-change tmp-model.c m16_model.c + $(srcdir)/../../move-if-change tmp-support.h m16_support.h + $(srcdir)/../../move-if-change tmp-support.c m16_support.c + ../igen/igen \ + $(IGEN_TRACE) \ + -I $(srcdir) \ + -Werror \ + -Wnodiscard \ + @sim_igen_flags@ \ + -G gen-direct-access \ + -G gen-zero-r0 \ + -B 32 \ + -H 31 \ + -i $(IGEN_INSN) \ + -o $(IGEN_DC) \ + -P m32_ \ + -x \ + -n m32_icache.h -hc tmp-icache.h \ + -n m32_icache.c -c tmp-icache.c \ + -n m32_semantics.h -hs tmp-semantics.h \ + -n m32_semantics.c -s tmp-semantics.c \ + -n m32_idecode.h -hd tmp-idecode.h \ + -n m32_idecode.c -d tmp-idecode.c \ + -n m32_model.h -hm tmp-model.h \ + -n m32_model.c -m tmp-model.c \ + -n m32_support.h -hf tmp-support.h \ + -n m32_support.c -f tmp-support.c \ + # + $(srcdir)/../../move-if-change tmp-icache.h m32_icache.h + $(srcdir)/../../move-if-change tmp-icache.c m32_icache.c + $(srcdir)/../../move-if-change tmp-idecode.h m32_idecode.h + $(srcdir)/../../move-if-change tmp-idecode.c m32_idecode.c + $(srcdir)/../../move-if-change tmp-semantics.h m32_semantics.h + $(srcdir)/../../move-if-change tmp-semantics.c m32_semantics.c + $(srcdir)/../../move-if-change tmp-model.h m32_model.h + $(srcdir)/../../move-if-change tmp-model.c m32_model.c + $(srcdir)/../../move-if-change tmp-support.h m32_support.h + $(srcdir)/../../move-if-change tmp-support.c m32_support.c + ../igen/igen \ + $(IGEN_TRACE) \ + -I $(srcdir) \ + -Werror \ + -Wnodiscard \ + -Wnowidth \ + @sim_igen_flags@ @sim_m16_flags@ \ + -G gen-direct-access \ + -G gen-zero-r0 \ + -i $(IGEN_INSN) \ + -n itable.h -ht tmp-itable.h \ + -n itable.c -t tmp-itable.c \ + # + $(srcdir)/../../move-if-change tmp-itable.h itable.h + $(srcdir)/../../move-if-change tmp-itable.c itable.c + touch tmp-m16 + + +clean-extra: + rm -f $(BUILT_SRC_FROM_GEN) + rm -f $(BUILT_SRC_FROM_IGEN) + rm -f $(BUILT_SRC_FROM_M16) + rm -f tmp-* + rm -f m16* m32* itable* + diff --git a/sim/mips/acconfig.h b/sim/mips/acconfig.h new file mode 100644 index 0000000..f9b87a1 --- /dev/null +++ b/sim/mips/acconfig.h @@ -0,0 +1,15 @@ + +/* Define to 1 if NLS is requested. */ +#undef ENABLE_NLS + +/* Define as 1 if you have catgets and don't want to use GNU gettext. */ +#undef HAVE_CATGETS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Define as 1 if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if your locale.h file contains LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES diff --git a/sim/mips/config.in b/sim/mips/config.in new file mode 100644 index 0000000..dbd6508 --- /dev/null +++ b/sim/mips/config.in @@ -0,0 +1,174 @@ +/* config.in. Generated automatically from configure.in by autoheader. */ + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have <alloca.h> and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define to `long' if <sys/types.h> doesn't define. */ +#undef off_t + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* Define as the return type of signal handlers (int or void). */ +#undef RETSIGTYPE + +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +#undef size_t + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +/* Define to 1 if NLS is requested. */ +#undef ENABLE_NLS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Define as 1 if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if your locale.h file contains LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Define if you have the __argz_count function. */ +#undef HAVE___ARGZ_COUNT + +/* Define if you have the __argz_next function. */ +#undef HAVE___ARGZ_NEXT + +/* Define if you have the __argz_stringify function. */ +#undef HAVE___ARGZ_STRINGIFY + +/* Define if you have the __setfpucw function. */ +#undef HAVE___SETFPUCW + +/* Define if you have the aint function. */ +#undef HAVE_AINT + +/* Define if you have the anint function. */ +#undef HAVE_ANINT + +/* Define if you have the dcgettext function. */ +#undef HAVE_DCGETTEXT + +/* Define if you have the getcwd function. */ +#undef HAVE_GETCWD + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the getrusage function. */ +#undef HAVE_GETRUSAGE + +/* Define if you have the munmap function. */ +#undef HAVE_MUNMAP + +/* Define if you have the putenv function. */ +#undef HAVE_PUTENV + +/* Define if you have the setenv function. */ +#undef HAVE_SETENV + +/* Define if you have the setlocale function. */ +#undef HAVE_SETLOCALE + +/* Define if you have the sigaction function. */ +#undef HAVE_SIGACTION + +/* Define if you have the sqrt function. */ +#undef HAVE_SQRT + +/* Define if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if you have the strcasecmp function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the strchr function. */ +#undef HAVE_STRCHR + +/* Define if you have the time function. */ +#undef HAVE_TIME + +/* Define if you have the <argz.h> header file. */ +#undef HAVE_ARGZ_H + +/* Define if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the <fpu_control.h> header file. */ +#undef HAVE_FPU_CONTROL_H + +/* Define if you have the <limits.h> header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the <locale.h> header file. */ +#undef HAVE_LOCALE_H + +/* Define if you have the <malloc.h> header file. */ +#undef HAVE_MALLOC_H + +/* Define if you have the <nl_types.h> header file. */ +#undef HAVE_NL_TYPES_H + +/* Define if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the <sys/param.h> header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the <sys/resource.h> header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define if you have the <sys/time.h> header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the <time.h> header file. */ +#undef HAVE_TIME_H + +/* Define if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the <values.h> header file. */ +#undef HAVE_VALUES_H + +/* Define if you have the m library (-lm). */ +#undef HAVE_LIBM diff --git a/sim/mips/configure b/sim/mips/configure new file mode 100755 index 0000000..58be065 --- /dev/null +++ b/sim/mips/configure @@ -0,0 +1,4890 @@ +#! /bin/sh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +sim_inline="-DDEFAULT_INLINE=0" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# This file is derived from `gettext.m4'. The difference is that the +# included macros assume Cygnus-style source and build trees. + +# Macro to add for using GNU gettext. +# Ulrich Drepper <drepper@cygnus.com>, 1995. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 3 + + + + + +# Search path for a program which passes the given test. +# Ulrich Drepper <drepper@cygnus.com>, 1996. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + + + +# Check whether LC_MESSAGES is available in <locale.h>. +# Ulrich Drepper <drepper@cygnus.com>, 1995. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + + + +# Check to see if we're running under Cygwin32, without using +# AC_CANONICAL_*. If so, set output variable CYGWIN32 to "yes". +# Otherwise set it to "no". + + + +# Check to see if we're running under Win32, without using +# AC_CANONICAL_*. If so, set output variable EXEEXT to ".exe". +# Otherwise set it to "". + + + + + + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12.2 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --disable-nls do not use Native Language Support" +ac_help="$ac_help + --with-included-gettext use the GNU gettext library included here" +ac_help="$ac_help + --enable-maintainer-mode Enable developer functionality." +ac_help="$ac_help + --enable-sim-bswap Use Host specific BSWAP instruction." +ac_help="$ac_help + --enable-sim-cflags=opts Extra CFLAGS for use in building simulator" +ac_help="$ac_help + --enable-sim-debug=opts Enable debugging flags" +ac_help="$ac_help + --enable-sim-stdio Specify whether to use stdio for console input/output." +ac_help="$ac_help + --enable-sim-trace=opts Enable tracing flags" +ac_help="$ac_help + --enable-sim-profile=opts Enable profiling flags" +ac_help="$ac_help + --enable-sim-inline=inlines Specify which functions should be inlined." +ac_help="$ac_help + --enable-sim-alignment=align Specify strict, nonstrict or forced alignment of memory accesses." +ac_help="$ac_help + --enable-sim-hostendian=end Specify host byte endian orientation." +ac_help="$ac_help + --enable-build-warnings[=LIST] Enable build-time compiler warnings" +ac_help="$ac_help + --enable-sim-endian=endian Specify target byte endian orientation." +ac_help="$ac_help + --enable-sim-bitsize=N Specify target bitsize (32 or 64)." +ac_help="$ac_help + --enable-sim-float Specify that the target processor has floating point hardware." +ac_help="$ac_help + --enable-sim-smp=n Specify number of processors to configure for (default ${default_sim_smp})." +ac_help="$ac_help + --enable-sim-hardware=LIST Specify the hardware to be included in the build." +ac_help="$ac_help + --with-x use the X Window System" +ac_help="$ac_help + --with-sim-gpu2=path Use GPU2 library under given directory" +ac_help="$ac_help + --with-x use the X Window System" +ac_help="$ac_help + --with-sim-funit=path Use target FP library under given directory" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12.2" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=Makefile.in + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:705: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext <<EOF +#line 720 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:726: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext <<EOF +#line 737 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:743: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext <<EOF +#line 754 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:760: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:785: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 +echo "configure:812: checking for POSIXized ISC" >&5 +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 +then + echo "$ac_t""yes" 1>&6 + ISC=yes # If later tests want to check for ISC. + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +else + echo "$ac_t""no" 1>&6 + ISC= +fi + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:833: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 838 "configure" +#include "confdefs.h" +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:846: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 863 "configure" +#include "confdefs.h" +#include <string.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 881 "configure" +#include "confdefs.h" +#include <stdlib.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext <<EOF +#line 902 "configure" +#include "confdefs.h" +#include <ctype.h> +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:937: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 942 "configure" +#include "confdefs.h" + +int main() { + +/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *ccp; +char **p; +/* NEC SVR4.0.2 mips cc rejects this. */ +struct point {int x, y;}; +static struct point const zero = {0,0}; +/* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in an arm + of an if-expression whose if-part is not a constant expression */ +const char *g = "string"; +ccp = &g + (g ? g-g : 0); +/* HPUX 7.0 cc rejects these. */ +++ccp; +p = (char**) ccp; +ccp = (char const *const *) p; +{ /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; +} +{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; +} +{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; +} +{ /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:991: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:1012: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat > conftest.$ac_ext <<EOF +#line 1019 "configure" +#include "confdefs.h" + +int main() { +} $ac_kw foo() { +; return 0; } +EOF +if { (eval echo configure:1026: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_inline=$ac_kw; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done + +fi + +echo "$ac_t""$ac_cv_c_inline" 1>&6 +case "$ac_cv_c_inline" in + inline | yes) ;; + no) cat >> confdefs.h <<\EOF +#define inline +EOF + ;; + *) cat >> confdefs.h <<EOF +#define inline $ac_cv_c_inline +EOF + ;; +esac + +echo $ac_n "checking for off_t""... $ac_c" 1>&6 +echo "configure:1052: checking for off_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1057 "configure" +#include "confdefs.h" +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_off_t=yes +else + rm -rf conftest* + ac_cv_type_off_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_off_t" 1>&6 +if test $ac_cv_type_off_t = no; then + cat >> confdefs.h <<\EOF +#define off_t long +EOF + +fi + +echo $ac_n "checking for size_t""... $ac_c" 1>&6 +echo "configure:1085: checking for size_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1090 "configure" +#include "confdefs.h" +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_size_t=yes +else + rm -rf conftest* + ac_cv_type_size_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_size_t" 1>&6 +if test $ac_cv_type_size_t = no; then + cat >> confdefs.h <<\EOF +#define size_t unsigned +EOF + +fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 +echo "configure:1120: checking for working alloca.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1125 "configure" +#include "confdefs.h" +#include <alloca.h> +int main() { +char *p = alloca(2 * sizeof(int)); +; return 0; } +EOF +if { (eval echo configure:1132: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_header_alloca_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_alloca_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_alloca_h" 1>&6 +if test $ac_cv_header_alloca_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA_H 1 +EOF + +fi + +echo $ac_n "checking for alloca""... $ac_c" 1>&6 +echo "configure:1153: checking for alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1158 "configure" +#include "confdefs.h" + +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int main() { +char *p = (char *) alloca(1); +; return 0; } +EOF +if { (eval echo configure:1186: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_func_alloca_works=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_func_alloca_works=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_func_alloca_works" 1>&6 +if test $ac_cv_func_alloca_works = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA 1 +EOF + +fi + +if test $ac_cv_func_alloca_works = no; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.${ac_objext} + cat >> confdefs.h <<\EOF +#define C_ALLOCA 1 +EOF + + +echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 +echo "configure:1218: checking whether alloca needs Cray hooks" >&5 +if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1223 "configure" +#include "confdefs.h" +#if defined(CRAY) && ! defined(CRAY2) +webecray +#else +wenotbecray +#endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "webecray" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_os_cray=yes +else + rm -rf conftest* + ac_cv_os_cray=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_os_cray" 1>&6 +if test $ac_cv_os_cray = yes; then +for ac_func in _getb67 GETB67 getb67; do + echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1248: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1253 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1276: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<EOF +#define CRAY_STACKSEG_END $ac_func +EOF + + break +else + echo "$ac_t""no" 1>&6 +fi + +done +fi + +echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 +echo "configure:1303: checking stack direction for C alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat > conftest.$ac_ext <<EOF +#line 1311 "configure" +#include "confdefs.h" +find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} +main () +{ + exit (find_stack_direction() < 0); +} +EOF +if { (eval echo configure:1330: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_c_stack_direction=1 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_stack_direction=-1 +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_c_stack_direction" 1>&6 +cat >> confdefs.h <<EOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +EOF + +fi + +for ac_hdr in unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1355: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1360 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1365: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1394: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1399 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1422: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +echo $ac_n "checking for working mmap""... $ac_c" 1>&6 +echo "configure:1447: checking for working mmap" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat > conftest.$ac_ext <<EOF +#line 1455 "configure" +#include "confdefs.h" + +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the filesystem buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propogated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ +#include <sys/types.h> +#include <fcntl.h> +#include <sys/mman.h> + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include <unistd.h> +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} + +EOF +if { (eval echo configure:1595: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_mmap_fixed_mapped=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 +if test $ac_cv_func_mmap_fixed_mapped = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP 1 +EOF + +fi + + +# autoconf.info says this should be called right after AC_INIT. + + +ac_aux_dir= +for ac_dir in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; +esac + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:1668: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:1689: checking target system type" >&5 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$target" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:1707: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1751: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1780: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1830: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1861: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <<EOF +#line 1871 "configure" +#include "confdefs.h" +main(){return(0);} +EOF +if { (eval echo configure:1875: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1895: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:1900: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1909: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1928: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1971: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# Put a plausible default for CC_FOR_BUILD in Makefile. +if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' +else + CC_FOR_BUILD=gcc +fi + + + + +AR=${AR-ar} + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2037: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +ALL_LINGUAS= + + for ac_hdr in argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h values.h sys/param.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2071: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2076 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2081: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + for ac_func in getcwd munmap putenv setenv setlocale strchr strcasecmp \ +__argz_count __argz_stringify __argz_next +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2111: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2116 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2139: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + + if test "${ac_cv_func_stpcpy+set}" != "set"; then + for ac_func in stpcpy +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2168: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2173 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2196: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + fi + if test "${ac_cv_func_stpcpy}" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_STPCPY 1 +EOF + + fi + + if test $ac_cv_header_locale_h = yes; then + echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6 +echo "configure:2230: checking for LC_MESSAGES" >&5 +if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2235 "configure" +#include "confdefs.h" +#include <locale.h> +int main() { +return LC_MESSAGES +; return 0; } +EOF +if { (eval echo configure:2242: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + am_cv_val_LC_MESSAGES=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + am_cv_val_LC_MESSAGES=no +fi +rm -f conftest* +fi + +echo "$ac_t""$am_cv_val_LC_MESSAGES" 1>&6 + if test $am_cv_val_LC_MESSAGES = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_LC_MESSAGES 1 +EOF + + fi + fi + echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6 +echo "configure:2263: checking whether NLS is requested" >&5 + # Check whether --enable-nls or --disable-nls was given. +if test "${enable_nls+set}" = set; then + enableval="$enable_nls" + USE_NLS=$enableval +else + USE_NLS=yes +fi + + echo "$ac_t""$USE_NLS" 1>&6 + + + USE_INCLUDED_LIBINTL=no + + if test "$USE_NLS" = "yes"; then + cat >> confdefs.h <<\EOF +#define ENABLE_NLS 1 +EOF + + echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6 +echo "configure:2283: checking whether included gettext is requested" >&5 + # Check whether --with-included-gettext or --without-included-gettext was given. +if test "${with_included_gettext+set}" = set; then + withval="$with_included_gettext" + nls_cv_force_use_gnu_gettext=$withval +else + nls_cv_force_use_gnu_gettext=no +fi + + echo "$ac_t""$nls_cv_force_use_gnu_gettext" 1>&6 + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for libintl.h""... $ac_c" 1>&6 +echo "configure:2302: checking for libintl.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2307 "configure" +#include "confdefs.h" +#include <libintl.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2312: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6 +echo "configure:2329: checking for gettext in libc" >&5 +if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2334 "configure" +#include "confdefs.h" +#include <libintl.h> +int main() { +return (int) gettext ("") +; return 0; } +EOF +if { (eval echo configure:2341: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + gt_cv_func_gettext_libc=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gt_cv_func_gettext_libc=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6 + + if test "$gt_cv_func_gettext_libc" != "yes"; then + echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6 +echo "configure:2357: checking for bindtextdomain in -lintl" >&5 +ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lintl $LIBS" +cat > conftest.$ac_ext <<EOF +#line 2365 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char bindtextdomain(); + +int main() { +bindtextdomain() +; return 0; } +EOF +if { (eval echo configure:2376: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6 +echo "configure:2392: checking for gettext in libintl" >&5 +if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2397 "configure" +#include "confdefs.h" + +int main() { +return (int) gettext ("") +; return 0; } +EOF +if { (eval echo configure:2404: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + gt_cv_func_gettext_libintl=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gt_cv_func_gettext_libintl=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gt_cv_func_gettext_libintl" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + fi + + if test "$gt_cv_func_gettext_libc" = "yes" \ + || test "$gt_cv_func_gettext_libintl" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_GETTEXT 1 +EOF + + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2432: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + echo "$ac_t""$MSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + if test "$MSGFMT" != "no"; then + for ac_func in dcgettext +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2466: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2471 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2494: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2521: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2556: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + cat > conftest.$ac_ext <<EOF +#line 2588 "configure" +#include "confdefs.h" + +int main() { +extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr +; return 0; } +EOF +if { (eval echo configure:2596: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + CATOBJEXT=.gmo + DATADIRNAME=share +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CATOBJEXT=.mo + DATADIRNAME=lib +fi +rm -f conftest* + INSTOBJEXT=.mo + fi + fi + +else + echo "$ac_t""no" 1>&6 +fi + + + + if test "$CATOBJEXT" = "NONE"; then + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + INTLOBJS="\$(GETTOBJS)" + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2628: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="msgfmt" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + echo "$ac_t""$MSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2662: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2697: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.gmo + INSTOBJEXT=.mo + DATADIRNAME=share + INTLDEPS='$(top_builddir)/../intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + if test "$XGETTEXT" != ":"; then + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + echo "$ac_t""found xgettext programs is not GNU xgettext; ignore it" 1>&6 + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + else + DATADIRNAME=share + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + # If this is used in GNU gettext we have to set USE_NLS to `yes' + # because some of the sources are only built for this goal. + if test "$PACKAGE" = gettext; then + USE_NLS=yes + USE_INCLUDED_LIBINTL=yes + fi + + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + + + + + + + + + + + + + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6 +echo "configure:2787: checking for catalogs to be installed" >&5 + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + echo "$ac_t""$LINGUAS" 1>&6 + fi + + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + if test $ac_cv_header_locale_h = yes; then + INCLUDE_LOCALE_H="#include <locale.h>" + else + INCLUDE_LOCALE_H="\ +/* The system does not provide the header <locale.h>. Take care yourself. */" + fi + + + if test -f $srcdir/po2tbl.sed.in; then + if test "$CATOBJEXT" = ".cat"; then + ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6 +echo "configure:2815: checking for linux/version.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2820 "configure" +#include "confdefs.h" +#include <linux/version.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2825: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + msgformat=linux +else + echo "$ac_t""no" 1>&6 +msgformat=xopen +fi + + + sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed + fi + sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \ + $srcdir/po2tbl.sed.in > po2tbl.sed + fi + + if test "$PACKAGE" = "gettext"; then + GT_NO="#NO#" + GT_YES= + else + GT_NO= + GT_YES="#YES#" + fi + + + + MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs" + + + l= + + + if test -d $srcdir/po; then + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + fi + + +# Check for common headers. +# FIXME: Seems to me this can cause problems for i386-windows hosts. +# At one point there were hardcoded AC_DEFINE's if ${host} = i386-*-windows*. +for ac_hdr in stdlib.h string.h strings.h unistd.h time.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2894: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2899 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2904: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_hdr in sys/time.h sys/resource.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2934: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2939 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2944: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_hdr in fcntl.h fpu_control.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2974: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2979 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2984: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_hdr in dlfcn.h errno.h sys/stat.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:3014: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3019 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:3024: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in getrusage time sigaction __setfpucw +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3053: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3058 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3081: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + +# Check for socket libraries +echo $ac_n "checking for bind in -lsocket""... $ac_c" 1>&6 +echo "configure:3108: checking for bind in -lsocket" >&5 +ac_lib_var=`echo socket'_'bind | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $LIBS" +cat > conftest.$ac_ext <<EOF +#line 3116 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char bind(); + +int main() { +bind() +; return 0; } +EOF +if { (eval echo configure:3127: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lsocket $LIBS" + +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 +echo "configure:3155: checking for gethostbyname in -lnsl" >&5 +ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lnsl $LIBS" +cat > conftest.$ac_ext <<EOF +#line 3163 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname(); + +int main() { +gethostbyname() +; return 0; } +EOF +if { (eval echo configure:3174: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lnsl $LIBS" + +else + echo "$ac_t""no" 1>&6 +fi + + +. ${srcdir}/../../bfd/configure.host + + + +USE_MAINTAINER_MODE=no +# Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + case "${enableval}" in + yes) MAINT="" USE_MAINTAINER_MODE=yes ;; + no) MAINT="#" ;; + *) { echo "configure: error: "--enable-maintainer-mode does not take a value"" 1>&2; exit 1; }; MAINT="#" ;; +esac +if test x"$silent" != x"yes" && test x"$MAINT" = x""; then + echo "Setting maintainer mode" 6>&1 +fi +else + MAINT="#" +fi + + + +# Check whether --enable-sim-bswap or --disable-sim-bswap was given. +if test "${enable_sim_bswap+set}" = set; then + enableval="$enable_sim_bswap" + case "${enableval}" in + yes) sim_bswap="-DWITH_BSWAP=1 -DUSE_BSWAP=1";; + no) sim_bswap="-DWITH_BSWAP=0";; + *) { echo "configure: error: "--enable-sim-bswap does not take a value"" 1>&2; exit 1; }; sim_bswap="";; +esac +if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then + echo "Setting bswap flags = $sim_bswap" 6>&1 +fi +else + sim_bswap="" +fi + + + +# Check whether --enable-sim-cflags or --disable-sim-cflags was given. +if test "${enable_sim_cflags+set}" = set; then + enableval="$enable_sim_cflags" + case "${enableval}" in + yes) sim_cflags="-O2 -fomit-frame-pointer";; + trace) { echo "configure: error: "Please use --enable-sim-debug instead."" 1>&2; exit 1; }; sim_cflags="";; + no) sim_cflags="";; + *) sim_cflags=`echo "${enableval}" | sed -e "s/,/ /g"`;; +esac +if test x"$silent" != x"yes" && test x"$sim_cflags" != x""; then + echo "Setting sim cflags = $sim_cflags" 6>&1 +fi +else + sim_cflags="" +fi + + + +# Check whether --enable-sim-debug or --disable-sim-debug was given. +if test "${enable_sim_debug+set}" = set; then + enableval="$enable_sim_debug" + case "${enableval}" in + yes) sim_debug="-DDEBUG=7 -DWITH_DEBUG=7";; + no) sim_debug="-DDEBUG=0 -DWITH_DEBUG=0";; + *) sim_debug="-DDEBUG='(${enableval})' -DWITH_DEBUG='(${enableval})'";; +esac +if test x"$silent" != x"yes" && test x"$sim_debug" != x""; then + echo "Setting sim debug = $sim_debug" 6>&1 +fi +else + sim_debug="" +fi + + + +# Check whether --enable-sim-stdio or --disable-sim-stdio was given. +if test "${enable_sim_stdio+set}" = set; then + enableval="$enable_sim_stdio" + case "${enableval}" in + yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";; + no) sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-stdio"" 1>&2; exit 1; }; sim_stdio="";; +esac +if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then + echo "Setting stdio flags = $sim_stdio" 6>&1 +fi +else + sim_stdio="" +fi + + + +# Check whether --enable-sim-trace or --disable-sim-trace was given. +if test "${enable_sim_trace+set}" = set; then + enableval="$enable_sim_trace" + case "${enableval}" in + yes) sim_trace="-DTRACE=1 -DWITH_TRACE=-1";; + no) sim_trace="-DTRACE=0 -DWITH_TRACE=0";; + [-0-9]*) + sim_trace="-DTRACE='(${enableval})' -DWITH_TRACE='(${enableval})'";; + [a-z]*) + sim_trace="" + for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + if test x"$sim_trace" = x; then + sim_trace="-DWITH_TRACE='(TRACE_$x" + else + sim_trace="${sim_trace}|TRACE_$x" + fi + done + sim_trace="$sim_trace)'" ;; +esac +if test x"$silent" != x"yes" && test x"$sim_trace" != x""; then + echo "Setting sim trace = $sim_trace" 6>&1 +fi +else + sim_trace="" +fi + + + +# Check whether --enable-sim-profile or --disable-sim-profile was given. +if test "${enable_sim_profile+set}" = set; then + enableval="$enable_sim_profile" + case "${enableval}" in + yes) sim_profile="-DPROFILE=1 -DWITH_PROFILE=-1";; + no) sim_profile="-DPROFILE=0 -DWITH_PROFILE=0";; + [-0-9]*) + sim_profile="-DPROFILE='(${enableval})' -DWITH_PROFILE='(${enableval})'";; + [a-z]*) + sim_profile="" + for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + if test x"$sim_profile" = x; then + sim_profile="-DWITH_PROFILE='(PROFILE_$x" + else + sim_profile="${sim_profile}|PROFILE_$x" + fi + done + sim_profile="$sim_profile)'" ;; +esac +if test x"$silent" != x"yes" && test x"$sim_profile" != x""; then + echo "Setting sim profile = $sim_profile" 6>&1 +fi +else + sim_profile="" +fi + + + +echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 +echo "configure:3350: checking return type of signal handlers" >&5 +if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3355 "configure" +#include "confdefs.h" +#include <sys/types.h> +#include <signal.h> +#ifdef signal +#undef signal +#endif +#ifdef __cplusplus +extern "C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif + +int main() { +int i; +; return 0; } +EOF +if { (eval echo configure:3372: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_type_signal=void +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_type_signal=int +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_type_signal" 1>&6 +cat >> confdefs.h <<EOF +#define RETSIGTYPE $ac_cv_type_signal +EOF + + + +echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 +echo "configure:3392: checking for executable suffix" >&5 +if eval "test \"`echo '$''{'am_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$CYGWIN32" = yes; then +am_cv_exeext=.exe +else +cat > am_c_test.c << 'EOF' +int main() { +/* Nothing needed here */ +} +EOF +${CC-cc} -o am_c_test $CFLAGS $CPPFLAGS $LDFLAGS am_c_test.c $LIBS 1>&5 +am_cv_exeext=`ls am_c_test.* | grep -v am_c_test.c | sed -e s/am_c_test//` +rm -f am_c_test* +fi + +test x"${am_cv_exeext}" = x && am_cv_exeext=no +fi +EXEEXT="" +test x"${am_cv_exeext}" != xno && EXEEXT=${am_cv_exeext} +echo "$ac_t""${am_cv_exeext}" 1>&6 + + +sim_link_files= +sim_link_links= + +sim_link_links=tconfig.h +if test -f ${srcdir}/tconfig.in +then + sim_link_files=tconfig.in +else + sim_link_files=../common/tconfig.in +fi + +# targ-vals.def points to the libc macro description file. +case "${target}" in +*-*-*) TARG_VALS_DEF=../common/nltvals.def ;; +esac +sim_link_files="${sim_link_files} ${TARG_VALS_DEF}" +sim_link_links="${sim_link_links} targ-vals.def" + + + + +default_sim_inline="" +# Check whether --enable-sim-inline or --disable-sim-inline was given. +if test "${enable_sim_inline+set}" = set; then + enableval="$enable_sim_inline" + sim_inline="" +case "$enableval" in + no) sim_inline="-DDEFAULT_INLINE=0";; + 0) sim_inline="-DDEFAULT_INLINE=0";; + yes | 2) sim_inline="-DDEFAULT_INLINE=ALL_C_INLINE";; + 1) sim_inline="-DDEFAULT_INLINE=INLINE_LOCALS";; + *) for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + new_flag="" + case "$x" in + *_INLINE=*) new_flag="-D$x";; + *=*) new_flag=`echo "$x" | sed -e "s/=/_INLINE=/" -e "s/^/-D/"`;; + *_INLINE) new_flag="-D$x=ALL_C_INLINE";; + *) new_flag="-D$x""_INLINE=ALL_C_INLINE";; + esac + if test x"$sim_inline" = x""; then + sim_inline="$new_flag" + else + sim_inline="$sim_inline $new_flag" + fi + done;; +esac +if test x"$silent" != x"yes" && test x"$sim_inline" != x""; then + echo "Setting inline flags = $sim_inline" 6>&1 +fi +else + +if test "x$cross_compiling" = "xno"; then + if test x"$GCC" != "x" -a x"${default_sim_inline}" != "x" ; then + sim_inline="${default_sim_inline}" + if test x"$silent" != x"yes"; then + echo "Setting inline flags = $sim_inline" 6>&1 + fi + else + sim_inline="" + fi +else + sim_inline="-DDEFAULT_INLINE=0" +fi +fi + +wire_alignment="NONSTRICT_ALIGNMENT" +default_alignment="" + +# Check whether --enable-sim-alignment or --disable-sim-alignment was given. +if test "${enable_sim_alignment+set}" = set; then + enableval="$enable_sim_alignment" + case "${enableval}" in + strict | STRICT) sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";; + nonstrict | NONSTRICT) sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";; + forced | FORCED) sim_alignment="-DWITH_ALIGNMENT=FORCED_ALIGNMENT";; + yes) if test x"$wire_alignment" != x; then + sim_alignment="-DWITH_ALIGNMENT=${wire_alignment}" + else + if test x"$default_alignment" != x; then + sim_alignment="-DWITH_ALIGNMENT=${default_alignment}" + else + echo "No hard-wired alignment for target $target" 1>&6 + sim_alignment="-DWITH_ALIGNMENT=0" + fi + fi;; + no) if test x"$default_alignment" != x; then + sim_alignment="-DWITH_DEFAULT_ALIGNMENT=${default_alignment}" + else + if test x"$wire_alignment" != x; then + sim_alignment="-DWITH_DEFAULT_ALIGNMENT=${wire_alignment}" + else + echo "No default alignment for target $target" 1>&6 + sim_alignment="-DWITH_DEFAULT_ALIGNMENT=0" + fi + fi;; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-alignment"" 1>&2; exit 1; }; sim_alignment="";; +esac +if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then + echo "Setting alignment flags = $sim_alignment" 6>&1 +fi +else + if test x"$default_alignment" != x; then + sim_alignment="-DWITH_DEFAULT_ALIGNMENT=${default_alignment}" +else + if test x"$wire_alignment" != x; then + sim_alignment="-DWITH_ALIGNMENT=${wire_alignment}" + else + sim_alignment= + fi +fi +fi + + +# Check whether --enable-sim-hostendian or --disable-sim-hostendian was given. +if test "${enable_sim_hostendian+set}" = set; then + enableval="$enable_sim_hostendian" + case "${enableval}" in + no) sim_hostendian="-DWITH_HOST_BYTE_ORDER=0";; + b*|B*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN";; + l*|L*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN";; + *) { echo "configure: error: "Unknown value $enableval for --enable-sim-hostendian"" 1>&2; exit 1; }; sim_hostendian="";; +esac +if test x"$silent" != x"yes" && test x"$sim_hostendian" != x""; then + echo "Setting hostendian flags = $sim_hostendian" 6>&1 +fi +else + +if test "x$cross_compiling" = "xno"; then + echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 +echo "configure:3545: checking whether byte ordering is bigendian" >&5 +if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_bigendian=unknown +# See if sys/param.h defines the BYTE_ORDER macro. +cat > conftest.$ac_ext <<EOF +#line 3552 "configure" +#include "confdefs.h" +#include <sys/types.h> +#include <sys/param.h> +int main() { + +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif +; return 0; } +EOF +if { (eval echo configure:3563: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + # It does; now see whether it defined to BIG_ENDIAN or not. +cat > conftest.$ac_ext <<EOF +#line 3567 "configure" +#include "confdefs.h" +#include <sys/types.h> +#include <sys/param.h> +int main() { + +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif +; return 0; } +EOF +if { (eval echo configure:3578: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_bigendian=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_bigendian=no +fi +rm -f conftest* +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +if test $ac_cv_c_bigendian = unknown; then +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 3598 "configure" +#include "confdefs.h" +main () { + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +} +EOF +if { (eval echo configure:3611: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_c_bigendian=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_bigendian=yes +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_c_bigendian" 1>&6 +if test $ac_cv_c_bigendian = yes; then + cat >> confdefs.h <<\EOF +#define WORDS_BIGENDIAN 1 +EOF + +fi + + if test $ac_cv_c_bigendian = yes; then + sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN" + else + sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN" + fi +else + sim_hostendian="-DWITH_HOST_BYTE_ORDER=0" +fi +fi + + +# Check whether --enable-build-warnings or --disable-build-warnings was given. +if test "${enable_build_warnings+set}" = set; then + enableval="$enable_build_warnings" + build_warnings="-Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations" +case "${enableval}" in + yes) ;; + no) build_warnings="-w";; + ,*) t=`echo "${enableval}" | sed -e "s/,/ /g"` + build_warnings="${build_warnings} ${t}";; + *,) t=`echo "${enableval}" | sed -e "s/,/ /g"` + build_warnings="${t} ${build_warnings}";; + *) build_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;; +esac +if test x"$silent" != x"yes" && test x"$build_warnings" != x""; then + echo "Setting warning flags = $build_warnings" 6>&1 +fi +else + build_warnings="" +fi + + +# DEPRECATED +# +# Instead of defining a `subtarget' macro, code should be checking +# the value of {STATE,CPU}_ARCHITECTURE to identify the architecture +# in question. +# +case "${target}" in + mips*tx39*) SIM_SUBTARGET="-DSUBTARGET_R3900=1";; + *) SIM_SUBTARGET="";; +esac + + + + +# +# Select the byte order of the target +# +mips_endian= +default_endian= +case "${target}" in + mips64el*-*-*) mips_endian=LITTLE_ENDIAN ;; + mips64*-*-*) default_endian=BIG_ENDIAN ;; + mips16*-*-*) default_endian=BIG_ENDIAN ;; + mips*-*-*) default_endian=BIG_ENDIAN ;; + *) default_endian=BIG_ENDIAN ;; +esac + +wire_endian="$mips_endian" +default_endian="$default_endian" +# Check whether --enable-sim-endian or --disable-sim-endian was given. +if test "${enable_sim_endian+set}" = set; then + enableval="$enable_sim_endian" + case "${enableval}" in + b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";; + l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";; + yes) if test x"$wire_endian" != x; then + sim_endian="-DWITH_TARGET_BYTE_ORDER=${wire_endian}" + else + if test x"$default_endian" != x; then + sim_endian="-DWITH_TARGET_BYTE_ORDER=${default_endian}" + else + echo "No hard-wired endian for target $target" 1>&6 + sim_endian="-DWITH_TARGET_BYTE_ORDER=0" + fi + fi;; + no) if test x"$default_endian" != x; then + sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=${default_endian}" + else + if test x"$wire_endian" != x; then + sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=${wire_endian}" + else + echo "No default endian for target $target" 1>&6 + sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=0" + fi + fi;; + *) { echo "configure: error: "Unknown value $enableval for --enable-sim-endian"" 1>&2; exit 1; }; sim_endian="";; +esac +if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then + echo "Setting endian flags = $sim_endian" 6>&1 +fi +else + if test x"$default_endian" != x; then + sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=${default_endian}" +else + if test x"$wire_endian" != x; then + sim_endian="-DWITH_TARGET_BYTE_ORDER=${wire_endian}" + else + sim_endian= + fi +fi +fi + + + + +# +# Select the bitsize of the target +# +mips_addr_bitsize= +case "${target}" in + mips64*-*-*) mips_bitsize=64 ; mips_msb=63 ;; + mips16*-*-*) mips_bitsize=64 ; mips_msb=63 ;; + mips*-*-*) mips_bitsize=32 ; mips_msb=31 ;; + *) mips_bitsize=64 ; mips_msb=63 ;; +esac +wire_word_bitsize="$mips_bitsize" +wire_word_msb="$mips_msb" +wire_address_bitsize="$mips_addr_bitsize" +wire_cell_bitsize="" +# Check whether --enable-sim-bitsize or --disable-sim-bitsize was given. +if test "${enable_sim_bitsize+set}" = set; then + enableval="$enable_sim_bitsize" + sim_bitsize= +case "${enableval}" in + 64,63 | 64,63,* ) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=64 -DWITH_TARGET_WORD_MSB=63";; + 32,31 | 32,31,* ) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=31";; + 64,0 | 64,0,* ) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=0";; + 32,0 | 64,0,* ) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=0";; + 32) if test x"$wire_word_msb" != x -a x"$wire_word_msb" != x0; then + sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=31" + else + sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=0" + fi ;; + 64) if test x"$wire_word_msb" != x -a x"$wire_word_msb" != x0; then + sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=64 -DWITH_TARGET_WORD_MSB=63" + else + sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=64 -DWITH_TARGET_WORD_MSB=0" + fi ;; + *) { echo "configure: error: "--enable-sim-bitsize was given $enableval. Expected 32 or 64"" 1>&2; exit 1; } ;; +esac +# address bitsize +tmp=`echo "${enableval}" | sed -e "s/^[0-9]*,*[0-9]*,*//"` +case x"${tmp}" in + x ) ;; + x32 | x32,* ) sim_bitsize="${sim_bitsize} -DWITH_TARGET_ADDRESS_BITSIZE=32" ;; + x64 | x64,* ) sim_bitsize="${sim_bitsize} -DWITH_TARGET_ADDRESS_BITSIZE=64" ;; + * ) { echo "configure: error: "--enable-sim-bitsize was given address size $enableval. Expected 32 or 64"" 1>&2; exit 1; } ;; +esac +# cell bitsize +tmp=`echo "${enableval}" | sed -e "s/^[0-9]*,*[0-9*]*,*[0-9]*,*//"` +case x"${tmp}" in + x ) ;; + x32 | x32,* ) sim_bitsize="${sim_bitsize} -DWITH_TARGET_CELL_BITSIZE=32" ;; + x64 | x64,* ) sim_bitsize="${sim_bitsize} -DWITH_TARGET_CELL_BITSIZE=64" ;; + * ) { echo "configure: error: "--enable-sim-bitsize was given cell size $enableval. Expected 32 or 64"" 1>&2; exit 1; } ;; +esac +if test x"$silent" != x"yes" && test x"$sim_bitsize" != x""; then + echo "Setting bitsize flags = $sim_bitsize" 6>&1 +fi +else + sim_bitsize="" +if test x"$wire_word_bitsize" != x; then + sim_bitsize="$sim_bitsize -DWITH_TARGET_WORD_BITSIZE=$wire_word_bitsize" +fi +if test x"$wire_word_msb" != x; then + sim_bitsize="$sim_bitsize -DWITH_TARGET_WORD_MSB=$wire_word_msb" +fi +if test x"$wire_address_bitsize" != x; then + sim_bitsize="$sim_bitsize -DWITH_TARGET_ADDRESS_BITSIZE=$wire_address_bitsize" +fi +if test x"$wire_cell_bitsize" != x; then + sim_bitsize="$sim_bitsize -DWITH_TARGET_CELL_BITSIZE=$wire_cell_bitsize" +fi +fi + + + + +# +# Select the floating hardware support of the target +# +mips_fpu=HARDWARE_FLOATING_POINT +mips_fpu_bitsize= +case "${target}" in + mips*tx39*) mips_fpu=HARD_FLOATING_POINT + mips_fpu_bitsize=32 + ;; + mips64*-*-*) mips_fpu=HARD_FLOATING_POINT ;; + mips16*-*-*) mips_fpu=HARD_FLOATING_POINT ;; + mips*-*-*) mips_fpu=HARD_FLOATING_POINT ; mips_fpu_bitsize=32 ;; + *) mips_fpu=HARD_FLOATING_POINT ;; +esac + +default_sim_float="$mips_fpu" +default_sim_float_bitsize="$mips_fpu_bitsize" +# Check whether --enable-sim-float or --disable-sim-float was given. +if test "${enable_sim_float+set}" = set; then + enableval="$enable_sim_float" + case "${enableval}" in + yes | hard) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";; + no | soft) sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";; + 32) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT -DWITH_TARGET_FLOATING_POINT_BITSIZE=32";; + 64) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT -DWITH_TARGET_FLOATING_POINT_BITSIZE=64";; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-float"" 1>&2; exit 1; }; sim_float="";; +esac +if test x"$silent" != x"yes" && test x"$sim_float" != x""; then + echo "Setting float flags = $sim_float" 6>&1 +fi +else + +sim_float= +if test x"${default_sim_float}" != x""; then + sim_float="-DWITH_FLOATING_POINT=${default_sim_float}" +fi +if test x"${default_sim_float_bitsize}" != x""; then + sim_float="$sim_float -DWITH_TARGET_FLOATING_POINT_BITSIZE=${default_sim_float_bitsize}" +fi + +fi + + + + +# +# Select the level of SMP support +# +case "${target}" in + *) mips_smp=0 ;; +esac + +default_sim_smp="$mips_smp" +# Check whether --enable-sim-smp or --disable-sim-smp was given. +if test "${enable_sim_smp+set}" = set; then + enableval="$enable_sim_smp" + case "${enableval}" in + yes) sim_smp="-DWITH_SMP=5" ; sim_igen_smp="-N 5";; + no) sim_smp="-DWITH_SMP=0" ; sim_igen_smp="-N 0";; + *) sim_smp="-DWITH_SMP=$enableval" ; sim_igen_smp="-N $enableval";; +esac +if test x"$silent" != x"yes" && test x"$sim_smp" != x""; then + echo "Setting smp flags = $sim_smp" 6>&1 +fi +else + sim_smp="-DWITH_SMP=${default_sim_smp}" ; sim_igen_smp="-N ${default_sim_smp}" +if test x"$silent" != x"yes"; then + echo "Setting smp flags = $sim_smp" 6>&1 +fi +fi + + + + +# +# Select the IGEN architecture +# +sim_gen=IGEN +sim_igen_machine="-M mipsIV" +sim_m16_machine="-M mips16" +sim_igen_filter="32,64,f" +sim_m16_filter="16" +case "${target}" in + mips*tx39*) sim_gen=IGEN + sim_igen_filter="32,f" + sim_igen_machine="-M r3900" + ;; + mips64vr43*-*-*) sim_gen=IGEN + sim_igen_machine="-M mipsIV" + ;; + mips64vr5*-*-*) sim_gen=IGEN + sim_igen_machine="-M vr5000" + ;; + mips64vr41*) sim_gen=M16 + sim_igen_machine="-M vr4100" + sim_m16_machine="-M vr4100" + sim_igen_filter="32,64,f" + sim_m16_filter="16" + ;; + mips64*-*-*) sim_igen_filter="32,64,f" + sim_gen=IGEN + ;; + mips16*-*-*) sim_gen=M16 + sim_igen_filter="32,64,f" + sim_m16_filter="16" + ;; + mips*lsi*) sim_gen=M16 + sim_igen_machine="-M mipsIII,mips16" + sim_m16_machine="-M mips16,mipsIII" + sim_igen_filter="32,f" + sim_m16_filter="16" + ;; + mips*-*-*) sim_gen=IGEN + sim_igen_filter="32,f" + ;; +esac +sim_igen_flags="-F ${sim_igen_filter} ${sim_igen_machine} ${sim_igen_smp}" +sim_m16_flags=" -F ${sim_m16_filter} ${sim_m16_machine} ${sim_igen_smp}" + + + + + +# +# Add simulated hardware devices +# +hw_enabled=no +case "${target}" in + mips*tx39*) + hw_enabled=yes + hw_extra_devices="tx3904cpu tx3904irc tx3904tmr tx3904sio" + mips_extra_objs="dv-sockser.o" + SIM_SUBTARGET="$SIM_SUBTARGET -DTARGET_TX3904=1" + ;; + *) + mips_extra_objs="" + ;; +esac + +if test x"$hw_enabled" = x"yes"; then + sim_hw_p=yes +else + sim_hw_p=no +fi +if test "$hw_devices"; then + hardware="core pal glue" +else + hardware="core pal glue $hw_extra_devices" +fi +sim_hw_cflags="-DWITH_HW=1" +sim_hw="$hardware" +sim_hw_objs="\$(SIM_COMMON_HW_OBJS) `echo $sim_hw | sed -e 's/\([^ ][^ ]*\)/dv-\1.o/g'`" +# Check whether --enable-sim-hardware or --disable-sim-hardware was given. +if test "${enable_sim_hardware+set}" = set; then + enableval="$enable_sim_hardware" + +case "${enableval}" in + yes) sim_hw_p=yes;; + no) sim_hw_p=no;; + ,*) sim_hw_p=yes; hardware="${hardware} `echo ${enableval} | sed -e 's/,/ /'`";; + *,) sim_hw_p=yes; hardware="`echo ${enableval} | sed -e 's/,/ /'` ${hardware}";; + *) sim_hw_p=yes; hardware="`echo ${enableval} | sed -e 's/,/ /'`"'';; +esac +if test "$sim_hw_p" != yes; then + sim_hw_objs= + sim_hw_cflags="-DWITH_HW=0" + sim_hw= +else + sim_hw_cflags="-DWITH_HW=1" + # remove duplicates + sim_hw="" + sim_hw_objs="\$(SIM_COMMON_HW_OBJS)" + for i in x $hardware ; do + case " $f " in + x) ;; + *" $i "*) ;; + *) sim_hw="$sim_hw $i" ; sim_hw_objs="$sim_hw_objs dv-$i.o";; + esac + done +fi +if test x"$silent" != x"yes" && test "$sim_hw_p" = "yes"; then + echo "Setting hardware to $sim_hw_cflags, $sim_hw, $sim_hw_objs" +fi +else + +if test "$sim_hw_p" != yes; then + sim_hw_objs= + sim_hw_cflags="-DWITH_HW=0" + sim_hw= +fi +if test x"$silent" != x"yes"; then + echo "Setting hardware to $sim_hw_cflags, $sim_hw, $sim_hw_objs" +fi +fi + + + + +# Choose simulator engine +case "${target}" in + *) mips_igen_engine="engine.o" + ;; +esac + + + +# If we find X, set shell vars x_includes and x_libraries to the +# paths, otherwise set no_x=yes. +# Uses ac_ vars as temps to allow command line to override cache and checks. +# --without-x overrides everything else, but does not touch the cache. +echo $ac_n "checking for X""... $ac_c" 1>&6 +echo "configure:4125: checking for X" >&5 + +# Check whether --with-x or --without-x was given. +if test "${with_x+set}" = set; then + withval="$with_x" + : +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then + # Both variables are already set. + have_x=yes + else +if eval "test \"`echo '$''{'ac_cv_have_x'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=NO ac_x_libraries=NO +rm -fr conftestdir +if mkdir conftestdir; then + cd conftestdir + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat > Imakefile <<'EOF' +acfindx: + @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' +EOF + if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl; do + if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && + test -f $ac_im_libdir/libX11.$ac_extension; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case "$ac_im_incroot" in + /usr/include) ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;; + esac + case "$ac_im_usrlibdir" in + /usr/lib | /lib) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;; + esac + fi + cd .. + rm -fr conftestdir +fi + +if test "$ac_x_includes" = NO; then + # Guess where to find include files, by looking for this one X11 .h file. + test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h + + # First, try using that file with no special directory specified. +cat > conftest.$ac_ext <<EOF +#line 4187 "configure" +#include "confdefs.h" +#include <$x_direct_test_include> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:4192: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + # We can compile using X headers with no special include directory. +ac_x_includes= +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + # Look for the header file in a standard set of common directories. +# Check X11 before X11Rn because it is often a symlink to the current release. + for ac_dir in \ + /usr/X11/include \ + /usr/X11R6/include \ + /usr/X11R5/include \ + /usr/X11R4/include \ + \ + /usr/include/X11 \ + /usr/include/X11R6 \ + /usr/include/X11R5 \ + /usr/include/X11R4 \ + \ + /usr/local/X11/include \ + /usr/local/X11R6/include \ + /usr/local/X11R5/include \ + /usr/local/X11R4/include \ + \ + /usr/local/include/X11 \ + /usr/local/include/X11R6 \ + /usr/local/include/X11R5 \ + /usr/local/include/X11R4 \ + \ + /usr/X386/include \ + /usr/x386/include \ + /usr/XFree86/include/X11 \ + \ + /usr/include \ + /usr/local/include \ + /usr/unsupported/include \ + /usr/athena/include \ + /usr/local/x11r5/include \ + /usr/lpp/Xamples/include \ + \ + /usr/openwin/include \ + /usr/openwin/share/include \ + ; \ + do + if test -r "$ac_dir/$x_direct_test_include"; then + ac_x_includes=$ac_dir + break + fi + done +fi +rm -f conftest* +fi # $ac_x_includes = NO + +if test "$ac_x_libraries" = NO; then + # Check for the libraries. + + test -z "$x_direct_test_library" && x_direct_test_library=Xt + test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc + + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS="$LIBS" + LIBS="-l$x_direct_test_library $LIBS" +cat > conftest.$ac_ext <<EOF +#line 4261 "configure" +#include "confdefs.h" + +int main() { +${x_direct_test_function}() +; return 0; } +EOF +if { (eval echo configure:4268: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + LIBS="$ac_save_LIBS" +# We can link X programs with no special library path. +ac_x_libraries= +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + LIBS="$ac_save_LIBS" +# First see if replacing the include by lib works. +# Check X11 before X11Rn because it is often a symlink to the current release. +for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \ + /usr/X11/lib \ + /usr/X11R6/lib \ + /usr/X11R5/lib \ + /usr/X11R4/lib \ + \ + /usr/lib/X11 \ + /usr/lib/X11R6 \ + /usr/lib/X11R5 \ + /usr/lib/X11R4 \ + \ + /usr/local/X11/lib \ + /usr/local/X11R6/lib \ + /usr/local/X11R5/lib \ + /usr/local/X11R4/lib \ + \ + /usr/local/lib/X11 \ + /usr/local/lib/X11R6 \ + /usr/local/lib/X11R5 \ + /usr/local/lib/X11R4 \ + \ + /usr/X386/lib \ + /usr/x386/lib \ + /usr/XFree86/lib/X11 \ + \ + /usr/lib \ + /usr/local/lib \ + /usr/unsupported/lib \ + /usr/athena/lib \ + /usr/local/x11r5/lib \ + /usr/lpp/Xamples/lib \ + /lib/usr/lib/X11 \ + \ + /usr/openwin/lib \ + /usr/openwin/share/lib \ + ; \ +do + for ac_extension in a so sl; do + if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f conftest* +fi # $ac_x_libraries = NO + +if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then + # Didn't find X anywhere. Cache the known absence of X. + ac_cv_have_x="have_x=no" +else + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" +fi +fi + fi + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + echo "$ac_t""$have_x" 1>&6 + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$x_includes ac_x_libraries=$x_libraries" + echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6 +fi + +mips_extra_libs="" + + +for ac_hdr in string.h strings.h stdlib.h stdlib.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:5155: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 5160 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:5165: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +echo $ac_n "checking for fabs in -lm""... $ac_c" 1>&6 +echo "configure:5192: checking for fabs in -lm" >&5 +ac_lib_var=`echo m'_'fabs | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lm $LIBS" +cat > conftest.$ac_ext <<EOF +#line 5200 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char fabs(); + +int main() { +fabs() +; return 0; } +EOF +if { (eval echo configure:5211: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo m | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lm $LIBS" + +else + echo "$ac_t""no" 1>&6 +fi + +for ac_func in aint anint sqrt +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:5241: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 5246 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5269: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1 | grep ac_space` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS <<EOF +#! /bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12.2" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile.sim:Makefile.in Make-common.sim:../common/Make-common.in .gdbinit:../common/gdbinit.in config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS <<EOF + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@sim_environment@%$sim_environment%g +s%@sim_alignment@%$sim_alignment%g +s%@sim_assert@%$sim_assert%g +s%@sim_bitsize@%$sim_bitsize%g +s%@sim_endian@%$sim_endian%g +s%@sim_hostendian@%$sim_hostendian%g +s%@sim_float@%$sim_float%g +s%@sim_scache@%$sim_scache%g +s%@sim_default_model@%$sim_default_model%g +s%@sim_hw_cflags@%$sim_hw_cflags%g +s%@sim_hw_objs@%$sim_hw_objs%g +s%@sim_hw@%$sim_hw%g +s%@sim_inline@%$sim_inline%g +s%@sim_packages@%$sim_packages%g +s%@sim_regparm@%$sim_regparm%g +s%@sim_reserved_bits@%$sim_reserved_bits%g +s%@sim_smp@%$sim_smp%g +s%@sim_stdcall@%$sim_stdcall%g +s%@sim_xor_endian@%$sim_xor_endian%g +s%@build_warnings@%$build_warnings%g +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@target@%$target%g +s%@target_alias@%$target_alias%g +s%@target_cpu@%$target_cpu%g +s%@target_vendor@%$target_vendor%g +s%@target_os@%$target_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@CC@%$CC%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g +s%@HDEFINES@%$HDEFINES%g +s%@AR@%$AR%g +s%@RANLIB@%$RANLIB%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CPP@%$CPP%g +s%@ALLOCA@%$ALLOCA%g +s%@USE_NLS@%$USE_NLS%g +s%@MSGFMT@%$MSGFMT%g +s%@GMSGFMT@%$GMSGFMT%g +s%@XGETTEXT@%$XGETTEXT%g +s%@USE_INCLUDED_LIBINTL@%$USE_INCLUDED_LIBINTL%g +s%@CATALOGS@%$CATALOGS%g +s%@CATOBJEXT@%$CATOBJEXT%g +s%@DATADIRNAME@%$DATADIRNAME%g +s%@GMOFILES@%$GMOFILES%g +s%@INSTOBJEXT@%$INSTOBJEXT%g +s%@INTLDEPS@%$INTLDEPS%g +s%@INTLLIBS@%$INTLLIBS%g +s%@INTLOBJS@%$INTLOBJS%g +s%@POFILES@%$POFILES%g +s%@POSUB@%$POSUB%g +s%@INCLUDE_LOCALE_H@%$INCLUDE_LOCALE_H%g +s%@GT_NO@%$GT_NO%g +s%@GT_YES@%$GT_YES%g +s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g +s%@l@%$l%g +s%@MAINT@%$MAINT%g +s%@sim_bswap@%$sim_bswap%g +s%@sim_cflags@%$sim_cflags%g +s%@sim_debug@%$sim_debug%g +s%@sim_stdio@%$sim_stdio%g +s%@sim_trace@%$sim_trace%g +s%@sim_profile@%$sim_profile%g +s%@EXEEXT@%$EXEEXT%g +s%@SIM_SUBTARGET@%$SIM_SUBTARGET%g +s%@sim_igen_flags@%$sim_igen_flags%g +s%@sim_m16_flags@%$sim_m16_flags%g +s%@sim_gen@%$sim_gen%g +s%@mips_extra_objs@%$mips_extra_objs%g +s%@mips_igen_engine@%$mips_igen_engine%g +s%@mips_extra_libs@%$mips_extra_libs%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <<EOF + +CONFIG_FILES=\${CONFIG_FILES-"Makefile.sim:Makefile.in Make-common.sim:../common/Make-common.in .gdbinit:../common/gdbinit.in"} +EOF +cat >> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <<EOF + CONFIG_HEADERS="config.h:config.in" +EOF +cat >> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF + +cat >> $CONFIG_STATUS <<EOF +ac_sources="$sim_link_files" +ac_dests="$sim_link_links" +EOF + +cat >> $CONFIG_STATUS <<\EOF +srcdir=$ac_given_srcdir +while test -n "$ac_sources"; do + set $ac_dests; ac_dest=$1; shift; ac_dests=$* + set $ac_sources; ac_source=$1; shift; ac_sources=$* + + echo "linking $srcdir/$ac_source to $ac_dest" + + if test ! -r $srcdir/$ac_source; then + { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; } + fi + rm -f $ac_dest + + # Make relative symlinks. + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'` + if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then + # The dest file is in a subdirectory. + test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir" + ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dest_dir_suffix. + ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dest_dir_suffix= ac_dots= + fi + + case "$srcdir" in + [/$]*) ac_rel_source="$srcdir/$ac_source" ;; + *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;; + esac + + # Make a symlink if possible; otherwise try a hard link. + if ln -s $ac_rel_source $ac_dest 2>/dev/null || + ln $srcdir/$ac_source $ac_dest; then : + else + { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; } + fi +done +EOF +cat >> $CONFIG_STATUS <<EOF + +EOF +cat >> $CONFIG_STATUS <<\EOF +case "x$CONFIG_FILES" in + xMakefile*) + echo "Merging Makefile.sim+Make-common.sim into Makefile ..." + rm -f Makesim1.tmp Makesim2.tmp Makefile + sed -n -e '/^## COMMON_PRE_/,/^## End COMMON_PRE_/ p' <Make-common.sim >Makesim1.tmp + sed -n -e '/^## COMMON_POST_/,/^## End COMMON_POST_/ p' <Make-common.sim >Makesim2.tmp + sed -e '/^## COMMON_PRE_/ r Makesim1.tmp' \ + -e '/^## COMMON_POST_/ r Makesim2.tmp' \ + <Makefile.sim >Makefile + rm -f Makefile.sim Make-common.sim Makesim1.tmp Makesim2.tmp + ;; + esac + case "x$CONFIG_HEADERS" in xconfig.h:config.in) echo > stamp-h ;; esac + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + diff --git a/sim/mips/configure.in b/sim/mips/configure.in new file mode 100644 index 0000000..89959fe --- /dev/null +++ b/sim/mips/configure.in @@ -0,0 +1,170 @@ +dnl Process this file with autoconf to produce a configure script. +sinclude(../common/aclocal.m4) +AC_PREREQ(2.5)dnl +AC_INIT(Makefile.in) + +SIM_AC_COMMON + +dnl Options available in this module +SIM_AC_OPTION_INLINE() +SIM_AC_OPTION_ALIGNMENT(NONSTRICT_ALIGNMENT) +SIM_AC_OPTION_HOSTENDIAN +SIM_AC_OPTION_WARNINGS + +# DEPRECATED +# +# Instead of defining a `subtarget' macro, code should be checking +# the value of {STATE,CPU}_ARCHITECTURE to identify the architecture +# in question. +# +case "${target}" in + mips*tx39*) SIM_SUBTARGET="-DSUBTARGET_R3900=1";; + *) SIM_SUBTARGET="";; +esac +AC_SUBST(SIM_SUBTARGET) + + + +# +# Select the byte order of the target +# +mips_endian= +default_endian= +case "${target}" in + mips64el*-*-*) mips_endian=LITTLE_ENDIAN ;; + mips64*-*-*) default_endian=BIG_ENDIAN ;; + mips16*-*-*) default_endian=BIG_ENDIAN ;; + mips*-*-*) default_endian=BIG_ENDIAN ;; + *) default_endian=BIG_ENDIAN ;; +esac +SIM_AC_OPTION_ENDIAN($mips_endian,$default_endian) + + + +# +# Select the bitsize of the target +# +mips_addr_bitsize= +case "${target}" in + mips64*-*-*) mips_bitsize=64 ; mips_msb=63 ;; + mips16*-*-*) mips_bitsize=64 ; mips_msb=63 ;; + mips*-*-*) mips_bitsize=32 ; mips_msb=31 ;; + *) mips_bitsize=64 ; mips_msb=63 ;; +esac +SIM_AC_OPTION_BITSIZE($mips_bitsize,$mips_msb,$mips_addr_bitsize) + + + +# +# Select the floating hardware support of the target +# +mips_fpu=HARDWARE_FLOATING_POINT +mips_fpu_bitsize= +case "${target}" in + mips*tx39*) mips_fpu=HARD_FLOATING_POINT + mips_fpu_bitsize=32 + ;; + mips64*-*-*) mips_fpu=HARD_FLOATING_POINT ;; + mips16*-*-*) mips_fpu=HARD_FLOATING_POINT ;; + mips*-*-*) mips_fpu=HARD_FLOATING_POINT ; mips_fpu_bitsize=32 ;; + *) mips_fpu=HARD_FLOATING_POINT ;; +esac +SIM_AC_OPTION_FLOAT($mips_fpu,$mips_fpu_bitsize) + + + +# +# Select the level of SMP support +# +case "${target}" in + *) mips_smp=0 ;; +esac +SIM_AC_OPTION_SMP($mips_smp) + + + +# +# Select the IGEN architecture +# +sim_gen=IGEN +sim_igen_machine="-M mipsIV" +sim_m16_machine="-M mips16" +sim_igen_filter="32,64,f" +sim_m16_filter="16" +case "${target}" in + mips*tx39*) sim_gen=IGEN + sim_igen_filter="32,f" + sim_igen_machine="-M r3900" + ;; + mips64vr43*-*-*) sim_gen=IGEN + sim_igen_machine="-M mipsIV" + ;; + mips64vr5*-*-*) sim_gen=IGEN + sim_igen_machine="-M vr5000" + ;; + mips64vr41*) sim_gen=M16 + sim_igen_machine="-M vr4100" + sim_m16_machine="-M vr4100" + sim_igen_filter="32,64,f" + sim_m16_filter="16" + ;; + mips64*-*-*) sim_igen_filter="32,64,f" + sim_gen=IGEN + ;; + mips16*-*-*) sim_gen=M16 + sim_igen_filter="32,64,f" + sim_m16_filter="16" + ;; + mips*lsi*) sim_gen=M16 + sim_igen_machine="-M mipsIII,mips16" + sim_m16_machine="-M mips16,mipsIII" + sim_igen_filter="32,f" + sim_m16_filter="16" + ;; + mips*-*-*) sim_gen=IGEN + sim_igen_filter="32,f" + ;; +esac +sim_igen_flags="-F ${sim_igen_filter} ${sim_igen_machine} ${sim_igen_smp}" +sim_m16_flags=" -F ${sim_m16_filter} ${sim_m16_machine} ${sim_igen_smp}" +AC_SUBST(sim_igen_flags) +AC_SUBST(sim_m16_flags) +AC_SUBST(sim_gen) + + +# +# Add simulated hardware devices +# +hw_enabled=no +case "${target}" in + mips*tx39*) + hw_enabled=yes + hw_extra_devices="tx3904cpu tx3904irc tx3904tmr tx3904sio" + mips_extra_objs="dv-sockser.o" + SIM_SUBTARGET="$SIM_SUBTARGET -DTARGET_TX3904=1" + ;; + *) + mips_extra_objs="" + ;; +esac +SIM_AC_OPTION_HARDWARE($hw_enabled,$hw_devices,$hw_extra_devices) +AC_SUBST(mips_extra_objs) + + +# Choose simulator engine +case "${target}" in + *) mips_igen_engine="engine.o" + ;; +esac +AC_SUBST(mips_igen_engine) + + +AC_PATH_X +mips_extra_libs="" +AC_SUBST(mips_extra_libs) + +AC_CHECK_HEADERS(string.h strings.h stdlib.h stdlib.h) +AC_CHECK_LIB(m, fabs) +AC_CHECK_FUNCS(aint anint sqrt) + +SIM_AC_OUTPUT diff --git a/sim/mips/dv-tx3904cpu.c b/sim/mips/dv-tx3904cpu.c new file mode 100644 index 0000000..07b8521 --- /dev/null +++ b/sim/mips/dv-tx3904cpu.c @@ -0,0 +1,246 @@ +/* This file is part of the program GDB, the GNU debugger. + + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "sim-main.h" +#include "hw-main.h" + +/* DEVICE + + + tx3904cpu - tx3904 cpu virtual device + + + DESCRIPTION + + + Implements the external tx3904 functionality. This includes the + delivery of of interrupts generated from other devices and the + handling of device specific registers. + + + PROPERTIES + + none + + + PORTS + + + reset (input) + + Currently ignored. + + + nmi (input) + + Deliver a non-maskable interrupt to the processor. + + + level (input) + + Deliver a maskable interrupt of given level, corresponding to + IP[5:0], to processor. + + + + BUGS + + + When delivering an interrupt, this code assumes that there is only + one processor (number 0). + + This code does not attempt to be efficient at handling pending + interrupts. It simply schedules the interrupt delivery handler + every instruction cycle until all pending interrupts go away. An + alternative implementation might modify instructions that change + the PSW and have them check to see if the change makes an interrupt + delivery possible. + + */ + + + +struct tx3904cpu { + /* Pending interrupts for delivery by event handler */ + int pending_reset, pending_nmi, pending_level; + struct hw_event* event; +}; + + + +/* input port ID's */ + +enum { + RESET_PORT, + NMI_PORT, + LEVEL_PORT, +}; + + +static const struct hw_port_descriptor tx3904cpu_ports[] = { + + /* interrupt inputs */ + { "reset", RESET_PORT, 0, input_port, }, + { "nmi", NMI_PORT, 0, input_port, }, + { "level", LEVEL_PORT, 0, input_port, }, + + { NULL, }, +}; + + +/* Finish off the partially created hw device. Attach our local + callbacks. Wire up our port names etc */ + +static hw_port_event_method tx3904cpu_port_event; + + + +static void +tx3904cpu_finish (struct hw *me) +{ + struct tx3904cpu *controller; + + controller = HW_ZALLOC (me, struct tx3904cpu); + set_hw_data (me, controller); + set_hw_ports (me, tx3904cpu_ports); + set_hw_port_event (me, tx3904cpu_port_event); + + /* Initialize the pending interrupt flags */ + controller->pending_level = 0; + controller->pending_reset = 0; + controller->pending_nmi = 0; + controller->event = NULL; +} + + + +/* An event arrives on an interrupt port */ + +static void +deliver_tx3904cpu_interrupt (struct hw *me, + void *data) +{ + struct tx3904cpu *controller = hw_data (me); + SIM_DESC sd = hw_system (me); + sim_cpu *cpu = STATE_CPU (sd, 0); /* NB: fix CPU 0. */ + address_word cia = CIA_GET (cpu); + +#define CPU cpu +#define SD current_state + + if (controller->pending_reset) + { + controller->pending_reset = 0; + HW_TRACE ((me, "reset pc=0x%08lx", (long) CIA_GET (cpu))); + SignalExceptionNMIReset(); + } + else if (controller->pending_nmi) + { + controller->pending_nmi = 0; + HW_TRACE ((me, "nmi pc=0x%08lx", (long) CIA_GET (cpu))); + SignalExceptionNMIReset(); + } + else if (controller->pending_level) + { + HW_TRACE ((me, "interrupt level=%d pc=0x%08lx sr=0x%08lx", + controller->pending_level, + (long) CIA_GET (cpu), (long) SR)); + + /* Clear CAUSE register. It may stay this way if the interrupt + was cleared with a negative pending_level. */ + CAUSE &= ~ (cause_IP_mask << cause_IP_shift); + + if(controller->pending_level > 0) /* interrupt set */ + { + /* set hardware-interrupt subfields of CAUSE register */ + CAUSE |= (controller->pending_level & cause_IP_mask) << cause_IP_shift; + + /* check for enabled / unmasked interrupts */ + if((SR & status_IEc) && + (controller->pending_level & ((SR >> status_IM_shift) & status_IM_mask))) + { + controller->pending_level = 0; + SignalExceptionInterrupt(0 /* dummy value */); + } + else + { + /* reschedule soon */ + if(controller->event != NULL) + hw_event_queue_deschedule(me, controller->event); + controller->event = + hw_event_queue_schedule (me, 1, deliver_tx3904cpu_interrupt, NULL); + } + } /* interrupt set */ + } +#undef CPU cpu +#undef SD current_state +} + + +static void +tx3904cpu_port_event (struct hw *me, + int my_port, + struct hw *source, + int source_port, + int level) +{ + struct tx3904cpu *controller = hw_data (me); + + switch (my_port) + { + case RESET_PORT: + controller->pending_reset = 1; + HW_TRACE ((me, "port-in reset")); + break; + + case NMI_PORT: + controller->pending_nmi = 1; + HW_TRACE ((me, "port-in nmi")); + break; + + case LEVEL_PORT: + /* level == 0 means that the interrupt was cleared */ + if(level == 0) + controller->pending_level = -1; /* signal end of interrupt */ + else + controller->pending_level = level; + HW_TRACE ((me, "port-in level=%d", level)); + break; + + default: + hw_abort (me, "bad switch"); + break; + } + + /* Schedule an event to be delivered immediately after current + instruction. */ + if(controller->event != NULL) + hw_event_queue_deschedule(me, controller->event); + controller->event = + hw_event_queue_schedule (me, 0, deliver_tx3904cpu_interrupt, NULL); +} + + +const struct hw_descriptor dv_tx3904cpu_descriptor[] = { + { "tx3904cpu", tx3904cpu_finish, }, + { NULL }, +}; diff --git a/sim/mips/dv-tx3904irc.c b/sim/mips/dv-tx3904irc.c new file mode 100644 index 0000000..8b84e5c --- /dev/null +++ b/sim/mips/dv-tx3904irc.c @@ -0,0 +1,413 @@ +/* This file is part of the program GDB, the GNU debugger. + + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "sim-main.h" +#include "hw-main.h" + + +/* DEVICE + + + tx3904irc - tx3904 interrupt controller + + + DESCRIPTION + + + Implements the tx3904 interrupt controller described in the tx3904 + user guide. It does not include the interrupt detection circuit + that preprocesses the eight external interrupts, so assumes that + each event on an input interrupt port signals a new interrupt. + That is, it implements edge- rather than level-triggered + interrupts. + + This implementation does not support multiple concurrent + interrupts. + + + PROPERTIES + + + reg <base> <length> + + Base of IRC control register bank. <length> must equal 0x20. + Registers offsets: 0: ISR: interrupt status register + 4: IMR: interrupt mask register + 16: ILR0: interrupt level register 3..0 + 20: ILR1: interrupt level register 7..4 + 24: ILR2: interrupt level register 11..8 + 28: ILR3: interrupt level register 15..12 + + + + PORTS + + + ip (output) + + Interrupt priority port. An event is generated when an interrupt + of a sufficient priority is passed through the IRC. The value + associated with the event is the interrupt level (16-31), as given + for bits IP[5:0] in the book TMPR3904F Rev. 2.0, pg. 11-3. Note + that even though INT[0] is tied externally to IP[5], we simulate + it as passing through the controller. + + An output level of zero signals the clearing of a level interrupt. + + + int0-7 (input) + + External interrupts. Level = 0 -> level interrupt cleared. + + + dmac0-3 (input) + + DMA internal interrupts, correspond to DMA channels 0-3. Level = 0 -> level interrupt cleared. + + + sio0-1 (input) + + SIO internal interrupts. Level = 0 -> level interrupt cleared. + + + tmr0-2 (input) + + Timer internal interrupts. Level = 0 -> level interrupt cleared. + + */ + + + + + +/* register numbers; each is one word long */ +enum +{ + ISR_REG = 0, + IMR_REG = 1, + ILR0_REG = 4, + ILR1_REG = 5, + ILR2_REG = 6, + ILR3_REG = 7, +}; + + +/* port ID's */ + +enum +{ + /* inputs, ordered to correspond to interrupt sources 0..15 */ + INT1_PORT = 0, INT2_PORT, INT3_PORT, INT4_PORT, INT5_PORT, INT6_PORT, INT7_PORT, + DMAC3_PORT, DMAC2_PORT, DMAC1_PORT, DMAC0_PORT, SIO0_PORT, SIO1_PORT, + TMR0_PORT, TMR1_PORT, TMR2_PORT, + + /* special INT[0] port */ + INT0_PORT, + + /* reset */ + RESET_PORT, + + /* output */ + IP_PORT +}; + + +static const struct hw_port_descriptor tx3904irc_ports[] = { + + /* interrupt output */ + + { "ip", IP_PORT, 0, output_port, }, + + /* interrupt inputs (as names) */ + /* in increasing order of level number */ + + { "int1", INT1_PORT, 0, input_port, }, + { "int2", INT2_PORT, 0, input_port, }, + { "int3", INT3_PORT, 0, input_port, }, + { "int4", INT4_PORT, 0, input_port, }, + { "int5", INT5_PORT, 0, input_port, }, + { "int6", INT6_PORT, 0, input_port, }, + { "int7", INT7_PORT, 0, input_port, }, + + { "dmac3", DMAC3_PORT, 0, input_port, }, + { "dmac2", DMAC2_PORT, 0, input_port, }, + { "dmac1", DMAC1_PORT, 0, input_port, }, + { "dmac0", DMAC0_PORT, 0, input_port, }, + + { "sio0", SIO0_PORT, 0, input_port, }, + { "sio1", SIO1_PORT, 0, input_port, }, + + { "tmr0", TMR0_PORT, 0, input_port, }, + { "tmr1", TMR1_PORT, 0, input_port, }, + { "tmr2", TMR2_PORT, 0, input_port, }, + + { "reset", RESET_PORT, 0, input_port, }, + { "int0", INT0_PORT, 0, input_port, }, + + { NULL, }, +}; + + +#define NR_SOURCES (TMR3_PORT - INT1_PORT + 1) /* 16: number of interrupt sources */ + + +/* The interrupt controller register internal state. Note that we + store state using the control register images, in host endian + order. */ + +struct tx3904irc { + address_word base_address; /* control register base */ + unsigned_4 isr; +#define ISR_SET(c,s) ((c)->isr &= ~ (1 << (s))) + unsigned_4 imr; +#define IMR_GET(c) ((c)->imr) + unsigned_4 ilr[4]; +#define ILR_GET(c,s) LSEXTRACTED32((c)->ilr[(s)/4], (s) % 4 * 8 + 2, (s) % 4 * 8) +}; + + + +/* Finish off the partially created hw device. Attach our local + callbacks. Wire up our port names etc */ + +static hw_io_read_buffer_method tx3904irc_io_read_buffer; +static hw_io_write_buffer_method tx3904irc_io_write_buffer; +static hw_port_event_method tx3904irc_port_event; + +static void +attach_tx3904irc_regs (struct hw *me, + struct tx3904irc *controller) +{ + unsigned_word attach_address; + int attach_space; + unsigned attach_size; + reg_property_spec reg; + + if (hw_find_property (me, "reg") == NULL) + hw_abort (me, "Missing \"reg\" property"); + + if (!hw_find_reg_array_property (me, "reg", 0, ®)) + hw_abort (me, "\"reg\" property must contain one addr/size entry"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, + &attach_address, + me); + hw_unit_size_to_attach_size (hw_parent (me), + ®.size, + &attach_size, me); + + hw_attach_address (hw_parent (me), 0, + attach_space, attach_address, attach_size, + me); + + controller->base_address = attach_address; +} + + +static void +tx3904irc_finish (struct hw *me) +{ + struct tx3904irc *controller; + + controller = HW_ZALLOC (me, struct tx3904irc); + set_hw_data (me, controller); + set_hw_io_read_buffer (me, tx3904irc_io_read_buffer); + set_hw_io_write_buffer (me, tx3904irc_io_write_buffer); + set_hw_ports (me, tx3904irc_ports); + set_hw_port_event (me, tx3904irc_port_event); + + /* Attach ourself to our parent bus */ + attach_tx3904irc_regs (me, controller); + + /* Initialize to reset state */ + controller->isr = 0x0000ffff; + controller->imr = 0; + controller->ilr[0] = + controller->ilr[1] = + controller->ilr[2] = + controller->ilr[3] = 0; +} + + + +/* An event arrives on an interrupt port */ + +static void +tx3904irc_port_event (struct hw *me, + int my_port, + struct hw *source_dev, + int source_port, + int level) +{ + struct tx3904irc *controller = hw_data (me); + + /* handle deactivated interrupt */ + if(level == 0) + { + HW_TRACE ((me, "interrupt cleared on port %d", my_port)); + hw_port_event(me, IP_PORT, 0); + return; + } + + switch (my_port) + { + case INT0_PORT: + { + int ip_number = 32; /* compute IP[5:0] */ + HW_TRACE ((me, "port-event INT[0]")); + hw_port_event(me, IP_PORT, ip_number); + break; + } + + case INT1_PORT: case INT2_PORT: case INT3_PORT: case INT4_PORT: + case INT5_PORT: case INT6_PORT: case INT7_PORT: case DMAC3_PORT: + case DMAC2_PORT: case DMAC1_PORT: case DMAC0_PORT: case SIO0_PORT: + case SIO1_PORT: case TMR0_PORT: case TMR1_PORT: case TMR2_PORT: + { + int source = my_port - INT1_PORT; + + HW_TRACE ((me, "interrupt asserted on port %d", source)); + ISR_SET(controller, source); + if(ILR_GET(controller, source) > IMR_GET(controller)) + { + int ip_number = 16 + source; /* compute IP[4:0] */ + HW_TRACE ((me, "interrupt level %d", ILR_GET(controller,source))); + hw_port_event(me, IP_PORT, ip_number); + } + break; + } + + case RESET_PORT: + { + HW_TRACE ((me, "reset")); + controller->isr = 0x0000ffff; + controller->imr = 0; + controller->ilr[0] = + controller->ilr[1] = + controller->ilr[2] = + controller->ilr[3] = 0; + break; + } + + case IP_PORT: + hw_abort (me, "Event on output port %d", my_port); + break; + + default: + hw_abort (me, "Event on unknown port %d", my_port); + break; + } +} + + +/* generic read/write */ + +static unsigned +tx3904irc_io_read_buffer (struct hw *me, + void *dest, + int space, + unsigned_word base, + unsigned nr_bytes) +{ + struct tx3904irc *controller = hw_data (me); + unsigned byte; + + HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); + for (byte = 0; byte < nr_bytes; byte++) + { + address_word address = base + byte; + int reg_number = (address - controller->base_address) / 4; + int reg_offset = (address - controller->base_address) % 4; + unsigned_4 register_value; /* in target byte order */ + + /* fill in entire register_value word */ + switch (reg_number) + { + case ISR_REG: register_value = controller->isr; break; + case IMR_REG: register_value = controller->imr; break; + case ILR0_REG: register_value = controller->ilr[0]; break; + case ILR1_REG: register_value = controller->ilr[1]; break; + case ILR2_REG: register_value = controller->ilr[2]; break; + case ILR3_REG: register_value = controller->ilr[3]; break; + default: register_value = 0; + } + + /* write requested byte out */ + register_value = H2T_4(register_value); + memcpy ((char*) dest + byte, ((char*)& register_value)+reg_offset, 1); + } + + return nr_bytes; +} + + + +static unsigned +tx3904irc_io_write_buffer (struct hw *me, + const void *source, + int space, + unsigned_word base, + unsigned nr_bytes) +{ + struct tx3904irc *controller = hw_data (me); + unsigned byte; + + HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); + for (byte = 0; byte < nr_bytes; byte++) + { + address_word address = base + byte; + int reg_number = (address - controller->base_address) / 4; + int reg_offset = (address - controller->base_address) % 4; + unsigned_4* register_ptr; + unsigned_4 register_value; + + /* fill in entire register_value word */ + switch (reg_number) + { + case ISR_REG: register_ptr = & controller->isr; break; + case IMR_REG: register_ptr = & controller->imr; break; + case ILR0_REG: register_ptr = & controller->ilr[0]; break; + case ILR1_REG: register_ptr = & controller->ilr[1]; break; + case ILR2_REG: register_ptr = & controller->ilr[2]; break; + case ILR3_REG: register_ptr = & controller->ilr[3]; break; + default: register_ptr = & register_value; /* used as a dummy */ + } + + /* HW_TRACE ((me, "reg %d pre: %08lx", reg_number, (long) *register_ptr)); */ + + /* overwrite requested byte */ + register_value = H2T_4(* register_ptr); + memcpy (((char*)®ister_value)+reg_offset, (const char*)source + byte, 1); + * register_ptr = T2H_4(register_value); + + /* HW_TRACE ((me, "post: %08lx", (long) *register_ptr)); */ + } + return nr_bytes; +} + + +const struct hw_descriptor dv_tx3904irc_descriptor[] = { + { "tx3904irc", tx3904irc_finish, }, + { NULL }, +}; diff --git a/sim/mips/dv-tx3904sio.c b/sim/mips/dv-tx3904sio.c new file mode 100644 index 0000000..a1e3ddb --- /dev/null +++ b/sim/mips/dv-tx3904sio.c @@ -0,0 +1,621 @@ +/* This file is part of the program GDB, the GNU debugger. + + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "sim-main.h" +#include "hw-main.h" +#include "dv-sockser.h" +#include "sim-assert.h" + + +/* DEVICE + + + tx3904sio - tx3904 serial I/O + + + DESCRIPTION + + + Implements one tx3904 serial I/O controller described in the tx3904 + user guide. Three instances are required for SIO0 and SIO1 within + the tx3904, at different base addresses. + + Both internal and system clocks are synthesized as divided versions + of the simulator clock. + + There is no support for: + - CTS/RTS flow control + - baud rate emulation - use infinite speed instead + - general frame format - use 8N1 + - multi-controller system + - DMA - use interrupt-driven or polled-I/O instead + + + PROPERTIES + + + reg <base> <length> + + Base of SIO control register bank. <length> must equal 0x100. + Register offsets: 0: SLCR: line control register + 4: SLSR: line status register + 8: SDICR: DMA/interrupt control register + 12: SDISR: DMA/interrupt status register + 16: SFCR: FIFO control register + 20: SBGR: baud rate control register + 32: transfer FIFO buffer + 48: transfer FIFO buffer + + backend {tcp | stdio} + + Use dv-sockser TCP-port backend or stdio for backend. Default: stdio. + + + + PORTS + + + int (output) + + Interrupt port. An event is generated when a timer interrupt + occurs. + + + reset (input) + + Reset port. + + */ + + + +/* static functions */ + +struct tx3904sio_fifo; + +static void tx3904sio_tickle(struct hw*); +static int tx3904sio_fifo_nonempty(struct hw*, struct tx3904sio_fifo*); +static char tx3904sio_fifo_pop(struct hw*, struct tx3904sio_fifo*); +static void tx3904sio_fifo_push(struct hw*, struct tx3904sio_fifo*, char); +static void tx3904sio_fifo_reset(struct hw*, struct tx3904sio_fifo*); +static void tx3904sio_poll(struct hw*, void* data); + + +/* register numbers; each is one word long */ +enum +{ + SLCR_REG = 0, + SLSR_REG = 1, + SDICR_REG = 2, + SDISR_REG = 3, + SFCR_REG = 4, + SBGR_REG = 5, + TFIFO_REG = 8, + SFIFO_REG = 12, +}; + + + +/* port ID's */ + +enum + { + RESET_PORT, + INT_PORT, +}; + + +static const struct hw_port_descriptor tx3904sio_ports[] = +{ + { "int", INT_PORT, 0, output_port, }, + { "reset", RESET_PORT, 0, input_port, }, + { NULL, }, +}; + + + +/* Generic FIFO */ +struct tx3904sio_fifo +{ + int size, used; + unsigned_1 *buffer; +}; + + + +/* The timer/counter register internal state. Note that we store + state using the control register images, in host endian order. */ + +struct tx3904sio +{ + address_word base_address; /* control register base */ + enum {sio_tcp, sio_stdio} backend; /* backend */ + + struct tx3904sio_fifo rx_fifo, tx_fifo; /* FIFOs */ + + unsigned_4 slcr; +#define SLCR_WR_MASK 0xe17f0000U +#define SLCR_SET_BYTE(c,o,b) ((c)->slcr = SLCR_WR_MASK & (((c)->slcr & ~LSMASK32((o)*8+7,(o)*8)) | ((b)<< (o)*8))) + unsigned_4 slsr; +#define SLSR_WR_MASK 0x00000000 /* UFER/UPER/UOER unimplemented */ + unsigned_4 sdicr; +#define SDICR_WR_MASK 0x000f0000U +#define SDICR_SET_BYTE(c,o,b) ((c)->sdicr = SDICR_WR_MASK & (((c)->sdicr & ~LSMASK32((o)*8+7,(o)*8)) | ((b)<< (o)*8))) +#define SDICR_GET_SDMAE(c) ((c)->sdicr & 0x00080000) +#define SDICR_GET_ERIE(c) ((c)->sdicr & 0x00040000) +#define SDICR_GET_TDIE(c) ((c)->sdicr & 0x00020000) +#define SDICR_GET_RDIE(c) ((c)->sdicr & 0x00010000) + unsigned_4 sdisr; +#define SDISR_WR_MASK 0x00070000U +#define SDISR_SET_BYTE(c,o,b) ((c)->sdisr = SDISR_WR_MASK & (((c)->sdisr & ~LSMASK32((o)*8+7,(o)*8)) | ((b)<< (o)*8))) +#define SDISR_GET_TDIS(c) ((c)->sdisr & 0x00020000) +#define SDISR_SET_TDIS(c) ((c)->sdisr |= 0x00020000) +#define SDISR_GET_RDIS(c) ((c)->sdisr & 0x00010000) +#define SDISR_SET_RDIS(c) ((c)->sdisr |= 0x00010000) + unsigned_4 sfcr; +#define SFCR_WR_MASK 0x001f0000U +#define SFCR_SET_BYTE(c,o,b) ((c)->sfcr = SFCR_WR_MASK & (((c)->sfcr & ~LSMASK32((o)*8+7,(o)*8)) | ((b)<< (o)*8))) +#define SFCR_GET_TFRST(c) ((c)->sfcr & 0x00040000) +#define SFCR_GET_RFRST(c) ((c)->sfcr & 0x00020000) +#define SFCR_GET_FRSTE(c) ((c)->sfcr & 0x00010000) + unsigned_4 sbgr; +#define SBGR_WR_MASK 0x03ff0000U +#define SBGR_SET_BYTE(c,o,b) ((c)->sbgr = SBGR_WR_MASK & (((c)->sbgr & ~LSMASK32((o)*8+7,(o)*8)) | ((b)<< (o)*8))) + + /* Periodic I/O polling */ + struct hw_event* poll_event; +}; + + + +/* Finish off the partially created hw device. Attach our local + callbacks. Wire up our port names etc */ + +static hw_io_read_buffer_method tx3904sio_io_read_buffer; +static hw_io_write_buffer_method tx3904sio_io_write_buffer; +static hw_port_event_method tx3904sio_port_event; + + +static void +attach_tx3904sio_regs (struct hw *me, + struct tx3904sio *controller) +{ + unsigned_word attach_address; + int attach_space; + unsigned attach_size; + reg_property_spec reg; + + if (hw_find_property (me, "reg") == NULL) + hw_abort (me, "Missing \"reg\" property"); + + if (!hw_find_reg_array_property (me, "reg", 0, ®)) + hw_abort (me, "\"reg\" property must contain one addr/size entry"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, + &attach_address, + me); + hw_unit_size_to_attach_size (hw_parent (me), + ®.size, + &attach_size, me); + + hw_attach_address (hw_parent (me), 0, + attach_space, attach_address, attach_size, + me); + + if(hw_find_property(me, "backend") != NULL) + { + const char* value = hw_find_string_property(me, "backend"); + if(! strcmp(value, "tcp")) + controller->backend = sio_tcp; + else if(! strcmp(value, "stdio")) + controller->backend = sio_stdio; + else + hw_abort(me, "illegal value for backend parameter `%s': use tcp or stdio", value); + } + + controller->base_address = attach_address; +} + + +static void +tx3904sio_finish (struct hw *me) +{ + struct tx3904sio *controller; + + controller = HW_ZALLOC (me, struct tx3904sio); + set_hw_data (me, controller); + set_hw_io_read_buffer (me, tx3904sio_io_read_buffer); + set_hw_io_write_buffer (me, tx3904sio_io_write_buffer); + set_hw_ports (me, tx3904sio_ports); + set_hw_port_event (me, tx3904sio_port_event); + + /* Preset defaults */ + controller->backend = sio_stdio; + + /* Attach ourself to our parent bus */ + attach_tx3904sio_regs (me, controller); + + /* Initialize to reset state */ + tx3904sio_fifo_reset(me, & controller->rx_fifo); + tx3904sio_fifo_reset(me, & controller->tx_fifo); + controller->slsr = controller->sdicr + = controller->sdisr = controller->sfcr + = controller->sbgr = 0; + controller->slcr = 0x40000000; /* set TWUB */ + controller->sbgr = 0x03ff0000; /* set BCLK=3, BRD=FF */ + controller->poll_event = NULL; +} + + + +/* An event arrives on an interrupt port */ + +static void +tx3904sio_port_event (struct hw *me, + int my_port, + struct hw *source, + int source_port, + int level) +{ + struct tx3904sio *controller = hw_data (me); + + switch (my_port) + { + case RESET_PORT: + { + HW_TRACE ((me, "reset")); + + tx3904sio_fifo_reset(me, & controller->rx_fifo); + tx3904sio_fifo_reset(me, & controller->tx_fifo); + controller->slsr = controller->sdicr + = controller->sdisr = controller->sfcr + = controller->sbgr = 0; + controller->slcr = 0x40000000; /* set TWUB */ + controller->sbgr = 0x03ff0000; /* set BCLK=3, BRD=FF */ + /* Don't interfere with I/O poller. */ + break; + } + + default: + hw_abort (me, "Event on unknown port %d", my_port); + break; + } +} + + +/* generic read/write */ + +static unsigned +tx3904sio_io_read_buffer (struct hw *me, + void *dest, + int space, + unsigned_word base, + unsigned nr_bytes) +{ + struct tx3904sio *controller = hw_data (me); + unsigned byte; + + HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); + + /* tickle fifos */ + tx3904sio_tickle(me); + + for (byte = 0; byte < nr_bytes; byte++) + { + address_word address = base + byte; + int reg_number = (address - controller->base_address) / 4; + int reg_offset = (address - controller->base_address) % 4; + unsigned_4 register_value; /* in target byte order */ + + /* fill in entire register_value word */ + switch (reg_number) + { + case SLCR_REG: register_value = controller->slcr; break; + case SLSR_REG: register_value = controller->slsr; break; + case SDICR_REG: register_value = controller->sdicr; break; + case SDISR_REG: register_value = controller->sdisr; break; + case SFCR_REG: register_value = controller->sfcr; break; + case SBGR_REG: register_value = controller->sbgr; break; + case TFIFO_REG: register_value = 0; break; + case SFIFO_REG: + /* consume rx fifo for MS byte */ + if(reg_offset == 0 && tx3904sio_fifo_nonempty(me, & controller->rx_fifo)) + register_value = (tx3904sio_fifo_pop(me, & controller->rx_fifo) << 24); + else + register_value = 0; + break; + default: register_value = 0; + } + + /* write requested byte out */ + register_value = H2T_4(register_value); + /* HW_TRACE ((me, "byte %d %02x", reg_offset, ((char*)& register_value)[reg_offset])); */ + memcpy ((char*) dest + byte, ((char*)& register_value)+reg_offset, 1); + } + + return nr_bytes; +} + + + +static unsigned +tx3904sio_io_write_buffer (struct hw *me, + const void *source, + int space, + unsigned_word base, + unsigned nr_bytes) +{ + struct tx3904sio *controller = hw_data (me); + unsigned byte; + + HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); + for (byte = 0; byte < nr_bytes; byte++) + { + address_word address = base + byte; + unsigned_1 write_byte = ((const unsigned char*) source)[byte]; + int reg_number = (address - controller->base_address) / 4; + int reg_offset = 3 - (address - controller->base_address) % 4; + + /* HW_TRACE ((me, "byte %d %02x", reg_offset, write_byte)); */ + + /* fill in entire register_value word */ + switch (reg_number) + { + case SLCR_REG: + SLCR_SET_BYTE(controller, reg_offset, write_byte); + break; + + case SLSR_REG: /* unwriteable */ break; + + case SDICR_REG: + { + unsigned_4 last_int, next_int; + + /* deassert interrupt upon clear */ + last_int = controller->sdisr & controller->sdicr; + /* HW_TRACE ((me, "sdicr - sdisr %08x sdicr %08x", + controller->sdisr, controller->sdicr)); */ + SDICR_SET_BYTE(controller, reg_offset, write_byte); + /* HW_TRACE ((me, "sdicr + sdisr %08x sdicr %08x", + controller->sdisr, controller->sdicr)); */ + next_int = controller->sdisr & controller->sdicr; + + if(SDICR_GET_SDMAE(controller)) + hw_abort(me, "Cannot support DMA-driven sio."); + + if(~last_int & next_int) /* any bits set? */ + hw_port_event(me, INT_PORT, 1); + if(last_int & ~next_int) /* any bits cleared? */ + hw_port_event(me, INT_PORT, 0); + } + break; + + case SDISR_REG: + { + unsigned_4 last_int, next_int; + + /* deassert interrupt upon clear */ + last_int = controller->sdisr & controller->sdicr; + /* HW_TRACE ((me, "sdisr - sdisr %08x sdicr %08x", + controller->sdisr, controller->sdicr)); */ + SDISR_SET_BYTE(controller, reg_offset, write_byte); + /* HW_TRACE ((me, "sdisr + sdisr %08x sdicr %08x", + controller->sdisr, controller->sdicr)); */ + next_int = controller->sdisr & controller->sdicr; + + if(~last_int & next_int) /* any bits set? */ + hw_port_event(me, INT_PORT, 1); + if(last_int & ~next_int) /* any bits cleared? */ + hw_port_event(me, INT_PORT, 0); + } + break; + + case SFCR_REG: + SFCR_SET_BYTE(controller, reg_offset, write_byte); + if(SFCR_GET_FRSTE(controller)) + { + if(SFCR_GET_TFRST(controller)) tx3904sio_fifo_reset(me, & controller->tx_fifo); + if(SFCR_GET_RFRST(controller)) tx3904sio_fifo_reset(me, & controller->rx_fifo); + } + break; + + case SBGR_REG: + SBGR_SET_BYTE(controller, reg_offset, write_byte); + break; + + case SFIFO_REG: /* unwriteable */ break; + + case TFIFO_REG: + if(reg_offset == 3) /* first byte */ + tx3904sio_fifo_push(me, & controller->tx_fifo, write_byte); + break; + + default: + HW_TRACE ((me, "write to illegal register %d", reg_number)); + } + } /* loop over bytes */ + + /* tickle fifos */ + tx3904sio_tickle(me); + + return nr_bytes; +} + + + + + + +/* Send enqueued characters from tx_fifo and trigger TX interrupt. +Receive characters into rx_fifo and trigger RX interrupt. */ +void +tx3904sio_tickle(struct hw *me) +{ + struct tx3904sio* controller = hw_data(me); + int c; + char cc; + unsigned_4 last_int, next_int; + + /* HW_TRACE ((me, "tickle backend: %02x", controller->backend)); */ + switch(controller->backend) + { + case sio_tcp: + + while(tx3904sio_fifo_nonempty(me, & controller->tx_fifo)) + { + cc = tx3904sio_fifo_pop(me, & controller->tx_fifo); + dv_sockser_write(hw_system(me), cc); + HW_TRACE ((me, "tcp output: %02x", cc)); + } + + c = dv_sockser_read(hw_system(me)); + while(c != -1) + { + cc = (char) c; + HW_TRACE ((me, "tcp input: %02x", cc)); + tx3904sio_fifo_push(me, & controller->rx_fifo, cc); + c = dv_sockser_read(hw_system(me)); + } + break; + + case sio_stdio: + + while(tx3904sio_fifo_nonempty(me, & controller->tx_fifo)) + { + cc = tx3904sio_fifo_pop(me, & controller->tx_fifo); + sim_io_write_stdout(hw_system(me), & cc, 1); + sim_io_flush_stdout(hw_system(me)); + HW_TRACE ((me, "stdio output: %02x", cc)); + } + + c = sim_io_poll_read(hw_system(me), 0 /* stdin */, & cc, 1); + while(c == 1) + { + HW_TRACE ((me, "stdio input: %02x", cc)); + tx3904sio_fifo_push(me, & controller->rx_fifo, cc); + c = sim_io_poll_read(hw_system(me), 0 /* stdin */, & cc, 1); + } + + break; + + default: + hw_abort(me, "Illegal backend mode: %d", controller->backend); + } + + /* Update RDIS / TDIS flags */ + last_int = controller->sdisr & controller->sdicr; + /* HW_TRACE ((me, "tickle - sdisr %08x sdicr %08x", controller->sdisr, controller->sdicr)); */ + if(tx3904sio_fifo_nonempty(me, & controller->rx_fifo)) + SDISR_SET_RDIS(controller); + if(! tx3904sio_fifo_nonempty(me, & controller->tx_fifo)) + SDISR_SET_TDIS(controller); + next_int = controller->sdisr & controller->sdicr; + /* HW_TRACE ((me, "tickle + sdisr %08x sdicr %08x", controller->sdisr, controller->sdicr)); */ + + if(~last_int & next_int) /* any bits set? */ + hw_port_event(me, INT_PORT, 1); + if(last_int & ~next_int) /* any bits cleared? */ + hw_port_event(me, INT_PORT, 0); + + /* Add periodic polling for this port, if it's not already going. */ + if(controller->poll_event == NULL) + { + controller->poll_event = hw_event_queue_schedule (me, 1000, + tx3904sio_poll, NULL); + + } +} + + + + +int +tx3904sio_fifo_nonempty(struct hw* me, struct tx3904sio_fifo* fifo) +{ + /* HW_TRACE ((me, "fifo used: %d", fifo->used)); */ + return(fifo->used > 0); +} + + +char +tx3904sio_fifo_pop(struct hw* me, struct tx3904sio_fifo* fifo) +{ + char it; + ASSERT(fifo->used > 0); + ASSERT(fifo->buffer != NULL); + it = fifo->buffer[0]; + memcpy(& fifo->buffer[0], & fifo->buffer[1], fifo->used - 1); + fifo->used --; + /* HW_TRACE ((me, "pop fifo -> %02x", it)); */ + return it; +} + + +void +tx3904sio_fifo_push(struct hw* me, struct tx3904sio_fifo* fifo, char it) +{ + /* HW_TRACE ((me, "push %02x -> fifo", it)); */ + if(fifo->size == fifo->used) /* full */ + { + int next_size = fifo->size * 2 + 16; + char* next_buf = zalloc(next_size); + memcpy(next_buf, fifo->buffer, fifo->used); + + if(fifo->buffer != NULL) zfree(fifo->buffer); + fifo->buffer = next_buf; + fifo->size = next_size; + } + + fifo->buffer[fifo->used] = it; + fifo->used ++; +} + + +void +tx3904sio_fifo_reset(struct hw* me, struct tx3904sio_fifo* fifo) +{ + /* HW_TRACE ((me, "reset fifo")); */ + fifo->used = 0; + fifo->size = 0; + zfree(fifo->buffer); + fifo->buffer = 0; +} + + +void +tx3904sio_poll(struct hw* me, void* ignored) +{ + struct tx3904sio* controller = hw_data (me); + tx3904sio_tickle (me); + hw_event_queue_deschedule (me, controller->poll_event); + controller->poll_event = hw_event_queue_schedule (me, 1000, + tx3904sio_poll, NULL); +} + + + +const struct hw_descriptor dv_tx3904sio_descriptor[] = { + { "tx3904sio", tx3904sio_finish, }, + { NULL }, +}; diff --git a/sim/mips/dv-tx3904tmr.c b/sim/mips/dv-tx3904tmr.c new file mode 100644 index 0000000..c1c7b8c --- /dev/null +++ b/sim/mips/dv-tx3904tmr.c @@ -0,0 +1,698 @@ +/* This file is part of the program GDB, the GNU debugger. + + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "sim-main.h" +#include "hw-main.h" + + +/* DEVICE + + + tx3904tmr - tx3904 timer + + + DESCRIPTION + + + Implements one tx3904 timer/counter described in the tx3904 + user guide. Three instances are required for TMR0, TMR1, and + TMR3 within the tx3904, at different base addresses. + + Both internal and system clocks are synthesized as divided versions + of the simulator clock. + + There is no support for: + - edge sensitivity of external clock + - different mode restrictions for TMR0..2 + - level interrupts (interrupts are treated as events that occur at edges) + + + + PROPERTIES + + + reg <base> <length> + + Base of TMR control register bank. <length> must equal 0x100. + Register offsets: 0: TCR: timer control register + 4: TISR: timer interrupt status register + 8: CPRA: compare register A + 12: CPRB: compare register B + 16: ITMR: interval timer mode register + 32: CCDR: divider register + 48: PMGR: pulse generator mode register + 64: WTMR: watchdog timer mode register + 240: TRR: timer read register + + + clock <ticks> + + Rate of timer clock signal. This number is the number of simulator + ticks per clock signal tick. Default 1. + + + ext <ticks> + + Rate of "external input clock signal", the other clock input of the + timer. It uses the same scale as above. Default 100. + + + + PORTS + + + int (output) + + Interrupt port. An event is generated when a timer interrupt + occurs. + + + ff (output) + + Flip-flop output, corresponds to the TMFFOUT port. An event is + generated when flip-flop changes value. The integer associated + with the event is 1/0 according to flip-flop value. + + + reset (input) + + Reset port. + + */ + + + +/* static functions */ + +static void deliver_tx3904tmr_tick (struct hw *me, void *data); + + +/* register numbers; each is one word long */ +enum +{ + TCR_REG = 0, + TISR_REG = 1, + CPRA_REG = 2, + CPRB_REG = 3, + ITMR_REG = 4, + CCDR_REG = 8, + PMGR_REG = 12, + WTMR_REG = 16, + TRR_REG = 60 +}; + + + +/* port ID's */ + +enum + { + RESET_PORT, + INT_PORT, + FF_PORT +}; + + +static const struct hw_port_descriptor tx3904tmr_ports[] = +{ + { "int", INT_PORT, 0, output_port, }, + { "ff", FF_PORT, 0, output_port, }, + { "reset", RESET_PORT, 0, input_port, }, + { NULL, }, +}; + + + +/* The timer/counter register internal state. Note that we store + state using the control register images, in host endian order. */ + +struct tx3904tmr { + address_word base_address; /* control register base */ + unsigned_4 clock_ticks, ext_ticks; /* clock frequencies */ + signed_8 last_ticks; /* time at last deliver_*_tick call */ + signed_8 roundoff_ticks; /* sim ticks unprocessed during last tick call */ + int ff; /* pulse generator flip-flop value: 1/0 */ + struct hw_event* event; /* last scheduled event */ + + unsigned_4 tcr; +#define GET_TCR_TCE(c) (((c)->tcr & 0x80) >> 7) +#define GET_TCR_CCDE(c) (((c)->tcr & 0x40) >> 6) +#define GET_TCR_CRE(c) (((c)->tcr & 0x20) >> 5) +#define GET_TCR_CCS(c) (((c)->tcr & 0x04) >> 2) +#define GET_TCR_TMODE(c) (((c)->tcr & 0x03) >> 0) + unsigned_4 tisr; +#define SET_TISR_TWIS(c) ((c)->tisr |= 0x08) +#define SET_TISR_TPIBS(c) ((c)->tisr |= 0x04) +#define SET_TISR_TPIAS(c) ((c)->tisr |= 0x02) +#define SET_TISR_TIIS(c) ((c)->tisr |= 0x01) + unsigned_4 cpra; + unsigned_4 cprb; + unsigned_4 itmr; +#define GET_ITMR_TIIE(c) (((c)->itmr & 0x8000) >> 15) +#define SET_ITMR_TIIE(c,v) BLIT32((c)->itmr, 15, (v) ? 1 : 0) +#define GET_ITMR_TZCE(c) (((c)->itmr & 0x0001) >> 0) +#define SET_ITMR_TZCE(c,v) BLIT32((c)->itmr, 0, (v) ? 1 : 0) + unsigned_4 ccdr; +#define GET_CCDR_CDR(c) (((c)->ccdr & 0x07) >> 0) + unsigned_4 pmgr; +#define GET_PMGR_TPIBE(c) (((c)->pmgr & 0x8000) >> 15) +#define SET_PMGR_TPIBE(c,v) BLIT32((c)->pmgr, 15, (v) ? 1 : 0) +#define GET_PMGR_TPIAE(c) (((c)->pmgr & 0x4000) >> 14) +#define SET_PMGR_TPIAE(c,v) BLIT32((c)->pmgr, 14, (v) ? 1 : 0) +#define GET_PMGR_FFI(c) (((c)->pmgr & 0x0001) >> 0) +#define SET_PMGR_FFI(c,v) BLIT32((c)->pmgr, 0, (v) ? 1 : 0) + unsigned_4 wtmr; +#define GET_WTMR_TWIE(c) (((c)->wtmr & 0x8000) >> 15) +#define SET_WTMR_TWIE(c,v) BLIT32((c)->wtmr, 15, (v) ? 1 : 0) +#define GET_WTMR_WDIS(c) (((c)->wtmr & 0x0080) >> 7) +#define SET_WTMR_WDIS(c,v) BLIT32((c)->wtmr, 7, (v) ? 1 : 0) +#define GET_WTMR_TWC(c) (((c)->wtmr & 0x0001) >> 0) +#define SET_WTMR_TWC(c,v) BLIT32((c)->wtmr, 0, (v) ? 1 : 0) + unsigned_4 trr; +}; + + + +/* Finish off the partially created hw device. Attach our local + callbacks. Wire up our port names etc */ + +static hw_io_read_buffer_method tx3904tmr_io_read_buffer; +static hw_io_write_buffer_method tx3904tmr_io_write_buffer; +static hw_port_event_method tx3904tmr_port_event; + +static void +attach_tx3904tmr_regs (struct hw *me, + struct tx3904tmr *controller) +{ + unsigned_word attach_address; + int attach_space; + unsigned attach_size; + reg_property_spec reg; + + if (hw_find_property (me, "reg") == NULL) + hw_abort (me, "Missing \"reg\" property"); + + if (!hw_find_reg_array_property (me, "reg", 0, ®)) + hw_abort (me, "\"reg\" property must contain one addr/size entry"); + + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, + &attach_address, + me); + hw_unit_size_to_attach_size (hw_parent (me), + ®.size, + &attach_size, me); + + hw_attach_address (hw_parent (me), 0, + attach_space, attach_address, attach_size, + me); + + if(hw_find_property(me, "clock") != NULL) + controller->clock_ticks = (unsigned_4) hw_find_integer_property(me, "clock"); + + if(hw_find_property(me, "ext") != NULL) + controller->ext_ticks = (unsigned_4) hw_find_integer_property(me, "ext"); + + controller->base_address = attach_address; +} + + +static void +tx3904tmr_finish (struct hw *me) +{ + struct tx3904tmr *controller; + + controller = HW_ZALLOC (me, struct tx3904tmr); + set_hw_data (me, controller); + set_hw_io_read_buffer (me, tx3904tmr_io_read_buffer); + set_hw_io_write_buffer (me, tx3904tmr_io_write_buffer); + set_hw_ports (me, tx3904tmr_ports); + set_hw_port_event (me, tx3904tmr_port_event); + + /* Preset clock dividers */ + controller->clock_ticks = 1; + controller->ext_ticks = 100; + + /* Attach ourself to our parent bus */ + attach_tx3904tmr_regs (me, controller); + + /* Initialize to reset state */ + controller->tcr = + controller->itmr = + controller->ccdr = + controller->pmgr = + controller->wtmr = + controller->tisr = + controller->trr = 0; + controller->cpra = controller->cprb = 0x00FFFFFF; + controller->ff = 0; + controller->last_ticks = controller->roundoff_ticks = 0; + controller->event = NULL; +} + + + +/* An event arrives on an interrupt port */ + +static void +tx3904tmr_port_event (struct hw *me, + int my_port, + struct hw *source, + int source_port, + int level) +{ + struct tx3904tmr *controller = hw_data (me); + + switch (my_port) + { + case RESET_PORT: + { + HW_TRACE ((me, "reset")); + + /* preset flip-flop to FFI value */ + controller->ff = GET_PMGR_FFI(controller); + + controller->tcr = + controller->itmr = + controller->ccdr = + controller->pmgr = + controller->wtmr = + controller->tisr = + controller->trr = 0; + controller->cpra = controller->cprb = 0x00FFFFFF; + controller->last_ticks = controller->roundoff_ticks = 0; + if(controller->event != NULL) + hw_event_queue_deschedule(me, controller->event); + controller->event = NULL; + break; + } + + default: + hw_abort (me, "Event on unknown port %d", my_port); + break; + } +} + + +/* generic read/write */ + +static unsigned +tx3904tmr_io_read_buffer (struct hw *me, + void *dest, + int space, + unsigned_word base, + unsigned nr_bytes) +{ + struct tx3904tmr *controller = hw_data (me); + unsigned byte; + + HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); + for (byte = 0; byte < nr_bytes; byte++) + { + address_word address = base + byte; + int reg_number = (address - controller->base_address) / 4; + int reg_offset = 3 - (address - controller->base_address) % 4; + unsigned_4 register_value; /* in target byte order */ + + /* fill in entire register_value word */ + switch (reg_number) + { + case TCR_REG: register_value = controller->tcr; break; + case TISR_REG: register_value = controller->tisr; break; + case CPRA_REG: register_value = controller->cpra; break; + case CPRB_REG: register_value = controller->cprb; break; + case ITMR_REG: register_value = controller->itmr; break; + case CCDR_REG: register_value = controller->ccdr; break; + case PMGR_REG: register_value = controller->pmgr; break; + case WTMR_REG: register_value = controller->wtmr; break; + case TRR_REG: register_value = controller->trr; break; + default: register_value = 0; + } + + /* write requested byte out */ + memcpy ((char*) dest + byte, ((char*)& register_value)+reg_offset, 1); + } + + return nr_bytes; +} + + + +static unsigned +tx3904tmr_io_write_buffer (struct hw *me, + const void *source, + int space, + unsigned_word base, + unsigned nr_bytes) +{ + struct tx3904tmr *controller = hw_data (me); + unsigned byte; + + HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); + for (byte = 0; byte < nr_bytes; byte++) + { + address_word address = base + byte; + unsigned_1 write_byte = ((const char*) source)[byte]; + int reg_number = (address - controller->base_address) / 4; + int reg_offset = 3 - (address - controller->base_address) % 4; + + /* fill in entire register_value word */ + switch (reg_number) + { + case TCR_REG: + if(reg_offset == 0) /* first byte */ + { + /* update register, but mask out NOP bits */ + controller->tcr = (unsigned_4) (write_byte & 0xef); + + /* Reset counter value if timer suspended and CRE is set. */ + if(GET_TCR_TCE(controller) == 0 && + GET_TCR_CRE(controller) == 1) + controller->trr = 0; + } + /* HW_TRACE ((me, "tcr: %08lx", (long) controller->tcr)); */ + break; + + case ITMR_REG: + if(reg_offset == 1) /* second byte */ + { + SET_ITMR_TIIE(controller, write_byte & 0x80); + } + else if(reg_offset == 0) /* first byte */ + { + SET_ITMR_TZCE(controller, write_byte & 0x01); + } + /* HW_TRACE ((me, "itmr: %08lx", (long) controller->itmr)); */ + break; + + case CCDR_REG: + if(reg_offset == 0) /* first byte */ + { + controller->ccdr = write_byte & 0x07; + } + /* HW_TRACE ((me, "ccdr: %08lx", (long) controller->ccdr)); */ + break; + + case PMGR_REG: + if(reg_offset == 1) /* second byte */ + { + SET_PMGR_TPIBE(controller, write_byte & 0x80); + SET_PMGR_TPIAE(controller, write_byte & 0x40); + } + else if(reg_offset == 0) /* first byte */ + { + SET_PMGR_FFI(controller, write_byte & 0x01); + } + /* HW_TRACE ((me, "pmgr: %08lx", (long) controller->pmgr)); */ + break; + + case WTMR_REG: + if(reg_offset == 1) /* second byte */ + { + SET_WTMR_TWIE(controller, write_byte & 0x80); + } + else if(reg_offset == 0) /* first byte */ + { + SET_WTMR_WDIS(controller, write_byte & 0x80); + SET_WTMR_TWC(controller, write_byte & 0x01); + } + /* HW_TRACE ((me, "wtmr: %08lx", (long) controller->wtmr)); */ + break; + + case TISR_REG: + if(reg_offset == 0) /* first byte */ + { + /* All bits must be zero in given byte, according to + spec. */ + + /* Send an "interrupt off" event on the interrupt port */ + if(controller->tisr != 0) /* any interrupts active? */ + { + hw_port_event(me, INT_PORT, 0); + } + + /* clear interrupt status register */ + controller->tisr = 0; + } + /* HW_TRACE ((me, "tisr: %08lx", (long) controller->tisr)); */ + break; + + case CPRA_REG: + if(reg_offset < 3) /* first, second, or third byte */ + { + MBLIT32(controller->cpra, (reg_offset*8)+7, (reg_offset*8), write_byte); + } + /* HW_TRACE ((me, "cpra: %08lx", (long) controller->cpra)); */ + break; + + case CPRB_REG: + if(reg_offset < 3) /* first, second, or third byte */ + { + MBLIT32(controller->cprb, (reg_offset*8)+7, (reg_offset*8), write_byte); + } + /* HW_TRACE ((me, "cprb: %08lx", (long) controller->cprb)); */ + break; + + default: + HW_TRACE ((me, "write to illegal register %d", reg_number)); + } + } /* loop over bytes */ + + /* Schedule a timer event in near future, so we can increment or + stop the counter, to respond to register updates. */ + hw_event_queue_schedule(me, 1, deliver_tx3904tmr_tick, NULL); + + return nr_bytes; +} + + + +/* Deliver a clock tick to the counter. */ +static void +deliver_tx3904tmr_tick (struct hw *me, + void *data) +{ + struct tx3904tmr *controller = hw_data (me); + SIM_DESC sd = hw_system (me); + signed_8 this_ticks = sim_events_time(sd); + + signed_8 warp; + signed_8 divisor; + signed_8 quotient, remainder; + + /* compute simulation ticks between last tick and this tick */ + if(controller->last_ticks != 0) + warp = this_ticks - controller->last_ticks + controller->roundoff_ticks; + else + { + controller->last_ticks = this_ticks; /* initialize */ + warp = controller->roundoff_ticks; + } + + if(controller->event != NULL) + hw_event_queue_deschedule(me, controller->event); + controller->event = NULL; + + /* Check whether the timer ticking is enabled at this moment. This + largely a function of the TCE bit, but is also slightly + mode-dependent. */ + switch((int) GET_TCR_TMODE(controller)) + { + case 0: /* interval */ + /* do not advance counter if TCE = 0 or if holding at count = CPRA */ + if(GET_TCR_TCE(controller) == 0 || + controller->trr == controller->cpra) + return; + break; + + case 1: /* pulse generator */ + /* do not advance counter if TCE = 0 */ + if(GET_TCR_TCE(controller) == 0) + return; + break; + + case 2: /* watchdog */ + /* do not advance counter if TCE = 0 and WDIS = 1 */ + if(GET_TCR_TCE(controller) == 0 && + GET_WTMR_WDIS(controller) == 1) + return; + break; + + case 3: /* disabled */ + /* regardless of TCE, do not advance counter */ + return; + } + + /* In any of the above cases that return, a subsequent register + write will be needed to restart the timer. A tick event is + scheduled by any register write, so it is more efficient not to + reschedule dummy events here. */ + + + /* find appropriate divisor etc. */ + if(GET_TCR_CCS(controller) == 0) /* internal system clock */ + { + /* apply internal clock divider */ + if(GET_TCR_CCDE(controller)) /* divisor circuit enabled? */ + divisor = controller->clock_ticks * (1 << (1 + GET_CCDR_CDR(controller))); + else + divisor = controller->clock_ticks; + } + else + { + divisor = controller->ext_ticks; + } + + /* how many times to increase counter? */ + quotient = warp / divisor; + remainder = warp % divisor; + + /* NOTE: If the event rescheduling code works properly, the quotient + should never be larger than 1. That is, we should receive events + here at least as frequently as the simulated counter is supposed + to decrement. So the remainder (-> roundoff_ticks) will slowly + accumulate, with the quotient == 0. Once in a while, quotient + will equal 1. */ + + controller->roundoff_ticks = remainder; + controller->last_ticks = this_ticks; + while(quotient > 0) /* Is it time to increment counter? */ + { + /* next 24-bit counter value */ + unsigned_4 next_trr = (controller->trr + 1) % (1 << 24); + quotient --; + + switch((int) GET_TCR_TMODE(controller)) + { + case 0: /* interval timer mode */ + { + /* Current or next counter value matches CPRA value? The + first case covers counter holding at maximum before + reset. The second case covers normal counting + behavior. */ + if(controller->trr == controller->cpra || + next_trr == controller->cpra) + { + /* likely hold CPRA value */ + if(controller->trr == controller->cpra) + next_trr = controller->cpra; + + SET_TISR_TIIS(controller); + + /* Signal an interrupt if it is enabled with TIIE, + and if we just arrived at CPRA. Don't repeatedly + interrupt if holding due to TZCE=0 */ + if(GET_ITMR_TIIE(controller) && + next_trr != controller->trr) + { + hw_port_event(me, INT_PORT, 1); + } + + /* Reset counter? */ + if(GET_ITMR_TZCE(controller)) + { + next_trr = 0; + } + } + } + break; + + case 1: /* pulse generator mode */ + { + /* first trip point */ + if(next_trr == controller->cpra) + { + /* flip flip-flop & report */ + controller->ff ^= 1; + hw_port_event(me, FF_PORT, controller->ff); + SET_TISR_TPIAS(controller); + + /* signal interrupt */ + if(GET_PMGR_TPIAE(controller)) + { + hw_port_event(me, INT_PORT, 1); + } + + } + /* second trip point */ + else if(next_trr == controller->cprb) + { + /* flip flip-flop & report */ + controller->ff ^= 1; + hw_port_event(me, FF_PORT, controller->ff); + SET_TISR_TPIBS(controller); + + /* signal interrupt */ + if(GET_PMGR_TPIBE(controller)) + { + hw_port_event(me, INT_PORT, 1); + } + + /* clear counter */ + next_trr = 0; + } + } + break; + + case 2: /* watchdog timer mode */ + { + /* watchdog timer expiry */ + if(next_trr == controller->cpra) + { + SET_TISR_TWIS(controller); + + /* signal interrupt */ + if(GET_WTMR_TWIE(controller)) + { + hw_port_event(me, INT_PORT, 1); + } + + /* clear counter */ + next_trr = 0; + } + } + break; + + case 3: /* disabled */ + default: + } + + /* update counter and report */ + controller->trr = next_trr; + /* HW_TRACE ((me, "counter trr %ld tisr %lx", + (long) controller->trr, (long) controller->tisr)); */ + } /* end quotient loop */ + + /* Reschedule a timer event in near future, so we can increment the + counter again. Set the event about 75% of divisor time away, so + we will experience roughly 1.3 events per counter increment. */ + controller->event = hw_event_queue_schedule(me, divisor*3/4, deliver_tx3904tmr_tick, NULL); +} + + + + +const struct hw_descriptor dv_tx3904tmr_descriptor[] = { + { "tx3904tmr", tx3904tmr_finish, }, + { NULL }, +}; diff --git a/sim/mips/interp.c b/sim/mips/interp.c new file mode 100644 index 0000000..75bc54b --- /dev/null +++ b/sim/mips/interp.c @@ -0,0 +1,3228 @@ +/*> interp.c <*/ +/* Simulator for the MIPS architecture. + + This file is part of the MIPS sim + + THIS SOFTWARE IS NOT COPYRIGHTED + + Cygnus offers the following for use in the public domain. Cygnus + makes no warranty with regard to the software or it's performance + and the user accepts the software "AS IS" with all faults. + + CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO + THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + $Revision$ + $Date$ + +NOTEs: + +The IDT monitor (found on the VR4300 board), seems to lie about +register contents. It seems to treat the registers as sign-extended +32-bit values. This cause *REAL* problems when single-stepping 64-bit +code on the hardware. + +*/ + +/* The TRACE manifests enable the provision of extra features. If they + are not defined then a simpler (quicker) simulator is constructed + without the required run-time checks, etc. */ +#if 1 /* 0 to allow user build selection, 1 to force inclusion */ +#define TRACE (1) +#endif + +#include "bfd.h" +#include "sim-main.h" +#include "sim-utils.h" +#include "sim-options.h" +#include "sim-assert.h" +#include "sim-hw.h" + +#include "itable.h" + + +#include "config.h" + +#include <stdio.h> +#include <stdarg.h> +#include <ansidecl.h> +#include <ctype.h> +#include <limits.h> +#include <math.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#else +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#endif + +#include "getopt.h" +#include "libiberty.h" +#include "bfd.h" +#include "callback.h" /* GDB simulator callback interface */ +#include "remote-sim.h" /* GDB simulator interface */ + +#include "sysdep.h" + +#ifndef PARAMS +#define PARAMS(x) +#endif + +char* pr_addr PARAMS ((SIM_ADDR addr)); +char* pr_uword64 PARAMS ((uword64 addr)); + + +/* Within interp.c we refer to the sim_state and sim_cpu directly. */ +#define CPU cpu +#define SD sd + + +/* The following reserved instruction value is used when a simulator + trap is required. NOTE: Care must be taken, since this value may be + used in later revisions of the MIPS ISA. */ + +#define RSVD_INSTRUCTION (0x00000005) +#define RSVD_INSTRUCTION_MASK (0xFC00003F) + +#define RSVD_INSTRUCTION_ARG_SHIFT 6 +#define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF + + +/* Bits in the Debug register */ +#define Debug_DBD 0x80000000 /* Debug Branch Delay */ +#define Debug_DM 0x40000000 /* Debug Mode */ +#define Debug_DBp 0x00000002 /* Debug Breakpoint indicator */ + +/*---------------------------------------------------------------------------*/ +/*-- GDB simulator interface ------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +static void ColdReset PARAMS((SIM_DESC sd)); + +/*---------------------------------------------------------------------------*/ + + + +#define DELAYSLOT() {\ + if (STATE & simDELAYSLOT)\ + sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\ + STATE |= simDELAYSLOT;\ + } + +#define JALDELAYSLOT() {\ + DELAYSLOT ();\ + STATE |= simJALDELAYSLOT;\ + } + +#define NULLIFY() {\ + STATE &= ~simDELAYSLOT;\ + STATE |= simSKIPNEXT;\ + } + +#define CANCELDELAYSLOT() {\ + DSSTATE = 0;\ + STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\ + } + +#define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0) +#define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0) + +#define K0BASE (0x80000000) +#define K0SIZE (0x20000000) +#define K1BASE (0xA0000000) +#define K1SIZE (0x20000000) +#define MONITOR_BASE (0xBFC00000) +#define MONITOR_SIZE (1 << 11) +#define MEM_SIZE (2 << 20) + + +#if defined(TRACE) +static char *tracefile = "trace.din"; /* default filename for trace log */ +FILE *tracefh = NULL; +static void open_trace PARAMS((SIM_DESC sd)); +#endif /* TRACE */ + +static const char * get_insn_name (sim_cpu *, int); + +/* simulation target board. NULL=canonical */ +static char* board = NULL; + + +static DECLARE_OPTION_HANDLER (mips_option_handler); + +enum { + OPTION_DINERO_TRACE = OPTION_START, + OPTION_DINERO_FILE, + OPTION_BOARD +}; + + +static SIM_RC +mips_option_handler (sd, cpu, opt, arg, is_command) + SIM_DESC sd; + sim_cpu *cpu; + int opt; + char *arg; + int is_command; +{ + int cpu_nr; + switch (opt) + { + case OPTION_DINERO_TRACE: /* ??? */ +#if defined(TRACE) + /* Eventually the simTRACE flag could be treated as a toggle, to + allow external control of the program points being traced + (i.e. only from main onwards, excluding the run-time setup, + etc.). */ + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) + { + sim_cpu *cpu = STATE_CPU (sd, cpu_nr); + if (arg == NULL) + STATE |= simTRACE; + else if (strcmp (arg, "yes") == 0) + STATE |= simTRACE; + else if (strcmp (arg, "no") == 0) + STATE &= ~simTRACE; + else if (strcmp (arg, "on") == 0) + STATE |= simTRACE; + else if (strcmp (arg, "off") == 0) + STATE &= ~simTRACE; + else + { + fprintf (stderr, "Unrecognized dinero-trace option `%s'\n", arg); + return SIM_RC_FAIL; + } + } + return SIM_RC_OK; +#else /* !TRACE */ + fprintf(stderr,"\ +Simulator constructed without dinero tracing support (for performance).\n\ +Re-compile simulator with \"-DTRACE\" to enable this option.\n"); + return SIM_RC_FAIL; +#endif /* !TRACE */ + + case OPTION_DINERO_FILE: +#if defined(TRACE) + if (optarg != NULL) { + char *tmp; + tmp = (char *)malloc(strlen(optarg) + 1); + if (tmp == NULL) + { + sim_io_printf(sd,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg); + return SIM_RC_FAIL; + } + else { + strcpy(tmp,optarg); + tracefile = tmp; + sim_io_printf(sd,"Placing trace information into file \"%s\"\n",tracefile); + } + } +#endif /* TRACE */ + return SIM_RC_OK; + + case OPTION_BOARD: + { + if (arg) + { + board = zalloc(strlen(arg) + 1); + strcpy(board, arg); + } + return SIM_RC_OK; + } + } + + return SIM_RC_OK; +} + + +static const OPTION mips_options[] = +{ + { {"dinero-trace", optional_argument, NULL, OPTION_DINERO_TRACE}, + '\0', "on|off", "Enable dinero tracing", + mips_option_handler }, + { {"dinero-file", required_argument, NULL, OPTION_DINERO_FILE}, + '\0', "FILE", "Write dinero trace to FILE", + mips_option_handler }, + { {"board", required_argument, NULL, OPTION_BOARD}, + '\0', "none" /* rely on compile-time string concatenation for other options */ + +#define BOARD_JMR3904 "jmr3904" + "|" BOARD_JMR3904 +#define BOARD_JMR3904_PAL "jmr3904pal" + "|" BOARD_JMR3904_PAL +#define BOARD_JMR3904_DEBUG "jmr3904debug" + "|" BOARD_JMR3904_DEBUG + + , "Customize simulation for a particular board.", mips_option_handler }, + + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + + +int interrupt_pending; + +void +interrupt_event (SIM_DESC sd, void *data) +{ + sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */ + address_word cia = CIA_GET (cpu); + if (SR & status_IE) + { + interrupt_pending = 0; + SignalExceptionInterrupt (1); /* interrupt "1" */ + } + else if (!interrupt_pending) + sim_events_schedule (sd, 1, interrupt_event, data); +} + + +/*---------------------------------------------------------------------------*/ +/*-- Device registration hook -----------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +static void device_init(SIM_DESC sd) { +#ifdef DEVICE_INIT + extern void register_devices(SIM_DESC); + register_devices(sd); +#endif +} + +/*---------------------------------------------------------------------------*/ +/*-- GDB simulator interface ------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +SIM_DESC +sim_open (kind, cb, abfd, argv) + SIM_OPEN_KIND kind; + host_callback *cb; + struct _bfd *abfd; + char **argv; +{ + SIM_DESC sd = sim_state_alloc (kind, cb); + sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */ + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + /* FIXME: watchpoints code shouldn't need this */ + STATE_WATCHPOINTS (sd)->pc = &(PC); + STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC); + STATE_WATCHPOINTS (sd)->interrupt_handler = interrupt_event; + + /* Initialize the mechanism for doing insn profiling. */ + CPU_INSN_NAME (cpu) = get_insn_name; + CPU_MAX_INSNS (cpu) = nr_itable_entries; + + STATE = 0; + + if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) + return 0; + sim_add_option_table (sd, NULL, mips_options); + + + /* 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) + { + /* Uninstall the modules to avoid memory leaks, + file descriptor leaks, etc. */ + sim_module_uninstall (sd); + return 0; + } + + /* handle board-specific memory maps */ + if (board == NULL) + { + /* Allocate core managed memory */ + + /* the monitor */ + sim_do_commandf (sd, "memory region 0x%lx,0x%lx", MONITOR_BASE, MONITOR_SIZE); + /* For compatibility with the old code - under this (at level one) + are the kernel spaces K0 & K1. Both of these map to a single + smaller sub region */ + sim_do_command(sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */ + sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x", + K1BASE, K0SIZE, + MEM_SIZE, /* actual size */ + K0BASE); + + device_init(sd); + } + +#if (WITH_HW) + if (board != NULL + && (strcmp(board, BOARD_JMR3904) == 0 || + strcmp(board, BOARD_JMR3904_PAL) == 0 || + strcmp(board, BOARD_JMR3904_DEBUG) == 0)) + { + /* match VIRTUAL memory layout of JMR-TX3904 board */ + int i; + + /* --- environment --- */ + + STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT; + + /* --- memory --- */ + + /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */ + sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x", + 0x9FC00000, + 4 * 1024 * 1024, /* 4 MB */ + 0xBFC00000); + + /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */ + sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x", + 0x80000000, + 4 * 1024 * 1024, /* 4 MB */ + 0xA0000000); + + /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */ + for (i=0; i<8; i++) /* 32 MB total */ + { + unsigned size = 4 * 1024 * 1024; /* 4 MB */ + sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x", + 0x88000000 + (i * size), + size, + 0xA8000000 + (i * size)); + } + + /* Dummy memory regions for unsimulated devices */ + + sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFFE010, 0x00c); /* EBIF */ + sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFF9000, 0x200); /* EBIF */ + sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFFF500, 0x300); /* PIO */ + + /* --- simulated devices --- */ + sim_hw_parse (sd, "/tx3904irc@0xffffc000/reg 0xffffc000 0x20"); + sim_hw_parse (sd, "/tx3904cpu"); + sim_hw_parse (sd, "/tx3904tmr@0xfffff000/reg 0xfffff000 0x100"); + sim_hw_parse (sd, "/tx3904tmr@0xfffff100/reg 0xfffff100 0x100"); + sim_hw_parse (sd, "/tx3904tmr@0xfffff200/reg 0xfffff200 0x100"); + sim_hw_parse (sd, "/tx3904sio@0xfffff300/reg 0xfffff300 0x100"); + { + /* FIXME: poking at dv-sockser internals, use tcp backend if + --sockser_addr option was given.*/ + extern char* sockser_addr; + if(sockser_addr == NULL) + sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend stdio"); + else + sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend tcp"); + } + sim_hw_parse (sd, "/tx3904sio@0xfffff400/reg 0xfffff400 0x100"); + sim_hw_parse (sd, "/tx3904sio@0xfffff400/backend stdio"); + + /* -- device connections --- */ + sim_hw_parse (sd, "/tx3904irc > ip level /tx3904cpu"); + sim_hw_parse (sd, "/tx3904tmr@0xfffff000 > int tmr0 /tx3904irc"); + sim_hw_parse (sd, "/tx3904tmr@0xfffff100 > int tmr1 /tx3904irc"); + sim_hw_parse (sd, "/tx3904tmr@0xfffff200 > int tmr2 /tx3904irc"); + sim_hw_parse (sd, "/tx3904sio@0xfffff300 > int sio0 /tx3904irc"); + sim_hw_parse (sd, "/tx3904sio@0xfffff400 > int sio1 /tx3904irc"); + + /* add PAL timer & I/O module */ + if(! strcmp(board, BOARD_JMR3904_PAL)) + { + /* the device */ + sim_hw_parse (sd, "/pal@0xffff0000"); + sim_hw_parse (sd, "/pal@0xffff0000/reg 0xffff0000 64"); + + /* wire up interrupt ports to irc */ + sim_hw_parse (sd, "/pal@0x31000000 > countdown tmr0 /tx3904irc"); + sim_hw_parse (sd, "/pal@0x31000000 > timer tmr1 /tx3904irc"); + sim_hw_parse (sd, "/pal@0x31000000 > int int0 /tx3904irc"); + } + + if(! strcmp(board, BOARD_JMR3904_DEBUG)) + { + /* -- DEBUG: glue interrupt generators --- */ + sim_hw_parse (sd, "/glue@0xffff0000/reg 0xffff0000 0x50"); + sim_hw_parse (sd, "/glue@0xffff0000 > int0 int0 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int1 int1 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int2 int2 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int3 int3 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int4 int4 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int5 int5 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int6 int6 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int7 int7 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int8 dmac0 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int9 dmac1 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int10 dmac2 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int11 dmac3 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int12 sio0 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int13 sio1 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int14 tmr0 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int15 tmr1 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int16 tmr2 /tx3904irc"); + sim_hw_parse (sd, "/glue@0xffff0000 > int17 nmi /tx3904cpu"); + } + + device_init(sd); + } +#endif + + + /* 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) + { + sim_module_uninstall (sd); + return 0; + } + + /* 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 (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; + } + + /* verify assumptions the simulator made about the host type system. + This macro does not return if there is a problem */ + SIM_ASSERT (sizeof(int) == (4 * sizeof(char))); + SIM_ASSERT (sizeof(word64) == (8 * sizeof(char))); + + /* This is NASTY, in that we are assuming the size of specific + registers: */ + { + int rn; + for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++) + { + if (rn < 32) + cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE; + else if ((rn >= FGRIDX) && (rn < (FGRIDX + NR_FGR))) + cpu->register_widths[rn] = WITH_TARGET_FLOATING_POINT_BITSIZE; + else if ((rn >= 33) && (rn <= 37)) + cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE; + else if ((rn == SRIDX) + || (rn == FCR0IDX) + || (rn == FCR31IDX) + || ((rn >= 72) && (rn <= 89))) + cpu->register_widths[rn] = 32; + else + cpu->register_widths[rn] = 0; + } + + + } + +#if defined(TRACE) + if (STATE & simTRACE) + open_trace(sd); +#endif /* TRACE */ + + /* Write an abort sequence into the TRAP (common) exception vector + addresses. This is to catch code executing a TRAP (et.al.) + instruction without installing a trap handler. */ + { + unsigned32 halt[2] = { 0x2404002f /* addiu r4, r0, 47 */, + HALT_INSTRUCTION /* BREAK */ }; + H2T (halt[0]); + H2T (halt[1]); + sim_write (sd, 0x80000000, (char *) halt, sizeof (halt)); + sim_write (sd, 0x80000180, (char *) halt, sizeof (halt)); + sim_write (sd, 0x80000200, (char *) halt, sizeof (halt)); + sim_write (sd, 0xBFC00200, (char *) halt, sizeof (halt)); + sim_write (sd, 0xBFC00380, (char *) halt, sizeof (halt)); + sim_write (sd, 0xBFC00400, (char *) halt, sizeof (halt)); + } + + + /* Write the monitor trap address handlers into the monitor (eeprom) + address space. This can only be done once the target endianness + has been determined. */ + { + unsigned loop; + /* Entry into the IDT monitor is via fixed address vectors, and + not using machine instructions. To avoid clashing with use of + the MIPS TRAP system, we place our own (simulator specific) + "undefined" instructions into the relevant vector slots. */ + for (loop = 0; (loop < MONITOR_SIZE); loop += 4) + { + address_word vaddr = (MONITOR_BASE + loop); + unsigned32 insn = (RSVD_INSTRUCTION | (((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK) << RSVD_INSTRUCTION_ARG_SHIFT)); + H2T (insn); + sim_write (sd, vaddr, (char *)&insn, sizeof (insn)); + } + /* The PMON monitor uses the same address space, but rather than + branching into it the address of a routine is loaded. We can + cheat for the moment, and direct the PMON routine to IDT style + instructions within the monitor space. This relies on the IDT + monitor not using the locations from 0xBFC00500 onwards as its + entry points.*/ + for (loop = 0; (loop < 24); loop++) + { + address_word vaddr = (MONITOR_BASE + 0x500 + (loop * 4)); + unsigned32 value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */ + switch (loop) + { + case 0: /* read */ + value = 7; + break; + case 1: /* write */ + value = 8; + break; + case 2: /* open */ + value = 6; + break; + case 3: /* close */ + value = 10; + break; + case 5: /* printf */ + value = ((0x500 - 16) / 8); /* not an IDT reason code */ + break; + case 8: /* cliexit */ + value = 17; + break; + case 11: /* flush_cache */ + value = 28; + break; + } + /* FIXME - should monitor_base be SIM_ADDR?? */ + value = ((unsigned int)MONITOR_BASE + (value * 8)); + H2T (value); + sim_write (sd, vaddr, (char *)&value, sizeof (value)); + + /* The LSI MiniRISC PMON has its vectors at 0x200, not 0x500. */ + vaddr -= 0x300; + sim_write (sd, vaddr, (char *)&value, sizeof (value)); + } + } + + + + return sd; +} + +#if defined(TRACE) +static void +open_trace(sd) + SIM_DESC sd; +{ + tracefh = fopen(tracefile,"wb+"); + if (tracefh == NULL) + { + sim_io_eprintf(sd,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile); + tracefh = stderr; + } +} +#endif /* TRACE */ + +/* Return name of an insn, used by insn profiling. */ +static const char * +get_insn_name (sim_cpu *cpu, int i) +{ + return itable[i].name; +} + +void +sim_close (sd, quitting) + SIM_DESC sd; + int quitting; +{ +#ifdef DEBUG + printf("DBG: sim_close: entered (quitting = %d)\n",quitting); +#endif + + + /* "quitting" is non-zero if we cannot hang on errors */ + + /* shut down modules */ + sim_module_uninstall (sd); + + /* Ensure that any resources allocated through the callback + mechanism are released: */ + sim_io_shutdown (sd); + +#if defined(TRACE) + if (tracefh != NULL && tracefh != stderr) + fclose(tracefh); + tracefh = NULL; +#endif /* TRACE */ + + /* FIXME - free SD */ + + return; +} + + +int +sim_write (sd,addr,buffer,size) + SIM_DESC sd; + SIM_ADDR addr; + unsigned char *buffer; + int size; +{ + int index; + sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */ + + /* Return the number of bytes written, or zero if error. */ +#ifdef DEBUG + sim_io_printf(sd,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr),size); +#endif + + /* We use raw read and write routines, since we do not want to count + the GDB memory accesses in our statistics gathering. */ + + for (index = 0; index < size; index++) + { + address_word vaddr = (address_word)addr + index; + address_word paddr; + int cca; + if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isSTORE, &paddr, &cca, isRAW)) + break; + if (sim_core_write_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1) + break; + } + + return(index); +} + +int +sim_read (sd,addr,buffer,size) + SIM_DESC sd; + SIM_ADDR addr; + unsigned char *buffer; + int size; +{ + int index; + sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */ + + /* Return the number of bytes read, or zero if error. */ +#ifdef DEBUG + sim_io_printf(sd,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr),size); +#endif /* DEBUG */ + + for (index = 0; (index < size); index++) + { + address_word vaddr = (address_word)addr + index; + address_word paddr; + int cca; + if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isLOAD, &paddr, &cca, isRAW)) + break; + if (sim_core_read_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1) + break; + } + + return(index); +} + +int +sim_store_register (sd,rn,memory,length) + SIM_DESC sd; + int rn; + unsigned char *memory; + int length; +{ + sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */ + /* NOTE: gdb (the client) stores registers in target byte order + while the simulator uses host byte order */ +#ifdef DEBUG + sim_io_printf(sd,"sim_store_register(%d,*memory=0x%s);\n",rn,pr_addr(*((SIM_ADDR *)memory))); +#endif /* DEBUG */ + + /* Unfortunately this suffers from the same problem as the register + numbering one. We need to know what the width of each logical + register number is for the architecture being simulated. */ + + if (cpu->register_widths[rn] == 0) + { + sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn); + return 0; + } + + + + if (rn >= FGRIDX && rn < FGRIDX + NR_FGR) + { + if (cpu->register_widths[rn] == 32) + { + cpu->fgr[rn - FGRIDX] = T2H_4 (*(unsigned32*)memory); + return 4; + } + else + { + cpu->fgr[rn - FGRIDX] = T2H_8 (*(unsigned64*)memory); + return 8; + } + } + + if (cpu->register_widths[rn] == 32) + { + cpu->registers[rn] = T2H_4 (*(unsigned32*)memory); + return 4; + } + else + { + cpu->registers[rn] = T2H_8 (*(unsigned64*)memory); + return 8; + } + + return 0; +} + +int +sim_fetch_register (sd,rn,memory,length) + SIM_DESC sd; + int rn; + unsigned char *memory; + int length; +{ + sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */ + /* NOTE: gdb (the client) stores registers in target byte order + while the simulator uses host byte order */ +#ifdef DEBUG +#if 0 /* FIXME: doesn't compile */ + sim_io_printf(sd,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn,pr_addr(registers[rn])); +#endif +#endif /* DEBUG */ + + if (cpu->register_widths[rn] == 0) + { + sim_io_eprintf (sd, "Invalid register width for %d (register fetch ignored)\n",rn); + return 0; + } + + + + /* Any floating point register */ + if (rn >= FGRIDX && rn < FGRIDX + NR_FGR) + { + if (cpu->register_widths[rn] == 32) + { + *(unsigned32*)memory = H2T_4 (cpu->fgr[rn - FGRIDX]); + return 4; + } + else + { + *(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGRIDX]); + return 8; + } + } + + if (cpu->register_widths[rn] == 32) + { + *(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->registers[rn])); + return 4; + } + else + { + *(unsigned64*)memory = H2T_8 ((unsigned64)(cpu->registers[rn])); + return 8; + } + + return 0; +} + + +SIM_RC +sim_create_inferior (sd, abfd, argv,env) + SIM_DESC sd; + struct _bfd *abfd; + char **argv; + char **env; +{ + +#ifdef DEBUG +#if 0 /* FIXME: doesn't compile */ + printf("DBG: sim_create_inferior entered: start_address = 0x%s\n", + pr_addr(PC)); +#endif +#endif /* DEBUG */ + + ColdReset(sd); + + if (abfd != NULL) + { + /* override PC value set by ColdReset () */ + int cpu_nr; + for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++) + { + sim_cpu *cpu = STATE_CPU (sd, cpu_nr); + CIA_SET (cpu, (unsigned64) bfd_get_start_address (abfd)); + } + } + +#if 0 /* def DEBUG */ + if (argv || env) + { + /* We should really place the argv slot values into the argument + registers, and onto the stack as required. However, this + assumes that we have a stack defined, which is not + necessarily true at the moment. */ + char **cptr; + sim_io_printf(sd,"sim_create_inferior() : passed arguments ignored\n"); + for (cptr = argv; (cptr && *cptr); cptr++) + printf("DBG: arg \"%s\"\n",*cptr); + } +#endif /* DEBUG */ + + return SIM_RC_OK; +} + +void +sim_do_command (sd,cmd) + SIM_DESC sd; + char *cmd; +{ + if (sim_args_command (sd, cmd) != SIM_RC_OK) + sim_io_printf (sd, "Error: \"%s\" is not a valid MIPS simulator command.\n", + cmd); +} + +/*---------------------------------------------------------------------------*/ +/*-- Private simulator support interface ------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +/* Read a null terminated string from memory, return in a buffer */ +static char * +fetch_str (SIM_DESC sd, + address_word addr) +{ + char *buf; + int nr = 0; + char null; + while (sim_read (sd, addr + nr, &null, 1) == 1 && null != 0) + nr++; + buf = NZALLOC (char, nr + 1); + sim_read (sd, addr, buf, nr); + return buf; +} + +/* Simple monitor interface (currently setup for the IDT and PMON monitors) */ +void +sim_monitor (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + unsigned int reason) +{ +#ifdef DEBUG + printf("DBG: sim_monitor: entered (reason = %d)\n",reason); +#endif /* DEBUG */ + + /* The IDT monitor actually allows two instructions per vector + slot. However, the simulator currently causes a trap on each + individual instruction. We cheat, and lose the bottom bit. */ + reason >>= 1; + + /* The following callback functions are available, however the + monitor we are simulating does not make use of them: get_errno, + isatty, lseek, rename, system, time and unlink */ + switch (reason) + { + + case 6: /* int open(char *path,int flags) */ + { + char *path = fetch_str (sd, A0); + V0 = sim_io_open (sd, path, (int)A1); + zfree (path); + break; + } + + case 7: /* int read(int file,char *ptr,int len) */ + { + int fd = A0; + int nr = A2; + char *buf = zalloc (nr); + V0 = sim_io_read (sd, fd, buf, nr); + sim_write (sd, A1, buf, nr); + zfree (buf); + } + break; + + case 8: /* int write(int file,char *ptr,int len) */ + { + int fd = A0; + int nr = A2; + char *buf = zalloc (nr); + sim_read (sd, A1, buf, nr); + V0 = sim_io_write (sd, fd, buf, nr); + zfree (buf); + break; + } + + case 10: /* int close(int file) */ + { + V0 = sim_io_close (sd, (int)A0); + break; + } + + case 2: /* Densan monitor: char inbyte(int waitflag) */ + { + if (A0 == 0) /* waitflag == NOWAIT */ + V0 = (unsigned_word)-1; + } + /* Drop through to case 11 */ + + case 11: /* char inbyte(void) */ + { + char tmp; + if (sim_io_read_stdin (sd, &tmp, sizeof(char)) != sizeof(char)) + { + sim_io_error(sd,"Invalid return from character read"); + V0 = (unsigned_word)-1; + } + else + V0 = (unsigned_word)tmp; + break; + } + + case 3: /* Densan monitor: void co(char chr) */ + case 12: /* void outbyte(char chr) : write a byte to "stdout" */ + { + char tmp = (char)(A0 & 0xFF); + sim_io_write_stdout (sd, &tmp, sizeof(char)); + break; + } + + case 17: /* void _exit() */ + { + sim_io_eprintf (sd, "sim_monitor(17): _exit(int reason) to be coded\n"); + sim_engine_halt (SD, CPU, NULL, NULL_CIA, sim_exited, + (unsigned int)(A0 & 0xFFFFFFFF)); + break; + } + + case 28 : /* PMON flush_cache */ + break; + + case 55: /* void get_mem_info(unsigned int *ptr) */ + /* in: A0 = pointer to three word memory location */ + /* out: [A0 + 0] = size */ + /* [A0 + 4] = instruction cache size */ + /* [A0 + 8] = data cache size */ + { + unsigned_4 value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */; + unsigned_4 zero = 0; + H2T (value); + sim_write (sd, A0 + 0, (char *)&value, 4); + sim_write (sd, A0 + 4, (char *)&zero, 4); + sim_write (sd, A0 + 8, (char *)&zero, 4); + /* sim_io_eprintf (sd, "sim: get_mem_info() depreciated\n"); */ + break; + } + + case 158 : /* PMON printf */ + /* in: A0 = pointer to format string */ + /* A1 = optional argument 1 */ + /* A2 = optional argument 2 */ + /* A3 = optional argument 3 */ + /* out: void */ + /* The following is based on the PMON printf source */ + { + address_word s = A0; + char c; + signed_word *ap = &A1; /* 1st argument */ + /* This isn't the quickest way, since we call the host print + routine for every character almost. But it does avoid + having to allocate and manage a temporary string buffer. */ + /* TODO: Include check that we only use three arguments (A1, + A2 and A3) */ + while (sim_read (sd, s++, &c, 1) && c != '\0') + { + if (c == '%') + { + char tmp[40]; + enum {FMT_RJUST, FMT_LJUST, FMT_RJUST0, FMT_CENTER} fmt = FMT_RJUST; + int width = 0, trunc = 0, haddot = 0, longlong = 0; + while (sim_read (sd, s++, &c, 1) && c != '\0') + { + if (strchr ("dobxXulscefg%", c)) + break; + else if (c == '-') + fmt = FMT_LJUST; + else if (c == '0') + fmt = FMT_RJUST0; + else if (c == '~') + fmt = FMT_CENTER; + else if (c == '*') + { + if (haddot) + trunc = (int)*ap++; + else + width = (int)*ap++; + } + else if (c >= '1' && c <= '9') + { + address_word t = s; + unsigned int n; + while (sim_read (sd, s++, &c, 1) == 1 && isdigit (c)) + tmp[s - t] = c; + tmp[s - t] = '\0'; + n = (unsigned int)strtol(tmp,NULL,10); + if (haddot) + trunc = n; + else + width = n; + s--; + } + else if (c == '.') + haddot = 1; + } + switch (c) + { + case '%': + sim_io_printf (sd, "%%"); + break; + case 's': + if ((int)*ap != 0) + { + address_word p = *ap++; + char ch; + while (sim_read (sd, p++, &ch, 1) == 1 && ch != '\0') + sim_io_printf(sd, "%c", ch); + } + else + sim_io_printf(sd,"(null)"); + break; + case 'c': + sim_io_printf (sd, "%c", (int)*ap++); + break; + default: + if (c == 'l') + { + sim_read (sd, s++, &c, 1); + if (c == 'l') + { + longlong = 1; + sim_read (sd, s++, &c, 1); + } + } + if (strchr ("dobxXu", c)) + { + word64 lv = (word64) *ap++; + if (c == 'b') + sim_io_printf(sd,"<binary not supported>"); + else + { + sprintf (tmp, "%%%s%c", longlong ? "ll" : "", c); + if (longlong) + sim_io_printf(sd, tmp, lv); + else + sim_io_printf(sd, tmp, (int)lv); + } + } + else if (strchr ("eEfgG", c)) + { + double dbl = *(double*)(ap++); + sprintf (tmp, "%%%d.%d%c", width, trunc, c); + sim_io_printf (sd, tmp, dbl); + trunc = 0; + } + } + } + else + sim_io_printf(sd, "%c", c); + } + break; + } + + default: + sim_io_error (sd, "TODO: sim_monitor(%d) : PC = 0x%s\n", + reason, pr_addr(cia)); + break; + } + return; +} + +/* Store a word into memory. */ + +static void +store_word (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + uword64 vaddr, + signed_word val) +{ + address_word paddr; + int uncached; + + if ((vaddr & 3) != 0) + SignalExceptionAddressStore (); + else + { + if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, + isTARGET, isREAL)) + { + const uword64 mask = 7; + uword64 memval; + unsigned int byte; + + paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)); + byte = (vaddr & mask) ^ (BigEndianCPU << 2); + memval = ((uword64) val) << (8 * byte); + StoreMemory (uncached, AccessLength_WORD, memval, 0, paddr, vaddr, + isREAL); + } + } +} + +/* Load a word from memory. */ + +static signed_word +load_word (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + uword64 vaddr) +{ + if ((vaddr & 3) != 0) + { + SIM_CORE_SIGNAL (SD, cpu, cia, read_map, AccessLength_WORD+1, vaddr, read_transfer, sim_core_unaligned_signal); + } + else + { + address_word paddr; + int uncached; + + if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, + isTARGET, isREAL)) + { + const uword64 mask = 0x7; + const unsigned int reverse = ReverseEndian ? 1 : 0; + const unsigned int bigend = BigEndianCPU ? 1 : 0; + uword64 memval; + unsigned int byte; + + paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2)); + LoadMemory (&memval,NULL,uncached, AccessLength_WORD, paddr, vaddr, + isDATA, isREAL); + byte = (vaddr & mask) ^ (bigend << 2); + return SIGNEXTEND (((memval >> (8 * byte)) & 0xffffffff), 32); + } + } + + return 0; +} + +/* Simulate the mips16 entry and exit pseudo-instructions. These + would normally be handled by the reserved instruction exception + code, but for ease of simulation we just handle them directly. */ + +static void +mips16_entry (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + unsigned int insn) +{ + int aregs, sregs, rreg; + +#ifdef DEBUG + printf("DBG: mips16_entry: entered (insn = 0x%08X)\n",insn); +#endif /* DEBUG */ + + aregs = (insn & 0x700) >> 8; + sregs = (insn & 0x0c0) >> 6; + rreg = (insn & 0x020) >> 5; + + /* This should be checked by the caller. */ + if (sregs == 3) + abort (); + + if (aregs < 5) + { + int i; + signed_word tsp; + + /* This is the entry pseudo-instruction. */ + + for (i = 0; i < aregs; i++) + store_word (SD, CPU, cia, (uword64) (SP + 4 * i), GPR[i + 4]); + + tsp = SP; + SP -= 32; + + if (rreg) + { + tsp -= 4; + store_word (SD, CPU, cia, (uword64) tsp, RA); + } + + for (i = 0; i < sregs; i++) + { + tsp -= 4; + store_word (SD, CPU, cia, (uword64) tsp, GPR[16 + i]); + } + } + else + { + int i; + signed_word tsp; + + /* This is the exit pseudo-instruction. */ + + tsp = SP + 32; + + if (rreg) + { + tsp -= 4; + RA = load_word (SD, CPU, cia, (uword64) tsp); + } + + for (i = 0; i < sregs; i++) + { + tsp -= 4; + GPR[i + 16] = load_word (SD, CPU, cia, (uword64) tsp); + } + + SP += 32; + + if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) + { + if (aregs == 5) + { + FGR[0] = WORD64LO (GPR[4]); + FPR_STATE[0] = fmt_uninterpreted; + } + else if (aregs == 6) + { + FGR[0] = WORD64LO (GPR[5]); + FGR[1] = WORD64LO (GPR[4]); + FPR_STATE[0] = fmt_uninterpreted; + FPR_STATE[1] = fmt_uninterpreted; + } + } + + PC = RA; + } + +} + +/*-- trace support ----------------------------------------------------------*/ + +/* The TRACE support is provided (if required) in the memory accessing + routines. Since we are also providing the architecture specific + features, the architecture simulation code can also deal with + notifying the TRACE world of cache flushes, etc. Similarly we do + not need to provide profiling support in the simulator engine, + since we can sample in the instruction fetch control loop. By + defining the TRACE manifest, we add tracing as a run-time + option. */ + +#if defined(TRACE) +/* Tracing by default produces "din" format (as required by + dineroIII). Each line of such a trace file *MUST* have a din label + and address field. The rest of the line is ignored, so comments can + be included if desired. The first field is the label which must be + one of the following values: + + 0 read data + 1 write data + 2 instruction fetch + 3 escape record (treated as unknown access type) + 4 escape record (causes cache flush) + + The address field is a 32bit (lower-case) hexadecimal address + value. The address should *NOT* be preceded by "0x". + + The size of the memory transfer is not important when dealing with + cache lines (as long as no more than a cache line can be + transferred in a single operation :-), however more information + could be given following the dineroIII requirement to allow more + complete memory and cache simulators to provide better + results. i.e. the University of Pisa has a cache simulator that can + also take bus size and speed as (variable) inputs to calculate + complete system performance (a much more useful ability when trying + to construct an end product, rather than a processor). They + currently have an ARM version of their tool called ChARM. */ + + +void +dotrace (SIM_DESC sd, + sim_cpu *cpu, + FILE *tracefh, + int type, + SIM_ADDR address, + int width, + char *comment,...) +{ + if (STATE & simTRACE) { + va_list ap; + fprintf(tracefh,"%d %s ; width %d ; ", + type, + pr_addr(address), + width); + va_start(ap,comment); + vfprintf(tracefh,comment,ap); + va_end(ap); + fprintf(tracefh,"\n"); + } + /* NOTE: Since the "din" format will only accept 32bit addresses, and + we may be generating 64bit ones, we should put the hi-32bits of the + address into the comment field. */ + + /* TODO: Provide a buffer for the trace lines. We can then avoid + performing writes until the buffer is filled, or the file is + being closed. */ + + /* NOTE: We could consider adding a comment field to the "din" file + produced using type 3 markers (unknown access). This would then + allow information about the program that the "din" is for, and + the MIPs world that was being simulated, to be placed into the + trace file. */ + + return; +} +#endif /* TRACE */ + +/*---------------------------------------------------------------------------*/ +/*-- simulator engine -------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +static void +ColdReset (SIM_DESC sd) +{ + int cpu_nr; + for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++) + { + sim_cpu *cpu = STATE_CPU (sd, cpu_nr); + /* RESET: Fixed PC address: */ + PC = (unsigned_word) UNSIGNED64 (0xFFFFFFFFBFC00000); + /* The reset vector address is in the unmapped, uncached memory space. */ + + SR &= ~(status_SR | status_TS | status_RP); + SR |= (status_ERL | status_BEV); + + /* Cheat and allow access to the complete register set immediately */ + if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT + && WITH_TARGET_WORD_BITSIZE == 64) + SR |= status_FR; /* 64bit registers */ + + /* Ensure that any instructions with pending register updates are + cleared: */ + PENDING_INVALIDATE(); + + /* Initialise the FPU registers to the unknown state */ + if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) + { + int rn; + for (rn = 0; (rn < 32); rn++) + FPR_STATE[rn] = fmt_uninterpreted; + } + + } +} + + + + +/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */ +/* Signal an exception condition. This will result in an exception + that aborts the instruction. The instruction operation pseudocode + will never see a return from this function call. */ + +void +signal_exception (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + int exception,...) +{ + /* int vector; */ + +#ifdef DEBUG + sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",exception,pr_addr(cia)); +#endif /* DEBUG */ + + /* Ensure that any active atomic read/modify/write operation will fail: */ + LLBIT = 0; + + /* Save registers before interrupt dispatching */ +#ifdef SIM_CPU_EXCEPTION_TRIGGER + SIM_CPU_EXCEPTION_TRIGGER(sd, cpu, cia); +#endif + + switch (exception) { + + case DebugBreakPoint : + if (! (Debug & Debug_DM)) + { + if (INDELAYSLOT()) + { + CANCELDELAYSLOT(); + + Debug |= Debug_DBD; /* signaled from within in delay slot */ + DEPC = cia - 4; /* reference the branch instruction */ + } + else + { + Debug &= ~Debug_DBD; /* not signaled from within a delay slot */ + DEPC = cia; + } + + Debug |= Debug_DM; /* in debugging mode */ + Debug |= Debug_DBp; /* raising a DBp exception */ + PC = 0xBFC00200; + sim_engine_restart (SD, CPU, NULL, NULL_CIA); + } + break; + + case ReservedInstruction : + { + va_list ap; + unsigned int instruction; + va_start(ap,exception); + instruction = va_arg(ap,unsigned int); + va_end(ap); + /* Provide simple monitor support using ReservedInstruction + exceptions. The following code simulates the fixed vector + entry points into the IDT monitor by causing a simulator + trap, performing the monitor operation, and returning to + the address held in the $ra register (standard PCS return + address). This means we only need to pre-load the vector + space with suitable instruction values. For systems were + actual trap instructions are used, we would not need to + perform this magic. */ + if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION) + { + sim_monitor (SD, CPU, cia, ((instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK) ); + /* NOTE: This assumes that a branch-and-link style + instruction was used to enter the vector (which is the + case with the current IDT monitor). */ + sim_engine_restart (SD, CPU, NULL, RA); + } + /* Look for the mips16 entry and exit instructions, and + simulate a handler for them. */ + else if ((cia & 1) != 0 + && (instruction & 0xf81f) == 0xe809 + && (instruction & 0x0c0) != 0x0c0) + { + mips16_entry (SD, CPU, cia, instruction); + sim_engine_restart (sd, NULL, NULL, NULL_CIA); + } + /* else fall through to normal exception processing */ + sim_io_eprintf(sd,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia)); + } + + default: + /* Store exception code into current exception id variable (used + by exit code): */ + + /* TODO: If not simulating exceptions then stop the simulator + execution. At the moment we always stop the simulation. */ + +#ifdef SUBTARGET_R3900 + /* update interrupt-related registers */ + + /* insert exception code in bits 6:2 */ + CAUSE = LSMASKED32(CAUSE, 31, 7) | LSINSERTED32(exception, 6, 2); + /* shift IE/KU history bits left */ + SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 3, 0), 5, 2); + + if (STATE & simDELAYSLOT) + { + STATE &= ~simDELAYSLOT; + CAUSE |= cause_BD; + EPC = (cia - 4); /* reference the branch instruction */ + } + else + EPC = cia; + + if (SR & status_BEV) + PC = (signed)0xBFC00000 + 0x180; + else + PC = (signed)0x80000000 + 0x080; +#else + /* See figure 5-17 for an outline of the code below */ + if (! (SR & status_EXL)) + { + CAUSE = (exception << 2); + if (STATE & simDELAYSLOT) + { + STATE &= ~simDELAYSLOT; + CAUSE |= cause_BD; + EPC = (cia - 4); /* reference the branch instruction */ + } + else + EPC = cia; + /* FIXME: TLB et.al. */ + /* vector = 0x180; */ + } + else + { + CAUSE = (exception << 2); + /* vector = 0x180; */ + } + SR |= status_EXL; + /* Store exception code into current exception id variable (used + by exit code): */ + + if (SR & status_BEV) + PC = (signed)0xBFC00200 + 0x180; + else + PC = (signed)0x80000000 + 0x180; +#endif + + switch ((CAUSE >> 2) & 0x1F) + { + case Interrupt: + /* Interrupts arrive during event processing, no need to + restart */ + return; + + case NMIReset: + /* Ditto */ +#ifdef SUBTARGET_3900 + /* Exception vector: BEV=0 BFC00000 / BEF=1 BFC00000 */ + PC = (signed)0xBFC00000; +#endif SUBTARGET_3900 + return; + + case TLBModification: + case TLBLoad: + case TLBStore: + case AddressLoad: + case AddressStore: + case InstructionFetch: + case DataReference: + /* The following is so that the simulator will continue from the + exception handler address. */ + sim_engine_halt (SD, CPU, NULL, PC, + sim_stopped, SIM_SIGBUS); + + case ReservedInstruction: + case CoProcessorUnusable: + PC = EPC; + sim_engine_halt (SD, CPU, NULL, PC, + sim_stopped, SIM_SIGILL); + + case IntegerOverflow: + case FPE: + sim_engine_halt (SD, CPU, NULL, PC, + sim_stopped, SIM_SIGFPE); + + case BreakPoint: + sim_engine_halt (SD, CPU, NULL, PC, sim_stopped, SIM_SIGTRAP); + break; + + case SystemCall: + case Trap: + sim_engine_restart (SD, CPU, NULL, PC); + break; + + case Watch: + PC = EPC; + sim_engine_halt (SD, CPU, NULL, PC, + sim_stopped, SIM_SIGTRAP); + + default : /* Unknown internal exception */ + PC = EPC; + sim_engine_halt (SD, CPU, NULL, PC, + sim_stopped, SIM_SIGABRT); + + } + + case SimulatorFault: + { + va_list ap; + char *msg; + va_start(ap,exception); + msg = va_arg(ap,char *); + va_end(ap); + sim_engine_abort (SD, CPU, NULL_CIA, + "FATAL: Simulator error \"%s\"\n",msg); + } + } + + return; +} + + + +#if defined(WARN_RESULT) +/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */ +/* This function indicates that the result of the operation is + undefined. However, this should not affect the instruction + stream. All that is meant to happen is that the destination + register is set to an undefined result. To keep the simulator + simple, we just don't bother updating the destination register, so + the overall result will be undefined. If desired we can stop the + simulator by raising a pseudo-exception. */ +#define UndefinedResult() undefined_result (sd,cia) +static void +undefined_result(sd,cia) + SIM_DESC sd; + address_word cia; +{ + sim_io_eprintf(sd,"UndefinedResult: PC = 0x%s\n",pr_addr(cia)); +#if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */ + state |= simSTOP; +#endif + return; +} +#endif /* WARN_RESULT */ + +/*-- FPU support routines ---------------------------------------------------*/ + +/* Numbers are held in normalized form. The SINGLE and DOUBLE binary + formats conform to ANSI/IEEE Std 754-1985. */ +/* SINGLE precision floating: + * seeeeeeeefffffffffffffffffffffff + * s = 1bit = sign + * e = 8bits = exponent + * f = 23bits = fraction + */ +/* SINGLE precision fixed: + * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii + * s = 1bit = sign + * i = 31bits = integer + */ +/* DOUBLE precision floating: + * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff + * s = 1bit = sign + * e = 11bits = exponent + * f = 52bits = fraction + */ +/* DOUBLE precision fixed: + * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii + * s = 1bit = sign + * i = 63bits = integer + */ + +/* Extract sign-bit: */ +#define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0) +#define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0) +/* Extract biased exponent: */ +#define FP_S_be(v) (((v) >> 23) & 0xFF) +#define FP_D_be(v) (((v) >> 52) & 0x7FF) +/* Extract unbiased Exponent: */ +#define FP_S_e(v) (FP_S_be(v) - 0x7F) +#define FP_D_e(v) (FP_D_be(v) - 0x3FF) +/* Extract complete fraction field: */ +#define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23)) +#define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52)) +/* Extract numbered fraction bit: */ +#define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0) +#define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0) + +/* Explicit QNaN values used when value required: */ +#define FPQNaN_SINGLE (0x7FBFFFFF) +#define FPQNaN_WORD (0x7FFFFFFF) +#define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF) +#define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF) + +/* Explicit Infinity values used when required: */ +#define FPINF_SINGLE (0x7F800000) +#define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000) + +#define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor"))) +#define DOFMT(v) (((v) == fmt_single) ? "single" : (((v) == fmt_double) ? "double" : (((v) == fmt_word) ? "word" : (((v) == fmt_long) ? "long" : (((v) == fmt_unknown) ? "<unknown>" : (((v) == fmt_uninterpreted) ? "<uninterpreted>" : (((v) == fmt_uninterpreted_32) ? "<uninterpreted_32>" : (((v) == fmt_uninterpreted_64) ? "<uninterpreted_64>" : "<format error>")))))))) + +uword64 +value_fpr (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + int fpr, + FP_formats fmt) +{ + uword64 value = 0; + int err = 0; + + /* Treat unused register values, as fixed-point 64bit values: */ + if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown)) +#if 1 + /* If request to read data as "uninterpreted", then use the current + encoding: */ + fmt = FPR_STATE[fpr]; +#else + fmt = fmt_long; +#endif + + /* For values not yet accessed, set to the desired format: */ + if (FPR_STATE[fpr] == fmt_uninterpreted) { + FPR_STATE[fpr] = fmt; +#ifdef DEBUG + printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt)); +#endif /* DEBUG */ + } + if (fmt != FPR_STATE[fpr]) { + sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(FPR_STATE[fpr]),DOFMT(fmt),pr_addr(cia)); + FPR_STATE[fpr] = fmt_unknown; + } + + if (FPR_STATE[fpr] == fmt_unknown) { + /* Set QNaN value: */ + switch (fmt) { + case fmt_single: + value = FPQNaN_SINGLE; + break; + + case fmt_double: + value = FPQNaN_DOUBLE; + break; + + case fmt_word: + value = FPQNaN_WORD; + break; + + case fmt_long: + value = FPQNaN_LONG; + break; + + default: + err = -1; + break; + } + } else if (SizeFGR() == 64) { + switch (fmt) { + case fmt_single: + case fmt_word: + value = (FGR[fpr] & 0xFFFFFFFF); + break; + + case fmt_uninterpreted: + case fmt_double: + case fmt_long: + value = FGR[fpr]; + break; + + default : + err = -1; + break; + } + } else { + switch (fmt) { + case fmt_single: + case fmt_word: + value = (FGR[fpr] & 0xFFFFFFFF); + break; + + case fmt_uninterpreted: + case fmt_double: + case fmt_long: + if ((fpr & 1) == 0) { /* even registers only */ +#ifdef DEBUG + printf("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n", + fpr+1, pr_uword64( (uword64) FGR[fpr+1] ), + fpr, pr_uword64( (uword64) FGR[fpr] )); +#endif + value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF)); + } else { + SignalException(ReservedInstruction,0); + } + break; + + default : + err = -1; + break; + } + } + + if (err) + SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()"); + +#ifdef DEBUG + printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_uword64(value),pr_addr(cia),SizeFGR()); +#endif /* DEBUG */ + + return(value); +} + +void +store_fpr (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + int fpr, + FP_formats fmt, + uword64 value) +{ + int err = 0; + +#ifdef DEBUG + printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d,\n",fpr,DOFMT(fmt),pr_uword64(value),pr_addr(cia),SizeFGR()); +#endif /* DEBUG */ + + if (SizeFGR() == 64) { + switch (fmt) { + case fmt_uninterpreted_32: + fmt = fmt_uninterpreted; + case fmt_single : + case fmt_word : + FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF)); + FPR_STATE[fpr] = fmt; + break; + + case fmt_uninterpreted_64: + fmt = fmt_uninterpreted; + case fmt_uninterpreted: + case fmt_double : + case fmt_long : + FGR[fpr] = value; + FPR_STATE[fpr] = fmt; + break; + + default : + FPR_STATE[fpr] = fmt_unknown; + err = -1; + break; + } + } else { + switch (fmt) { + case fmt_uninterpreted_32: + fmt = fmt_uninterpreted; + case fmt_single : + case fmt_word : + FGR[fpr] = (value & 0xFFFFFFFF); + FPR_STATE[fpr] = fmt; + break; + + case fmt_uninterpreted_64: + fmt = fmt_uninterpreted; + case fmt_uninterpreted: + case fmt_double : + case fmt_long : + if ((fpr & 1) == 0) { /* even register number only */ + FGR[fpr+1] = (value >> 32); + FGR[fpr] = (value & 0xFFFFFFFF); + FPR_STATE[fpr + 1] = fmt; + FPR_STATE[fpr] = fmt; + } else { + FPR_STATE[fpr] = fmt_unknown; + FPR_STATE[fpr + 1] = fmt_unknown; + SignalException(ReservedInstruction,0); + } + break; + + default : + FPR_STATE[fpr] = fmt_unknown; + err = -1; + break; + } + } +#if defined(WARN_RESULT) + else + UndefinedResult(); +#endif /* WARN_RESULT */ + + if (err) + SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()"); + +#ifdef DEBUG + printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr,pr_uword64(FGR[fpr]),DOFMT(fmt)); +#endif /* DEBUG */ + + return; +} + +int +NaN(op,fmt) + uword64 op; + FP_formats fmt; +{ + int boolean = 0; + switch (fmt) { + case fmt_single: + case fmt_word: + { + sim_fpu wop; + sim_fpu_32to (&wop, op); + boolean = sim_fpu_is_nan (&wop); + break; + } + case fmt_double: + case fmt_long: + { + sim_fpu wop; + sim_fpu_64to (&wop, op); + boolean = sim_fpu_is_nan (&wop); + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG +printf("DBG: NaN: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt)); +#endif /* DEBUG */ + + return(boolean); +} + +int +Infinity(op,fmt) + uword64 op; + FP_formats fmt; +{ + int boolean = 0; + +#ifdef DEBUG + printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt),pr_addr(op)); +#endif /* DEBUG */ + + switch (fmt) { + case fmt_single: + { + sim_fpu wop; + sim_fpu_32to (&wop, op); + boolean = sim_fpu_is_infinity (&wop); + break; + } + case fmt_double: + { + sim_fpu wop; + sim_fpu_64to (&wop, op); + boolean = sim_fpu_is_infinity (&wop); + break; + } + default: + printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt)); + break; + } + +#ifdef DEBUG + printf("DBG: Infinity: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt)); +#endif /* DEBUG */ + + return(boolean); +} + +int +Less(op1,op2,fmt) + uword64 op1; + uword64 op2; + FP_formats fmt; +{ + int boolean = 0; + + /* Argument checking already performed by the FPCOMPARE code */ + +#ifdef DEBUG + printf("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + boolean = sim_fpu_is_lt (&wop1, &wop2); + break; + } + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + boolean = sim_fpu_is_lt (&wop1, &wop2); + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Less: returning %d (format = %s)\n",boolean,DOFMT(fmt)); +#endif /* DEBUG */ + + return(boolean); +} + +int +Equal(op1,op2,fmt) + uword64 op1; + uword64 op2; + FP_formats fmt; +{ + int boolean = 0; + + /* Argument checking already performed by the FPCOMPARE code */ + +#ifdef DEBUG + printf("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + boolean = sim_fpu_is_eq (&wop1, &wop2); + break; + } + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + boolean = sim_fpu_is_eq (&wop1, &wop2); + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Equal: returning %d (format = %s)\n",boolean,DOFMT(fmt)); +#endif /* DEBUG */ + + return(boolean); +} + +uword64 +AbsoluteValue(op,fmt) + uword64 op; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); +#endif /* DEBUG */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop; + unsigned32 ans; + sim_fpu_32to (&wop, op); + sim_fpu_abs (&wop, &wop); + sim_fpu_to32 (&ans, &wop); + result = ans; + break; + } + case fmt_double: + { + sim_fpu wop; + unsigned64 ans; + sim_fpu_64to (&wop, op); + sim_fpu_abs (&wop, &wop); + sim_fpu_to64 (&ans, &wop); + result = ans; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + + return(result); +} + +uword64 +Negate(op,fmt) + uword64 op; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); +#endif /* DEBUG */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop; + unsigned32 ans; + sim_fpu_32to (&wop, op); + sim_fpu_neg (&wop, &wop); + sim_fpu_to32 (&ans, &wop); + result = ans; + break; + } + case fmt_double: + { + sim_fpu wop; + unsigned64 ans; + sim_fpu_64to (&wop, op); + sim_fpu_neg (&wop, &wop); + sim_fpu_to64 (&ans, &wop); + result = ans; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + + return(result); +} + +uword64 +Add(op1,op2,fmt) + uword64 op1; + uword64 op2; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned32 res; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + sim_fpu_add (&ans, &wop1, &wop2); + sim_fpu_to32 (&res, &ans); + result = res; + break; + } + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned64 res; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + sim_fpu_add (&ans, &wop1, &wop2); + sim_fpu_to64 (&res, &ans); + result = res; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Add: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} + +uword64 +Sub(op1,op2,fmt) + uword64 op1; + uword64 op2; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned32 res; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + sim_fpu_sub (&ans, &wop1, &wop2); + sim_fpu_to32 (&res, &ans); + result = res; + } + break; + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned64 res; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + sim_fpu_sub (&ans, &wop1, &wop2); + sim_fpu_to64 (&res, &ans); + result = res; + } + break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Sub: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} + +uword64 +Multiply(op1,op2,fmt) + uword64 op1; + uword64 op2; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned32 res; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + sim_fpu_mul (&ans, &wop1, &wop2); + sim_fpu_to32 (&res, &ans); + result = res; + break; + } + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned64 res; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + sim_fpu_mul (&ans, &wop1, &wop2); + sim_fpu_to64 (&res, &ans); + result = res; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Multiply: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} + +uword64 +Divide(op1,op2,fmt) + uword64 op1; + uword64 op2; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned32 res; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + sim_fpu_div (&ans, &wop1, &wop2); + sim_fpu_to32 (&res, &ans); + result = res; + break; + } + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned64 res; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + sim_fpu_div (&ans, &wop1, &wop2); + sim_fpu_to64 (&res, &ans); + result = res; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Divide: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} + +uword64 UNUSED +Recip(op,fmt) + uword64 op; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop; + sim_fpu ans; + unsigned32 res; + sim_fpu_32to (&wop, op); + sim_fpu_inv (&ans, &wop); + sim_fpu_to32 (&res, &ans); + result = res; + break; + } + case fmt_double: + { + sim_fpu wop; + sim_fpu ans; + unsigned64 res; + sim_fpu_64to (&wop, op); + sim_fpu_inv (&ans, &wop); + sim_fpu_to64 (&res, &ans); + result = res; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Recip: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} + +uword64 +SquareRoot(op,fmt) + uword64 op; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop; + sim_fpu ans; + unsigned32 res; + sim_fpu_32to (&wop, op); + sim_fpu_sqrt (&ans, &wop); + sim_fpu_to32 (&res, &ans); + result = res; + break; + } + case fmt_double: + { + sim_fpu wop; + sim_fpu ans; + unsigned64 res; + sim_fpu_64to (&wop, op); + sim_fpu_sqrt (&ans, &wop); + sim_fpu_to64 (&res, &ans); + result = res; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: SquareRoot: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} + +#if 0 +uword64 +Max (uword64 op1, + uword64 op2, + FP_formats fmt) +{ + int cmp; + unsigned64 result; + +#ifdef DEBUG + printf("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) + { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + cmp = sim_fpu_cmp (&wop1, &wop2); + break; + } + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + cmp = sim_fpu_cmp (&wop1, &wop2); + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + + switch (cmp) + { + case SIM_FPU_IS_SNAN: + case SIM_FPU_IS_QNAN: + result = op1; + case SIM_FPU_IS_NINF: + case SIM_FPU_IS_NNUMBER: + case SIM_FPU_IS_NDENORM: + case SIM_FPU_IS_NZERO: + result = op2; /* op1 - op2 < 0 */ + case SIM_FPU_IS_PINF: + case SIM_FPU_IS_PNUMBER: + case SIM_FPU_IS_PDENORM: + case SIM_FPU_IS_PZERO: + result = op1; /* op1 - op2 > 0 */ + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Max: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} +#endif + +#if 0 +uword64 +Min (uword64 op1, + uword64 op2, + FP_formats fmt) +{ + int cmp; + unsigned64 result; + +#ifdef DEBUG + printf("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) + { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + cmp = sim_fpu_cmp (&wop1, &wop2); + break; + } + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + cmp = sim_fpu_cmp (&wop1, &wop2); + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + + switch (cmp) + { + case SIM_FPU_IS_SNAN: + case SIM_FPU_IS_QNAN: + result = op1; + case SIM_FPU_IS_NINF: + case SIM_FPU_IS_NNUMBER: + case SIM_FPU_IS_NDENORM: + case SIM_FPU_IS_NZERO: + result = op1; /* op1 - op2 < 0 */ + case SIM_FPU_IS_PINF: + case SIM_FPU_IS_PNUMBER: + case SIM_FPU_IS_PDENORM: + case SIM_FPU_IS_PZERO: + result = op2; /* op1 - op2 > 0 */ + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Min: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} +#endif + +uword64 +convert (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + int rm, + uword64 op, + FP_formats from, + FP_formats to) +{ + sim_fpu wop; + sim_fpu_round round; + unsigned32 result32; + unsigned64 result64; + +#ifdef DEBUG +#if 0 /* FIXME: doesn't compile */ + printf("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",RMMODE(rm),pr_addr(op),DOFMT(from),DOFMT(to),pr_addr(IPC)); +#endif +#endif /* DEBUG */ + + switch (rm) + { + case FP_RM_NEAREST: + /* Round result to nearest representable value. When two + representable values are equally near, round to the value + that has a least significant bit of zero (i.e. is even). */ + round = sim_fpu_round_near; + break; + case FP_RM_TOZERO: + /* Round result to the value closest to, and not greater in + magnitude than, the result. */ + round = sim_fpu_round_zero; + break; + case FP_RM_TOPINF: + /* Round result to the value closest to, and not less than, + the result. */ + round = sim_fpu_round_up; + break; + + case FP_RM_TOMINF: + /* Round result to the value closest to, and not greater than, + the result. */ + round = sim_fpu_round_down; + break; + default: + round = 0; + fprintf (stderr, "Bad switch\n"); + abort (); + } + + /* Convert the input to sim_fpu internal format */ + switch (from) + { + case fmt_double: + sim_fpu_64to (&wop, op); + break; + case fmt_single: + sim_fpu_32to (&wop, op); + break; + case fmt_word: + sim_fpu_i32to (&wop, op, round); + break; + case fmt_long: + sim_fpu_i64to (&wop, op, round); + break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + + /* Convert sim_fpu format into the output */ + /* The value WOP is converted to the destination format, rounding + using mode RM. When the destination is a fixed-point format, then + a source value of Infinity, NaN or one which would round to an + integer outside the fixed point range then an IEEE Invalid + Operation condition is raised. */ + switch (to) + { + case fmt_single: + sim_fpu_round_32 (&wop, round, 0); + sim_fpu_to32 (&result32, &wop); + result64 = result32; + break; + case fmt_double: + sim_fpu_round_64 (&wop, round, 0); + sim_fpu_to64 (&result64, &wop); + break; + case fmt_word: + sim_fpu_to32i (&result32, &wop, round); + result64 = result32; + break; + case fmt_long: + sim_fpu_to64i (&result64, &wop, round); + break; + default: + result64 = 0; + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64),DOFMT(to)); +#endif /* DEBUG */ + + return(result64); +} + + +/*-- co-processor support routines ------------------------------------------*/ + +static int UNUSED +CoProcPresent(unsigned int coproc_number) +{ + /* Return TRUE if simulator provides a model for the given co-processor number */ + return(0); +} + +void +cop_lw (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + int coproc_num, + int coproc_reg, + unsigned int memword) +{ + switch (coproc_num) + { + case 1: + if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) + { +#ifdef DEBUG + printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword)); +#endif + StoreFPR(coproc_reg,fmt_word,(uword64)memword); + FPR_STATE[coproc_reg] = fmt_uninterpreted; + break; + } + + default: +#if 0 /* this should be controlled by a configuration option */ + sim_io_printf(sd,"COP_LW(%d,%d,0x%08X) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,memword,pr_addr(cia)); +#endif + break; + } + + return; +} + +void +cop_ld (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + int coproc_num, + int coproc_reg, + uword64 memword) +{ + +#ifdef DEBUG + printf("DBG: COP_LD: coproc_num = %d, coproc_reg = %d, value = 0x%s : PC = 0x%s\n", coproc_num, coproc_reg, pr_uword64(memword), pr_addr(cia) ); +#endif + + switch (coproc_num) { + case 1: + if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) + { + StoreFPR(coproc_reg,fmt_uninterpreted,memword); + break; + } + + default: +#if 0 /* this message should be controlled by a configuration option */ + sim_io_printf(sd,"COP_LD(%d,%d,0x%s) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(memword),pr_addr(cia)); +#endif + break; + } + + return; +} + + + + +unsigned int +cop_sw (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + int coproc_num, + int coproc_reg) +{ + unsigned int value = 0; + + switch (coproc_num) + { + case 1: + if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) + { + FP_formats hold; + hold = FPR_STATE[coproc_reg]; + FPR_STATE[coproc_reg] = fmt_word; + value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted); + FPR_STATE[coproc_reg] = hold; + break; + } + + default: +#if 0 /* should be controlled by configuration option */ + sim_io_printf(sd,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia)); +#endif + break; + } + + return(value); +} + +uword64 +cop_sd (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + int coproc_num, + int coproc_reg) +{ + uword64 value = 0; + switch (coproc_num) + { + case 1: + if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) + { + value = ValueFPR(coproc_reg,fmt_uninterpreted); + break; + } + + default: +#if 0 /* should be controlled by configuration option */ + sim_io_printf(sd,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia)); +#endif + break; + } + + return(value); +} + + + + +void +decode_coproc (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + unsigned int instruction) +{ + int coprocnum = ((instruction >> 26) & 3); + + switch (coprocnum) + { + case 0: /* standard CPU control and cache registers */ + { + int code = ((instruction >> 21) & 0x1F); + int rt = ((instruction >> 16) & 0x1F); + int rd = ((instruction >> 11) & 0x1F); + int tail = instruction & 0x3ff; + /* R4000 Users Manual (second edition) lists the following CP0 + instructions: + CODE><-RT><RD-><--TAIL---> + DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000) + DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000) + MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000) + MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000) + TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001) + TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010) + TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110) + TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000) + CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii) + ERET Exception return (VR4100 = 01000010000000000000000000011000) + */ + if (((code == 0x00) || (code == 0x04)) && tail == 0) + { + /* M[TF]C0 - 32 bit word */ + + switch (rd) /* NOTEs: Standard CP0 registers */ + { + /* 0 = Index R4000 VR4100 VR4300 */ + /* 1 = Random R4000 VR4100 VR4300 */ + /* 2 = EntryLo0 R4000 VR4100 VR4300 */ + /* 3 = EntryLo1 R4000 VR4100 VR4300 */ + /* 4 = Context R4000 VR4100 VR4300 */ + /* 5 = PageMask R4000 VR4100 VR4300 */ + /* 6 = Wired R4000 VR4100 VR4300 */ + /* 8 = BadVAddr R4000 VR4100 VR4300 */ + /* 9 = Count R4000 VR4100 VR4300 */ + /* 10 = EntryHi R4000 VR4100 VR4300 */ + /* 11 = Compare R4000 VR4100 VR4300 */ + /* 12 = SR R4000 VR4100 VR4300 */ +#ifdef SUBTARGET_R3900 + case 3: + /* 3 = Config R3900 */ + case 7: + /* 7 = Cache R3900 */ + case 15: + /* 15 = PRID R3900 */ + + /* ignore */ + break; + + case 8: + /* 8 = BadVAddr R4000 VR4100 VR4300 */ + if (code == 0x00) + GPR[rt] = COP0_BADVADDR; + else + COP0_BADVADDR = GPR[rt]; + break; + +#endif /* SUBTARGET_R3900 */ + case 12: + if (code == 0x00) + GPR[rt] = SR; + else + SR = GPR[rt]; + break; + /* 13 = Cause R4000 VR4100 VR4300 */ + case 13: + if (code == 0x00) + GPR[rt] = CAUSE; + else + CAUSE = GPR[rt]; + break; + /* 14 = EPC R4000 VR4100 VR4300 */ + case 14: + if (code == 0x00) + GPR[rt] = (signed_word) (signed_address) EPC; + else + EPC = GPR[rt]; + break; + /* 15 = PRId R4000 VR4100 VR4300 */ +#ifdef SUBTARGET_R3900 + /* 16 = Debug */ + case 16: + if (code == 0x00) + GPR[rt] = Debug; + else + Debug = GPR[rt]; + break; +#else + /* 16 = Config R4000 VR4100 VR4300 */ + case 16: + if (code == 0x00) + GPR[rt] = C0_CONFIG; + else + C0_CONFIG = GPR[rt]; + break; +#endif +#ifdef SUBTARGET_R3900 + /* 17 = Debug */ + case 17: + if (code == 0x00) + GPR[rt] = DEPC; + else + DEPC = GPR[rt]; + break; +#else + /* 17 = LLAddr R4000 VR4100 VR4300 */ +#endif + /* 18 = WatchLo R4000 VR4100 VR4300 */ + /* 19 = WatchHi R4000 VR4100 VR4300 */ + /* 20 = XContext R4000 VR4100 VR4300 */ + /* 26 = PErr or ECC R4000 VR4100 VR4300 */ + /* 27 = CacheErr R4000 VR4100 */ + /* 28 = TagLo R4000 VR4100 VR4300 */ + /* 29 = TagHi R4000 VR4100 VR4300 */ + /* 30 = ErrorEPC R4000 VR4100 VR4300 */ + GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */ + /* CPR[0,rd] = GPR[rt]; */ + default: + if (code == 0x00) + GPR[rt] = (signed_word) (signed32) COP0_GPR[rd]; + else + COP0_GPR[rd] = GPR[rt]; +#if 0 + if (code == 0x00) + sim_io_printf(sd,"Warning: MFC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt,rd, (unsigned)cia); + else + sim_io_printf(sd,"Warning: MTC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt,rd, (unsigned)cia); +#endif + } + } + else if (code == 0x10 && (tail & 0x3f) == 0x18) + { + /* ERET */ + if (SR & status_ERL) + { + /* Oops, not yet available */ + sim_io_printf(sd,"Warning: ERET when SR[ERL] set not handled yet"); + PC = EPC; + SR &= ~status_ERL; + } + else + { + PC = EPC; + SR &= ~status_EXL; + } + } + else if (code == 0x10 && (tail & 0x3f) == 0x10) + { + /* RFE */ +#ifdef SUBTARGET_R3900 + /* TX39: Copy IEp/KUp -> IEc/KUc, and IEo/KUo -> IEp/KUp */ + + /* shift IE/KU history bits right */ + SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 5, 2), 3, 0); + + /* TODO: CACHE register */ +#endif /* SUBTARGET_R3900 */ + } + else if (code == 0x10 && (tail & 0x3f) == 0x1F) + { + /* DERET */ + Debug &= ~Debug_DM; + DELAYSLOT(); + DSPC = DEPC; + } + else + sim_io_eprintf(sd,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia)); + /* TODO: When executing an ERET or RFE instruction we should + clear LLBIT, to ensure that any out-standing atomic + read/modify/write sequence fails. */ + } + break; + + case 2: /* co-processor 2 */ + { + int handle = 0; + + + if(! handle) + { + sim_io_eprintf(sd, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n", + instruction,pr_addr(cia)); + } + } + break; + + case 1: /* should not occur (FPU co-processor) */ + case 3: /* should not occur (FPU co-processor) */ + SignalException(ReservedInstruction,instruction); + break; + } + + return; +} + + +/* This code copied from gdb's utils.c. Would like to share this code, + but don't know of a common place where both could get to it. */ + +/* Temporary storage using circular buffer */ +#define NUMCELLS 16 +#define CELLSIZE 32 +static char* +get_cell (void) +{ + static char buf[NUMCELLS][CELLSIZE]; + static int cell=0; + if (++cell>=NUMCELLS) cell=0; + return buf[cell]; +} + +/* Print routines to handle variable size regs, etc */ + +/* Eliminate warning from compiler on 32-bit systems */ +static int thirty_two = 32; + +char* +pr_addr(addr) + SIM_ADDR addr; +{ + char *paddr_str=get_cell(); + switch (sizeof(addr)) + { + case 8: + sprintf(paddr_str,"%08lx%08lx", + (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff)); + break; + case 4: + sprintf(paddr_str,"%08lx",(unsigned long)addr); + break; + case 2: + sprintf(paddr_str,"%04x",(unsigned short)(addr&0xffff)); + break; + default: + sprintf(paddr_str,"%x",addr); + } + return paddr_str; +} + +char* +pr_uword64(addr) + uword64 addr; +{ + char *paddr_str=get_cell(); + sprintf(paddr_str,"%08lx%08lx", + (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff)); + return paddr_str; +} + + +void +mips_core_signal (SIM_DESC sd, + sim_cpu *cpu, + sim_cia cia, + unsigned map, + int nr_bytes, + address_word addr, + transfer_type transfer, + sim_core_signals sig) +{ + const char *copy = (transfer == read_transfer ? "read" : "write"); + address_word ip = CIA_ADDR (cia); + + switch (sig) + { + case sim_core_unmapped_signal: + sim_io_eprintf (sd, "mips-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n", + nr_bytes, copy, + (unsigned long) addr, (unsigned long) ip); + COP0_BADVADDR = addr; + SignalExceptionDataReference(); + break; + + case sim_core_unaligned_signal: + sim_io_eprintf (sd, "mips-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n", + nr_bytes, copy, + (unsigned long) addr, (unsigned long) ip); + COP0_BADVADDR = addr; + if(transfer == read_transfer) + SignalExceptionAddressLoad(); + else + SignalExceptionAddressStore(); + break; + + default: + sim_engine_abort (sd, cpu, cia, + "mips_core_signal - internal error - bad switch"); + } +} + + +void +mips_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word cia) +{ + ASSERT(cpu != NULL); + + if(cpu->exc_suspended > 0) + sim_io_eprintf(sd, "Warning, nested exception triggered (%d)\n", cpu->exc_suspended); + + PC = cia; + memcpy(cpu->exc_trigger_registers, cpu->registers, sizeof(cpu->exc_trigger_registers)); + cpu->exc_suspended = 0; +} + +void +mips_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception) +{ + ASSERT(cpu != NULL); + + if(cpu->exc_suspended > 0) + sim_io_eprintf(sd, "Warning, nested exception signal (%d then %d)\n", + cpu->exc_suspended, exception); + + memcpy(cpu->exc_suspend_registers, cpu->registers, sizeof(cpu->exc_suspend_registers)); + memcpy(cpu->registers, cpu->exc_trigger_registers, sizeof(cpu->registers)); + cpu->exc_suspended = exception; +} + +void +mips_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception) +{ + ASSERT(cpu != NULL); + + if(exception == 0 && cpu->exc_suspended > 0) + { + /* warn not for breakpoints */ + if(cpu->exc_suspended != sim_signal_to_host(sd, SIM_SIGTRAP)) + sim_io_eprintf(sd, "Warning, resuming but ignoring pending exception signal (%d)\n", + cpu->exc_suspended); + } + else if(exception != 0 && cpu->exc_suspended > 0) + { + if(exception != cpu->exc_suspended) + sim_io_eprintf(sd, "Warning, resuming with mismatched exception signal (%d vs %d)\n", + cpu->exc_suspended, exception); + + memcpy(cpu->registers, cpu->exc_suspend_registers, sizeof(cpu->registers)); + } + else if(exception != 0 && cpu->exc_suspended == 0) + { + sim_io_eprintf(sd, "Warning, ignoring spontanous exception signal (%d)\n", exception); + } + cpu->exc_suspended = 0; +} + + +/*---------------------------------------------------------------------------*/ +/*> EOF interp.c <*/ diff --git a/sim/mips/m16.dc b/sim/mips/m16.dc new file mode 100644 index 0000000..292587c --- /dev/null +++ b/sim/mips/m16.dc @@ -0,0 +1,25 @@ +# most instructions +# ------ options ------ : Fst : Lst : ff : fl : fe : word : --- fmt --- : model ... +# { : mask : value : word } + +# Top level - create a very big switch statement. + + padded-switch,combine : 15 : 11 : : : : : : + + switch,combine : 10 : 8 : : : : : : + + switch,combine : 4 : 0 : : : : : : + + switch,combine : 7 : 5 : : : : : : + + +# Extended instructions, decode the same way + + padded-switch,combine : 15 : 11 : : : : 1 : : + + switch,combine : 10 : 8 : : : : 1 : : + + switch,combine : 4 : 0 : : : : 1 : : + + switch,combine : 7 : 5 : : : : 1 : : + diff --git a/sim/mips/m16.igen b/sim/mips/m16.igen new file mode 100644 index 0000000..9b36ff9 --- /dev/null +++ b/sim/mips/m16.igen @@ -0,0 +1,1236 @@ +// -*- C -*- +// +// +// MIPS Architecture: +// +// CPU Instruction Set (mips16) +// + +// The instructions in this section are ordered according +// to http://www.sgi.com/MIPS/arch/MIPS16/mips16.pdf. + + +// The MIPS16 codes registers in a special way, map from one to the other. +// :<type>:<flags>:<models>:<typedef>:<name>:<field>:<expression> +:compute:::int:TRX:RX:((RX < 2) ? (16 + RX) \: RX) +:compute:::int:TRY:RY:((RY < 2) ? (16 + RY) \: RY) +:compute:::int:TRZ:RZ:((RZ < 2) ? (16 + RZ) \: RZ) +:compute:::int:SHIFT:SHAMT:((SHAMT == 0) ? 8 \: SHAMT) + +:compute:::int:SHAMT:SHAMT_4_0,S5:(LSINSERTED (S5, 5, 5) | SHAMT_4_0) + +:compute:::address_word:IMMEDIATE:IMM_25_21,IMM_20_16,IMMED_15_0:(LSINSERTED (IMM_25_21, 25, 21) | LSINSERTED (IMM_20_16, 20, 16) | LSINSERTED (IMMED_15_0, 15, 0)) +:compute:::int:R32:R32L,R32H:((R32H << 3) | R32L) + +:compute:::address_word:IMMEDIATE:IMM_10_5,IMM_15_11,IMM_4_0:(LSINSERTED (IMM_10_5, 10, 5) | LSINSERTED (IMM_15_11, 15, 11) | LSINSERTED (IMM_4_0, 4, 0)) + +:compute:::address_word:IMMEDIATE:IMM_10_4,IMM_14_11,IMM_3_0:(LSINSERTED (IMM_10_4, 10, 4) | LSINSERTED (IMM_14_11, 14, 11) | LSINSERTED (IMM_3_0, 3, 0)) + + +// Load and Store Instructions + + +10000,3.RX,3.RY,5.IMMED:RRI:16::LB +"lb r<TRY>, <IMMED> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = EXTEND8 (do_load (SD_, AccessLength_BYTE, GPR[TRX], IMMED)); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 10000,3.RX,3.RY,5.IMM_4_0:EXT-RRI:16::LB +"lb r<TRY>, <IMMEDIATE> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = EXTEND8 (do_load (SD_, AccessLength_BYTE, GPR[TRX], EXTEND16 (IMMEDIATE))); +} + + + +10100,3.RX,3.RY,5.IMMED:RRI:16::LBU +"lbu r<TRY>, <IMMED> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = do_load (SD_, AccessLength_BYTE, GPR[TRX], IMMED); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 10100,3.RX,3.RY,5.IMM_4_0:EXT-RRI:16::LBU +"lbu r<TRY>, <IMMEDIATE> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = do_load (SD_, AccessLength_BYTE, GPR[TRX], EXTEND16 (IMMEDIATE)); +} + + + +10001,3.RX,3.RY,5.IMMED:RRI:16::LH +"lh r<TRY>, <IMMED> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[TRX], IMMED << 1)); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 10001,3.RX,3.RY,5.IMM_4_0:EXT-RRI:16::LH +"lh r<TRY>, <IMMEDIATE> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[TRX], EXTEND16 (IMMEDIATE))); +} + + + +10101,3.RX,3.RY,5.IMMED:RRI:16::LHU +"lhu r<TRY>, <IMMED> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = do_load (SD_, AccessLength_HALFWORD, GPR[TRX], IMMED << 1); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 10101,3.RX,3.RY,5.IMM_4_0:EXT-RRI:16::LHU +"lhu r<TRY>, <IMMEDIATE> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = do_load (SD_, AccessLength_HALFWORD, GPR[TRX], EXTEND16 (IMMEDIATE)); +} + + + +10011,3.RX,3.RY,5.IMMED:RRI:16::LW +"lw r<TRY>, <IMMED> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[TRX], IMMED << 2)); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 10011,3.RX,3.RY,5.IMM_4_0:EXT-RRI:16::LW +"lw r<TRY>, <IMMEDIATE> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[TRX], EXTEND16 (IMMEDIATE))); +} + + + +10110,3.RX,8.IMMED:RI:16::LWPC +"lw r<TRX>, <IMMED> (PC)" +*mips16: +*vr4100: +{ + GPR[TRX] = EXTEND32 (do_load (SD_, AccessLength_WORD, + basepc (SD_) & ~3, IMMED << 2)); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 10110,3.RX,000,5.IMM_4_0:EXT-RI:16::LWPC +"lw r<TRX>, <IMMEDIATE> (PC)" +*mips16: +*vr4100: +{ + GPR[TRX] = EXTEND32 (do_load (SD_, AccessLength_WORD, basepc (SD_) & ~3, EXTEND16 (IMMEDIATE))); +} + + + +10010,3.RX,8.IMMED:RI:16::LWSP +"lw r<TRX>, <IMMED> (SP)" +*mips16: +*vr4100: +{ + GPR[TRX] = EXTEND32 (do_load (SD_, AccessLength_WORD, SP, IMMED << 2)); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 10010,3.RX,000,5.IMM_4_0:EXT-RI:16::LWSP +"lw r<TRX>, <IMMEDIATE> (SP)" +*mips16: +*vr4100: +{ + GPR[TRX] = EXTEND32 (do_load (SD_, AccessLength_WORD, SP, EXTEND16 (IMMEDIATE))); +} + + + +10111,3.RX,3.RY,5.IMMED:RRI:16::LWU +"lwu r<TRY>, <IMMED> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = do_load (SD_, AccessLength_WORD, GPR[TRX], IMMED << 2); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 10111,3.RX,3.RY,5.IMM_4_0:EXT-RRI:16::LWU +"lwu r<TRY>, <IMMEDIATE> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = do_load (SD_, AccessLength_WORD, GPR[TRX], EXTEND16 (IMMEDIATE)); +} + + + +00111,3.RX,3.RY,5.IMMED:RRI:16::LD +"ld r<TRY>, <IMMED> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = do_load (SD_, AccessLength_DOUBLEWORD, GPR[TRX], IMMED << 3); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 00111,3.RX,3.RY,5.IMM_4_0:EXT-RRI:16::LD +"ld r<TRY>, <IMMEDIATE> (r<TRX>)" +*mips16: +*vr4100: +{ + GPR[TRY] = do_load (SD_, AccessLength_DOUBLEWORD, GPR[TRX], EXTEND16 (IMMEDIATE)); +} + + + +11111,100,3.RY,5.IMMED:RI64:16::LDPC +"ld r<TRY>, <IMMED> (PC)" +*mips16: +*vr4100: +{ + GPR[TRY] = do_load (SD_, AccessLength_DOUBLEWORD, + basepc (SD_) & ~7, IMMED << 3); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 11111,100,3.RY,5.IMM_4_0:EXT-RI64:16::LDPC +"ld r<TRY>, <IMMEDIATE> (PC)" +*mips16: +*vr4100: +{ + GPR[TRY] = do_load (SD_, AccessLength_DOUBLEWORD, basepc (SD_) & ~7, EXTEND16 (IMMEDIATE)); +} + + + +11111,000,3.RY,5.IMMED:RI64:16::LDSP +"ld r<TRY>, <IMMED> (SP)" +*mips16: +*vr4100: +{ + GPR[TRY] = do_load (SD_, AccessLength_DOUBLEWORD, SP, IMMED << 3); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 11111,000,3.RY,5.IMM_4_0:EXT-RI64:16::LDSP +"ld r<TRY>, <IMMEDIATE> (SP)" +*mips16: +*vr4100: +{ + GPR[TRY] = do_load (SD_, AccessLength_DOUBLEWORD, SP, EXTEND16 (IMMEDIATE)); +} + + + +11000,3.RX,3.RY,5.IMMED:RRI:16::SB +"sb r<TRY>, <IMMED> (r<TRX>)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_BYTE, GPR[TRX], IMMED, GPR[TRY]); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 11000,3.RX,3.RY,5.IMM_4_0:EXT-RRI:16::SB +"sb r<TRY>, <IMMEDIATE> (r<TRX>)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_BYTE, GPR[TRX], EXTEND16 (IMMEDIATE), GPR[TRY]); +} + + + +11001,3.RX,3.RY,5.IMMED:RRI:16::SH +"sh r<TRY>, <IMMED> (r<TRX>)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_HALFWORD, GPR[TRX], IMMED << 1, GPR[TRY]); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 11001,3.RX,3.RY,5.IMM_4_0:EXT-RRI:16::SH +"sh r<TRY>, <IMMEDIATE> (r<TRX>)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_HALFWORD, GPR[TRX], EXTEND16 (IMMEDIATE), GPR[TRY]); +} + + + +11011,3.RX,3.RY,5.IMMED:RRI:16::SW +"sw r<TRY>, <IMMED> (r<TRX>)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_WORD, GPR[TRX], IMMED << 2, GPR[TRY]); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 11011,3.RX,3.RY,5.IMM_4_0:EXT-RRI:16::SW +"sw r<TRY>, <IMMEDIATE> (r<TRX>)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_WORD, GPR[TRX], EXTEND16 (IMMEDIATE), GPR[TRY]); +} + + + +11010,3.RX,8.IMMED:RI:16::SWSP +"sw r<TRX>, <IMMED> (SP)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_WORD, SP, IMMED << 2, GPR[TRX]); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 11010,3.RX,000,5.IMM_4_0:EXT-RI:16::SWSP +"sw r<TRX>, <IMMEDIATE> (SP)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_WORD, SP, EXTEND16 (IMMEDIATE), GPR[TRX]); +} + + + +01100,010,8.IMMED:I8:16::SWRASP +"sw r<RAIDX>, <IMMED> (SP)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_WORD, SP, IMMED << 2, RA); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 01100,010,000,5.IMM_4_0:EXT-I8:16::SWRASP +"sw r<RAIDX>, <IMMEDIATE> (SP)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_WORD, SP, EXTEND16 (IMMEDIATE), RA); +} + + + +01111,3.RX,3.RY,5.IMMED:RRI:16::SD +"sd r<TRY>, <IMMED> (r<TRX>)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_DOUBLEWORD, GPR[TRX], IMMED << 3, GPR[TRY]); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 01111,3.RX,3.RY,5.IMM_4_0:EXT-RRI:16::SD +"sd r<TRY>, <IMMEDIATE> (r<TRX>)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_DOUBLEWORD, GPR[TRX], EXTEND16 (IMMEDIATE), GPR[TRY]); +} + + + +11111,001,3.RY,5.IMMED:RI64:16::SDSP +"sd r<TRY>, <IMMED> (SP)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_DOUBLEWORD, SP, IMMED << 3, GPR[TRY]); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 11111,001,3.RY,5.IMM_4_0:EXT-RI64:16::SDSP +"sd r<TRY>, <IMMEDIATE> (SP)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_DOUBLEWORD, SP, EXTEND16 (IMMEDIATE), GPR[TRY]); +} + + + +11111,010,8.IMMED:I64:16::SDRASP +"sd r<RAIDX>, <IMMED> (SP)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_DOUBLEWORD, SP, IMMED << 3, RA); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 11111,010,000,5.IMM_4_0:EXT-I64:16::SDRASP +"sd r<RAIDX>, <IMMEDIATE> (SP)" +*mips16: +*vr4100: +{ + do_store (SD_, AccessLength_DOUBLEWORD, SP, EXTEND16 (IMMEDIATE), RA); +} + + + +// ALU Immediate Instructions + + +01101,3.RX,8.IMMED:RI:16::LI +"li r<TRX>, <IMMED>" +*mips16: +*vr4100: +{ + do_ori (SD_, 0, TRX, IMMED); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 01101,3.RX,000,5.IMM_4_0:EXT-RI:16::LI +"li r<TRX>, <IMMEDIATE>" +*mips16: +*vr4100: +{ + do_ori (SD_, 0, TRX, IMMEDIATE); +} + + + +01000,3.RX,3.RY,0,4.IMMED:RRI-A:16::ADDIU +"addiu r<TRY>, r<TRX>, <IMMED>" +*mips16: +*vr4100: +{ + do_addiu (SD_, TRX, TRY, EXTEND4 (IMMED)); +} + +11110,7.IMM_10_4,4.IMM_14_11 + 01000,3.RX,3.RY,0,4.IMM_3_0:EXT-RRI-A:16::ADDIU +"addiu r<TRY>, r<TRX>, <IMMEDIATE>" +*mips16: +*vr4100: +{ + do_addiu (SD_, TRX, TRY, EXTEND15 (IMMEDIATE)); +} + + + +01001,3.RX,8.IMMED:RI:16::ADDIU8 +"addiu r<TRX>, <IMMED>" +*mips16: +*vr4100: +{ + do_addiu (SD_, TRX, TRX, EXTEND8 (IMMED)); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 01001,3.RX,000,5.IMM_4_0:EXT-RI:16::ADDIU8 +"addiu r<TRX>, <IMMEDIATE>" +*mips16: +*vr4100: +{ + do_addiu (SD_, TRX, TRX, EXTEND16 (IMMEDIATE)); +} + + + +01100,011,8.IMMED:I8:16::ADJSP +"addiu SP, <IMMED>" +*mips16: +*vr4100: +{ + do_addiu (SD_, SPIDX, SPIDX, EXTEND8 (IMMED) << 3); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 01100,011,000,5.IMM_4_0:EXT-I8:16::ADJSP +"addiu SP, <IMMEDIATE>" +*mips16: +*vr4100: +{ + do_addiu (SD_, SPIDX, SPIDX, EXTEND16 (IMMEDIATE)); +} + + + +00001,3.RX,8.IMMED:RI:16::ADDIUPC +"addiu r<TRX>, PC, <IMMED>" +*mips16: +*vr4100: +{ + unsigned32 temp = (basepc (SD_) & ~3) + (IMMED << 2); + GPR[TRX] = EXTEND32 (temp); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 00001,3.RX,000,5.IMM_4_0:EXT-RI:16::ADDIUPC +"addiu r<TRX>, PC, <IMMEDIATE>" +*mips16: +*vr4100: +{ + unsigned32 temp = (basepc (SD_) & ~3) + EXTEND16 (IMMEDIATE); + GPR[TRX] = EXTEND32 (temp); +} + + + +00000,3.RX,8.IMMED:RI:16::ADDIUSP +"addiu r<TRX>, SP, <IMMED>" +*mips16: +*vr4100: +{ + do_addiu (SD_, SPIDX, TRX, IMMED << 2); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 00000,3.RX,000,5.IMM_4_0:EXT-RI:16::ADDIUSP +"addiu r<TRX>, SP, <IMMEDIATE>" +*mips16: +*vr4100: +{ + do_addiu (SD_, SPIDX, TRX, EXTEND16 (IMMEDIATE)); +} + + + +01000,3.RX,3.RY,1,4.IMMED:RRI-A:16::DADDIU +"daddiu r<TRY>, r<TRX>, <IMMED>" +*mips16: +*vr4100: +{ + do_daddiu (SD_, TRX, TRY, EXTEND4 (IMMED)); +} + +11110,7.IMM_10_4,4.IMM_14_11 + 01000,3.RX,3.RY,1,4.IMM_3_0:EXT-RRI-A:16::DADDIU +"daddiu r<TRY>, r<TRX>, <IMMEDIATE>" +*mips16: +*vr4100: +{ + do_daddiu (SD_, TRX, TRY, EXTEND15 (IMMEDIATE)); +} + + + +11111,101,3.RY,5.IMMED:RI64:16::DADDIU5 +"daddiu r<TRY>, <IMMED>" +*mips16: +*vr4100: +{ + do_daddiu (SD_, TRY, TRY, EXTEND5 (IMMED)); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 11111,101,3.RY,5.IMM_4_0:EXT-RI64:16::DADDIU5 +"daddiu r<TRY>, <IMMEDIATE>" +*mips16: +*vr4100: +{ + do_daddiu (SD_, TRY, TRY, EXTEND16 (IMMEDIATE)); +} + + + +11111,011,8.IMMED:I64:16::DADJSP +"daddiu SP, <IMMED>" +*mips16: +*vr4100: +{ + do_daddiu (SD_, SPIDX, SPIDX, EXTEND8 (IMMED) << 3); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 11111,011,000,5.IMM_4_0:EXT-I64:16::DADJSP +"daddiu SP, <IMMEDIATE>" +*mips16: +*vr4100: +{ + do_daddiu (SD_, SPIDX, SPIDX, EXTEND16 (IMMEDIATE)); +} + + + +11111,110,3.RY,5.IMMED:RI64:16::DADDIUPC +"daddiu r<TRY>, PC, <IMMED>" +*mips16: +*vr4100: +{ + GPR[TRY] = (basepc (SD_) & ~3) + (IMMED << 2); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 11111,110,3.RY,5.IMM_4_0:EXT-RI64:16::DADDIUPC +"daddiu r<TRY>, PC, <IMMEDIATE>" +*mips16: +*vr4100: +{ + GPR[TRY] = (basepc (SD_) & ~3) + EXTEND16 (IMMEDIATE); +} + + + +11111,111,3.RY,5.IMMED:RI64:16::DADDIUSP +"daddiu r<TRY>, SP, <IMMED>" +*mips16: +*vr4100: +{ + do_daddiu (SD_, SPIDX, TRY, IMMED << 2); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 11111,111,3.RY,5.IMM_4_0:EXT-RI64:16::DADDIUSP +"daddiu r<TRY>, SP, <IMMEDIATE>" +*mips16: +*vr4100: +{ + do_daddiu (SD_, SPIDX, TRY, EXTEND16 (IMMEDIATE)); +} + + + +01010,3.RX,8.IMMED:RI:16::SLTI +"slti r<TRX>, <IMMED>" +*mips16: +*vr4100: +{ + do_slti (SD_, TRX, T8IDX, IMMED); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 01010,3.RX,000,5.IMM_4_0:EXT-RI:16::SLTI +"slti r<TRX>, <IMMEDIATE>" +*mips16: +*vr4100: +{ + do_slti (SD_, TRX, T8IDX, IMMEDIATE); +} + + + +01011,3.RX,8.IMMED:RI:16::SLTIU +"sltiu r<TRX>, <IMMED>" +*mips16: +*vr4100: +{ + do_sltiu (SD_, TRX, T8IDX, IMMED); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 01011,3.RX,000,5.IMM_4_0:EXT-RI:16::SLTIU +"sltiu r<TRX>, <IMMEDIATE>" +*mips16: +*vr4100: +{ + do_sltiu (SD_, TRX, T8IDX, IMMEDIATE); +} + + + +11101,3.RX,3.RY,01010:RR:16::CMP +"sltiu r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_xor (SD_, TRX, TRY, T8IDX); +} + + +01110,3.RX,8.IMMED:RI:16::CMPI +"sltiu r<TRX>, <IMMED>" +*mips16: +*vr4100: +{ + do_xori (SD_, TRX, T8IDX, IMMED); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 01110,3.RX,000,5.IMM_4_0:EXT-RI:16::CMPI +"sltiu r<TRX>, <IMMEDIATE>" +*mips16: +*vr4100: +{ + do_xori (SD_, TRX, T8IDX, IMMEDIATE); +} + + + +// Two/Three Operand, Register-Type + + + +11100,3.RX,3.RY,3.RZ,01:RRR:16::ADDU +"addu r<TRZ>, r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_addu (SD_, TRX, TRY, TRZ); +} + + + +11100,3.RX,3.RY,3.RZ,11:RRR:16::SUBU +"subu r<TRZ>, r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_subu (SD_, TRX, TRY, TRZ); +} + +11100,3.RX,3.RY,3.RZ,00:RRR:16::DADDU +"daddu r<TRZ>, r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_daddu (SD_, TRX, TRY, TRZ); +} + + + +11100,3.RX,3.RY,3.RZ,10:RRR:16::DSUBU +"dsubu r<TRZ>, r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_dsubu (SD_, TRX, TRY, TRZ); +} + + + +11101,3.RX,3.RY,00010:RR:16::SLT +"slt r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_slt (SD_, TRX, TRY, T8IDX); +} + + + +11101,3.RX,3.RY,00011:RR:16::SLTU +"sltu r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_sltu (SD_, TRX, TRY, T8IDX); +} + + + +11101,3.RX,3.RY,01011:RR:16::NEG +"neg r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_subu (SD_, 0, TRY, TRX); +} + + + +11101,3.RX,3.RY,01100:RR:16::AND +"and r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_and (SD_, TRX, TRY, TRX); +} + + + +11101,3.RX,3.RY,01101:RR:16::OR +"or r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_or (SD_, TRX, TRY, TRX); +} + + + +11101,3.RX,3.RY,01110:RR:16::XOR +"xor r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_xor (SD_, TRX, TRY, TRX); +} + + + +11101,3.RX,3.RY,01111:RR:16::NOT +"not r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_nor (SD_, 0, TRY, TRX); +} + + + +01100,111,3.RY,5.R32:I8_MOVR32:16::MOVR32 +"move r<TRY>, r<R32>" +*mips16: +*vr4100: +{ + do_or (SD_, R32, 0, TRY); +} + + + +01100,101,3.R32L,2.R32H,3.RZ:I8_MOV32R:16::MOV32R +"move r<R32>, r<TRZ>" +*mips16: +*vr4100: +{ + do_or (SD_, TRZ, 0, R32); +} + + + +00110,3.RX,3.RY,3.SHAMT,00:SHIFT:16::SLL +"sll r<TRX>, r<TRY>, <SHIFT>" +*mips16: +*vr4100: +{ + do_sll (SD_, TRY, TRX, SHIFT); +} + +11110,5.SHAMT,0,00000 + 00110,3.RX,3.RY,000,00:EXT-SHIFT:16::SLL +"sll r<TRX>, r<TRY>, <SHIFT>" +*mips16: +*vr4100: +{ + do_sll (SD_, TRY, TRX, SHAMT); +} + + + +00110,3.RX,3.RY,3.SHAMT,10:SHIFT:16::SRL +"srl r<TRX>, r<TRY>, <SHIFT>" +*mips16: +*vr4100: +{ + do_srl (SD_, TRY, TRX, SHIFT); +} + +11110,5.SHAMT,0,00000 + 00110,3.RX,3.RY,000,10:EXT-SHIFT:16::SRL +"srl r<TRX>, r<TRY>, <SHIFT>" +*mips16: +*vr4100: +{ + do_srl (SD_, TRY, TRX, SHAMT); +} + + + +00110,3.RX,3.RY,3.SHAMT,11:SHIFT:16::SRA +"sra r<TRX>, r<TRY>, <SHIFT>" +*mips16: +*vr4100: +{ + do_sra (SD_, TRY, TRX, SHIFT); +} + +11110,5.SHAMT,0,00000 + 00110,3.RX,3.RY,000,11:EXT-SHIFT:16::SRA +"sra r<TRX>, r<TRY>, <SHIFT>" +*mips16: +*vr4100: +{ + do_sra (SD_, TRY, TRX, SHAMT); +} + + + +11101,3.RX,3.RY,00100:RR:16::SLLV +"sllv r<TRY>, r<TRX>" +*mips16: +*vr4100: +{ + do_sllv (SD_, TRX, TRY, TRY); +} + + +11101,3.RX,3.RY,00110:RR:16::SRLV +"srlv r<TRY>, r<TRX>" +*mips16: +*vr4100: +{ + do_srlv (SD_, TRX, TRY, TRY); +} + + +11101,3.RX,3.RY,00111:RR:16::SRAV +"srav r<TRY>, r<TRX>" +*mips16: +*vr4100: +{ + do_srav (SD_, TRX, TRY, TRY); +} + + +00110,3.RX,3.RY,3.SHAMT,01:SHIFT:16::DSLL +"dsll r<TRY>, r<TRX>, <SHIFT>" +*mips16: +*vr4100: +{ + do_dsll (SD_, TRY, TRX, SHIFT); +} + +11110,5.SHAMT_4_0,1.S5,00000 + 00110,3.RX,3.RY,000,01:EXT-SHIFT:16::DSLL +"dsll r<TRY>, r<TRX>, <SHAMT>" +*mips16: +*vr4100: +{ + do_dsll (SD_, TRY, TRX, SHAMT); +} + + + +11101,3.SHAMT,3.RY,01000:SHIFT64:16::DSRL +"dsrl r<TRY>, <SHIFT>" +*mips16: +*vr4100: +{ + do_dsrl (SD_, TRY, TRY, SHIFT); +} + +11110,5.SHAMT_4_0,1.S5,00000 + 11101,000,3.RY,01000:EXT-SHIFT64:16::DSRL +"dsrl r<TRY>, <SHAMT>" +*mips16: +*vr4100: +{ + do_dsrl (SD_, TRY, TRY, SHAMT); +} + + + +11101,3.SHAMT,3.RY,10011:SHIFT64:16::DSRA +"dsra r<TRY>, <SHIFT>" +*mips16: +*vr4100: +{ + do_dsra (SD_, TRY, TRY, SHIFT); +} + +11110,5.SHAMT_4_0,1.S5,00000 + 11101,000,3.RY,10011:EXT-SHIFT64:16::DSRA +"dsra r<TRY>, <SHAMT>" +*mips16: +*vr4100: +{ + do_dsra (SD_, TRY, TRY, SHAMT); +} + + + +11101,3.RX,3.RY,10100:RR:16::DSLLV +"dsllv r<TRY>, r<TRX>" +*mips16: +*vr4100: +{ + do_dsllv (SD_, TRX, TRY, TRY); +} + + +11101,3.RX,3.RY,10110:RR:16::DSRLV +"dsrlv r<TRY>, r<TRX>" +*mips16: +*vr4100: +{ + do_dsrlv (SD_, TRX, TRY, TRY); +} + + +11101,3.RX,3.RY,10111:RR:16::DSRAV +"dsrav r<TRY>, r<TRX>" +*mips16: +*vr4100: +{ + do_dsrav (SD_, TRX, TRY, TRY); +} + + +// Multiply /Divide Instructions + + +11101,3.RX,3.RY,11000:RR:16::MULT +"mult r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_mult (SD_, TRX, TRY, 0); +} + + +11101,3.RX,3.RY,11001:RR:16::MULTU +"multu r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_multu (SD_, TRX, TRY, 0); +} + + +11101,3.RX,3.RY,11010:RR:16::DIV +"div r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_div (SD_, TRX, TRY); +} + + +11101,3.RX,3.RY,11011:RR:16::DIVU +"divu r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_divu (SD_, TRX, TRY); +} + + +11101,3.RX,000,10000:RR:16::MFHI +"mfhi r<TRX>" +*mips16: +*vr4100: +{ + do_mfhi (SD_, TRX); +} + + +11101,3.RX,000,10010:RR:16::MFLO +"mflo r<TRX>" +*mips16: +*vr4100: +{ + do_mflo (SD_, TRX); +} + + +11101,3.RX,3.RY,11100:RR:16::DMULT +"dmult r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_dmult (SD_, TRX, TRY, 0); +} + + +11101,3.RX,3.RY,11101:RR:16::DMULTU +"dmultu r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_dmultu (SD_, TRX, TRY, 0); +} + + +11101,3.RX,3.RY,11110:RR:16::DDIV +"ddiv r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_ddiv (SD_, TRX, TRY); +} + + +11101,3.RX,3.RY,11111:RR:16::DDIVU +"ddivu r<TRX>, r<TRY>" +*mips16: +*vr4100: +{ + do_ddivu (SD_, TRX, TRY); +} + + +// Jump and Branch Instructions + + + +// Issue instruction in delay slot of branch +:function:::address_word:delayslot16:address_word nia, address_word target +{ + instruction_word delay_insn; + sim_events_slip (SD, 1); + DSPC = CIA; /* save current PC somewhere */ + STATE |= simDELAYSLOT; + delay_insn = IMEM16 (nia); /* NOTE: mips16 */ + idecode_issue (CPU_, delay_insn, (nia)); + STATE &= ~simDELAYSLOT; + return target; +} + +// compute basepc dependant on us being in a delay slot +:function:::address_word:basepc: +{ + if (STATE & simDELAYSLOT) + { + return DSPC; /* return saved address of preceeding jmp */ + } + else + { + return CIA; + } +} + + +// JAL +00011,0,5.IMM_20_16,5.IMM_25_21 + 16.IMMED_15_0:JAL:16::JAL +"jal <IMMEDIATE>" +*mips16: +*vr4100: +{ + address_word region = (NIA & MASK (63, 28)); + RA = NIA + 2; /* skip 16 bit delayslot insn */ + NIA = delayslot16 (SD_, NIA, (region | (IMMEDIATE << 2))) | 1; +} + + + +// JALX - 32 and 16 bit versions. + +011101,26.IMMED:JALX:32::JALX32 +"jalx <IMMED>" +*mips16: +*vr4100: +{ + address_word region = (NIA & MASK (63, 28)); + RA = NIA + 4; /* skip 32 bit delayslot insn */ + NIA = delayslot32 (SD_, (region | (IMMED << 2)) | 1); +} + +00011,1,5.IMM_20_16,5.IMM_25_21 + 16.IMMED_15_0:JALX:16::JALX16 +"jalx <IMMEDIATE>" +*mips16: +*vr4100: +{ + address_word region = (NIA & MASK (63, 28)); + RA = NIA + 2; /* 16 bit INSN */ + NIA = delayslot16 (SD_, NIA, (region | (IMMEDIATE << 2)) & ~1); +} + + + +11101,3.RX,000,00000:RR:16::JR +"jr r<TRX>" +*mips16: +*vr4100: +{ + NIA = delayslot16 (SD_, NIA, GPR[TRX]); +} + + +11101,000,001,00000:RR:16::JRRA +"jrra" +*mips16: +*vr4100: +{ + NIA = delayslot16 (SD_, NIA, RA); +} + + + +11101,3.RX,010,00000:RR:16::JALR +"jalr r<TRX>" +*mips16: +*vr4100: +{ + RA = NIA + 2; + NIA = delayslot16 (SD_, NIA, GPR[TRX]); +} + + + +00100,3.RX,8.IMMED:RI:16::BEQZ +"beqz r<TRX>, <IMMED>" +*mips16: +*vr4100: +{ + if (GPR[TRX] == 0) + NIA = (NIA + (EXTEND8 (IMMED) << 1)); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 00100,3.RX,000,5.IMM_4_0:EXT-RI:16::BEQZ +"beqz r<TRX>, <IMMEDIATE>" +*mips16: +*vr4100: +{ + if (GPR[TRX] == 0) + NIA = (NIA + (EXTEND16 (IMMEDIATE) << 1)); +} + + + +00101,3.RX,8.IMMED:RI:16::BNEZ +"bnez r<TRX>, <IMMED>" +*mips16: +*vr4100: +{ + if (GPR[TRX] != 0) + NIA = (NIA + (EXTEND8 (IMMED) << 1)); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 00101,3.RX,000,5.IMM_4_0:EXT-RI:16::BNEZ +"bnez r<TRX>, <IMMEDIATE>" +*mips16: +*vr4100: +{ + if (GPR[TRX] != 0) + NIA = (NIA + (EXTEND16 (IMMEDIATE) << 1)); +} + + + +01100,000,8.IMMED:I8:16::BTEQZ +"bteqz <IMMED>" +*mips16: +*vr4100: +{ + if (T8 == 0) + NIA = (NIA + (EXTEND8 (IMMED) << 1)); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 01100,000,000,5.IMM_4_0:EXT-I8:16::BTEQZ +"bteqz <IMMEDIATE>" +*mips16: +*vr4100: +{ + if (T8 == 0) + NIA = (NIA + (EXTEND16 (IMMEDIATE) << 1)); +} + + + +01100,001,8.IMMED:I8:16::BTNEZ +"btnez <IMMED>" +*mips16: +*vr4100: +{ + if (T8 != 0) + NIA = (NIA + (EXTEND8 (IMMED) << 1)); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 01100,001,000,5.IMM_4_0:EXT-I8:16::BTNEZ +"btnez <IMMEDIATE>" +*mips16: +*vr4100: +{ + if (T8 != 0) + NIA = (NIA + (EXTEND16 (IMMEDIATE) << 1)); +} + + + +00010,11.IMMED:I:16::B +"b <IMMED>" +*mips16: +*vr4100: +{ + NIA = (NIA + (EXTEND11 (IMMED) << 1)); +} + +11110,6.IMM_10_5,5.IMM_15_11 + 00010,6.0,5.IMM_4_0:EXT-I:16::B +"b <IMMEDIATE>" +*mips16: +*vr4100: +{ + NIA = (NIA + (EXTEND16 (IMMEDIATE) << 1)); +} + + + +11101,3.RX,3.RY,00101:RR:16::BREAK +"break" +*mips16: +*vr4100: +{ + if (STATE & simDELAYSLOT) + PC = cia - 2; /* reference the branch instruction */ + else + PC = cia; + sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGTRAP); +} diff --git a/sim/mips/m16run.c b/sim/mips/m16run.c new file mode 100644 index 0000000..8a5d607 --- /dev/null +++ b/sim/mips/m16run.c @@ -0,0 +1,74 @@ +/* This file is part of the program psim. + + Copyright (C) 1998, Andrew Cagney <cagney@highland.com.au> + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#include "sim-main.h" +#include "m16_idecode.h" +#include "m32_idecode.h" +#include "bfd.h" + + +#define SD sd +#define CPU cpu + +void +sim_engine_run (SIM_DESC sd, + int next_cpu_nr, + int nr_cpus, /* ignore */ + int siggnal) /* ignore */ +{ + sim_cpu *cpu = STATE_CPU (sd, next_cpu_nr); + address_word cia = CIA_GET (cpu); + + while (1) + { + address_word nia; + +#if defined (ENGINE_ISSUE_PREFIX_HOOK) + ENGINE_ISSUE_PREFIX_HOOK (); +#endif + + if ((cia & 1)) + { + m16_instruction_word instruction_0 = IMEM16 (cia); + nia = m16_idecode_issue (sd, instruction_0, cia); + } + else + { + m32_instruction_word instruction_0 = IMEM32 (cia); + nia = m32_idecode_issue (sd, instruction_0, cia); + } + +#if defined (ENGINE_ISSUE_POSTFIX_HOOK) + ENGINE_ISSUE_POSTFIX_HOOK (); +#endif + + /* Update the instruction address */ + cia = nia; + + /* process any events */ + if (sim_events_tick (sd)) + { + CIA_SET (CPU, cia); + sim_events_process (sd); + cia = CIA_GET (CPU); + } + + } +} diff --git a/sim/mips/mips.dc b/sim/mips/mips.dc new file mode 100644 index 0000000..98da024 --- /dev/null +++ b/sim/mips/mips.dc @@ -0,0 +1,16 @@ +# most instructions +# ------ options ------ : Fst : Lst : ff : fl : fe : word : --- fmt --- : model ... +# { : mask : value : word } + +# Top level - create a very big switch statement. + + padded-switch,combine : 31 : 26 : : : : : : + + switch,combine : 5 : 0 : : : : : : + + switch,combine : 20 : 16 : : : : : : + + switch,combine : 25 : 21 : : : : : : + + switch,combine : 10 : 6 : : : : : : + diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen new file mode 100644 index 0000000..bfc209a --- /dev/null +++ b/sim/mips/mips.igen @@ -0,0 +1,3895 @@ +// -*- C -*- +// +// In mips.igen, the semantics for many of the instructions were created +// using code generated by gencode. Those semantic segments could be +// greatly simplified. +// +// <insn> ::= +// <insn-word> { "+" <insn-word> } +// ":" <format-name> +// ":" <filter-flags> +// ":" <options> +// ":" <name> +// <nl> +// { <insn-model> } +// { <insn-mnemonic> } +// <code-block> +// + + +// IGEN config - mips16 +// :option:16::insn-bit-size:16 +// :option:16::hi-bit-nr:15 +:option:16::insn-specifying-widths:true +:option:16::gen-delayed-branch:false + +// IGEN config - mips32/64.. +// :option:32::insn-bit-size:32 +// :option:32::hi-bit-nr:31 +:option:32::insn-specifying-widths:true +:option:32::gen-delayed-branch:false + + +// Generate separate simulators for each target +// :option:::multi-sim:true + + +// Models known by this simulator +:model:::mipsI:mips3000: +:model:::mipsII:mips6000: +:model:::mipsIII:mips4000: +:model:::mipsIV:mips8000: +:model:::mips16:mips16: +:model:::r3900:mips3900: +:model:::vr4100:mips4100: +:model:::vr5000:mips5000: + + + +// Pseudo instructions known by IGEN +:internal::::illegal: +{ + SignalException (ReservedInstruction, 0); +} + + +// Pseudo instructions known by interp.c +// For grep - RSVD_INSTRUCTION, RSVD_INSTRUCTION_MASK +000000,5.*,5.*,5.*,5.OP,000101:SPECIAL:32::RSVD +"rsvd <OP>" +{ + SignalException (ReservedInstruction, instruction_0); +} + + + +// Helper: +// +// Simulate a 32 bit delayslot instruction +// + +:function:::address_word:delayslot32:address_word target +{ + instruction_word delay_insn; + sim_events_slip (SD, 1); + DSPC = CIA; + CIA = CIA + 4; /* NOTE not mips16 */ + STATE |= simDELAYSLOT; + delay_insn = IMEM32 (CIA); /* NOTE not mips16 */ + idecode_issue (CPU_, delay_insn, (CIA)); + STATE &= ~simDELAYSLOT; + return target; +} + +:function:::address_word:nullify_next_insn32: +{ + sim_events_slip (SD, 1); + dotrace (SD, CPU, tracefh, 2, CIA + 4, 4, "load instruction"); + return CIA + 8; +} + +// Helper: +// +// Check that an access to a HI/LO register meets timing requirements +// +// The following requirements exist: +// +// - A MT {HI,LO} update was not immediatly preceeded by a MF {HI,LO} read +// - A OP {HI,LO} update was not immediatly preceeded by a MF {HI,LO} read +// - A MF {HI,LO} read was not corrupted by a preceeding MT{LO,HI} update +// corruption occures when MT{LO,HI} is preceeded by a OP {HI,LO}. +// + +:function:::int:check_mf_cycles:hilo_history *history, signed64 time, const char *new +{ + if (history->mf.timestamp + 3 > time) + { + sim_engine_abort (SD, CPU, CIA, "HILO: %s: %s at 0x%08lx too close to MF at 0x%08lx\n", + itable[MY_INDEX].name, + new, (long) CIA, + (long) history->mf.cia); + return 0; + } + return 1; +} + +:function:::int:check_mt_hilo:hilo_history *history +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +{ + signed64 time = sim_events_time (SD); + int ok = check_mf_cycles (SD_, history, time, "MT"); + history->mt.timestamp = time; + history->mt.cia = CIA; + return ok; +} + +:function:::int:check_mt_hilo:hilo_history *history +*r3900: +{ + signed64 time = sim_events_time (SD); + history->mt.timestamp = time; + history->mt.cia = CIA; + return 1; +} + + +:function:::int:check_mf_hilo:hilo_history *history, hilo_history *peer +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + signed64 time = sim_events_time (SD); + int ok = 1; + if (peer != NULL + && peer->mt.timestamp > history->op.timestamp + && history->mt.timestamp < history->op.timestamp + && ! (history->mf.timestamp > history->op.timestamp + && history->mf.timestamp < peer->mt.timestamp) + && ! (peer->mf.timestamp > history->op.timestamp + && peer->mf.timestamp < peer->mt.timestamp)) + { + /* The peer has been written to since the last OP yet we have + not */ + sim_engine_abort (SD, CPU, CIA, "HILO: %s: MF at 0x%08lx following OP at 0x%08lx corrupted by MT at 0x%08lx\n", + itable[MY_INDEX].name, + (long) CIA, + (long) history->op.cia, + (long) peer->mt.cia); + ok = 0; + } + history->mf.timestamp = time; + history->mf.cia = CIA; + return ok; +} + + + +:function:::int:check_mult_hilo:hilo_history *hi, hilo_history *lo +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +{ + signed64 time = sim_events_time (SD); + int ok = (check_mf_cycles (SD_, hi, time, "OP") + && check_mf_cycles (SD_, lo, time, "OP")); + hi->op.timestamp = time; + lo->op.timestamp = time; + hi->op.cia = CIA; + lo->op.cia = CIA; + return ok; +} + +// The r3900 mult and multu insns _can_ be exectuted immediatly after +// a mf{hi,lo} +:function:::int:check_mult_hilo:hilo_history *hi, hilo_history *lo +*r3900: +{ + /* FIXME: could record the fact that a stall occured if we want */ + signed64 time = sim_events_time (SD); + hi->op.timestamp = time; + lo->op.timestamp = time; + hi->op.cia = CIA; + lo->op.cia = CIA; + return 1; +} + + +:function:::int:check_div_hilo:hilo_history *hi, hilo_history *lo +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + signed64 time = sim_events_time (SD); + int ok = (check_mf_cycles (SD_, hi, time, "OP") + && check_mf_cycles (SD_, lo, time, "OP")); + hi->op.timestamp = time; + lo->op.timestamp = time; + hi->op.cia = CIA; + lo->op.cia = CIA; + return ok; +} + + + + + +// +// Mips Architecture: +// +// CPU Instruction Set (mipsI - mipsIV) +// + + + +000000,5.RS,5.RT,5.RD,00000,100000:SPECIAL:32::ADD +"add r<RD>, r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + { + ALU32_BEGIN (GPR[RS]); + ALU32_ADD (GPR[RT]); + ALU32_END (GPR[RD]); + } + TRACE_ALU_RESULT (GPR[RD]); +} + + + +001000,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::ADDI +"addi r<RT>, r<RS>, IMMEDIATE" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + TRACE_ALU_INPUT2 (GPR[RS], EXTEND16 (IMMEDIATE)); + { + ALU32_BEGIN (GPR[RS]); + ALU32_ADD (EXTEND16 (IMMEDIATE)); + ALU32_END (GPR[RT]); + } + TRACE_ALU_RESULT (GPR[RT]); +} + + + +:function:::void:do_addiu:int rs, int rt, unsigned16 immediate +{ + TRACE_ALU_INPUT2 (GPR[rs], EXTEND16 (immediate)); + GPR[rt] = EXTEND32 (GPR[rs] + EXTEND16 (immediate)); + TRACE_ALU_RESULT (GPR[rt]); +} + +001001,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::ADDIU +"addiu r<RT>, r<RS>, <IMMEDIATE>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_addiu (SD_, RS, RT, IMMEDIATE); +} + + + +:function:::void:do_addu:int rs, int rt, int rd +{ + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + GPR[rd] = EXTEND32 (GPR[rs] + GPR[rt]); + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000,100001:SPECIAL:32::ADDU +"addu r<RD>, r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_addu (SD_, RS, RT, RD); +} + + + +:function:::void:do_and:int rs, int rt, int rd +{ + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + GPR[rd] = GPR[rs] & GPR[rt]; + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000,100100:SPECIAL:32::AND +"and r<RD>, r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_and (SD_, RS, RT, RD); +} + + + +001100,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::ANDI +"and r<RT>, r<RS>, <IMMEDIATE>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE); + GPR[RT] = GPR[RS] & IMMEDIATE; + TRACE_ALU_RESULT (GPR[RT]); +} + + + +000100,5.RS,5.RT,16.OFFSET:NORMAL:32::BEQ +"beq r<RS>, r<RT>, <OFFSET>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + if ((signed_word) GPR[RS] == (signed_word) GPR[RT]) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } +} + + + +010100,5.RS,5.RT,16.OFFSET:NORMAL:32::BEQL +"beql r<RS>, r<RT>, <OFFSET>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + if ((signed_word) GPR[RS] == (signed_word) GPR[RT]) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } + else + NULLIFY_NEXT_INSTRUCTION (); +} + + + +000001,5.RS,00001,16.OFFSET:REGIMM:32::BGEZ +"bgez r<RS>, <OFFSET>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + if ((signed_word) GPR[RS] >= 0) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } +} + + + +000001,5.RS!31,10001,16.OFFSET:REGIMM:32::BGEZAL +"bgezal r<RS>, <OFFSET>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + RA = (CIA + 8); + if ((signed_word) GPR[RS] >= 0) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } +} + + + +000001,5.RS!31,10011,16.OFFSET:REGIMM:32::BGEZALL +"bgezall r<RS>, <OFFSET>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + RA = (CIA + 8); + /* NOTE: The branch occurs AFTER the next instruction has been + executed */ + if ((signed_word) GPR[RS] >= 0) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } + else + NULLIFY_NEXT_INSTRUCTION (); +} + + + +000001,5.RS,00011,16.OFFSET:REGIMM:32::BGEZL +"bgezl r<RS>, <OFFSET>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + if ((signed_word) GPR[RS] >= 0) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } + else + NULLIFY_NEXT_INSTRUCTION (); +} + + + +000111,5.RS,00000,16.OFFSET:NORMAL:32::BGTZ +"bgtz r<RS>, <OFFSET>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + if ((signed_word) GPR[RS] > 0) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } +} + + + +010111,5.RS,00000,16.OFFSET:NORMAL:32::BGTZL +"bgtzl r<RS>, <OFFSET>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + /* NOTE: The branch occurs AFTER the next instruction has been + executed */ + if ((signed_word) GPR[RS] > 0) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } + else + NULLIFY_NEXT_INSTRUCTION (); +} + + + +000110,5.RS,00000,16.OFFSET:NORMAL:32::BLEZ +"blez r<RS>, <OFFSET>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + /* NOTE: The branch occurs AFTER the next instruction has been + executed */ + if ((signed_word) GPR[RS] <= 0) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } +} + + + +010110,5.RS,00000,16.OFFSET:NORMAL:32::BLEZL +"bgezl r<RS>, <OFFSET>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + if ((signed_word) GPR[RS] <= 0) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } + else + NULLIFY_NEXT_INSTRUCTION (); +} + + + +000001,5.RS,00000,16.OFFSET:REGIMM:32::BLTZ +"bltz r<RS>, <OFFSET>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + if ((signed_word) GPR[RS] < 0) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } +} + + + +000001,5.RS!31,10000,16.OFFSET:REGIMM:32::BLTZAL +"bltzal r<RS>, <OFFSET>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + RA = (CIA + 8); + /* NOTE: The branch occurs AFTER the next instruction has been + executed */ + if ((signed_word) GPR[RS] < 0) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } +} + + + +000001,5.RS!31,10010,16.OFFSET:REGIMM:32::BLTZALL +"bltzall r<RS>, <OFFSET>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + RA = (CIA + 8); + if ((signed_word) GPR[RS] < 0) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } + else + NULLIFY_NEXT_INSTRUCTION (); +} + + + +000001,5.RS,00010,16.OFFSET:REGIMM:32::BLTZL +"bltzl r<RS>, <OFFSET>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + /* NOTE: The branch occurs AFTER the next instruction has been + executed */ + if ((signed_word) GPR[RS] < 0) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } + else + NULLIFY_NEXT_INSTRUCTION (); +} + + + +000101,5.RS,5.RT,16.OFFSET:NORMAL:32::BNE +"bne r<RS>, r<RT>, <OFFSET>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + if ((signed_word) GPR[RS] != (signed_word) GPR[RT]) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } +} + + + +010101,5.RS,5.RT,16.OFFSET:NORMAL:32::BNEL +"bnel r<RS>, r<RT>, <OFFSET>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_branch_bug (); + if ((signed_word) GPR[RS] != (signed_word) GPR[RT]) + { + mark_branch_bug (NIA+offset); + DELAY_SLOT (NIA + offset); + } + else + NULLIFY_NEXT_INSTRUCTION (); +} + + + +000000,20.CODE,001101:SPECIAL:32::BREAK +"break" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + /* Check for some break instruction which are reserved for use by the simulator. */ + unsigned int break_code = instruction_0 & HALT_INSTRUCTION_MASK; + if (break_code == (HALT_INSTRUCTION & HALT_INSTRUCTION_MASK) || + break_code == (HALT_INSTRUCTION2 & HALT_INSTRUCTION_MASK)) + { + sim_engine_halt (SD, CPU, NULL, cia, + sim_exited, (unsigned int)(A0 & 0xFFFFFFFF)); + } + else if (break_code == (BREAKPOINT_INSTRUCTION & HALT_INSTRUCTION_MASK) || + break_code == (BREAKPOINT_INSTRUCTION2 & HALT_INSTRUCTION_MASK)) + { + if (STATE & simDELAYSLOT) + PC = cia - 4; /* reference the branch instruction */ + else + PC = cia; + SignalException(BreakPoint, instruction_0); + } + + else + { + /* If we get this far, we're not an instruction reserved by the sim. Raise + the exception. */ + SignalException(BreakPoint, instruction_0); + } +} + + + + + + +000000,5.RS,5.RT,5.RD,00000,101100:SPECIAL:64::DADD +"dadd r<RD>, r<RS>, r<RT>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + /* this check's for overflow */ + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + { + ALU64_BEGIN (GPR[RS]); + ALU64_ADD (GPR[RT]); + ALU64_END (GPR[RD]); + } + TRACE_ALU_RESULT (GPR[RD]); +} + + + +011000,5.RS,5.RT,16.IMMEDIATE:NORMAL:64::DADDI +"daddi r<RT>, r<RS>, <IMMEDIATE>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + TRACE_ALU_INPUT2 (GPR[RS], EXTEND16 (IMMEDIATE)); + { + ALU64_BEGIN (GPR[RS]); + ALU64_ADD (EXTEND16 (IMMEDIATE)); + ALU64_END (GPR[RT]); + } + TRACE_ALU_RESULT (GPR[RT]); +} + + + +:function:::void:do_daddiu:int rs, int rt, unsigned16 immediate +{ + TRACE_ALU_INPUT2 (GPR[rs], EXTEND16 (immediate)); + GPR[rt] = GPR[rs] + EXTEND16 (immediate); + TRACE_ALU_RESULT (GPR[rt]); +} + +011001,5.RS,5.RT,16.IMMEDIATE:NORMAL:64::DADDIU +"daddu r<RT>, r<RS>, <IMMEDIATE>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_daddiu (SD_, RS, RT, IMMEDIATE); +} + + + +:function:::void:do_daddu:int rs, int rt, int rd +{ + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + GPR[rd] = GPR[rs] + GPR[rt]; + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000,101101:SPECIAL:64::DADDU +"daddu r<RD>, r<RS>, r<RT>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_daddu (SD_, RS, RT, RD); +} + + + +:function:::void:do_ddiv:int rs, int rt +{ + check_div_hilo (SD_, HIHISTORY, LOHISTORY); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + { + signed64 n = GPR[rs]; + signed64 d = GPR[rt]; + signed64 hi; + signed64 lo; + if (d == 0) + { + lo = SIGNED64 (0x8000000000000000); + hi = 0; + } + else if (d == -1 && n == SIGNED64 (0x8000000000000000)) + { + lo = SIGNED64 (0x8000000000000000); + hi = 0; + } + else + { + lo = (n / d); + hi = (n % d); + } + HI = hi; + LO = lo; + } + TRACE_ALU_RESULT2 (HI, LO); +} + +000000,5.RS,5.RT,0000000000011110:SPECIAL:64::DDIV +"ddiv r<RS>, r<RT>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_ddiv (SD_, RS, RT); +} + + + +:function:::void:do_ddivu:int rs, int rt +{ + check_div_hilo (SD_, HIHISTORY, LOHISTORY); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + { + unsigned64 n = GPR[rs]; + unsigned64 d = GPR[rt]; + unsigned64 hi; + unsigned64 lo; + if (d == 0) + { + lo = SIGNED64 (0x8000000000000000); + hi = 0; + } + else + { + lo = (n / d); + hi = (n % d); + } + HI = hi; + LO = lo; + } + TRACE_ALU_RESULT2 (HI, LO); +} + +000000,5.RS,5.RT,0000000000,011111:SPECIAL:64::DDIVU +"ddivu r<RS>, r<RT>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_ddivu (SD_, RS, RT); +} + + + +:function:::void:do_div:int rs, int rt +{ + check_div_hilo (SD_, HIHISTORY, LOHISTORY); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + { + signed32 n = GPR[rs]; + signed32 d = GPR[rt]; + if (d == 0) + { + LO = EXTEND32 (0x80000000); + HI = EXTEND32 (0); + } + else if (n == SIGNED32 (0x80000000) && d == -1) + { + LO = EXTEND32 (0x80000000); + HI = EXTEND32 (0); + } + else + { + LO = EXTEND32 (n / d); + HI = EXTEND32 (n % d); + } + } + TRACE_ALU_RESULT2 (HI, LO); +} + +000000,5.RS,5.RT,0000000000011010:SPECIAL:32::DIV +"div r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_div (SD_, RS, RT); +} + + + +:function:::void:do_divu:int rs, int rt +{ + check_div_hilo (SD_, HIHISTORY, LOHISTORY); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + { + unsigned32 n = GPR[rs]; + unsigned32 d = GPR[rt]; + if (d == 0) + { + LO = EXTEND32 (0x80000000); + HI = EXTEND32 (0); + } + else + { + LO = EXTEND32 (n / d); + HI = EXTEND32 (n % d); + } + } + TRACE_ALU_RESULT2 (HI, LO); +} + +000000,5.RS,5.RT,0000000000011011:SPECIAL:32::DIVU +"divu r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_divu (SD_, RS, RT); +} + + + +:function:::void:do_dmultx:int rs, int rt, int rd, int signed_p +{ + unsigned64 lo; + unsigned64 hi; + unsigned64 m00; + unsigned64 m01; + unsigned64 m10; + unsigned64 m11; + unsigned64 mid; + int sign; + unsigned64 op1 = GPR[rs]; + unsigned64 op2 = GPR[rt]; + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + /* make signed multiply unsigned */ + sign = 0; + if (signed_p) + { + if (op1 < 0) + { + op1 = - op1; + ++sign; + } + if (op2 < 0) + { + op2 = - op2; + ++sign; + } + } + /* multuply out the 4 sub products */ + m00 = ((unsigned64) VL4_8 (op1) * (unsigned64) VL4_8 (op2)); + m10 = ((unsigned64) VH4_8 (op1) * (unsigned64) VL4_8 (op2)); + m01 = ((unsigned64) VL4_8 (op1) * (unsigned64) VH4_8 (op2)); + m11 = ((unsigned64) VH4_8 (op1) * (unsigned64) VH4_8 (op2)); + /* add the products */ + mid = ((unsigned64) VH4_8 (m00) + + (unsigned64) VL4_8 (m10) + + (unsigned64) VL4_8 (m01)); + lo = U8_4 (mid, m00); + hi = (m11 + + (unsigned64) VH4_8 (mid) + + (unsigned64) VH4_8 (m01) + + (unsigned64) VH4_8 (m10)); + /* fix the sign */ + if (sign & 1) + { + lo = -lo; + if (lo == 0) + hi = -hi; + else + hi = -hi - 1; + } + /* save the result HI/LO (and a gpr) */ + LO = lo; + HI = hi; + if (rd != 0) + GPR[rd] = lo; + TRACE_ALU_RESULT2 (HI, LO); +} + +:function:::void:do_dmult:int rs, int rt, int rd +{ + do_dmultx (SD_, rs, rt, rd, 1); +} + +000000,5.RS,5.RT,0000000000011100:SPECIAL:64::DMULT +"dmult r<RS>, r<RT>" +*mipsIII,mipsIV: +*vr4100: +{ + do_dmult (SD_, RS, RT, 0); +} + +000000,5.RS,5.RT,5.RD,00000011100:SPECIAL:64::DMULT +"dmult r<RS>, r<RT>":RD == 0 +"dmult r<RD>, r<RS>, r<RT>" +*vr5000: +{ + do_dmult (SD_, RS, RT, RD); +} + + + +:function:::void:do_dmultu:int rs, int rt, int rd +{ + do_dmultx (SD_, rs, rt, rd, 0); +} + +000000,5.RS,5.RT,0000000000011101:SPECIAL:64::DMULTU +"dmultu r<RS>, r<RT>" +*mipsIII,mipsIV: +*vr4100: +{ + do_dmultu (SD_, RS, RT, 0); +} + +000000,5.RS,5.RT,5.RD,00000011101:SPECIAL:64::DMULTU +"dmultu r<RD>, r<RS>, r<RT>":RD == 0 +"dmultu r<RS>, r<RT>" +*vr5000: +{ + do_dmultu (SD_, RS, RT, RD); +} + +:function:::void:do_dsll:int rt, int rd, int shift +{ + GPR[rd] = GPR[rt] << shift; +} + +:function:::void:do_dsllv:int rs, int rt, int rd +{ + int s = MASKED64 (GPR[rs], 5, 0); + GPR[rd] = GPR[rt] << s; +} + + +00000000000,5.RT,5.RD,5.SHIFT,111000:SPECIAL:64::DSLL +"dsll r<RD>, r<RT>, <SHIFT>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_dsll (SD_, RT, RD, SHIFT); +} + + +00000000000,5.RT,5.RD,5.SHIFT,111100:SPECIAL:64::DSLL32 +"dsll32 r<RD>, r<RT>, <SHIFT>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + int s = 32 + SHIFT; + GPR[RD] = GPR[RT] << s; +} + +000000,5.RS,5.RT,5.RD,00000010100:SPECIAL:64::DSLLV +"dsllv r<RD>, r<RT>, r<RS>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_dsllv (SD_, RS, RT, RD); +} + +:function:::void:do_dsra:int rt, int rd, int shift +{ + GPR[rd] = ((signed64) GPR[rt]) >> shift; +} + + +00000000000,5.RT,5.RD,5.SHIFT,111011:SPECIAL:64::DSRA +"dsra r<RD>, r<RT>, <SHIFT>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_dsra (SD_, RT, RD, SHIFT); +} + + +00000000000,5.RT,5.RD,5.SHIFT,111111:SPECIAL:64::DSRA32 +"dsra32 r<RT>, r<RD>, <SHIFT>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + int s = 32 + SHIFT; + GPR[RD] = ((signed64) GPR[RT]) >> s; +} + + +:function:::void:do_dsrav:int rs, int rt, int rd +{ + int s = MASKED64 (GPR[rs], 5, 0); + TRACE_ALU_INPUT2 (GPR[rt], s); + GPR[rd] = ((signed64) GPR[rt]) >> s; + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000010111:SPECIAL:64::DSRAV +"dsra32 r<RT>, r<RD>, r<RS>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_dsrav (SD_, RS, RT, RD); +} + +:function:::void:do_dsrl:int rt, int rd, int shift +{ + GPR[rd] = (unsigned64) GPR[rt] >> shift; +} + + +00000000000,5.RT,5.RD,5.SHIFT,111010:SPECIAL:64::DSRL +"dsrl r<RD>, r<RT>, <SHIFT>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_dsrl (SD_, RT, RD, SHIFT); +} + + +00000000000,5.RT,5.RD,5.SHIFT,111110:SPECIAL:64::DSRL32 +"dsrl32 r<RD>, r<RT>, <SHIFT>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + int s = 32 + SHIFT; + GPR[RD] = (unsigned64) GPR[RT] >> s; +} + + +:function:::void:do_dsrlv:int rs, int rt, int rd +{ + int s = MASKED64 (GPR[rs], 5, 0); + GPR[rd] = (unsigned64) GPR[rt] >> s; +} + + + +000000,5.RS,5.RT,5.RD,00000010110:SPECIAL:64::DSRLV +"dsrl32 r<RD>, r<RT>, r<RS>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_dsrlv (SD_, RS, RT, RD); +} + + +000000,5.RS,5.RT,5.RD,00000101110:SPECIAL:64::DSUB +"dsub r<RD>, r<RS>, r<RT>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + { + ALU64_BEGIN (GPR[RS]); + ALU64_SUB (GPR[RT]); + ALU64_END (GPR[RD]); + } + TRACE_ALU_RESULT (GPR[RD]); +} + + +:function:::void:do_dsubu:int rs, int rt, int rd +{ + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + GPR[rd] = GPR[rs] - GPR[rt]; + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000101111:SPECIAL:64::DSUBU +"dsubu r<RD>, r<RS>, r<RT>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_dsubu (SD_, RS, RT, RD); +} + + +000010,26.INSTR_INDEX:NORMAL:32::J +"j <INSTR_INDEX>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + /* NOTE: The region used is that of the delay slot NIA and NOT the + current instruction */ + address_word region = (NIA & MASK (63, 28)); + DELAY_SLOT (region | (INSTR_INDEX << 2)); +} + + +000011,26.INSTR_INDEX:NORMAL:32::JAL +"jal <INSTR_INDEX>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + /* NOTE: The region used is that of the delay slot and NOT the + current instruction */ + address_word region = (NIA & MASK (63, 28)); + GPR[31] = CIA + 8; + DELAY_SLOT (region | (INSTR_INDEX << 2)); +} + +000000,5.RS,00000,5.RD,00000001001:SPECIAL:32::JALR +"jalr r<RS>":RD == 31 +"jalr r<RD>, r<RS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + address_word temp = GPR[RS]; + GPR[RD] = CIA + 8; + DELAY_SLOT (temp); +} + + +000000,5.RS,000000000000000001000:SPECIAL:32::JR +"jr r<RS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + DELAY_SLOT (GPR[RS]); +} + + +:function:::unsigned_word:do_load:unsigned access, address_word base, address_word offset +{ + address_word mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); + address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0); + address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0); + unsigned int byte; + address_word paddr; + int uncached; + unsigned64 memval; + address_word vaddr; + + vaddr = base + offset; + if ((vaddr & access) != 0) + { + SIM_CORE_SIGNAL (SD, STATE_CPU (SD, 0), cia, read_map, access+1, vaddr, read_transfer, sim_core_unaligned_signal); + } + AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, isTARGET, isREAL); + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian)); + LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isDATA, isREAL); + byte = ((vaddr & mask) ^ bigendiancpu); + return (memval >> (8 * byte)); +} + + +100000,5.BASE,5.RT,16.OFFSET:NORMAL:32::LB +"lb r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + GPR[RT] = EXTEND8 (do_load (SD_, AccessLength_BYTE, GPR[BASE], EXTEND16 (OFFSET))); +} + + +100100,5.BASE,5.RT,16.OFFSET:NORMAL:32::LBU +"lbu r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + GPR[RT] = do_load (SD_, AccessLength_BYTE, GPR[BASE], EXTEND16 (OFFSET)); +} + + +110111,5.BASE,5.RT,16.OFFSET:NORMAL:64::LD +"ld r<RT>, <OFFSET>(r<BASE>)" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + GPR[RT] = EXTEND64 (do_load (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET))); +} + + +1101,ZZ!0!1!3,5.BASE,5.RT,16.OFFSET:NORMAL:64::LDCz +"ldc<ZZ> r<RT>, <OFFSET>(r<BASE>)" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + COP_LD (ZZ, RT, do_load (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET))); +} + + + + +011010,5.BASE,5.RT,16.OFFSET:NORMAL:64::LDL +"ldl r<RT>, <OFFSET>(r<BASE>)" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + GPR[RT] = do_load_left (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT]); +} + + +011011,5.BASE,5.RT,16.OFFSET:NORMAL:64::LDR +"ldr r<RT>, <OFFSET>(r<BASE>)" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + GPR[RT] = do_load_right (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT]); +} + + +100001,5.BASE,5.RT,16.OFFSET:NORMAL:32::LH +"lh r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + GPR[RT] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[BASE], EXTEND16 (OFFSET))); +} + + +100101,5.BASE,5.RT,16.OFFSET:NORMAL:32::LHU +"lhu r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + GPR[RT] = do_load (SD_, AccessLength_HALFWORD, GPR[BASE], EXTEND16 (OFFSET)); +} + + +110000,5.BASE,5.RT,16.OFFSET:NORMAL:32::LL +"ll r<RT>, <OFFSET>(r<BASE>)" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + { + SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, read_transfer, sim_core_unaligned_signal); + } + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 2; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (SIGNEXTEND(((memval >> (8 * byte)) & 0xFFFFFFFF),32)); + LLBIT = 1; + } + } + } +} + + +110100,5.BASE,5.RT,16.OFFSET:NORMAL:64::LLD +"lld r<RT>, <OFFSET>(r<BASE>)" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + { + SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 8, vaddr, read_transfer, sim_core_unaligned_signal); + } + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + LoadMemory(&memval,&memval1,uncached,AccessLength_DOUBLEWORD,paddr,vaddr,isDATA,isREAL); + GPR[destreg] = memval; + LLBIT = 1; + } + } + } +} + + +001111,00000,5.RT,16.IMMEDIATE:NORMAL:32::LUI +"lui r<RT>, <IMMEDIATE>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + TRACE_ALU_INPUT1 (IMMEDIATE); + GPR[RT] = EXTEND32 (IMMEDIATE << 16); + TRACE_ALU_RESULT (GPR[RT]); +} + + +100011,5.BASE,5.RT,16.OFFSET:NORMAL:32::LW +"lw r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + GPR[RT] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET))); +} + + +1100,ZZ!0!1!3,5.BASE,5.RT,16.OFFSET:NORMAL:32::LWCz +"lwc<ZZ> r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + COP_LW (ZZ, RT, do_load (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET))); +} + + +:function:::unsigned_word:do_load_left:unsigned access, address_word base, address_word offset, unsigned_word rt +{ + address_word mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); + address_word reverseendian = (ReverseEndian ? -1 : 0); + address_word bigendiancpu = (BigEndianCPU ? -1 : 0); + unsigned int byte; + unsigned int word; + address_word paddr; + int uncached; + unsigned64 memval; + address_word vaddr; + int nr_lhs_bits; + int nr_rhs_bits; + unsigned_word lhs_mask; + unsigned_word temp; + + vaddr = base + offset; + AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, isTARGET, isREAL); + paddr = (paddr ^ (reverseendian & mask)); + if (BigEndianMem == 0) + paddr = paddr & ~access; + + /* compute where within the word/mem we are */ + byte = ((vaddr ^ bigendiancpu) & access); /* 0..access */ + word = ((vaddr ^ bigendiancpu) & (mask & ~access)) / (access + 1); /* 0..1 */ + nr_lhs_bits = 8 * byte + 8; + nr_rhs_bits = 8 * access - 8 * byte; + /* nr_lhs_bits + nr_rhs_bits == 8 * (accesss + 1) */ + + /* fprintf (stderr, "l[wd]l: 0x%08lx%08lx 0x%08lx%08lx %d:%d %d+%d\n", + (long) ((unsigned64) vaddr >> 32), (long) vaddr, + (long) ((unsigned64) paddr >> 32), (long) paddr, + word, byte, nr_lhs_bits, nr_rhs_bits); */ + + LoadMemory (&memval, NULL, uncached, byte, paddr, vaddr, isDATA, isREAL); + if (word == 0) + { + /* GPR{31..32-NR_LHS_BITS} = memval{NR_LHS_BITS-1..0} */ + temp = (memval << nr_rhs_bits); + } + else + { + /* GPR{31..32-NR_LHS_BITS = memval{32+NR_LHS_BITS..32} */ + temp = (memval >> nr_lhs_bits); + } + lhs_mask = LSMASK (nr_lhs_bits + nr_rhs_bits - 1, nr_rhs_bits); + rt = (rt & ~lhs_mask) | (temp & lhs_mask); + + /* fprintf (stderr, "l[wd]l: 0x%08lx%08lx -> 0x%08lx%08lx & 0x%08lx%08lx -> 0x%08lx%08lx\n", + (long) ((unsigned64) memval >> 32), (long) memval, + (long) ((unsigned64) temp >> 32), (long) temp, + (long) ((unsigned64) lhs_mask >> 32), (long) lhs_mask, + (long) (rt >> 32), (long) rt); */ + return rt; +} + + +100010,5.BASE,5.RT,16.OFFSET:NORMAL:32::LWL +"lwl r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + GPR[RT] = EXTEND32 (do_load_left (SD_, AccessLength_WORD, GPR[BASE], EXTEND32 (OFFSET), GPR[RT])); +} + + +:function:::unsigned_word:do_load_right:unsigned access, address_word base, address_word offset, unsigned_word rt +{ + address_word mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); + address_word reverseendian = (ReverseEndian ? -1 : 0); + address_word bigendiancpu = (BigEndianCPU ? -1 : 0); + unsigned int byte; + address_word paddr; + int uncached; + unsigned64 memval; + address_word vaddr; + + vaddr = base + offset; + AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, isTARGET, isREAL); + /* NOTE: SPEC is wrong, has `BigEndianMem == 0' not `BigEndianMem != 0' */ + paddr = (paddr ^ (reverseendian & mask)); + if (BigEndianMem != 0) + paddr = paddr & ~access; + byte = ((vaddr & mask) ^ (bigendiancpu & mask)); + /* NOTE: SPEC is wrong, had `byte' not `access - byte'. See SW. */ + LoadMemory (&memval, NULL, uncached, access - (access & byte), paddr, vaddr, isDATA, isREAL); + /* printf ("lr: 0x%08lx %d@0x%08lx 0x%08lx\n", + (long) paddr, byte, (long) paddr, (long) memval); */ + { + unsigned_word screen = LSMASK (8 * (access - (byte & access) + 1) - 1, 0); + rt &= ~screen; + rt |= (memval >> (8 * byte)) & screen; + } + return rt; +} + + +100110,5.BASE,5.RT,16.OFFSET:NORMAL:32::LWR +"lwr r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + GPR[RT] = EXTEND32 (do_load_right (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT])); +} + + +100111,5.BASE,5.RT,16.OFFSET:NORMAL:32::LWU +"lwu r<RT>, <OFFSET>(r<BASE>)" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + GPR[RT] = do_load (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET)); +} + + +:function:::void:do_mfhi:int rd +{ + check_mf_hilo (SD_, HIHISTORY, LOHISTORY); + TRACE_ALU_INPUT1 (HI); + GPR[rd] = HI; + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,0000000000,5.RD,00000,010000:SPECIAL:32::MFHI +"mfhi r<RD>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_mfhi (SD_, RD); +} + + + +:function:::void:do_mflo:int rd +{ + check_mf_hilo (SD_, LOHISTORY, HIHISTORY); + TRACE_ALU_INPUT1 (LO); + GPR[rd] = LO; + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,0000000000,5.RD,00000,010010:SPECIAL:32::MFLO +"mflo r<RD>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_mflo (SD_, RD); +} + + + +000000,5.RS,5.RT,5.RD,00000001011:SPECIAL:32::MOVN +"movn r<RD>, r<RS>, r<RT>" +*mipsIV: +*vr5000: +{ + if (GPR[RT] != 0) + GPR[RD] = GPR[RS]; +} + + + +000000,5.RS,5.RT,5.RD,00000001010:SPECIAL:32::MOVZ +"movz r<RD>, r<RS>, r<RT>" +*mipsIV: +*vr5000: +{ + if (GPR[RT] == 0) + GPR[RD] = GPR[RS]; +} + + + +000000,5.RS,000000000000000,010001:SPECIAL:32::MTHI +"mthi r<RS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + check_mt_hilo (SD_, HIHISTORY); + HI = GPR[RS]; +} + + + +000000,5.RS,000000000000000010011:SPECIAL:32::MTLO +"mtlo r<RS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + check_mt_hilo (SD_, LOHISTORY); + LO = GPR[RS]; +} + + + +:function:::void:do_mult:int rs, int rt, int rd +{ + signed64 prod; + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + prod = (((signed64)(signed32) GPR[rs]) + * ((signed64)(signed32) GPR[rt])); + LO = EXTEND32 (VL4_8 (prod)); + HI = EXTEND32 (VH4_8 (prod)); + if (rd != 0) + GPR[rd] = LO; + TRACE_ALU_RESULT2 (HI, LO); +} + +000000,5.RS,5.RT,00000,00000011000:SPECIAL:32::MULT +"mult r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +{ + do_mult (SD_, RS, RT, 0); +} + + +000000,5.RS,5.RT,5.RD,00000011000:SPECIAL:32::MULT +"mult r<RD>, r<RS>, r<RT>" +*vr5000: +*r3900: +{ + do_mult (SD_, RS, RT, RD); +} + + +:function:::void:do_multu:int rs, int rt, int rd +{ + unsigned64 prod; + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + prod = (((unsigned64)(unsigned32) GPR[rs]) + * ((unsigned64)(unsigned32) GPR[rt])); + LO = EXTEND32 (VL4_8 (prod)); + HI = EXTEND32 (VH4_8 (prod)); + if (rd != 0) + GPR[rd] = LO; + TRACE_ALU_RESULT2 (HI, LO); +} + +000000,5.RS,5.RT,00000,00000011001:SPECIAL:32::MULTU +"multu r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +{ + do_multu (SD_, RS, RT, 0); +} + +000000,5.RS,5.RT,5.RD,00000011001:SPECIAL:32::MULTU +"multu r<RD>, r<RS>, r<RT>" +*vr5000: +*r3900: +{ + do_multu (SD_, RS, RT, 0); +} + + +:function:::void:do_nor:int rs, int rt, int rd +{ + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + GPR[rd] = ~ (GPR[rs] | GPR[rt]); + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000,100111:SPECIAL:32::NOR +"nor r<RD>, r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_nor (SD_, RS, RT, RD); +} + + +:function:::void:do_or:int rs, int rt, int rd +{ + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + GPR[rd] = (GPR[rs] | GPR[rt]); + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000,100101:SPECIAL:32::OR +"or r<RD>, r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_or (SD_, RS, RT, RD); +} + + + +:function:::void:do_ori:int rs, int rt, unsigned immediate +{ + TRACE_ALU_INPUT2 (GPR[rs], immediate); + GPR[rt] = (GPR[rs] | immediate); + TRACE_ALU_RESULT (GPR[rt]); +} + +001101,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::ORI +"ori r<RT>, r<RS>, <IMMEDIATE>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_ori (SD_, RS, RT, IMMEDIATE); +} + + +110011,5.RS,nnnnn,16.OFFSET:NORMAL:32::PREF +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int hint = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + Prefetch(uncached,paddr,vaddr,isDATA,hint); + } + } +} + +:function:::void:do_store:unsigned access, address_word base, address_word offset, unsigned_word word +{ + address_word mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); + address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0); + address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0); + unsigned int byte; + address_word paddr; + int uncached; + unsigned64 memval; + address_word vaddr; + + vaddr = base + offset; + if ((vaddr & access) != 0) + { + SIM_CORE_SIGNAL (SD, STATE_CPU(SD, 0), cia, read_map, access+1, vaddr, write_transfer, sim_core_unaligned_signal); + } + AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, isTARGET, isREAL); + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian)); + byte = ((vaddr & mask) ^ bigendiancpu); + memval = (word << (8 * byte)); + StoreMemory (uncached, access, memval, 0, paddr, vaddr, isREAL); +} + + +101000,5.BASE,5.RT,16.OFFSET:NORMAL:32::SB +"sb r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_store (SD_, AccessLength_BYTE, GPR[BASE], EXTEND16 (OFFSET), GPR[RT]); +} + + +111000,5.BASE,5.RT,16.OFFSET:NORMAL:32::SC +"sc r<RT>, <OFFSET>(r<BASE>)" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + { + SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, write_transfer, sim_core_unaligned_signal); + } + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2))); + byte = ((vaddr & mask) ^ (BigEndianCPU << 2)); + memval = ((unsigned64) op2 << (8 * byte)); + if (LLBIT) + { + StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); + } + GPR[(instruction >> 16) & 0x0000001F] = LLBIT; + } + } + } +} + + +111100,5.BASE,5.RT,16.OFFSET:NORMAL:64::SCD +"scd r<RT>, <OFFSET>(r<BASE>)" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + { + SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 8, vaddr, write_transfer, sim_core_unaligned_signal); + } + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + memval = op2; + if (LLBIT) + { + StoreMemory(uncached,AccessLength_DOUBLEWORD,memval,memval1,paddr,vaddr,isREAL); + } + GPR[(instruction >> 16) & 0x0000001F] = LLBIT; + } + } + } +} + + +111111,5.BASE,5.RT,16.OFFSET:NORMAL:64::SD +"sd r<RT>, <OFFSET>(r<BASE>)" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_store (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT]); +} + + +1111,ZZ!0!1!3,5.BASE,5.RT,16.OFFSET:NORMAL:64::SDCz +"sdc<ZZ> r<RT>, <OFFSET>(r<BASE>)" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_store (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET), COP_SD (ZZ, RT)); +} + + +101100,5.BASE,5.RT,16.OFFSET:NORMAL:64::SDL +"sdl r<RT>, <OFFSET>(r<BASE>)" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_store_left (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT]); +} + + +101101,5.BASE,5.RT,16.OFFSET:NORMAL:64::SDR +"sdr r<RT>, <OFFSET>(r<BASE>)" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + do_store_right (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT]); +} + + +101001,5.BASE,5.RT,16.OFFSET:NORMAL:32::SH +"sh r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_store (SD_, AccessLength_HALFWORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT]); +} + + +:function:::void:do_sll:int rt, int rd, int shift +{ + unsigned32 temp = (GPR[rt] << shift); + TRACE_ALU_INPUT2 (GPR[rt], shift); + GPR[rd] = EXTEND32 (temp); + TRACE_ALU_RESULT (GPR[rd]); +} + +00000000000,5.RT,5.RD,5.SHIFT,000000:SPECIAL:32::SLL +"sll r<RD>, r<RT>, <SHIFT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_sll (SD_, RT, RD, SHIFT); +} + + +:function:::void:do_sllv:int rs, int rt, int rd +{ + int s = MASKED (GPR[rs], 4, 0); + unsigned32 temp = (GPR[rt] << s); + TRACE_ALU_INPUT2 (GPR[rt], s); + GPR[rd] = EXTEND32 (temp); + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000000100:SPECIAL:32::SLLV +"sllv r<RD>, r<RT>, r<RS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_sllv (SD_, RS, RT, RD); +} + + +:function:::void:do_slt:int rs, int rt, int rd +{ + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + GPR[rd] = ((signed_word) GPR[rs] < (signed_word) GPR[rt]); + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000101010:SPECIAL:32::SLT +"slt r<RD>, r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_slt (SD_, RS, RT, RD); +} + + +:function:::void:do_slti:int rs, int rt, unsigned16 immediate +{ + TRACE_ALU_INPUT2 (GPR[rs], EXTEND16 (immediate)); + GPR[rt] = ((signed_word) GPR[rs] < (signed_word) EXTEND16 (immediate)); + TRACE_ALU_RESULT (GPR[rt]); +} + +001010,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::SLTI +"slti r<RT>, r<RS>, <IMMEDIATE>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_slti (SD_, RS, RT, IMMEDIATE); +} + + +:function:::void:do_sltiu:int rs, int rt, unsigned16 immediate +{ + TRACE_ALU_INPUT2 (GPR[rs], EXTEND16 (immediate)); + GPR[rt] = ((unsigned_word) GPR[rs] < (unsigned_word) EXTEND16 (immediate)); + TRACE_ALU_RESULT (GPR[rt]); +} + +001011,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::SLTIU +"sltiu r<RT>, r<RS>, <IMMEDIATE>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_sltiu (SD_, RS, RT, IMMEDIATE); +} + + + +:function:::void:do_sltu:int rs, int rt, int rd +{ + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + GPR[rd] = ((unsigned_word) GPR[rs] < (unsigned_word) GPR[rt]); + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000101011:SPECIAL:32::SLTU +"sltu r<RD>, r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_sltu (SD_, RS, RT, RD); +} + + +:function:::void:do_sra:int rt, int rd, int shift +{ + signed32 temp = (signed32) GPR[rt] >> shift; + TRACE_ALU_INPUT2 (GPR[rt], shift); + GPR[rd] = EXTEND32 (temp); + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,00000,5.RT,5.RD,5.SHIFT,000011:SPECIAL:32::SRA +"sra r<RD>, r<RT>, <SHIFT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_sra (SD_, RT, RD, SHIFT); +} + + + +:function:::void:do_srav:int rs, int rt, int rd +{ + int s = MASKED (GPR[rs], 4, 0); + signed32 temp = (signed32) GPR[rt] >> s; + TRACE_ALU_INPUT2 (GPR[rt], s); + GPR[rd] = EXTEND32 (temp); + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000000111:SPECIAL:32::SRAV +"srav r<RD>, r<RT>, r<RS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_srav (SD_, RS, RT, RD); +} + + + +:function:::void:do_srl:int rt, int rd, int shift +{ + unsigned32 temp = (unsigned32) GPR[rt] >> shift; + TRACE_ALU_INPUT2 (GPR[rt], shift); + GPR[rd] = EXTEND32 (temp); + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,00000,5.RT,5.RD,5.SHIFT,000010:SPECIAL:32::SRL +"srl r<RD>, r<RT>, <SHIFT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_srl (SD_, RT, RD, SHIFT); +} + + +:function:::void:do_srlv:int rs, int rt, int rd +{ + int s = MASKED (GPR[rs], 4, 0); + unsigned32 temp = (unsigned32) GPR[rt] >> s; + TRACE_ALU_INPUT2 (GPR[rt], s); + GPR[rd] = EXTEND32 (temp); + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000000110:SPECIAL:32::SRLV +"srlv r<RD>, r<RT>, r<RS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_srlv (SD_, RS, RT, RD); +} + + +000000,5.RS,5.RT,5.RD,00000100010:SPECIAL:32::SUB +"sub r<RD>, r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + { + ALU32_BEGIN (GPR[RS]); + ALU32_SUB (GPR[RT]); + ALU32_END (GPR[RD]); + } + TRACE_ALU_RESULT (GPR[RD]); +} + + +:function:::void:do_subu:int rs, int rt, int rd +{ + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + GPR[rd] = EXTEND32 (GPR[rs] - GPR[rt]); + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000100011:SPECIAL:32::SUBU +"subu r<RD>, r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_subu (SD_, RS, RT, RD); +} + + +101011,5.BASE,5.RT,16.OFFSET:NORMAL:32::SW +"sw r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*r3900: +*vr5000: +{ + do_store (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT]); +} + + +1110,ZZ!0!1!3,5.BASE,5.RT,16.OFFSET:NORMAL:32::SWCz +"swc<ZZ> r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_store (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET), COP_SW (ZZ, RT)); +} + + + +:function:::void:do_store_left:unsigned access, address_word base, address_word offset, unsigned_word rt +{ + address_word mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); + address_word reverseendian = (ReverseEndian ? -1 : 0); + address_word bigendiancpu = (BigEndianCPU ? -1 : 0); + unsigned int byte; + unsigned int word; + address_word paddr; + int uncached; + unsigned64 memval; + address_word vaddr; + int nr_lhs_bits; + int nr_rhs_bits; + + vaddr = base + offset; + AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, isTARGET, isREAL); + paddr = (paddr ^ (reverseendian & mask)); + if (BigEndianMem == 0) + paddr = paddr & ~access; + + /* compute where within the word/mem we are */ + byte = ((vaddr ^ bigendiancpu) & access); /* 0..access */ + word = ((vaddr ^ bigendiancpu) & (mask & ~access)) / (access + 1); /* 0..1 */ + nr_lhs_bits = 8 * byte + 8; + nr_rhs_bits = 8 * access - 8 * byte; + /* nr_lhs_bits + nr_rhs_bits == 8 * (accesss + 1) */ + /* fprintf (stderr, "s[wd]l: 0x%08lx%08lx 0x%08lx%08lx %d:%d %d+%d\n", + (long) ((unsigned64) vaddr >> 32), (long) vaddr, + (long) ((unsigned64) paddr >> 32), (long) paddr, + word, byte, nr_lhs_bits, nr_rhs_bits); */ + + if (word == 0) + { + memval = (rt >> nr_rhs_bits); + } + else + { + memval = (rt << nr_lhs_bits); + } + /* fprintf (stderr, "s[wd]l: 0x%08lx%08lx -> 0x%08lx%08lx\n", + (long) ((unsigned64) rt >> 32), (long) rt, + (long) ((unsigned64) memval >> 32), (long) memval); */ + StoreMemory (uncached, byte, memval, 0, paddr, vaddr, isREAL); +} + + +101010,5.BASE,5.RT,16.OFFSET:NORMAL:32::SWL +"swl r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_store_left (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT]); +} + + +:function:::void:do_store_right:unsigned access, address_word base, address_word offset, unsigned_word rt +{ + address_word mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); + address_word reverseendian = (ReverseEndian ? -1 : 0); + address_word bigendiancpu = (BigEndianCPU ? -1 : 0); + unsigned int byte; + address_word paddr; + int uncached; + unsigned64 memval; + address_word vaddr; + + vaddr = base + offset; + AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, isTARGET, isREAL); + paddr = (paddr ^ (reverseendian & mask)); + if (BigEndianMem != 0) + paddr &= ~access; + byte = ((vaddr & mask) ^ (bigendiancpu & mask)); + memval = (rt << (byte * 8)); + StoreMemory (uncached, access - (access & byte), memval, 0, paddr, vaddr, isREAL); +} + +101110,5.BASE,5.RT,16.OFFSET:NORMAL:32::SWR +"swr r<RT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_store_right (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT]); +} + + +000000000000000000000,5.STYPE,001111:SPECIAL:32::SYNC +"sync":STYPE == 0 +"sync <STYPE>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + SyncOperation (STYPE); +} + + +000000,20.CODE,001100:SPECIAL:32::SYSCALL +"syscall <CODE>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + SignalException(SystemCall, instruction_0); +} + + +000000,5.RS,5.RT,10.CODE,110100:SPECIAL:32::TEQ +"teq r<RS>, r<RT>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if ((signed_word) GPR[RS] == (signed_word) GPR[RT]) + SignalException(Trap, instruction_0); +} + + +000001,5.RS,01100,16.IMMEDIATE:REGIMM:32::TEQI +"teqi r<RS>, <IMMEDIATE>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if ((signed_word) GPR[RS] == (signed_word) EXTEND16 (IMMEDIATE)) + SignalException(Trap, instruction_0); +} + + +000000,5.RS,5.RT,10.CODE,110000:SPECIAL:32::TGE +"tge r<RS>, r<RT>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if ((signed_word) GPR[RS] >= (signed_word) GPR[RT]) + SignalException(Trap, instruction_0); +} + + +000001,5.RS,01000,16.IMMEDIATE:REGIMM:32::TGEI +"tgei r<RS>, <IMMEDIATE>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if ((signed_word) GPR[RS] >= (signed_word) EXTEND16 (IMMEDIATE)) + SignalException(Trap, instruction_0); +} + + +000001,5.RS,01001,16.IMMEDIATE:REGIMM:32::TGEIU +"tgeiu r<RS>, <IMMEDIATE>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if ((unsigned_word) GPR[RS] >= (unsigned_word) EXTEND16 (IMMEDIATE)) + SignalException(Trap, instruction_0); +} + + +000000,5.RS,5.RT,10.CODE,110001:SPECIAL:32::TGEU +"tgeu r<RS>, r<RT>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if ((unsigned_word) GPR[RS] >= (unsigned_word) GPR[RT]) + SignalException(Trap, instruction_0); +} + + +000000,5.RS,5.RT,10.CODE,110010:SPECIAL:32::TLT +"tlt r<RS>, r<RT>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if ((signed_word) GPR[RS] < (signed_word) GPR[RT]) + SignalException(Trap, instruction_0); +} + + +000001,5.RS,01010,16.IMMEDIATE:REGIMM:32::TLTI +"tlti r<RS>, <IMMEDIATE>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if ((signed_word) GPR[RS] < (signed_word) EXTEND16 (IMMEDIATE)) + SignalException(Trap, instruction_0); +} + + +000001,5.RS,01011,16.IMMEDIATE:REGIMM:32::TLTIU +"tltiu r<RS>, <IMMEDIATE>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if ((unsigned_word) GPR[RS] < (unsigned_word) EXTEND16 (IMMEDIATE)) + SignalException(Trap, instruction_0); +} + + +000000,5.RS,5.RT,10.CODE,110011:SPECIAL:32::TLTU +"tltu r<RS>, r<RT>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if ((unsigned_word) GPR[RS] < (unsigned_word) GPR[RT]) + SignalException(Trap, instruction_0); +} + + +000000,5.RS,5.RT,10.CODE,110110:SPECIAL:32::TNE +"tne r<RS>, r<RT>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if ((signed_word) GPR[RS] != (signed_word) GPR[RT]) + SignalException(Trap, instruction_0); +} + + +000001,5.RS,01110,16.IMMEDIATE:REGIMM:32::TNEI +"tne r<RS>, <IMMEDIATE>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if ((signed_word) GPR[RS] != (signed_word) EXTEND16 (IMMEDIATE)) + SignalException(Trap, instruction_0); +} + + +:function:::void:do_xor:int rs, int rt, int rd +{ + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + GPR[rd] = GPR[rs] ^ GPR[rt]; + TRACE_ALU_RESULT (GPR[rd]); +} + +000000,5.RS,5.RT,5.RD,00000100110:SPECIAL:32::XOR +"xor r<RD>, r<RS>, r<RT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_xor (SD_, RS, RT, RD); +} + + +:function:::void:do_xori:int rs, int rt, unsigned16 immediate +{ + TRACE_ALU_INPUT2 (GPR[rs], immediate); + GPR[rt] = GPR[rs] ^ immediate; + TRACE_ALU_RESULT (GPR[rt]); +} + +001110,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::XORI +"xori r<RT>, r<RS>, <IMMEDIATE>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_xori (SD_, RS, RT, IMMEDIATE); +} + + +// +// MIPS Architecture: +// +// FPU Instruction Set (COP1 & COP1X) +// + + +:%s::::FMT:int fmt +{ + switch (fmt) + { + case fmt_single: return "s"; + case fmt_double: return "d"; + case fmt_word: return "w"; + case fmt_long: return "l"; + default: return "?"; + } +} + +:%s::::X:int x +{ + switch (x) + { + case 0: return "f"; + case 1: return "t"; + default: return "?"; + } +} + +:%s::::TF:int tf +{ + if (tf) + return "t"; + else + return "f"; +} + +:%s::::ND:int nd +{ + if (nd) + return "l"; + else + return ""; +} + +:%s::::COND:int cond +{ + switch (cond) + { + case 00: return "f"; + case 01: return "un"; + case 02: return "eq"; + case 03: return "ueq"; + case 04: return "olt"; + case 05: return "ult"; + case 06: return "ole"; + case 07: return "ule"; + case 010: return "sf"; + case 011: return "ngle"; + case 012: return "seq"; + case 013: return "ngl"; + case 014: return "lt"; + case 015: return "nge"; + case 016: return "le"; + case 017: return "ngt"; + default: return "?"; + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,000101:COP1:32,f::ABS.fmt +"abs.%s<FMT> f<FD>, f<FS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format)); + } +} + + + +010001,10,3.FMT,5.FT,5.FS,5.FD,000000:COP1:32,f::ADD.fmt +"add.%s<FMT> f<FD>, f<FS>, f<FT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction, instruction); + else + StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format)); + } +} + + + +// BC1F +// BC1FL +// BC1T +// BC1TL + +010001,01000,3.0,1.ND,1.TF,16.OFFSET:COP1S:32,f::BC1a +"bc1%s<TF>%s<ND> <OFFSET>" +*mipsI,mipsII,mipsIII: +{ + check_branch_bug (); + TRACE_BRANCH_INPUT (PREVCOC1()); + if (PREVCOC1() == TF) + { + address_word dest = NIA + (EXTEND16 (OFFSET) << 2); + TRACE_BRANCH_RESULT (dest); + mark_branch_bug (dest); + DELAY_SLOT (dest); + } + else if (ND) + { + TRACE_BRANCH_RESULT (0); + NULLIFY_NEXT_INSTRUCTION (); + } + else + { + TRACE_BRANCH_RESULT (NIA); + } +} + +010001,01000,3.CC,1.ND,1.TF,16.OFFSET:COP1S:32,f::BC1b +"bc1%s<TF>%s<ND> <OFFSET>":CC == 0 +"bc1%s<TF>%s<ND> <CC>, <OFFSET>" +*mipsIV: +*vr5000: +#*vr4100: +*r3900: +{ + check_branch_bug (); + if (GETFCC(CC) == TF) + { + address_word dest = NIA + (EXTEND16 (OFFSET) << 2); + mark_branch_bug (dest); + DELAY_SLOT (dest); + } + else if (ND) + { + NULLIFY_NEXT_INSTRUCTION (); + } +} + + + + + + +// C.EQ.S +// C.EQ.D +// ... + +:function:::void:do_c_cond_fmt:int fmt, int ft, int fs, int cc, int cond, instruction_word insn +{ + if ((fmt != fmt_single) && (fmt != fmt_double)) + SignalException (ReservedInstruction, insn); + else + { + int less; + int equal; + int unordered; + int condition; + unsigned64 ofs = ValueFPR (fs, fmt); + unsigned64 oft = ValueFPR (ft, fmt); + if (NaN (ofs, fmt) || NaN (oft, fmt)) + { + if (FCSR & FP_ENABLE (IO)) + { + FCSR |= FP_CAUSE (IO); + SignalExceptionFPE (); + } + less = 0; + equal = 0; + unordered = 1; + } + else + { + less = Less (ofs, oft, fmt); + equal = Equal (ofs, oft, fmt); + unordered = 0; + } + condition = (((cond & (1 << 2)) && less) + || ((cond & (1 << 1)) && equal) + || ((cond & (1 << 0)) && unordered)); + SETFCC (cc, condition); + } +} + +010001,10,3.FMT,5.FT,5.FS,3.0,00,11,4.COND:COP1:32::C.cond.fmta +"c.%s<COND>.%s<FMT> f<FS>, f<FT>" +*mipsI,mipsII,mipsIII: +{ + do_c_cond_fmt (SD_, FMT, FT, FS, 0, COND, instruction_0); +} + +010001,10,3.FMT,5.FT,5.FS,3.CC,00,11,4.COND:COP1:32::C.cond.fmtb +"c.%s<COND>.%s<FMT> f<FS>, f<FT>":CC == 0 +"c.%s<COND>.%s<FMT> <CC>, f<FS>, f<FT>" +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_c_cond_fmt (SD_, FMT, FT, FS, CC, COND, instruction_0); +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001010:COP1:64::CEIL.L.fmt +"ceil.l.%s<FMT> f<FD>, f<FS>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_long,Convert(FP_RM_TOPINF,ValueFPR(fs,format),format,fmt_long)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001110:COP1:32::CEIL.W +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_word,Convert(FP_RM_TOPINF,ValueFPR(fs,format),format,fmt_word)); + } +} + + +// CFC1 +// CTC1 +010001,00,X,10,5.RT,5.FS,00000000000:COP1Sa:32::CxC1 +"c%s<X>c1 r<RT>, f<FS>" +*mipsI: +*mipsII: +*mipsIII: +{ + if (X) + { + if (FS == 0) + PENDING_FILL((FS + FCR0IDX),VL4_8(GPR[RT])); + else if (FS == 31) + PENDING_FILL((FS + FCR31IDX),VL4_8(GPR[RT])); + /* else NOP */ + PENDING_FILL(COCIDX,0); /* special case */ + } + else + { /* control from */ + if (FS == 0) + PENDING_FILL(RT,SIGNEXTEND(FCR0,32)); + else if (FS == 31) + PENDING_FILL(RT,SIGNEXTEND(FCR31,32)); + /* else NOP */ + } +} +010001,00,X,10,5.RT,5.FS,00000000000:COP1Sb:32::CxC1 +"c%s<X>c1 r<RT>, f<FS>" +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + if (X) + { + /* control to */ + TRACE_ALU_INPUT1 (GPR[RT]); + if (FS == 0) + { + FCR0 = VL4_8(GPR[RT]); + TRACE_ALU_RESULT (FCR0); + } + else if (FS == 31) + { + FCR31 = VL4_8(GPR[RT]); + SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); + TRACE_ALU_RESULT (FCR31); + } + else + { + TRACE_ALU_RESULT0 (); + } + /* else NOP */ + } + else + { /* control from */ + if (FS == 0) + { + TRACE_ALU_INPUT1 (FCR0); + GPR[RT] = SIGNEXTEND (FCR0, 32); + } + else if (FS == 31) + { + TRACE_ALU_INPUT1 (FCR31); + GPR[RT] = SIGNEXTEND (FCR31, 32); + } + TRACE_ALU_RESULT (GPR[RT]); + /* else NOP */ + } +} + + +// +// FIXME: Does not correctly differentiate between mips* +// +010001,10,3.FMT,00000,5.FS,5.FD,100001:COP1:32::CVT.D.fmt +"cvt.d.%s<FMT> f<FD>, f<FS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format == fmt_double) | 0) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_double,Convert(GETRM(),ValueFPR(fs,format),format,fmt_double)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,100101:COP1:64::CVT.L.fmt +"cvt.l.%s<FMT> f<FD>, f<FS>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format == fmt_long) | ((format == fmt_long) || (format == fmt_word))) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_long,Convert(GETRM(),ValueFPR(fs,format),format,fmt_long)); + } +} + + +// +// FIXME: Does not correctly differentiate between mips* +// +010001,10,3.FMT,00000,5.FS,5.FD,100000:COP1:32::CVT.S.fmt +"cvt.s.%s<FMT> f<FD>, f<FS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format == fmt_single) | 0) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_single,Convert(GETRM(),ValueFPR(fs,format),format,fmt_single)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,100100:COP1:32::CVT.W.fmt +"cvt.w.%s<FMT> f<FD>, f<FS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format == fmt_word) | ((format == fmt_long) || (format == fmt_word))) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_word,Convert(GETRM(),ValueFPR(fs,format),format,fmt_word)); + } +} + + +010001,10,3.FMT,5.FT,5.FS,5.FD,000011:COP1:32::DIV.fmt +"div.%s<FMT> f<FD>, f<FS>, f<FT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format)); + } +} + + +// DMFC1 +// DMTC1 +010001,00,X,01,5.RT,5.FS,00000000000:COP1Sa:64::DMxC1 +"dm%s<X>c1 r<RT>, f<FS>" +*mipsIII: +{ + if (X) + { + if (SizeFGR() == 64) + PENDING_FILL((FS + FGRIDX),GPR[RT]); + else if ((FS & 0x1) == 0) + { + PENDING_FILL(((FS + 1) + FGRIDX),VH4_8(GPR[RT])); + PENDING_FILL((FS + FGRIDX),VL4_8(GPR[RT])); + } + } + else + { + if (SizeFGR() == 64) + PENDING_FILL(RT,FGR[FS]); + else if ((FS & 0x1) == 0) + PENDING_FILL(RT,(SET64HI(FGR[FS+1]) | FGR[FS])); + else + PENDING_FILL(RT,SET64HI(0xDEADC0DE) | 0xBAD0BAD0); + } +} +010001,00,X,01,5.RT,5.FS,00000000000:COP1Sb:64::DMxC1 +"dm%s<X>c1 r<RT>, f<FS>" +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + if (X) + { + if (SizeFGR() == 64) + StoreFPR (FS, fmt_uninterpreted_64, GPR[RT]); + else if ((FS & 0x1) == 0) + StoreFPR (FS, fmt_uninterpreted_64, SET64HI (FGR[FS+1]) | FGR[FS]); + } + else + { + if (SizeFGR() == 64) + GPR[RT] = FGR[FS]; + else if ((FS & 0x1) == 0) + GPR[RT] = SET64HI (FGR[FS+1]) | FGR[FS]; + else + GPR[RT] = SET64HI (0xDEADC0DE) | 0xBAD0BAD0; + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001011:COP1:64::FLOOR.L.fmt +"floor.l.%s<FMT> f<FD>, f<FS>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_long,Convert(FP_RM_TOMINF,ValueFPR(fs,format),format,fmt_long)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001111:COP1:32::FLOOR.W.fmt +"floor.w.%s<FMT> f<FD>, f<FS>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_word,Convert(FP_RM_TOMINF,ValueFPR(fs,format),format,fmt_word)); + } +} + + +110101,5.BASE,5.FT,16.OFFSET:COP1:64::LDC1 +"ldc1 f<FT>, <OFFSET>(r<BASE>)" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + COP_LD (1, FT, do_load (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET))); +} + + +010011,5.BASE,5.INDEX,5.0,5.FD,000001:COP1X:64::LDXC1 +"ldxc1 f<FD>, r<INDEX>(r<BASE>)" +*mipsIV: +*vr5000: +{ + COP_LD (1, FD, do_load (SD_, AccessLength_DOUBLEWORD, GPR[BASE], GPR[INDEX])); +} + + + +110001,5.BASE,5.FT,16.OFFSET:COP1:32::LWC1 +"lwc1 f<FT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + COP_LW (1, FT, do_load (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET))); +} + + +010011,5.BASE,5.INDEX,5.0,5.FD,000000:COP1X:32::LWXC1 +"lwxc1 f<FD>, r<INDEX>(r<BASE>)" +*mipsIV: +*vr5000: +{ + COP_LW (1, FD, do_load (SD_, AccessLength_WORD, GPR[BASE], GPR[INDEX])); +} + + + +// +// FIXME: Not correct for mips* +// +010011,5.FR,5.FT,5.FS,5.FD,100,001:COP1X:32,f::MADD.D +"madd.d f<FD>, f<FR>, f<FS>, f<FT>" +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_double,Add(Multiply(ValueFPR(fs,fmt_double),ValueFPR(ft,fmt_double),fmt_double),ValueFPR(fr,fmt_double),fmt_double)); + } +} + + +010011,5.FR,5.FT,5.FS,5.FD,100,000:COP1X:32,f::MADD.S +"madd.s f<FD>, f<FR>, f<FS>, f<FT>" +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_single,Add(Multiply(ValueFPR(fs,fmt_single),ValueFPR(ft,fmt_single),fmt_single),ValueFPR(fr,fmt_single),fmt_single)); + } +} + + +// MFC1 +// MTC1 +010001,00,X,00,5.RT,5.FS,00000000000:COP1Sa:32::MxC1 +"m%s<X>c1 r<RT>, f<FS>" +*mipsI: +*mipsII: +*mipsIII: +{ + if (X) + { /*MTC1*/ + if (SizeFGR() == 64) + PENDING_FILL ((FS + FGRIDX), (SET64HI(0xDEADC0DE) | VL4_8(GPR[RT]))); + else + PENDING_FILL ((FS + FGRIDX), VL4_8(GPR[RT])); + } + else /*MFC1*/ + PENDING_FILL (RT, SIGNEXTEND(FGR[FS],32)); +} +010001,00,X,00,5.RT,5.FS,00000000000:COP1Sb:32::MxC1 +"m%s<X>c1 r<RT>, f<FS>" +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + int fs = FS; + if (X) + /*MTC1*/ + StoreFPR (FS, fmt_uninterpreted_32, VL4_8 (GPR[RT])); + else /*MFC1*/ + GPR[RT] = SIGNEXTEND(FGR[FS],32); +} + + +010001,10,3.FMT,00000,5.FS,5.FD,000110:COP1:32::MOV.fmt +"mov.%s<FMT> f<FD>, f<FS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + StoreFPR(destreg,format,ValueFPR(fs,format)); + } +} + + +// MOVF +000000,5.RS,3.CC,0,1.TF,5.RD,00000000001:SPECIAL:32::MOVtf +"mov%s<TF> r<RD>, r<RS>, <CC>" +*mipsIV: +*vr5000: +{ + if (GETFCC(CC) == TF) + GPR[RD] = GPR[RS]; +} + + +// MOVF.fmt +010001,10,3.FMT,3.CC,0,1.TF,5.FS,5.FD,010001:COP1:32::MOVtf.fmt +"mov%s<TF>.%s<FMT> f<FD>, f<FS>, <CC>" +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int format = ((instruction >> 21) & 0x00000007); + { + if (GETFCC(CC) == TF) + StoreFPR (FD, format, ValueFPR (FS, format)); + else + StoreFPR (FD, format, ValueFPR (FD, format)); + } +} + + +010001,10,3.FMT,5.RT,5.FS,5.FD,010011:COP1:32::MOVN.fmt +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + StoreFPR(destreg,format,ValueFPR(fs,format)); + } +} + + +// MOVT see MOVtf + + +// MOVT.fmt see MOVtf.fmt + + + +010001,10,3.FMT,5.RT,5.FS,5.FD,010010:COP1:32::MOVZ.fmt +"movz.%s<FMT> f<FD>, f<FS>, r<RT>" +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + StoreFPR(destreg,format,ValueFPR(fs,format)); + } +} + + +// MSUB.fmt +010011,5.FR,5.FT,5.FS,5.FD,101,001:COP1X:32::MSUB.D +"msub.d f<FD>, f<FR>, f<FS>, f<FT>" +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_double,Sub(Multiply(ValueFPR(fs,fmt_double),ValueFPR(ft,fmt_double),fmt_double),ValueFPR(fr,fmt_double),fmt_double)); + } +} + + +// MSUB.fmt +010011,5.FR,5.FT,5.FS,5.FD,101000:COP1X:32::MSUB.S +"msub.s f<FD>, f<FR>, f<FS>, f<FT>" +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_single,Sub(Multiply(ValueFPR(fs,fmt_single),ValueFPR(ft,fmt_single),fmt_single),ValueFPR(fr,fmt_single),fmt_single)); + } +} + + +// MTC1 see MxC1 + + +010001,10,3.FMT,5.FT,5.FS,5.FD,000010:COP1:32::MUL.fmt +"mul.%s<FMT> f<FD>, f<FS>, f<FT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,000111:COP1:32::NEG.fmt +"neg.%s<FMT> f<FD>, f<FS>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format)); + } +} + + +// NMADD.fmt +010011,5.FR,5.FT,5.FS,5.FD,110001:COP1X:32::NMADD.D +"nmadd.d f<FD>, f<FR>, f<FS>, f<FT>" +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_double,Negate(Add(Multiply(ValueFPR(fs,fmt_double),ValueFPR(ft,fmt_double),fmt_double),ValueFPR(fr,fmt_double),fmt_double),fmt_double)); + } +} + + +// NMADD.fmt +010011,5.FR,5.FT,5.FS,5.FD,110000:COP1X:32::NMADD.S +"nmadd.s f<FD>, f<FR>, f<FS>, f<FT>" +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_single,Negate(Add(Multiply(ValueFPR(fs,fmt_single),ValueFPR(ft,fmt_single),fmt_single),ValueFPR(fr,fmt_single),fmt_single),fmt_single)); + } +} + + +// NMSUB.fmt +010011,5.FR,5.FT,5.FS,5.FD,111001:COP1X:32::NMSUB.D +"nmsub.d f<FD>, f<FR>, f<FS>, f<FT>" +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_double,Negate(Sub(Multiply(ValueFPR(fs,fmt_double),ValueFPR(ft,fmt_double),fmt_double),ValueFPR(fr,fmt_double),fmt_double),fmt_double)); + } +} + + +// NMSUB.fmt +010011,5.FR,5.FT,5.FS,5.FD,111000:COP1X:32::NMSUB.S +"nmsub.s f<FD>, f<FR>, f<FS>, f<FT>" +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_single,Negate(Sub(Multiply(ValueFPR(fs,fmt_single),ValueFPR(ft,fmt_single),fmt_single),ValueFPR(fr,fmt_single),fmt_single),fmt_single)); + } +} + + +010011,5.BASE,5.INDEX,5.HINT,00000001111:COP1X:32::PREFX +"prefx <HINT>, r<INDEX>(r<BASE>)" +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int fs = ((instruction >> 11) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + (unsigned64)op2); + address_word paddr; + int uncached; + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + Prefetch(uncached,paddr,vaddr,isDATA,fs); + } +} + +010001,10,3.FMT,00000,5.FS,5.FD,010101:COP1:32::RECIP.fmt +*mipsIV: +"recip.%s<FMT> f<FD>, f<FS>" +*vr5000: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001000:COP1:64::ROUND.L.fmt +"round.l.%s<FMT> f<FD>, f<FS>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_long,Convert(FP_RM_NEAREST,ValueFPR(fs,format),format,fmt_long)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001100:COP1:32::ROUND.W.fmt +"round.w.%s<FMT> f<FD>, f<FS>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_word,Convert(FP_RM_NEAREST,ValueFPR(fs,format),format,fmt_word)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,010110:COP1:32::RSQRT.fmt +*mipsIV: +"rsqrt.%s<FMT> f<FD>, f<FS>" +*vr5000: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,Recip(SquareRoot(ValueFPR(fs,format),format),format)); + } +} + + +111101,5.BASE,5.FT,16.OFFSET:COP1:64::SDC1 +"sdc1 f<FT>, <OFFSET>(r<BASE>)" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + do_store (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET), COP_SD (1, FT)); +} + + +010011,5.BASE,5.INDEX,5.FS,00000001001:COP1X:64::SDXC1 +"ldxc1 f<FS>, r<INDEX>(r<BASE>)" +*mipsIV: +*vr5000: +{ + do_store (SD_, AccessLength_DOUBLEWORD, GPR[BASE], GPR[INDEX], COP_SD (1, FS)); +} + + +010001,10,3.FMT,00000,5.FS,5.FD,000100:COP1:32::SQRT.fmt +"sqrt.%s<FMT> f<FD>, f<FS>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,(SquareRoot(ValueFPR(fs,format),format))); + } +} + + +010001,10,3.FMT,5.FT,5.FS,5.FD,000001:COP1:32::SUB.fmt +"sub.%s<FMT> f<FD>, f<FS>, f<FT>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format)); + } +} + + + +111001,5.BASE,5.FT,16.OFFSET:COP1:32::SWC1 +"swc1 f<FT>, <OFFSET>(r<BASE>)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + signed_word offset = EXTEND16 (OFFSET); + int destreg UNUSED = ((instruction >> 16) & 0x0000001F); + signed_word op1 UNUSED = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((uword64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + { + SIM_CORE_SIGNAL (SD, CPU, cia, read_map, AccessLength_WORD+1, vaddr, write_transfer, sim_core_unaligned_signal); + } + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + uword64 memval = 0; + uword64 memval1 = 0; + uword64 mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); + address_word reverseendian = (ReverseEndian ?(mask ^ AccessLength_WORD): 0); + address_word bigendiancpu = (BigEndianCPU ?(mask ^ AccessLength_WORD): 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian)); + byte = ((vaddr & mask) ^ bigendiancpu); + memval = (((uword64)COP_SW(((instruction >> 26) & 0x3),destreg)) << (8 * byte)); + StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } +} + + +010011,5.BASE,5.INDEX,5.FS,00000,001000:COP1X:32::SWXC1 +"swxc1 f<FS>, r<INDEX>(r<BASE>)" +*mipsIV: +*vr5000: +{ + unsigned32 instruction = instruction_0; + int fs = ((instruction >> 11) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + op2); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + { + SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, write_transfer, sim_core_unaligned_signal); + } + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2))); + byte = ((vaddr & mask) ^ (BigEndianCPU << 2)); + memval = (((unsigned64)COP_SW(1,fs)) << (8 * byte)); + { + StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001001:COP1:64::TRUNC.L.fmt +"trunc.l.%s<FMT> f<FD>, f<FS>" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_long,Convert(FP_RM_TOZERO,ValueFPR(fs,format),format,fmt_long)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001101:COP1:32::TRUNC.W +"trunc.w.%s<FMT> f<FD>, f<FS>" +*mipsII: +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_word,Convert(FP_RM_TOZERO,ValueFPR(fs,format),format,fmt_word)); + } +} + + +// +// MIPS Architecture: +// +// System Control Instruction Set (COP0) +// + + +010000,01000,00000,16.OFFSET:COP0:32::BC0F +"bc0f <OFFSET>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: + + +010000,01000,00010,16.OFFSET:COP0:32::BC0FL +"bc0fl <OFFSET>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: + + +010000,01000,00001,16.OFFSET:COP0:32::BC0T +"bc0t <OFFSET>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: + + +010000,01000,00011,16.OFFSET:COP0:32::BC0TL +"bc0tl <OFFSET>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: + + +101111,5.BASE,5.OP,16.OFFSET:NORMAL:32::CACHE +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int hint = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = (op1 + offset); + address_word paddr; + int uncached; + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + CacheOp(hint,vaddr,paddr,instruction); + } +} + + +010000,10000,000000000000000,111001:COP0:32::DI +"di" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: + + +010000,10000,000000000000000,111000:COP0:32::EI +"ei" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: + + +010000,10000,000000000000000,011000:COP0:32::ERET +"eret" +*mipsIII: +*mipsIV: +*vr4100: +*vr5000: +{ + if (SR & status_ERL) + { + /* Oops, not yet available */ + sim_io_printf (SD, "Warning: ERET when SR[ERL] set not supported"); + NIA = EPC; + SR &= ~status_ERL; + } + else + { + NIA = EPC; + SR &= ~status_EXL; + } +} + + +010000,00000,5.RT,5.RD,00000,6.REGX:COP0:32::MFC0 +"mfc0 r<RT>, r<RD> # <REGX>" +*mipsI,mipsII,mipsIII,mipsIV: +*r3900: +*vr4100: +*vr5000: +{ + TRACE_ALU_INPUT0 (); + DecodeCoproc (instruction_0); + TRACE_ALU_RESULT (GPR[RT]); +} + +010000,00100,5.RT,5.RD,00000,6.REGX:COP0:32::MTC0 +"mtc0 r<RT>, r<RD> # <REGX>" +*mipsI,mipsII,mipsIII,mipsIV: +*r3900: +*vr4100: +*vr5000: +{ + DecodeCoproc (instruction_0); +} + + +010000,10000,000000000000000,010000:COP0:32::RFE +"rfe" +*mipsI,mipsII,mipsIII,mipsIV: +*r3900: +*vr4100: +*vr5000: +{ + DecodeCoproc (instruction_0); +} + + +0100,ZZ!0!1!3,5.COP_FUN0!8,5.COP_FUN1,16.COP_FUN2:NORMAL:32::COPz +"cop<ZZ> <COP_FUN0><COP_FUN1><COP_FUN2>" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*r3900: +{ + DecodeCoproc (instruction_0); +} + + + +010000,10000,000000000000000,001000:COP0:32::TLBP +"tlbp" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: + + +010000,10000,000000000000000,000001:COP0:32::TLBR +"tlbr" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: + + +010000,10000,000000000000000,000010:COP0:32::TLBWI +"tlbwi" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: + + +010000,10000,000000000000000,000110:COP0:32::TLBWR +"tlbwr" +*mipsI,mipsII,mipsIII,mipsIV: +*vr4100: +*vr5000: + + +:include:::m16.igen +:include:::tx.igen +:include:::vr.igen + diff --git a/sim/mips/sim-main.c b/sim/mips/sim-main.c new file mode 100644 index 0000000..58e63dc --- /dev/null +++ b/sim/mips/sim-main.c @@ -0,0 +1,579 @@ +/* Copyright (C) 1998, Cygnus Solutions + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef SIM_MAIN_C +#define SIM_MAIN_C + +#include "sim-main.h" +#include "sim-assert.h" + + +/*---------------------------------------------------------------------------*/ +/*-- simulator engine -------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + + +/* Description from page A-22 of the "MIPS IV Instruction Set" manual + (revision 3.1) */ +/* Translate a virtual address to a physical address and cache + coherence algorithm describing the mechanism used to resolve the + memory reference. Given the virtual address vAddr, and whether the + reference is to Instructions ot Data (IorD), find the corresponding + physical address (pAddr) and the cache coherence algorithm (CCA) + used to resolve the reference. If the virtual address is in one of + the unmapped address spaces the physical address and the CCA are + determined directly by the virtual address. If the virtual address + is in one of the mapped address spaces then the TLB is used to + determine the physical address and access type; if the required + translation is not present in the TLB or the desired access is not + permitted the function fails and an exception is taken. + + NOTE: Normally (RAW == 0), when address translation fails, this + function raises an exception and does not return. */ + +INLINE_SIM_MAIN +(int) +address_translation (SIM_DESC sd, + sim_cpu * cpu, + address_word cia, + address_word vAddr, + int IorD, + int LorS, + address_word * pAddr, + int *CCA, + int raw) +{ + int res = -1; /* TRUE : Assume good return */ + +#ifdef DEBUG + sim_io_printf (sd, "AddressTranslation(0x%s,%s,%s,...);\n", pr_addr (vAddr), (IorD ? "isDATA" : "isINSTRUCTION"), (LorS ? "iSTORE" : "isLOAD")); +#endif + + /* Check that the address is valid for this memory model */ + + /* For a simple (flat) memory model, we simply pass virtual + addressess through (mostly) unchanged. */ + vAddr &= 0xFFFFFFFF; + + *pAddr = vAddr; /* default for isTARGET */ + *CCA = Uncached; /* not used for isHOST */ + + return (res); +} + + + +/* Description from page A-23 of the "MIPS IV Instruction Set" manual + (revision 3.1) */ +/* Prefetch data from memory. Prefetch is an advisory instruction for + which an implementation specific action is taken. The action taken + may increase performance, but must not change the meaning of the + program, or alter architecturally-visible state. */ + +INLINE_SIM_MAIN (void) +prefetch (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + int CCA, + address_word pAddr, + address_word vAddr, + int DATA, + int hint) +{ +#ifdef DEBUG + sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint); +#endif /* DEBUG */ + + /* For our simple memory model we do nothing */ + return; +} + +/* Description from page A-22 of the "MIPS IV Instruction Set" manual + (revision 3.1) */ +/* Load a value from memory. Use the cache and main memory as + specified in the Cache Coherence Algorithm (CCA) and the sort of + access (IorD) to find the contents of AccessLength memory bytes + starting at physical location pAddr. The data is returned in the + fixed width naturally-aligned memory element (MemElem). The + low-order two (or three) bits of the address and the AccessLength + indicate which of the bytes within MemElem needs to be given to the + processor. If the memory access type of the reference is uncached + then only the referenced bytes are read from memory and valid + within the memory element. If the access type is cached, and the + data is not present in cache, an implementation specific size and + alignment block of memory is read and loaded into the cache to + satisfy a load reference. At a minimum, the block is the entire + memory element. */ +INLINE_SIM_MAIN (void) +load_memory (SIM_DESC SD, + sim_cpu *CPU, + address_word cia, + uword64* memvalp, + uword64* memval1p, + int CCA, + unsigned int AccessLength, + address_word pAddr, + address_word vAddr, + int IorD) +{ + uword64 value = 0; + uword64 value1 = 0; + +#ifdef DEBUG + sim_io_printf(sd,"DBG: LoadMemory(%p,%p,%d,%d,0x%s,0x%s,%s)\n",memvalp,memval1p,CCA,AccessLength,pr_addr(pAddr),pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION")); +#endif /* DEBUG */ + +#if defined(WARN_MEM) + if (CCA != uncached) + sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA); +#endif /* WARN_MEM */ + + if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK) + { + /* In reality this should be a Bus Error */ + sim_io_error (SD, "LOAD AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n", + AccessLength, + (LOADDRMASK + 1) << 3, + pr_addr (pAddr)); + } + +#if defined(TRACE) + dotrace (SD, CPU, tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction")); +#endif /* TRACE */ + + /* Read the specified number of bytes from memory. Adjust for + host/target byte ordering/ Align the least significant byte + read. */ + + switch (AccessLength) + { + case AccessLength_QUADWORD : + { + unsigned_16 val = sim_core_read_aligned_16 (CPU, NULL_CIA, read_map, pAddr); + value1 = VH8_16 (val); + value = VL8_16 (val); + break; + } + case AccessLength_DOUBLEWORD : + value = sim_core_read_aligned_8 (CPU, NULL_CIA, + read_map, pAddr); + break; + case AccessLength_SEPTIBYTE : + value = sim_core_read_misaligned_7 (CPU, NULL_CIA, + read_map, pAddr); + break; + case AccessLength_SEXTIBYTE : + value = sim_core_read_misaligned_6 (CPU, NULL_CIA, + read_map, pAddr); + break; + case AccessLength_QUINTIBYTE : + value = sim_core_read_misaligned_5 (CPU, NULL_CIA, + read_map, pAddr); + break; + case AccessLength_WORD : + value = sim_core_read_aligned_4 (CPU, NULL_CIA, + read_map, pAddr); + break; + case AccessLength_TRIPLEBYTE : + value = sim_core_read_misaligned_3 (CPU, NULL_CIA, + read_map, pAddr); + break; + case AccessLength_HALFWORD : + value = sim_core_read_aligned_2 (CPU, NULL_CIA, + read_map, pAddr); + break; + case AccessLength_BYTE : + value = sim_core_read_aligned_1 (CPU, NULL_CIA, + read_map, pAddr); + break; + default: + abort (); + } + +#ifdef DEBUG + printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n", + (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value)); +#endif /* DEBUG */ + + /* See also store_memory. Position data in correct byte lanes. */ + if (AccessLength <= LOADDRMASK) + { + if (BigEndianMem) + /* for big endian target, byte (pAddr&LOADDRMASK == 0) is + shifted to the most significant byte position. */ + value <<= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8); + else + /* For little endian target, byte (pAddr&LOADDRMASK == 0) + is already in the correct postition. */ + value <<= ((pAddr & LOADDRMASK) * 8); + } + +#ifdef DEBUG + printf("DBG: LoadMemory() : shifted value = 0x%s%s\n", + pr_uword64(value1),pr_uword64(value)); +#endif /* DEBUG */ + + *memvalp = value; + if (memval1p) *memval1p = value1; +} + + +/* Description from page A-23 of the "MIPS IV Instruction Set" manual + (revision 3.1) */ +/* Store a value to memory. The specified data is stored into the + physical location pAddr using the memory hierarchy (data caches and + main memory) as specified by the Cache Coherence Algorithm + (CCA). The MemElem contains the data for an aligned, fixed-width + memory element (word for 32-bit processors, doubleword for 64-bit + processors), though only the bytes that will actually be stored to + memory need to be valid. The low-order two (or three) bits of pAddr + and the AccessLength field indicates which of the bytes within the + MemElem data should actually be stored; only these bytes in memory + will be changed. */ + +INLINE_SIM_MAIN (void) +store_memory (SIM_DESC SD, + sim_cpu *CPU, + address_word cia, + int CCA, + unsigned int AccessLength, + uword64 MemElem, + uword64 MemElem1, /* High order 64 bits */ + address_word pAddr, + address_word vAddr) +{ +#ifdef DEBUG + sim_io_printf(sd,"DBG: StoreMemory(%d,%d,0x%s,0x%s,0x%s,0x%s)\n",CCA,AccessLength,pr_uword64(MemElem),pr_uword64(MemElem1),pr_addr(pAddr),pr_addr(vAddr)); +#endif /* DEBUG */ + +#if defined(WARN_MEM) + if (CCA != uncached) + sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA); +#endif /* WARN_MEM */ + + if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK) + sim_io_error (SD, "STORE AccessLength of %d would extend over %d bit aligned boundary for physical address 0x%s\n", + AccessLength, + (LOADDRMASK + 1) << 3, + pr_addr(pAddr)); + +#if defined(TRACE) + dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store"); +#endif /* TRACE */ + +#ifdef DEBUG + printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem)); +#endif /* DEBUG */ + + /* See also load_memory. Position data in correct byte lanes. */ + if (AccessLength <= LOADDRMASK) + { + if (BigEndianMem) + /* for big endian target, byte (pAddr&LOADDRMASK == 0) is + shifted to the most significant byte position. */ + MemElem >>= (((LOADDRMASK - (pAddr & LOADDRMASK)) - AccessLength) * 8); + else + /* For little endian target, byte (pAddr&LOADDRMASK == 0) + is already in the correct postition. */ + MemElem >>= ((pAddr & LOADDRMASK) * 8); + } + +#ifdef DEBUG + printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem)); +#endif /* DEBUG */ + + switch (AccessLength) + { + case AccessLength_QUADWORD : + { + unsigned_16 val = U16_8 (MemElem1, MemElem); + sim_core_write_aligned_16 (CPU, NULL_CIA, write_map, pAddr, val); + break; + } + case AccessLength_DOUBLEWORD : + sim_core_write_aligned_8 (CPU, NULL_CIA, + write_map, pAddr, MemElem); + break; + case AccessLength_SEPTIBYTE : + sim_core_write_misaligned_7 (CPU, NULL_CIA, + write_map, pAddr, MemElem); + break; + case AccessLength_SEXTIBYTE : + sim_core_write_misaligned_6 (CPU, NULL_CIA, + write_map, pAddr, MemElem); + break; + case AccessLength_QUINTIBYTE : + sim_core_write_misaligned_5 (CPU, NULL_CIA, + write_map, pAddr, MemElem); + break; + case AccessLength_WORD : + sim_core_write_aligned_4 (CPU, NULL_CIA, + write_map, pAddr, MemElem); + break; + case AccessLength_TRIPLEBYTE : + sim_core_write_misaligned_3 (CPU, NULL_CIA, + write_map, pAddr, MemElem); + break; + case AccessLength_HALFWORD : + sim_core_write_aligned_2 (CPU, NULL_CIA, + write_map, pAddr, MemElem); + break; + case AccessLength_BYTE : + sim_core_write_aligned_1 (CPU, NULL_CIA, + write_map, pAddr, MemElem); + break; + default: + abort (); + } + + return; +} + + +INLINE_SIM_MAIN (unsigned32) +ifetch32 (SIM_DESC SD, + sim_cpu *CPU, + address_word cia, + address_word vaddr) +{ + /* Copy the action of the LW instruction */ + address_word mask = LOADDRMASK; + address_word access = AccessLength_WORD; + address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0); + address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0); + unsigned int byte; + address_word paddr; + int uncached; + unsigned64 memval; + + if ((vaddr & access) != 0) + SignalExceptionInstructionFetch (); + AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL); + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian)); + LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL); + byte = ((vaddr & mask) ^ bigendiancpu); + return (memval >> (8 * byte)); +} + + +INLINE_SIM_MAIN (unsigned16) +ifetch16 (SIM_DESC SD, + sim_cpu *CPU, + address_word cia, + address_word vaddr) +{ + /* Copy the action of the LH instruction */ + address_word mask = LOADDRMASK; + address_word access = AccessLength_HALFWORD; + address_word reverseendian = (ReverseEndian ? (mask ^ access) : 0); + address_word bigendiancpu = (BigEndianCPU ? (mask ^ access) : 0); + unsigned int byte; + address_word paddr; + int uncached; + unsigned64 memval; + + if ((vaddr & access) != 0) + SignalExceptionInstructionFetch (); + AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL); + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian)); + LoadMemory (&memval, NULL, uncached, access, paddr, vaddr, isINSTRUCTION, isREAL); + byte = ((vaddr & mask) ^ bigendiancpu); + return (memval >> (8 * byte)); +} + + + +/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */ +/* Order loads and stores to synchronise shared memory. Perform the + action necessary to make the effects of groups of synchronizable + loads and stores indicated by stype occur in the same order for all + processors. */ +INLINE_SIM_MAIN (void) +sync_operation (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + int stype) +{ +#ifdef DEBUG + sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype); +#endif /* DEBUG */ + return; +} + +INLINE_SIM_MAIN (void) +cache_op (SIM_DESC SD, + sim_cpu *CPU, + address_word cia, + int op, + address_word pAddr, + address_word vAddr, + unsigned int instruction) +{ +#if 1 /* stop warning message being displayed (we should really just remove the code) */ + static int icache_warning = 1; + static int dcache_warning = 1; +#else + static int icache_warning = 0; + static int dcache_warning = 0; +#endif + + /* If CP0 is not useable (User or Supervisor mode) and the CP0 + enable bit in the Status Register is clear - a coprocessor + unusable exception is taken. */ +#if 0 + sim_io_printf(SD,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia)); +#endif + + switch (op & 0x3) { + case 0: /* instruction cache */ + switch (op >> 2) { + case 0: /* Index Invalidate */ + case 1: /* Index Load Tag */ + case 2: /* Index Store Tag */ + case 4: /* Hit Invalidate */ + case 5: /* Fill */ + case 6: /* Hit Writeback */ + if (!icache_warning) + { + sim_io_eprintf(SD,"Instruction CACHE operation %d to be coded\n",(op >> 2)); + icache_warning = 1; + } + break; + + default: + SignalException(ReservedInstruction,instruction); + break; + } + break; + + case 1: /* data cache */ + switch (op >> 2) { + case 0: /* Index Writeback Invalidate */ + case 1: /* Index Load Tag */ + case 2: /* Index Store Tag */ + case 3: /* Create Dirty */ + case 4: /* Hit Invalidate */ + case 5: /* Hit Writeback Invalidate */ + case 6: /* Hit Writeback */ + if (!dcache_warning) + { + sim_io_eprintf(SD,"Data CACHE operation %d to be coded\n",(op >> 2)); + dcache_warning = 1; + } + break; + + default: + SignalException(ReservedInstruction,instruction); + break; + } + break; + + default: /* unrecognised cache ID */ + SignalException(ReservedInstruction,instruction); + break; + } + + return; +} + + +INLINE_SIM_MAIN (void) +pending_tick (SIM_DESC SD, + sim_cpu *CPU, + address_word cia) +{ + if (PENDING_TRACE) + sim_io_eprintf (SD, "PENDING_DRAIN - 0x%lx - pending_in = %d, pending_out = %d, pending_total = %d\n", (unsigned long) cia, PENDING_IN, PENDING_OUT, PENDING_TOTAL); + if (PENDING_OUT != PENDING_IN) + { + int loop; + int index = PENDING_OUT; + int total = PENDING_TOTAL; + if (PENDING_TOTAL == 0) + sim_engine_abort (SD, CPU, cia, "PENDING_DRAIN - Mis-match on pending update pointers\n"); + for (loop = 0, index = PENDING_OUT; + (loop < total); + loop++, index = (index + 1) % PSLOTS) + { + if (PENDING_SLOT_DEST[index] != NULL) + { + PENDING_SLOT_DELAY[index] -= 1; + if (PENDING_SLOT_DELAY[index] == 0) + { + if (PENDING_TRACE) + sim_io_eprintf (SD, "PENDING_DRAIN - drained - index %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n", + index, + (unsigned long) PENDING_SLOT_DEST[index], + PENDING_SLOT_BIT[index], + (unsigned long) PENDING_SLOT_VALUE[index], + PENDING_SLOT_SIZE[index]); + if (PENDING_SLOT_BIT[index] >= 0) + switch (PENDING_SLOT_SIZE[index]) + { + case 4: + if (PENDING_SLOT_VALUE[index]) + *(unsigned32*)PENDING_SLOT_DEST[index] |= + BIT32 (PENDING_SLOT_BIT[index]); + else + *(unsigned32*)PENDING_SLOT_DEST[index] &= + BIT32 (PENDING_SLOT_BIT[index]); + break; + case 8: + if (PENDING_SLOT_VALUE[index]) + *(unsigned64*)PENDING_SLOT_DEST[index] |= + BIT64 (PENDING_SLOT_BIT[index]); + else + *(unsigned64*)PENDING_SLOT_DEST[index] &= + BIT64 (PENDING_SLOT_BIT[index]); + break; + } + else + switch (PENDING_SLOT_SIZE[index]) + { + case 4: + *(unsigned32*)PENDING_SLOT_DEST[index] = + PENDING_SLOT_VALUE[index]; + break; + case 8: + *(unsigned64*)PENDING_SLOT_DEST[index] = + PENDING_SLOT_VALUE[index]; + break; + } + if (PENDING_OUT == index) + { + PENDING_SLOT_DEST[index] = NULL; + PENDING_OUT = (PENDING_OUT + 1) % PSLOTS; + PENDING_TOTAL--; + } + } + else if (PENDING_TRACE && PENDING_SLOT_DELAY[index] > 0) + sim_io_eprintf (SD, "PENDING_DRAIN - queued - index %d, delay %d, dest 0x%lx, bit %d, val 0x%lx, size %d\n", + index, PENDING_SLOT_DELAY[index], + (unsigned long) PENDING_SLOT_DEST[index], + PENDING_SLOT_BIT[index], + (unsigned long) PENDING_SLOT_VALUE[index], + PENDING_SLOT_SIZE[index]); + + } + } + } +} + + +#endif diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h new file mode 100644 index 0000000..6b6a6f9 --- /dev/null +++ b/sim/mips/sim-main.h @@ -0,0 +1,785 @@ +/* MIPS Simulator definition. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +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 2, 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, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef SIM_MAIN_H +#define SIM_MAIN_H + +/* This simulator doesn't cache the Current Instruction Address */ +/* #define SIM_ENGINE_HALT_HOOK(SD, LAST_CPU, CIA) */ +/* #define SIM_ENGINE_RESUME_HOOK(SD, LAST_CPU, CIA) */ + +#define SIM_HAVE_BIENDIAN + + +/* hobble some common features for moment */ +#define WITH_WATCHPOINTS 1 +#define WITH_MODULO_MEMORY 1 + + +#define SIM_CORE_SIGNAL(SD,CPU,CIA,MAP,NR_BYTES,ADDR,TRANSFER,ERROR) \ +mips_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), (TRANSFER), (ERROR)) + +#include "sim-basics.h" + +typedef address_word sim_cia; + +#include "sim-base.h" + + +/* Depreciated macros and types for manipulating 64bit values. Use + ../common/sim-bits.h and ../common/sim-endian.h macros instead. */ + +typedef signed64 word64; +typedef unsigned64 uword64; + +#define WORD64LO(t) (unsigned int)((t)&0xFFFFFFFF) +#define WORD64HI(t) (unsigned int)(((uword64)(t))>>32) +#define SET64LO(t) (((uword64)(t))&0xFFFFFFFF) +#define SET64HI(t) (((uword64)(t))<<32) +#define WORD64(h,l) ((word64)((SET64HI(h)|SET64LO(l)))) +#define UWORD64(h,l) (SET64HI(h)|SET64LO(l)) + +/* Sign-extend the given value (e) as a value (b) bits long. We cannot + assume the HI32bits of the operand are zero, so we must perform a + mask to ensure we can use the simple subtraction to sign-extend. */ +#define SIGNEXTEND(e,b) \ + ((unsigned_word) \ + (((e) & ((uword64) 1 << ((b) - 1))) \ + ? (((e) & (((uword64) 1 << (b)) - 1)) - ((uword64)1 << (b))) \ + : ((e) & (((((uword64) 1 << ((b) - 1)) - 1) << 1) | 1)))) + +/* Check if a value will fit within a halfword: */ +#define NOTHALFWORDVALUE(v) ((((((uword64)(v)>>16) == 0) && !((v) & ((unsigned)1 << 15))) || (((((uword64)(v)>>32) == 0xFFFFFFFF) && ((((uword64)(v)>>16) & 0xFFFF) == 0xFFFF)) && ((v) & ((unsigned)1 << 15)))) ? (1 == 0) : (1 == 1)) + + + +/* Floating-point operations: */ + +#include "sim-fpu.h" + +/* FPU registers must be one of the following types. All other values + are reserved (and undefined). */ +typedef enum { + fmt_single = 0, + fmt_double = 1, + fmt_word = 4, + fmt_long = 5, + /* The following are well outside the normal acceptable format + range, and are used in the register status vector. */ + fmt_unknown = 0x10000000, + fmt_uninterpreted = 0x20000000, + fmt_uninterpreted_32 = 0x40000000, + fmt_uninterpreted_64 = 0x80000000U, +} FP_formats; + +unsigned64 value_fpr PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int fpr, FP_formats)); +#define ValueFPR(FPR,FMT) value_fpr (SD, CPU, cia, (FPR), (FMT)) + +void store_fpr PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int fpr, FP_formats fmt, unsigned64 value)); +#define StoreFPR(FPR,FMT,VALUE) store_fpr (SD, CPU, cia, (FPR), (FMT), (VALUE)) + +int NaN PARAMS ((unsigned64 op, FP_formats fmt)); +int Infinity PARAMS ((unsigned64 op, FP_formats fmt)); +int Less PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +int Equal PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 AbsoluteValue PARAMS ((unsigned64 op, FP_formats fmt)); +unsigned64 Negate PARAMS ((unsigned64 op, FP_formats fmt)); +unsigned64 Add PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Sub PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Multiply PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Divide PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Recip PARAMS ((unsigned64 op, FP_formats fmt)); +unsigned64 SquareRoot PARAMS ((unsigned64 op, FP_formats fmt)); +unsigned64 Max PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Min PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 convert PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int rm, unsigned64 op, FP_formats from, FP_formats to)); +#define Convert(rm,op,from,to) \ +convert (SD, CPU, cia, rm, op, from, to) + +/* Macro to update FPSR condition-code field. This is complicated by + the fact that there is a hole in the index range of the bits within + the FCSR register. Also, the number of bits visible depends on the + MIPS ISA version being supported. */ + +#define SETFCC(cc,v) {\ + int bit = ((cc == 0) ? 23 : (24 + (cc)));\ + FCSR = ((FCSR & ~(1 << bit)) | ((v) << bit));\ +} +#define GETFCC(cc) (((((cc) == 0) ? (FCSR & (1 << 23)) : (FCSR & (1 << (24 + (cc))))) != 0) ? 1U : 0) + +/* This should be the COC1 value at the start of the preceding + instruction: */ +#define PREVCOC1() ((STATE & simPCOC1) ? 1 : 0) + +#ifdef TARGET_ENABLE_FR +/* FIXME: this should be enabled for all targets, but needs testing first. */ +#define SizeFGR() (((WITH_TARGET_FLOATING_POINT_BITSIZE) == 64) \ + ? ((SR & status_FR) ? 64 : 32) \ + : (WITH_TARGET_FLOATING_POINT_BITSIZE)) +#else +#define SizeFGR() (WITH_TARGET_FLOATING_POINT_BITSIZE) +#endif + +/* Standard FCRS bits: */ +#define IR (0) /* Inexact Result */ +#define UF (1) /* UnderFlow */ +#define OF (2) /* OverFlow */ +#define DZ (3) /* Division by Zero */ +#define IO (4) /* Invalid Operation */ +#define UO (5) /* Unimplemented Operation */ + +/* Get masks for individual flags: */ +#if 1 /* SAFE version */ +#define FP_FLAGS(b) (((unsigned)(b) < 5) ? (1 << ((b) + 2)) : 0) +#define FP_ENABLE(b) (((unsigned)(b) < 5) ? (1 << ((b) + 7)) : 0) +#define FP_CAUSE(b) (((unsigned)(b) < 6) ? (1 << ((b) + 12)) : 0) +#else +#define FP_FLAGS(b) (1 << ((b) + 2)) +#define FP_ENABLE(b) (1 << ((b) + 7)) +#define FP_CAUSE(b) (1 << ((b) + 12)) +#endif + +#define FP_FS (1 << 24) /* MIPS III onwards : Flush to Zero */ + +#define FP_MASK_RM (0x3) +#define FP_SH_RM (0) +#define FP_RM_NEAREST (0) /* Round to nearest (Round) */ +#define FP_RM_TOZERO (1) /* Round to zero (Trunc) */ +#define FP_RM_TOPINF (2) /* Round to Plus infinity (Ceil) */ +#define FP_RM_TOMINF (3) /* Round to Minus infinity (Floor) */ +#define GETRM() (int)((FCSR >> FP_SH_RM) & FP_MASK_RM) + + + + + + +/* HI/LO register accesses */ + +/* For some MIPS targets, the HI/LO registers have certain timing + restrictions in that, for instance, a read of a HI register must be + separated by at least three instructions from a preceeding read. + + The struct below is used to record the last access by each of A MT, + MF or other OP instruction to a HI/LO register. See mips.igen for + more details. */ + +typedef struct _hilo_access { + signed64 timestamp; + address_word cia; +} hilo_access; + +typedef struct _hilo_history { + hilo_access mt; + hilo_access mf; + hilo_access op; +} hilo_history; + + + + +/* Integer ALU operations: */ + +#include "sim-alu.h" + +#define ALU32_END(ANS) \ + if (ALU32_HAD_OVERFLOW) \ + SignalExceptionIntegerOverflow (); \ + (ANS) = (signed32) ALU32_OVERFLOW_RESULT + + +#define ALU64_END(ANS) \ + if (ALU64_HAD_OVERFLOW) \ + SignalExceptionIntegerOverflow (); \ + (ANS) = ALU64_OVERFLOW_RESULT; + + + + + +/* The following is probably not used for MIPS IV onwards: */ +/* Slots for delayed register updates. For the moment we just have a + fixed number of slots (rather than a more generic, dynamic + system). This keeps the simulator fast. However, we only allow + for the register update to be delayed for a single instruction + cycle. */ +#define PSLOTS (8) /* Maximum number of instruction cycles */ + +typedef struct _pending_write_queue { + int in; + int out; + int total; + int slot_delay[PSLOTS]; + int slot_size[PSLOTS]; + int slot_bit[PSLOTS]; + void *slot_dest[PSLOTS]; + unsigned64 slot_value[PSLOTS]; +} pending_write_queue; + +#ifndef PENDING_TRACE +#define PENDING_TRACE 0 +#endif +#define PENDING_IN ((CPU)->pending.in) +#define PENDING_OUT ((CPU)->pending.out) +#define PENDING_TOTAL ((CPU)->pending.total) +#define PENDING_SLOT_SIZE ((CPU)->pending.slot_size) +#define PENDING_SLOT_BIT ((CPU)->pending.slot_bit) +#define PENDING_SLOT_DELAY ((CPU)->pending.slot_delay) +#define PENDING_SLOT_DEST ((CPU)->pending.slot_dest) +#define PENDING_SLOT_VALUE ((CPU)->pending.slot_value) + +/* Invalidate the pending write queue, all pending writes are + discarded. */ + +#define PENDING_INVALIDATE() \ +memset (&(CPU)->pending, 0, sizeof ((CPU)->pending)) + +/* Schedule a write to DEST for N cycles time. For 64 bit + destinations, schedule two writes. For floating point registers, + the caller should schedule a write to both the dest register and + the FPR_STATE register. When BIT is non-negative, only BIT of DEST + is updated. */ + +#define PENDING_SCHED(DEST,VAL,DELAY,BIT) \ + do { \ + if (PENDING_SLOT_DEST[PENDING_IN] != NULL) \ + sim_engine_abort (SD, CPU, cia, \ + "PENDING_SCHED - buffer overflow\n"); \ + if (PENDING_TRACE) \ + sim_io_eprintf (SD, "PENDING_SCHED - 0x%lx - dest 0x%lx, val 0x%lx, bit %d, size %d, pending_in %d, pending_out %d, pending_total %d\n", \ + (unsigned long) cia, (unsigned long) &(DEST), \ + (unsigned long) (VAL), (BIT), (int) sizeof (DEST),\ + PENDING_IN, PENDING_OUT, PENDING_TOTAL); \ + PENDING_SLOT_DELAY[PENDING_IN] = (DELAY) + 1; \ + PENDING_SLOT_DEST[PENDING_IN] = &(DEST); \ + PENDING_SLOT_VALUE[PENDING_IN] = (VAL); \ + PENDING_SLOT_SIZE[PENDING_IN] = sizeof (DEST); \ + PENDING_SLOT_BIT[PENDING_IN] = (BIT); \ + PENDING_IN = (PENDING_IN + 1) % PSLOTS; \ + PENDING_TOTAL += 1; \ + } while (0) + +#define PENDING_WRITE(DEST,VAL,DELAY) PENDING_SCHED(DEST,VAL,DELAY,-1) +#define PENDING_BIT(DEST,VAL,DELAY,BIT) PENDING_SCHED(DEST,VAL,DELAY,BIT) + +#define PENDING_TICK() pending_tick (SD, CPU, cia) + +#define PENDING_FLUSH() abort () /* think about this one */ +#define PENDING_FP() abort () /* think about this one */ + +/* For backward compatibility */ +#define PENDING_FILL(R,VAL) \ +do { \ + if ((R) >= FGRIDX && (R) < FGRIDX + NR_FGR) \ + { \ + PENDING_SCHED(FGR[(R) - FGRIDX], VAL, 1, -1); \ + PENDING_SCHED(FPR_STATE[(R) - FGRIDX], fmt_uninterpreted, 1, -1); \ + } \ + else \ + PENDING_SCHED(GPR[(R)], VAL, 1, -1); \ +} while (0) + + + +struct _sim_cpu { + + + /* The following are internal simulator state variables: */ +#define CIA_GET(CPU) ((CPU)->registers[PCIDX] + 0) +#define CIA_SET(CPU,CIA) ((CPU)->registers[PCIDX] = (CIA)) + address_word dspc; /* delay-slot PC */ +#define DSPC ((CPU)->dspc) + +#define DELAY_SLOT(TARGET) NIA = delayslot32 (SD_, (TARGET)) +#define NULLIFY_NEXT_INSTRUCTION() NIA = nullify_next_insn32 (SD_) + + + /* State of the simulator */ + unsigned int state; + unsigned int dsstate; +#define STATE ((CPU)->state) +#define DSSTATE ((CPU)->dsstate) + +/* Flags in the "state" variable: */ +#define simHALTEX (1 << 2) /* 0 = run; 1 = halt on exception */ +#define simHALTIN (1 << 3) /* 0 = run; 1 = halt on interrupt */ +#define simTRACE (1 << 8) /* 0 = do nothing; 1 = trace address activity */ +#define simPCOC0 (1 << 17) /* COC[1] from current */ +#define simPCOC1 (1 << 18) /* COC[1] from previous */ +#define simDELAYSLOT (1 << 24) /* 0 = do nothing; 1 = delay slot entry exists */ +#define simSKIPNEXT (1 << 25) /* 0 = do nothing; 1 = skip instruction */ +#define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */ +#define simJALDELAYSLOT (1 << 29) /* 1 = in jal delay slot */ + +#define ENGINE_ISSUE_PREFIX_HOOK() \ + { \ + /* Perform any pending writes */ \ + PENDING_TICK(); \ + /* Set previous flag, depending on current: */ \ + if (STATE & simPCOC0) \ + STATE |= simPCOC1; \ + else \ + STATE &= ~simPCOC1; \ + /* and update the current value: */ \ + if (GETFCC(0)) \ + STATE |= simPCOC0; \ + else \ + STATE &= ~simPCOC0; \ + } + + +/* This is nasty, since we have to rely on matching the register + numbers used by GDB. Unfortunately, depending on the MIPS target + GDB uses different register numbers. We cannot just include the + relevant "gdb/tm.h" link, since GDB may not be configured before + the sim world, and also the GDB header file requires too much other + state. */ + +#ifndef TM_MIPS_H +#define LAST_EMBED_REGNUM (89) +#define NUM_REGS (LAST_EMBED_REGNUM + 1) + + +#endif + + +enum float_operation + { + FLOP_ADD, FLOP_SUB, FLOP_MUL, FLOP_MADD, + FLOP_MSUB, FLOP_MAX=10, FLOP_MIN, FLOP_ABS, + FLOP_ITOF0=14, FLOP_FTOI0=18, FLOP_NEG=23 + }; + +/* To keep this default simulator simple, and fast, we use a direct + vector of registers. The internal simulator engine then uses + manifests to access the correct slot. */ + + unsigned_word registers[LAST_EMBED_REGNUM + 1]; + + int register_widths[NUM_REGS]; +#define REGISTERS ((CPU)->registers) + +#define GPR (®ISTERS[0]) +#define GPR_SET(N,VAL) (REGISTERS[(N)] = (VAL)) + + /* While space is allocated for the floating point registers in the + main registers array, they are stored separatly. This is because + their size may not necessarily match the size of either the + general-purpose or system specific registers */ +#define NR_FGR (32) +#define FGRIDX (38) + fp_word fgr[NR_FGR]; +#define FGR ((CPU)->fgr) + +#define LO (REGISTERS[33]) +#define HI (REGISTERS[34]) +#define PCIDX 37 +#define PC (REGISTERS[PCIDX]) +#define CAUSE (REGISTERS[36]) +#define SRIDX (32) +#define SR (REGISTERS[SRIDX]) /* CPU status register */ +#define FCR0IDX (71) +#define FCR0 (REGISTERS[FCR0IDX]) /* really a 32bit register */ +#define FCR31IDX (70) +#define FCR31 (REGISTERS[FCR31IDX]) /* really a 32bit register */ +#define FCSR (FCR31) +#define Debug (REGISTERS[86]) +#define DEPC (REGISTERS[87]) +#define EPC (REGISTERS[88]) +#define COCIDX (LAST_EMBED_REGNUM + 2) /* special case : outside the normal range */ + + /* All internal state modified by signal_exception() that may need to be + rolled back for passing moment-of-exception image back to gdb. */ + unsigned_word exc_trigger_registers[LAST_EMBED_REGNUM + 1]; + unsigned_word exc_suspend_registers[LAST_EMBED_REGNUM + 1]; + int exc_suspended; + +#define SIM_CPU_EXCEPTION_TRIGGER(SD,CPU,CIA) mips_cpu_exception_trigger(SD,CPU,CIA) +#define SIM_CPU_EXCEPTION_SUSPEND(SD,CPU,EXC) mips_cpu_exception_suspend(SD,CPU,EXC) +#define SIM_CPU_EXCEPTION_RESUME(SD,CPU,EXC) mips_cpu_exception_resume(SD,CPU,EXC) + + unsigned_word c0_config_reg; +#define C0_CONFIG ((CPU)->c0_config_reg) + +/* The following are pseudonyms for standard registers */ +#define ZERO (REGISTERS[0]) +#define V0 (REGISTERS[2]) +#define A0 (REGISTERS[4]) +#define A1 (REGISTERS[5]) +#define A2 (REGISTERS[6]) +#define A3 (REGISTERS[7]) +#define T8IDX 24 +#define T8 (REGISTERS[T8IDX]) +#define SPIDX 29 +#define SP (REGISTERS[SPIDX]) +#define RAIDX 31 +#define RA (REGISTERS[RAIDX]) + + /* While space is allocated in the main registers arrray for some of + the COP0 registers, that space isn't sufficient. Unknown COP0 + registers overflow into the array below */ + +#define NR_COP0_GPR 32 + unsigned_word cop0_gpr[NR_COP0_GPR]; +#define COP0_GPR ((CPU)->cop0_gpr) +#define COP0_BADVADDR ((unsigned32)(COP0_GPR[8])) + + /* Keep the current format state for each register: */ + FP_formats fpr_state[32]; +#define FPR_STATE ((CPU)->fpr_state) + + pending_write_queue pending; + + /* LLBIT = Load-Linked bit. A bit of "virtual" state used by atomic + read-write instructions. It is set when a linked load occurs. It + is tested and cleared by the conditional store. It is cleared + (during other CPU operations) when a store to the location would + no longer be atomic. In particular, it is cleared by exception + return instructions. */ + int llbit; +#define LLBIT ((CPU)->llbit) + + +/* The HIHISTORY and LOHISTORY timestamps are used to ensure that + corruptions caused by using the HI or LO register too close to a + following operation is spotted. See mips.igen for more details. */ + + hilo_history hi_history; +#define HIHISTORY (&(CPU)->hi_history) + hilo_history lo_history; +#define LOHISTORY (&(CPU)->lo_history) + +#define check_branch_bug() +#define mark_branch_bug(TARGET) + + + + sim_cpu_base base; +}; + + +/* MIPS specific simulator watch config */ + +void watch_options_install PARAMS ((SIM_DESC sd)); + +struct swatch { + sim_event *pc; + sim_event *clock; + sim_event *cycles; +}; + + +/* FIXME: At present much of the simulator is still static */ +struct sim_state { + + struct swatch watch; + + sim_cpu cpu[MAX_NR_PROCESSORS]; +#if (WITH_SMP) +#define STATE_CPU(sd,n) (&(sd)->cpu[n]) +#else +#define STATE_CPU(sd,n) (&(sd)->cpu[0]) +#endif + + + sim_state_base base; +}; + + + +/* Status information: */ + +/* TODO : these should be the bitmasks for these bits within the + status register. At the moment the following are VR4300 + bit-positions: */ +#define status_KSU_mask (0x18) /* mask for KSU bits */ +#define status_KSU_shift (3) /* shift for field */ +#define ksu_kernel (0x0) +#define ksu_supervisor (0x1) +#define ksu_user (0x2) +#define ksu_unknown (0x3) + +#define SR_KSU ((SR & status_KSU_mask) >> status_KSU_shift) + +#define status_IE (1 << 0) /* Interrupt enable */ +#define status_EIE (1 << 16) /* Enable Interrupt Enable */ +#define status_EXL (1 << 1) /* Exception level */ +#define status_RE (1 << 25) /* Reverse Endian in user mode */ +#define status_FR (1 << 26) /* enables MIPS III additional FP registers */ +#define status_SR (1 << 20) /* soft reset or NMI */ +#define status_BEV (1 << 22) /* Location of general exception vectors */ +#define status_TS (1 << 21) /* TLB shutdown has occurred */ +#define status_ERL (1 << 2) /* Error level */ +#define status_IM7 (1 << 15) /* Timer Interrupt Mask */ +#define status_RP (1 << 27) /* Reduced Power mode */ + +/* Specializations for TX39 family */ +#define status_IEc (1 << 0) /* Interrupt enable (current) */ +#define status_KUc (1 << 1) /* Kernel/User mode */ +#define status_IEp (1 << 2) /* Interrupt enable (previous) */ +#define status_KUp (1 << 3) /* Kernel/User mode */ +#define status_IEo (1 << 4) /* Interrupt enable (old) */ +#define status_KUo (1 << 5) /* Kernel/User mode */ +#define status_IM_mask (0xff) /* Interrupt mask */ +#define status_IM_shift (8) +#define status_NMI (1 << 20) /* NMI */ +#define status_NMI (1 << 20) /* NMI */ + +#define cause_BD ((unsigned)1 << 31) /* L1 Exception in branch delay slot */ +#define cause_BD2 (1 << 30) /* L2 Exception in branch delay slot */ +#define cause_CE_mask 0x30000000 /* Coprocessor exception */ +#define cause_CE_shift 28 +#define cause_EXC2_mask 0x00070000 +#define cause_EXC2_shift 16 +#define cause_IP7 (1 << 15) /* Interrupt pending */ +#define cause_SIOP (1 << 12) /* SIO pending */ +#define cause_IP3 (1 << 11) /* Int 0 pending */ +#define cause_IP2 (1 << 10) /* Int 1 pending */ + +#define cause_EXC_mask (0x1c) /* Exception code */ +#define cause_EXC_shift (2) + +#define cause_SW0 (1 << 8) /* Software interrupt 0 */ +#define cause_SW1 (1 << 9) /* Software interrupt 1 */ +#define cause_IP_mask (0x3f) /* Interrupt pending field */ +#define cause_IP_shift (10) + +#define cause_set_EXC(x) CAUSE = (CAUSE & ~cause_EXC_mask) | ((x << cause_EXC_shift) & cause_EXC_mask) +#define cause_set_EXC2(x) CAUSE = (CAUSE & ~cause_EXC2_mask) | ((x << cause_EXC2_shift) & cause_EXC2_mask) + + +/* NOTE: We keep the following status flags as bit values (1 for true, + 0 for false). This allows them to be used in binary boolean + operations without worrying about what exactly the non-zero true + value is. */ + +/* UserMode */ +#ifdef SUBTARGET_R3900 +#define UserMode ((SR & status_KUc) ? 1 : 0) +#else +#define UserMode ((((SR & status_KSU_mask) >> status_KSU_shift) == ksu_user) ? 1 : 0) +#endif /* SUBTARGET_R3900 */ + +/* BigEndianMem */ +/* Hardware configuration. Affects endianness of LoadMemory and + StoreMemory and the endianness of Kernel and Supervisor mode + execution. The value is 0 for little-endian; 1 for big-endian. */ +#define BigEndianMem (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) +/*(state & simBE) ? 1 : 0)*/ + +/* ReverseEndian */ +/* This mode is selected if in User mode with the RE bit being set in + SR (Status Register). It reverses the endianness of load and store + instructions. */ +#define ReverseEndian (((SR & status_RE) && UserMode) ? 1 : 0) + +/* BigEndianCPU */ +/* The endianness for load and store instructions (0=little;1=big). In + User mode this endianness may be switched by setting the state_RE + bit in the SR register. Thus, BigEndianCPU may be computed as + (BigEndianMem EOR ReverseEndian). */ +#define BigEndianCPU (BigEndianMem ^ ReverseEndian) /* Already bits */ + + + +/* Exceptions: */ + +/* NOTE: These numbers depend on the processor architecture being + simulated: */ +enum ExceptionCause { + Interrupt = 0, + TLBModification = 1, + TLBLoad = 2, + TLBStore = 3, + AddressLoad = 4, + AddressStore = 5, + InstructionFetch = 6, + DataReference = 7, + SystemCall = 8, + BreakPoint = 9, + ReservedInstruction = 10, + CoProcessorUnusable = 11, + IntegerOverflow = 12, /* Arithmetic overflow (IDT monitor raises SIGFPE) */ + Trap = 13, + FPE = 15, + DebugBreakPoint = 16, + Watch = 23, + NMIReset = 31, + + +/* The following exception code is actually private to the simulator + world. It is *NOT* a processor feature, and is used to signal + run-time errors in the simulator. */ + SimulatorFault = 0xFFFFFFFF +}; + +#define TLB_REFILL (0) +#define TLB_INVALID (1) + + +/* The following break instructions are reserved for use by the + simulator. The first is used to halt the simulation. The second + is used by gdb for break-points. NOTE: Care must be taken, since + this value may be used in later revisions of the MIPS ISA. */ +#define HALT_INSTRUCTION_MASK (0x03FFFFC0) + +#define HALT_INSTRUCTION (0x03ff000d) +#define HALT_INSTRUCTION2 (0x0000ffcd) + + +#define BREAKPOINT_INSTRUCTION (0x0005000d) +#define BREAKPOINT_INSTRUCTION2 (0x0000014d) + + + +void interrupt_event (SIM_DESC sd, void *data); + +void signal_exception (SIM_DESC sd, sim_cpu *cpu, address_word cia, int exception, ...); +#define SignalException(exc,instruction) signal_exception (SD, CPU, cia, (exc), (instruction)) +#define SignalExceptionInterrupt(level) signal_exception (SD, CPU, cia, Interrupt, level) +#define SignalExceptionInstructionFetch() signal_exception (SD, CPU, cia, InstructionFetch) +#define SignalExceptionAddressStore() signal_exception (SD, CPU, cia, AddressStore) +#define SignalExceptionAddressLoad() signal_exception (SD, CPU, cia, AddressLoad) +#define SignalExceptionDataReference() signal_exception (SD, CPU, cia, DataReference) +#define SignalExceptionSimulatorFault(buf) signal_exception (SD, CPU, cia, SimulatorFault, buf) +#define SignalExceptionFPE() signal_exception (SD, CPU, cia, FPE) +#define SignalExceptionIntegerOverflow() signal_exception (SD, CPU, cia, IntegerOverflow) +#define SignalExceptionCoProcessorUnusable() signal_exception (SD, CPU, cia, CoProcessorUnusable) +#define SignalExceptionNMIReset() signal_exception (SD, CPU, cia, NMIReset) +#define SignalExceptionTLBRefillStore() signal_exception (SD, CPU, cia, TLBStore, TLB_REFILL) +#define SignalExceptionTLBRefillLoad() signal_exception (SD, CPU, cia, TLBLoad, TLB_REFILL) +#define SignalExceptionTLBInvalidStore() signal_exception (SD, CPU, cia, TLBStore, TLB_INVALID) +#define SignalExceptionTLBInvalidLoad() signal_exception (SD, CPU, cia, TLBLoad, TLB_INVALID) +#define SignalExceptionTLBModification() signal_exception (SD, CPU, cia, TLBModification) + +/* Co-processor accesses */ + +void cop_lw PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg, unsigned int memword)); +void cop_ld PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg, uword64 memword)); +unsigned int cop_sw PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg)); +uword64 cop_sd PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg)); + +#define COP_LW(coproc_num,coproc_reg,memword) \ +cop_lw (SD, CPU, cia, coproc_num, coproc_reg, memword) +#define COP_LD(coproc_num,coproc_reg,memword) \ +cop_ld (SD, CPU, cia, coproc_num, coproc_reg, memword) +#define COP_SW(coproc_num,coproc_reg) \ +cop_sw (SD, CPU, cia, coproc_num, coproc_reg) +#define COP_SD(coproc_num,coproc_reg) \ +cop_sd (SD, CPU, cia, coproc_num, coproc_reg) + + +void decode_coproc PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, unsigned int instruction)); +#define DecodeCoproc(instruction) \ +decode_coproc (SD, CPU, cia, (instruction)) + +void sim_monitor (SIM_DESC sd, sim_cpu *cpu, address_word cia, unsigned int arg); + + + +/* Memory accesses */ + +/* The following are generic to all versions of the MIPS architecture + to date: */ + +/* Memory Access Types (for CCA): */ +#define Uncached (0) +#define CachedNoncoherent (1) +#define CachedCoherent (2) +#define Cached (3) + +#define isINSTRUCTION (1 == 0) /* FALSE */ +#define isDATA (1 == 1) /* TRUE */ +#define isLOAD (1 == 0) /* FALSE */ +#define isSTORE (1 == 1) /* TRUE */ +#define isREAL (1 == 0) /* FALSE */ +#define isRAW (1 == 1) /* TRUE */ +/* The parameter HOST (isTARGET / isHOST) is ignored */ +#define isTARGET (1 == 0) /* FALSE */ +/* #define isHOST (1 == 1) TRUE */ + +/* The "AccessLength" specifications for Loads and Stores. NOTE: This + is the number of bytes minus 1. */ +#define AccessLength_BYTE (0) +#define AccessLength_HALFWORD (1) +#define AccessLength_TRIPLEBYTE (2) +#define AccessLength_WORD (3) +#define AccessLength_QUINTIBYTE (4) +#define AccessLength_SEXTIBYTE (5) +#define AccessLength_SEPTIBYTE (6) +#define AccessLength_DOUBLEWORD (7) +#define AccessLength_QUADWORD (15) + +#define LOADDRMASK (WITH_TARGET_WORD_BITSIZE == 64 \ + ? AccessLength_DOUBLEWORD /*7*/ \ + : AccessLength_WORD /*3*/) +#define PSIZE (WITH_TARGET_ADDRESS_BITSIZE) + + +INLINE_SIM_MAIN (int) address_translation PARAMS ((SIM_DESC sd, sim_cpu *, address_word cia, address_word vAddr, int IorD, int LorS, address_word *pAddr, int *CCA, int raw)); +#define AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw) \ +address_translation (SD, CPU, cia, vAddr, IorD, LorS, pAddr, CCA, raw) + +INLINE_SIM_MAIN (void) load_memory PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, uword64* memvalp, uword64* memval1p, int CCA, unsigned int AccessLength, address_word pAddr, address_word vAddr, int IorD)); +#define LoadMemory(memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw) \ +load_memory (SD, CPU, cia, memvalp, memval1p, CCA, AccessLength, pAddr, vAddr, IorD) + +INLINE_SIM_MAIN (void) store_memory PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int CCA, unsigned int AccessLength, uword64 MemElem, uword64 MemElem1, address_word pAddr, address_word vAddr)); +#define StoreMemory(CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw) \ +store_memory (SD, CPU, cia, CCA, AccessLength, MemElem, MemElem1, pAddr, vAddr) + +INLINE_SIM_MAIN (void) cache_op PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int op, address_word pAddr, address_word vAddr, unsigned int instruction)); +#define CacheOp(op,pAddr,vAddr,instruction) \ +cache_op (SD, CPU, cia, op, pAddr, vAddr, instruction) + +INLINE_SIM_MAIN (void) sync_operation PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int stype)); +#define SyncOperation(stype) \ +sync_operation (SD, CPU, cia, (stype)) + +INLINE_SIM_MAIN (void) prefetch PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int CCA, address_word pAddr, address_word vAddr, int DATA, int hint)); +#define Prefetch(CCA,pAddr,vAddr,DATA,hint) \ +prefetch (SD, CPU, cia, CCA, pAddr, vAddr, DATA, hint) + +INLINE_SIM_MAIN (unsigned32) ifetch32 PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, address_word vaddr)); +#define IMEM32(CIA) ifetch32 (SD, CPU, (CIA), (CIA)) +INLINE_SIM_MAIN (unsigned16) ifetch16 PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, address_word vaddr)); +#define IMEM16(CIA) ifetch16 (SD, CPU, (CIA), ((CIA) & ~1)) +#define IMEM16_IMMED(CIA,NR) ifetch16 (SD, CPU, (CIA), ((CIA) & ~1) + 2 * (NR)) + +void dotrace PARAMS ((SIM_DESC sd, sim_cpu *cpu, FILE *tracefh, int type, SIM_ADDR address, int width, char *comment, ...)); +extern FILE *tracefh; + +INLINE_SIM_MAIN (void) pending_tick PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia)); +extern SIM_CORE_SIGNAL_FN mips_core_signal; + +char* pr_addr PARAMS ((SIM_ADDR addr)); +char* pr_uword64 PARAMS ((uword64 addr)); + + +void mips_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word pc); +void mips_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception); +void mips_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception); + + +#if H_REVEALS_MODULE_P (SIM_MAIN_INLINE) +#include "sim-main.c" +#endif + +#endif diff --git a/sim/mips/tconfig.in b/sim/mips/tconfig.in new file mode 100644 index 0000000..e8062a3 --- /dev/null +++ b/sim/mips/tconfig.in @@ -0,0 +1,31 @@ +/* mips target configuration file. */ + +/* See sim-hload.c. We properly handle LMA. */ +#ifdef TARGET_TX3904 +#define SIM_HANDLES_LMA 1 + +/* FIXME: This is unnecessarily necessary: */ +#include "ansidecl.h" +#include "callback.h" +#include "remote-sim.h" +#include "sim-module.h" + +MODULE_INSTALL_FN dv_sockser_install; +#define MODULE_LIST dv_sockser_install, +#endif + +/* Define this if the simulator supports profiling. + See the mips simulator for an example. + This enables the `-p foo' and `-s bar' options. + The target is required to provide sim_set_profile{,_size}. */ +#define SIM_HAVE_PROFILE + +/* Define this if the simulator uses an instruction cache. + See the h8/300 simulator for an example. + This enables the `-c size' option to set the size of the cache. + The target is required to provide sim_set_simcache_size. */ +/* #define SIM_HAVE_SIMCACHE */ + +/* Define this if the target cpu is bi-endian + and the simulator supports it. */ +#define SIM_HAVE_BIENDIAN diff --git a/sim/mips/tx.igen b/sim/mips/tx.igen new file mode 100644 index 0000000..1727ecc --- /dev/null +++ b/sim/mips/tx.igen @@ -0,0 +1,41 @@ +// -*- C -*- +// +// toshiba specific instructions. +// + +011100,5.RS,5.RT,5.RD,00000000000:MMINORM:::MADD +"madd r<RS>, r<RT>":RD == 0 +"madd r<RD>, r<RS>, r<RT>" +*r3900 +{ + signed64 prod = (U8_4 (VL4_8 (HI), VL4_8 (LO)) + + ((signed64) EXTEND32 (GPR[RT]) + * (signed64) EXTEND32 (GPR[RS]))); + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + LO = EXTEND32 (prod); + HI = EXTEND32 (VH4_8 (prod)); + TRACE_ALU_RESULT2 (HI, LO); + if(RD != 0 ) + GPR[RD] = LO; +} + + +011100,5.RS,5.RT,5.RD,00000000001:MMINORM:::MADDU +"maddu r<RS>, r<RT>":RD == 0 +"maddu r<RD>, r<RS>, r<RT>" +*r3900 +{ + unsigned64 prod = (U8_4 (VL4_8 (HI), VL4_8 (LO)) + + ((unsigned64) VL4_8 (GPR[RS]) + * (unsigned64) VL4_8 (GPR[RT]))); + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + LO = EXTEND32 (prod); + HI = EXTEND32 (VH4_8 (prod)); + TRACE_ALU_RESULT2 (HI, LO); + if(RD != 0) + GPR[RD] = LO; +} + + diff --git a/sim/mips/vr.igen b/sim/mips/vr.igen new file mode 100644 index 0000000..863bb55 --- /dev/null +++ b/sim/mips/vr.igen @@ -0,0 +1,78 @@ +// -*- C -*- +// +// NEC specific instructions +// + +// Integer Instructions +// -------------------- +// +// MulAcc is the Multiply Accumulator. +// This register is mapped on the the HI and LO registers. +// Upper 32 bits of MulAcc is mapped on to lower 32 bits of HI register. +// Lower 32 bits of MulAcc is mapped on to lower 32 bits of LO register. + + +:function:::unsigned64:MulAcc: +*vr4100: +{ + unsigned64 result = U8_4 (HI, LO); + return result; +} + +:function:::void:SET_MulAcc:unsigned64 value +*vr4100: +{ + /* 64 bit specific */ + *AL4_8 (&HI) = VH4_8 (value); + *AL4_8 (&LO) = VL4_8 (value); +} + +:function:::signed64:SignedMultiply:signed32 l, signed32 r +*vr4100: +{ + signed64 result = (signed64) l * (signed64) r; + return result; +} + +:function:::unsigned64:UnsignedMultiply:unsigned32 l, unsigned32 r +*vr4100: +{ + unsigned64 result = (unsigned64) l * (unsigned64) r; + return result; +} + +:function:::unsigned64:Low32Bits:unsigned64 value +*vr4100: +{ + unsigned64 result = (signed64) (signed32) VL4_8 (value); + return result; +} + +:function:::unsigned64:High32Bits:unsigned64 value +*vr4100: +{ + unsigned64 result = (signed64) (signed32) VH4_8 (value); + return result; +} + + + +// Multiply, Accumulate +000000,5.RS,5.RT,00000,00000,101000::64::MAC +"mac r<RS>, r<RT>" +*vr4100: +{ + SET_MulAcc (SD_, MulAcc (SD_) + SignedMultiply (SD_, GPR[RS], GPR[RT])); +} + + +// D-Multiply, Accumulate +000000,5.RS,5.RT,00000,00000,101001::64::DMAC +"dmac r<RS>, r<RT>" +*vr4100: +{ + LO = LO + SignedMultiply (SD_, GPR[RS], GPR[RT]); +} + + + |