166e63ce3Schristos /* m32r exception, interrupt, and trap (EIT) support
2*1424dfb3Schristos    Copyright (C) 1998-2020 Free Software Foundation, Inc.
366e63ce3Schristos    Contributed by Renesas.
466e63ce3Schristos 
566e63ce3Schristos    This file is part of GDB, the GNU debugger.
666e63ce3Schristos 
766e63ce3Schristos    This program is free software; you can redistribute it and/or modify
866e63ce3Schristos    it under the terms of the GNU General Public License as published by
966e63ce3Schristos    the Free Software Foundation; either version 3 of the License, or
1066e63ce3Schristos    (at your option) any later version.
1166e63ce3Schristos 
1266e63ce3Schristos    This program is distributed in the hope that it will be useful,
1366e63ce3Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1466e63ce3Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1566e63ce3Schristos    GNU General Public License for more details.
1666e63ce3Schristos 
1766e63ce3Schristos    You should have received a copy of the GNU General Public License
1866e63ce3Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
1966e63ce3Schristos 
2066e63ce3Schristos #include "sim-main.h"
21ed6a76a9Schristos #include "sim-syscall.h"
2266e63ce3Schristos #include "syscall.h"
2366e63ce3Schristos #include "targ-vals.h"
2466e63ce3Schristos #include <dirent.h>
2566e63ce3Schristos #include <errno.h>
2666e63ce3Schristos #include <fcntl.h>
2766e63ce3Schristos #include <time.h>
2866e63ce3Schristos #include <unistd.h>
2966e63ce3Schristos #include <utime.h>
3066e63ce3Schristos #include <sys/mman.h>
3166e63ce3Schristos #include <sys/poll.h>
3266e63ce3Schristos #include <sys/resource.h>
3366e63ce3Schristos #include <sys/sysinfo.h>
3466e63ce3Schristos #include <sys/stat.h>
3566e63ce3Schristos #include <sys/time.h>
3666e63ce3Schristos #include <sys/timeb.h>
3766e63ce3Schristos #include <sys/timex.h>
3866e63ce3Schristos #include <sys/types.h>
3966e63ce3Schristos #include <sys/uio.h>
4066e63ce3Schristos #include <sys/utsname.h>
4166e63ce3Schristos #include <sys/vfs.h>
4266e63ce3Schristos #include <linux/sysctl.h>
4366e63ce3Schristos #include <linux/types.h>
4466e63ce3Schristos #include <linux/unistd.h>
4566e63ce3Schristos 
4666e63ce3Schristos #define TRAP_ELF_SYSCALL 0
4766e63ce3Schristos #define TRAP_LINUX_SYSCALL 2
4866e63ce3Schristos #define TRAP_FLUSH_CACHE 12
4966e63ce3Schristos 
5066e63ce3Schristos /* The semantic code invokes this for invalid (unrecognized) instructions.  */
5166e63ce3Schristos 
5266e63ce3Schristos SEM_PC
sim_engine_invalid_insn(SIM_CPU * current_cpu,IADDR cia,SEM_PC vpc)5366e63ce3Schristos sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
5466e63ce3Schristos {
5566e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu);
5666e63ce3Schristos 
5766e63ce3Schristos #if 0
5866e63ce3Schristos   if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
5966e63ce3Schristos     {
6066e63ce3Schristos       h_bsm_set (current_cpu, h_sm_get (current_cpu));
6166e63ce3Schristos       h_bie_set (current_cpu, h_ie_get (current_cpu));
6266e63ce3Schristos       h_bcond_set (current_cpu, h_cond_get (current_cpu));
6366e63ce3Schristos       /* sm not changed */
6466e63ce3Schristos       h_ie_set (current_cpu, 0);
6566e63ce3Schristos       h_cond_set (current_cpu, 0);
6666e63ce3Schristos 
6766e63ce3Schristos       h_bpc_set (current_cpu, cia);
6866e63ce3Schristos 
6966e63ce3Schristos       sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL,
7066e63ce3Schristos 			  EIT_RSVD_INSN_ADDR);
7166e63ce3Schristos     }
7266e63ce3Schristos   else
7366e63ce3Schristos #endif
7466e63ce3Schristos     sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
7566e63ce3Schristos   return vpc;
7666e63ce3Schristos }
7766e63ce3Schristos 
7866e63ce3Schristos /* Process an address exception.  */
7966e63ce3Schristos 
8066e63ce3Schristos void
m32r_core_signal(SIM_DESC sd,SIM_CPU * current_cpu,sim_cia cia,unsigned int map,int nr_bytes,address_word addr,transfer_type transfer,sim_core_signals sig)8166e63ce3Schristos m32r_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
8266e63ce3Schristos 		  unsigned int map, int nr_bytes, address_word addr,
8366e63ce3Schristos 		  transfer_type transfer, sim_core_signals sig)
8466e63ce3Schristos {
8566e63ce3Schristos   if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
8666e63ce3Schristos     {
8766e63ce3Schristos       m32rbf_h_cr_set (current_cpu, H_CR_BBPC,
8866e63ce3Schristos                        m32rbf_h_cr_get (current_cpu, H_CR_BPC));
8966e63ce3Schristos       if (MACH_NUM (CPU_MACH (current_cpu)) == MACH_M32R)
9066e63ce3Schristos         {
9166e63ce3Schristos           m32rbf_h_bpsw_set (current_cpu, m32rbf_h_psw_get (current_cpu));
9266e63ce3Schristos           /* sm not changed */
9366e63ce3Schristos           m32rbf_h_psw_set (current_cpu, m32rbf_h_psw_get (current_cpu) & 0x80);
9466e63ce3Schristos         }
9566e63ce3Schristos       else if (MACH_NUM (CPU_MACH (current_cpu)) == MACH_M32RX)
9666e63ce3Schristos         {
9766e63ce3Schristos           m32rxf_h_bpsw_set (current_cpu, m32rxf_h_psw_get (current_cpu));
9866e63ce3Schristos           /* sm not changed */
9966e63ce3Schristos           m32rxf_h_psw_set (current_cpu, m32rxf_h_psw_get (current_cpu) & 0x80);
10066e63ce3Schristos         }
10166e63ce3Schristos       else
10266e63ce3Schristos         {
10366e63ce3Schristos           m32r2f_h_bpsw_set (current_cpu, m32r2f_h_psw_get (current_cpu));
10466e63ce3Schristos           /* sm not changed */
10566e63ce3Schristos           m32r2f_h_psw_set (current_cpu, m32r2f_h_psw_get (current_cpu) & 0x80);
10666e63ce3Schristos         }
10766e63ce3Schristos       m32rbf_h_cr_set (current_cpu, H_CR_BPC, cia);
10866e63ce3Schristos 
10966e63ce3Schristos       sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL,
11066e63ce3Schristos                           EIT_ADDR_EXCP_ADDR);
11166e63ce3Schristos     }
11266e63ce3Schristos   else
11366e63ce3Schristos     sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr,
11466e63ce3Schristos                      transfer, sig);
11566e63ce3Schristos }
11666e63ce3Schristos 
11766e63ce3Schristos /* Translate target's address to host's address.  */
11866e63ce3Schristos 
11966e63ce3Schristos static void *
t2h_addr(host_callback * cb,struct cb_syscall * sc,unsigned long taddr)12066e63ce3Schristos t2h_addr (host_callback *cb, struct cb_syscall *sc,
12166e63ce3Schristos           unsigned long taddr)
12266e63ce3Schristos {
12366e63ce3Schristos   void *addr;
12466e63ce3Schristos   SIM_DESC sd = (SIM_DESC) sc->p1;
12566e63ce3Schristos   SIM_CPU *cpu = (SIM_CPU *) sc->p2;
12666e63ce3Schristos 
12766e63ce3Schristos   if (taddr == 0)
12866e63ce3Schristos     return NULL;
12966e63ce3Schristos 
13066e63ce3Schristos   return sim_core_trans_addr (sd, cpu, read_map, taddr);
13166e63ce3Schristos }
13266e63ce3Schristos 
13366e63ce3Schristos static unsigned int
conv_endian(unsigned int tvalue)13466e63ce3Schristos conv_endian (unsigned int tvalue)
13566e63ce3Schristos {
13666e63ce3Schristos   unsigned int hvalue;
13766e63ce3Schristos   unsigned int t1, t2, t3, t4;
13866e63ce3Schristos 
139c03b94e9Schristos   if (HOST_BYTE_ORDER == BFD_ENDIAN_LITTLE)
14066e63ce3Schristos     {
14166e63ce3Schristos       t1 = tvalue & 0xff000000;
14266e63ce3Schristos       t2 = tvalue & 0x00ff0000;
14366e63ce3Schristos       t3 = tvalue & 0x0000ff00;
14466e63ce3Schristos       t4 = tvalue & 0x000000ff;
14566e63ce3Schristos 
14666e63ce3Schristos       hvalue =  t1 >> 24;
14766e63ce3Schristos       hvalue += t2 >> 8;
14866e63ce3Schristos       hvalue += t3 << 8;
14966e63ce3Schristos       hvalue += t4 << 24;
15066e63ce3Schristos     }
15166e63ce3Schristos   else
15266e63ce3Schristos     hvalue = tvalue;
15366e63ce3Schristos 
15466e63ce3Schristos   return hvalue;
15566e63ce3Schristos }
15666e63ce3Schristos 
15766e63ce3Schristos static unsigned short
conv_endian16(unsigned short tvalue)15866e63ce3Schristos conv_endian16 (unsigned short tvalue)
15966e63ce3Schristos {
16066e63ce3Schristos   unsigned short hvalue;
16166e63ce3Schristos   unsigned short t1, t2;
16266e63ce3Schristos 
163c03b94e9Schristos   if (HOST_BYTE_ORDER == BFD_ENDIAN_LITTLE)
16466e63ce3Schristos     {
16566e63ce3Schristos       t1 = tvalue & 0xff00;
16666e63ce3Schristos       t2 = tvalue & 0x00ff;
16766e63ce3Schristos 
16866e63ce3Schristos       hvalue =  t1 >> 8;
16966e63ce3Schristos       hvalue += t2 << 8;
17066e63ce3Schristos     }
17166e63ce3Schristos   else
17266e63ce3Schristos     hvalue = tvalue;
17366e63ce3Schristos 
17466e63ce3Schristos   return hvalue;
17566e63ce3Schristos }
17666e63ce3Schristos 
17766e63ce3Schristos static void
translate_endian(void * addr,size_t size)17866e63ce3Schristos translate_endian(void *addr, size_t size)
17966e63ce3Schristos {
18066e63ce3Schristos   unsigned int *p = (unsigned int *) addr;
18166e63ce3Schristos   int i;
18266e63ce3Schristos 
18366e63ce3Schristos   for (i = 0; i <= size - 4; i += 4,p++)
18466e63ce3Schristos     *p = conv_endian(*p);
18566e63ce3Schristos 
18666e63ce3Schristos   if (i <= size - 2)
18766e63ce3Schristos     *((unsigned short *) p) = conv_endian16(*((unsigned short *) p));
18866e63ce3Schristos }
18966e63ce3Schristos 
19066e63ce3Schristos /* Trap support.
19166e63ce3Schristos    The result is the pc address to continue at.
19266e63ce3Schristos    Preprocessing like saving the various registers has already been done.  */
19366e63ce3Schristos 
19466e63ce3Schristos USI
m32r_trap(SIM_CPU * current_cpu,PCADDR pc,int num)19566e63ce3Schristos m32r_trap (SIM_CPU *current_cpu, PCADDR pc, int num)
19666e63ce3Schristos {
19766e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu);
19866e63ce3Schristos   host_callback *cb = STATE_CALLBACK (sd);
19966e63ce3Schristos 
20066e63ce3Schristos   switch (num)
20166e63ce3Schristos     {
20266e63ce3Schristos     case TRAP_ELF_SYSCALL :
20366e63ce3Schristos       {
204ed6a76a9Schristos 	long result, result2;
205ed6a76a9Schristos 	int errcode;
20666e63ce3Schristos 
207ed6a76a9Schristos 	sim_syscall_multi (current_cpu,
208ed6a76a9Schristos 			   m32rbf_h_gr_get (current_cpu, 0),
209ed6a76a9Schristos 			   m32rbf_h_gr_get (current_cpu, 1),
210ed6a76a9Schristos 			   m32rbf_h_gr_get (current_cpu, 2),
211ed6a76a9Schristos 			   m32rbf_h_gr_get (current_cpu, 3),
212ed6a76a9Schristos 			   m32rbf_h_gr_get (current_cpu, 4),
213ed6a76a9Schristos 			   &result, &result2, &errcode);
21466e63ce3Schristos 
215ed6a76a9Schristos 	m32rbf_h_gr_set (current_cpu, 2, errcode);
216ed6a76a9Schristos 	m32rbf_h_gr_set (current_cpu, 0, result);
217ed6a76a9Schristos 	m32rbf_h_gr_set (current_cpu, 1, result2);
21866e63ce3Schristos 	break;
21966e63ce3Schristos       }
22066e63ce3Schristos 
22166e63ce3Schristos     case TRAP_LINUX_SYSCALL :
22266e63ce3Schristos       {
22366e63ce3Schristos 	CB_SYSCALL s;
22466e63ce3Schristos         unsigned int func, arg1, arg2, arg3, arg4, arg5, arg6, arg7;
22566e63ce3Schristos         int result, result2, errcode;
22666e63ce3Schristos 
22766e63ce3Schristos         if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
22866e63ce3Schristos           {
22966e63ce3Schristos             /* The new pc is the trap vector entry.
23066e63ce3Schristos                We assume there's a branch there to some handler.
23166e63ce3Schristos 	       Use cr5 as EVB (EIT Vector Base) register.  */
23266e63ce3Schristos             USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4;
23366e63ce3Schristos             return new_pc;
23466e63ce3Schristos           }
23566e63ce3Schristos 
23666e63ce3Schristos 	func = m32rbf_h_gr_get (current_cpu, 7);
23766e63ce3Schristos 	arg1 = m32rbf_h_gr_get (current_cpu, 0);
23866e63ce3Schristos 	arg2 = m32rbf_h_gr_get (current_cpu, 1);
23966e63ce3Schristos 	arg3 = m32rbf_h_gr_get (current_cpu, 2);
24066e63ce3Schristos 	arg4 = m32rbf_h_gr_get (current_cpu, 3);
24166e63ce3Schristos 	arg5 = m32rbf_h_gr_get (current_cpu, 4);
24266e63ce3Schristos 	arg6 = m32rbf_h_gr_get (current_cpu, 5);
24366e63ce3Schristos 	arg7 = m32rbf_h_gr_get (current_cpu, 6);
24466e63ce3Schristos 
24566e63ce3Schristos         CB_SYSCALL_INIT (&s);
24666e63ce3Schristos         s.func = func;
24766e63ce3Schristos         s.arg1 = arg1;
24866e63ce3Schristos         s.arg2 = arg2;
24966e63ce3Schristos         s.arg3 = arg3;
25066e63ce3Schristos 
25166e63ce3Schristos         s.p1 = (PTR) sd;
25266e63ce3Schristos         s.p2 = (PTR) current_cpu;
253ed6a76a9Schristos         s.read_mem = sim_syscall_read_mem;
254ed6a76a9Schristos         s.write_mem = sim_syscall_write_mem;
25566e63ce3Schristos 
25666e63ce3Schristos         result = 0;
25766e63ce3Schristos         result2 = 0;
25866e63ce3Schristos         errcode = 0;
25966e63ce3Schristos 
26066e63ce3Schristos         switch (func)
26166e63ce3Schristos           {
26266e63ce3Schristos           case __NR_exit:
26366e63ce3Schristos 	    sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, arg1);
26466e63ce3Schristos             break;
26566e63ce3Schristos 
26666e63ce3Schristos           case __NR_read:
26766e63ce3Schristos             result = read(arg1, t2h_addr(cb, &s, arg2), arg3);
26866e63ce3Schristos             errcode = errno;
26966e63ce3Schristos             break;
27066e63ce3Schristos 
27166e63ce3Schristos           case __NR_write:
27266e63ce3Schristos             result = write(arg1, t2h_addr(cb, &s, arg2), arg3);
27366e63ce3Schristos             errcode = errno;
27466e63ce3Schristos             break;
27566e63ce3Schristos 
27666e63ce3Schristos           case __NR_open:
27766e63ce3Schristos             result = open((char *) t2h_addr(cb, &s, arg1), arg2, arg3);
27866e63ce3Schristos             errcode = errno;
27966e63ce3Schristos             break;
28066e63ce3Schristos 
28166e63ce3Schristos           case __NR_close:
28266e63ce3Schristos             result = close(arg1);
28366e63ce3Schristos             errcode = errno;
28466e63ce3Schristos             break;
28566e63ce3Schristos 
28666e63ce3Schristos           case __NR_creat:
28766e63ce3Schristos             result = creat((char *) t2h_addr(cb, &s, arg1), arg2);
28866e63ce3Schristos             errcode = errno;
28966e63ce3Schristos             break;
29066e63ce3Schristos 
29166e63ce3Schristos           case __NR_link:
29266e63ce3Schristos             result = link((char *) t2h_addr(cb, &s, arg1),
29366e63ce3Schristos                           (char *) t2h_addr(cb, &s, arg2));
29466e63ce3Schristos             errcode = errno;
29566e63ce3Schristos             break;
29666e63ce3Schristos 
29766e63ce3Schristos           case __NR_unlink:
29866e63ce3Schristos             result = unlink((char *) t2h_addr(cb, &s, arg1));
29966e63ce3Schristos             errcode = errno;
30066e63ce3Schristos             break;
30166e63ce3Schristos 
30266e63ce3Schristos           case __NR_chdir:
30366e63ce3Schristos             result = chdir((char *) t2h_addr(cb, &s, arg1));
30466e63ce3Schristos             errcode = errno;
30566e63ce3Schristos             break;
30666e63ce3Schristos 
30766e63ce3Schristos           case __NR_time:
30866e63ce3Schristos             {
30966e63ce3Schristos               time_t t;
31066e63ce3Schristos 
31166e63ce3Schristos               if (arg1 == 0)
31266e63ce3Schristos                 {
31366e63ce3Schristos                   result = (int) time(NULL);
31466e63ce3Schristos                   errcode = errno;
31566e63ce3Schristos                 }
31666e63ce3Schristos               else
31766e63ce3Schristos                 {
31866e63ce3Schristos                   result = (int) time(&t);
31966e63ce3Schristos                   errcode = errno;
32066e63ce3Schristos 
32166e63ce3Schristos                   if (result != 0)
32266e63ce3Schristos                     break;
32366e63ce3Schristos 
32466e63ce3Schristos                   translate_endian((void *) &t, sizeof(t));
32566e63ce3Schristos                   if ((s.write_mem) (cb, &s, arg1, (char *) &t, sizeof(t)) != sizeof(t))
32666e63ce3Schristos                     {
32766e63ce3Schristos                       result = -1;
32866e63ce3Schristos                       errcode = EINVAL;
32966e63ce3Schristos                     }
33066e63ce3Schristos                 }
33166e63ce3Schristos             }
33266e63ce3Schristos             break;
33366e63ce3Schristos 
33466e63ce3Schristos           case __NR_mknod:
33566e63ce3Schristos             result = mknod((char *) t2h_addr(cb, &s, arg1),
33666e63ce3Schristos                            (mode_t) arg2, (dev_t) arg3);
33766e63ce3Schristos             errcode = errno;
33866e63ce3Schristos             break;
33966e63ce3Schristos 
34066e63ce3Schristos           case __NR_chmod:
34166e63ce3Schristos             result = chmod((char *) t2h_addr(cb, &s, arg1), (mode_t) arg2);
34266e63ce3Schristos             errcode = errno;
34366e63ce3Schristos             break;
34466e63ce3Schristos 
34566e63ce3Schristos           case __NR_lchown32:
34666e63ce3Schristos           case __NR_lchown:
34766e63ce3Schristos             result = lchown((char *) t2h_addr(cb, &s, arg1),
34866e63ce3Schristos                             (uid_t) arg2, (gid_t) arg3);
34966e63ce3Schristos             errcode = errno;
35066e63ce3Schristos             break;
35166e63ce3Schristos 
35266e63ce3Schristos           case __NR_lseek:
35366e63ce3Schristos             result = (int) lseek(arg1, (off_t) arg2, arg3);
35466e63ce3Schristos             errcode = errno;
35566e63ce3Schristos             break;
35666e63ce3Schristos 
35766e63ce3Schristos           case __NR_getpid:
35866e63ce3Schristos             result = getpid();
35966e63ce3Schristos             errcode = errno;
36066e63ce3Schristos             break;
36166e63ce3Schristos 
36266e63ce3Schristos           case __NR_getuid32:
36366e63ce3Schristos           case __NR_getuid:
36466e63ce3Schristos             result = getuid();
36566e63ce3Schristos             errcode = errno;
36666e63ce3Schristos             break;
36766e63ce3Schristos 
36866e63ce3Schristos           case __NR_utime:
36966e63ce3Schristos             {
37066e63ce3Schristos               struct utimbuf buf;
37166e63ce3Schristos 
37266e63ce3Schristos               if (arg2 == 0)
37366e63ce3Schristos                 {
37466e63ce3Schristos                   result = utime((char *) t2h_addr(cb, &s, arg1), NULL);
37566e63ce3Schristos                   errcode = errno;
37666e63ce3Schristos                 }
37766e63ce3Schristos               else
37866e63ce3Schristos                 {
37966e63ce3Schristos                   buf = *((struct utimbuf *) t2h_addr(cb, &s, arg2));
38066e63ce3Schristos                   translate_endian((void *) &buf, sizeof(buf));
38166e63ce3Schristos                   result = utime((char *) t2h_addr(cb, &s, arg1), &buf);
38266e63ce3Schristos                   errcode = errno;
38366e63ce3Schristos                 }
38466e63ce3Schristos             }
38566e63ce3Schristos             break;
38666e63ce3Schristos 
38766e63ce3Schristos           case __NR_access:
38866e63ce3Schristos             result = access((char *) t2h_addr(cb, &s, arg1), arg2);
38966e63ce3Schristos             errcode = errno;
39066e63ce3Schristos             break;
39166e63ce3Schristos 
39266e63ce3Schristos           case __NR_ftime:
39366e63ce3Schristos             {
39466e63ce3Schristos               struct timeb t;
39566e63ce3Schristos 
39666e63ce3Schristos               result = ftime(&t);
39766e63ce3Schristos               errcode = errno;
39866e63ce3Schristos 
39966e63ce3Schristos               if (result != 0)
40066e63ce3Schristos                 break;
40166e63ce3Schristos 
40266e63ce3Schristos               t.time = conv_endian(t.time);
40366e63ce3Schristos               t.millitm = conv_endian16(t.millitm);
40466e63ce3Schristos               t.timezone = conv_endian16(t.timezone);
40566e63ce3Schristos               t.dstflag = conv_endian16(t.dstflag);
40666e63ce3Schristos               if ((s.write_mem) (cb, &s, arg1, (char *) &t, sizeof(t))
40766e63ce3Schristos                   != sizeof(t))
40866e63ce3Schristos                 {
40966e63ce3Schristos                   result = -1;
41066e63ce3Schristos                   errcode = EINVAL;
41166e63ce3Schristos                 }
41266e63ce3Schristos             }
41366e63ce3Schristos 
41466e63ce3Schristos           case __NR_sync:
41566e63ce3Schristos             sync();
41666e63ce3Schristos             result = 0;
41766e63ce3Schristos             break;
41866e63ce3Schristos 
41966e63ce3Schristos           case __NR_rename:
42066e63ce3Schristos             result = rename((char *) t2h_addr(cb, &s, arg1),
42166e63ce3Schristos                             (char *) t2h_addr(cb, &s, arg2));
42266e63ce3Schristos             errcode = errno;
42366e63ce3Schristos             break;
42466e63ce3Schristos 
42566e63ce3Schristos           case __NR_mkdir:
42666e63ce3Schristos             result = mkdir((char *) t2h_addr(cb, &s, arg1), arg2);
42766e63ce3Schristos             errcode = errno;
42866e63ce3Schristos             break;
42966e63ce3Schristos 
43066e63ce3Schristos           case __NR_rmdir:
43166e63ce3Schristos             result = rmdir((char *) t2h_addr(cb, &s, arg1));
43266e63ce3Schristos             errcode = errno;
43366e63ce3Schristos             break;
43466e63ce3Schristos 
43566e63ce3Schristos           case __NR_dup:
43666e63ce3Schristos             result = dup(arg1);
43766e63ce3Schristos             errcode = errno;
43866e63ce3Schristos             break;
43966e63ce3Schristos 
44066e63ce3Schristos           case __NR_brk:
44166e63ce3Schristos             result = brk((void *) arg1);
44266e63ce3Schristos             errcode = errno;
44366e63ce3Schristos             //result = arg1;
44466e63ce3Schristos             break;
44566e63ce3Schristos 
44666e63ce3Schristos           case __NR_getgid32:
44766e63ce3Schristos           case __NR_getgid:
44866e63ce3Schristos             result = getgid();
44966e63ce3Schristos             errcode = errno;
45066e63ce3Schristos             break;
45166e63ce3Schristos 
45266e63ce3Schristos           case __NR_geteuid32:
45366e63ce3Schristos           case __NR_geteuid:
45466e63ce3Schristos             result = geteuid();
45566e63ce3Schristos             errcode = errno;
45666e63ce3Schristos             break;
45766e63ce3Schristos 
45866e63ce3Schristos           case __NR_getegid32:
45966e63ce3Schristos           case __NR_getegid:
46066e63ce3Schristos             result = getegid();
46166e63ce3Schristos             errcode = errno;
46266e63ce3Schristos             break;
46366e63ce3Schristos 
46466e63ce3Schristos           case __NR_ioctl:
46566e63ce3Schristos             result = ioctl(arg1, arg2, arg3);
46666e63ce3Schristos             errcode = errno;
46766e63ce3Schristos             break;
46866e63ce3Schristos 
46966e63ce3Schristos           case __NR_fcntl:
47066e63ce3Schristos             result = fcntl(arg1, arg2, arg3);
47166e63ce3Schristos             errcode = errno;
47266e63ce3Schristos             break;
47366e63ce3Schristos 
47466e63ce3Schristos           case __NR_dup2:
47566e63ce3Schristos             result = dup2(arg1, arg2);
47666e63ce3Schristos             errcode = errno;
47766e63ce3Schristos             break;
47866e63ce3Schristos 
47966e63ce3Schristos           case __NR_getppid:
48066e63ce3Schristos             result = getppid();
48166e63ce3Schristos             errcode = errno;
48266e63ce3Schristos             break;
48366e63ce3Schristos 
48466e63ce3Schristos           case __NR_getpgrp:
48566e63ce3Schristos             result = getpgrp();
48666e63ce3Schristos             errcode = errno;
48766e63ce3Schristos             break;
48866e63ce3Schristos 
48966e63ce3Schristos           case __NR_getrlimit:
49066e63ce3Schristos             {
49166e63ce3Schristos               struct rlimit rlim;
49266e63ce3Schristos 
49366e63ce3Schristos               result = getrlimit(arg1, &rlim);
49466e63ce3Schristos               errcode = errno;
49566e63ce3Schristos 
49666e63ce3Schristos               if (result != 0)
49766e63ce3Schristos                 break;
49866e63ce3Schristos 
49966e63ce3Schristos               translate_endian((void *) &rlim, sizeof(rlim));
50066e63ce3Schristos               if ((s.write_mem) (cb, &s, arg2, (char *) &rlim, sizeof(rlim))
50166e63ce3Schristos                   != sizeof(rlim))
50266e63ce3Schristos                 {
50366e63ce3Schristos                   result = -1;
50466e63ce3Schristos                   errcode = EINVAL;
50566e63ce3Schristos                 }
50666e63ce3Schristos             }
50766e63ce3Schristos             break;
50866e63ce3Schristos 
50966e63ce3Schristos           case __NR_getrusage:
51066e63ce3Schristos             {
51166e63ce3Schristos               struct rusage usage;
51266e63ce3Schristos 
51366e63ce3Schristos               result = getrusage(arg1, &usage);
51466e63ce3Schristos               errcode = errno;
51566e63ce3Schristos 
51666e63ce3Schristos               if (result != 0)
51766e63ce3Schristos                 break;
51866e63ce3Schristos 
51966e63ce3Schristos               translate_endian((void *) &usage, sizeof(usage));
52066e63ce3Schristos               if ((s.write_mem) (cb, &s, arg2, (char *) &usage, sizeof(usage))
52166e63ce3Schristos                   != sizeof(usage))
52266e63ce3Schristos                 {
52366e63ce3Schristos                   result = -1;
52466e63ce3Schristos                   errcode = EINVAL;
52566e63ce3Schristos                 }
52666e63ce3Schristos             }
52766e63ce3Schristos             break;
52866e63ce3Schristos 
52966e63ce3Schristos           case __NR_gettimeofday:
53066e63ce3Schristos             {
53166e63ce3Schristos               struct timeval tv;
53266e63ce3Schristos               struct timezone tz;
53366e63ce3Schristos 
53466e63ce3Schristos               result = gettimeofday(&tv, &tz);
53566e63ce3Schristos               errcode = errno;
53666e63ce3Schristos 
53766e63ce3Schristos               if (result != 0)
53866e63ce3Schristos                 break;
53966e63ce3Schristos 
54066e63ce3Schristos               translate_endian((void *) &tv, sizeof(tv));
54166e63ce3Schristos               if ((s.write_mem) (cb, &s, arg1, (char *) &tv, sizeof(tv))
54266e63ce3Schristos                   != sizeof(tv))
54366e63ce3Schristos                 {
54466e63ce3Schristos                   result = -1;
54566e63ce3Schristos                   errcode = EINVAL;
54666e63ce3Schristos                 }
54766e63ce3Schristos 
54866e63ce3Schristos               translate_endian((void *) &tz, sizeof(tz));
54966e63ce3Schristos               if ((s.write_mem) (cb, &s, arg2, (char *) &tz, sizeof(tz))
55066e63ce3Schristos                   != sizeof(tz))
55166e63ce3Schristos                 {
55266e63ce3Schristos                   result = -1;
55366e63ce3Schristos                   errcode = EINVAL;
55466e63ce3Schristos                 }
55566e63ce3Schristos             }
55666e63ce3Schristos             break;
55766e63ce3Schristos 
55866e63ce3Schristos           case __NR_getgroups32:
55966e63ce3Schristos           case __NR_getgroups:
56066e63ce3Schristos             {
56166e63ce3Schristos               gid_t *list;
56266e63ce3Schristos 
56366e63ce3Schristos               if (arg1 > 0)
56466e63ce3Schristos                 list = (gid_t *) malloc(arg1 * sizeof(gid_t));
56566e63ce3Schristos 
56666e63ce3Schristos               result = getgroups(arg1, list);
56766e63ce3Schristos               errcode = errno;
56866e63ce3Schristos 
56966e63ce3Schristos               if (result != 0)
57066e63ce3Schristos                 break;
57166e63ce3Schristos 
57266e63ce3Schristos               translate_endian((void *) list, arg1 * sizeof(gid_t));
57366e63ce3Schristos               if (arg1 > 0)
57466e63ce3Schristos                 if ((s.write_mem) (cb, &s, arg2, (char *) list, arg1 * sizeof(gid_t))
57566e63ce3Schristos                     != arg1 * sizeof(gid_t))
57666e63ce3Schristos                   {
57766e63ce3Schristos                     result = -1;
57866e63ce3Schristos                      errcode = EINVAL;
57966e63ce3Schristos                   }
58066e63ce3Schristos             }
58166e63ce3Schristos             break;
58266e63ce3Schristos 
58366e63ce3Schristos           case __NR_select:
58466e63ce3Schristos             {
58566e63ce3Schristos               int n;
58666e63ce3Schristos               fd_set readfds;
58766e63ce3Schristos               fd_set *treadfdsp;
58866e63ce3Schristos               fd_set *hreadfdsp;
58966e63ce3Schristos               fd_set writefds;
59066e63ce3Schristos               fd_set *twritefdsp;
59166e63ce3Schristos               fd_set *hwritefdsp;
59266e63ce3Schristos               fd_set exceptfds;
59366e63ce3Schristos               fd_set *texceptfdsp;
59466e63ce3Schristos               fd_set *hexceptfdsp;
59566e63ce3Schristos               struct timeval *ttimeoutp;
59666e63ce3Schristos               struct timeval timeout;
59766e63ce3Schristos 
59866e63ce3Schristos               n = arg1;
59966e63ce3Schristos 
60066e63ce3Schristos               treadfdsp = (fd_set *) arg2;
60166e63ce3Schristos               if (treadfdsp != NULL)
60266e63ce3Schristos                 {
60366e63ce3Schristos                   readfds = *((fd_set *) t2h_addr(cb, &s, (unsigned int) treadfdsp));
60466e63ce3Schristos                   translate_endian((void *) &readfds, sizeof(readfds));
60566e63ce3Schristos                   hreadfdsp = &readfds;
60666e63ce3Schristos                 }
60766e63ce3Schristos               else
60866e63ce3Schristos                 hreadfdsp = NULL;
60966e63ce3Schristos 
61066e63ce3Schristos               twritefdsp  = (fd_set *) arg3;
61166e63ce3Schristos               if (twritefdsp != NULL)
61266e63ce3Schristos                 {
61366e63ce3Schristos                   writefds = *((fd_set *) t2h_addr(cb, &s, (unsigned int) twritefdsp));
61466e63ce3Schristos                   translate_endian((void *) &writefds, sizeof(writefds));
61566e63ce3Schristos                   hwritefdsp = &writefds;
61666e63ce3Schristos                 }
61766e63ce3Schristos               else
61866e63ce3Schristos                 hwritefdsp = NULL;
61966e63ce3Schristos 
62066e63ce3Schristos               texceptfdsp = (fd_set *) arg4;
62166e63ce3Schristos               if (texceptfdsp != NULL)
62266e63ce3Schristos                 {
62366e63ce3Schristos                   exceptfds = *((fd_set *) t2h_addr(cb, &s, (unsigned int) texceptfdsp));
62466e63ce3Schristos                   translate_endian((void *) &exceptfds, sizeof(exceptfds));
62566e63ce3Schristos                   hexceptfdsp = &exceptfds;
62666e63ce3Schristos                 }
62766e63ce3Schristos               else
62866e63ce3Schristos                 hexceptfdsp = NULL;
62966e63ce3Schristos 
63066e63ce3Schristos               ttimeoutp = (struct timeval *) arg5;
63166e63ce3Schristos               timeout = *((struct timeval *) t2h_addr(cb, &s, (unsigned int) ttimeoutp));
63266e63ce3Schristos               translate_endian((void *) &timeout, sizeof(timeout));
63366e63ce3Schristos 
63466e63ce3Schristos               result = select(n, hreadfdsp, hwritefdsp, hexceptfdsp, &timeout);
63566e63ce3Schristos               errcode = errno;
63666e63ce3Schristos 
63766e63ce3Schristos               if (result != 0)
63866e63ce3Schristos                 break;
63966e63ce3Schristos 
64066e63ce3Schristos               if (treadfdsp != NULL)
64166e63ce3Schristos                 {
64266e63ce3Schristos                   translate_endian((void *) &readfds, sizeof(readfds));
64366e63ce3Schristos                   if ((s.write_mem) (cb, &s, (unsigned long) treadfdsp,
64466e63ce3Schristos                        (char *) &readfds, sizeof(readfds)) != sizeof(readfds))
64566e63ce3Schristos                     {
64666e63ce3Schristos                       result = -1;
64766e63ce3Schristos                       errcode = EINVAL;
64866e63ce3Schristos                     }
64966e63ce3Schristos                 }
65066e63ce3Schristos 
65166e63ce3Schristos               if (twritefdsp != NULL)
65266e63ce3Schristos                 {
65366e63ce3Schristos                   translate_endian((void *) &writefds, sizeof(writefds));
65466e63ce3Schristos                   if ((s.write_mem) (cb, &s, (unsigned long) twritefdsp,
65566e63ce3Schristos                        (char *) &writefds, sizeof(writefds)) != sizeof(writefds))
65666e63ce3Schristos                     {
65766e63ce3Schristos                       result = -1;
65866e63ce3Schristos                       errcode = EINVAL;
65966e63ce3Schristos                     }
66066e63ce3Schristos                 }
66166e63ce3Schristos 
66266e63ce3Schristos               if (texceptfdsp != NULL)
66366e63ce3Schristos                 {
66466e63ce3Schristos                   translate_endian((void *) &exceptfds, sizeof(exceptfds));
66566e63ce3Schristos                   if ((s.write_mem) (cb, &s, (unsigned long) texceptfdsp,
66666e63ce3Schristos                        (char *) &exceptfds, sizeof(exceptfds)) != sizeof(exceptfds))
66766e63ce3Schristos                     {
66866e63ce3Schristos                       result = -1;
66966e63ce3Schristos                       errcode = EINVAL;
67066e63ce3Schristos                     }
67166e63ce3Schristos                 }
67266e63ce3Schristos 
67366e63ce3Schristos               translate_endian((void *) &timeout, sizeof(timeout));
67466e63ce3Schristos               if ((s.write_mem) (cb, &s, (unsigned long) ttimeoutp,
67566e63ce3Schristos                    (char *) &timeout, sizeof(timeout)) != sizeof(timeout))
67666e63ce3Schristos                 {
67766e63ce3Schristos                   result = -1;
67866e63ce3Schristos                   errcode = EINVAL;
67966e63ce3Schristos                 }
68066e63ce3Schristos             }
68166e63ce3Schristos             break;
68266e63ce3Schristos 
68366e63ce3Schristos           case __NR_symlink:
68466e63ce3Schristos             result = symlink((char *) t2h_addr(cb, &s, arg1),
68566e63ce3Schristos                              (char *) t2h_addr(cb, &s, arg2));
68666e63ce3Schristos             errcode = errno;
68766e63ce3Schristos             break;
68866e63ce3Schristos 
68966e63ce3Schristos           case __NR_readlink:
69066e63ce3Schristos             result = readlink((char *) t2h_addr(cb, &s, arg1),
69166e63ce3Schristos                               (char *) t2h_addr(cb, &s, arg2),
69266e63ce3Schristos                               arg3);
69366e63ce3Schristos             errcode = errno;
69466e63ce3Schristos             break;
69566e63ce3Schristos 
69666e63ce3Schristos           case __NR_readdir:
69766e63ce3Schristos             result = (int) readdir((DIR *) t2h_addr(cb, &s, arg1));
69866e63ce3Schristos             errcode = errno;
69966e63ce3Schristos             break;
70066e63ce3Schristos 
70166e63ce3Schristos #if 0
70266e63ce3Schristos           case __NR_mmap:
70366e63ce3Schristos             {
70466e63ce3Schristos               result = (int) mmap((void *) t2h_addr(cb, &s, arg1),
70566e63ce3Schristos                                   arg2, arg3, arg4, arg5, arg6);
70666e63ce3Schristos               errcode = errno;
70766e63ce3Schristos 
70866e63ce3Schristos               if (errno == 0)
70966e63ce3Schristos                 {
71066e63ce3Schristos                   sim_core_attach (sd, NULL,
71166e63ce3Schristos                                    0, access_read_write_exec, 0,
71266e63ce3Schristos                                    result, arg2, 0, NULL, NULL);
71366e63ce3Schristos                 }
71466e63ce3Schristos             }
71566e63ce3Schristos             break;
71666e63ce3Schristos #endif
71766e63ce3Schristos           case __NR_mmap2:
71866e63ce3Schristos             {
71966e63ce3Schristos               void *addr;
72066e63ce3Schristos               size_t len;
72166e63ce3Schristos               int prot, flags, fildes;
72266e63ce3Schristos               off_t off;
72366e63ce3Schristos 
72466e63ce3Schristos               addr   = (void *)  t2h_addr(cb, &s, arg1);
72566e63ce3Schristos               len    = arg2;
72666e63ce3Schristos               prot   = arg3;
72766e63ce3Schristos               flags  = arg4;
72866e63ce3Schristos               fildes = arg5;
72966e63ce3Schristos               off    = arg6 << 12;
73066e63ce3Schristos 
73166e63ce3Schristos 	      result = (int) mmap(addr, len, prot, flags, fildes, off);
73266e63ce3Schristos               errcode = errno;
73366e63ce3Schristos               if (result != -1)
73466e63ce3Schristos                 {
73566e63ce3Schristos                   char c;
73666e63ce3Schristos 		  if (sim_core_read_buffer (sd, NULL, read_map, &c, result, 1) == 0)
73766e63ce3Schristos                     sim_core_attach (sd, NULL,
73866e63ce3Schristos                                      0, access_read_write_exec, 0,
73966e63ce3Schristos                                      result, len, 0, NULL, NULL);
74066e63ce3Schristos                 }
74166e63ce3Schristos             }
74266e63ce3Schristos             break;
74366e63ce3Schristos 
74466e63ce3Schristos           case __NR_mmap:
74566e63ce3Schristos             {
74666e63ce3Schristos               void *addr;
74766e63ce3Schristos               size_t len;
74866e63ce3Schristos               int prot, flags, fildes;
74966e63ce3Schristos               off_t off;
75066e63ce3Schristos 
75166e63ce3Schristos               addr   = *((void **)  t2h_addr(cb, &s, arg1));
75266e63ce3Schristos               len    = *((size_t *) t2h_addr(cb, &s, arg1 + 4));
75366e63ce3Schristos               prot   = *((int *)    t2h_addr(cb, &s, arg1 + 8));
75466e63ce3Schristos               flags  = *((int *)    t2h_addr(cb, &s, arg1 + 12));
75566e63ce3Schristos               fildes = *((int *)    t2h_addr(cb, &s, arg1 + 16));
75666e63ce3Schristos               off    = *((off_t *)  t2h_addr(cb, &s, arg1 + 20));
75766e63ce3Schristos 
75866e63ce3Schristos               addr   = (void *) conv_endian((unsigned int) addr);
75966e63ce3Schristos               len    = conv_endian(len);
76066e63ce3Schristos               prot   = conv_endian(prot);
76166e63ce3Schristos               flags  = conv_endian(flags);
76266e63ce3Schristos               fildes = conv_endian(fildes);
76366e63ce3Schristos               off    = conv_endian(off);
76466e63ce3Schristos 
76566e63ce3Schristos               //addr   = (void *) t2h_addr(cb, &s, (unsigned int) addr);
76666e63ce3Schristos               result = (int) mmap(addr, len, prot, flags, fildes, off);
76766e63ce3Schristos               errcode = errno;
76866e63ce3Schristos 
76966e63ce3Schristos               //if (errno == 0)
77066e63ce3Schristos               if (result != -1)
77166e63ce3Schristos                 {
77266e63ce3Schristos                   char c;
77366e63ce3Schristos 		  if (sim_core_read_buffer (sd, NULL, read_map, &c, result, 1) == 0)
77466e63ce3Schristos                     sim_core_attach (sd, NULL,
77566e63ce3Schristos                                      0, access_read_write_exec, 0,
77666e63ce3Schristos                                      result, len, 0, NULL, NULL);
77766e63ce3Schristos                 }
77866e63ce3Schristos             }
77966e63ce3Schristos             break;
78066e63ce3Schristos 
78166e63ce3Schristos           case __NR_munmap:
78266e63ce3Schristos             {
78366e63ce3Schristos             result = munmap((void *)arg1, arg2);
78466e63ce3Schristos             errcode = errno;
78566e63ce3Schristos             if (result != -1)
78666e63ce3Schristos               {
78766e63ce3Schristos                 sim_core_detach (sd, NULL, 0, arg2, result);
78866e63ce3Schristos               }
78966e63ce3Schristos             }
79066e63ce3Schristos             break;
79166e63ce3Schristos 
79266e63ce3Schristos           case __NR_truncate:
79366e63ce3Schristos             result = truncate((char *) t2h_addr(cb, &s, arg1), arg2);
79466e63ce3Schristos             errcode = errno;
79566e63ce3Schristos             break;
79666e63ce3Schristos 
79766e63ce3Schristos           case __NR_ftruncate:
79866e63ce3Schristos             result = ftruncate(arg1, arg2);
79966e63ce3Schristos             errcode = errno;
80066e63ce3Schristos             break;
80166e63ce3Schristos 
80266e63ce3Schristos           case __NR_fchmod:
80366e63ce3Schristos             result = fchmod(arg1, arg2);
80466e63ce3Schristos             errcode = errno;
80566e63ce3Schristos             break;
80666e63ce3Schristos 
80766e63ce3Schristos           case __NR_fchown32:
80866e63ce3Schristos           case __NR_fchown:
80966e63ce3Schristos             result = fchown(arg1, arg2, arg3);
81066e63ce3Schristos             errcode = errno;
81166e63ce3Schristos             break;
81266e63ce3Schristos 
81366e63ce3Schristos           case __NR_statfs:
81466e63ce3Schristos             {
81566e63ce3Schristos               struct statfs statbuf;
81666e63ce3Schristos 
81766e63ce3Schristos               result = statfs((char *) t2h_addr(cb, &s, arg1), &statbuf);
81866e63ce3Schristos               errcode = errno;
81966e63ce3Schristos 
82066e63ce3Schristos               if (result != 0)
82166e63ce3Schristos                 break;
82266e63ce3Schristos 
82366e63ce3Schristos               translate_endian((void *) &statbuf, sizeof(statbuf));
82466e63ce3Schristos               if ((s.write_mem) (cb, &s, arg2, (char *) &statbuf, sizeof(statbuf))
82566e63ce3Schristos                   != sizeof(statbuf))
82666e63ce3Schristos                 {
82766e63ce3Schristos                   result = -1;
82866e63ce3Schristos                   errcode = EINVAL;
82966e63ce3Schristos                 }
83066e63ce3Schristos             }
83166e63ce3Schristos             break;
83266e63ce3Schristos 
83366e63ce3Schristos           case __NR_fstatfs:
83466e63ce3Schristos             {
83566e63ce3Schristos               struct statfs statbuf;
83666e63ce3Schristos 
83766e63ce3Schristos               result = fstatfs(arg1, &statbuf);
83866e63ce3Schristos               errcode = errno;
83966e63ce3Schristos 
84066e63ce3Schristos               if (result != 0)
84166e63ce3Schristos                 break;
84266e63ce3Schristos 
84366e63ce3Schristos               translate_endian((void *) &statbuf, sizeof(statbuf));
84466e63ce3Schristos               if ((s.write_mem) (cb, &s, arg2, (char *) &statbuf, sizeof(statbuf))
84566e63ce3Schristos                   != sizeof(statbuf))
84666e63ce3Schristos                 {
84766e63ce3Schristos                   result = -1;
84866e63ce3Schristos                   errcode = EINVAL;
84966e63ce3Schristos                 }
85066e63ce3Schristos             }
85166e63ce3Schristos             break;
85266e63ce3Schristos 
85366e63ce3Schristos           case __NR_syslog:
85466e63ce3Schristos             result = syslog(arg1, (char *) t2h_addr(cb, &s, arg2));
85566e63ce3Schristos             errcode = errno;
85666e63ce3Schristos             break;
85766e63ce3Schristos 
85866e63ce3Schristos           case __NR_setitimer:
85966e63ce3Schristos             {
86066e63ce3Schristos               struct itimerval value, ovalue;
86166e63ce3Schristos 
86266e63ce3Schristos               value = *((struct itimerval *) t2h_addr(cb, &s, arg2));
86366e63ce3Schristos               translate_endian((void *) &value, sizeof(value));
86466e63ce3Schristos 
86566e63ce3Schristos               if (arg2 == 0)
86666e63ce3Schristos                 {
86766e63ce3Schristos                   result = setitimer(arg1, &value, NULL);
86866e63ce3Schristos                   errcode = errno;
86966e63ce3Schristos                 }
87066e63ce3Schristos               else
87166e63ce3Schristos                 {
87266e63ce3Schristos                   result = setitimer(arg1, &value, &ovalue);
87366e63ce3Schristos                   errcode = errno;
87466e63ce3Schristos 
87566e63ce3Schristos                   if (result != 0)
87666e63ce3Schristos                     break;
87766e63ce3Schristos 
87866e63ce3Schristos                   translate_endian((void *) &ovalue, sizeof(ovalue));
87966e63ce3Schristos                   if ((s.write_mem) (cb, &s, arg3, (char *) &ovalue, sizeof(ovalue))
88066e63ce3Schristos                       != sizeof(ovalue))
88166e63ce3Schristos                     {
88266e63ce3Schristos                       result = -1;
88366e63ce3Schristos                       errcode = EINVAL;
88466e63ce3Schristos                     }
88566e63ce3Schristos                 }
88666e63ce3Schristos             }
88766e63ce3Schristos             break;
88866e63ce3Schristos 
88966e63ce3Schristos           case __NR_getitimer:
89066e63ce3Schristos             {
89166e63ce3Schristos               struct itimerval value;
89266e63ce3Schristos 
89366e63ce3Schristos               result = getitimer(arg1, &value);
89466e63ce3Schristos               errcode = errno;
89566e63ce3Schristos 
89666e63ce3Schristos               if (result != 0)
89766e63ce3Schristos                 break;
89866e63ce3Schristos 
89966e63ce3Schristos               translate_endian((void *) &value, sizeof(value));
90066e63ce3Schristos               if ((s.write_mem) (cb, &s, arg2, (char *) &value, sizeof(value))
90166e63ce3Schristos                   != sizeof(value))
90266e63ce3Schristos                 {
90366e63ce3Schristos                   result = -1;
90466e63ce3Schristos                   errcode = EINVAL;
90566e63ce3Schristos                 }
90666e63ce3Schristos             }
90766e63ce3Schristos             break;
90866e63ce3Schristos 
90966e63ce3Schristos           case __NR_stat:
91066e63ce3Schristos             {
91166e63ce3Schristos               char *buf;
91266e63ce3Schristos               int buflen;
91366e63ce3Schristos               struct stat statbuf;
91466e63ce3Schristos 
91566e63ce3Schristos               result = stat((char *) t2h_addr(cb, &s, arg1), &statbuf);
91666e63ce3Schristos               errcode = errno;
91766e63ce3Schristos               if (result < 0)
91866e63ce3Schristos                 break;
91966e63ce3Schristos 
92066e63ce3Schristos               buflen = cb_host_to_target_stat (cb, NULL, NULL);
92166e63ce3Schristos               buf = xmalloc (buflen);
92266e63ce3Schristos               if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
92366e63ce3Schristos                 {
92466e63ce3Schristos                   /* The translation failed.  This is due to an internal
92566e63ce3Schristos                      host program error, not the target's fault.  */
92666e63ce3Schristos                   free (buf);
92766e63ce3Schristos                   result = -1;
92866e63ce3Schristos                   errcode = ENOSYS;
92966e63ce3Schristos                   break;
93066e63ce3Schristos                 }
93166e63ce3Schristos               if ((s.write_mem) (cb, &s, arg2, buf, buflen) != buflen)
93266e63ce3Schristos                 {
93366e63ce3Schristos                   free (buf);
93466e63ce3Schristos                   result = -1;
93566e63ce3Schristos                   errcode = EINVAL;
93666e63ce3Schristos                   break;
93766e63ce3Schristos                 }
93866e63ce3Schristos               free (buf);
93966e63ce3Schristos             }
94066e63ce3Schristos             break;
94166e63ce3Schristos 
94266e63ce3Schristos           case __NR_lstat:
94366e63ce3Schristos             {
94466e63ce3Schristos               char *buf;
94566e63ce3Schristos               int buflen;
94666e63ce3Schristos               struct stat statbuf;
94766e63ce3Schristos 
94866e63ce3Schristos               result = lstat((char *) t2h_addr(cb, &s, arg1), &statbuf);
94966e63ce3Schristos               errcode = errno;
95066e63ce3Schristos               if (result < 0)
95166e63ce3Schristos                 break;
95266e63ce3Schristos 
95366e63ce3Schristos               buflen = cb_host_to_target_stat (cb, NULL, NULL);
95466e63ce3Schristos               buf = xmalloc (buflen);
95566e63ce3Schristos               if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
95666e63ce3Schristos                 {
95766e63ce3Schristos                   /* The translation failed.  This is due to an internal
95866e63ce3Schristos                      host program error, not the target's fault.  */
95966e63ce3Schristos                   free (buf);
96066e63ce3Schristos                   result = -1;
96166e63ce3Schristos                   errcode = ENOSYS;
96266e63ce3Schristos                   break;
96366e63ce3Schristos                 }
96466e63ce3Schristos               if ((s.write_mem) (cb, &s, arg2, buf, buflen) != buflen)
96566e63ce3Schristos                 {
96666e63ce3Schristos                   free (buf);
96766e63ce3Schristos                   result = -1;
96866e63ce3Schristos                   errcode = EINVAL;
96966e63ce3Schristos                   break;
97066e63ce3Schristos                 }
97166e63ce3Schristos               free (buf);
97266e63ce3Schristos             }
97366e63ce3Schristos             break;
97466e63ce3Schristos 
97566e63ce3Schristos           case __NR_fstat:
97666e63ce3Schristos             {
97766e63ce3Schristos               char *buf;
97866e63ce3Schristos               int buflen;
97966e63ce3Schristos               struct stat statbuf;
98066e63ce3Schristos 
98166e63ce3Schristos               result = fstat(arg1, &statbuf);
98266e63ce3Schristos               errcode = errno;
98366e63ce3Schristos               if (result < 0)
98466e63ce3Schristos                 break;
98566e63ce3Schristos 
98666e63ce3Schristos               buflen = cb_host_to_target_stat (cb, NULL, NULL);
98766e63ce3Schristos               buf = xmalloc (buflen);
98866e63ce3Schristos               if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
98966e63ce3Schristos                 {
99066e63ce3Schristos                   /* The translation failed.  This is due to an internal
99166e63ce3Schristos                      host program error, not the target's fault.  */
99266e63ce3Schristos                   free (buf);
99366e63ce3Schristos                   result = -1;
99466e63ce3Schristos                   errcode = ENOSYS;
99566e63ce3Schristos                   break;
99666e63ce3Schristos                 }
99766e63ce3Schristos               if ((s.write_mem) (cb, &s, arg2, buf, buflen) != buflen)
99866e63ce3Schristos                 {
99966e63ce3Schristos                   free (buf);
100066e63ce3Schristos                   result = -1;
100166e63ce3Schristos                   errcode = EINVAL;
100266e63ce3Schristos                   break;
100366e63ce3Schristos                 }
100466e63ce3Schristos               free (buf);
100566e63ce3Schristos             }
100666e63ce3Schristos             break;
100766e63ce3Schristos 
100866e63ce3Schristos           case __NR_sysinfo:
100966e63ce3Schristos             {
101066e63ce3Schristos               struct sysinfo info;
101166e63ce3Schristos 
101266e63ce3Schristos               result = sysinfo(&info);
101366e63ce3Schristos               errcode = errno;
101466e63ce3Schristos 
101566e63ce3Schristos               if (result != 0)
101666e63ce3Schristos                 break;
101766e63ce3Schristos 
101866e63ce3Schristos               info.uptime    = conv_endian(info.uptime);
101966e63ce3Schristos               info.loads[0]  = conv_endian(info.loads[0]);
102066e63ce3Schristos               info.loads[1]  = conv_endian(info.loads[1]);
102166e63ce3Schristos               info.loads[2]  = conv_endian(info.loads[2]);
102266e63ce3Schristos               info.totalram  = conv_endian(info.totalram);
102366e63ce3Schristos               info.freeram   = conv_endian(info.freeram);
102466e63ce3Schristos               info.sharedram = conv_endian(info.sharedram);
102566e63ce3Schristos               info.bufferram = conv_endian(info.bufferram);
102666e63ce3Schristos               info.totalswap = conv_endian(info.totalswap);
102766e63ce3Schristos               info.freeswap  = conv_endian(info.freeswap);
102866e63ce3Schristos               info.procs     = conv_endian16(info.procs);
102966e63ce3Schristos #if LINUX_VERSION_CODE >= 0x20400
103066e63ce3Schristos               info.totalhigh = conv_endian(info.totalhigh);
103166e63ce3Schristos               info.freehigh  = conv_endian(info.freehigh);
103266e63ce3Schristos               info.mem_unit  = conv_endian(info.mem_unit);
103366e63ce3Schristos #endif
103466e63ce3Schristos               if ((s.write_mem) (cb, &s, arg1, (char *) &info, sizeof(info))
103566e63ce3Schristos                   != sizeof(info))
103666e63ce3Schristos                 {
103766e63ce3Schristos                   result = -1;
103866e63ce3Schristos                   errcode = EINVAL;
103966e63ce3Schristos                 }
104066e63ce3Schristos             }
104166e63ce3Schristos             break;
104266e63ce3Schristos 
104366e63ce3Schristos #if 0
104466e63ce3Schristos           case __NR_ipc:
104566e63ce3Schristos             {
104666e63ce3Schristos               result = ipc(arg1, arg2, arg3, arg4,
104766e63ce3Schristos                            (void *) t2h_addr(cb, &s, arg5), arg6);
104866e63ce3Schristos               errcode = errno;
104966e63ce3Schristos             }
105066e63ce3Schristos             break;
105166e63ce3Schristos #endif
105266e63ce3Schristos 
105366e63ce3Schristos           case __NR_fsync:
105466e63ce3Schristos             result = fsync(arg1);
105566e63ce3Schristos             errcode = errno;
105666e63ce3Schristos             break;
105766e63ce3Schristos 
105866e63ce3Schristos           case __NR_uname:
105966e63ce3Schristos             /* utsname contains only arrays of char, so it is not necessary
106066e63ce3Schristos                to translate endian. */
106166e63ce3Schristos             result = uname((struct utsname *) t2h_addr(cb, &s, arg1));
106266e63ce3Schristos             errcode = errno;
106366e63ce3Schristos             break;
106466e63ce3Schristos 
106566e63ce3Schristos           case __NR_adjtimex:
106666e63ce3Schristos             {
106766e63ce3Schristos               struct timex buf;
106866e63ce3Schristos 
106966e63ce3Schristos               result = adjtimex(&buf);
107066e63ce3Schristos               errcode = errno;
107166e63ce3Schristos 
107266e63ce3Schristos               if (result != 0)
107366e63ce3Schristos                 break;
107466e63ce3Schristos 
107566e63ce3Schristos               translate_endian((void *) &buf, sizeof(buf));
107666e63ce3Schristos               if ((s.write_mem) (cb, &s, arg1, (char *) &buf, sizeof(buf))
107766e63ce3Schristos                   != sizeof(buf))
107866e63ce3Schristos                 {
107966e63ce3Schristos                   result = -1;
108066e63ce3Schristos                   errcode = EINVAL;
108166e63ce3Schristos                 }
108266e63ce3Schristos             }
108366e63ce3Schristos             break;
108466e63ce3Schristos 
108566e63ce3Schristos           case __NR_mprotect:
108666e63ce3Schristos             result = mprotect((void *) arg1, arg2, arg3);
108766e63ce3Schristos             errcode = errno;
108866e63ce3Schristos             break;
108966e63ce3Schristos 
109066e63ce3Schristos           case __NR_fchdir:
109166e63ce3Schristos             result = fchdir(arg1);
109266e63ce3Schristos             errcode = errno;
109366e63ce3Schristos             break;
109466e63ce3Schristos 
109566e63ce3Schristos           case __NR_setfsuid32:
109666e63ce3Schristos           case __NR_setfsuid:
109766e63ce3Schristos             result = setfsuid(arg1);
109866e63ce3Schristos             errcode = errno;
109966e63ce3Schristos             break;
110066e63ce3Schristos 
110166e63ce3Schristos           case __NR_setfsgid32:
110266e63ce3Schristos           case __NR_setfsgid:
110366e63ce3Schristos             result = setfsgid(arg1);
110466e63ce3Schristos             errcode = errno;
110566e63ce3Schristos             break;
110666e63ce3Schristos 
110766e63ce3Schristos #if 0
110866e63ce3Schristos           case __NR__llseek:
110966e63ce3Schristos             {
111066e63ce3Schristos               loff_t buf;
111166e63ce3Schristos 
111266e63ce3Schristos               result = _llseek(arg1, arg2, arg3, &buf, arg5);
111366e63ce3Schristos               errcode = errno;
111466e63ce3Schristos 
111566e63ce3Schristos               if (result != 0)
111666e63ce3Schristos                 break;
111766e63ce3Schristos 
111866e63ce3Schristos               translate_endian((void *) &buf, sizeof(buf));
111966e63ce3Schristos               if ((s.write_mem) (cb, &s, t2h_addr(cb, &s, arg4),
112066e63ce3Schristos                                  (char *) &buf, sizeof(buf)) != sizeof(buf))
112166e63ce3Schristos                 {
112266e63ce3Schristos                   result = -1;
112366e63ce3Schristos                   errcode = EINVAL;
112466e63ce3Schristos                 }
112566e63ce3Schristos             }
112666e63ce3Schristos             break;
112766e63ce3Schristos 
112866e63ce3Schristos           case __NR_getdents:
112966e63ce3Schristos             {
113066e63ce3Schristos               struct dirent dir;
113166e63ce3Schristos 
113266e63ce3Schristos               result = getdents(arg1, &dir, arg3);
113366e63ce3Schristos               errcode = errno;
113466e63ce3Schristos 
113566e63ce3Schristos               if (result != 0)
113666e63ce3Schristos                 break;
113766e63ce3Schristos 
113866e63ce3Schristos               dir.d_ino = conv_endian(dir.d_ino);
113966e63ce3Schristos               dir.d_off = conv_endian(dir.d_off);
114066e63ce3Schristos               dir.d_reclen = conv_endian16(dir.d_reclen);
114166e63ce3Schristos               if ((s.write_mem) (cb, &s, arg2, (char *) &dir, sizeof(dir))
114266e63ce3Schristos                   != sizeof(dir))
114366e63ce3Schristos                 {
114466e63ce3Schristos                   result = -1;
114566e63ce3Schristos                   errcode = EINVAL;
114666e63ce3Schristos                 }
114766e63ce3Schristos             }
114866e63ce3Schristos             break;
114966e63ce3Schristos #endif
115066e63ce3Schristos 
115166e63ce3Schristos           case __NR_flock:
115266e63ce3Schristos             result = flock(arg1, arg2);
115366e63ce3Schristos             errcode = errno;
115466e63ce3Schristos             break;
115566e63ce3Schristos 
115666e63ce3Schristos           case __NR_msync:
115766e63ce3Schristos             result = msync((void *) arg1, arg2, arg3);
115866e63ce3Schristos             errcode = errno;
115966e63ce3Schristos             break;
116066e63ce3Schristos 
116166e63ce3Schristos           case __NR_readv:
116266e63ce3Schristos             {
116366e63ce3Schristos               struct iovec vector;
116466e63ce3Schristos 
116566e63ce3Schristos               vector = *((struct iovec *) t2h_addr(cb, &s, arg2));
116666e63ce3Schristos               translate_endian((void *) &vector, sizeof(vector));
116766e63ce3Schristos 
116866e63ce3Schristos               result = readv(arg1, &vector, arg3);
116966e63ce3Schristos               errcode = errno;
117066e63ce3Schristos             }
117166e63ce3Schristos             break;
117266e63ce3Schristos 
117366e63ce3Schristos           case __NR_writev:
117466e63ce3Schristos             {
117566e63ce3Schristos               struct iovec vector;
117666e63ce3Schristos 
117766e63ce3Schristos               vector = *((struct iovec *) t2h_addr(cb, &s, arg2));
117866e63ce3Schristos               translate_endian((void *) &vector, sizeof(vector));
117966e63ce3Schristos 
118066e63ce3Schristos               result = writev(arg1, &vector, arg3);
118166e63ce3Schristos               errcode = errno;
118266e63ce3Schristos             }
118366e63ce3Schristos             break;
118466e63ce3Schristos 
118566e63ce3Schristos           case __NR_fdatasync:
118666e63ce3Schristos             result = fdatasync(arg1);
118766e63ce3Schristos             errcode = errno;
118866e63ce3Schristos             break;
118966e63ce3Schristos 
119066e63ce3Schristos           case __NR_mlock:
119166e63ce3Schristos             result = mlock((void *) t2h_addr(cb, &s, arg1), arg2);
119266e63ce3Schristos             errcode = errno;
119366e63ce3Schristos             break;
119466e63ce3Schristos 
119566e63ce3Schristos           case __NR_munlock:
119666e63ce3Schristos             result = munlock((void *) t2h_addr(cb, &s, arg1), arg2);
119766e63ce3Schristos             errcode = errno;
119866e63ce3Schristos             break;
119966e63ce3Schristos 
120066e63ce3Schristos           case __NR_nanosleep:
120166e63ce3Schristos             {
120266e63ce3Schristos               struct timespec req, rem;
120366e63ce3Schristos 
120466e63ce3Schristos               req = *((struct timespec *) t2h_addr(cb, &s, arg2));
120566e63ce3Schristos               translate_endian((void *) &req, sizeof(req));
120666e63ce3Schristos 
120766e63ce3Schristos               result = nanosleep(&req, &rem);
120866e63ce3Schristos               errcode = errno;
120966e63ce3Schristos 
121066e63ce3Schristos               if (result != 0)
121166e63ce3Schristos                 break;
121266e63ce3Schristos 
121366e63ce3Schristos               translate_endian((void *) &rem, sizeof(rem));
121466e63ce3Schristos               if ((s.write_mem) (cb, &s, arg2, (char *) &rem, sizeof(rem))
121566e63ce3Schristos                   != sizeof(rem))
121666e63ce3Schristos                 {
121766e63ce3Schristos                   result = -1;
121866e63ce3Schristos                   errcode = EINVAL;
121966e63ce3Schristos                 }
122066e63ce3Schristos             }
122166e63ce3Schristos             break;
122266e63ce3Schristos 
122366e63ce3Schristos           case __NR_mremap: /* FIXME */
122466e63ce3Schristos             result = (int) mremap((void *) t2h_addr(cb, &s, arg1), arg2, arg3, arg4);
122566e63ce3Schristos             errcode = errno;
122666e63ce3Schristos             break;
122766e63ce3Schristos 
122866e63ce3Schristos           case __NR_getresuid32:
122966e63ce3Schristos           case __NR_getresuid:
123066e63ce3Schristos             {
123166e63ce3Schristos               uid_t ruid, euid, suid;
123266e63ce3Schristos 
123366e63ce3Schristos               result = getresuid(&ruid, &euid, &suid);
123466e63ce3Schristos               errcode = errno;
123566e63ce3Schristos 
123666e63ce3Schristos               if (result != 0)
123766e63ce3Schristos                 break;
123866e63ce3Schristos 
123966e63ce3Schristos               *((uid_t *) t2h_addr(cb, &s, arg1)) = conv_endian(ruid);
124066e63ce3Schristos               *((uid_t *) t2h_addr(cb, &s, arg2)) = conv_endian(euid);
124166e63ce3Schristos               *((uid_t *) t2h_addr(cb, &s, arg3)) = conv_endian(suid);
124266e63ce3Schristos             }
124366e63ce3Schristos             break;
124466e63ce3Schristos 
124566e63ce3Schristos           case __NR_poll:
124666e63ce3Schristos             {
124766e63ce3Schristos               struct pollfd ufds;
124866e63ce3Schristos 
124966e63ce3Schristos               ufds = *((struct pollfd *) t2h_addr(cb, &s, arg1));
125066e63ce3Schristos               ufds.fd = conv_endian(ufds.fd);
125166e63ce3Schristos               ufds.events = conv_endian16(ufds.events);
125266e63ce3Schristos               ufds.revents = conv_endian16(ufds.revents);
125366e63ce3Schristos 
125466e63ce3Schristos               result = poll(&ufds, arg2, arg3);
125566e63ce3Schristos               errcode = errno;
125666e63ce3Schristos             }
125766e63ce3Schristos             break;
125866e63ce3Schristos 
125966e63ce3Schristos           case __NR_getresgid32:
126066e63ce3Schristos           case __NR_getresgid:
126166e63ce3Schristos             {
126266e63ce3Schristos               uid_t rgid, egid, sgid;
126366e63ce3Schristos 
126466e63ce3Schristos               result = getresgid(&rgid, &egid, &sgid);
126566e63ce3Schristos               errcode = errno;
126666e63ce3Schristos 
126766e63ce3Schristos               if (result != 0)
126866e63ce3Schristos                 break;
126966e63ce3Schristos 
127066e63ce3Schristos               *((uid_t *) t2h_addr(cb, &s, arg1)) = conv_endian(rgid);
127166e63ce3Schristos               *((uid_t *) t2h_addr(cb, &s, arg2)) = conv_endian(egid);
127266e63ce3Schristos               *((uid_t *) t2h_addr(cb, &s, arg3)) = conv_endian(sgid);
127366e63ce3Schristos             }
127466e63ce3Schristos             break;
127566e63ce3Schristos 
127666e63ce3Schristos           case __NR_pread:
127766e63ce3Schristos             result =  pread(arg1, (void *) t2h_addr(cb, &s, arg2), arg3, arg4);
127866e63ce3Schristos             errcode = errno;
127966e63ce3Schristos             break;
128066e63ce3Schristos 
128166e63ce3Schristos           case __NR_pwrite:
128266e63ce3Schristos             result =  pwrite(arg1, (void *) t2h_addr(cb, &s, arg2), arg3, arg4);
128366e63ce3Schristos             errcode = errno;
128466e63ce3Schristos             break;
128566e63ce3Schristos 
128666e63ce3Schristos           case __NR_chown32:
128766e63ce3Schristos           case __NR_chown:
128866e63ce3Schristos             result = chown((char *) t2h_addr(cb, &s, arg1), arg2, arg3);
128966e63ce3Schristos             errcode = errno;
129066e63ce3Schristos             break;
129166e63ce3Schristos 
129266e63ce3Schristos           case __NR_getcwd:
129366e63ce3Schristos             result = (int) getcwd((char *) t2h_addr(cb, &s, arg1), arg2);
129466e63ce3Schristos             errcode = errno;
129566e63ce3Schristos             break;
129666e63ce3Schristos 
129766e63ce3Schristos           case __NR_sendfile:
129866e63ce3Schristos             {
129966e63ce3Schristos               off_t offset;
130066e63ce3Schristos 
130166e63ce3Schristos               offset = *((off_t *) t2h_addr(cb, &s, arg3));
130266e63ce3Schristos               offset = conv_endian(offset);
130366e63ce3Schristos 
130466e63ce3Schristos               result = sendfile(arg1, arg2, &offset, arg3);
130566e63ce3Schristos               errcode = errno;
130666e63ce3Schristos 
130766e63ce3Schristos               if (result != 0)
130866e63ce3Schristos                 break;
130966e63ce3Schristos 
131066e63ce3Schristos               *((off_t *) t2h_addr(cb, &s, arg3)) = conv_endian(offset);
131166e63ce3Schristos             }
131266e63ce3Schristos             break;
131366e63ce3Schristos 
131466e63ce3Schristos           default:
131566e63ce3Schristos             result = -1;
131666e63ce3Schristos             errcode = ENOSYS;
131766e63ce3Schristos             break;
131866e63ce3Schristos           }
131966e63ce3Schristos 
132066e63ce3Schristos         if (result == -1)
132166e63ce3Schristos 	  m32rbf_h_gr_set (current_cpu, 0, -errcode);
132266e63ce3Schristos         else
132366e63ce3Schristos 	  m32rbf_h_gr_set (current_cpu, 0, result);
132466e63ce3Schristos 	break;
132566e63ce3Schristos       }
132666e63ce3Schristos 
132766e63ce3Schristos     case TRAP_BREAKPOINT:
132866e63ce3Schristos       sim_engine_halt (sd, current_cpu, NULL, pc,
132966e63ce3Schristos 		       sim_stopped, SIM_SIGTRAP);
133066e63ce3Schristos       break;
133166e63ce3Schristos 
133266e63ce3Schristos     case TRAP_FLUSH_CACHE:
133366e63ce3Schristos       /* Do nothing.  */
133466e63ce3Schristos       break;
133566e63ce3Schristos 
133666e63ce3Schristos     default :
133766e63ce3Schristos       {
133866e63ce3Schristos 	/* Use cr5 as EVB (EIT Vector Base) register.  */
133966e63ce3Schristos         USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4;
134066e63ce3Schristos 	return new_pc;
134166e63ce3Schristos       }
134266e63ce3Schristos     }
134366e63ce3Schristos 
134466e63ce3Schristos   /* Fake an "rte" insn.  */
134566e63ce3Schristos   /* FIXME: Should duplicate all of rte processing.  */
134666e63ce3Schristos   return (pc & -4) + 4;
134766e63ce3Schristos }
1348