mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-31 20:44:16 +00:00 
			
		
		
		
	 fcf5ef2ab5
			
		
	
	
		fcf5ef2ab5
		
	
	
	
	
		
			
			We've currently got 18 architectures in QEMU, and thus 18 target-xxx folders in the root folder of the QEMU source tree. More architectures (e.g. RISC-V, AVR) are likely to be included soon, too, so the main folder of the QEMU sources slowly gets quite overcrowded with the target-xxx folders. To disburden the main folder a little bit, let's move the target-xxx folders into a dedicated target/ folder, so that target-xxx/ simply becomes target/xxx/ instead. Acked-by: Laurent Vivier <laurent@vivier.eu> [m68k part] Acked-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> [tricore part] Acked-by: Michael Walle <michael@walle.cc> [lm32 part] Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com> [s390x part] Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> [s390x part] Acked-by: Eduardo Habkost <ehabkost@redhat.com> [i386 part] Acked-by: Artyom Tarasenko <atar4qemu@gmail.com> [sparc part] Acked-by: Richard Henderson <rth@twiddle.net> [alpha part] Acked-by: Max Filippov <jcmvbkbc@gmail.com> [xtensa part] Reviewed-by: David Gibson <david@gibson.dropbear.id.au> [ppc part] Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> [crisµblaze part] Acked-by: Guan Xuetao <gxt@mprc.pku.edu.cn> [unicore32 part] Signed-off-by: Thomas Huth <thuth@redhat.com>
		
			
				
	
	
		
			213 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  *  Lattice Mico32 semihosting syscall interface
 | |
|  *
 | |
|  *  Copyright (c) 2014 Michael Walle <michael@walle.cc>
 | |
|  *
 | |
|  * Based on target/m68k/m68k-semi.c, which is
 | |
|  *  Copyright (c) 2005-2007 CodeSourcery.
 | |
|  *
 | |
|  * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | |
|  * See the COPYING file in the top-level directory.
 | |
|  */
 | |
| 
 | |
| #include "qemu/osdep.h"
 | |
| #include "cpu.h"
 | |
| #include "exec/helper-proto.h"
 | |
| #include "qemu/log.h"
 | |
| #include "exec/softmmu-semi.h"
 | |
| 
 | |
| enum {
 | |
|     TARGET_SYS_exit    = 1,
 | |
|     TARGET_SYS_open    = 2,
 | |
|     TARGET_SYS_close   = 3,
 | |
|     TARGET_SYS_read    = 4,
 | |
|     TARGET_SYS_write   = 5,
 | |
|     TARGET_SYS_lseek   = 6,
 | |
|     TARGET_SYS_fstat   = 10,
 | |
|     TARGET_SYS_stat    = 15,
 | |
| };
 | |
| 
 | |
| enum {
 | |
|     NEWLIB_O_RDONLY    =   0x0,
 | |
|     NEWLIB_O_WRONLY    =   0x1,
 | |
|     NEWLIB_O_RDWR      =   0x2,
 | |
|     NEWLIB_O_APPEND    =   0x8,
 | |
|     NEWLIB_O_CREAT     = 0x200,
 | |
|     NEWLIB_O_TRUNC     = 0x400,
 | |
|     NEWLIB_O_EXCL      = 0x800,
 | |
| };
 | |
| 
 | |
| static int translate_openflags(int flags)
 | |
| {
 | |
|     int hf;
 | |
| 
 | |
|     if (flags & NEWLIB_O_WRONLY) {
 | |
|         hf = O_WRONLY;
 | |
|     } else if (flags & NEWLIB_O_RDWR) {
 | |
|         hf = O_RDWR;
 | |
|     } else {
 | |
|         hf = O_RDONLY;
 | |
|     }
 | |
| 
 | |
|     if (flags & NEWLIB_O_APPEND) {
 | |
|         hf |= O_APPEND;
 | |
|     }
 | |
| 
 | |
|     if (flags & NEWLIB_O_CREAT) {
 | |
|         hf |= O_CREAT;
 | |
|     }
 | |
| 
 | |
|     if (flags & NEWLIB_O_TRUNC) {
 | |
|         hf |= O_TRUNC;
 | |
|     }
 | |
| 
 | |
|     if (flags & NEWLIB_O_EXCL) {
 | |
|         hf |= O_EXCL;
 | |
|     }
 | |
| 
 | |
|     return hf;
 | |
| }
 | |
| 
 | |
| struct newlib_stat {
 | |
|     int16_t     newlib_st_dev;     /* device */
 | |
|     uint16_t    newlib_st_ino;     /* inode */
 | |
|     uint16_t    newlib_st_mode;    /* protection */
 | |
|     uint16_t    newlib_st_nlink;   /* number of hard links */
 | |
|     uint16_t    newlib_st_uid;     /* user ID of owner */
 | |
|     uint16_t    newlib_st_gid;     /* group ID of owner */
 | |
|     int16_t     newlib_st_rdev;    /* device type (if inode device) */
 | |
|     int32_t     newlib_st_size;    /* total size, in bytes */
 | |
|     int32_t     newlib_st_atime;   /* time of last access */
 | |
|     uint32_t    newlib_st_spare1;
 | |
|     int32_t     newlib_st_mtime;   /* time of last modification */
 | |
|     uint32_t    newlib_st_spare2;
 | |
|     int32_t     newlib_st_ctime;   /* time of last change */
 | |
|     uint32_t    newlib_st_spare3;
 | |
| } QEMU_PACKED;
 | |
