Home | History | Annotate | Line # | Download | only in iq2000
      1 /* IQ2000 simulator support code
      2    Copyright (C) 2000-2024 Free Software Foundation, Inc.
      3    Contributed by Cygnus Support.
      4 
      5    This file is part of the GNU simulators.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19 
     20 /* This must come before any other includes.  */
     21 #include "defs.h"
     22 
     23 #define WANT_CPU
     24 #define WANT_CPU_IQ2000BF
     25 
     26 #include "sim-main.h"
     27 #include "sim-signal.h"
     28 #include "cgen-mem.h"
     29 #include "cgen-ops.h"
     30 #include "target-newlib-syscall.h"
     31 #include <stdlib.h>
     32 
     33 enum
     34 {
     35   GPR0_REGNUM = 0,
     36   NR_GPR = 32,
     37   PC_REGNUM = 32
     38 };
     39 
     40 /* Read a null terminated string from memory, return in a buffer */
     41 static char *
     42 fetch_str (SIM_CPU *current_cpu, PCADDR pc, DI addr)
     43 {
     44   char *buf;
     45   int nr = 0;
     46   while (sim_core_read_1 (current_cpu,
     47                           pc, read_map, CPU2DATA(addr + nr)) != 0)
     48     nr++;
     49   buf = NZALLOC (char, nr + 1);
     50   sim_read (CPU_STATE (current_cpu), CPU2DATA(addr), buf, nr);
     51   return buf;
     52 }
     53 
     54 void
     55 do_syscall (SIM_CPU *current_cpu, PCADDR pc)
     56 {
     57 #if 0
     58   int syscall = H2T_4 (iq2000bf_h_gr_get (current_cpu, 11));
     59 #endif
     60   int syscall_function = iq2000bf_h_gr_get (current_cpu, 4);
     61   char *buf;
     62   int PARM1 = iq2000bf_h_gr_get (current_cpu, 5);
     63   int PARM2 = iq2000bf_h_gr_get (current_cpu, 6);
     64   int PARM3 = iq2000bf_h_gr_get (current_cpu, 7);
     65   const int ret_reg = 2;
     66 
     67   switch (syscall_function)
     68     {
     69     case 0:
     70       switch (H2T_4 (iq2000bf_h_gr_get (current_cpu, 11)))
     71 	{
     72 	case 0:
     73 	  /* Pass.  */
     74 	  puts ("pass");
     75 	  exit (0);
     76 	case 1:
     77 	  /* Fail.  */
     78 	  puts ("fail");
     79 	  exit (1);
     80 	default:
     81 	  puts ("unknown exit");
     82 	  exit (2);
     83 	}
     84 
     85     case TARGET_NEWLIB_SYS_write:
     86       buf = zalloc (PARM3);
     87       sim_read (CPU_STATE (current_cpu), CPU2DATA(PARM2), buf, PARM3);
     88       SET_H_GR (ret_reg,
     89 		sim_io_write (CPU_STATE (current_cpu),
     90 			      PARM1, buf, PARM3));
     91       free (buf);
     92       break;
     93 
     94     case TARGET_NEWLIB_SYS_lseek:
     95       SET_H_GR (ret_reg,
     96 		sim_io_lseek (CPU_STATE (current_cpu),
     97 			      PARM1, PARM2, PARM3));
     98       break;
     99 
    100     case TARGET_NEWLIB_SYS_exit:
    101       sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
    102 		       NULL, pc, sim_exited, PARM1);
    103       break;
    104 
    105     case TARGET_NEWLIB_SYS_read:
    106       buf = zalloc (PARM3);
    107       SET_H_GR (ret_reg,
    108 		sim_io_read (CPU_STATE (current_cpu),
    109 			     PARM1, buf, PARM3));
    110       sim_write (CPU_STATE (current_cpu), CPU2DATA(PARM2),
    111 		 (unsigned char *) buf, PARM3);
    112       free (buf);
    113       break;
    114 
    115     case TARGET_NEWLIB_SYS_open:
    116       buf = fetch_str (current_cpu, pc, PARM1);
    117       SET_H_GR (ret_reg,
    118 		sim_io_open (CPU_STATE (current_cpu),
    119 			     buf, PARM2));
    120       free (buf);
    121       break;
    122 
    123     case TARGET_NEWLIB_SYS_close:
    124       SET_H_GR (ret_reg,
    125 		sim_io_close (CPU_STATE (current_cpu), PARM1));
    126       break;
    127 
    128     case TARGET_NEWLIB_SYS_time:
    129       SET_H_GR (ret_reg, time (0));
    130       break;
    131 
    132     default:
    133       SET_H_GR (ret_reg, -1);
    134     }
    135 }
    136 
    137 void
    138 do_break (SIM_CPU *current_cpu, PCADDR pc)
    139 {
    140   SIM_DESC sd = CPU_STATE (current_cpu);
    141   sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
    142 }
    143 
    144 /* The semantic code invokes this for invalid (unrecognized) instructions.  */
    145 
    146 SEM_PC
    147 sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
    148 {
    149   SIM_DESC sd = CPU_STATE (current_cpu);
    150   sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
    151 
    152   return vpc;
    153 }
    154 
    155 
    156 /* Process an address exception.  */
    157 
    158 void
    159 iq2000_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
    160                   unsigned int map, int nr_bytes, address_word addr,
    161                   transfer_type transfer, sim_core_signals sig)
    162 {
    163   sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr,
    164 		   transfer, sig);
    165 }
    166 
    167 
    168 /* Initialize cycle counting for an insn.
    169    FIRST_P is non-zero if this is the first insn in a set of parallel
    170    insns.  */
    171 
    172 void
    173 iq2000bf_model_insn_before (SIM_CPU *cpu, int first_p)
    174 {
    175   /* Do nothing.  */
    176 }
    177 
    178 
    179 /* Record the cycles computed for an insn.
    180    LAST_P is non-zero if this is the last insn in a set of parallel insns,
    181    and we update the total cycle count.
    182    CYCLES is the cycle count of the insn.  */
    183 
    184 void
    185 iq2000bf_model_insn_after(SIM_CPU *cpu, int last_p, int cycles)
    186 {
    187   /* Do nothing.  */
    188 }
    189 
    190 
    191 int
    192 iq2000bf_model_iq2000_u_exec (SIM_CPU *cpu, const IDESC *idesc,
    193 			    int unit_num, int referenced)
    194 {
    195   return idesc->timing->units[unit_num].done;
    196 }
    197 
    198 PCADDR
    199 get_h_pc (SIM_CPU *cpu)
    200 {
    201   return CPU_CGEN_HW(cpu)->h_pc;
    202 }
    203 
    204 void
    205 set_h_pc (SIM_CPU *cpu, PCADDR addr)
    206 {
    207   CPU_CGEN_HW(cpu)->h_pc = addr | IQ2000_INSN_MASK;
    208 }
    209 
    210 int
    211 iq2000bf_fetch_register (SIM_CPU *cpu, int nr, void *buf, int len)
    212 {
    213   if (nr >= GPR0_REGNUM
    214       && nr < (GPR0_REGNUM + NR_GPR)
    215       && len == 4)
    216     {
    217       *((uint32_t*)buf) =
    218 	H2T_4 (iq2000bf_h_gr_get (cpu, nr - GPR0_REGNUM));
    219       return 4;
    220     }
    221   else if (nr == PC_REGNUM
    222 	   && len == 4)
    223     {
    224       *((uint32_t*)buf) = H2T_4 (get_h_pc (cpu));
    225       return 4;
    226     }
    227   else
    228     return 0;
    229 }
    230 
    231 int
    232 iq2000bf_store_register (SIM_CPU *cpu, int nr, const void *buf, int len)
    233 {
    234   if (nr >= GPR0_REGNUM
    235       && nr < (GPR0_REGNUM + NR_GPR)
    236       && len == 4)
    237     {
    238       iq2000bf_h_gr_set (cpu, nr - GPR0_REGNUM, T2H_4 (*((uint32_t*)buf)));
    239       return 4;
    240     }
    241   else if (nr == PC_REGNUM
    242 	   && len == 4)
    243     {
    244       set_h_pc (cpu, T2H_4 (*((uint32_t*)buf)));
    245       return 4;
    246     }
    247   else
    248     return 0;
    249 }
    250