13b3c1694SLeon Alrae /* 23b3c1694SLeon Alrae * Unified Hosting Interface syscalls. 33b3c1694SLeon Alrae * 43b3c1694SLeon Alrae * Copyright (c) 2015 Imagination Technologies 53b3c1694SLeon Alrae * 63b3c1694SLeon Alrae * This library is free software; you can redistribute it and/or 73b3c1694SLeon Alrae * modify it under the terms of the GNU Lesser General Public 83b3c1694SLeon Alrae * License as published by the Free Software Foundation; either 989975214SChetan Pant * version 2.1 of the License, or (at your option) any later version. 103b3c1694SLeon Alrae * 113b3c1694SLeon Alrae * This library is distributed in the hope that it will be useful, 123b3c1694SLeon Alrae * but WITHOUT ANY WARRANTY; without even the implied warranty of 133b3c1694SLeon Alrae * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 143b3c1694SLeon Alrae * Lesser General Public License for more details. 153b3c1694SLeon Alrae * 163b3c1694SLeon Alrae * You should have received a copy of the GNU Lesser General Public 173b3c1694SLeon Alrae * License along with this library; if not, see <http://www.gnu.org/licenses/>. 183b3c1694SLeon Alrae */ 193b3c1694SLeon Alrae 20c684822aSPeter Maydell #include "qemu/osdep.h" 213b3c1694SLeon Alrae #include "cpu.h" 2263c91552SPaolo Bonzini #include "qemu/log.h" 23c89a14adSRichard Henderson #include "semihosting/softmmu-uaccess.h" 246b5fe137SPhilippe Mathieu-Daudé #include "semihosting/semihost.h" 256b5fe137SPhilippe Mathieu-Daudé #include "semihosting/console.h" 268ec7e3c5SRichard Henderson #include "internal.h" 273b3c1694SLeon Alrae 283b3c1694SLeon Alrae typedef enum UHIOp { 293b3c1694SLeon Alrae UHI_exit = 1, 303b3c1694SLeon Alrae UHI_open = 2, 313b3c1694SLeon Alrae UHI_close = 3, 323b3c1694SLeon Alrae UHI_read = 4, 333b3c1694SLeon Alrae UHI_write = 5, 343b3c1694SLeon Alrae UHI_lseek = 6, 353b3c1694SLeon Alrae UHI_unlink = 7, 363b3c1694SLeon Alrae UHI_fstat = 8, 373b3c1694SLeon Alrae UHI_argc = 9, 383b3c1694SLeon Alrae UHI_argnlen = 10, 393b3c1694SLeon Alrae UHI_argn = 11, 403b3c1694SLeon Alrae UHI_plog = 13, 413b3c1694SLeon Alrae UHI_assert = 14, 423b3c1694SLeon Alrae UHI_pread = 19, 433b3c1694SLeon Alrae UHI_pwrite = 20, 443b3c1694SLeon Alrae UHI_link = 22 453b3c1694SLeon Alrae } UHIOp; 463b3c1694SLeon Alrae 473b3c1694SLeon Alrae typedef struct UHIStat { 483b3c1694SLeon Alrae int16_t uhi_st_dev; 493b3c1694SLeon Alrae uint16_t uhi_st_ino; 503b3c1694SLeon Alrae uint32_t uhi_st_mode; 513b3c1694SLeon Alrae uint16_t uhi_st_nlink; 523b3c1694SLeon Alrae uint16_t uhi_st_uid; 533b3c1694SLeon Alrae uint16_t uhi_st_gid; 543b3c1694SLeon Alrae int16_t uhi_st_rdev; 553b3c1694SLeon Alrae uint64_t uhi_st_size; 563b3c1694SLeon Alrae uint64_t uhi_st_atime; 573b3c1694SLeon Alrae uint64_t uhi_st_spare1; 583b3c1694SLeon Alrae uint64_t uhi_st_mtime; 593b3c1694SLeon Alrae uint64_t uhi_st_spare2; 603b3c1694SLeon Alrae uint64_t uhi_st_ctime; 613b3c1694SLeon Alrae uint64_t uhi_st_spare3; 623b3c1694SLeon Alrae uint64_t uhi_st_blksize; 633b3c1694SLeon Alrae uint64_t uhi_st_blocks; 643b3c1694SLeon Alrae uint64_t uhi_st_spare4[2]; 653b3c1694SLeon Alrae } UHIStat; 663b3c1694SLeon Alrae 673b3c1694SLeon Alrae enum UHIOpenFlags { 683b3c1694SLeon Alrae UHIOpen_RDONLY = 0x0, 693b3c1694SLeon Alrae UHIOpen_WRONLY = 0x1, 703b3c1694SLeon Alrae UHIOpen_RDWR = 0x2, 713b3c1694SLeon Alrae UHIOpen_APPEND = 0x8, 723b3c1694SLeon Alrae UHIOpen_CREAT = 0x200, 733b3c1694SLeon Alrae UHIOpen_TRUNC = 0x400, 743b3c1694SLeon Alrae UHIOpen_EXCL = 0x800 753b3c1694SLeon Alrae }; 763b3c1694SLeon Alrae 777ba6e53aSRichard Henderson enum UHIErrno { 787ba6e53aSRichard Henderson UHI_EACCESS = 13, 797ba6e53aSRichard Henderson UHI_EAGAIN = 11, 807ba6e53aSRichard Henderson UHI_EBADF = 9, 817ba6e53aSRichard Henderson UHI_EBADMSG = 77, 827ba6e53aSRichard Henderson UHI_EBUSY = 16, 837ba6e53aSRichard Henderson UHI_ECONNRESET = 104, 847ba6e53aSRichard Henderson UHI_EEXIST = 17, 857ba6e53aSRichard Henderson UHI_EFBIG = 27, 867ba6e53aSRichard Henderson UHI_EINTR = 4, 877ba6e53aSRichard Henderson UHI_EINVAL = 22, 887ba6e53aSRichard Henderson UHI_EIO = 5, 897ba6e53aSRichard Henderson UHI_EISDIR = 21, 907ba6e53aSRichard Henderson UHI_ELOOP = 92, 917ba6e53aSRichard Henderson UHI_EMFILE = 24, 927ba6e53aSRichard Henderson UHI_EMLINK = 31, 937ba6e53aSRichard Henderson UHI_ENAMETOOLONG = 91, 947ba6e53aSRichard Henderson UHI_ENETDOWN = 115, 957ba6e53aSRichard Henderson UHI_ENETUNREACH = 114, 967ba6e53aSRichard Henderson UHI_ENFILE = 23, 977ba6e53aSRichard Henderson UHI_ENOBUFS = 105, 987ba6e53aSRichard Henderson UHI_ENOENT = 2, 997ba6e53aSRichard Henderson UHI_ENOMEM = 12, 1007ba6e53aSRichard Henderson UHI_ENOSPC = 28, 1017ba6e53aSRichard Henderson UHI_ENOSR = 63, 1027ba6e53aSRichard Henderson UHI_ENOTCONN = 128, 1037ba6e53aSRichard Henderson UHI_ENOTDIR = 20, 1047ba6e53aSRichard Henderson UHI_ENXIO = 6, 1057ba6e53aSRichard Henderson UHI_EOVERFLOW = 139, 1067ba6e53aSRichard Henderson UHI_EPERM = 1, 1077ba6e53aSRichard Henderson UHI_EPIPE = 32, 1087ba6e53aSRichard Henderson UHI_ERANGE = 34, 1097ba6e53aSRichard Henderson UHI_EROFS = 30, 1107ba6e53aSRichard Henderson UHI_ESPIPE = 29, 1117ba6e53aSRichard Henderson UHI_ETIMEDOUT = 116, 1127ba6e53aSRichard Henderson UHI_ETXTBSY = 26, 1137ba6e53aSRichard Henderson UHI_EWOULDBLOCK = 11, 1147ba6e53aSRichard Henderson UHI_EXDEV = 18, 1157ba6e53aSRichard Henderson }; 1167ba6e53aSRichard Henderson 117*d53a3ed4SRichard Henderson static void report_fault(CPUMIPSState *env) 118*d53a3ed4SRichard Henderson { 119*d53a3ed4SRichard Henderson int op = env->active_tc.gpr[25]; 120*d53a3ed4SRichard Henderson error_report("Fault during UHI operation %d", op); 121*d53a3ed4SRichard Henderson abort(); 122*d53a3ed4SRichard Henderson } 123*d53a3ed4SRichard Henderson 124d859a77dSPhilippe Mathieu-Daudé static int errno_mips(int host_errno) 125d859a77dSPhilippe Mathieu-Daudé { 1262c44b19cSLeon Alrae /* Errno values taken from asm-mips/errno.h */ 127d859a77dSPhilippe Mathieu-Daudé switch (host_errno) { 128d859a77dSPhilippe Mathieu-Daudé case 0: return 0; 129d859a77dSPhilippe Mathieu-Daudé case ENAMETOOLONG: return 78; 1302c44b19cSLeon Alrae #ifdef EOVERFLOW 131d859a77dSPhilippe Mathieu-Daudé case EOVERFLOW: return 79; 1322c44b19cSLeon Alrae #endif 1332c44b19cSLeon Alrae #ifdef ELOOP 134d859a77dSPhilippe Mathieu-Daudé case ELOOP: return 90; 1352c44b19cSLeon Alrae #endif 136d859a77dSPhilippe Mathieu-Daudé default: return EINVAL; 1372c44b19cSLeon Alrae } 1382c44b19cSLeon Alrae } 1392c44b19cSLeon Alrae 1403b3c1694SLeon Alrae static int copy_stat_to_target(CPUMIPSState *env, const struct stat *src, 1413b3c1694SLeon Alrae target_ulong vaddr) 1423b3c1694SLeon Alrae { 1433b3c1694SLeon Alrae hwaddr len = sizeof(struct UHIStat); 1443b3c1694SLeon Alrae UHIStat *dst = lock_user(VERIFY_WRITE, vaddr, len, 0); 1453b3c1694SLeon Alrae if (!dst) { 146*d53a3ed4SRichard Henderson report_fault(env); 1473b3c1694SLeon Alrae } 1483b3c1694SLeon Alrae 1493b3c1694SLeon Alrae dst->uhi_st_dev = tswap16(src->st_dev); 1503b3c1694SLeon Alrae dst->uhi_st_ino = tswap16(src->st_ino); 1513b3c1694SLeon Alrae dst->uhi_st_mode = tswap32(src->st_mode); 1523b3c1694SLeon Alrae dst->uhi_st_nlink = tswap16(src->st_nlink); 1533b3c1694SLeon Alrae dst->uhi_st_uid = tswap16(src->st_uid); 1543b3c1694SLeon Alrae dst->uhi_st_gid = tswap16(src->st_gid); 1553b3c1694SLeon Alrae dst->uhi_st_rdev = tswap16(src->st_rdev); 1563b3c1694SLeon Alrae dst->uhi_st_size = tswap64(src->st_size); 1573b3c1694SLeon Alrae dst->uhi_st_atime = tswap64(src->st_atime); 1583b3c1694SLeon Alrae dst->uhi_st_mtime = tswap64(src->st_mtime); 1593b3c1694SLeon Alrae dst->uhi_st_ctime = tswap64(src->st_ctime); 1603b3c1694SLeon Alrae #ifdef _WIN32 1613b3c1694SLeon Alrae dst->uhi_st_blksize = 0; 1623b3c1694SLeon Alrae dst->uhi_st_blocks = 0; 1633b3c1694SLeon Alrae #else 1643b3c1694SLeon Alrae dst->uhi_st_blksize = tswap64(src->st_blksize); 1653b3c1694SLeon Alrae dst->uhi_st_blocks = tswap64(src->st_blocks); 1663b3c1694SLeon Alrae #endif 1673b3c1694SLeon Alrae unlock_user(dst, vaddr, len); 1683b3c1694SLeon Alrae return 0; 1693b3c1694SLeon Alrae } 1703b3c1694SLeon Alrae 1713b3c1694SLeon Alrae static int get_open_flags(target_ulong target_flags) 1723b3c1694SLeon Alrae { 1733b3c1694SLeon Alrae int open_flags = 0; 1743b3c1694SLeon Alrae 1753b3c1694SLeon Alrae if (target_flags & UHIOpen_RDWR) { 1763b3c1694SLeon Alrae open_flags |= O_RDWR; 1773b3c1694SLeon Alrae } else if (target_flags & UHIOpen_WRONLY) { 1783b3c1694SLeon Alrae open_flags |= O_WRONLY; 1793b3c1694SLeon Alrae } else { 1803b3c1694SLeon Alrae open_flags |= O_RDONLY; 1813b3c1694SLeon Alrae } 1823b3c1694SLeon Alrae 1833b3c1694SLeon Alrae open_flags |= (target_flags & UHIOpen_APPEND) ? O_APPEND : 0; 1843b3c1694SLeon Alrae open_flags |= (target_flags & UHIOpen_CREAT) ? O_CREAT : 0; 1853b3c1694SLeon Alrae open_flags |= (target_flags & UHIOpen_TRUNC) ? O_TRUNC : 0; 1863b3c1694SLeon Alrae open_flags |= (target_flags & UHIOpen_EXCL) ? O_EXCL : 0; 1873b3c1694SLeon Alrae 1883b3c1694SLeon Alrae return open_flags; 1893b3c1694SLeon Alrae } 1903b3c1694SLeon Alrae 1916863e92dSRichard Henderson static int write_to_file(CPUMIPSState *env, target_ulong fd, 1926863e92dSRichard Henderson target_ulong vaddr, target_ulong len) 1933b3c1694SLeon Alrae { 1943b3c1694SLeon Alrae int num_of_bytes; 1953b3c1694SLeon Alrae void *dst = lock_user(VERIFY_READ, vaddr, len, 1); 1963b3c1694SLeon Alrae if (!dst) { 197*d53a3ed4SRichard Henderson report_fault(env); 1983b3c1694SLeon Alrae } 1993b3c1694SLeon Alrae 2003b3c1694SLeon Alrae num_of_bytes = write(fd, dst, len); 2013b3c1694SLeon Alrae 2023b3c1694SLeon Alrae unlock_user(dst, vaddr, 0); 2033b3c1694SLeon Alrae return num_of_bytes; 2043b3c1694SLeon Alrae } 2053b3c1694SLeon Alrae 2063b3c1694SLeon Alrae static int read_from_file(CPUMIPSState *env, target_ulong fd, 2076863e92dSRichard Henderson target_ulong vaddr, target_ulong len) 2083b3c1694SLeon Alrae { 2093b3c1694SLeon Alrae int num_of_bytes; 2103b3c1694SLeon Alrae void *dst = lock_user(VERIFY_WRITE, vaddr, len, 0); 2113b3c1694SLeon Alrae if (!dst) { 212*d53a3ed4SRichard Henderson report_fault(env); 2133b3c1694SLeon Alrae } 2143b3c1694SLeon Alrae 2153b3c1694SLeon Alrae num_of_bytes = read(fd, dst, len); 2163b3c1694SLeon Alrae 2173b3c1694SLeon Alrae unlock_user(dst, vaddr, len); 2183b3c1694SLeon Alrae return num_of_bytes; 2193b3c1694SLeon Alrae } 2203b3c1694SLeon Alrae 2213b3c1694SLeon Alrae static int copy_argn_to_target(CPUMIPSState *env, int arg_num, 2223b3c1694SLeon Alrae target_ulong vaddr) 2233b3c1694SLeon Alrae { 2243b3c1694SLeon Alrae int strsize = strlen(semihosting_get_arg(arg_num)) + 1; 2253b3c1694SLeon Alrae char *dst = lock_user(VERIFY_WRITE, vaddr, strsize, 0); 2263b3c1694SLeon Alrae if (!dst) { 227*d53a3ed4SRichard Henderson report_fault(env); 2283b3c1694SLeon Alrae } 2293b3c1694SLeon Alrae 2303b3c1694SLeon Alrae strcpy(dst, semihosting_get_arg(arg_num)); 2313b3c1694SLeon Alrae 2323b3c1694SLeon Alrae unlock_user(dst, vaddr, strsize); 2333b3c1694SLeon Alrae return 0; 2343b3c1694SLeon Alrae } 2353b3c1694SLeon Alrae 2363b3c1694SLeon Alrae #define GET_TARGET_STRING(p, addr) \ 2373b3c1694SLeon Alrae do { \ 2383b3c1694SLeon Alrae p = lock_user_string(addr); \ 2393b3c1694SLeon Alrae if (!p) { \ 240*d53a3ed4SRichard Henderson report_fault(env); \ 2413b3c1694SLeon Alrae } \ 2423b3c1694SLeon Alrae } while (0) 2433b3c1694SLeon Alrae 24426e7e982SLeon Alrae #define GET_TARGET_STRINGS_2(p, addr, p2, addr2) \ 24526e7e982SLeon Alrae do { \ 24626e7e982SLeon Alrae p = lock_user_string(addr); \ 24726e7e982SLeon Alrae if (!p) { \ 248*d53a3ed4SRichard Henderson report_fault(env); \ 24926e7e982SLeon Alrae } \ 25026e7e982SLeon Alrae p2 = lock_user_string(addr2); \ 25126e7e982SLeon Alrae if (!p2) { \ 252*d53a3ed4SRichard Henderson report_fault(env); \ 25326e7e982SLeon Alrae } \ 25426e7e982SLeon Alrae } while (0) 25526e7e982SLeon Alrae 2563b3c1694SLeon Alrae #define FREE_TARGET_STRING(p, gpr) \ 2573b3c1694SLeon Alrae do { \ 2583b3c1694SLeon Alrae unlock_user(p, gpr, 0); \ 2593b3c1694SLeon Alrae } while (0) 2603b3c1694SLeon Alrae 2618ec7e3c5SRichard Henderson void mips_semihosting(CPUMIPSState *env) 2623b3c1694SLeon Alrae { 2633b3c1694SLeon Alrae target_ulong *gpr = env->active_tc.gpr; 2643b3c1694SLeon Alrae const UHIOp op = gpr[25]; 2653b3c1694SLeon Alrae char *p, *p2; 2663b3c1694SLeon Alrae 2673b3c1694SLeon Alrae switch (op) { 2683b3c1694SLeon Alrae case UHI_exit: 2693b3c1694SLeon Alrae qemu_log("UHI(%d): exit(%d)\n", op, (int)gpr[4]); 2703b3c1694SLeon Alrae exit(gpr[4]); 2713b3c1694SLeon Alrae case UHI_open: 2723b3c1694SLeon Alrae GET_TARGET_STRING(p, gpr[4]); 2733b3c1694SLeon Alrae if (!strcmp("/dev/stdin", p)) { 2743b3c1694SLeon Alrae gpr[2] = 0; 2753b3c1694SLeon Alrae } else if (!strcmp("/dev/stdout", p)) { 2763b3c1694SLeon Alrae gpr[2] = 1; 2773b3c1694SLeon Alrae } else if (!strcmp("/dev/stderr", p)) { 2783b3c1694SLeon Alrae gpr[2] = 2; 2793b3c1694SLeon Alrae } else { 2803b3c1694SLeon Alrae gpr[2] = open(p, get_open_flags(gpr[5]), gpr[6]); 2812c44b19cSLeon Alrae gpr[3] = errno_mips(errno); 2823b3c1694SLeon Alrae } 2833b3c1694SLeon Alrae FREE_TARGET_STRING(p, gpr[4]); 2843b3c1694SLeon Alrae break; 2853b3c1694SLeon Alrae case UHI_close: 2863b3c1694SLeon Alrae if (gpr[4] < 3) { 2873b3c1694SLeon Alrae /* ignore closing stdin/stdout/stderr */ 2883b3c1694SLeon Alrae gpr[2] = 0; 28954fc33fdSDaniel Henrique Barboza return; 2903b3c1694SLeon Alrae } 2913b3c1694SLeon Alrae gpr[2] = close(gpr[4]); 2922c44b19cSLeon Alrae gpr[3] = errno_mips(errno); 2933b3c1694SLeon Alrae break; 2943b3c1694SLeon Alrae case UHI_read: 2956863e92dSRichard Henderson gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6]); 2962c44b19cSLeon Alrae gpr[3] = errno_mips(errno); 2973b3c1694SLeon Alrae break; 2983b3c1694SLeon Alrae case UHI_write: 2996863e92dSRichard Henderson gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6]); 3002c44b19cSLeon Alrae gpr[3] = errno_mips(errno); 3013b3c1694SLeon Alrae break; 3023b3c1694SLeon Alrae case UHI_lseek: 3033b3c1694SLeon Alrae gpr[2] = lseek(gpr[4], gpr[5], gpr[6]); 3042c44b19cSLeon Alrae gpr[3] = errno_mips(errno); 3053b3c1694SLeon Alrae break; 3063b3c1694SLeon Alrae case UHI_unlink: 3073b3c1694SLeon Alrae GET_TARGET_STRING(p, gpr[4]); 3083b3c1694SLeon Alrae gpr[2] = remove(p); 3092c44b19cSLeon Alrae gpr[3] = errno_mips(errno); 3103b3c1694SLeon Alrae FREE_TARGET_STRING(p, gpr[4]); 3113b3c1694SLeon Alrae break; 3123b3c1694SLeon Alrae case UHI_fstat: 3133b3c1694SLeon Alrae { 3143b3c1694SLeon Alrae struct stat sbuf; 3153b3c1694SLeon Alrae memset(&sbuf, 0, sizeof(sbuf)); 3163b3c1694SLeon Alrae gpr[2] = fstat(gpr[4], &sbuf); 3172c44b19cSLeon Alrae gpr[3] = errno_mips(errno); 3183b3c1694SLeon Alrae if (gpr[2]) { 31954fc33fdSDaniel Henrique Barboza return; 3203b3c1694SLeon Alrae } 3213b3c1694SLeon Alrae gpr[2] = copy_stat_to_target(env, &sbuf, gpr[5]); 3222c44b19cSLeon Alrae gpr[3] = errno_mips(errno); 3233b3c1694SLeon Alrae } 3243b3c1694SLeon Alrae break; 3253b3c1694SLeon Alrae case UHI_argc: 3263b3c1694SLeon Alrae gpr[2] = semihosting_get_argc(); 3273b3c1694SLeon Alrae break; 3283b3c1694SLeon Alrae case UHI_argnlen: 3293b3c1694SLeon Alrae if (gpr[4] >= semihosting_get_argc()) { 3303b3c1694SLeon Alrae gpr[2] = -1; 33154fc33fdSDaniel Henrique Barboza return; 3323b3c1694SLeon Alrae } 3333b3c1694SLeon Alrae gpr[2] = strlen(semihosting_get_arg(gpr[4])); 3343b3c1694SLeon Alrae break; 3353b3c1694SLeon Alrae case UHI_argn: 3363b3c1694SLeon Alrae if (gpr[4] >= semihosting_get_argc()) { 3373b3c1694SLeon Alrae gpr[2] = -1; 33854fc33fdSDaniel Henrique Barboza return; 3393b3c1694SLeon Alrae } 3403b3c1694SLeon Alrae gpr[2] = copy_argn_to_target(env, gpr[4], gpr[5]); 3413b3c1694SLeon Alrae break; 3423b3c1694SLeon Alrae case UHI_plog: 3433b3c1694SLeon Alrae GET_TARGET_STRING(p, gpr[4]); 3443b3c1694SLeon Alrae p2 = strstr(p, "%d"); 3453b3c1694SLeon Alrae if (p2) { 3463b3c1694SLeon Alrae int char_num = p2 - p; 34754eb6cdaSAlex Bennée GString *s = g_string_new_len(p, char_num); 34854eb6cdaSAlex Bennée g_string_append_printf(s, "%d%s", (int)gpr[5], p2 + 2); 34954eb6cdaSAlex Bennée gpr[2] = qemu_semihosting_log_out(s->str, s->len); 35054eb6cdaSAlex Bennée g_string_free(s, true); 3513b3c1694SLeon Alrae } else { 35254eb6cdaSAlex Bennée gpr[2] = qemu_semihosting_log_out(p, strlen(p)); 3533b3c1694SLeon Alrae } 3543b3c1694SLeon Alrae FREE_TARGET_STRING(p, gpr[4]); 3553b3c1694SLeon Alrae break; 3563b3c1694SLeon Alrae case UHI_assert: 35726e7e982SLeon Alrae GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]); 3583b3c1694SLeon Alrae printf("assertion '"); 3593b3c1694SLeon Alrae printf("\"%s\"", p); 3603b3c1694SLeon Alrae printf("': file \"%s\", line %d\n", p2, (int)gpr[6]); 3613b3c1694SLeon Alrae FREE_TARGET_STRING(p2, gpr[5]); 3623b3c1694SLeon Alrae FREE_TARGET_STRING(p, gpr[4]); 3633b3c1694SLeon Alrae abort(); 3643b3c1694SLeon Alrae break; 3653b3c1694SLeon Alrae #ifndef _WIN32 3663b3c1694SLeon Alrae case UHI_link: 36726e7e982SLeon Alrae GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]); 3683b3c1694SLeon Alrae gpr[2] = link(p, p2); 3692c44b19cSLeon Alrae gpr[3] = errno_mips(errno); 3703b3c1694SLeon Alrae FREE_TARGET_STRING(p2, gpr[5]); 3713b3c1694SLeon Alrae FREE_TARGET_STRING(p, gpr[4]); 3723b3c1694SLeon Alrae break; 3733b3c1694SLeon Alrae #endif 3743b3c1694SLeon Alrae default: 375*d53a3ed4SRichard Henderson error_report("Unknown UHI operation %d", op); 3763b3c1694SLeon Alrae abort(); 3773b3c1694SLeon Alrae } 3783b3c1694SLeon Alrae return; 3793b3c1694SLeon Alrae } 380