| 
 | |
| static int translate_stat(CPULM32State *env, target_ulong addr,
 | |
|         struct stat *s)
 | |
| {
 | |
|     struct newlib_stat *p;
 | |
| 
 | |
|     p = lock_user(VERIFY_WRITE, addr, sizeof(struct newlib_stat), 0);
 | |
|     if (!p) {
 | |
|         return 0;
 | |
|     }
 | |
|     p->newlib_st_dev = cpu_to_be16(s->st_dev);
 | |
|     p->newlib_st_ino = cpu_to_be16(s->st_ino);
 | |
|     p->newlib_st_mode = cpu_to_be16(s->st_mode);
 | |
|     p->newlib_st_nlink = cpu_to_be16(s->st_nlink);
 | |
|     p->newlib_st_uid = cpu_to_be16(s->st_uid);
 | |
|     p->newlib_st_gid = cpu_to_be16(s->st_gid);
 | |
|     p->newlib_st_rdev = cpu_to_be16(s->st_rdev);
 | |
|     p->newlib_st_size = cpu_to_be32(s->st_size);
 | |
|     p->newlib_st_atime = cpu_to_be32(s->st_atime);
 | |
|     p->newlib_st_mtime = cpu_to_be32(s->st_mtime);
 | |
|     p->newlib_st_ctime = cpu_to_be32(s->st_ctime);
 | |
|     unlock_user(p, addr, sizeof(struct newlib_stat));
 | |
| 
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| bool lm32_cpu_do_semihosting(CPUState *cs)
 | |
| {
 | |
|     LM32CPU *cpu = LM32_CPU(cs);
 | |
|     CPULM32State *env = &cpu->env;
 | |
| 
 | |
|     int ret = -1;
 | |
|     target_ulong nr, arg0, arg1, arg2;
 | |
|     void *p;
 | |
|     struct stat s;
 | |
| 
 | |
|     nr = env->regs[R_R8];
 | |
|     arg0 = env->regs[R_R1];
 | |
|     arg1 = env->regs[R_R2];
 | |
|     arg2 = env->regs[R_R3];
 | |
| 
 | |
|     switch (nr) {
 | |
|     case TARGET_SYS_exit:
 | |
|         /* void _exit(int rc) */
 | |
|         exit(arg0);
 | |
| 
 | |
|     case TARGET_SYS_open:
 | |
|         /* int open(const char *pathname, int flags) */
 | |
|         p = lock_user_string(arg0);
 | |
|         if (!p) {
 | |
|             ret = -1;
 | |
|         } else {
 | |
|             ret = open(p, translate_openflags(arg2));
 | |
|             unlock_user(p, arg0, 0);
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|     case TARGET_SYS_read:
 | |
|         /* ssize_t read(int fd, const void *buf, size_t count) */
 | |
|         p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
 | |
|         if (!p) {
 | |
|             ret = -1;
 | |
|         } else {
 | |
|             ret = read(arg0, p, arg2);
 | |
|             unlock_user(p, arg1, arg2);
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|     case TARGET_SYS_write:
 | |
|         /* ssize_t write(int fd, const void *buf, size_t count) */
 | |
|         p = lock_user(VERIFY_READ, arg1, arg2, 1);
 | |
|         if (!p) {
 | |
|             ret = -1;
 | |
|         } else {
 | |
|             ret = write(arg0, p, arg2);
 | |
|             unlock_user(p, arg1, 0);
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|     case TARGET_SYS_close:
 | |
|         /* int close(int fd) */
 | |
|         /* don't close stdin/stdout/stderr */
 | |
|         if (arg0 > 2) {
 | |
|             ret = close(arg0);
 | |
|         } else {
 | |
|             ret = 0;
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|     case TARGET_SYS_lseek:
 | |
|         /* off_t lseek(int fd, off_t offset, int whence */
 | |
|         ret = lseek(arg0, arg1, arg2);
 | |
|         break;
 | |
| 
 | |
|     case TARGET_SYS_stat:
 | |
|         /* int stat(const char *path, struct stat *buf) */
 | |
|         p = lock_user_string(arg0);
 | |
|         if (!p) {
 | |
|             ret = -1;
 | |
|         } else {
 | |
|             ret = stat(p, &s);
 | |
|             unlock_user(p, arg0, 0);
 | |
|             if (translate_stat(env, arg1, &s) == 0) {
 | |
|                 ret = -1;
 | |
|             }
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|     case TARGET_SYS_fstat:
 | |
|         /* int stat(int fd, struct stat *buf) */
 | |
|         ret = fstat(arg0, &s);
 | |
|         if (ret == 0) {
 | |
|             if (translate_stat(env, arg1, &s) == 0) {
 | |
|                 ret = -1;
 | |
|             }
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|     default:
 | |
|         /* unhandled */
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     env->regs[R_R1] = ret;
 | |
|     return true;
 | |
| }
 |