├── AARCH64 ├── X86Emulator.c └── X86EmulatorThunk.S ├── Glue.c ├── LICENSE ├── Qsort.c ├── README.md ├── X86Emulator.c ├── X86Emulator.dsc ├── X86Emulator.h ├── X86Emulator.inf ├── main.c ├── main.h └── qemu ├── bswap.h ├── cache-utils.c ├── cache-utils.h ├── compiler.h ├── config-host.h ├── config-target.h ├── config.h ├── cpu-all.h ├── cpu-common.h ├── cpu-defs.h ├── cpu-exec.c ├── cpus.h ├── cutils.c ├── def-helper.h ├── disas.h ├── exec-all.h ├── exec.c ├── fpu ├── softfloat-macros.h ├── softfloat-specialize.h ├── softfloat.c └── softfloat.h ├── host-utils.c ├── host-utils.h ├── ioport.h ├── iorange.h ├── nomath.h ├── osdep.h ├── qemu-barrier.h ├── qemu-common.h ├── qemu-lock.h ├── qemu-log.h ├── qemu-os-posix.h ├── qemu-queue.h ├── qemu-types.h ├── sysemu.h ├── target-i386 ├── TODO ├── cpu.h ├── cpuid.c ├── helper.c ├── helper.h ├── helper_template.h ├── op_helper.c ├── ops_sse.h ├── ops_sse_header.h ├── svm.h └── translate.c ├── targphys.h ├── tcg-runtime.c ├── tcg ├── README ├── aarch64 │ ├── tcg-target.c │ └── tcg-target.h ├── optimize.c ├── tcg-op.h ├── tcg-opc.h ├── tcg-runtime.h ├── tcg.c └── tcg.h └── translate-all.c /AARCH64/X86Emulator.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017, Linaro, Ltd. 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | 10 | #include "X86Emulator.h" 11 | 12 | #include 13 | 14 | extern CONST UINT64 X86EmulatorThunk[]; 15 | 16 | VOID 17 | EFIAPI 18 | X86InterpreterSyncExceptionCallback ( 19 | IN EFI_EXCEPTION_TYPE ExceptionType, 20 | IN OUT EFI_SYSTEM_CONTEXT SystemContext 21 | ) 22 | { 23 | EFI_SYSTEM_CONTEXT_AARCH64 *AArch64Context; 24 | X86_IMAGE_RECORD *Record; 25 | UINTN Ec; 26 | UINTN Rt; 27 | 28 | AArch64Context = SystemContext.SystemContextAArch64; 29 | 30 | // instruction permission faults or PC misalignment faults take us to the emu 31 | Ec = AArch64Context->ESR >> 26; 32 | if ((Ec == 0x21 && (AArch64Context->ESR & 0x3c) == 0xc) || Ec == 0x22) { 33 | Record = FindImageRecord (AArch64Context->ELR); 34 | if (Record != NULL) { 35 | AArch64Context->X16 = AArch64Context->ELR; 36 | AArch64Context->X17 = (UINT64)Record; 37 | AArch64Context->ELR = (UINT64)X86EmulatorThunk; 38 | return; 39 | } 40 | } 41 | 42 | // check whether the exception occurred in the JITed code 43 | if (AArch64Context->ELR >= (UINTN)static_code_gen_buffer && 44 | AArch64Context->ELR < (UINTN)static_code_gen_buffer + 45 | EFI_PAGES_TO_SIZE (CODE_GEN_BUFFER_PAGES)) { 46 | // 47 | // It looks like we crashed in the JITed code. Check whether we are 48 | // accessing page 0, and fix up the access in that case. 49 | // 50 | if (Ec == 0x25 && AArch64Context->FAR < EFI_PAGE_SIZE) { 51 | 52 | if ((AArch64Context->ESR & BIT24) && // Instruction syndrome valid 53 | !(AArch64Context->ESR & BIT6)) { // Load instruction 54 | 55 | Rt = (AArch64Context->ESR >> 16) & 0x1f; 56 | if (Rt != 31) { // ignore wzr/xzr 57 | (&AArch64Context->X0)[Rt] = 0; 58 | } 59 | } 60 | DEBUG ((DEBUG_WARN, 61 | "%a: Illegal %a address 0x%lx from X86 code!! Fixing up ...\n", 62 | __FUNCTION__, 63 | (AArch64Context->ESR & BIT6) ? "write to" : "read from", 64 | AArch64Context->FAR)); 65 | 66 | AArch64Context->ELR += 4; 67 | return; 68 | } 69 | // 70 | // We can't handle this exception. Try to produce some meaningful 71 | // diagnostics regarding the X86 code this maps onto. 72 | // 73 | DEBUG ((DEBUG_ERROR, "Exception occurred during emulation:\n")); 74 | dump_x86_state(); 75 | } 76 | DefaultExceptionHandler (ExceptionType, SystemContext); 77 | } 78 | -------------------------------------------------------------------------------- /AARCH64/X86EmulatorThunk.S: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017, Linaro, Ltd. 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | 10 | .text 11 | .global X86EmulatorThunk 12 | X86EmulatorThunk: 13 | stp x29, x30, [sp, #-80]! 14 | mov x29, sp 15 | 16 | stp x0, x1, [sp, #16] 17 | stp x2, x3, [sp, #32] 18 | stp x4, x5, [sp, #48] 19 | stp x6, x7, [sp, #64] 20 | 21 | mov x0, x16 22 | add x1, sp, #16 23 | mov x2, x17 24 | mov x3, x30 25 | bl X86EmulatorVmEntry 26 | 27 | ldp x29, x30, [sp], #80 28 | ret 29 | -------------------------------------------------------------------------------- /Glue.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017, Linaro, Ltd. 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | 10 | #include "X86Emulator.h" 11 | 12 | #include 13 | #include 14 | 15 | VOID 16 | flush_icache_range ( 17 | IN UINTN Start, 18 | IN UINTN End 19 | ) 20 | { 21 | InvalidateInstructionCacheRange ((VOID *)Start, End - Start + 1); 22 | } 23 | 24 | VOID 25 | longjmp ( 26 | IN VOID *env, 27 | IN INT32 val 28 | ) 29 | { 30 | LongJump((BASE_LIBRARY_JUMP_BUFFER *)env, (UINTN)((val == 0) ? 1 : val)); 31 | } 32 | 33 | EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL **stdout; 34 | EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL **stderr; 35 | 36 | UINTN 37 | AsciiInternalPrint ( 38 | IN CONST CHAR8 *Format, 39 | IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Console, 40 | IN VA_LIST Marker 41 | ); 42 | 43 | INT32 44 | vfprintf ( 45 | IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL **stream, 46 | IN CONST CHAR8 *format, 47 | VA_LIST ap 48 | ) 49 | { 50 | ASSERT (stream == stdout || stream == stderr); 51 | 52 | return (INT32)AsciiInternalPrint (format, *stream, ap); 53 | } 54 | 55 | INT32 56 | fprintf ( 57 | IN VOID *stream, 58 | IN CONST CHAR8 *format, 59 | ...) 60 | { 61 | VA_LIST Marker; 62 | INT32 Result; 63 | 64 | VA_START (Marker, format); 65 | Result = vfprintf(stream, format, Marker); 66 | VA_END (Marker); 67 | 68 | return Result; 69 | } 70 | 71 | INT32 72 | printf ( 73 | IN CONST CHAR8 *format, 74 | ...) 75 | { 76 | VA_LIST Marker; 77 | INT32 Result; 78 | 79 | VA_START (Marker, format); 80 | Result = vfprintf(stdout, format, Marker); 81 | VA_END (Marker); 82 | 83 | return Result; 84 | } 85 | 86 | INT32 87 | snprintf ( 88 | OUT CHAR8 *str, 89 | IN UINTN sizeOfBuffer, 90 | IN CONST CHAR8 *format, 91 | ...) 92 | { 93 | VA_LIST Marker; 94 | INT32 NumberOfPrinted; 95 | 96 | VA_START (Marker, format); 97 | NumberOfPrinted = (INT32)AsciiVSPrint (str, sizeOfBuffer, format, Marker); 98 | VA_END (Marker); 99 | 100 | return NumberOfPrinted; 101 | } 102 | 103 | INT32 104 | strcmp ( 105 | IN CONST CHAR8 *s1, 106 | IN CONST CHAR8 *s2 107 | ) 108 | { 109 | return AsciiStrCmp (s1, s2); 110 | } 111 | 112 | -------------------------------------------------------------------------------- /Qsort.c: -------------------------------------------------------------------------------- 1 | /** @file 2 | Quick Sort utility function. 3 | 4 | This utility makes use of a comparison function to search arrays of 5 | unspecified type. Where an argument declared as size_t nmemb specifies the 6 | length of the array for a function, nmemb can have the value zero on a call 7 | to that function; the comparison function is not called, a search finds no 8 | matching element. Pointer arguments on such a call shall still have valid 9 | values. 10 | 11 | The implementation shall ensure that both arguments of the comparison 12 | function are pointers to elements of the array. 13 | 14 | The comparison function shall not alter the contents of the array. The 15 | implementation may reorder elements of the array between calls to the 16 | comparison function, but shall not alter the contents of any individual 17 | element. 18 | 19 | When the same objects (consisting of size bytes, irrespective of their 20 | current positions in the array) are passed more than once to the comparison 21 | function, the results shall be consistent with one another. That is, they 22 | define a total ordering on the array. 23 | 24 | A sequence point occurs immediately before and immediately after each call to 25 | the comparison function, and also between any call to the comparison function 26 | and any movement of the objects passed as arguments to that call. 27 | 28 | Copyright (c) 2010, Intel Corporation. All rights reserved.
29 | * Copyright (c) 1992, 1993 30 | * The Regents of the University of California. All rights reserved. 31 | * 32 | * Redistribution and use in source and binary forms, with or without 33 | * modification, are permitted provided that the following conditions 34 | * are met: 35 | * 1. Redistributions of source code must retain the above copyright 36 | * notice, this list of conditions and the following disclaimer. 37 | * 2. Redistributions in binary form must reproduce the above copyright 38 | * notice, this list of conditions and the following disclaimer in the 39 | * documentation and/or other materials provided with the distribution. 40 | * 4. Neither the name of the University nor the names of its contributors 41 | * may be used to endorse or promote products derived from this software 42 | * without specific prior written permission. 43 | * 44 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 45 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 48 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 | * SUCH DAMAGE. 55 | 56 | ("$FreeBSD: src/lib/libc/stdlib/qsort.c,v 1.15.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $"); 57 | */ 58 | 59 | typedef __SIZE_TYPE__ size_t; 60 | 61 | typedef int cmp_t(const void *, const void *); 62 | 63 | static char *med3(char *, char *, char *, cmp_t *); 64 | static void swapfunc(char *, char *, size_t, int); 65 | 66 | /* 67 | * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". 68 | */ 69 | #define swapcode(TYPE, parmi, parmj, n) { \ 70 | size_t i = (n) / sizeof (TYPE); \ 71 | TYPE *pi = (TYPE *) (parmi); \ 72 | TYPE *pj = (TYPE *) (parmj); \ 73 | do { \ 74 | TYPE t = *pi; \ 75 | *pi++ = *pj; \ 76 | *pj++ = t; \ 77 | } while (--i > 0); \ 78 | } 79 | 80 | #define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ 81 | es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; 82 | 83 | static __inline void 84 | swapfunc(char *a, char *b, size_t n, int swaptype) 85 | { 86 | if(swaptype <= 1) 87 | swapcode(long, a, b, n) 88 | else 89 | swapcode(char, a, b, n) 90 | } 91 | 92 | #define swap(a, b) \ 93 | if (swaptype == 0) { \ 94 | long t = *(long *)(a); \ 95 | *(long *)(a) = *(long *)(b); \ 96 | *(long *)(b) = t; \ 97 | } else \ 98 | swapfunc(a, b, es, swaptype) 99 | 100 | #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) 101 | 102 | static __inline char * 103 | med3(char *a, char *b, char *c, cmp_t *cmp ) 104 | { 105 | return cmp(a, b) < 0 ? 106 | (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) 107 | :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); 108 | } 109 | 110 | /* The qsort function sorts an array of nmemb objects, the initial element of 111 | which is pointed to by base. The size of each object is specified by size. 112 | 113 | The contents of the array are sorted into ascending order according to a 114 | comparison function pointed to by compar, which is called with two 115 | arguments that point to the objects being compared. The function shall 116 | return an integer less than, equal to, or greater than zero if the first 117 | argument is considered to be respectively less than, equal to, or greater 118 | than the second. 119 | 120 | If two elements compare as equal, their order in the resulting sorted array 121 | is unspecified. 122 | */ 123 | void 124 | qsort(void *a, size_t n, size_t es, cmp_t *cmp) 125 | { 126 | char *pa, *pb, *pc, *pd, *pl, *pm, *pn; 127 | size_t d, r; 128 | int cmp_result; 129 | int swaptype, swap_cnt; 130 | 131 | loop: SWAPINIT(a, es); 132 | swap_cnt = 0; 133 | if (n < 7) { 134 | for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) 135 | for (pl = pm; 136 | pl > (char *)a && cmp(pl - es, pl) > 0; 137 | pl -= es) 138 | swap(pl, pl - es); 139 | return; 140 | } 141 | pm = (char *)a + (n / 2) * es; 142 | if (n > 7) { 143 | pl = a; 144 | pn = (char *)a + (n - 1) * es; 145 | if (n > 40) { 146 | d = (n / 8) * es; 147 | pl = med3(pl, pl + d, pl + 2 * d, cmp); 148 | pm = med3(pm - d, pm, pm + d, cmp); 149 | pn = med3(pn - 2 * d, pn - d, pn, cmp); 150 | } 151 | pm = med3(pl, pm, pn, cmp); 152 | } 153 | swap(a, pm); 154 | pa = pb = (char *)a + es; 155 | 156 | pc = pd = (char *)a + (n - 1) * es; 157 | for (;;) { 158 | while (pb <= pc && (cmp_result = cmp(pb, a)) <= 0) { 159 | if (cmp_result == 0) { 160 | swap_cnt = 1; 161 | swap(pa, pb); 162 | pa += es; 163 | } 164 | pb += es; 165 | } 166 | while (pb <= pc && (cmp_result = cmp(pc, a)) >= 0) { 167 | if (cmp_result == 0) { 168 | swap_cnt = 1; 169 | swap(pc, pd); 170 | pd -= es; 171 | } 172 | pc -= es; 173 | } 174 | if (pb > pc) 175 | break; 176 | swap(pb, pc); 177 | swap_cnt = 1; 178 | pb += es; 179 | pc -= es; 180 | } 181 | if (swap_cnt == 0) { /* Switch to insertion sort */ 182 | for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) 183 | for (pl = pm; 184 | pl > (char *)a && cmp(pl - es, pl) > 0; 185 | pl -= es) 186 | swap(pl, pl - es); 187 | return; 188 | } 189 | 190 | pn = (char *)a + n * es; 191 | r = MIN(pa - (char *)a, pb - pa); 192 | vecswap(a, pb - r, r); 193 | r = MIN((size_t)(pd - pc), ((size_t)(pn - pd)) - es); 194 | vecswap(pb, pn - r, r); 195 | if ((size_t)(r = pb - pa) > es) 196 | qsort(a, r / es, es, cmp); 197 | if ((size_t)(r = pd - pc) > es) { 198 | /* Iterate rather than recurse to save stack space */ 199 | a = pn - r; 200 | n = r / es; 201 | goto loop; 202 | } 203 | /* qsort(pn - r, r / es, es, cmp);*/ 204 | } 205 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # X86EmulatorPkg 2 | 3 | This code implements a DXE driver for EDK2/Tianocore that allows UEFI 4 | drivers built for x86_64 aka X64 aka amd64 to be executed on 64-bit 5 | ARM systems (aka AArch64) 6 | 7 | All prerequisites in the core code have been merged into the upstream 8 | Tianocore EDK2 repository as of commit 26d60374b87d. 9 | 10 | A prebuilt RELEASE binary of this driver is included in the edk2-non-osi 11 | repository at commit 596043ffb61d5f74. 12 | 13 | ## Quick Start 14 | 15 | To quickly compile an OVMF version that contains the emulator, run 16 | 17 | $ git clone https://github.com/tianocore/edk2.git 18 | $ cd edk2 19 | $ git submodule add https://github.com/ardbiesheuvel/X86EmulatorPkg.git 20 | $ git submodule update --init 21 | $ echo " X86EmulatorPkg/X86Emulator.inf" >> ArmVirtPkg/ArmVirtQemu.dsc 22 | $ echo " INF X86EmulatorPkg/X86Emulator.inf" >> ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc 23 | $ make -C BaseTools 24 | $ . edksetup.sh 25 | $ export GCC5_AARCH64_PREFIX=... (if you are on a non-aarch64 system) 26 | $ build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemu.dsc -b RELEASE (-b DEBUG for debug build) 27 | 28 | You can then use QEMU to execute it: 29 | 30 | $ qemu-system-aarch64 -M virt -cpu cortex-a57 -m 2G -nographic -bios ./Build/ArmVirtQemu-AARCH64/RELEASE_GCC5/FV/QEMU_EFI.fd 31 | 32 | If you see dots on your screen, that is the x86_64 virtio iPXE rom in action! 33 | -------------------------------------------------------------------------------- /X86Emulator.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017, Linaro, Ltd. 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | 10 | #include "X86Emulator.h" 11 | #include "main.h" 12 | 13 | STATIC EFI_CPU_ARCH_PROTOCOL *mCpu; 14 | STATIC EFI_CPU_IO2_PROTOCOL *mCpuIo2; 15 | STATIC LIST_ENTRY mX86ImageList; 16 | STATIC BOOLEAN gX86EmulatorIsInitialized; 17 | 18 | X86_IMAGE_RECORD* 19 | EFIAPI 20 | FindImageRecord ( 21 | IN EFI_PHYSICAL_ADDRESS Address 22 | ) 23 | { 24 | LIST_ENTRY *Entry; 25 | X86_IMAGE_RECORD *Record; 26 | 27 | for (Entry = GetFirstNode (&mX86ImageList); 28 | !IsNull (&mX86ImageList, Entry); 29 | Entry = GetNextNode (&mX86ImageList, Entry)) { 30 | 31 | Record = BASE_CR (Entry, X86_IMAGE_RECORD, Link); 32 | 33 | if (Address >= Record->ImageBase && 34 | Address < Record->ImageBase + Record->ImageSize) { 35 | return Record; 36 | } 37 | } 38 | return NULL; 39 | } 40 | 41 | BOOLEAN 42 | pc_is_native_call ( 43 | IN UINT64 Pc 44 | ) 45 | { 46 | return FindImageRecord ((EFI_PHYSICAL_ADDRESS)Pc) == NULL; 47 | } 48 | 49 | STATIC 50 | BOOLEAN 51 | EFIAPI 52 | IsX86ImageSupported ( 53 | IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This, 54 | IN UINT16 ImageType, 55 | IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL 56 | ) 57 | { 58 | if (ImageType != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION && 59 | ImageType != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) { 60 | return FALSE; 61 | } 62 | return TRUE; 63 | } 64 | 65 | STATIC 66 | EFI_STATUS 67 | EFIAPI 68 | RegisterX86Image ( 69 | IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This, 70 | IN EFI_PHYSICAL_ADDRESS ImageBase, 71 | IN UINT64 ImageSize, 72 | IN OUT EFI_IMAGE_ENTRY_POINT *EntryPoint 73 | ) 74 | { 75 | X86_IMAGE_RECORD *Record; 76 | 77 | DEBUG_CODE_BEGIN (); 78 | PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; 79 | EFI_STATUS Status; 80 | 81 | ZeroMem (&ImageContext, sizeof (ImageContext)); 82 | 83 | ImageContext.Handle = (VOID *)(UINTN)ImageBase; 84 | ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory; 85 | 86 | Status = PeCoffLoaderGetImageInfo (&ImageContext); 87 | if (EFI_ERROR (Status)) { 88 | return Status; 89 | } 90 | 91 | ASSERT (ImageContext.Machine == EFI_IMAGE_MACHINE_X64); 92 | ASSERT (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION || 93 | ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER); 94 | DEBUG_CODE_END (); 95 | 96 | Record = AllocatePool (sizeof *Record); 97 | if (Record == NULL) { 98 | return EFI_OUT_OF_RESOURCES; 99 | } 100 | 101 | Record->ImageBase = ImageBase; 102 | Record->ImageSize = ImageSize; 103 | 104 | InsertTailList (&mX86ImageList, &Record->Link); 105 | 106 | return mCpu->SetMemoryAttributes (mCpu, ImageBase, ImageSize, EFI_MEMORY_XP); 107 | } 108 | 109 | STATIC 110 | EFI_STATUS 111 | EFIAPI 112 | UnregisterX86Image ( 113 | IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This, 114 | IN EFI_PHYSICAL_ADDRESS ImageBase 115 | ) 116 | { 117 | X86_IMAGE_RECORD *Record; 118 | EFI_STATUS Status; 119 | 120 | Record = FindImageRecord (ImageBase); 121 | if (Record == NULL) { 122 | return EFI_NOT_FOUND; 123 | } 124 | 125 | // remove non-exec protection 126 | Status = mCpu->SetMemoryAttributes (mCpu, Record->ImageBase, 127 | Record->ImageSize, 0); 128 | 129 | RemoveEntryList (&Record->Link); 130 | FreePool (Record); 131 | 132 | return Status; 133 | } 134 | 135 | STATIC EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL mX86EmulatorProtocol = { 136 | IsX86ImageSupported, 137 | RegisterX86Image, 138 | UnregisterX86Image, 139 | EDKII_PECOFF_IMAGE_EMULATOR_VERSION, 140 | EFI_IMAGE_MACHINE_X64 141 | }; 142 | 143 | UINT8 144 | cpu_inb ( 145 | IN UINTN addr 146 | ) 147 | { 148 | UINT8 Result = -1; 149 | 150 | mCpuIo2->Io.Read(mCpuIo2, EfiCpuIoWidthUint8, addr, 1, &Result); 151 | return Result; 152 | } 153 | 154 | UINT16 155 | cpu_inw ( 156 | IN UINTN addr 157 | ) 158 | { 159 | UINT16 Result = -1; 160 | 161 | mCpuIo2->Io.Read(mCpuIo2, EfiCpuIoWidthUint16, addr, 1, &Result); 162 | return Result; 163 | } 164 | 165 | UINT32 166 | cpu_inl ( 167 | IN UINTN addr 168 | ) 169 | { 170 | UINT32 Result = -1; 171 | 172 | mCpuIo2->Io.Read(mCpuIo2, EfiCpuIoWidthUint32, addr, 1, &Result); 173 | return Result; 174 | } 175 | 176 | VOID 177 | cpu_outb ( 178 | IN UINTN addr, 179 | IN UINT8 val 180 | ) 181 | { 182 | mCpuIo2->Io.Write(mCpuIo2, EfiCpuIoWidthUint8, addr, 1, &val); 183 | } 184 | 185 | VOID 186 | cpu_outw ( 187 | IN UINTN addr, 188 | IN UINT16 val 189 | ) 190 | { 191 | mCpuIo2->Io.Write(mCpuIo2, EfiCpuIoWidthUint16, addr, 1, &val); 192 | } 193 | 194 | VOID 195 | cpu_outl ( 196 | IN UINTN addr, 197 | IN UINT32 val 198 | ) 199 | { 200 | mCpuIo2->Io.Write(mCpuIo2, EfiCpuIoWidthUint32, addr, 1, &val); 201 | } 202 | 203 | UINT64 204 | X86EmulatorVmEntry ( 205 | IN UINT64 Pc, 206 | IN UINT64 *Args, 207 | IN X86_IMAGE_RECORD *Record, 208 | IN UINT64 Lr 209 | ) 210 | { 211 | if (!gX86EmulatorIsInitialized) { 212 | x86emu_init(); 213 | gX86EmulatorIsInitialized = TRUE; 214 | } 215 | 216 | return run_x86_func((void*)Pc, (uint64_t *)Args); 217 | } 218 | 219 | extern EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL **stdout; 220 | extern EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL **stderr; 221 | 222 | UINT8 *code_gen_prologue; 223 | 224 | EFI_STATUS 225 | EFIAPI 226 | X86EmulatorDxeEntryPoint ( 227 | IN EFI_HANDLE ImageHandle, 228 | IN EFI_SYSTEM_TABLE *SystemTable 229 | ) 230 | { 231 | EFI_STATUS Status; 232 | EFI_PHYSICAL_ADDRESS Alloc; 233 | 234 | InitializeListHead (&mX86ImageList); 235 | 236 | Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, 237 | CODE_GEN_BUFFER_PAGES + 1, &Alloc); 238 | if (EFI_ERROR (Status)) { 239 | return Status; 240 | } 241 | 242 | code_gen_prologue = (UINT8 *)(UINTN)Alloc; 243 | static_code_gen_buffer = code_gen_prologue + EFI_PAGE_SIZE; 244 | 245 | Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu); 246 | ASSERT_EFI_ERROR(Status); 247 | 248 | Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, 249 | (VOID **)&mCpuIo2); 250 | ASSERT_EFI_ERROR(Status); 251 | 252 | Status = mCpu->RegisterInterruptHandler (mCpu, X86_EMU_EXCEPTION_TYPE, 253 | &X86InterpreterSyncExceptionCallback); 254 | 255 | if (EFI_ERROR (Status)) { 256 | return Status; 257 | } 258 | 259 | Status = gBS->InstallProtocolInterface (&ImageHandle, 260 | &gEdkiiPeCoffImageEmulatorProtocolGuid, 261 | EFI_NATIVE_INTERFACE, 262 | &mX86EmulatorProtocol); 263 | if (EFI_ERROR (Status)) { 264 | mCpu->RegisterInterruptHandler (mCpu, X86_EMU_EXCEPTION_TYPE, NULL); 265 | } 266 | 267 | stdout = &gST->ConOut; 268 | stderr = &gST->StdErr; 269 | 270 | return Status; 271 | } 272 | -------------------------------------------------------------------------------- /X86Emulator.dsc: -------------------------------------------------------------------------------- 1 | #/** @file 2 | # 3 | # Copyright (c) 2017 - 2019, Linaro Ltd. All rights reserved.
4 | # 5 | # This library is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU Lesser General Public 7 | # License as published by the Free Software Foundation; either 8 | # version 2 of the License, or (at your option) any later version. 9 | # 10 | #**/ 11 | 12 | ################################################################################ 13 | # 14 | # Defines Section - statements that will be processed to create a Makefile. 15 | # 16 | ################################################################################ 17 | [Defines] 18 | PLATFORM_NAME = X86Emulator 19 | PLATFORM_GUID = 62ad1d2c-27bf-4021-b32d-268d0e71c032 20 | PLATFORM_VERSION = 0.1 21 | DSC_SPECIFICATION = 1.28 22 | OUTPUT_DIRECTORY = Build/X86Emulator 23 | SUPPORTED_ARCHITECTURES = AARCH64 24 | BUILD_TARGETS = DEBUG|RELEASE|NOOPT 25 | SKUID_IDENTIFIER = DEFAULT 26 | 27 | 28 | ################################################################################ 29 | # 30 | # SKU Identification section - list of all SKU IDs supported by this 31 | # Platform. 32 | # 33 | ################################################################################ 34 | [SkuIds] 35 | 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required. 36 | 37 | 38 | ################################################################################ 39 | # 40 | # Library Class section - list of all Library Classes needed by this Platform. 41 | # 42 | ################################################################################ 43 | [LibraryClasses.common] 44 | ArmGenericTimerCounterLib|ArmPkg/Library/ArmGenericTimerVirtCounterLib/ArmGenericTimerVirtCounterLib.inf 45 | ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf 46 | BaseLib|MdePkg/Library/BaseLib/BaseLib.inf 47 | BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf 48 | CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf 49 | CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf 50 | 51 | !if $(TARGET) == RELEASE 52 | DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf 53 | !else 54 | DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf 55 | !endif 56 | 57 | DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf 58 | DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf 59 | MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf 60 | PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf 61 | PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf 62 | PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf 63 | PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf 64 | PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf 65 | SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf 66 | UefiLib|MdePkg/Library/UefiLib/UefiLib.inf 67 | UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf 68 | UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf 69 | UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf 70 | NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf 71 | 72 | [LibraryClasses.AARCH64] 73 | ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf 74 | DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf 75 | TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf 76 | NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf 77 | 78 | [BuildOptions] 79 | GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG 80 | *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES 81 | 82 | ################################################################################ 83 | # 84 | # Components Section - list of all Modules needed by this Platform 85 | # 86 | ################################################################################ 87 | [Components] 88 | X86EmulatorPkg/X86Emulator.inf 89 | -------------------------------------------------------------------------------- /X86Emulator.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017, Linaro, Ltd. 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #ifdef MDE_CPU_AARCH64 24 | #define X86_EMU_EXCEPTION_TYPE EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS 25 | #else 26 | #error 27 | #endif 28 | 29 | typedef struct { 30 | LIST_ENTRY Link; 31 | EFI_PHYSICAL_ADDRESS ImageBase; 32 | UINT64 ImageSize; 33 | } X86_IMAGE_RECORD; 34 | 35 | VOID 36 | EFIAPI 37 | X86InterpreterSyncExceptionCallback ( 38 | IN EFI_EXCEPTION_TYPE ExceptionType, 39 | IN OUT EFI_SYSTEM_CONTEXT SystemContext 40 | ); 41 | 42 | X86_IMAGE_RECORD* 43 | EFIAPI 44 | FindImageRecord ( 45 | IN EFI_PHYSICAL_ADDRESS Address 46 | ); 47 | 48 | #define CODE_GEN_BUFFER_PAGES (8 * 1024) 49 | 50 | extern UINT8 *static_code_gen_buffer; 51 | 52 | void dump_x86_state(void); 53 | -------------------------------------------------------------------------------- /X86Emulator.inf: -------------------------------------------------------------------------------- 1 | ## @file 2 | # 3 | # Copyright (c) 2017, Linaro, Ltd. 4 | # 5 | # This library is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU Lesser General Public 7 | # License as published by the Free Software Foundation; either 8 | # version 2 of the License, or (at your option) any later version. 9 | # 10 | ## 11 | 12 | [Defines] 13 | INF_VERSION = 0x00010019 14 | BASE_NAME = X86EmulatorDxe 15 | FILE_GUID = E6727A5E-CBCD-44C8-B37F-78BC3A0C16C8 16 | MODULE_TYPE = DXE_DRIVER 17 | VERSION_STRING = 1.0 18 | ENTRY_POINT = X86EmulatorDxeEntryPoint 19 | 20 | # 21 | # VALID_ARCHITECTURES = AARCH64 22 | # 23 | 24 | [Sources] 25 | X86Emulator.c 26 | Glue.c 27 | Qsort.c 28 | 29 | qemu/fpu/softfloat.c 30 | qemu/target-i386/translate.c 31 | qemu/target-i386/helper.c 32 | qemu/target-i386/op_helper.c 33 | qemu/target-i386/cpuid.c 34 | qemu/tcg/optimize.c 35 | qemu/tcg/tcg.c 36 | qemu/cpu-exec.c 37 | qemu/cutils.c 38 | qemu/host-utils.c 39 | qemu/cache-utils.c 40 | qemu/tcg-runtime.c 41 | qemu/exec.c 42 | qemu/translate-all.c 43 | main.c 44 | 45 | [Sources.AARCH64] 46 | AARCH64/X86Emulator.c 47 | AARCH64/X86EmulatorThunk.S 48 | 49 | [Packages] 50 | MdePkg/MdePkg.dec 51 | MdeModulePkg/MdeModulePkg.dec 52 | 53 | [Packages.AARCH64] 54 | ArmPkg/ArmPkg.dec 55 | 56 | [LibraryClasses] 57 | BaseLib 58 | BaseMemoryLib 59 | CacheMaintenanceLib 60 | CpuLib 61 | DebugLib 62 | MemoryAllocationLib 63 | PeCoffLib 64 | UefiBootServicesTableLib 65 | UefiDriverEntryPoint 66 | PrintLib 67 | TimerLib 68 | 69 | [LibraryClasses.AARCH64] 70 | DefaultExceptionHandlerLib 71 | 72 | [Protocols] 73 | gEfiCpuArchProtocolGuid ## CONSUMES 74 | gEfiCpuIo2ProtocolGuid ## CONSUMES 75 | gEdkiiPeCoffImageEmulatorProtocolGuid ## PRODUCES 76 | 77 | [Depex] 78 | gEfiCpuArchProtocolGuid AND gEfiCpuIo2ProtocolGuid 79 | 80 | [BuildOptions] 81 | GCC:*_*_*_CC_FLAGS = -ffreestanding -mcmodel=small -U_FORTIFY_SOURCE -Wno-unused-function 82 | GCC:*_*_*_DLINK_FLAGS = -Wl,--defsym=_setjmp=SetJump -z common-page-size=0x1000 83 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QEMU Emulator glue 3 | * 4 | * Copyright (c) 2017 Alexander Graf 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #include 21 | #include "assert.h" 22 | #include "qemu-common.h" 23 | #include "qemu/osdep.h" 24 | #include "cache-utils.h" 25 | #include "cpu.h" 26 | #include "tcg.h" 27 | #include "ioport.h" 28 | #include "main.h" 29 | #include "X86Emulator.h" 30 | #include 31 | #include 32 | 33 | typedef __SIZE_TYPE__ size_t; // GCC builtin definition 34 | 35 | int singlestep; 36 | volatile int in_critical; 37 | 38 | /* The same as cpu_single_env - we only ever run in one context at a time */ 39 | CPUState *env; 40 | 41 | /* 42 | * We provide up to 8 nesting stacks. While the guest code is running 43 | * we do not know the exact value of RSP as it might be stored in a 44 | * register. So for nesting calls, just use separate stacks. 45 | */ 46 | #define MAX_NESTING 8 47 | int nesting_level = -1; 48 | 49 | #define STACK_SIZE (1024 * 1024) /* 1MB */ 50 | uint8_t *stacks[MAX_NESTING]; 51 | 52 | /* 53 | * In addition to stacks, we also provide 8 nesting CPU environments. 54 | * That way we don't have to save/restore anything on function entry. 55 | */ 56 | CPUState *envs[MAX_NESTING]; 57 | 58 | /* 59 | * This option enables a few sanity checks that happen to trigger from 60 | * time to time. The only reason I can see why they would trigger is buggy 61 | * code, but I guess nobody realized that yet, as the buggyness didn't 62 | * result in crashes. By default, let's be compatible rather than paranoid. 63 | */ 64 | /* #define BE_PARANOID */ 65 | 66 | /* Use Linux's GDT setup */ 67 | static uint64_t gdt_table[16] = { 68 | [5] = 0xffff | (0xf0000ULL << 32) | /* Limit */ 69 | (DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | 70 | DESC_S_MASK | (3 << DESC_DPL_SHIFT) | 71 | (0x2ULL << DESC_TYPE_SHIFT)) << 32, /* Flags */ 72 | [6] = 0xffff | (0xf0000ULL << 32) | /* Limit */ 73 | (DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | 74 | DESC_S_MASK | DESC_L_MASK | (3 << DESC_DPL_SHIFT) | 75 | (0xaULL << DESC_TYPE_SHIFT)) << 32, /* Flags */ 76 | }; 77 | 78 | #if 0 79 | #define printf_verbose printf 80 | #else 81 | #define printf_verbose(a,...) do { } while(0) 82 | #endif 83 | 84 | int pthread_mutex_lock(pthread_mutex_t *mutex) 85 | { 86 | return 0; 87 | } 88 | 89 | int pthread_mutex_unlock(pthread_mutex_t *mutex) 90 | { 91 | return 0; 92 | } 93 | 94 | int cpu_get_pic_interrupt(CPUX86State *s) 95 | { 96 | assert(0); 97 | __builtin_unreachable(); 98 | } 99 | 100 | uint64_t cpu_get_tsc(CPUX86State *env) 101 | { 102 | uint64_t r = GetPerformanceCounter(); 103 | printf_verbose("XXX TSC: %lx\n", r); 104 | return r; 105 | } 106 | 107 | void cpu_resume_from_signal(CPUState *env, void *puc) 108 | { 109 | assert(0); 110 | __builtin_unreachable(); 111 | } 112 | 113 | void __assert_fail (const char *__assertion, const char *__file, 114 | unsigned int __line, const char *__function) 115 | { 116 | printf("Assert failed: %a file=%a line=%d function=%a\n", __assertion, __file, __line, __function); 117 | while (1) ; 118 | } 119 | 120 | void abort(void) 121 | { 122 | asm ("hlt #0x86"); // force an exception so we get a backtrace 123 | while (1) ; 124 | } 125 | 126 | void *malloc(unsigned long size) 127 | { 128 | int Status; 129 | void *r = NULL; 130 | 131 | Status = gBS->AllocatePool ( EfiBootServicesData, 132 | size, 133 | &r ); 134 | 135 | if (Status != EFI_SUCCESS) 136 | return NULL; 137 | 138 | return r; 139 | } 140 | 141 | void free(void *p) 142 | { 143 | gBS->FreePool (p); 144 | } 145 | 146 | void *realloc(void *ptr, size_t size) 147 | { 148 | void *newptr; 149 | 150 | if (ptr && !size) { 151 | free(ptr); 152 | return NULL; 153 | } 154 | 155 | newptr = malloc(size); 156 | if (!ptr || !newptr) 157 | return newptr; 158 | 159 | memcpy(newptr, ptr, size); 160 | free(ptr); 161 | return newptr; 162 | } 163 | 164 | int fclose(FILE *f) 165 | { 166 | return 0; 167 | } 168 | 169 | int fflush(FILE *f) 170 | { 171 | return 0; 172 | } 173 | 174 | FILE *fopen(const char *n, const char *m) 175 | { 176 | return NULL; 177 | } 178 | 179 | int getpagesize(void) 180 | { 181 | return 4096; 182 | } 183 | 184 | size_t strlen(const char *s) 185 | { 186 | return (size_t)AsciiStrSize (s); 187 | } 188 | 189 | // clang cludge 190 | #ifdef strdup 191 | #undef strdup 192 | extern char *strdup(const char *s) asm ("__strdup"); 193 | #endif 194 | char *strdup(const char *s) 195 | { 196 | char *result; 197 | int len; 198 | 199 | len = strlen(s); 200 | result = (char *)AllocateCopyPool (len + 1, s); 201 | result[len] = 0; 202 | return result; 203 | } 204 | 205 | void disas(FILE *out, void *code, unsigned long size) 206 | { 207 | uint8_t *c = (void*)code; 208 | unsigned long i; 209 | 210 | fprintf(out, "Output code: "); 211 | for (i = 0; i < size; i++) { 212 | fprintf(out, "%02x", c[i]); 213 | } 214 | fprintf(out, "\n"); 215 | } 216 | 217 | void target_disas(FILE *out, target_ulong code, target_ulong size, int flags) 218 | { 219 | //assert(0); 220 | uint8_t *c = (void*)code; 221 | target_ulong i; 222 | 223 | fprintf(out, "Input code: "); 224 | for (i = 0; i < size; i++) { 225 | fprintf(out, "%02x", c[i]); 226 | } 227 | fprintf(out, "\n"); 228 | } 229 | 230 | void qemu_free(void *ptr) 231 | { 232 | free(ptr); 233 | } 234 | 235 | void *qemu_malloc(size_t size) 236 | { 237 | return malloc(size); 238 | } 239 | 240 | void *qemu_mallocz(size_t size) 241 | { 242 | void *r = qemu_malloc(size); 243 | memset(r, 0, size); 244 | return r; 245 | } 246 | 247 | const char *lookup_symbol(target_ulong orig_addr) 248 | { 249 | return ""; 250 | } 251 | 252 | static void stack_push64(uint64_t val) 253 | { 254 | uint64_t rsp = env->regs[R_ESP]; 255 | 256 | rsp -= 8; 257 | #ifdef BE_PARANOID 258 | assert(rsp >= (uintptr_t)stacks[nesting_level]); 259 | #endif 260 | 261 | env->regs[R_ESP] = rsp; 262 | *(uint64_t*)rsp = val; 263 | } 264 | 265 | static uint64_t stack_pop64(void) 266 | { 267 | uint64_t rsp = env->regs[R_ESP]; 268 | uint64_t r; 269 | 270 | #ifdef BE_PARANOID 271 | assert((rsp + 8) <= (uintptr_t)&stacks[nesting_level][STACK_SIZE]); 272 | #endif 273 | 274 | r = *(uint64_t*)rsp; 275 | rsp += 8; 276 | 277 | env->regs[R_ESP] = rsp; 278 | 279 | return r; 280 | } 281 | 282 | void dump_x86_state(void) 283 | { 284 | target_disas(stdout, env->eip, 0x100, 0); 285 | cpu_dump_state(env, stdout, fprintf, 0); 286 | } 287 | 288 | bool pc_is_native_return(uint64_t pc) 289 | { 290 | printf_verbose("XXX Current IP: %llx\n", pc); 291 | 292 | return pc == 0x1234567890abcdefULL; 293 | } 294 | 295 | uint64_t run_x86_func(void *func, uint64_t *args) 296 | { 297 | int trapnr; 298 | uint64_t r; 299 | int i; 300 | const int maxargs = 16; 301 | uint8_t *stack; 302 | uintptr_t stack_end; 303 | 304 | /* We can not reenter if a translation is ongoing */ 305 | assert(!in_critical); 306 | 307 | nesting_level++; 308 | assert(nesting_level < MAX_NESTING); 309 | 310 | cpu_single_env = env = envs[nesting_level]; 311 | stack = stacks[nesting_level]; 312 | stack_end = (uintptr_t)&stack[STACK_SIZE] & ~0x8UL; 313 | env->regs[R_ESP] = stack_end; 314 | 315 | printf_verbose("XXX Calling x86_64 %llx(%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx)\n", 316 | (uint64_t)func, 317 | args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); 318 | 319 | env->regs[R_ECX] = args[0]; 320 | env->regs[R_EDX] = args[1]; 321 | env->regs[8] = args[2]; 322 | env->regs[9] = args[3]; 323 | 324 | for (i = 0; i < (maxargs - 4); i++) { 325 | /* Push arguments on stack in reverse order */ 326 | stack_push64(args[(maxargs - 1) - i]); 327 | } 328 | 329 | for (i = 0; i < 4; i++) { 330 | /* Home Zone for the called function */ 331 | stack_push64(0); 332 | } 333 | env->eip = (uintptr_t)func; 334 | /* Return pointer, magic value that brings us back */ 335 | stack_push64(0x1234567890abcdefULL); 336 | 337 | for(;;) { 338 | unsigned long sp; 339 | 340 | asm volatile ("mov %0, sp" : "=r"(sp)); 341 | printf_verbose("XXX Entering x86 at %lx (sp=%lx)\n", env->eip, sp); 342 | env->exec_tpl = gBS->RaiseTPL (TPL_NOTIFY); 343 | in_critical = 1; 344 | trapnr = cpu_x86_exec(env); 345 | in_critical = 0; 346 | gBS->RestoreTPL (env->exec_tpl); 347 | asm volatile ("mov %0, sp" : "=r"(sp)); 348 | printf_verbose("XXX Left x86 at %lx (sp=%lx)\n", env->eip, sp); 349 | if (trapnr == EXCP_RETURN_TO_NATIVE) { 350 | printf_verbose("XXX Return from x86\n"); 351 | break; 352 | } else if (trapnr == EXCP_CALL_TO_NATIVE) { 353 | uint64_t (*f)(uint64_t a, uint64_t b, uint64_t c, uint64_t d, 354 | uint64_t e, uint64_t f, uint64_t g, uint64_t h, 355 | uint64_t i, uint64_t j, uint64_t k, uint64_t l, 356 | uint64_t m, uint64_t n, uint64_t o, uint64_t p) = (void *)env->eip; 357 | uint64_t *stackargs = (uint64_t*)env->regs[R_ESP]; 358 | 359 | /* 360 | * MS x86_64 Stack Layout (in uint64_t's): 361 | * 362 | * ---------------- 363 | * ... 364 | * arg9 365 | * arg8 366 | * arg7 367 | * arg6 368 | * arg5 369 | * arg4 370 | * home zone (reserved for called function) 371 | * home zone (reserved for called function) 372 | * home zone (reserved for called function) 373 | * home zone (reserved for called function) 374 | * return pointer 375 | * ---------------- 376 | */ 377 | 378 | if (env->eip < 0x1000) { 379 | /* Calling into the zero page, this is broken code. Shout out loud. */ 380 | printf("Invalid jump to zero page from caller %llx\n", *stackargs); 381 | dump_x86_state(); 382 | #ifdef BE_PARANOID 383 | assert(env->eip >= 0x1000); 384 | #endif 385 | 386 | /* Try to rescue ourselves as much as we can */ 387 | env->regs[R_EAX] = EFI_UNSUPPORTED; 388 | env->eip = stack_pop64(); 389 | } 390 | 391 | printf_verbose("XXX Calling aarch64 %p(%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx)\n", 392 | f, env->regs[R_ECX], env->regs[R_EDX], env->regs[8], 393 | env->regs[9], stackargs[5], stackargs[6], stackargs[7], 394 | stackargs[8]); 395 | assert(!(env->eip & 0x3)); /* Make sure we're calling aarch64 code which is aligned */ 396 | env->regs[R_EAX] = f(env->regs[R_ECX], env->regs[R_EDX], env->regs[8], env->regs[9], 397 | stackargs[5], stackargs[6], stackargs[7], stackargs[8], 398 | stackargs[9], stackargs[10], stackargs[11], stackargs[12], 399 | stackargs[13], stackargs[14], stackargs[15], stackargs[16]); 400 | printf_verbose("XXX Finished aarch64 call to %p (return to %lx)\n", f, stackargs[0]); 401 | env->eip = stack_pop64(); 402 | } else if (trapnr == EXCP_HLT) { 403 | CpuSleep (); 404 | env->halted = 0; 405 | } else { 406 | printf("XXX Trap: #%x (eip=%lx)\n", trapnr, env->eip); 407 | dump_x86_state(); 408 | ASSERT(FALSE); 409 | break; 410 | } 411 | } 412 | 413 | /* Pop stack passed parameters */ 414 | for (i = 0; i < 4; i++) { 415 | /* Home Zone, modifyable by function */ 416 | stack_pop64(); 417 | } 418 | for (; i < maxargs; i++) { 419 | /* Double check that nobody modified the arg */ 420 | uint64_t curarg = stack_pop64(); 421 | 422 | if (curarg != args[i]) { 423 | #ifdef BE_PARANOID 424 | printf("Argument %d mismatch at RSP=%llx: %llx vs %llx\n", 425 | i, env->regs[R_ESP], curarg, args[i]); 426 | assert(curarg == args[i]); 427 | #endif 428 | } 429 | } 430 | 431 | assert(env->regs[R_ESP] == stack_end); 432 | nesting_level--; 433 | 434 | /* Restore old context */ 435 | r = env->regs[R_EAX]; 436 | cpu_single_env = env = envs[nesting_level]; 437 | 438 | return r; 439 | } 440 | 441 | int x86emu_init(void) 442 | { 443 | int i; 444 | 445 | x86_cpudef_setup(); 446 | cpu_set_log_filename("qemulog"); 447 | cpu_set_log(0); 448 | cpu_exec_init_all(0); 449 | 450 | /* Populate our env copies */ 451 | for (i = 0; i < MAX_NESTING; i++) { 452 | envs[i] = cpu_init("qemu64"); 453 | 454 | env = envs[i]; 455 | assert(env); 456 | cpu_reset(env); 457 | 458 | /* We run everything in user mode, UEFI drivers *should* not need CPL0 */ 459 | cpu_x86_set_cpl(env, 3); 460 | 461 | /* Enable user mode, paging, 64bit, sse */ 462 | env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; 463 | env->cr[4] |= CR4_OSFXSR_MASK | CR4_PAE_MASK; 464 | env->hflags |= HF_PE_MASK | HF_OSFXSR_MASK | HF_LMA_MASK; 465 | env->efer |= MSR_EFER_LMA | MSR_EFER_LME; 466 | 467 | /* Map CS/DS as flat, CS as 64bit code */ 468 | env->gdt.base = (uintptr_t)gdt_table; 469 | env->gdt.limit = sizeof(gdt_table) - 1; 470 | cpu_x86_load_seg(env, R_CS, 0x33); 471 | cpu_x86_load_seg(env, R_SS, 0x2B); 472 | cpu_x86_load_seg(env, R_DS, 0); 473 | cpu_x86_load_seg(env, R_ES, 0); 474 | cpu_x86_load_seg(env, R_FS, 0); 475 | cpu_x86_load_seg(env, R_GS, 0); 476 | 477 | /* Initialize x86 stack at 16-byte boundary */ 478 | stacks[i] = malloc(STACK_SIZE); 479 | } 480 | 481 | return 0; 482 | } 483 | -------------------------------------------------------------------------------- /main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QEMU Emulator glue 3 | * 4 | * Copyright (c) 2017 Alexander Graf 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef __MAIN_H__ 21 | #define __MAIN_H__ 22 | 23 | #include 24 | 25 | int x86emu_init(void); 26 | uint64_t run_x86_func(void *func, uint64_t *args); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /qemu/cache-utils.c: -------------------------------------------------------------------------------- 1 | #include "cache-utils.h" 2 | 3 | #if defined(_ARCH_PPC) 4 | struct qemu_cache_conf qemu_cache_conf = { 5 | .dcache_bsize = 16, 6 | .icache_bsize = 16 7 | }; 8 | 9 | #if defined _AIX 10 | #include 11 | 12 | static void ppc_init_cacheline_sizes(void) 13 | { 14 | qemu_cache_conf.icache_bsize = _system_configuration.icache_line; 15 | qemu_cache_conf.dcache_bsize = _system_configuration.dcache_line; 16 | } 17 | 18 | #elif defined __linux__ 19 | 20 | #define QEMU_AT_NULL 0 21 | #define QEMU_AT_DCACHEBSIZE 19 22 | #define QEMU_AT_ICACHEBSIZE 20 23 | 24 | static void ppc_init_cacheline_sizes(char **envp) 25 | { 26 | unsigned long *auxv; 27 | 28 | while (*envp++); 29 | 30 | for (auxv = (unsigned long *) envp; *auxv != QEMU_AT_NULL; auxv += 2) { 31 | switch (*auxv) { 32 | case QEMU_AT_DCACHEBSIZE: qemu_cache_conf.dcache_bsize = auxv[1]; break; 33 | case QEMU_AT_ICACHEBSIZE: qemu_cache_conf.icache_bsize = auxv[1]; break; 34 | default: break; 35 | } 36 | } 37 | } 38 | 39 | #elif defined __APPLE__ 40 | #include 41 | #include 42 | #include 43 | 44 | static void ppc_init_cacheline_sizes(void) 45 | { 46 | size_t len; 47 | unsigned cacheline; 48 | int name[2] = { CTL_HW, HW_CACHELINE }; 49 | 50 | len = sizeof(cacheline); 51 | if (sysctl(name, 2, &cacheline, &len, NULL, 0)) { 52 | perror("sysctl CTL_HW HW_CACHELINE failed"); 53 | } else { 54 | qemu_cache_conf.dcache_bsize = cacheline; 55 | qemu_cache_conf.icache_bsize = cacheline; 56 | } 57 | } 58 | #endif 59 | 60 | #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | 68 | static void ppc_init_cacheline_sizes(void) 69 | { 70 | size_t len = 4; 71 | unsigned cacheline; 72 | 73 | if (sysctlbyname ("machdep.cacheline_size", &cacheline, &len, NULL, 0)) { 74 | fprintf(stderr, "sysctlbyname machdep.cacheline_size failed: %s\n", 75 | strerror(errno)); 76 | exit(1); 77 | } 78 | 79 | qemu_cache_conf.dcache_bsize = cacheline; 80 | qemu_cache_conf.icache_bsize = cacheline; 81 | } 82 | #endif 83 | 84 | #ifdef __linux__ 85 | void qemu_cache_utils_init(char **envp) 86 | { 87 | ppc_init_cacheline_sizes(envp); 88 | } 89 | #else 90 | void qemu_cache_utils_init(char **envp) 91 | { 92 | (void) envp; 93 | ppc_init_cacheline_sizes(); 94 | } 95 | #endif 96 | 97 | #endif /* _ARCH_PPC */ 98 | -------------------------------------------------------------------------------- /qemu/cache-utils.h: -------------------------------------------------------------------------------- 1 | #ifndef QEMU_CACHE_UTILS_H 2 | #define QEMU_CACHE_UTILS_H 3 | 4 | #if defined(_ARCH_PPC) 5 | struct qemu_cache_conf { 6 | unsigned long dcache_bsize; 7 | unsigned long icache_bsize; 8 | }; 9 | 10 | extern struct qemu_cache_conf qemu_cache_conf; 11 | 12 | void qemu_cache_utils_init(char **envp); 13 | 14 | /* mildly adjusted code from tcg-dyngen.c */ 15 | static inline void flush_icache_range(unsigned long start, unsigned long stop) 16 | { 17 | unsigned long p, start1, stop1; 18 | unsigned long dsize = qemu_cache_conf.dcache_bsize; 19 | unsigned long isize = qemu_cache_conf.icache_bsize; 20 | 21 | start1 = start & ~(dsize - 1); 22 | stop1 = (stop + dsize - 1) & ~(dsize - 1); 23 | for (p = start1; p < stop1; p += dsize) { 24 | asm volatile ("dcbst 0,%0" : : "r"(p) : "memory"); 25 | } 26 | asm volatile ("sync" : : : "memory"); 27 | 28 | start &= start & ~(isize - 1); 29 | stop1 = (stop + isize - 1) & ~(isize - 1); 30 | for (p = start1; p < stop1; p += isize) { 31 | asm volatile ("icbi 0,%0" : : "r"(p) : "memory"); 32 | } 33 | asm volatile ("sync" : : : "memory"); 34 | asm volatile ("isync" : : : "memory"); 35 | } 36 | 37 | #else 38 | #define qemu_cache_utils_init(envp) do { (void) (envp); } while (0) 39 | #endif 40 | 41 | #endif /* QEMU_CACHE_UTILS_H */ 42 | -------------------------------------------------------------------------------- /qemu/compiler.h: -------------------------------------------------------------------------------- 1 | /* public domain */ 2 | 3 | #ifndef COMPILER_H 4 | #define COMPILER_H 5 | 6 | #include "config-host.h" 7 | 8 | #define QEMU_NORETURN __attribute__ ((__noreturn__)) 9 | #ifdef CONFIG_GCC_ATTRIBUTE_WARN_UNUSED_RESULT 10 | #define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) 11 | #else 12 | #define QEMU_WARN_UNUSED_RESULT 13 | #endif 14 | 15 | #define QEMU_BUILD_BUG_ON(x) \ 16 | typedef char qemu_build_bug_on__##__LINE__[(x)?-1:1]; 17 | 18 | #if defined __GNUC__ 19 | # if (__GNUC__ < 4) || \ 20 | defined(__GNUC_MINOR__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4) 21 | /* gcc versions before 4.4.x don't support gnu_printf, so use printf. */ 22 | # define GCC_ATTR __attribute__((__unused__, format(printf, 1, 2))) 23 | # define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m))) 24 | # else 25 | /* Use gnu_printf when supported (qemu uses standard format strings). */ 26 | # define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2))) 27 | # define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m))) 28 | # endif 29 | #else 30 | #define GCC_ATTR /**/ 31 | #define GCC_FMT_ATTR(n, m) 32 | #endif 33 | 34 | #endif /* COMPILER_H */ 35 | -------------------------------------------------------------------------------- /qemu/config-host.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define CONFIG_QEMU_CONFDIR "/usr/local/etc/qemu" 3 | #define CONFIG_QEMU_DATADIR "/usr/local/share/qemu" 4 | #define CONFIG_QEMU_DOCDIR "/usr/local/share/doc/qemu" 5 | #define CONFIG_QEMU_MODDIR "/usr/local/lib/qemu" 6 | #define CONFIG_QEMU_LOCALSTATEDIR "/usr/local/var" 7 | #define CONFIG_QEMU_HELPERDIR "/usr/local/libexec" 8 | #define CONFIG_QEMU_LOCALEDIR "/usr/local/share/locale" 9 | #define HOST_X86_64 1 10 | #define CONFIG_POSIX 1 11 | #define CONFIG_LINUX 1 12 | #define CONFIG_SLIRP 1 13 | #define CONFIG_SMBD_COMMAND "/usr/sbin/smbd" 14 | #define CONFIG_L2TPV3 1 15 | #define CONFIG_AUDIO_DRIVERS \ 16 | &oss_audio_driver,\ 17 | 18 | #define CONFIG_OSS 1 19 | #define CONFIG_BDRV_RW_WHITELIST\ 20 | NULL 21 | #define CONFIG_BDRV_RO_WHITELIST\ 22 | NULL 23 | #define CONFIG_VNC 1 24 | #define CONFIG_VNC_SASL 1 25 | #define CONFIG_VNC_JPEG 1 26 | #define CONFIG_VNC_PNG 1 27 | #define CONFIG_FNMATCH 1 28 | #define QEMU_VERSION "2.8.50" 29 | #define QEMU_VERSION_MAJOR 2 30 | #define QEMU_VERSION_MINOR 8 31 | #define QEMU_VERSION_MICRO 50 32 | #define CONFIG_SDL 1 33 | #define CONFIG_SDLABI 1.2 34 | #define CONFIG_CURSES 1 35 | #define CONFIG_UTIMENSAT 1 36 | #define CONFIG_PIPE2 1 37 | #define CONFIG_ACCEPT4 1 38 | #define CONFIG_SPLICE 1 39 | #define CONFIG_EVENTFD 1 40 | #define CONFIG_FALLOCATE 1 41 | #define CONFIG_FALLOCATE_PUNCH_HOLE 1 42 | #define CONFIG_POSIX_FALLOCATE 1 43 | #define CONFIG_SYNC_FILE_RANGE 1 44 | #define CONFIG_FIEMAP 1 45 | #define CONFIG_DUP3 1 46 | #define CONFIG_PPOLL 1 47 | #define CONFIG_PRCTL_PR_SET_TIMERSLACK 1 48 | #define CONFIG_EPOLL 1 49 | #define CONFIG_EPOLL_CREATE1 1 50 | #define CONFIG_SENDFILE 1 51 | #define CONFIG_TIMERFD 1 52 | #define CONFIG_SETNS 1 53 | #define CONFIG_CLOCK_ADJTIME 1 54 | #define CONFIG_SYNCFS 1 55 | #define CONFIG_INOTIFY 1 56 | #define CONFIG_INOTIFY1 1 57 | #define CONFIG_CURL m 58 | #define CONFIG_HAS_GLIB_SUBPROCESS_TESTS 1 59 | #define CONFIG_GTK 1 60 | #define CONFIG_GTKABI 2.0 61 | #define CONFIG_TLS_PRIORITY "NORMAL" 62 | #define HAVE_IFADDRS_H 1 63 | #define CONFIG_LINUX_AIO 1 64 | #define CONFIG_ATTR 1 65 | #define CONFIG_VHOST_SCSI 1 66 | #define CONFIG_VHOST_NET_USED 1 67 | #define CONFIG_VHOST_VSOCK 1 68 | #define CONFIG_IOVEC 1 69 | #define CONFIG_PREADV 1 70 | #define CONFIG_FDT 1 71 | #define CONFIG_SIGNALFD 1 72 | #define CONFIG_FDATASYNC 1 73 | #define CONFIG_MADVISE 1 74 | #define CONFIG_POSIX_MADVISE 1 75 | #define CONFIG_SMARTCARD 1 76 | #define CONFIG_BZIP2 1 77 | #define CONFIG_QOM_CAST_DEBUG 1 78 | #define CONFIG_COROUTINE_BACKEND ucontext 79 | #define CONFIG_COROUTINE_POOL 1 80 | #define CONFIG_OPEN_BY_HANDLE 1 81 | #define CONFIG_LINUX_MAGIC_H 1 82 | #define CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE 1 83 | #define CONFIG_VALGRIND_H 1 84 | #define CONFIG_HAS_ENVIRON 1 85 | #define CONFIG_CPUID_H 1 86 | #define CONFIG_INT128 1 87 | #define CONFIG_ATOMIC128 1 88 | #define CONFIG_ATOMIC64 1 89 | #define CONFIG_GETAUXVAL 1 90 | #define CONFIG_TPM 1 91 | #define CONFIG_TPM_PASSTHROUGH 1 92 | #define CONFIG_TRACE_LOG 1 93 | #define CONFIG_TRACE_FILE trace 94 | #define CONFIG_COLO 1 95 | #define CONFIG_REPLICATION 1 96 | #define CONFIG_THREAD_SETNAME_BYTHREAD 1 97 | #define CONFIG_PTHREAD_SETNAME_NP 1 98 | #define CONFIG_IASL iasl 99 | #define HOST_DSOSUF ".so" 100 | -------------------------------------------------------------------------------- /qemu/config-target.h: -------------------------------------------------------------------------------- 1 | /* Automatically generated by create_config - do not modify */ 2 | #define CONFIG_QEMU_INTERP_PREFIX "/usr/gnemul/qemu-x86_64" 3 | #define TARGET_SHORT_ALIGNMENT 2 4 | #define TARGET_INT_ALIGNMENT 4 5 | #define TARGET_LONG_ALIGNMENT 8 6 | #define TARGET_LLONG_ALIGNMENT 8 7 | #define TARGET_ARCH "x86_64" 8 | #define TARGET_X86_64 1 9 | #define TARGET_I386 1 10 | #define CONFIG_NO_XEN 1 11 | #define CONFIG_USER_ONLY 1 12 | #define CONFIG_LINUX_USER 1 13 | #define CONFIG_I386_DIS 1 14 | #define CONFIG_I386_DIS 1 15 | #define NEED_CPU_H 1 16 | -------------------------------------------------------------------------------- /qemu/config.h: -------------------------------------------------------------------------------- 1 | #include "config-host.h" 2 | #include "config-target.h" 3 | -------------------------------------------------------------------------------- /qemu/cpu-common.h: -------------------------------------------------------------------------------- 1 | #ifndef CPU_COMMON_H 2 | #define CPU_COMMON_H 1 3 | 4 | /* CPU interfaces that are target indpendent. */ 5 | 6 | #ifdef TARGET_PHYS_ADDR_BITS 7 | #include "targphys.h" 8 | #endif 9 | 10 | #ifndef NEED_CPU_H 11 | #include "poison.h" 12 | #endif 13 | 14 | #include "bswap.h" 15 | #include "qemu-queue.h" 16 | 17 | #if !defined(CONFIG_USER_ONLY) 18 | 19 | enum device_endian { 20 | DEVICE_NATIVE_ENDIAN, 21 | DEVICE_BIG_ENDIAN, 22 | DEVICE_LITTLE_ENDIAN, 23 | }; 24 | 25 | /* address in the RAM (different from a physical address) */ 26 | #if defined(CONFIG_XEN_BACKEND) && TARGET_PHYS_ADDR_BITS == 64 27 | typedef uint64_t ram_addr_t; 28 | # define RAM_ADDR_MAX UINT64_MAX 29 | # define RAM_ADDR_FMT "%" PRIx64 30 | #else 31 | typedef unsigned long ram_addr_t; 32 | # define RAM_ADDR_MAX ULONG_MAX 33 | # define RAM_ADDR_FMT "%lx" 34 | #endif 35 | 36 | /* memory API */ 37 | 38 | typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value); 39 | typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr); 40 | 41 | void cpu_register_physical_memory_log(target_phys_addr_t start_addr, 42 | ram_addr_t size, 43 | ram_addr_t phys_offset, 44 | ram_addr_t region_offset, 45 | bool log_dirty); 46 | 47 | static inline void cpu_register_physical_memory_offset(target_phys_addr_t start_addr, 48 | ram_addr_t size, 49 | ram_addr_t phys_offset, 50 | ram_addr_t region_offset) 51 | { 52 | cpu_register_physical_memory_log(start_addr, size, phys_offset, 53 | region_offset, false); 54 | } 55 | 56 | static inline void cpu_register_physical_memory(target_phys_addr_t start_addr, 57 | ram_addr_t size, 58 | ram_addr_t phys_offset) 59 | { 60 | cpu_register_physical_memory_offset(start_addr, size, phys_offset, 0); 61 | } 62 | 63 | ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr); 64 | ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name, 65 | ram_addr_t size, void *host); 66 | ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size); 67 | void qemu_ram_free(ram_addr_t addr); 68 | void qemu_ram_free_from_ptr(ram_addr_t addr); 69 | void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); 70 | /* This should only be used for ram local to a device. */ 71 | void *qemu_get_ram_ptr(ram_addr_t addr); 72 | void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size); 73 | /* Same but slower, to use for migration, where the order of 74 | * RAMBlocks must not change. */ 75 | void *qemu_safe_ram_ptr(ram_addr_t addr); 76 | void qemu_put_ram_ptr(void *addr); 77 | /* This should not be used by devices. */ 78 | int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr); 79 | ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr); 80 | 81 | int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read, 82 | CPUWriteMemoryFunc * const *mem_write, 83 | void *opaque, enum device_endian endian); 84 | void cpu_unregister_io_memory(int table_address); 85 | 86 | void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 87 | int len, int is_write); 88 | static inline void cpu_physical_memory_read(target_phys_addr_t addr, 89 | void *buf, int len) 90 | { 91 | cpu_physical_memory_rw(addr, buf, len, 0); 92 | } 93 | static inline void cpu_physical_memory_write(target_phys_addr_t addr, 94 | const void *buf, int len) 95 | { 96 | cpu_physical_memory_rw(addr, (void *)buf, len, 1); 97 | } 98 | void *cpu_physical_memory_map(target_phys_addr_t addr, 99 | target_phys_addr_t *plen, 100 | int is_write); 101 | void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, 102 | int is_write, target_phys_addr_t access_len); 103 | void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque)); 104 | void cpu_unregister_map_client(void *cookie); 105 | 106 | struct CPUPhysMemoryClient; 107 | typedef struct CPUPhysMemoryClient CPUPhysMemoryClient; 108 | struct CPUPhysMemoryClient { 109 | void (*set_memory)(struct CPUPhysMemoryClient *client, 110 | target_phys_addr_t start_addr, 111 | ram_addr_t size, 112 | ram_addr_t phys_offset, 113 | bool log_dirty); 114 | int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client, 115 | target_phys_addr_t start_addr, 116 | target_phys_addr_t end_addr); 117 | int (*migration_log)(struct CPUPhysMemoryClient *client, 118 | int enable); 119 | int (*log_start)(struct CPUPhysMemoryClient *client, 120 | target_phys_addr_t phys_addr, ram_addr_t size); 121 | int (*log_stop)(struct CPUPhysMemoryClient *client, 122 | target_phys_addr_t phys_addr, ram_addr_t size); 123 | QLIST_ENTRY(CPUPhysMemoryClient) list; 124 | }; 125 | 126 | void cpu_register_phys_memory_client(CPUPhysMemoryClient *); 127 | void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *); 128 | 129 | /* Coalesced MMIO regions are areas where write operations can be reordered. 130 | * This usually implies that write operations are side-effect free. This allows 131 | * batching which can make a major impact on performance when using 132 | * virtualization. 133 | */ 134 | void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); 135 | 136 | void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); 137 | 138 | void qemu_flush_coalesced_mmio_buffer(void); 139 | 140 | uint32_t ldub_phys(target_phys_addr_t addr); 141 | uint32_t lduw_le_phys(target_phys_addr_t addr); 142 | uint32_t lduw_be_phys(target_phys_addr_t addr); 143 | uint32_t ldl_le_phys(target_phys_addr_t addr); 144 | uint32_t ldl_be_phys(target_phys_addr_t addr); 145 | uint64_t ldq_le_phys(target_phys_addr_t addr); 146 | uint64_t ldq_be_phys(target_phys_addr_t addr); 147 | void stb_phys(target_phys_addr_t addr, uint32_t val); 148 | void stw_le_phys(target_phys_addr_t addr, uint32_t val); 149 | void stw_be_phys(target_phys_addr_t addr, uint32_t val); 150 | void stl_le_phys(target_phys_addr_t addr, uint32_t val); 151 | void stl_be_phys(target_phys_addr_t addr, uint32_t val); 152 | void stq_le_phys(target_phys_addr_t addr, uint64_t val); 153 | void stq_be_phys(target_phys_addr_t addr, uint64_t val); 154 | 155 | #ifdef NEED_CPU_H 156 | uint32_t lduw_phys(target_phys_addr_t addr); 157 | uint32_t ldl_phys(target_phys_addr_t addr); 158 | uint64_t ldq_phys(target_phys_addr_t addr); 159 | void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val); 160 | void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val); 161 | void stw_phys(target_phys_addr_t addr, uint32_t val); 162 | void stl_phys(target_phys_addr_t addr, uint32_t val); 163 | void stq_phys(target_phys_addr_t addr, uint64_t val); 164 | #endif 165 | 166 | void cpu_physical_memory_write_rom(target_phys_addr_t addr, 167 | const uint8_t *buf, int len); 168 | 169 | #define IO_MEM_SHIFT 3 170 | 171 | #define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */ 172 | #define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ 173 | #define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT) 174 | #define IO_MEM_NOTDIRTY (3 << IO_MEM_SHIFT) 175 | 176 | /* Acts like a ROM when read and like a device when written. */ 177 | #define IO_MEM_ROMD (1) 178 | #define IO_MEM_SUBPAGE (2) 179 | 180 | #endif 181 | 182 | static inline bool kvm_enabled() 183 | { 184 | return false; 185 | } 186 | 187 | static inline bool kvm_irqchip_in_kernel() 188 | { 189 | return false; 190 | } 191 | 192 | extern CPUState *env; 193 | 194 | #endif /* !CPU_COMMON_H */ 195 | -------------------------------------------------------------------------------- /qemu/cpu-defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * common defines for all CPUs 3 | * 4 | * Copyright (c) 2003 Fabrice Bellard 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | #ifndef CPU_DEFS_H 20 | #define CPU_DEFS_H 21 | 22 | #ifndef NEED_CPU_H 23 | #error cpu.h included from common code 24 | #endif 25 | 26 | #include "config.h" 27 | #include 28 | #include 29 | #include 30 | #include "osdep.h" 31 | #include "qemu-queue.h" 32 | #include "targphys.h" 33 | 34 | #ifndef TARGET_LONG_BITS 35 | #error TARGET_LONG_BITS must be defined before including this header 36 | #endif 37 | 38 | #define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8) 39 | 40 | typedef int16_t target_short __attribute__ ((aligned(TARGET_SHORT_ALIGNMENT))); 41 | typedef uint16_t target_ushort __attribute__((aligned(TARGET_SHORT_ALIGNMENT))); 42 | typedef int32_t target_int __attribute__((aligned(TARGET_INT_ALIGNMENT))); 43 | typedef uint32_t target_uint __attribute__((aligned(TARGET_INT_ALIGNMENT))); 44 | typedef int64_t target_llong __attribute__((aligned(TARGET_LLONG_ALIGNMENT))); 45 | typedef uint64_t target_ullong __attribute__((aligned(TARGET_LLONG_ALIGNMENT))); 46 | /* target_ulong is the type of a virtual address */ 47 | #if TARGET_LONG_SIZE == 4 48 | #error foo 49 | typedef int32_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT))); 50 | typedef uint32_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT))); 51 | #define TARGET_FMT_lx "%08x" 52 | #define TARGET_FMT_ld "%d" 53 | #define TARGET_FMT_lu "%u" 54 | #elif TARGET_LONG_SIZE == 8 55 | typedef int64_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT))); 56 | typedef uint64_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT))); 57 | #define TARGET_FMT_lx "%016" PRIx64 58 | #define TARGET_FMT_ld "%" PRId64 59 | #define TARGET_FMT_lu "%" PRIu64 60 | #else 61 | #error TARGET_LONG_SIZE undefined 62 | #endif 63 | 64 | #define HOST_LONG_SIZE (HOST_LONG_BITS / 8) 65 | 66 | #define EXCP_INTERRUPT 0x10000 /* async interruption */ 67 | #define EXCP_HLT 0x10001 /* hlt instruction reached */ 68 | #define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */ 69 | #define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */ 70 | #define EXCP_RETURN_TO_NATIVE 0x10004 /* return to native code */ 71 | #define EXCP_CALL_TO_NATIVE 0x10005 /* call into native code */ 72 | 73 | #define TB_JMP_CACHE_BITS 12 74 | #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) 75 | 76 | /* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for 77 | addresses on the same page. The top bits are the same. This allows 78 | TLB invalidation to quickly clear a subset of the hash table. */ 79 | #define TB_JMP_PAGE_BITS (TB_JMP_CACHE_BITS / 2) 80 | #define TB_JMP_PAGE_SIZE (1 << TB_JMP_PAGE_BITS) 81 | #define TB_JMP_ADDR_MASK (TB_JMP_PAGE_SIZE - 1) 82 | #define TB_JMP_PAGE_MASK (TB_JMP_CACHE_SIZE - TB_JMP_PAGE_SIZE) 83 | 84 | #if !defined(CONFIG_USER_ONLY) 85 | #define CPU_TLB_BITS 8 86 | #define CPU_TLB_SIZE (1 << CPU_TLB_BITS) 87 | 88 | #if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32 89 | #define CPU_TLB_ENTRY_BITS 4 90 | #else 91 | #define CPU_TLB_ENTRY_BITS 5 92 | #endif 93 | 94 | typedef struct CPUTLBEntry { 95 | /* bit TARGET_LONG_BITS to TARGET_PAGE_BITS : virtual address 96 | bit TARGET_PAGE_BITS-1..4 : Nonzero for accesses that should not 97 | go directly to ram. 98 | bit 3 : indicates that the entry is invalid 99 | bit 2..0 : zero 100 | */ 101 | target_ulong addr_read; 102 | target_ulong addr_write; 103 | target_ulong addr_code; 104 | /* Addend to virtual address to get host address. IO accesses 105 | use the corresponding iotlb value. */ 106 | unsigned long addend; 107 | /* padding to get a power of two size */ 108 | uint8_t dummy[(1 << CPU_TLB_ENTRY_BITS) - 109 | (sizeof(target_ulong) * 3 + 110 | ((-sizeof(target_ulong) * 3) & (sizeof(unsigned long) - 1)) + 111 | sizeof(unsigned long))]; 112 | } CPUTLBEntry; 113 | 114 | extern int CPUTLBEntry_wrong_size[sizeof(CPUTLBEntry) == (1 << CPU_TLB_ENTRY_BITS) ? 1 : -1]; 115 | 116 | #define CPU_COMMON_TLB \ 117 | /* The meaning of the MMU modes is defined in the target code. */ \ 118 | CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \ 119 | target_phys_addr_t iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \ 120 | target_ulong tlb_flush_addr; \ 121 | target_ulong tlb_flush_mask; 122 | 123 | #else 124 | 125 | #define CPU_COMMON_TLB 126 | 127 | #endif 128 | 129 | 130 | #ifdef HOST_WORDS_BIGENDIAN 131 | typedef struct icount_decr_u16 { 132 | uint16_t high; 133 | uint16_t low; 134 | } icount_decr_u16; 135 | #else 136 | typedef struct icount_decr_u16 { 137 | uint16_t low; 138 | uint16_t high; 139 | } icount_decr_u16; 140 | #endif 141 | 142 | struct kvm_run; 143 | struct KVMState; 144 | struct qemu_work_item; 145 | 146 | typedef struct CPUBreakpoint { 147 | target_ulong pc; 148 | int flags; /* BP_* */ 149 | QTAILQ_ENTRY(CPUBreakpoint) entry; 150 | } CPUBreakpoint; 151 | 152 | typedef struct CPUWatchpoint { 153 | target_ulong vaddr; 154 | target_ulong len_mask; 155 | int flags; /* BP_* */ 156 | QTAILQ_ENTRY(CPUWatchpoint) entry; 157 | } CPUWatchpoint; 158 | 159 | #define CPU_TEMP_BUF_NLONGS 128 160 | #define CPU_COMMON \ 161 | struct TranslationBlock *current_tb; /* currently executing TB */ \ 162 | /* soft mmu support */ \ 163 | /* in order to avoid passing too many arguments to the MMIO \ 164 | helpers, we store some rarely used information in the CPU \ 165 | context) */ \ 166 | unsigned long mem_io_pc; /* host pc at which the memory was \ 167 | accessed */ \ 168 | target_ulong mem_io_vaddr; /* target virtual addr at which the \ 169 | memory was accessed */ \ 170 | uint32_t halted; /* Nonzero if the CPU is in suspend state */ \ 171 | uint32_t interrupt_request; \ 172 | volatile sig_atomic_t exit_request; \ 173 | CPU_COMMON_TLB \ 174 | struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \ 175 | /* buffer for temporaries in the code generator */ \ 176 | long temp_buf[CPU_TEMP_BUF_NLONGS]; \ 177 | \ 178 | int64_t icount_extra; /* Instructions until next timer event. */ \ 179 | /* Number of cycles left, with interrupt flag in high bit. \ 180 | This allows a single read-compare-cbranch-write sequence to test \ 181 | for both decrementer underflow and exceptions. */ \ 182 | union { \ 183 | uint32_t u32; \ 184 | icount_decr_u16 u16; \ 185 | } icount_decr; \ 186 | uint32_t can_do_io; /* nonzero if memory mapped IO is safe. */ \ 187 | \ 188 | /* from this point: preserved by CPU reset */ \ 189 | /* ice debug support */ \ 190 | QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; \ 191 | int singlestep_enabled; \ 192 | \ 193 | QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; \ 194 | CPUWatchpoint *watchpoint_hit; \ 195 | \ 196 | struct GDBRegisterState *gdb_regs; \ 197 | \ 198 | /* Core interrupt code */ \ 199 | jmp_buf jmp_env; \ 200 | int exception_index; \ 201 | \ 202 | CPUState *next_cpu; /* next CPU sharing TB cache */ \ 203 | int cpu_index; /* CPU index (informative) */ \ 204 | uint32_t host_tid; /* host thread ID */ \ 205 | int numa_node; /* NUMA node this cpu is belonging to */ \ 206 | int nr_cores; /* number of cores within this CPU package */ \ 207 | int nr_threads;/* number of threads within this CPU */ \ 208 | int running; /* Nonzero if cpu is currently running(usermode). */ \ 209 | int thread_id; \ 210 | /* user data */ \ 211 | void *opaque; \ 212 | \ 213 | uint32_t created; \ 214 | uint32_t stop; /* Stop request */ \ 215 | uint32_t stopped; /* Artificially stopped */ \ 216 | struct QemuThread *thread; \ 217 | struct QemuCond *halt_cond; \ 218 | int thread_kicked; \ 219 | struct qemu_work_item *queued_work_first, *queued_work_last; \ 220 | const char *cpu_model_str; \ 221 | struct KVMState *kvm_state; \ 222 | struct kvm_run *kvm_run; \ 223 | int kvm_fd; \ 224 | int kvm_vcpu_dirty; 225 | 226 | #endif 227 | -------------------------------------------------------------------------------- /qemu/cpus.h: -------------------------------------------------------------------------------- 1 | #ifndef QEMU_CPUS_H 2 | #define QEMU_CPUS_H 3 | 4 | /* cpus.c */ 5 | int qemu_init_main_loop(void); 6 | void qemu_main_loop_start(void); 7 | void resume_all_vcpus(void); 8 | void pause_all_vcpus(void); 9 | void cpu_stop_current(void); 10 | 11 | void cpu_synchronize_all_states(void); 12 | void cpu_synchronize_all_post_reset(void); 13 | void cpu_synchronize_all_post_init(void); 14 | 15 | /* vl.c */ 16 | extern int smp_cores; 17 | extern int smp_threads; 18 | void vm_state_notify(int running, int reason); 19 | bool cpu_exec_all(void); 20 | void set_numa_modes(void); 21 | void set_cpu_log(const char *optarg); 22 | void set_cpu_log_filename(const char *optarg); 23 | void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /qemu/cutils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple C functions to supplement the C library 3 | * 4 | * Copyright (c) 2006 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include "qemu-common.h" 25 | #include "host-utils.h" 26 | #include 27 | 28 | void pstrcpy(char *buf, int buf_size, const char *str) 29 | { 30 | int c; 31 | char *q = buf; 32 | 33 | if (buf_size <= 0) 34 | return; 35 | 36 | for(;;) { 37 | c = *str++; 38 | if (c == 0 || q >= buf + buf_size - 1) 39 | break; 40 | *q++ = c; 41 | } 42 | *q = '\0'; 43 | } 44 | 45 | /* strcat and truncate. */ 46 | char *pstrcat(char *buf, int buf_size, const char *s) 47 | { 48 | int len; 49 | len = strlen(buf); 50 | if (len < buf_size) 51 | pstrcpy(buf + len, buf_size - len, s); 52 | return buf; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /qemu/def-helper.h: -------------------------------------------------------------------------------- 1 | /* Helper file for declaring TCG helper functions. 2 | Should be included at the start and end of target-foo/helper.h. 3 | 4 | Targets should use DEF_HELPER_N and DEF_HELPER_FLAGS_N to declare helper 5 | functions. Names should be specified without the helper_ prefix, and 6 | the return and argument types specified. 3 basic types are understood 7 | (i32, i64 and ptr). Additional aliases are provided for convenience and 8 | to match the types used by the C helper implementation. 9 | 10 | The target helper.h should be included in all files that use/define 11 | helper functions. THis will ensure that function prototypes are 12 | consistent. In addition it should be included an extra two times for 13 | helper.c, defining: 14 | GEN_HELPER 1 to produce op generation functions (gen_helper_*) 15 | GEN_HELPER 2 to do runtime registration helper functions. 16 | */ 17 | 18 | #ifndef DEF_HELPER_H 19 | #define DEF_HELPER_H 1 20 | 21 | #define HELPER(name) glue(helper_, name) 22 | 23 | #define GET_TCGV_i32 GET_TCGV_I32 24 | #define GET_TCGV_i64 GET_TCGV_I64 25 | #define GET_TCGV_ptr GET_TCGV_PTR 26 | 27 | /* Some types that make sense in C, but not for TCG. */ 28 | #define dh_alias_i32 i32 29 | #define dh_alias_s32 i32 30 | #define dh_alias_int i32 31 | #define dh_alias_i64 i64 32 | #define dh_alias_s64 i64 33 | #define dh_alias_f32 i32 34 | #define dh_alias_f64 i64 35 | #if TARGET_LONG_BITS == 32 36 | #define dh_alias_tl i32 37 | #else 38 | #define dh_alias_tl i64 39 | #endif 40 | #define dh_alias_ptr ptr 41 | #define dh_alias_void void 42 | #define dh_alias_env ptr 43 | #define dh_alias(t) glue(dh_alias_, t) 44 | 45 | #define dh_ctype_i32 uint32_t 46 | #define dh_ctype_s32 int32_t 47 | #define dh_ctype_int int 48 | #define dh_ctype_i64 uint64_t 49 | #define dh_ctype_s64 int64_t 50 | #define dh_ctype_f32 float32 51 | #define dh_ctype_f64 float64 52 | #define dh_ctype_tl target_ulong 53 | #define dh_ctype_ptr void * 54 | #define dh_ctype_void void 55 | #define dh_ctype_env CPUState * 56 | #define dh_ctype(t) dh_ctype_##t 57 | 58 | /* We can't use glue() here because it falls foul of C preprocessor 59 | recursive expansion rules. */ 60 | #define dh_retvar_decl0_void void 61 | #define dh_retvar_decl0_i32 TCGv_i32 retval 62 | #define dh_retvar_decl0_i64 TCGv_i64 retval 63 | #define dh_retvar_decl0_ptr TCGv_ptr retval 64 | #define dh_retvar_decl0(t) glue(dh_retvar_decl0_, dh_alias(t)) 65 | 66 | #define dh_retvar_decl_void 67 | #define dh_retvar_decl_i32 TCGv_i32 retval, 68 | #define dh_retvar_decl_i64 TCGv_i64 retval, 69 | #define dh_retvar_decl_ptr TCGv_ptr retval, 70 | #define dh_retvar_decl(t) glue(dh_retvar_decl_, dh_alias(t)) 71 | 72 | #define dh_retvar_void TCG_CALL_DUMMY_ARG 73 | #define dh_retvar_i32 GET_TCGV_i32(retval) 74 | #define dh_retvar_i64 GET_TCGV_i64(retval) 75 | #define dh_retvar_ptr GET_TCGV_ptr(retval) 76 | #define dh_retvar(t) glue(dh_retvar_, dh_alias(t)) 77 | 78 | #define dh_is_64bit_void 0 79 | #define dh_is_64bit_i32 0 80 | #define dh_is_64bit_i64 1 81 | #define dh_is_64bit_ptr (TCG_TARGET_REG_BITS == 64) 82 | #define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t)) 83 | 84 | #define dh_is_signed_void 0 85 | #define dh_is_signed_i32 0 86 | #define dh_is_signed_s32 1 87 | #define dh_is_signed_i64 0 88 | #define dh_is_signed_s64 1 89 | #define dh_is_signed_f32 0 90 | #define dh_is_signed_f64 0 91 | #define dh_is_signed_tl 0 92 | #define dh_is_signed_int 1 93 | /* ??? This is highly specific to the host cpu. There are even special 94 | extension instructions that may be required, e.g. ia64's addp4. But 95 | for now we don't support any 64-bit targets with 32-bit pointers. */ 96 | #define dh_is_signed_ptr 0 97 | #define dh_is_signed_env dh_is_signed_ptr 98 | #define dh_is_signed(t) dh_is_signed_##t 99 | 100 | #define dh_sizemask(t, n) \ 101 | sizemask |= dh_is_64bit(t) << (n*2); \ 102 | sizemask |= dh_is_signed(t) << (n*2+1) 103 | 104 | #define dh_arg(t, n) \ 105 | args[n - 1] = glue(GET_TCGV_, dh_alias(t))(glue(arg, n)); \ 106 | dh_sizemask(t, n) 107 | 108 | #define dh_arg_decl(t, n) glue(TCGv_, dh_alias(t)) glue(arg, n) 109 | 110 | 111 | #define DEF_HELPER_0(name, ret) \ 112 | DEF_HELPER_FLAGS_0(name, 0, ret) 113 | #define DEF_HELPER_1(name, ret, t1) \ 114 | DEF_HELPER_FLAGS_1(name, 0, ret, t1) 115 | #define DEF_HELPER_2(name, ret, t1, t2) \ 116 | DEF_HELPER_FLAGS_2(name, 0, ret, t1, t2) 117 | #define DEF_HELPER_3(name, ret, t1, t2, t3) \ 118 | DEF_HELPER_FLAGS_3(name, 0, ret, t1, t2, t3) 119 | #define DEF_HELPER_4(name, ret, t1, t2, t3, t4) \ 120 | DEF_HELPER_FLAGS_4(name, 0, ret, t1, t2, t3, t4) 121 | 122 | #endif /* DEF_HELPER_H */ 123 | 124 | #ifndef GEN_HELPER 125 | /* Function prototypes. */ 126 | 127 | #define DEF_HELPER_FLAGS_0(name, flags, ret) \ 128 | dh_ctype(ret) HELPER(name) (void); 129 | 130 | #define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \ 131 | dh_ctype(ret) HELPER(name) (dh_ctype(t1)); 132 | 133 | #define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \ 134 | dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2)); 135 | 136 | #define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \ 137 | dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3)); 138 | 139 | #define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \ 140 | dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \ 141 | dh_ctype(t4)); 142 | 143 | #undef GEN_HELPER 144 | #define GEN_HELPER -1 145 | 146 | #elif GEN_HELPER == 1 147 | /* Gen functions. */ 148 | 149 | #define DEF_HELPER_FLAGS_0(name, flags, ret) \ 150 | static inline void glue(gen_helper_, name)(dh_retvar_decl0(ret)) \ 151 | { \ 152 | int sizemask; \ 153 | sizemask = dh_is_64bit(ret); \ 154 | tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 0, NULL); \ 155 | } 156 | 157 | #define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \ 158 | static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1)) \ 159 | { \ 160 | TCGArg args[1]; \ 161 | int sizemask = 0; \ 162 | dh_sizemask(ret, 0); \ 163 | dh_arg(t1, 1); \ 164 | tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 1, args); \ 165 | } 166 | 167 | #define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \ 168 | static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), \ 169 | dh_arg_decl(t2, 2)) \ 170 | { \ 171 | TCGArg args[2]; \ 172 | int sizemask = 0; \ 173 | dh_sizemask(ret, 0); \ 174 | dh_arg(t1, 1); \ 175 | dh_arg(t2, 2); \ 176 | tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 2, args); \ 177 | } 178 | 179 | #define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \ 180 | static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), \ 181 | dh_arg_decl(t2, 2), dh_arg_decl(t3, 3)) \ 182 | { \ 183 | TCGArg args[3]; \ 184 | int sizemask = 0; \ 185 | dh_sizemask(ret, 0); \ 186 | dh_arg(t1, 1); \ 187 | dh_arg(t2, 2); \ 188 | dh_arg(t3, 3); \ 189 | tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 3, args); \ 190 | } 191 | 192 | #define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \ 193 | static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1), \ 194 | dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), dh_arg_decl(t4, 4)) \ 195 | { \ 196 | TCGArg args[4]; \ 197 | int sizemask = 0; \ 198 | dh_sizemask(ret, 0); \ 199 | dh_arg(t1, 1); \ 200 | dh_arg(t2, 2); \ 201 | dh_arg(t3, 3); \ 202 | dh_arg(t4, 4); \ 203 | tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 4, args); \ 204 | } 205 | 206 | #undef GEN_HELPER 207 | #define GEN_HELPER -1 208 | 209 | #elif GEN_HELPER == 2 210 | /* Register helpers. */ 211 | 212 | #define DEF_HELPER_FLAGS_0(name, flags, ret) \ 213 | tcg_register_helper(HELPER(name), #name); 214 | 215 | #define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \ 216 | DEF_HELPER_FLAGS_0(name, flags, ret) 217 | 218 | #define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \ 219 | DEF_HELPER_FLAGS_0(name, flags, ret) 220 | 221 | #define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \ 222 | DEF_HELPER_FLAGS_0(name, flags, ret) 223 | 224 | #define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \ 225 | DEF_HELPER_FLAGS_0(name, flags, ret) 226 | 227 | #undef GEN_HELPER 228 | #define GEN_HELPER -1 229 | 230 | #elif GEN_HELPER == -1 231 | /* Undefine macros. */ 232 | 233 | #undef DEF_HELPER_FLAGS_0 234 | #undef DEF_HELPER_FLAGS_1 235 | #undef DEF_HELPER_FLAGS_2 236 | #undef DEF_HELPER_FLAGS_3 237 | #undef DEF_HELPER_FLAGS_4 238 | #undef GEN_HELPER 239 | 240 | #endif 241 | -------------------------------------------------------------------------------- /qemu/disas.h: -------------------------------------------------------------------------------- 1 | #ifndef _QEMU_DISAS_H 2 | #define _QEMU_DISAS_H 3 | 4 | #include "qemu-common.h" 5 | 6 | #ifdef NEED_CPU_H 7 | /* Disassemble this for me please... (debugging). */ 8 | void disas(FILE *out, void *code, unsigned long size); 9 | void target_disas(FILE *out, target_ulong code, target_ulong size, int flags); 10 | 11 | void monitor_disas(Monitor *mon, CPUState *env, 12 | target_ulong pc, int nb_insn, int is_physical, int flags); 13 | 14 | /* Look up symbol for debugging purpose. Returns "" if unknown. */ 15 | const char *lookup_symbol(target_ulong orig_addr); 16 | #endif 17 | 18 | struct syminfo; 19 | struct elf32_sym; 20 | struct elf64_sym; 21 | 22 | #if defined(CONFIG_USER_ONLY) 23 | typedef const char *(*lookup_symbol_t)(struct syminfo *s, target_ulong orig_addr); 24 | #else 25 | typedef const char *(*lookup_symbol_t)(struct syminfo *s, target_phys_addr_t orig_addr); 26 | #endif 27 | 28 | struct syminfo { 29 | lookup_symbol_t lookup_symbol; 30 | unsigned int disas_num_syms; 31 | union { 32 | struct elf32_sym *elf32; 33 | struct elf64_sym *elf64; 34 | } disas_symtab; 35 | const char *disas_strtab; 36 | struct syminfo *next; 37 | }; 38 | 39 | /* Filled in by elfload.c. Simplistic, but will do for now. */ 40 | extern struct syminfo *syminfos; 41 | 42 | #endif /* _QEMU_DISAS_H */ 43 | -------------------------------------------------------------------------------- /qemu/exec-all.h: -------------------------------------------------------------------------------- 1 | /* 2 | * internal execution defines for qemu 3 | * 4 | * Copyright (c) 2003 Fabrice Bellard 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | #ifndef _EXEC_ALL_H_ 21 | #define _EXEC_ALL_H_ 22 | 23 | #include "qemu-common.h" 24 | 25 | /* allow to see translation results - the slowdown should be negligible, so we leave it */ 26 | #define DEBUG_DISAS 27 | 28 | /* Page tracking code uses ram addresses in system mode, and virtual 29 | addresses in userspace mode. Define tb_page_addr_t to be an appropriate 30 | type. */ 31 | #if defined(CONFIG_USER_ONLY) 32 | typedef abi_ulong tb_page_addr_t; 33 | #else 34 | typedef ram_addr_t tb_page_addr_t; 35 | #endif 36 | 37 | /* is_jmp field values */ 38 | #define DISAS_NEXT 0 /* next instruction can be analyzed */ 39 | #define DISAS_JUMP 1 /* only pc was modified dynamically */ 40 | #define DISAS_UPDATE 2 /* cpu state was modified dynamically */ 41 | #define DISAS_TB_JUMP 3 /* only pc was modified statically */ 42 | 43 | struct TranslationBlock; 44 | typedef struct TranslationBlock TranslationBlock; 45 | 46 | /* XXX: make safe guess about sizes */ 47 | #define MAX_OP_PER_INSTR 208 48 | 49 | #if HOST_LONG_BITS == 32 50 | #define MAX_OPC_PARAM_PER_ARG 2 51 | #else 52 | #define MAX_OPC_PARAM_PER_ARG 1 53 | #endif 54 | #define MAX_OPC_PARAM_IARGS 4 55 | #define MAX_OPC_PARAM_OARGS 1 56 | #define MAX_OPC_PARAM_ARGS (MAX_OPC_PARAM_IARGS + MAX_OPC_PARAM_OARGS) 57 | 58 | /* A Call op needs up to 4 + 2N parameters on 32-bit archs, 59 | * and up to 4 + N parameters on 64-bit archs 60 | * (N = number of input arguments + output arguments). */ 61 | #define MAX_OPC_PARAM (4 + (MAX_OPC_PARAM_PER_ARG * MAX_OPC_PARAM_ARGS)) 62 | #define OPC_BUF_SIZE 640 63 | #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR) 64 | 65 | /* Maximum size a TCG op can expand to. This is complicated because a 66 | single op may require several host instructions and register reloads. 67 | For now take a wild guess at 192 bytes, which should allow at least 68 | a couple of fixup instructions per argument. */ 69 | #define TCG_MAX_OP_SIZE 192 70 | 71 | #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * MAX_OPC_PARAM) 72 | 73 | extern target_ulong gen_opc_pc[OPC_BUF_SIZE]; 74 | extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; 75 | extern uint16_t gen_opc_icount[OPC_BUF_SIZE]; 76 | 77 | #include "qemu-log.h" 78 | 79 | void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb); 80 | void gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb); 81 | void restore_state_to_opc(CPUState *env, struct TranslationBlock *tb, 82 | int pc_pos); 83 | 84 | void cpu_gen_init(void); 85 | int cpu_gen_code(CPUState *env, struct TranslationBlock *tb, 86 | int *gen_code_size_ptr); 87 | int cpu_restore_state(struct TranslationBlock *tb, 88 | CPUState *env, unsigned long searched_pc); 89 | void cpu_resume_from_signal(CPUState *env1, void *puc); 90 | void cpu_io_recompile(CPUState *env, void *retaddr); 91 | TranslationBlock *tb_gen_code(CPUState *env, 92 | target_ulong pc, target_ulong cs_base, int flags, 93 | int cflags); 94 | void cpu_exec_init(CPUState *env); 95 | void QEMU_NORETURN cpu_loop_exit(CPUState *env1); 96 | int page_unprotect(target_ulong address, unsigned long pc, void *puc); 97 | void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, 98 | int is_cpu_write_access); 99 | void tlb_flush_page(CPUState *env, target_ulong addr); 100 | void tlb_flush(CPUState *env, int flush_global); 101 | #if !defined(CONFIG_USER_ONLY) 102 | void tlb_set_page(CPUState *env, target_ulong vaddr, 103 | target_phys_addr_t paddr, int prot, 104 | int mmu_idx, target_ulong size); 105 | #endif 106 | 107 | #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ 108 | 109 | #define CODE_GEN_PHYS_HASH_BITS 15 110 | #define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS) 111 | 112 | #define MIN_CODE_GEN_BUFFER_SIZE (1024 * 1024) 113 | 114 | /* estimated block size for TB allocation */ 115 | /* XXX: use a per code average code fragment size and modulate it 116 | according to the host CPU */ 117 | #if defined(CONFIG_SOFTMMU) 118 | #define CODE_GEN_AVG_BLOCK_SIZE 128 119 | #else 120 | #define CODE_GEN_AVG_BLOCK_SIZE 64 121 | #endif 122 | 123 | #if defined(_ARCH_PPC) || defined(__x86_64__) || defined(__arm__) || defined(__i386__) || defined(__aarch64__) 124 | #define USE_DIRECT_JUMP 125 | #endif 126 | 127 | struct TranslationBlock { 128 | target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */ 129 | target_ulong cs_base; /* CS base for this block */ 130 | uint64_t flags; /* flags defining in which context the code was generated */ 131 | uint16_t size; /* size of target code for this block (1 <= 132 | size <= TARGET_PAGE_SIZE) */ 133 | uint16_t cflags; /* compile flags */ 134 | #define CF_COUNT_MASK 0x7fff 135 | #define CF_LAST_IO 0x8000 /* Last insn may be an IO access. */ 136 | 137 | uint8_t *tc_ptr; /* pointer to the translated code */ 138 | /* next matching tb for physical address. */ 139 | struct TranslationBlock *phys_hash_next; 140 | /* first and second physical page containing code. The lower bit 141 | of the pointer tells the index in page_next[] */ 142 | struct TranslationBlock *page_next[2]; 143 | tb_page_addr_t page_addr[2]; 144 | 145 | /* the following data are used to directly call another TB from 146 | the code of this one. */ 147 | uint16_t tb_next_offset[2]; /* offset of original jump target */ 148 | #ifdef USE_DIRECT_JUMP 149 | uint16_t tb_jmp_offset[2]; /* offset of jump instruction */ 150 | #else 151 | unsigned long tb_next[2]; /* address of jump generated code */ 152 | #endif 153 | /* list of TBs jumping to this one. This is a circular list using 154 | the two least significant bits of the pointers to tell what is 155 | the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 = 156 | jmp_first */ 157 | struct TranslationBlock *jmp_next[2]; 158 | struct TranslationBlock *jmp_first; 159 | uint32_t icount; 160 | }; 161 | 162 | static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc) 163 | { 164 | target_ulong tmp; 165 | tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)); 166 | return (tmp >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)) & TB_JMP_PAGE_MASK; 167 | } 168 | 169 | static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc) 170 | { 171 | target_ulong tmp; 172 | tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)); 173 | return (((tmp >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)) & TB_JMP_PAGE_MASK) 174 | | (tmp & TB_JMP_ADDR_MASK)); 175 | } 176 | 177 | static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc) 178 | { 179 | return (pc >> 2) & (CODE_GEN_PHYS_HASH_SIZE - 1); 180 | } 181 | 182 | void tb_free(TranslationBlock *tb); 183 | void tb_flush(CPUState *env); 184 | void tb_link_page(TranslationBlock *tb, 185 | tb_page_addr_t phys_pc, tb_page_addr_t phys_page2); 186 | void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr); 187 | 188 | extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; 189 | 190 | #if defined(USE_DIRECT_JUMP) 191 | 192 | #if defined(_ARCH_PPC) 193 | void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr); 194 | #define tb_set_jmp_target1 ppc_tb_set_jmp_target 195 | #elif defined(__i386__) || defined(__x86_64__) 196 | static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) 197 | { 198 | /* patch the branch destination */ 199 | *(uint32_t *)jmp_addr = addr - (jmp_addr + 4); 200 | /* no need to flush icache explicitly */ 201 | } 202 | #elif defined(__aarch64__) 203 | void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr); 204 | #define tb_set_jmp_target1 aarch64_tb_set_jmp_target 205 | #elif defined(__arm__) 206 | static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) 207 | { 208 | #if !QEMU_GNUC_PREREQ(4, 1) 209 | register unsigned long _beg __asm ("a1"); 210 | register unsigned long _end __asm ("a2"); 211 | register unsigned long _flg __asm ("a3"); 212 | #endif 213 | 214 | /* we could use a ldr pc, [pc, #-4] kind of branch and avoid the flush */ 215 | *(uint32_t *)jmp_addr = 216 | (*(uint32_t *)jmp_addr & ~0xffffff) 217 | | (((addr - (jmp_addr + 8)) >> 2) & 0xffffff); 218 | 219 | #if QEMU_GNUC_PREREQ(4, 1) 220 | __builtin___clear_cache((char *) jmp_addr, (char *) jmp_addr + 4); 221 | #else 222 | /* flush icache */ 223 | _beg = jmp_addr; 224 | _end = jmp_addr + 4; 225 | _flg = 0; 226 | __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); 227 | #endif 228 | } 229 | #endif 230 | 231 | static inline void tb_set_jmp_target(TranslationBlock *tb, 232 | int n, unsigned long addr) 233 | { 234 | unsigned long offset; 235 | 236 | offset = tb->tb_jmp_offset[n]; 237 | tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr); 238 | } 239 | 240 | #else 241 | 242 | /* set the jump target */ 243 | static inline void tb_set_jmp_target(TranslationBlock *tb, 244 | int n, unsigned long addr) 245 | { 246 | tb->tb_next[n] = addr; 247 | } 248 | 249 | #endif 250 | 251 | static inline void tb_add_jump(TranslationBlock *tb, int n, 252 | TranslationBlock *tb_next) 253 | { 254 | /* NOTE: this test is only needed for thread safety */ 255 | if (!tb->jmp_next[n]) { 256 | /* patch the native jump address */ 257 | tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr); 258 | 259 | /* add in TB jmp circular list */ 260 | tb->jmp_next[n] = tb_next->jmp_first; 261 | tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n)); 262 | } 263 | } 264 | 265 | TranslationBlock *tb_find_pc(unsigned long pc_ptr); 266 | 267 | #include "qemu-lock.h" 268 | 269 | extern spinlock_t tb_lock; 270 | 271 | extern int tb_invalidated_flag; 272 | 273 | #if !defined(CONFIG_USER_ONLY) 274 | 275 | extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; 276 | extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; 277 | extern void *io_mem_opaque[IO_MEM_NB_ENTRIES]; 278 | 279 | void tlb_fill(target_ulong addr, int is_write, int mmu_idx, 280 | void *retaddr); 281 | 282 | #include "softmmu_defs.h" 283 | 284 | #define ACCESS_TYPE (NB_MMU_MODES + 1) 285 | #define MEMSUFFIX _code 286 | #define env cpu_single_env 287 | 288 | #define DATA_SIZE 1 289 | #include "softmmu_header.h" 290 | 291 | #define DATA_SIZE 2 292 | #include "softmmu_header.h" 293 | 294 | #define DATA_SIZE 4 295 | #include "softmmu_header.h" 296 | 297 | #define DATA_SIZE 8 298 | #include "softmmu_header.h" 299 | 300 | #undef ACCESS_TYPE 301 | #undef MEMSUFFIX 302 | #undef env 303 | 304 | #endif 305 | 306 | #if defined(CONFIG_USER_ONLY) 307 | static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr) 308 | { 309 | return addr; 310 | } 311 | #else 312 | /* NOTE: this function can trigger an exception */ 313 | /* NOTE2: the returned address is not exactly the physical address: it 314 | is the offset relative to phys_ram_base */ 315 | static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr) 316 | { 317 | int mmu_idx, page_index, pd; 318 | void *p; 319 | 320 | page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); 321 | mmu_idx = cpu_mmu_index(env1); 322 | if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code != 323 | (addr & TARGET_PAGE_MASK))) { 324 | ldub_code(addr); 325 | } 326 | pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK; 327 | if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { 328 | #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC) 329 | cpu_unassigned_access(env1, addr, 0, 1, 0, 4); 330 | #else 331 | cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr); 332 | #endif 333 | } 334 | p = (void *)(unsigned long)addr 335 | + env1->tlb_table[mmu_idx][page_index].addend; 336 | return qemu_ram_addr_from_host_nofail(p); 337 | } 338 | #endif 339 | 340 | typedef void (CPUDebugExcpHandler)(CPUState *env); 341 | 342 | CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler); 343 | 344 | /* vl.c */ 345 | extern int singlestep; 346 | 347 | /* cpu-exec.c */ 348 | extern volatile sig_atomic_t exit_request; 349 | 350 | #endif 351 | -------------------------------------------------------------------------------- /qemu/host-utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Utility compute operations used by translated code. 3 | * 4 | * Copyright (c) 2003 Fabrice Bellard 5 | * Copyright (c) 2007 Aurelien Jarno 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include "host-utils.h" 29 | 30 | //#define DEBUG_MULDIV 31 | 32 | /* Long integer helpers */ 33 | #if !defined(__x86_64__) 34 | static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) 35 | { 36 | *plow += a; 37 | /* carry test */ 38 | if (*plow < a) 39 | (*phigh)++; 40 | *phigh += b; 41 | } 42 | 43 | static void neg128 (uint64_t *plow, uint64_t *phigh) 44 | { 45 | *plow = ~*plow; 46 | *phigh = ~*phigh; 47 | add128(plow, phigh, 1, 0); 48 | } 49 | 50 | static void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) 51 | { 52 | uint32_t a0, a1, b0, b1; 53 | uint64_t v; 54 | 55 | a0 = a; 56 | a1 = a >> 32; 57 | 58 | b0 = b; 59 | b1 = b >> 32; 60 | 61 | v = (uint64_t)a0 * (uint64_t)b0; 62 | *plow = v; 63 | *phigh = 0; 64 | 65 | v = (uint64_t)a0 * (uint64_t)b1; 66 | add128(plow, phigh, v << 32, v >> 32); 67 | 68 | v = (uint64_t)a1 * (uint64_t)b0; 69 | add128(plow, phigh, v << 32, v >> 32); 70 | 71 | v = (uint64_t)a1 * (uint64_t)b1; 72 | *phigh += v; 73 | } 74 | 75 | /* Unsigned 64x64 -> 128 multiplication */ 76 | void mulu64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) 77 | { 78 | mul64(plow, phigh, a, b); 79 | #if defined(DEBUG_MULDIV) 80 | printf("mulu64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n", 81 | a, b, *phigh, *plow); 82 | #endif 83 | } 84 | 85 | /* Signed 64x64 -> 128 multiplication */ 86 | void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b) 87 | { 88 | int sa, sb; 89 | 90 | sa = (a < 0); 91 | if (sa) 92 | a = -a; 93 | sb = (b < 0); 94 | if (sb) 95 | b = -b; 96 | mul64(plow, phigh, a, b); 97 | if (sa ^ sb) { 98 | neg128(plow, phigh); 99 | } 100 | #if defined(DEBUG_MULDIV) 101 | printf("muls64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n", 102 | a, b, *phigh, *plow); 103 | #endif 104 | } 105 | #endif /* !defined(__x86_64__) */ 106 | -------------------------------------------------------------------------------- /qemu/host-utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Utility compute operations used by translated code. 3 | * 4 | * Copyright (c) 2007 Thiemo Seufer 5 | * Copyright (c) 2007 Jocelyn Mayer 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include "osdep.h" 27 | 28 | #if defined(__x86_64__) 29 | #define __HAVE_FAST_MULU64__ 30 | static inline void mulu64(uint64_t *plow, uint64_t *phigh, 31 | uint64_t a, uint64_t b) 32 | { 33 | __asm__ ("mul %0\n\t" 34 | : "=d" (*phigh), "=a" (*plow) 35 | : "a" (a), "0" (b)); 36 | } 37 | #define __HAVE_FAST_MULS64__ 38 | static inline void muls64(uint64_t *plow, uint64_t *phigh, 39 | int64_t a, int64_t b) 40 | { 41 | __asm__ ("imul %0\n\t" 42 | : "=d" (*phigh), "=a" (*plow) 43 | : "a" (a), "0" (b)); 44 | } 45 | #else 46 | void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b); 47 | void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b); 48 | #endif 49 | 50 | /* Binary search for leading zeros. */ 51 | 52 | static inline int clz32(uint32_t val) 53 | { 54 | #if QEMU_GNUC_PREREQ(3, 4) 55 | if (val) 56 | return __builtin_clz(val); 57 | else 58 | return 32; 59 | #else 60 | int cnt = 0; 61 | 62 | if (!(val & 0xFFFF0000U)) { 63 | cnt += 16; 64 | val <<= 16; 65 | } 66 | if (!(val & 0xFF000000U)) { 67 | cnt += 8; 68 | val <<= 8; 69 | } 70 | if (!(val & 0xF0000000U)) { 71 | cnt += 4; 72 | val <<= 4; 73 | } 74 | if (!(val & 0xC0000000U)) { 75 | cnt += 2; 76 | val <<= 2; 77 | } 78 | if (!(val & 0x80000000U)) { 79 | cnt++; 80 | val <<= 1; 81 | } 82 | if (!(val & 0x80000000U)) { 83 | cnt++; 84 | } 85 | return cnt; 86 | #endif 87 | } 88 | 89 | static inline int clo32(uint32_t val) 90 | { 91 | return clz32(~val); 92 | } 93 | 94 | static inline int clz64(uint64_t val) 95 | { 96 | #if QEMU_GNUC_PREREQ(3, 4) 97 | if (val) 98 | return __builtin_clzll(val); 99 | else 100 | return 64; 101 | #else 102 | int cnt = 0; 103 | 104 | if (!(val >> 32)) { 105 | cnt += 32; 106 | } else { 107 | val >>= 32; 108 | } 109 | 110 | return cnt + clz32(val); 111 | #endif 112 | } 113 | 114 | static inline int clo64(uint64_t val) 115 | { 116 | return clz64(~val); 117 | } 118 | 119 | static inline int ctz32(uint32_t val) 120 | { 121 | #if QEMU_GNUC_PREREQ(3, 4) 122 | if (val) 123 | return __builtin_ctz(val); 124 | else 125 | return 32; 126 | #else 127 | int cnt; 128 | 129 | cnt = 0; 130 | if (!(val & 0x0000FFFFUL)) { 131 | cnt += 16; 132 | val >>= 16; 133 | } 134 | if (!(val & 0x000000FFUL)) { 135 | cnt += 8; 136 | val >>= 8; 137 | } 138 | if (!(val & 0x0000000FUL)) { 139 | cnt += 4; 140 | val >>= 4; 141 | } 142 | if (!(val & 0x00000003UL)) { 143 | cnt += 2; 144 | val >>= 2; 145 | } 146 | if (!(val & 0x00000001UL)) { 147 | cnt++; 148 | val >>= 1; 149 | } 150 | if (!(val & 0x00000001UL)) { 151 | cnt++; 152 | } 153 | 154 | return cnt; 155 | #endif 156 | } 157 | 158 | static inline int cto32(uint32_t val) 159 | { 160 | return ctz32(~val); 161 | } 162 | 163 | static inline int ctz64(uint64_t val) 164 | { 165 | #if QEMU_GNUC_PREREQ(3, 4) 166 | if (val) 167 | return __builtin_ctzll(val); 168 | else 169 | return 64; 170 | #else 171 | int cnt; 172 | 173 | cnt = 0; 174 | if (!((uint32_t)val)) { 175 | cnt += 32; 176 | val >>= 32; 177 | } 178 | 179 | return cnt + ctz32(val); 180 | #endif 181 | } 182 | 183 | static inline int cto64(uint64_t val) 184 | { 185 | return ctz64(~val); 186 | } 187 | 188 | static inline int ctpop8(uint8_t val) 189 | { 190 | val = (val & 0x55) + ((val >> 1) & 0x55); 191 | val = (val & 0x33) + ((val >> 2) & 0x33); 192 | val = (val & 0x0f) + ((val >> 4) & 0x0f); 193 | 194 | return val; 195 | } 196 | 197 | static inline int ctpop16(uint16_t val) 198 | { 199 | val = (val & 0x5555) + ((val >> 1) & 0x5555); 200 | val = (val & 0x3333) + ((val >> 2) & 0x3333); 201 | val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f); 202 | val = (val & 0x00ff) + ((val >> 8) & 0x00ff); 203 | 204 | return val; 205 | } 206 | 207 | static inline int ctpop32(uint32_t val) 208 | { 209 | #if QEMU_GNUC_PREREQ(3, 4) 210 | return __builtin_popcount(val); 211 | #else 212 | val = (val & 0x55555555) + ((val >> 1) & 0x55555555); 213 | val = (val & 0x33333333) + ((val >> 2) & 0x33333333); 214 | val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f); 215 | val = (val & 0x00ff00ff) + ((val >> 8) & 0x00ff00ff); 216 | val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff); 217 | 218 | return val; 219 | #endif 220 | } 221 | 222 | static inline int ctpop64(uint64_t val) 223 | { 224 | #if QEMU_GNUC_PREREQ(3, 4) 225 | return __builtin_popcountll(val); 226 | #else 227 | val = (val & 0x5555555555555555ULL) + ((val >> 1) & 0x5555555555555555ULL); 228 | val = (val & 0x3333333333333333ULL) + ((val >> 2) & 0x3333333333333333ULL); 229 | val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) & 0x0f0f0f0f0f0f0f0fULL); 230 | val = (val & 0x00ff00ff00ff00ffULL) + ((val >> 8) & 0x00ff00ff00ff00ffULL); 231 | val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 0x0000ffff0000ffffULL); 232 | val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL); 233 | 234 | return val; 235 | #endif 236 | } 237 | -------------------------------------------------------------------------------- /qemu/ioport.h: -------------------------------------------------------------------------------- 1 | /* 2 | * defines ioport related functions 3 | * 4 | * Copyright (c) 2003 Fabrice Bellard 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | 20 | /************************************************************************** 21 | * IO ports API 22 | */ 23 | 24 | #ifndef IOPORT_H 25 | #define IOPORT_H 26 | 27 | #include "qemu-common.h" 28 | #include "iorange.h" 29 | 30 | typedef uint32_t pio_addr_t; 31 | #define FMT_pioaddr PRIx32 32 | 33 | #define MAX_IOPORTS (64 * 1024) 34 | #define IOPORTS_MASK (MAX_IOPORTS - 1) 35 | 36 | /* These should really be in isa.h, but are here to make pc.h happy. */ 37 | typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data); 38 | typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address); 39 | 40 | void ioport_register(IORange *iorange); 41 | int register_ioport_read(pio_addr_t start, int length, int size, 42 | IOPortReadFunc *func, void *opaque); 43 | int register_ioport_write(pio_addr_t start, int length, int size, 44 | IOPortWriteFunc *func, void *opaque); 45 | void isa_unassign_ioport(pio_addr_t start, int length); 46 | bool isa_is_ioport_assigned(pio_addr_t start); 47 | 48 | void cpu_outb(pio_addr_t addr, uint8_t val); 49 | void cpu_outw(pio_addr_t addr, uint16_t val); 50 | void cpu_outl(pio_addr_t addr, uint32_t val); 51 | uint8_t cpu_inb(pio_addr_t addr); 52 | uint16_t cpu_inw(pio_addr_t addr); 53 | uint32_t cpu_inl(pio_addr_t addr); 54 | 55 | #endif /* IOPORT_H */ 56 | -------------------------------------------------------------------------------- /qemu/iorange.h: -------------------------------------------------------------------------------- 1 | #ifndef IORANGE_H 2 | #define IORANGE_H 3 | 4 | #include 5 | 6 | typedef struct IORange IORange; 7 | typedef struct IORangeOps IORangeOps; 8 | 9 | struct IORangeOps { 10 | void (*read)(IORange *iorange, uint64_t offset, unsigned width, 11 | uint64_t *data); 12 | void (*write)(IORange *iorange, uint64_t offset, unsigned width, 13 | uint64_t data); 14 | }; 15 | 16 | struct IORange { 17 | const IORangeOps *ops; 18 | uint64_t base; 19 | uint64_t len; 20 | }; 21 | 22 | static inline void iorange_init(IORange *iorange, const IORangeOps *ops, 23 | uint64_t base, uint64_t len) 24 | { 25 | iorange->ops = ops; 26 | iorange->base = base; 27 | iorange->len = len; 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /qemu/nomath.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static inline double pow(double x, double y) 4 | { 5 | assert(0); 6 | __builtin_unreachable(); 7 | } 8 | 9 | static inline double log(double x) 10 | { 11 | assert(0); 12 | __builtin_unreachable(); 13 | } 14 | 15 | static inline double tan(double x) 16 | { 17 | assert(0); 18 | __builtin_unreachable(); 19 | } 20 | 21 | static inline double atan2(double y, double x) 22 | { 23 | assert(0); 24 | __builtin_unreachable(); 25 | } 26 | 27 | static inline int isinf(double x) 28 | { 29 | assert(0); 30 | __builtin_unreachable(); 31 | } 32 | 33 | static inline int isnan(double x) 34 | { 35 | assert(0); 36 | __builtin_unreachable(); 37 | } 38 | 39 | static inline double rint(double x) 40 | { 41 | assert(0); 42 | __builtin_unreachable(); 43 | } 44 | 45 | static inline double floor(double x) 46 | { 47 | assert(0); 48 | __builtin_unreachable(); 49 | } 50 | 51 | static inline double ceil(double x) 52 | { 53 | assert(0); 54 | __builtin_unreachable(); 55 | } 56 | 57 | static inline double fabs(double x) 58 | { 59 | assert(0); 60 | __builtin_unreachable(); 61 | } 62 | 63 | static inline double sin(double x) 64 | { 65 | assert(0); 66 | __builtin_unreachable(); 67 | } 68 | 69 | static inline double cos(double x) 70 | { 71 | assert(0); 72 | __builtin_unreachable(); 73 | } 74 | -------------------------------------------------------------------------------- /qemu/osdep.h: -------------------------------------------------------------------------------- 1 | #ifndef QEMU_OSDEP_H 2 | #define QEMU_OSDEP_H 3 | 4 | #include 5 | #include 6 | #ifdef __OpenBSD__ 7 | #include 8 | #include 9 | #endif 10 | 11 | #include 12 | 13 | #ifndef glue 14 | #define xglue(x, y) x ## y 15 | #define glue(x, y) xglue(x, y) 16 | #define stringify(s) tostring(s) 17 | #define tostring(s) #s 18 | #endif 19 | 20 | #ifndef likely 21 | #if __GNUC__ < 3 22 | #define __builtin_expect(x, n) (x) 23 | #endif 24 | 25 | #define likely(x) __builtin_expect(!!(x), 1) 26 | #define unlikely(x) __builtin_expect(!!(x), 0) 27 | #endif 28 | 29 | #ifdef CONFIG_NEED_OFFSETOF 30 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER) 31 | #endif 32 | #ifndef container_of 33 | #define container_of(ptr, type, member) ({ \ 34 | const typeof(((type *) 0)->member) *__mptr = (ptr); \ 35 | (type *) ((char *) __mptr - offsetof(type, member));}) 36 | #endif 37 | 38 | /* Convert from a base type to a parent type, with compile time checking. */ 39 | #ifdef __GNUC__ 40 | #define DO_UPCAST(type, field, dev) ( __extension__ ( { \ 41 | char __attribute__((unused)) offset_must_be_zero[ \ 42 | -offsetof(type, field)]; \ 43 | container_of(dev, type, field);})) 44 | #else 45 | #define DO_UPCAST(type, field, dev) container_of(dev, type, field) 46 | #endif 47 | 48 | #define typeof_field(type, field) typeof(((type *)0)->field) 49 | #define type_check(t1,t2) ((t1*)0 - (t2*)0) 50 | 51 | #ifndef MIN 52 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 53 | #endif 54 | #ifndef MAX 55 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 56 | #endif 57 | 58 | #ifndef DIV_ROUND_UP 59 | #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) 60 | #endif 61 | 62 | #ifndef ARRAY_SIZE 63 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 64 | #endif 65 | 66 | #ifndef always_inline 67 | #if !((__GNUC__ < 3) || defined(__APPLE__)) 68 | #ifdef __OPTIMIZE__ 69 | #define inline __attribute__ (( always_inline )) __inline__ 70 | #endif 71 | #endif 72 | #else 73 | #define inline always_inline 74 | #endif 75 | 76 | #ifdef __i386__ 77 | #define REGPARM __attribute((regparm(3))) 78 | #else 79 | #define REGPARM 80 | #endif 81 | 82 | #define qemu_printf printf 83 | 84 | #if defined (__GNUC__) && defined (__GNUC_MINOR__) 85 | # define QEMU_GNUC_PREREQ(maj, min) \ 86 | ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) 87 | #else 88 | # define QEMU_GNUC_PREREQ(maj, min) 0 89 | #endif 90 | 91 | int qemu_daemon(int nochdir, int noclose); 92 | void *qemu_memalign(size_t alignment, size_t size); 93 | void *qemu_vmalloc(size_t size); 94 | void qemu_vfree(void *ptr); 95 | 96 | #define QEMU_MADV_INVALID -1 97 | 98 | #if defined(CONFIG_MADVISE) 99 | 100 | #define QEMU_MADV_WILLNEED MADV_WILLNEED 101 | #define QEMU_MADV_DONTNEED MADV_DONTNEED 102 | #ifdef MADV_DONTFORK 103 | #define QEMU_MADV_DONTFORK MADV_DONTFORK 104 | #else 105 | #define QEMU_MADV_DONTFORK QEMU_MADV_INVALID 106 | #endif 107 | #ifdef MADV_MERGEABLE 108 | #define QEMU_MADV_MERGEABLE MADV_MERGEABLE 109 | #else 110 | #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID 111 | #endif 112 | 113 | #elif defined(CONFIG_POSIX_MADVISE) 114 | 115 | #define QEMU_MADV_WILLNEED POSIX_MADV_WILLNEED 116 | #define QEMU_MADV_DONTNEED POSIX_MADV_DONTNEED 117 | #define QEMU_MADV_DONTFORK QEMU_MADV_INVALID 118 | #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID 119 | 120 | #else /* no-op */ 121 | 122 | #define QEMU_MADV_WILLNEED QEMU_MADV_INVALID 123 | #define QEMU_MADV_DONTNEED QEMU_MADV_INVALID 124 | #define QEMU_MADV_DONTFORK QEMU_MADV_INVALID 125 | #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID 126 | 127 | #endif 128 | 129 | int qemu_madvise(void *addr, size_t len, int advice); 130 | 131 | #if defined(__HAIKU__) && defined(__i386__) 132 | #define FMT_pid "%ld" 133 | #else 134 | #define FMT_pid "%d" 135 | #endif 136 | 137 | int qemu_create_pidfile(const char *filename); 138 | int qemu_get_thread_id(void); 139 | 140 | #ifdef _WIN32 141 | static inline void qemu_timersub(const struct timeval *val1, 142 | const struct timeval *val2, 143 | struct timeval *res) 144 | { 145 | res->tv_sec = val1->tv_sec - val2->tv_sec; 146 | if (val1->tv_usec < val2->tv_usec) { 147 | res->tv_sec--; 148 | res->tv_usec = val1->tv_usec - val2->tv_usec + 1000 * 1000; 149 | } else { 150 | res->tv_usec = val1->tv_usec - val2->tv_usec; 151 | } 152 | } 153 | #else 154 | #define qemu_timersub timersub 155 | #endif 156 | 157 | #endif 158 | -------------------------------------------------------------------------------- /qemu/qemu-barrier.h: -------------------------------------------------------------------------------- 1 | #ifndef __QEMU_BARRIER_H 2 | #define __QEMU_BARRIER_H 1 3 | 4 | /* FIXME: arch dependant, x86 version */ 5 | #define smp_wmb() asm volatile("" ::: "memory") 6 | 7 | /* Compiler barrier */ 8 | #define barrier() asm volatile("" ::: "memory") 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /qemu/qemu-common.h: -------------------------------------------------------------------------------- 1 | /* Common header file that is included by all of qemu. */ 2 | #ifndef QEMU_COMMON_H 3 | #define QEMU_COMMON_H 4 | 5 | #include "compiler.h" 6 | #include "config-host.h" 7 | 8 | #if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__) 9 | #define WORDS_ALIGNED 10 | #endif 11 | 12 | #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR) 13 | 14 | typedef struct QEMUTimer QEMUTimer; 15 | typedef struct QEMUFile QEMUFile; 16 | typedef struct QEMUBH QEMUBH; 17 | typedef struct DeviceState DeviceState; 18 | 19 | struct Monitor; 20 | typedef struct Monitor Monitor; 21 | 22 | /* we put basic includes here to avoid repeating them in device drivers */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #ifdef _WIN32 42 | #include "qemu-os-win32.h" 43 | #endif 44 | 45 | #ifdef CONFIG_POSIX 46 | #include "qemu-os-posix.h" 47 | #endif 48 | 49 | #ifndef O_LARGEFILE 50 | #define O_LARGEFILE 0 51 | #endif 52 | #ifndef O_BINARY 53 | #define O_BINARY 0 54 | #endif 55 | #ifndef MAP_ANONYMOUS 56 | #define MAP_ANONYMOUS MAP_ANON 57 | #endif 58 | #ifndef ENOMEDIUM 59 | #define ENOMEDIUM ENODEV 60 | #endif 61 | #if !defined(ENOTSUP) 62 | #define ENOTSUP 4096 63 | #endif 64 | #ifndef TIME_MAX 65 | #define TIME_MAX LONG_MAX 66 | #endif 67 | 68 | #ifndef CONFIG_IOVEC 69 | #define CONFIG_IOVEC 70 | struct iovec { 71 | void *iov_base; 72 | size_t iov_len; 73 | }; 74 | /* 75 | * Use the same value as Linux for now. 76 | */ 77 | #define IOV_MAX 1024 78 | #else 79 | #include 80 | #endif 81 | 82 | typedef int (*fprintf_function)(FILE *f, const char *fmt, ...) 83 | GCC_FMT_ATTR(2, 3); 84 | 85 | #ifdef _WIN32 86 | #define fsync _commit 87 | #define lseek _lseeki64 88 | int qemu_ftruncate64(int, int64_t); 89 | #define ftruncate qemu_ftruncate64 90 | 91 | static inline char *realpath(const char *path, char *resolved_path) 92 | { 93 | _fullpath(resolved_path, path, _MAX_PATH); 94 | return resolved_path; 95 | } 96 | #endif 97 | 98 | /* FIXME: Remove NEED_CPU_H. */ 99 | #ifndef NEED_CPU_H 100 | 101 | #include "osdep.h" 102 | #include "bswap.h" 103 | 104 | #else 105 | 106 | #include "cpu.h" 107 | 108 | #endif /* !defined(NEED_CPU_H) */ 109 | 110 | /* main function, renamed */ 111 | #if defined(CONFIG_COCOA) 112 | int qemu_main(int argc, char **argv, char **envp); 113 | #endif 114 | 115 | /* bottom halves */ 116 | typedef void QEMUBHFunc(void *opaque); 117 | 118 | void async_context_push(void); 119 | void async_context_pop(void); 120 | int get_async_context_id(void); 121 | 122 | QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque); 123 | void qemu_bh_schedule(QEMUBH *bh); 124 | /* Bottom halfs that are scheduled from a bottom half handler are instantly 125 | * invoked. This can create an infinite loop if a bottom half handler 126 | * schedules itself. qemu_bh_schedule_idle() avoids this infinite loop by 127 | * ensuring that the bottom half isn't executed until the next main loop 128 | * iteration. 129 | */ 130 | void qemu_bh_schedule_idle(QEMUBH *bh); 131 | void qemu_bh_cancel(QEMUBH *bh); 132 | void qemu_bh_delete(QEMUBH *bh); 133 | int qemu_bh_poll(void); 134 | void qemu_bh_update_timeout(int *timeout); 135 | 136 | void qemu_get_timedate(struct tm *tm, int offset); 137 | int qemu_timedate_diff(struct tm *tm); 138 | 139 | /* cutils.c */ 140 | void pstrcpy(char *buf, int buf_size, const char *str); 141 | char *pstrcat(char *buf, int buf_size, const char *s); 142 | int strstart(const char *str, const char *val, const char **ptr); 143 | int stristart(const char *str, const char *val, const char **ptr); 144 | int qemu_strnlen(const char *s, int max_len); 145 | time_t mktimegm(struct tm *tm); 146 | int qemu_fls(int i); 147 | int qemu_fdatasync(int fd); 148 | int fcntl_setfl(int fd, int flag); 149 | 150 | /* 151 | * strtosz() suffixes used to specify the default treatment of an 152 | * argument passed to strtosz() without an explicit suffix. 153 | * These should be defined using upper case characters in the range 154 | * A-Z, as strtosz() will use qemu_toupper() on the given argument 155 | * prior to comparison. 156 | */ 157 | #define STRTOSZ_DEFSUFFIX_TB 'T' 158 | #define STRTOSZ_DEFSUFFIX_GB 'G' 159 | #define STRTOSZ_DEFSUFFIX_MB 'M' 160 | #define STRTOSZ_DEFSUFFIX_KB 'K' 161 | #define STRTOSZ_DEFSUFFIX_B 'B' 162 | int64_t strtosz(const char *nptr, char **end); 163 | int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix); 164 | 165 | /* path.c */ 166 | void init_paths(const char *prefix); 167 | const char *path(const char *pathname); 168 | 169 | #define qemu_isalnum(c) isalnum((unsigned char)(c)) 170 | #define qemu_isalpha(c) isalpha((unsigned char)(c)) 171 | #define qemu_iscntrl(c) iscntrl((unsigned char)(c)) 172 | #define qemu_isdigit(c) isdigit((unsigned char)(c)) 173 | #define qemu_isgraph(c) isgraph((unsigned char)(c)) 174 | #define qemu_islower(c) islower((unsigned char)(c)) 175 | #define qemu_isprint(c) isprint((unsigned char)(c)) 176 | #define qemu_ispunct(c) ispunct((unsigned char)(c)) 177 | #define qemu_isspace(c) isspace((unsigned char)(c)) 178 | #define qemu_isupper(c) isupper((unsigned char)(c)) 179 | #define qemu_isxdigit(c) isxdigit((unsigned char)(c)) 180 | #define qemu_tolower(c) tolower((unsigned char)(c)) 181 | #define qemu_toupper(c) toupper((unsigned char)(c)) 182 | #define qemu_isascii(c) isascii((unsigned char)(c)) 183 | #define qemu_toascii(c) toascii((unsigned char)(c)) 184 | 185 | void *qemu_oom_check(void *ptr); 186 | void *qemu_malloc(size_t size); 187 | void *qemu_realloc(void *ptr, size_t size); 188 | void *qemu_mallocz(size_t size); 189 | void qemu_free(void *ptr); 190 | char *qemu_strdup(const char *str); 191 | char *qemu_strndup(const char *str, size_t size); 192 | 193 | void qemu_mutex_lock_iothread(void); 194 | void qemu_mutex_unlock_iothread(void); 195 | 196 | int qemu_open(const char *name, int flags, ...); 197 | ssize_t qemu_write_full(int fd, const void *buf, size_t count) 198 | QEMU_WARN_UNUSED_RESULT; 199 | void qemu_set_cloexec(int fd); 200 | 201 | #ifndef _WIN32 202 | int qemu_add_child_watch(pid_t pid); 203 | int qemu_eventfd(int pipefd[2]); 204 | int qemu_pipe(int pipefd[2]); 205 | #endif 206 | 207 | #ifdef _WIN32 208 | #define qemu_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags) 209 | #else 210 | #define qemu_recv(sockfd, buf, len, flags) recv(sockfd, buf, len, flags) 211 | #endif 212 | 213 | /* Error handling. */ 214 | 215 | void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2); 216 | 217 | /* IO callbacks. */ 218 | typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); 219 | typedef int IOCanReadHandler(void *opaque); 220 | typedef void IOHandler(void *opaque); 221 | 222 | void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds); 223 | void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc); 224 | 225 | struct ParallelIOArg { 226 | void *buffer; 227 | int count; 228 | }; 229 | 230 | typedef int (*DMA_transfer_handler) (void *opaque, int nchan, int pos, int size); 231 | 232 | /* A load of opaque types so that device init declarations don't have to 233 | pull in all the real definitions. */ 234 | typedef struct NICInfo NICInfo; 235 | typedef struct HCIInfo HCIInfo; 236 | typedef struct AudioState AudioState; 237 | typedef struct BlockDriverState BlockDriverState; 238 | typedef struct DriveInfo DriveInfo; 239 | typedef struct DisplayState DisplayState; 240 | typedef struct DisplayChangeListener DisplayChangeListener; 241 | typedef struct DisplaySurface DisplaySurface; 242 | typedef struct DisplayAllocator DisplayAllocator; 243 | typedef struct PixelFormat PixelFormat; 244 | typedef struct TextConsole TextConsole; 245 | typedef TextConsole QEMUConsole; 246 | typedef struct CharDriverState CharDriverState; 247 | typedef struct MACAddr MACAddr; 248 | typedef struct VLANState VLANState; 249 | typedef struct VLANClientState VLANClientState; 250 | typedef struct i2c_bus i2c_bus; 251 | typedef struct i2c_slave i2c_slave; 252 | typedef struct SMBusDevice SMBusDevice; 253 | typedef struct PCIHostState PCIHostState; 254 | typedef struct PCIExpressHost PCIExpressHost; 255 | typedef struct PCIBus PCIBus; 256 | typedef struct PCIDevice PCIDevice; 257 | typedef struct PCIExpressDevice PCIExpressDevice; 258 | typedef struct PCIBridge PCIBridge; 259 | typedef struct PCIEAERMsg PCIEAERMsg; 260 | typedef struct PCIEAERLog PCIEAERLog; 261 | typedef struct PCIEAERErr PCIEAERErr; 262 | typedef struct PCIEPort PCIEPort; 263 | typedef struct PCIESlot PCIESlot; 264 | typedef struct SerialState SerialState; 265 | typedef struct IRQState *qemu_irq; 266 | typedef struct PCMCIACardState PCMCIACardState; 267 | typedef struct MouseTransformInfo MouseTransformInfo; 268 | typedef struct uWireSlave uWireSlave; 269 | typedef struct I2SCodec I2SCodec; 270 | typedef struct SSIBus SSIBus; 271 | typedef struct EventNotifier EventNotifier; 272 | typedef struct VirtIODevice VirtIODevice; 273 | 274 | typedef uint64_t pcibus_t; 275 | 276 | void cpu_exec_init_all(unsigned long tb_size); 277 | 278 | /* CPU save/load. */ 279 | void cpu_save(QEMUFile *f, void *opaque); 280 | int cpu_load(QEMUFile *f, void *opaque, int version_id); 281 | 282 | /* Force QEMU to stop what it's doing and service IO */ 283 | void qemu_service_io(void); 284 | 285 | /* Force QEMU to process pending events */ 286 | void qemu_notify_event(void); 287 | 288 | /* Unblock cpu */ 289 | void qemu_cpu_kick(void *env); 290 | void qemu_cpu_kick_self(void); 291 | int qemu_cpu_is_self(void *env); 292 | bool all_cpu_threads_idle(void); 293 | 294 | /* work queue */ 295 | struct qemu_work_item { 296 | struct qemu_work_item *next; 297 | void (*func)(void *data); 298 | void *data; 299 | int done; 300 | }; 301 | 302 | #ifdef CONFIG_USER_ONLY 303 | static inline void qemu_init_vcpu(void *env) 304 | { 305 | } 306 | #else 307 | void qemu_init_vcpu(void *env); 308 | #endif 309 | 310 | typedef struct QEMUIOVector { 311 | struct iovec *iov; 312 | int niov; 313 | int nalloc; 314 | size_t size; 315 | } QEMUIOVector; 316 | 317 | void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint); 318 | void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov); 319 | void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len); 320 | void qemu_iovec_copy(QEMUIOVector *dst, QEMUIOVector *src, uint64_t skip, 321 | size_t size); 322 | void qemu_iovec_concat(QEMUIOVector *dst, QEMUIOVector *src, size_t size); 323 | void qemu_iovec_destroy(QEMUIOVector *qiov); 324 | void qemu_iovec_reset(QEMUIOVector *qiov); 325 | void qemu_iovec_to_buffer(QEMUIOVector *qiov, void *buf); 326 | void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count); 327 | void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count); 328 | void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count, 329 | size_t skip); 330 | 331 | void qemu_progress_init(int enabled, float min_skip); 332 | void qemu_progress_end(void); 333 | void qemu_progress_print(float delta, int max); 334 | 335 | #define QEMU_FILE_TYPE_BIOS 0 336 | #define QEMU_FILE_TYPE_KEYMAP 1 337 | char *qemu_find_file(int type, const char *name); 338 | 339 | /* OS specific functions */ 340 | void os_setup_early_signal_handling(void); 341 | char *os_find_datadir(const char *argv0); 342 | void os_parse_cmd_args(int index, const char *optarg); 343 | void os_pidfile_error(void); 344 | 345 | /* Convert a byte between binary and BCD. */ 346 | static inline uint8_t to_bcd(uint8_t val) 347 | { 348 | return ((val / 10) << 4) | (val % 10); 349 | } 350 | 351 | static inline uint8_t from_bcd(uint8_t val) 352 | { 353 | return ((val >> 4) * 10) + (val & 0x0f); 354 | } 355 | 356 | /* compute with 96 bit intermediate result: (a*b)/c */ 357 | static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) 358 | { 359 | union { 360 | uint64_t ll; 361 | struct { 362 | #ifdef HOST_WORDS_BIGENDIAN 363 | uint32_t high, low; 364 | #else 365 | uint32_t low, high; 366 | #endif 367 | } l; 368 | } u, res; 369 | uint64_t rl, rh; 370 | 371 | u.ll = a; 372 | rl = (uint64_t)u.l.low * (uint64_t)b; 373 | rh = (uint64_t)u.l.high * (uint64_t)b; 374 | rh += (rl >> 32); 375 | res.l.high = rh / c; 376 | res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; 377 | return res.ll; 378 | } 379 | 380 | //#include "module.h" 381 | 382 | bool pc_is_native_return(uint64_t pc); 383 | bool pc_is_native_call(uint64_t pc); 384 | 385 | #endif 386 | -------------------------------------------------------------------------------- /qemu/qemu-lock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Fabrice Bellard 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, see 16 | */ 17 | 18 | /* configure guarantees us that we have pthreads on any host except 19 | * mingw32, which doesn't support any of the user-only targets. 20 | * So we can simply assume we have pthread mutexes here. 21 | */ 22 | #if 0 // defined(CONFIG_USER_ONLY) 23 | 24 | #include 25 | #define spin_lock pthread_mutex_lock 26 | #define spin_unlock pthread_mutex_unlock 27 | #define spinlock_t pthread_mutex_t 28 | #define SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER 29 | 30 | #else 31 | 32 | /* Empty implementations, on the theory that system mode emulation 33 | * is single-threaded. This means that these functions should only 34 | * be used from code run in the TCG cpu thread, and cannot protect 35 | * data structures which might also be accessed from the IO thread 36 | * or from signal handlers. 37 | */ 38 | typedef int spinlock_t; 39 | #define SPIN_LOCK_UNLOCKED 0 40 | 41 | static inline void spin_lock(spinlock_t *lock) 42 | { 43 | } 44 | 45 | static inline void spin_unlock(spinlock_t *lock) 46 | { 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /qemu/qemu-log.h: -------------------------------------------------------------------------------- 1 | #ifndef QEMU_LOG_H 2 | #define QEMU_LOG_H 3 | 4 | /* The deprecated global variables: */ 5 | extern FILE *logfile; 6 | extern int loglevel; 7 | 8 | 9 | /* 10 | * The new API: 11 | * 12 | */ 13 | 14 | /* Log settings checking macros: */ 15 | 16 | /* Returns true if qemu_log() will really write somewhere 17 | */ 18 | #define qemu_log_enabled() (logfile != NULL) 19 | 20 | /* Returns true if a bit is set in the current loglevel mask 21 | */ 22 | #define qemu_loglevel_mask(b) ((loglevel & (b)) != 0) 23 | 24 | 25 | /* Logging functions: */ 26 | 27 | /* main logging function 28 | */ 29 | #define qemu_log(...) do { \ 30 | if (logfile) \ 31 | fprintf(logfile, ## __VA_ARGS__); \ 32 | } while (0) 33 | 34 | /* vfprintf-like logging function 35 | */ 36 | #define qemu_log_vprintf(fmt, va) do { \ 37 | if (logfile) \ 38 | vfprintf(logfile, fmt, va); \ 39 | } while (0) 40 | 41 | /* log only if a bit is set on the current loglevel mask 42 | */ 43 | #define qemu_log_mask(b, ...) do { \ 44 | if (loglevel & (b)) \ 45 | fprintf(logfile, ## __VA_ARGS__); \ 46 | } while (0) 47 | 48 | 49 | 50 | 51 | /* Special cases: */ 52 | 53 | /* cpu_dump_state() logging functions: */ 54 | #define log_cpu_state(env, f) cpu_dump_state((env), logfile, fprintf, (f)); 55 | #define log_cpu_state_mask(b, env, f) do { \ 56 | if (loglevel & (b)) log_cpu_state((env), (f)); \ 57 | } while (0) 58 | 59 | /* disas() and target_disas() to logfile: */ 60 | #define log_target_disas(start, len, flags) \ 61 | target_disas(logfile, (start), (len), (flags)) 62 | #define log_disas(start, len) \ 63 | disas(logfile, (start), (len)) 64 | 65 | /* page_dump() output to the log file: */ 66 | #define log_page_dump() page_dump(logfile) 67 | 68 | 69 | 70 | /* Maintenance: */ 71 | 72 | /* fflush() the log file */ 73 | #define qemu_log_flush() fflush(logfile) 74 | 75 | /* Close the log file */ 76 | #define qemu_log_close() do { \ 77 | fclose(logfile); \ 78 | logfile = NULL; \ 79 | } while (0) 80 | 81 | /* Set up a new log file */ 82 | #define qemu_log_set_file(f) do { \ 83 | logfile = (f); \ 84 | } while (0) 85 | 86 | /* Set up a new log file, only if none is set */ 87 | #define qemu_log_try_set_file(f) do { \ 88 | if (!logfile) \ 89 | logfile = (f); \ 90 | } while (0) 91 | 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /qemu/qemu-os-posix.h: -------------------------------------------------------------------------------- 1 | /* 2 | * posix specific declarations 3 | * 4 | * Copyright (c) 2003-2008 Fabrice Bellard 5 | * Copyright (c) 2010 Jes Sorensen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef QEMU_OS_POSIX_H 27 | #define QEMU_OS_POSIX_H 28 | 29 | static inline void os_host_main_loop_wait(int *timeout) 30 | { 31 | } 32 | 33 | void os_set_line_buffering(void); 34 | void os_set_proc_name(const char *s); 35 | void os_setup_signal_handling(void); 36 | void os_daemonize(void); 37 | void os_setup_post(void); 38 | 39 | typedef struct timeval qemu_timeval; 40 | #define qemu_gettimeofday(tp) gettimeofday(tp, NULL) 41 | 42 | #ifndef CONFIG_UTIMENSAT 43 | #ifndef UTIME_NOW 44 | # define UTIME_NOW ((1l << 30) - 1l) 45 | #endif 46 | #ifndef UTIME_OMIT 47 | # define UTIME_OMIT ((1l << 30) - 2l) 48 | #endif 49 | #endif 50 | typedef struct timespec qemu_timespec; 51 | int qemu_utimensat(int dirfd, const char *path, const qemu_timespec *times, 52 | int flags); 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /qemu/qemu-types.h: -------------------------------------------------------------------------------- 1 | #ifndef QEMU_TYPES_H 2 | #define QEMU_TYPES_H 3 | #include "cpu.h" 4 | 5 | #ifdef TARGET_ABI32 6 | typedef uint32_t abi_ulong; 7 | typedef int32_t abi_long; 8 | #define TARGET_ABI_FMT_lx "%08x" 9 | #define TARGET_ABI_FMT_ld "%d" 10 | #define TARGET_ABI_FMT_lu "%u" 11 | #define TARGET_ABI_BITS 32 12 | #else 13 | typedef target_ulong abi_ulong; 14 | typedef target_long abi_long; 15 | #define TARGET_ABI_FMT_lx TARGET_FMT_lx 16 | #define TARGET_ABI_FMT_ld TARGET_FMT_ld 17 | #define TARGET_ABI_FMT_lu TARGET_FMT_lu 18 | #define TARGET_ABI_BITS TARGET_LONG_BITS 19 | /* for consistency, define ABI32 too */ 20 | #if TARGET_ABI_BITS == 32 21 | #define TARGET_ABI32 1 22 | #endif 23 | #endif 24 | #endif 25 | -------------------------------------------------------------------------------- /qemu/sysemu.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSEMU_H 2 | #define SYSEMU_H 3 | /* Misc. things related to the system emulator. */ 4 | 5 | #include "qemu-common.h" 6 | //#include "qemu-option.h" 7 | #include "qemu-queue.h" 8 | //#include "qemu-timer.h" 9 | //#include "notify.h" 10 | 11 | /* vl.c */ 12 | extern const char *bios_name; 13 | 14 | extern int vm_running; 15 | extern const char *qemu_name; 16 | extern uint8_t qemu_uuid[]; 17 | int qemu_uuid_parse(const char *str, uint8_t *uuid); 18 | #define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" 19 | 20 | typedef struct vm_change_state_entry VMChangeStateEntry; 21 | typedef void VMChangeStateHandler(void *opaque, int running, int reason); 22 | 23 | VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb, 24 | void *opaque); 25 | void qemu_del_vm_change_state_handler(VMChangeStateEntry *e); 26 | 27 | #define VMSTOP_USER 0 28 | #define VMSTOP_DEBUG 1 29 | #define VMSTOP_SHUTDOWN 2 30 | #define VMSTOP_DISKFULL 3 31 | #define VMSTOP_WATCHDOG 4 32 | #define VMSTOP_PANIC 5 33 | #define VMSTOP_SAVEVM 6 34 | #define VMSTOP_LOADVM 7 35 | #define VMSTOP_MIGRATE 8 36 | 37 | #define VMRESET_SILENT false 38 | #define VMRESET_REPORT true 39 | 40 | void vm_start(void); 41 | void vm_stop(int reason); 42 | 43 | void qemu_system_reset_request(void); 44 | void qemu_system_shutdown_request(void); 45 | void qemu_system_powerdown_request(void); 46 | void qemu_system_debug_request(void); 47 | void qemu_system_vmstop_request(int reason); 48 | int qemu_shutdown_requested_get(void); 49 | int qemu_reset_requested_get(void); 50 | int qemu_shutdown_requested(void); 51 | int qemu_reset_requested(void); 52 | int qemu_powerdown_requested(void); 53 | void qemu_system_killed(int signal, pid_t pid); 54 | void qemu_kill_report(void); 55 | extern qemu_irq qemu_system_powerdown; 56 | void qemu_system_reset(bool report); 57 | 58 | //void qemu_add_exit_notifier(Notifier *notify); 59 | //void qemu_remove_exit_notifier(Notifier *notify); 60 | 61 | //void qemu_add_machine_init_done_notifier(Notifier *notify); 62 | 63 | //void do_savevm(Monitor *mon, const QDict *qdict); 64 | int load_vmstate(const char *name); 65 | //void do_delvm(Monitor *mon, const QDict *qdict); 66 | void do_info_snapshots(Monitor *mon); 67 | 68 | void qemu_announce_self(void); 69 | 70 | void main_loop_wait(int nonblocking); 71 | 72 | bool qemu_savevm_state_blocked(Monitor *mon); 73 | int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable, 74 | int shared); 75 | int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f); 76 | int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f); 77 | void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f); 78 | int qemu_loadvm_state(QEMUFile *f); 79 | 80 | /* SLIRP */ 81 | void do_info_slirp(Monitor *mon); 82 | 83 | typedef enum DisplayType 84 | { 85 | DT_DEFAULT, 86 | DT_CURSES, 87 | DT_SDL, 88 | DT_NOGRAPHIC, 89 | DT_NONE, 90 | } DisplayType; 91 | 92 | extern int autostart; 93 | extern int bios_size; 94 | 95 | typedef enum { 96 | VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL, 97 | } VGAInterfaceType; 98 | 99 | extern int vga_interface_type; 100 | #define cirrus_vga_enabled (vga_interface_type == VGA_CIRRUS) 101 | #define std_vga_enabled (vga_interface_type == VGA_STD) 102 | #define xenfb_enabled (vga_interface_type == VGA_XENFB) 103 | #define vmsvga_enabled (vga_interface_type == VGA_VMWARE) 104 | #define qxl_enabled (vga_interface_type == VGA_QXL) 105 | 106 | extern int graphic_width; 107 | extern int graphic_height; 108 | extern int graphic_depth; 109 | extern uint8_t irq0override; 110 | extern DisplayType display_type; 111 | extern const char *keyboard_layout; 112 | extern int win2k_install_hack; 113 | extern int rtc_td_hack; 114 | extern int alt_grab; 115 | extern int ctrl_grab; 116 | extern int usb_enabled; 117 | extern int smp_cpus; 118 | extern int max_cpus; 119 | extern int cursor_hide; 120 | extern int graphic_rotate; 121 | extern int no_quit; 122 | extern int no_shutdown; 123 | extern int semihosting_enabled; 124 | extern int old_param; 125 | extern int boot_menu; 126 | extern uint8_t *boot_splash_filedata; 127 | extern int boot_splash_filedata_size; 128 | extern uint8_t qemu_extra_params_fw[2]; 129 | //extern QEMUClock *rtc_clock; 130 | 131 | #define MAX_NODES 64 132 | extern int nb_numa_nodes; 133 | extern uint64_t node_mem[MAX_NODES]; 134 | extern uint64_t node_cpumask[MAX_NODES]; 135 | 136 | #define MAX_OPTION_ROMS 16 137 | typedef struct QEMUOptionRom { 138 | const char *name; 139 | int32_t bootindex; 140 | } QEMUOptionRom; 141 | extern QEMUOptionRom option_rom[MAX_OPTION_ROMS]; 142 | extern int nb_option_roms; 143 | 144 | #define MAX_PROM_ENVS 128 145 | extern const char *prom_envs[MAX_PROM_ENVS]; 146 | extern unsigned int nb_prom_envs; 147 | 148 | /* pci-hotplug */ 149 | //void pci_device_hot_add(Monitor *mon, const QDict *qdict); 150 | //void drive_hot_add(Monitor *mon, const QDict *qdict); 151 | //void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict); 152 | 153 | /* pcie aer error injection */ 154 | //void pcie_aer_inject_error_print(Monitor *mon, const QObject *data); 155 | //int do_pcie_aer_inejct_error(Monitor *mon, 156 | // const QDict *qdict, QObject **ret_data); 157 | 158 | /* serial ports */ 159 | 160 | #define MAX_SERIAL_PORTS 4 161 | 162 | extern CharDriverState *serial_hds[MAX_SERIAL_PORTS]; 163 | 164 | /* parallel ports */ 165 | 166 | #define MAX_PARALLEL_PORTS 3 167 | 168 | extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; 169 | 170 | //void do_usb_add(Monitor *mon, const QDict *qdict); 171 | //void do_usb_del(Monitor *mon, const QDict *qdict); 172 | void usb_info(Monitor *mon); 173 | 174 | void rtc_change_mon_event(struct tm *tm); 175 | 176 | void register_devices(void); 177 | 178 | void add_boot_device_path(int32_t bootindex, DeviceState *dev, 179 | const char *suffix); 180 | char *get_boot_devices_list(uint32_t *size); 181 | #endif 182 | -------------------------------------------------------------------------------- /qemu/target-i386/TODO: -------------------------------------------------------------------------------- 1 | Correctness issues: 2 | 3 | - some eflags manipulation incorrectly reset the bit 0x2. 4 | - SVM: test, cpu save/restore, SMM save/restore. 5 | - x86_64: lcall/ljmp intel/amd differences ? 6 | - better code fetch (different exception handling + CS.limit support) 7 | - user/kernel PUSHL/POPL in helper.c 8 | - add missing cpuid tests 9 | - return UD exception if LOCK prefix incorrectly used 10 | - test ldt limit < 7 ? 11 | - fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret) 12 | - full support of segment limit/rights 13 | - full x87 exception support 14 | - improve x87 bit exactness (use bochs code ?) 15 | - DRx register support 16 | - CR0.AC emulation 17 | - SSE alignment checks 18 | - fix SSE min/max with nans 19 | 20 | Optimizations/Features: 21 | 22 | - add SVM nested paging support 23 | - add VMX support 24 | - add AVX support 25 | - add SSE5 support 26 | - fxsave/fxrstor AMD extensions 27 | - improve monitor/mwait support 28 | - faster EFLAGS update: consider SZAP, C, O can be updated separately 29 | with a bit field in CC_OP and more state variables. 30 | - evaluate x87 stack pointer statically 31 | - find a way to avoid translating several time the same TB if CR0.TS 32 | is set or not. 33 | -------------------------------------------------------------------------------- /qemu/target-i386/helper.h: -------------------------------------------------------------------------------- 1 | #include "def-helper.h" 2 | 3 | DEF_HELPER_FLAGS_1(cc_compute_all, TCG_CALL_PURE, i32, int) 4 | DEF_HELPER_FLAGS_1(cc_compute_c, TCG_CALL_PURE, i32, int) 5 | 6 | DEF_HELPER_0(lock, void) 7 | DEF_HELPER_0(unlock, void) 8 | DEF_HELPER_2(write_eflags, void, tl, i32) 9 | DEF_HELPER_0(read_eflags, tl) 10 | DEF_HELPER_1(divb_AL, void, tl) 11 | DEF_HELPER_1(idivb_AL, void, tl) 12 | DEF_HELPER_1(divw_AX, void, tl) 13 | DEF_HELPER_1(idivw_AX, void, tl) 14 | DEF_HELPER_1(divl_EAX, void, tl) 15 | DEF_HELPER_1(idivl_EAX, void, tl) 16 | #ifdef TARGET_X86_64 17 | DEF_HELPER_1(mulq_EAX_T0, void, tl) 18 | DEF_HELPER_1(imulq_EAX_T0, void, tl) 19 | DEF_HELPER_2(imulq_T0_T1, tl, tl, tl) 20 | DEF_HELPER_1(divq_EAX, void, tl) 21 | DEF_HELPER_1(idivq_EAX, void, tl) 22 | #endif 23 | 24 | DEF_HELPER_1(aam, void, int) 25 | DEF_HELPER_1(aad, void, int) 26 | DEF_HELPER_0(aaa, void) 27 | DEF_HELPER_0(aas, void) 28 | DEF_HELPER_0(daa, void) 29 | DEF_HELPER_0(das, void) 30 | 31 | DEF_HELPER_1(lsl, tl, tl) 32 | DEF_HELPER_1(lar, tl, tl) 33 | DEF_HELPER_1(verr, void, tl) 34 | DEF_HELPER_1(verw, void, tl) 35 | DEF_HELPER_1(lldt, void, int) 36 | DEF_HELPER_1(ltr, void, int) 37 | DEF_HELPER_2(load_seg, void, int, int) 38 | DEF_HELPER_3(ljmp_protected, void, int, tl, int) 39 | DEF_HELPER_4(lcall_real, void, int, tl, int, int) 40 | DEF_HELPER_4(lcall_protected, void, int, tl, int, int) 41 | DEF_HELPER_1(iret_real, void, int) 42 | DEF_HELPER_2(iret_protected, void, int, int) 43 | DEF_HELPER_2(lret_protected, void, int, int) 44 | DEF_HELPER_1(read_crN, tl, int) 45 | DEF_HELPER_2(write_crN, void, int, tl) 46 | DEF_HELPER_1(lmsw, void, tl) 47 | DEF_HELPER_0(clts, void) 48 | DEF_HELPER_2(movl_drN_T0, void, int, tl) 49 | DEF_HELPER_1(invlpg, void, tl) 50 | 51 | DEF_HELPER_3(enter_level, void, int, int, tl) 52 | #ifdef TARGET_X86_64 53 | DEF_HELPER_3(enter64_level, void, int, int, tl) 54 | #endif 55 | DEF_HELPER_0(sysenter, void) 56 | DEF_HELPER_1(sysexit, void, int) 57 | #ifdef TARGET_X86_64 58 | DEF_HELPER_1(syscall, void, int) 59 | DEF_HELPER_1(sysret, void, int) 60 | #endif 61 | DEF_HELPER_1(hlt, void, int) 62 | DEF_HELPER_1(monitor, void, tl) 63 | DEF_HELPER_1(mwait, void, int) 64 | DEF_HELPER_0(debug, void) 65 | DEF_HELPER_0(reset_rf, void) 66 | DEF_HELPER_2(raise_interrupt, void, int, int) 67 | DEF_HELPER_1(raise_exception, void, int) 68 | DEF_HELPER_0(cli, void) 69 | DEF_HELPER_0(sti, void) 70 | DEF_HELPER_0(set_inhibit_irq, void) 71 | DEF_HELPER_0(reset_inhibit_irq, void) 72 | DEF_HELPER_2(boundw, void, tl, int) 73 | DEF_HELPER_2(boundl, void, tl, int) 74 | DEF_HELPER_0(rsm, void) 75 | DEF_HELPER_1(into, void, int) 76 | DEF_HELPER_1(cmpxchg8b, void, tl) 77 | #ifdef TARGET_X86_64 78 | DEF_HELPER_1(cmpxchg16b, void, tl) 79 | #endif 80 | DEF_HELPER_0(single_step, void) 81 | DEF_HELPER_0(cpuid, void) 82 | DEF_HELPER_0(rdtsc, void) 83 | DEF_HELPER_0(rdtscp, void) 84 | DEF_HELPER_0(rdpmc, void) 85 | DEF_HELPER_0(rdmsr, void) 86 | DEF_HELPER_0(wrmsr, void) 87 | 88 | DEF_HELPER_1(check_iob, void, i32) 89 | DEF_HELPER_1(check_iow, void, i32) 90 | DEF_HELPER_1(check_iol, void, i32) 91 | DEF_HELPER_2(outb, void, i32, i32) 92 | DEF_HELPER_1(inb, tl, i32) 93 | DEF_HELPER_2(outw, void, i32, i32) 94 | DEF_HELPER_1(inw, tl, i32) 95 | DEF_HELPER_2(outl, void, i32, i32) 96 | DEF_HELPER_1(inl, tl, i32) 97 | 98 | DEF_HELPER_2(svm_check_intercept_param, void, i32, i64) 99 | DEF_HELPER_2(vmexit, void, i32, i64) 100 | DEF_HELPER_3(svm_check_io, void, i32, i32, i32) 101 | DEF_HELPER_2(vmrun, void, int, int) 102 | DEF_HELPER_0(vmmcall, void) 103 | DEF_HELPER_1(vmload, void, int) 104 | DEF_HELPER_1(vmsave, void, int) 105 | DEF_HELPER_0(stgi, void) 106 | DEF_HELPER_0(clgi, void) 107 | DEF_HELPER_0(skinit, void) 108 | DEF_HELPER_1(invlpga, void, int) 109 | 110 | /* x86 FPU */ 111 | 112 | DEF_HELPER_1(flds_FT0, void, i32) 113 | DEF_HELPER_1(fldl_FT0, void, i64) 114 | DEF_HELPER_1(fildl_FT0, void, s32) 115 | DEF_HELPER_1(flds_ST0, void, i32) 116 | DEF_HELPER_1(fldl_ST0, void, i64) 117 | DEF_HELPER_1(fildl_ST0, void, s32) 118 | DEF_HELPER_1(fildll_ST0, void, s64) 119 | DEF_HELPER_0(fsts_ST0, i32) 120 | DEF_HELPER_0(fstl_ST0, i64) 121 | DEF_HELPER_0(fist_ST0, s32) 122 | DEF_HELPER_0(fistl_ST0, s32) 123 | DEF_HELPER_0(fistll_ST0, s64) 124 | DEF_HELPER_0(fistt_ST0, s32) 125 | DEF_HELPER_0(fisttl_ST0, s32) 126 | DEF_HELPER_0(fisttll_ST0, s64) 127 | DEF_HELPER_1(fldt_ST0, void, tl) 128 | DEF_HELPER_1(fstt_ST0, void, tl) 129 | DEF_HELPER_0(fpush, void) 130 | DEF_HELPER_0(fpop, void) 131 | DEF_HELPER_0(fdecstp, void) 132 | DEF_HELPER_0(fincstp, void) 133 | DEF_HELPER_1(ffree_STN, void, int) 134 | DEF_HELPER_0(fmov_ST0_FT0, void) 135 | DEF_HELPER_1(fmov_FT0_STN, void, int) 136 | DEF_HELPER_1(fmov_ST0_STN, void, int) 137 | DEF_HELPER_1(fmov_STN_ST0, void, int) 138 | DEF_HELPER_1(fxchg_ST0_STN, void, int) 139 | DEF_HELPER_0(fcom_ST0_FT0, void) 140 | DEF_HELPER_0(fucom_ST0_FT0, void) 141 | DEF_HELPER_0(fcomi_ST0_FT0, void) 142 | DEF_HELPER_0(fucomi_ST0_FT0, void) 143 | DEF_HELPER_0(fadd_ST0_FT0, void) 144 | DEF_HELPER_0(fmul_ST0_FT0, void) 145 | DEF_HELPER_0(fsub_ST0_FT0, void) 146 | DEF_HELPER_0(fsubr_ST0_FT0, void) 147 | DEF_HELPER_0(fdiv_ST0_FT0, void) 148 | DEF_HELPER_0(fdivr_ST0_FT0, void) 149 | DEF_HELPER_1(fadd_STN_ST0, void, int) 150 | DEF_HELPER_1(fmul_STN_ST0, void, int) 151 | DEF_HELPER_1(fsub_STN_ST0, void, int) 152 | DEF_HELPER_1(fsubr_STN_ST0, void, int) 153 | DEF_HELPER_1(fdiv_STN_ST0, void, int) 154 | DEF_HELPER_1(fdivr_STN_ST0, void, int) 155 | DEF_HELPER_0(fchs_ST0, void) 156 | DEF_HELPER_0(fabs_ST0, void) 157 | DEF_HELPER_0(fxam_ST0, void) 158 | DEF_HELPER_0(fld1_ST0, void) 159 | DEF_HELPER_0(fldl2t_ST0, void) 160 | DEF_HELPER_0(fldl2e_ST0, void) 161 | DEF_HELPER_0(fldpi_ST0, void) 162 | DEF_HELPER_0(fldlg2_ST0, void) 163 | DEF_HELPER_0(fldln2_ST0, void) 164 | DEF_HELPER_0(fldz_ST0, void) 165 | DEF_HELPER_0(fldz_FT0, void) 166 | DEF_HELPER_0(fnstsw, i32) 167 | DEF_HELPER_0(fnstcw, i32) 168 | DEF_HELPER_1(fldcw, void, i32) 169 | DEF_HELPER_0(fclex, void) 170 | DEF_HELPER_0(fwait, void) 171 | DEF_HELPER_0(fninit, void) 172 | DEF_HELPER_1(fbld_ST0, void, tl) 173 | DEF_HELPER_1(fbst_ST0, void, tl) 174 | DEF_HELPER_0(f2xm1, void) 175 | DEF_HELPER_0(fyl2x, void) 176 | DEF_HELPER_0(fptan, void) 177 | DEF_HELPER_0(fpatan, void) 178 | DEF_HELPER_0(fxtract, void) 179 | DEF_HELPER_0(fprem1, void) 180 | DEF_HELPER_0(fprem, void) 181 | DEF_HELPER_0(fyl2xp1, void) 182 | DEF_HELPER_0(fsqrt, void) 183 | DEF_HELPER_0(fsincos, void) 184 | DEF_HELPER_0(frndint, void) 185 | DEF_HELPER_0(fscale, void) 186 | DEF_HELPER_0(fsin, void) 187 | DEF_HELPER_0(fcos, void) 188 | DEF_HELPER_2(fstenv, void, tl, int) 189 | DEF_HELPER_2(fldenv, void, tl, int) 190 | DEF_HELPER_2(fsave, void, tl, int) 191 | DEF_HELPER_2(frstor, void, tl, int) 192 | DEF_HELPER_2(fxsave, void, tl, int) 193 | DEF_HELPER_2(fxrstor, void, tl, int) 194 | DEF_HELPER_1(bsf, tl, tl) 195 | DEF_HELPER_1(bsr, tl, tl) 196 | DEF_HELPER_2(lzcnt, tl, tl, int) 197 | 198 | /* MMX/SSE */ 199 | 200 | DEF_HELPER_0(enter_mmx, void) 201 | DEF_HELPER_0(emms, void) 202 | DEF_HELPER_2(movq, void, ptr, ptr) 203 | 204 | #define SHIFT 0 205 | #include "ops_sse_header.h" 206 | #define SHIFT 1 207 | #include "ops_sse_header.h" 208 | 209 | DEF_HELPER_2(rclb, tl, tl, tl) 210 | DEF_HELPER_2(rclw, tl, tl, tl) 211 | DEF_HELPER_2(rcll, tl, tl, tl) 212 | DEF_HELPER_2(rcrb, tl, tl, tl) 213 | DEF_HELPER_2(rcrw, tl, tl, tl) 214 | DEF_HELPER_2(rcrl, tl, tl, tl) 215 | #ifdef TARGET_X86_64 216 | DEF_HELPER_2(rclq, tl, tl, tl) 217 | DEF_HELPER_2(rcrq, tl, tl, tl) 218 | #endif 219 | 220 | #include "def-helper.h" 221 | -------------------------------------------------------------------------------- /qemu/target-i386/helper_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * i386 helpers 3 | * 4 | * Copyright (c) 2008 Fabrice Bellard 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | #define DATA_BITS (1 << (3 + SHIFT)) 20 | #define SHIFT_MASK (DATA_BITS - 1) 21 | #define SIGN_MASK (((target_ulong)1) << (DATA_BITS - 1)) 22 | #if DATA_BITS <= 32 23 | #define SHIFT1_MASK 0x1f 24 | #else 25 | #define SHIFT1_MASK 0x3f 26 | #endif 27 | 28 | #if DATA_BITS == 8 29 | #define SUFFIX b 30 | #define DATA_TYPE uint8_t 31 | #define DATA_STYPE int8_t 32 | #define DATA_MASK 0xff 33 | #elif DATA_BITS == 16 34 | #define SUFFIX w 35 | #define DATA_TYPE uint16_t 36 | #define DATA_STYPE int16_t 37 | #define DATA_MASK 0xffff 38 | #elif DATA_BITS == 32 39 | #define SUFFIX l 40 | #define DATA_TYPE uint32_t 41 | #define DATA_STYPE int32_t 42 | #define DATA_MASK 0xffffffff 43 | #elif DATA_BITS == 64 44 | #define SUFFIX q 45 | #define DATA_TYPE uint64_t 46 | #define DATA_STYPE int64_t 47 | #define DATA_MASK 0xffffffffffffffffULL 48 | #else 49 | #error unhandled operand size 50 | #endif 51 | 52 | /* dynamic flags computation */ 53 | 54 | static int glue(compute_all_add, SUFFIX)(void) 55 | { 56 | int cf, pf, af, zf, sf, of; 57 | target_long src1, src2; 58 | src1 = CC_SRC; 59 | src2 = CC_DST - CC_SRC; 60 | cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1; 61 | pf = parity_table[(uint8_t)CC_DST]; 62 | af = (CC_DST ^ src1 ^ src2) & 0x10; 63 | zf = ((DATA_TYPE)CC_DST == 0) << 6; 64 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 65 | of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; 66 | return cf | pf | af | zf | sf | of; 67 | } 68 | 69 | static int glue(compute_c_add, SUFFIX)(void) 70 | { 71 | int cf; 72 | target_long src1; 73 | src1 = CC_SRC; 74 | cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1; 75 | return cf; 76 | } 77 | 78 | static int glue(compute_all_adc, SUFFIX)(void) 79 | { 80 | int cf, pf, af, zf, sf, of; 81 | target_long src1, src2; 82 | src1 = CC_SRC; 83 | src2 = CC_DST - CC_SRC - 1; 84 | cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1; 85 | pf = parity_table[(uint8_t)CC_DST]; 86 | af = (CC_DST ^ src1 ^ src2) & 0x10; 87 | zf = ((DATA_TYPE)CC_DST == 0) << 6; 88 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 89 | of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; 90 | return cf | pf | af | zf | sf | of; 91 | } 92 | 93 | static int glue(compute_c_adc, SUFFIX)(void) 94 | { 95 | int cf; 96 | target_long src1; 97 | src1 = CC_SRC; 98 | cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1; 99 | return cf; 100 | } 101 | 102 | static int glue(compute_all_sub, SUFFIX)(void) 103 | { 104 | int cf, pf, af, zf, sf, of; 105 | target_long src1, src2; 106 | src1 = CC_DST + CC_SRC; 107 | src2 = CC_SRC; 108 | cf = (DATA_TYPE)src1 < (DATA_TYPE)src2; 109 | pf = parity_table[(uint8_t)CC_DST]; 110 | af = (CC_DST ^ src1 ^ src2) & 0x10; 111 | zf = ((DATA_TYPE)CC_DST == 0) << 6; 112 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 113 | of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; 114 | return cf | pf | af | zf | sf | of; 115 | } 116 | 117 | static int glue(compute_c_sub, SUFFIX)(void) 118 | { 119 | int cf; 120 | target_long src1, src2; 121 | src1 = CC_DST + CC_SRC; 122 | src2 = CC_SRC; 123 | cf = (DATA_TYPE)src1 < (DATA_TYPE)src2; 124 | return cf; 125 | } 126 | 127 | static int glue(compute_all_sbb, SUFFIX)(void) 128 | { 129 | int cf, pf, af, zf, sf, of; 130 | target_long src1, src2; 131 | src1 = CC_DST + CC_SRC + 1; 132 | src2 = CC_SRC; 133 | cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2; 134 | pf = parity_table[(uint8_t)CC_DST]; 135 | af = (CC_DST ^ src1 ^ src2) & 0x10; 136 | zf = ((DATA_TYPE)CC_DST == 0) << 6; 137 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 138 | of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; 139 | return cf | pf | af | zf | sf | of; 140 | } 141 | 142 | static int glue(compute_c_sbb, SUFFIX)(void) 143 | { 144 | int cf; 145 | target_long src1, src2; 146 | src1 = CC_DST + CC_SRC + 1; 147 | src2 = CC_SRC; 148 | cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2; 149 | return cf; 150 | } 151 | 152 | static int glue(compute_all_logic, SUFFIX)(void) 153 | { 154 | int cf, pf, af, zf, sf, of; 155 | cf = 0; 156 | pf = parity_table[(uint8_t)CC_DST]; 157 | af = 0; 158 | zf = ((DATA_TYPE)CC_DST == 0) << 6; 159 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 160 | of = 0; 161 | return cf | pf | af | zf | sf | of; 162 | } 163 | 164 | static int glue(compute_c_logic, SUFFIX)(void) 165 | { 166 | return 0; 167 | } 168 | 169 | static int glue(compute_all_inc, SUFFIX)(void) 170 | { 171 | int cf, pf, af, zf, sf, of; 172 | target_long src1, src2; 173 | src1 = CC_DST - 1; 174 | src2 = 1; 175 | cf = CC_SRC; 176 | pf = parity_table[(uint8_t)CC_DST]; 177 | af = (CC_DST ^ src1 ^ src2) & 0x10; 178 | zf = ((DATA_TYPE)CC_DST == 0) << 6; 179 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 180 | of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11; 181 | return cf | pf | af | zf | sf | of; 182 | } 183 | 184 | #if DATA_BITS == 32 185 | static int glue(compute_c_inc, SUFFIX)(void) 186 | { 187 | return CC_SRC; 188 | } 189 | #endif 190 | 191 | static int glue(compute_all_dec, SUFFIX)(void) 192 | { 193 | int cf, pf, af, zf, sf, of; 194 | target_long src1, src2; 195 | src1 = CC_DST + 1; 196 | src2 = 1; 197 | cf = CC_SRC; 198 | pf = parity_table[(uint8_t)CC_DST]; 199 | af = (CC_DST ^ src1 ^ src2) & 0x10; 200 | zf = ((DATA_TYPE)CC_DST == 0) << 6; 201 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 202 | of = ((CC_DST & DATA_MASK) == ((target_ulong)SIGN_MASK - 1)) << 11; 203 | return cf | pf | af | zf | sf | of; 204 | } 205 | 206 | static int glue(compute_all_shl, SUFFIX)(void) 207 | { 208 | int cf, pf, af, zf, sf, of; 209 | cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C; 210 | pf = parity_table[(uint8_t)CC_DST]; 211 | af = 0; /* undefined */ 212 | zf = ((DATA_TYPE)CC_DST == 0) << 6; 213 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 214 | /* of is defined if shift count == 1 */ 215 | of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O; 216 | return cf | pf | af | zf | sf | of; 217 | } 218 | 219 | static int glue(compute_c_shl, SUFFIX)(void) 220 | { 221 | return (CC_SRC >> (DATA_BITS - 1)) & CC_C; 222 | } 223 | 224 | #if DATA_BITS == 32 225 | static int glue(compute_c_sar, SUFFIX)(void) 226 | { 227 | return CC_SRC & 1; 228 | } 229 | #endif 230 | 231 | static int glue(compute_all_sar, SUFFIX)(void) 232 | { 233 | int cf, pf, af, zf, sf, of; 234 | cf = CC_SRC & 1; 235 | pf = parity_table[(uint8_t)CC_DST]; 236 | af = 0; /* undefined */ 237 | zf = ((DATA_TYPE)CC_DST == 0) << 6; 238 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 239 | /* of is defined if shift count == 1 */ 240 | of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O; 241 | return cf | pf | af | zf | sf | of; 242 | } 243 | 244 | #if DATA_BITS == 32 245 | static int glue(compute_c_mul, SUFFIX)(void) 246 | { 247 | int cf; 248 | cf = (CC_SRC != 0); 249 | return cf; 250 | } 251 | #endif 252 | 253 | /* NOTE: we compute the flags like the P4. On olders CPUs, only OF and 254 | CF are modified and it is slower to do that. */ 255 | static int glue(compute_all_mul, SUFFIX)(void) 256 | { 257 | int cf, pf, af, zf, sf, of; 258 | cf = (CC_SRC != 0); 259 | pf = parity_table[(uint8_t)CC_DST]; 260 | af = 0; /* undefined */ 261 | zf = ((DATA_TYPE)CC_DST == 0) << 6; 262 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 263 | of = cf << 11; 264 | return cf | pf | af | zf | sf | of; 265 | } 266 | 267 | /* shifts */ 268 | 269 | target_ulong glue(helper_rcl, SUFFIX)(target_ulong t0, target_ulong t1) 270 | { 271 | int count, eflags; 272 | target_ulong src; 273 | target_long res; 274 | 275 | count = t1 & SHIFT1_MASK; 276 | #if DATA_BITS == 16 277 | count = rclw_table[count]; 278 | #elif DATA_BITS == 8 279 | count = rclb_table[count]; 280 | #endif 281 | if (count) { 282 | eflags = helper_cc_compute_all(CC_OP); 283 | t0 &= DATA_MASK; 284 | src = t0; 285 | res = (t0 << count) | ((target_ulong)(eflags & CC_C) << (count - 1)); 286 | if (count > 1) 287 | res |= t0 >> (DATA_BITS + 1 - count); 288 | t0 = res; 289 | env->cc_tmp = (eflags & ~(CC_C | CC_O)) | 290 | (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) | 291 | ((src >> (DATA_BITS - count)) & CC_C); 292 | } else { 293 | env->cc_tmp = -1; 294 | } 295 | return t0; 296 | } 297 | 298 | target_ulong glue(helper_rcr, SUFFIX)(target_ulong t0, target_ulong t1) 299 | { 300 | int count, eflags; 301 | target_ulong src; 302 | target_long res; 303 | 304 | count = t1 & SHIFT1_MASK; 305 | #if DATA_BITS == 16 306 | count = rclw_table[count]; 307 | #elif DATA_BITS == 8 308 | count = rclb_table[count]; 309 | #endif 310 | if (count) { 311 | eflags = helper_cc_compute_all(CC_OP); 312 | t0 &= DATA_MASK; 313 | src = t0; 314 | res = (t0 >> count) | ((target_ulong)(eflags & CC_C) << (DATA_BITS - count)); 315 | if (count > 1) 316 | res |= t0 << (DATA_BITS + 1 - count); 317 | t0 = res; 318 | env->cc_tmp = (eflags & ~(CC_C | CC_O)) | 319 | (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) | 320 | ((src >> (count - 1)) & CC_C); 321 | } else { 322 | env->cc_tmp = -1; 323 | } 324 | return t0; 325 | } 326 | 327 | #undef DATA_BITS 328 | #undef SHIFT_MASK 329 | #undef SHIFT1_MASK 330 | #undef SIGN_MASK 331 | #undef DATA_TYPE 332 | #undef DATA_STYPE 333 | #undef DATA_MASK 334 | #undef SUFFIX 335 | -------------------------------------------------------------------------------- /qemu/target-i386/ops_sse_header.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4/PNI support 3 | * 4 | * Copyright (c) 2005 Fabrice Bellard 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | #if SHIFT == 0 20 | #define Reg MMXReg 21 | #define SUFFIX _mmx 22 | #else 23 | #define Reg XMMReg 24 | #define SUFFIX _xmm 25 | #endif 26 | 27 | #define dh_alias_Reg ptr 28 | #define dh_alias_XMMReg ptr 29 | #define dh_alias_MMXReg ptr 30 | #define dh_ctype_Reg Reg * 31 | #define dh_ctype_XMMReg XMMReg * 32 | #define dh_ctype_MMXReg MMXReg * 33 | #define dh_is_signed_Reg dh_is_signed_ptr 34 | #define dh_is_signed_XMMReg dh_is_signed_ptr 35 | #define dh_is_signed_MMXReg dh_is_signed_ptr 36 | 37 | DEF_HELPER_2(glue(psrlw, SUFFIX), void, Reg, Reg) 38 | DEF_HELPER_2(glue(psraw, SUFFIX), void, Reg, Reg) 39 | DEF_HELPER_2(glue(psllw, SUFFIX), void, Reg, Reg) 40 | DEF_HELPER_2(glue(psrld, SUFFIX), void, Reg, Reg) 41 | DEF_HELPER_2(glue(psrad, SUFFIX), void, Reg, Reg) 42 | DEF_HELPER_2(glue(pslld, SUFFIX), void, Reg, Reg) 43 | DEF_HELPER_2(glue(psrlq, SUFFIX), void, Reg, Reg) 44 | DEF_HELPER_2(glue(psllq, SUFFIX), void, Reg, Reg) 45 | 46 | #if SHIFT == 1 47 | DEF_HELPER_2(glue(psrldq, SUFFIX), void, Reg, Reg) 48 | DEF_HELPER_2(glue(pslldq, SUFFIX), void, Reg, Reg) 49 | #endif 50 | 51 | #define SSE_HELPER_B(name, F)\ 52 | DEF_HELPER_2(glue(name, SUFFIX), void, Reg, Reg) 53 | 54 | #define SSE_HELPER_W(name, F)\ 55 | DEF_HELPER_2(glue(name, SUFFIX), void, Reg, Reg) 56 | 57 | #define SSE_HELPER_L(name, F)\ 58 | DEF_HELPER_2(glue(name, SUFFIX), void, Reg, Reg) 59 | 60 | #define SSE_HELPER_Q(name, F)\ 61 | DEF_HELPER_2(glue(name, SUFFIX), void, Reg, Reg) 62 | 63 | SSE_HELPER_B(paddb, FADD) 64 | SSE_HELPER_W(paddw, FADD) 65 | SSE_HELPER_L(paddl, FADD) 66 | SSE_HELPER_Q(paddq, FADD) 67 | 68 | SSE_HELPER_B(psubb, FSUB) 69 | SSE_HELPER_W(psubw, FSUB) 70 | SSE_HELPER_L(psubl, FSUB) 71 | SSE_HELPER_Q(psubq, FSUB) 72 | 73 | SSE_HELPER_B(paddusb, FADDUB) 74 | SSE_HELPER_B(paddsb, FADDSB) 75 | SSE_HELPER_B(psubusb, FSUBUB) 76 | SSE_HELPER_B(psubsb, FSUBSB) 77 | 78 | SSE_HELPER_W(paddusw, FADDUW) 79 | SSE_HELPER_W(paddsw, FADDSW) 80 | SSE_HELPER_W(psubusw, FSUBUW) 81 | SSE_HELPER_W(psubsw, FSUBSW) 82 | 83 | SSE_HELPER_B(pminub, FMINUB) 84 | SSE_HELPER_B(pmaxub, FMAXUB) 85 | 86 | SSE_HELPER_W(pminsw, FMINSW) 87 | SSE_HELPER_W(pmaxsw, FMAXSW) 88 | 89 | SSE_HELPER_Q(pand, FAND) 90 | SSE_HELPER_Q(pandn, FANDN) 91 | SSE_HELPER_Q(por, FOR) 92 | SSE_HELPER_Q(pxor, FXOR) 93 | 94 | SSE_HELPER_B(pcmpgtb, FCMPGTB) 95 | SSE_HELPER_W(pcmpgtw, FCMPGTW) 96 | SSE_HELPER_L(pcmpgtl, FCMPGTL) 97 | 98 | SSE_HELPER_B(pcmpeqb, FCMPEQ) 99 | SSE_HELPER_W(pcmpeqw, FCMPEQ) 100 | SSE_HELPER_L(pcmpeql, FCMPEQ) 101 | 102 | SSE_HELPER_W(pmullw, FMULLW) 103 | #if SHIFT == 0 104 | SSE_HELPER_W(pmulhrw, FMULHRW) 105 | #endif 106 | SSE_HELPER_W(pmulhuw, FMULHUW) 107 | SSE_HELPER_W(pmulhw, FMULHW) 108 | 109 | SSE_HELPER_B(pavgb, FAVG) 110 | SSE_HELPER_W(pavgw, FAVG) 111 | 112 | DEF_HELPER_2(glue(pmuludq, SUFFIX), void, Reg, Reg) 113 | DEF_HELPER_2(glue(pmaddwd, SUFFIX), void, Reg, Reg) 114 | 115 | DEF_HELPER_2(glue(psadbw, SUFFIX), void, Reg, Reg) 116 | DEF_HELPER_3(glue(maskmov, SUFFIX), void, Reg, Reg, tl) 117 | DEF_HELPER_2(glue(movl_mm_T0, SUFFIX), void, Reg, i32) 118 | #ifdef TARGET_X86_64 119 | DEF_HELPER_2(glue(movq_mm_T0, SUFFIX), void, Reg, i64) 120 | #endif 121 | 122 | #if SHIFT == 0 123 | DEF_HELPER_3(glue(pshufw, SUFFIX), void, Reg, Reg, int) 124 | #else 125 | DEF_HELPER_3(shufps, void, Reg, Reg, int) 126 | DEF_HELPER_3(shufpd, void, Reg, Reg, int) 127 | DEF_HELPER_3(glue(pshufd, SUFFIX), void, Reg, Reg, int) 128 | DEF_HELPER_3(glue(pshuflw, SUFFIX), void, Reg, Reg, int) 129 | DEF_HELPER_3(glue(pshufhw, SUFFIX), void, Reg, Reg, int) 130 | #endif 131 | 132 | #if SHIFT == 1 133 | /* FPU ops */ 134 | /* XXX: not accurate */ 135 | 136 | #define SSE_HELPER_S(name, F)\ 137 | DEF_HELPER_2(name ## ps , void, Reg, Reg) \ 138 | DEF_HELPER_2(name ## ss , void, Reg, Reg) \ 139 | DEF_HELPER_2(name ## pd , void, Reg, Reg) \ 140 | DEF_HELPER_2(name ## sd , void, Reg, Reg) 141 | 142 | SSE_HELPER_S(add, FPU_ADD) 143 | SSE_HELPER_S(sub, FPU_SUB) 144 | SSE_HELPER_S(mul, FPU_MUL) 145 | SSE_HELPER_S(div, FPU_DIV) 146 | SSE_HELPER_S(min, FPU_MIN) 147 | SSE_HELPER_S(max, FPU_MAX) 148 | SSE_HELPER_S(sqrt, FPU_SQRT) 149 | 150 | 151 | DEF_HELPER_2(cvtps2pd, void, Reg, Reg) 152 | DEF_HELPER_2(cvtpd2ps, void, Reg, Reg) 153 | DEF_HELPER_2(cvtss2sd, void, Reg, Reg) 154 | DEF_HELPER_2(cvtsd2ss, void, Reg, Reg) 155 | DEF_HELPER_2(cvtdq2ps, void, Reg, Reg) 156 | DEF_HELPER_2(cvtdq2pd, void, Reg, Reg) 157 | DEF_HELPER_2(cvtpi2ps, void, XMMReg, MMXReg) 158 | DEF_HELPER_2(cvtpi2pd, void, XMMReg, MMXReg) 159 | DEF_HELPER_2(cvtsi2ss, void, XMMReg, i32) 160 | DEF_HELPER_2(cvtsi2sd, void, XMMReg, i32) 161 | 162 | #ifdef TARGET_X86_64 163 | DEF_HELPER_2(cvtsq2ss, void, XMMReg, i64) 164 | DEF_HELPER_2(cvtsq2sd, void, XMMReg, i64) 165 | #endif 166 | 167 | DEF_HELPER_2(cvtps2dq, void, XMMReg, XMMReg) 168 | DEF_HELPER_2(cvtpd2dq, void, XMMReg, XMMReg) 169 | DEF_HELPER_2(cvtps2pi, void, MMXReg, XMMReg) 170 | DEF_HELPER_2(cvtpd2pi, void, MMXReg, XMMReg) 171 | DEF_HELPER_1(cvtss2si, s32, XMMReg) 172 | DEF_HELPER_1(cvtsd2si, s32, XMMReg) 173 | #ifdef TARGET_X86_64 174 | DEF_HELPER_1(cvtss2sq, s64, XMMReg) 175 | DEF_HELPER_1(cvtsd2sq, s64, XMMReg) 176 | #endif 177 | 178 | DEF_HELPER_2(cvttps2dq, void, XMMReg, XMMReg) 179 | DEF_HELPER_2(cvttpd2dq, void, XMMReg, XMMReg) 180 | DEF_HELPER_2(cvttps2pi, void, MMXReg, XMMReg) 181 | DEF_HELPER_2(cvttpd2pi, void, MMXReg, XMMReg) 182 | DEF_HELPER_1(cvttss2si, s32, XMMReg) 183 | DEF_HELPER_1(cvttsd2si, s32, XMMReg) 184 | #ifdef TARGET_X86_64 185 | DEF_HELPER_1(cvttss2sq, s64, XMMReg) 186 | DEF_HELPER_1(cvttsd2sq, s64, XMMReg) 187 | #endif 188 | 189 | DEF_HELPER_2(rsqrtps, void, XMMReg, XMMReg) 190 | DEF_HELPER_2(rsqrtss, void, XMMReg, XMMReg) 191 | DEF_HELPER_2(rcpps, void, XMMReg, XMMReg) 192 | DEF_HELPER_2(rcpss, void, XMMReg, XMMReg) 193 | DEF_HELPER_2(extrq_r, void, XMMReg, XMMReg) 194 | DEF_HELPER_3(extrq_i, void, XMMReg, int, int) 195 | DEF_HELPER_2(insertq_r, void, XMMReg, XMMReg) 196 | DEF_HELPER_3(insertq_i, void, XMMReg, int, int) 197 | DEF_HELPER_2(haddps, void, XMMReg, XMMReg) 198 | DEF_HELPER_2(haddpd, void, XMMReg, XMMReg) 199 | DEF_HELPER_2(hsubps, void, XMMReg, XMMReg) 200 | DEF_HELPER_2(hsubpd, void, XMMReg, XMMReg) 201 | DEF_HELPER_2(addsubps, void, XMMReg, XMMReg) 202 | DEF_HELPER_2(addsubpd, void, XMMReg, XMMReg) 203 | 204 | #define SSE_HELPER_CMP(name, F)\ 205 | DEF_HELPER_2( name ## ps , void, Reg, Reg) \ 206 | DEF_HELPER_2( name ## ss , void, Reg, Reg) \ 207 | DEF_HELPER_2( name ## pd , void, Reg, Reg) \ 208 | DEF_HELPER_2( name ## sd , void, Reg, Reg) 209 | 210 | SSE_HELPER_CMP(cmpeq, FPU_CMPEQ) 211 | SSE_HELPER_CMP(cmplt, FPU_CMPLT) 212 | SSE_HELPER_CMP(cmple, FPU_CMPLE) 213 | SSE_HELPER_CMP(cmpunord, FPU_CMPUNORD) 214 | SSE_HELPER_CMP(cmpneq, FPU_CMPNEQ) 215 | SSE_HELPER_CMP(cmpnlt, FPU_CMPNLT) 216 | SSE_HELPER_CMP(cmpnle, FPU_CMPNLE) 217 | SSE_HELPER_CMP(cmpord, FPU_CMPORD) 218 | 219 | DEF_HELPER_2(ucomiss, void, Reg, Reg) 220 | DEF_HELPER_2(comiss, void, Reg, Reg) 221 | DEF_HELPER_2(ucomisd, void, Reg, Reg) 222 | DEF_HELPER_2(comisd, void, Reg, Reg) 223 | DEF_HELPER_1(movmskps, i32, Reg) 224 | DEF_HELPER_1(movmskpd, i32, Reg) 225 | #endif 226 | 227 | DEF_HELPER_1(glue(pmovmskb, SUFFIX), i32, Reg) 228 | DEF_HELPER_2(glue(packsswb, SUFFIX), void, Reg, Reg) 229 | DEF_HELPER_2(glue(packuswb, SUFFIX), void, Reg, Reg) 230 | DEF_HELPER_2(glue(packssdw, SUFFIX), void, Reg, Reg) 231 | #define UNPCK_OP(base_name, base) \ 232 | DEF_HELPER_2(glue(punpck ## base_name ## bw, SUFFIX) , void, Reg, Reg) \ 233 | DEF_HELPER_2(glue(punpck ## base_name ## wd, SUFFIX) , void, Reg, Reg) \ 234 | DEF_HELPER_2(glue(punpck ## base_name ## dq, SUFFIX) , void, Reg, Reg) 235 | 236 | UNPCK_OP(l, 0) 237 | UNPCK_OP(h, 1) 238 | 239 | #if SHIFT == 1 240 | DEF_HELPER_2(glue(punpcklqdq, SUFFIX), void, Reg, Reg) 241 | DEF_HELPER_2(glue(punpckhqdq, SUFFIX), void, Reg, Reg) 242 | #endif 243 | 244 | /* 3DNow! float ops */ 245 | #if SHIFT == 0 246 | DEF_HELPER_2(pi2fd, void, MMXReg, MMXReg) 247 | DEF_HELPER_2(pi2fw, void, MMXReg, MMXReg) 248 | DEF_HELPER_2(pf2id, void, MMXReg, MMXReg) 249 | DEF_HELPER_2(pf2iw, void, MMXReg, MMXReg) 250 | DEF_HELPER_2(pfacc, void, MMXReg, MMXReg) 251 | DEF_HELPER_2(pfadd, void, MMXReg, MMXReg) 252 | DEF_HELPER_2(pfcmpeq, void, MMXReg, MMXReg) 253 | DEF_HELPER_2(pfcmpge, void, MMXReg, MMXReg) 254 | DEF_HELPER_2(pfcmpgt, void, MMXReg, MMXReg) 255 | DEF_HELPER_2(pfmax, void, MMXReg, MMXReg) 256 | DEF_HELPER_2(pfmin, void, MMXReg, MMXReg) 257 | DEF_HELPER_2(pfmul, void, MMXReg, MMXReg) 258 | DEF_HELPER_2(pfnacc, void, MMXReg, MMXReg) 259 | DEF_HELPER_2(pfpnacc, void, MMXReg, MMXReg) 260 | DEF_HELPER_2(pfrcp, void, MMXReg, MMXReg) 261 | DEF_HELPER_2(pfrsqrt, void, MMXReg, MMXReg) 262 | DEF_HELPER_2(pfsub, void, MMXReg, MMXReg) 263 | DEF_HELPER_2(pfsubr, void, MMXReg, MMXReg) 264 | DEF_HELPER_2(pswapd, void, MMXReg, MMXReg) 265 | #endif 266 | 267 | /* SSSE3 op helpers */ 268 | DEF_HELPER_2(glue(phaddw, SUFFIX), void, Reg, Reg) 269 | DEF_HELPER_2(glue(phaddd, SUFFIX), void, Reg, Reg) 270 | DEF_HELPER_2(glue(phaddsw, SUFFIX), void, Reg, Reg) 271 | DEF_HELPER_2(glue(phsubw, SUFFIX), void, Reg, Reg) 272 | DEF_HELPER_2(glue(phsubd, SUFFIX), void, Reg, Reg) 273 | DEF_HELPER_2(glue(phsubsw, SUFFIX), void, Reg, Reg) 274 | DEF_HELPER_2(glue(pabsb, SUFFIX), void, Reg, Reg) 275 | DEF_HELPER_2(glue(pabsw, SUFFIX), void, Reg, Reg) 276 | DEF_HELPER_2(glue(pabsd, SUFFIX), void, Reg, Reg) 277 | DEF_HELPER_2(glue(pmaddubsw, SUFFIX), void, Reg, Reg) 278 | DEF_HELPER_2(glue(pmulhrsw, SUFFIX), void, Reg, Reg) 279 | DEF_HELPER_2(glue(pshufb, SUFFIX), void, Reg, Reg) 280 | DEF_HELPER_2(glue(psignb, SUFFIX), void, Reg, Reg) 281 | DEF_HELPER_2(glue(psignw, SUFFIX), void, Reg, Reg) 282 | DEF_HELPER_2(glue(psignd, SUFFIX), void, Reg, Reg) 283 | DEF_HELPER_3(glue(palignr, SUFFIX), void, Reg, Reg, s32) 284 | 285 | /* SSE4.1 op helpers */ 286 | #if SHIFT == 1 287 | DEF_HELPER_2(glue(pblendvb, SUFFIX), void, Reg, Reg) 288 | DEF_HELPER_2(glue(blendvps, SUFFIX), void, Reg, Reg) 289 | DEF_HELPER_2(glue(blendvpd, SUFFIX), void, Reg, Reg) 290 | DEF_HELPER_2(glue(ptest, SUFFIX), void, Reg, Reg) 291 | DEF_HELPER_2(glue(pmovsxbw, SUFFIX), void, Reg, Reg) 292 | DEF_HELPER_2(glue(pmovsxbd, SUFFIX), void, Reg, Reg) 293 | DEF_HELPER_2(glue(pmovsxbq, SUFFIX), void, Reg, Reg) 294 | DEF_HELPER_2(glue(pmovsxwd, SUFFIX), void, Reg, Reg) 295 | DEF_HELPER_2(glue(pmovsxwq, SUFFIX), void, Reg, Reg) 296 | DEF_HELPER_2(glue(pmovsxdq, SUFFIX), void, Reg, Reg) 297 | DEF_HELPER_2(glue(pmovzxbw, SUFFIX), void, Reg, Reg) 298 | DEF_HELPER_2(glue(pmovzxbd, SUFFIX), void, Reg, Reg) 299 | DEF_HELPER_2(glue(pmovzxbq, SUFFIX), void, Reg, Reg) 300 | DEF_HELPER_2(glue(pmovzxwd, SUFFIX), void, Reg, Reg) 301 | DEF_HELPER_2(glue(pmovzxwq, SUFFIX), void, Reg, Reg) 302 | DEF_HELPER_2(glue(pmovzxdq, SUFFIX), void, Reg, Reg) 303 | DEF_HELPER_2(glue(pmuldq, SUFFIX), void, Reg, Reg) 304 | DEF_HELPER_2(glue(pcmpeqq, SUFFIX), void, Reg, Reg) 305 | DEF_HELPER_2(glue(packusdw, SUFFIX), void, Reg, Reg) 306 | DEF_HELPER_2(glue(pminsb, SUFFIX), void, Reg, Reg) 307 | DEF_HELPER_2(glue(pminsd, SUFFIX), void, Reg, Reg) 308 | DEF_HELPER_2(glue(pminuw, SUFFIX), void, Reg, Reg) 309 | DEF_HELPER_2(glue(pminud, SUFFIX), void, Reg, Reg) 310 | DEF_HELPER_2(glue(pmaxsb, SUFFIX), void, Reg, Reg) 311 | DEF_HELPER_2(glue(pmaxsd, SUFFIX), void, Reg, Reg) 312 | DEF_HELPER_2(glue(pmaxuw, SUFFIX), void, Reg, Reg) 313 | DEF_HELPER_2(glue(pmaxud, SUFFIX), void, Reg, Reg) 314 | DEF_HELPER_2(glue(pmulld, SUFFIX), void, Reg, Reg) 315 | DEF_HELPER_2(glue(phminposuw, SUFFIX), void, Reg, Reg) 316 | DEF_HELPER_3(glue(roundps, SUFFIX), void, Reg, Reg, i32) 317 | DEF_HELPER_3(glue(roundpd, SUFFIX), void, Reg, Reg, i32) 318 | DEF_HELPER_3(glue(roundss, SUFFIX), void, Reg, Reg, i32) 319 | DEF_HELPER_3(glue(roundsd, SUFFIX), void, Reg, Reg, i32) 320 | DEF_HELPER_3(glue(blendps, SUFFIX), void, Reg, Reg, i32) 321 | DEF_HELPER_3(glue(blendpd, SUFFIX), void, Reg, Reg, i32) 322 | DEF_HELPER_3(glue(pblendw, SUFFIX), void, Reg, Reg, i32) 323 | DEF_HELPER_3(glue(dpps, SUFFIX), void, Reg, Reg, i32) 324 | DEF_HELPER_3(glue(dppd, SUFFIX), void, Reg, Reg, i32) 325 | DEF_HELPER_3(glue(mpsadbw, SUFFIX), void, Reg, Reg, i32) 326 | #endif 327 | 328 | /* SSE4.2 op helpers */ 329 | #if SHIFT == 1 330 | DEF_HELPER_2(glue(pcmpgtq, SUFFIX), void, Reg, Reg) 331 | DEF_HELPER_3(glue(pcmpestri, SUFFIX), void, Reg, Reg, i32) 332 | DEF_HELPER_3(glue(pcmpestrm, SUFFIX), void, Reg, Reg, i32) 333 | DEF_HELPER_3(glue(pcmpistri, SUFFIX), void, Reg, Reg, i32) 334 | DEF_HELPER_3(glue(pcmpistrm, SUFFIX), void, Reg, Reg, i32) 335 | DEF_HELPER_3(crc32, tl, i32, tl, i32) 336 | DEF_HELPER_2(popcnt, tl, tl, i32) 337 | #endif 338 | 339 | #undef SHIFT 340 | #undef Reg 341 | #undef SUFFIX 342 | 343 | #undef SSE_HELPER_B 344 | #undef SSE_HELPER_W 345 | #undef SSE_HELPER_L 346 | #undef SSE_HELPER_Q 347 | #undef SSE_HELPER_S 348 | #undef SSE_HELPER_CMP 349 | #undef UNPCK_OP 350 | -------------------------------------------------------------------------------- /qemu/target-i386/svm.h: -------------------------------------------------------------------------------- 1 | #ifndef __SVM_H 2 | #define __SVM_H 3 | 4 | #define TLB_CONTROL_DO_NOTHING 0 5 | #define TLB_CONTROL_FLUSH_ALL_ASID 1 6 | 7 | #define V_TPR_MASK 0x0f 8 | 9 | #define V_IRQ_SHIFT 8 10 | #define V_IRQ_MASK (1 << V_IRQ_SHIFT) 11 | 12 | #define V_INTR_PRIO_SHIFT 16 13 | #define V_INTR_PRIO_MASK (0x0f << V_INTR_PRIO_SHIFT) 14 | 15 | #define V_IGN_TPR_SHIFT 20 16 | #define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT) 17 | 18 | #define V_INTR_MASKING_SHIFT 24 19 | #define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT) 20 | 21 | #define SVM_INTERRUPT_SHADOW_MASK 1 22 | 23 | #define SVM_IOIO_STR_SHIFT 2 24 | #define SVM_IOIO_REP_SHIFT 3 25 | #define SVM_IOIO_SIZE_SHIFT 4 26 | #define SVM_IOIO_ASIZE_SHIFT 7 27 | 28 | #define SVM_IOIO_TYPE_MASK 1 29 | #define SVM_IOIO_STR_MASK (1 << SVM_IOIO_STR_SHIFT) 30 | #define SVM_IOIO_REP_MASK (1 << SVM_IOIO_REP_SHIFT) 31 | #define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT) 32 | #define SVM_IOIO_ASIZE_MASK (7 << SVM_IOIO_ASIZE_SHIFT) 33 | 34 | #define SVM_EVTINJ_VEC_MASK 0xff 35 | 36 | #define SVM_EVTINJ_TYPE_SHIFT 8 37 | #define SVM_EVTINJ_TYPE_MASK (7 << SVM_EVTINJ_TYPE_SHIFT) 38 | 39 | #define SVM_EVTINJ_TYPE_INTR (0 << SVM_EVTINJ_TYPE_SHIFT) 40 | #define SVM_EVTINJ_TYPE_NMI (2 << SVM_EVTINJ_TYPE_SHIFT) 41 | #define SVM_EVTINJ_TYPE_EXEPT (3 << SVM_EVTINJ_TYPE_SHIFT) 42 | #define SVM_EVTINJ_TYPE_SOFT (4 << SVM_EVTINJ_TYPE_SHIFT) 43 | 44 | #define SVM_EVTINJ_VALID (1 << 31) 45 | #define SVM_EVTINJ_VALID_ERR (1 << 11) 46 | 47 | #define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK 48 | 49 | #define SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR 50 | #define SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI 51 | #define SVM_EXITINTINFO_TYPE_EXEPT SVM_EVTINJ_TYPE_EXEPT 52 | #define SVM_EXITINTINFO_TYPE_SOFT SVM_EVTINJ_TYPE_SOFT 53 | 54 | #define SVM_EXITINTINFO_VALID SVM_EVTINJ_VALID 55 | #define SVM_EXITINTINFO_VALID_ERR SVM_EVTINJ_VALID_ERR 56 | 57 | #define SVM_EXIT_READ_CR0 0x000 58 | #define SVM_EXIT_READ_CR3 0x003 59 | #define SVM_EXIT_READ_CR4 0x004 60 | #define SVM_EXIT_READ_CR8 0x008 61 | #define SVM_EXIT_WRITE_CR0 0x010 62 | #define SVM_EXIT_WRITE_CR3 0x013 63 | #define SVM_EXIT_WRITE_CR4 0x014 64 | #define SVM_EXIT_WRITE_CR8 0x018 65 | #define SVM_EXIT_READ_DR0 0x020 66 | #define SVM_EXIT_READ_DR1 0x021 67 | #define SVM_EXIT_READ_DR2 0x022 68 | #define SVM_EXIT_READ_DR3 0x023 69 | #define SVM_EXIT_READ_DR4 0x024 70 | #define SVM_EXIT_READ_DR5 0x025 71 | #define SVM_EXIT_READ_DR6 0x026 72 | #define SVM_EXIT_READ_DR7 0x027 73 | #define SVM_EXIT_WRITE_DR0 0x030 74 | #define SVM_EXIT_WRITE_DR1 0x031 75 | #define SVM_EXIT_WRITE_DR2 0x032 76 | #define SVM_EXIT_WRITE_DR3 0x033 77 | #define SVM_EXIT_WRITE_DR4 0x034 78 | #define SVM_EXIT_WRITE_DR5 0x035 79 | #define SVM_EXIT_WRITE_DR6 0x036 80 | #define SVM_EXIT_WRITE_DR7 0x037 81 | #define SVM_EXIT_EXCP_BASE 0x040 82 | #define SVM_EXIT_INTR 0x060 83 | #define SVM_EXIT_NMI 0x061 84 | #define SVM_EXIT_SMI 0x062 85 | #define SVM_EXIT_INIT 0x063 86 | #define SVM_EXIT_VINTR 0x064 87 | #define SVM_EXIT_CR0_SEL_WRITE 0x065 88 | #define SVM_EXIT_IDTR_READ 0x066 89 | #define SVM_EXIT_GDTR_READ 0x067 90 | #define SVM_EXIT_LDTR_READ 0x068 91 | #define SVM_EXIT_TR_READ 0x069 92 | #define SVM_EXIT_IDTR_WRITE 0x06a 93 | #define SVM_EXIT_GDTR_WRITE 0x06b 94 | #define SVM_EXIT_LDTR_WRITE 0x06c 95 | #define SVM_EXIT_TR_WRITE 0x06d 96 | #define SVM_EXIT_RDTSC 0x06e 97 | #define SVM_EXIT_RDPMC 0x06f 98 | #define SVM_EXIT_PUSHF 0x070 99 | #define SVM_EXIT_POPF 0x071 100 | #define SVM_EXIT_CPUID 0x072 101 | #define SVM_EXIT_RSM 0x073 102 | #define SVM_EXIT_IRET 0x074 103 | #define SVM_EXIT_SWINT 0x075 104 | #define SVM_EXIT_INVD 0x076 105 | #define SVM_EXIT_PAUSE 0x077 106 | #define SVM_EXIT_HLT 0x078 107 | #define SVM_EXIT_INVLPG 0x079 108 | #define SVM_EXIT_INVLPGA 0x07a 109 | #define SVM_EXIT_IOIO 0x07b 110 | #define SVM_EXIT_MSR 0x07c 111 | #define SVM_EXIT_TASK_SWITCH 0x07d 112 | #define SVM_EXIT_FERR_FREEZE 0x07e 113 | #define SVM_EXIT_SHUTDOWN 0x07f 114 | #define SVM_EXIT_VMRUN 0x080 115 | #define SVM_EXIT_VMMCALL 0x081 116 | #define SVM_EXIT_VMLOAD 0x082 117 | #define SVM_EXIT_VMSAVE 0x083 118 | #define SVM_EXIT_STGI 0x084 119 | #define SVM_EXIT_CLGI 0x085 120 | #define SVM_EXIT_SKINIT 0x086 121 | #define SVM_EXIT_RDTSCP 0x087 122 | #define SVM_EXIT_ICEBP 0x088 123 | #define SVM_EXIT_WBINVD 0x089 124 | /* only included in documentation, maybe wrong */ 125 | #define SVM_EXIT_MONITOR 0x08a 126 | #define SVM_EXIT_MWAIT 0x08b 127 | #define SVM_EXIT_NPF 0x400 128 | 129 | #define SVM_EXIT_ERR -1 130 | 131 | #define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) /* TS and MP */ 132 | 133 | struct __attribute__ ((__packed__)) vmcb_control_area { 134 | uint16_t intercept_cr_read; 135 | uint16_t intercept_cr_write; 136 | uint16_t intercept_dr_read; 137 | uint16_t intercept_dr_write; 138 | uint32_t intercept_exceptions; 139 | uint64_t intercept; 140 | uint8_t reserved_1[44]; 141 | uint64_t iopm_base_pa; 142 | uint64_t msrpm_base_pa; 143 | uint64_t tsc_offset; 144 | uint32_t asid; 145 | uint8_t tlb_ctl; 146 | uint8_t reserved_2[3]; 147 | uint32_t int_ctl; 148 | uint32_t int_vector; 149 | uint32_t int_state; 150 | uint8_t reserved_3[4]; 151 | uint64_t exit_code; 152 | uint64_t exit_info_1; 153 | uint64_t exit_info_2; 154 | uint32_t exit_int_info; 155 | uint32_t exit_int_info_err; 156 | uint64_t nested_ctl; 157 | uint8_t reserved_4[16]; 158 | uint32_t event_inj; 159 | uint32_t event_inj_err; 160 | uint64_t nested_cr3; 161 | uint64_t lbr_ctl; 162 | uint8_t reserved_5[832]; 163 | }; 164 | 165 | struct __attribute__ ((__packed__)) vmcb_seg { 166 | uint16_t selector; 167 | uint16_t attrib; 168 | uint32_t limit; 169 | uint64_t base; 170 | }; 171 | 172 | struct __attribute__ ((__packed__)) vmcb_save_area { 173 | struct vmcb_seg es; 174 | struct vmcb_seg cs; 175 | struct vmcb_seg ss; 176 | struct vmcb_seg ds; 177 | struct vmcb_seg fs; 178 | struct vmcb_seg gs; 179 | struct vmcb_seg gdtr; 180 | struct vmcb_seg ldtr; 181 | struct vmcb_seg idtr; 182 | struct vmcb_seg tr; 183 | uint8_t reserved_1[43]; 184 | uint8_t cpl; 185 | uint8_t reserved_2[4]; 186 | uint64_t efer; 187 | uint8_t reserved_3[112]; 188 | uint64_t cr4; 189 | uint64_t cr3; 190 | uint64_t cr0; 191 | uint64_t dr7; 192 | uint64_t dr6; 193 | uint64_t rflags; 194 | uint64_t rip; 195 | uint8_t reserved_4[88]; 196 | uint64_t rsp; 197 | uint8_t reserved_5[24]; 198 | uint64_t rax; 199 | uint64_t star; 200 | uint64_t lstar; 201 | uint64_t cstar; 202 | uint64_t sfmask; 203 | uint64_t kernel_gs_base; 204 | uint64_t sysenter_cs; 205 | uint64_t sysenter_esp; 206 | uint64_t sysenter_eip; 207 | uint64_t cr2; 208 | uint8_t reserved_6[32]; 209 | uint64_t g_pat; 210 | uint64_t dbgctl; 211 | uint64_t br_from; 212 | uint64_t br_to; 213 | uint64_t last_excp_from; 214 | uint64_t last_excp_to; 215 | }; 216 | 217 | struct __attribute__ ((__packed__)) vmcb { 218 | struct vmcb_control_area control; 219 | struct vmcb_save_area save; 220 | }; 221 | 222 | #endif 223 | -------------------------------------------------------------------------------- /qemu/targphys.h: -------------------------------------------------------------------------------- 1 | /* Define target_phys_addr_t if it exists. */ 2 | 3 | #ifndef TARGPHYS_H 4 | #define TARGPHYS_H 5 | 6 | #ifdef TARGET_PHYS_ADDR_BITS 7 | /* target_phys_addr_t is the type of a physical address (its size can 8 | be different from 'target_ulong'). */ 9 | 10 | #if TARGET_PHYS_ADDR_BITS == 32 11 | typedef uint32_t target_phys_addr_t; 12 | #define TARGET_PHYS_ADDR_MAX UINT32_MAX 13 | #define TARGET_FMT_plx "%08x" 14 | #elif TARGET_PHYS_ADDR_BITS == 64 15 | typedef uint64_t target_phys_addr_t; 16 | #define TARGET_PHYS_ADDR_MAX UINT64_MAX 17 | #define TARGET_FMT_plx "%016" PRIx64 18 | #endif 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /qemu/tcg-runtime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny Code Generator for QEMU 3 | * 4 | * Copyright (c) 2008 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | 26 | #include "tcg/tcg-runtime.h" 27 | 28 | /* 32-bit helpers */ 29 | 30 | int32_t tcg_helper_div_i32(int32_t arg1, int32_t arg2) 31 | { 32 | return arg1 / arg2; 33 | } 34 | 35 | int32_t tcg_helper_rem_i32(int32_t arg1, int32_t arg2) 36 | { 37 | return arg1 % arg2; 38 | } 39 | 40 | uint32_t tcg_helper_divu_i32(uint32_t arg1, uint32_t arg2) 41 | { 42 | return arg1 / arg2; 43 | } 44 | 45 | uint32_t tcg_helper_remu_i32(uint32_t arg1, uint32_t arg2) 46 | { 47 | return arg1 % arg2; 48 | } 49 | 50 | /* 64-bit helpers */ 51 | 52 | int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2) 53 | { 54 | return arg1 << arg2; 55 | } 56 | 57 | int64_t tcg_helper_shr_i64(int64_t arg1, int64_t arg2) 58 | { 59 | return (uint64_t)arg1 >> arg2; 60 | } 61 | 62 | int64_t tcg_helper_sar_i64(int64_t arg1, int64_t arg2) 63 | { 64 | return arg1 >> arg2; 65 | } 66 | 67 | int64_t tcg_helper_div_i64(int64_t arg1, int64_t arg2) 68 | { 69 | return arg1 / arg2; 70 | } 71 | 72 | int64_t tcg_helper_rem_i64(int64_t arg1, int64_t arg2) 73 | { 74 | return arg1 % arg2; 75 | } 76 | 77 | uint64_t tcg_helper_divu_i64(uint64_t arg1, uint64_t arg2) 78 | { 79 | return arg1 / arg2; 80 | } 81 | 82 | uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2) 83 | { 84 | return arg1 % arg2; 85 | } 86 | -------------------------------------------------------------------------------- /qemu/tcg/README: -------------------------------------------------------------------------------- 1 | Tiny Code Generator - Fabrice Bellard. 2 | 3 | 1) Introduction 4 | 5 | TCG (Tiny Code Generator) began as a generic backend for a C 6 | compiler. It was simplified to be used in QEMU. It also has its roots 7 | in the QOP code generator written by Paul Brook. 8 | 9 | 2) Definitions 10 | 11 | The TCG "target" is the architecture for which we generate the 12 | code. It is of course not the same as the "target" of QEMU which is 13 | the emulated architecture. As TCG started as a generic C backend used 14 | for cross compiling, it is assumed that the TCG target is different 15 | from the host, although it is never the case for QEMU. 16 | 17 | A TCG "function" corresponds to a QEMU Translated Block (TB). 18 | 19 | A TCG "temporary" is a variable only live in a basic 20 | block. Temporaries are allocated explicitly in each function. 21 | 22 | A TCG "local temporary" is a variable only live in a function. Local 23 | temporaries are allocated explicitly in each function. 24 | 25 | A TCG "global" is a variable which is live in all the functions 26 | (equivalent of a C global variable). They are defined before the 27 | functions defined. A TCG global can be a memory location (e.g. a QEMU 28 | CPU register), a fixed host register (e.g. the QEMU CPU state pointer) 29 | or a memory location which is stored in a register outside QEMU TBs 30 | (not implemented yet). 31 | 32 | A TCG "basic block" corresponds to a list of instructions terminated 33 | by a branch instruction. 34 | 35 | 3) Intermediate representation 36 | 37 | 3.1) Introduction 38 | 39 | TCG instructions operate on variables which are temporaries, local 40 | temporaries or globals. TCG instructions and variables are strongly 41 | typed. Two types are supported: 32 bit integers and 64 bit 42 | integers. Pointers are defined as an alias to 32 bit or 64 bit 43 | integers depending on the TCG target word size. 44 | 45 | Each instruction has a fixed number of output variable operands, input 46 | variable operands and always constant operands. 47 | 48 | The notable exception is the call instruction which has a variable 49 | number of outputs and inputs. 50 | 51 | In the textual form, output operands usually come first, followed by 52 | input operands, followed by constant operands. The output type is 53 | included in the instruction name. Constants are prefixed with a '$'. 54 | 55 | add_i32 t0, t1, t2 (t0 <- t1 + t2) 56 | 57 | 3.2) Assumptions 58 | 59 | * Basic blocks 60 | 61 | - Basic blocks end after branches (e.g. brcond_i32 instruction), 62 | goto_tb and exit_tb instructions. 63 | - Basic blocks start after the end of a previous basic block, or at a 64 | set_label instruction. 65 | 66 | After the end of a basic block, the content of temporaries is 67 | destroyed, but local temporaries and globals are preserved. 68 | 69 | * Floating point types are not supported yet 70 | 71 | * Pointers: depending on the TCG target, pointer size is 32 bit or 64 72 | bit. The type TCG_TYPE_PTR is an alias to TCG_TYPE_I32 or 73 | TCG_TYPE_I64. 74 | 75 | * Helpers: 76 | 77 | Using the tcg_gen_helper_x_y it is possible to call any function 78 | taking i32, i64 or pointer types. By default, before calling a helper, 79 | all globals are stored at their canonical location and it is assumed 80 | that the function can modify them. This can be overridden by the 81 | TCG_CALL_CONST function modifier. By default, the helper is allowed to 82 | modify the CPU state or raise an exception. This can be overridden by 83 | the TCG_CALL_PURE function modifier, in which case the call to the 84 | function is removed if the return value is not used. 85 | 86 | On some TCG targets (e.g. x86), several calling conventions are 87 | supported. 88 | 89 | * Branches: 90 | 91 | Use the instruction 'br' to jump to a label. Use 'jmp' to jump to an 92 | explicit address. Conditional branches can only jump to labels. 93 | 94 | 3.3) Code Optimizations 95 | 96 | When generating instructions, you can count on at least the following 97 | optimizations: 98 | 99 | - Single instructions are simplified, e.g. 100 | 101 | and_i32 t0, t0, $0xffffffff 102 | 103 | is suppressed. 104 | 105 | - A liveness analysis is done at the basic block level. The 106 | information is used to suppress moves from a dead variable to 107 | another one. It is also used to remove instructions which compute 108 | dead results. The later is especially useful for condition code 109 | optimization in QEMU. 110 | 111 | In the following example: 112 | 113 | add_i32 t0, t1, t2 114 | add_i32 t0, t0, $1 115 | mov_i32 t0, $1 116 | 117 | only the last instruction is kept. 118 | 119 | 3.4) Instruction Reference 120 | 121 | ********* Function call 122 | 123 | * call ptr 124 | 125 | call function 'ptr' (pointer type) 126 | 127 | optional 32 bit or 64 bit return value 128 | optional 32 bit or 64 bit parameters 129 | 130 | ********* Jumps/Labels 131 | 132 | * jmp t0 133 | 134 | Absolute jump to address t0 (pointer type). 135 | 136 | * set_label $label 137 | 138 | Define label 'label' at the current program point. 139 | 140 | * br $label 141 | 142 | Jump to label. 143 | 144 | * brcond_i32/i64 cond, t0, t1, label 145 | 146 | Conditional jump if t0 cond t1 is true. cond can be: 147 | TCG_COND_EQ 148 | TCG_COND_NE 149 | TCG_COND_LT /* signed */ 150 | TCG_COND_GE /* signed */ 151 | TCG_COND_LE /* signed */ 152 | TCG_COND_GT /* signed */ 153 | TCG_COND_LTU /* unsigned */ 154 | TCG_COND_GEU /* unsigned */ 155 | TCG_COND_LEU /* unsigned */ 156 | TCG_COND_GTU /* unsigned */ 157 | 158 | ********* Arithmetic 159 | 160 | * add_i32/i64 t0, t1, t2 161 | 162 | t0=t1+t2 163 | 164 | * sub_i32/i64 t0, t1, t2 165 | 166 | t0=t1-t2 167 | 168 | * neg_i32/i64 t0, t1 169 | 170 | t0=-t1 (two's complement) 171 | 172 | * mul_i32/i64 t0, t1, t2 173 | 174 | t0=t1*t2 175 | 176 | * div_i32/i64 t0, t1, t2 177 | 178 | t0=t1/t2 (signed). Undefined behavior if division by zero or overflow. 179 | 180 | * divu_i32/i64 t0, t1, t2 181 | 182 | t0=t1/t2 (unsigned). Undefined behavior if division by zero. 183 | 184 | * rem_i32/i64 t0, t1, t2 185 | 186 | t0=t1%t2 (signed). Undefined behavior if division by zero or overflow. 187 | 188 | * remu_i32/i64 t0, t1, t2 189 | 190 | t0=t1%t2 (unsigned). Undefined behavior if division by zero. 191 | 192 | ********* Logical 193 | 194 | * and_i32/i64 t0, t1, t2 195 | 196 | t0=t1&t2 197 | 198 | * or_i32/i64 t0, t1, t2 199 | 200 | t0=t1|t2 201 | 202 | * xor_i32/i64 t0, t1, t2 203 | 204 | t0=t1^t2 205 | 206 | * not_i32/i64 t0, t1 207 | 208 | t0=~t1 209 | 210 | * andc_i32/i64 t0, t1, t2 211 | 212 | t0=t1&~t2 213 | 214 | * eqv_i32/i64 t0, t1, t2 215 | 216 | t0=~(t1^t2), or equivalently, t0=t1^~t2 217 | 218 | * nand_i32/i64 t0, t1, t2 219 | 220 | t0=~(t1&t2) 221 | 222 | * nor_i32/i64 t0, t1, t2 223 | 224 | t0=~(t1|t2) 225 | 226 | * orc_i32/i64 t0, t1, t2 227 | 228 | t0=t1|~t2 229 | 230 | ********* Shifts/Rotates 231 | 232 | * shl_i32/i64 t0, t1, t2 233 | 234 | t0=t1 << t2. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64) 235 | 236 | * shr_i32/i64 t0, t1, t2 237 | 238 | t0=t1 >> t2 (unsigned). Undefined behavior if t2 < 0 or t2 >= 32 (resp 64) 239 | 240 | * sar_i32/i64 t0, t1, t2 241 | 242 | t0=t1 >> t2 (signed). Undefined behavior if t2 < 0 or t2 >= 32 (resp 64) 243 | 244 | * rotl_i32/i64 t0, t1, t2 245 | 246 | Rotation of t2 bits to the left. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64) 247 | 248 | * rotr_i32/i64 t0, t1, t2 249 | 250 | Rotation of t2 bits to the right. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64) 251 | 252 | ********* Misc 253 | 254 | * mov_i32/i64 t0, t1 255 | 256 | t0 = t1 257 | 258 | Move t1 to t0 (both operands must have the same type). 259 | 260 | * ext8s_i32/i64 t0, t1 261 | ext8u_i32/i64 t0, t1 262 | ext16s_i32/i64 t0, t1 263 | ext16u_i32/i64 t0, t1 264 | ext32s_i64 t0, t1 265 | ext32u_i64 t0, t1 266 | 267 | 8, 16 or 32 bit sign/zero extension (both operands must have the same type) 268 | 269 | * bswap16_i32/i64 t0, t1 270 | 271 | 16 bit byte swap on a 32/64 bit value. It assumes that the two/six high order 272 | bytes are set to zero. 273 | 274 | * bswap32_i32/i64 t0, t1 275 | 276 | 32 bit byte swap on a 32/64 bit value. With a 64 bit value, it assumes that 277 | the four high order bytes are set to zero. 278 | 279 | * bswap64_i64 t0, t1 280 | 281 | 64 bit byte swap 282 | 283 | * discard_i32/i64 t0 284 | 285 | Indicate that the value of t0 won't be used later. It is useful to 286 | force dead code elimination. 287 | 288 | * deposit_i32/i64 dest, t1, t2, pos, len 289 | 290 | Deposit T2 as a bitfield into T1, placing the result in DEST. 291 | The bitfield is described by POS/LEN, which are immediate values: 292 | 293 | LEN - the length of the bitfield 294 | POS - the position of the first bit, counting from the LSB 295 | 296 | For example, pos=8, len=4 indicates a 4-bit field at bit 8. 297 | This operation would be equivalent to 298 | 299 | dest = (t1 & ~0x0f00) | ((t2 << 8) & 0x0f00) 300 | 301 | 302 | ********* Conditional moves 303 | 304 | * setcond_i32/i64 cond, dest, t1, t2 305 | 306 | dest = (t1 cond t2) 307 | 308 | Set DEST to 1 if (T1 cond T2) is true, otherwise set to 0. 309 | 310 | ********* Type conversions 311 | 312 | * ext_i32_i64 t0, t1 313 | Convert t1 (32 bit) to t0 (64 bit) and does sign extension 314 | 315 | * extu_i32_i64 t0, t1 316 | Convert t1 (32 bit) to t0 (64 bit) and does zero extension 317 | 318 | * trunc_i64_i32 t0, t1 319 | Truncate t1 (64 bit) to t0 (32 bit) 320 | 321 | * concat_i32_i64 t0, t1, t2 322 | Construct t0 (64-bit) taking the low half from t1 (32 bit) and the high half 323 | from t2 (32 bit). 324 | 325 | * concat32_i64 t0, t1, t2 326 | Construct t0 (64-bit) taking the low half from t1 (64 bit) and the high half 327 | from t2 (64 bit). 328 | 329 | ********* Load/Store 330 | 331 | * ld_i32/i64 t0, t1, offset 332 | ld8s_i32/i64 t0, t1, offset 333 | ld8u_i32/i64 t0, t1, offset 334 | ld16s_i32/i64 t0, t1, offset 335 | ld16u_i32/i64 t0, t1, offset 336 | ld32s_i64 t0, t1, offset 337 | ld32u_i64 t0, t1, offset 338 | 339 | t0 = read(t1 + offset) 340 | Load 8, 16, 32 or 64 bits with or without sign extension from host memory. 341 | offset must be a constant. 342 | 343 | * st_i32/i64 t0, t1, offset 344 | st8_i32/i64 t0, t1, offset 345 | st16_i32/i64 t0, t1, offset 346 | st32_i64 t0, t1, offset 347 | 348 | write(t0, t1 + offset) 349 | Write 8, 16, 32 or 64 bits to host memory. 350 | 351 | ********* 64-bit target on 32-bit host support 352 | 353 | The following opcodes are internal to TCG. Thus they are to be implemented by 354 | 32-bit host code generators, but are not to be emitted by guest translators. 355 | They are emitted as needed by inline functions within "tcg-op.h". 356 | 357 | * brcond2_i32 cond, t0_low, t0_high, t1_low, t1_high, label 358 | 359 | Similar to brcond, except that the 64-bit values T0 and T1 360 | are formed from two 32-bit arguments. 361 | 362 | * add2_i32 t0_low, t0_high, t1_low, t1_high, t2_low, t2_high 363 | * sub2_i32 t0_low, t0_high, t1_low, t1_high, t2_low, t2_high 364 | 365 | Similar to add/sub, except that the 64-bit inputs T1 and T2 are 366 | formed from two 32-bit arguments, and the 64-bit output T0 367 | is returned in two 32-bit outputs. 368 | 369 | * mulu2_i32 t0_low, t0_high, t1, t2 370 | 371 | Similar to mul, except two 32-bit (unsigned) inputs T1 and T2 yielding 372 | the full 64-bit product T0. The later is returned in two 32-bit outputs. 373 | 374 | * setcond2_i32 cond, dest, t1_low, t1_high, t2_low, t2_high 375 | 376 | Similar to setcond, except that the 64-bit values T1 and T2 are 377 | formed from two 32-bit arguments. The result is a 32-bit value. 378 | 379 | ********* QEMU specific operations 380 | 381 | * exit_tb t0 382 | 383 | Exit the current TB and return the value t0 (word type). 384 | 385 | * goto_tb index 386 | 387 | Exit the current TB and jump to the TB index 'index' (constant) if the 388 | current TB was linked to this TB. Otherwise execute the next 389 | instructions. 390 | 391 | * qemu_ld8u t0, t1, flags 392 | qemu_ld8s t0, t1, flags 393 | qemu_ld16u t0, t1, flags 394 | qemu_ld16s t0, t1, flags 395 | qemu_ld32 t0, t1, flags 396 | qemu_ld32u t0, t1, flags 397 | qemu_ld32s t0, t1, flags 398 | qemu_ld64 t0, t1, flags 399 | 400 | Load data at the QEMU CPU address t1 into t0. t1 has the QEMU CPU address 401 | type. 'flags' contains the QEMU memory index (selects user or kernel access) 402 | for example. 403 | 404 | Note that "qemu_ld32" implies a 32-bit result, while "qemu_ld32u" and 405 | "qemu_ld32s" imply a 64-bit result appropriately extended from 32 bits. 406 | 407 | * qemu_st8 t0, t1, flags 408 | qemu_st16 t0, t1, flags 409 | qemu_st32 t0, t1, flags 410 | qemu_st64 t0, t1, flags 411 | 412 | Store the data t0 at the QEMU CPU Address t1. t1 has the QEMU CPU 413 | address type. 'flags' contains the QEMU memory index (selects user or 414 | kernel access) for example. 415 | 416 | Note 1: Some shortcuts are defined when the last operand is known to be 417 | a constant (e.g. addi for add, movi for mov). 418 | 419 | Note 2: When using TCG, the opcodes must never be generated directly 420 | as some of them may not be available as "real" opcodes. Always use the 421 | function tcg_gen_xxx(args). 422 | 423 | 4) Backend 424 | 425 | tcg-target.h contains the target specific definitions. tcg-target.c 426 | contains the target specific code. 427 | 428 | 4.1) Assumptions 429 | 430 | The target word size (TCG_TARGET_REG_BITS) is expected to be 32 bit or 431 | 64 bit. It is expected that the pointer has the same size as the word. 432 | 433 | On a 32 bit target, all 64 bit operations are converted to 32 bits. A 434 | few specific operations must be implemented to allow it (see add2_i32, 435 | sub2_i32, brcond2_i32). 436 | 437 | Floating point operations are not supported in this version. A 438 | previous incarnation of the code generator had full support of them, 439 | but it is better to concentrate on integer operations first. 440 | 441 | On a 64 bit target, no assumption is made in TCG about the storage of 442 | the 32 bit values in 64 bit registers. 443 | 444 | 4.2) Constraints 445 | 446 | GCC like constraints are used to define the constraints of every 447 | instruction. Memory constraints are not supported in this 448 | version. Aliases are specified in the input operands as for GCC. 449 | 450 | The same register may be used for both an input and an output, even when 451 | they are not explicitly aliased. If an op expands to multiple target 452 | instructions then care must be taken to avoid clobbering input values. 453 | GCC style "early clobber" outputs are not currently supported. 454 | 455 | A target can define specific register or constant constraints. If an 456 | operation uses a constant input constraint which does not allow all 457 | constants, it must also accept registers in order to have a fallback. 458 | 459 | The movi_i32 and movi_i64 operations must accept any constants. 460 | 461 | The mov_i32 and mov_i64 operations must accept any registers of the 462 | same type. 463 | 464 | The ld/st instructions must accept signed 32 bit constant offsets. It 465 | can be implemented by reserving a specific register to compute the 466 | address if the offset is too big. 467 | 468 | The ld/st instructions must accept any destination (ld) or source (st) 469 | register. 470 | 471 | 4.3) Function call assumptions 472 | 473 | - The only supported types for parameters and return value are: 32 and 474 | 64 bit integers and pointer. 475 | - The stack grows downwards. 476 | - The first N parameters are passed in registers. 477 | - The next parameters are passed on the stack by storing them as words. 478 | - Some registers are clobbered during the call. 479 | - The function can return 0 or 1 value in registers. On a 32 bit 480 | target, functions must be able to return 2 values in registers for 481 | 64 bit return type. 482 | 483 | 5) Recommended coding rules for best performance 484 | 485 | - Use globals to represent the parts of the QEMU CPU state which are 486 | often modified, e.g. the integer registers and the condition 487 | codes. TCG will be able to use host registers to store them. 488 | 489 | - Avoid globals stored in fixed registers. They must be used only to 490 | store the pointer to the CPU state and possibly to store a pointer 491 | to a register window. 492 | 493 | - Use temporaries. Use local temporaries only when really needed, 494 | e.g. when you need to use a value after a jump. Local temporaries 495 | introduce a performance hit in the current TCG implementation: their 496 | content is saved to memory at end of each basic block. 497 | 498 | - Free temporaries and local temporaries when they are no longer used 499 | (tcg_temp_free). Since tcg_const_x() also creates a temporary, you 500 | should free it after it is used. Freeing temporaries does not yield 501 | a better generated code, but it reduces the memory usage of TCG and 502 | the speed of the translation. 503 | 504 | - Don't hesitate to use helpers for complicated or seldom used target 505 | instructions. There is little performance advantage in using TCG to 506 | implement target instructions taking more than about twenty TCG 507 | instructions. Note that this rule of thumb is more applicable to 508 | helpers doing complex logic or arithmetic, where the C compiler has 509 | scope to do a good job of optimisation; it is less relevant where 510 | the instruction is mostly doing loads and stores, and in those cases 511 | inline TCG may still be faster for longer sequences. 512 | 513 | - The hard limit on the number of TCG instructions you can generate 514 | per target instruction is set by MAX_OP_PER_INSTR in exec-all.h -- 515 | you cannot exceed this without risking a buffer overrun. 516 | 517 | - Use the 'discard' instruction if you know that TCG won't be able to 518 | prove that a given global is "dead" at a given program point. The 519 | x86 target uses it to improve the condition codes optimisation. 520 | -------------------------------------------------------------------------------- /qemu/tcg/aarch64/tcg-target.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Initial TCG Implementation for aarch64 3 | * 4 | * Copyright (c) 2017 Huawei Technologies Duesseldorf GmbH 5 | * Written by Claudio Fontana 6 | * 7 | * This work is licensed under the terms of the GNU LGPL, version 2 or 8 | * (at your option) any later version. 9 | * 10 | * See the COPYING file in the top-level directory for details. 11 | */ 12 | 13 | #ifndef TCG_TARGET_AARCH64 14 | #define TCG_TARGET_AARCH64 1 15 | 16 | #undef TCG_TARGET_WORDS_BIGENDIAN 17 | #undef TCG_TARGET_STACK_GROWSUP 18 | 19 | typedef enum { 20 | TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3, TCG_REG_X4, 21 | TCG_REG_X5, TCG_REG_X6, TCG_REG_X7, TCG_REG_X8, TCG_REG_X9, 22 | TCG_REG_X10, TCG_REG_X11, TCG_REG_X12, TCG_REG_X13, TCG_REG_X14, 23 | TCG_REG_X15, TCG_REG_X16, TCG_REG_X17, TCG_REG_X18, TCG_REG_X19, 24 | TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23, TCG_REG_X24, 25 | TCG_REG_X25, TCG_REG_X26, TCG_REG_X27, TCG_REG_X28, 26 | TCG_REG_FP, /* frame pointer */ 27 | TCG_REG_LR, /* link register */ 28 | TCG_REG_SP, /* stack pointer or zero register */ 29 | TCG_REG_XZR = TCG_REG_SP /* same register number */ 30 | /* program counter is not directly accessible! */ 31 | } TCGReg; 32 | 33 | #define TCG_TARGET_NB_REGS 32 34 | 35 | /* used for function call generation */ 36 | #define TCG_REG_CALL_STACK TCG_REG_SP 37 | #define TCG_TARGET_STACK_ALIGN 16 38 | #define TCG_TARGET_CALL_ALIGN_ARGS 1 39 | #define TCG_TARGET_CALL_STACK_OFFSET 0 40 | 41 | /* optional instructions */ 42 | #define TCG_TARGET_HAS_div_i32 0 43 | #define TCG_TARGET_HAS_ext8s_i32 1 44 | #define TCG_TARGET_HAS_ext16s_i32 1 45 | #define TCG_TARGET_HAS_ext8u_i32 1 46 | #define TCG_TARGET_HAS_ext16u_i32 1 47 | #define TCG_TARGET_HAS_bswap16_i32 1 48 | #define TCG_TARGET_HAS_bswap32_i32 1 49 | #define TCG_TARGET_HAS_not_i32 0 50 | #define TCG_TARGET_HAS_neg_i32 0 51 | #define TCG_TARGET_HAS_rot_i32 1 52 | #define TCG_TARGET_HAS_andc_i32 0 53 | #define TCG_TARGET_HAS_orc_i32 0 54 | #define TCG_TARGET_HAS_eqv_i32 0 55 | #define TCG_TARGET_HAS_nand_i32 0 56 | #define TCG_TARGET_HAS_nor_i32 0 57 | #define TCG_TARGET_HAS_deposit_i32 0 58 | #define TCG_TARGET_HAS_movcond_i32 0 59 | #define TCG_TARGET_HAS_add2_i32 0 60 | #define TCG_TARGET_HAS_sub2_i32 0 61 | #define TCG_TARGET_HAS_mulu2_i32 0 62 | #define TCG_TARGET_HAS_muls2_i32 0 63 | 64 | #define TCG_TARGET_HAS_div_i64 0 65 | #define TCG_TARGET_HAS_ext8s_i64 1 66 | #define TCG_TARGET_HAS_ext16s_i64 1 67 | #define TCG_TARGET_HAS_ext32s_i64 1 68 | #define TCG_TARGET_HAS_ext8u_i64 1 69 | #define TCG_TARGET_HAS_ext16u_i64 1 70 | #define TCG_TARGET_HAS_ext32u_i64 1 71 | #define TCG_TARGET_HAS_bswap16_i64 1 72 | #define TCG_TARGET_HAS_bswap32_i64 1 73 | #define TCG_TARGET_HAS_bswap64_i64 1 74 | #define TCG_TARGET_HAS_not_i64 0 75 | #define TCG_TARGET_HAS_neg_i64 0 76 | #define TCG_TARGET_HAS_rot_i64 1 77 | #define TCG_TARGET_HAS_andc_i64 0 78 | #define TCG_TARGET_HAS_orc_i64 0 79 | #define TCG_TARGET_HAS_eqv_i64 0 80 | #define TCG_TARGET_HAS_nand_i64 0 81 | #define TCG_TARGET_HAS_nor_i64 0 82 | #define TCG_TARGET_HAS_deposit_i64 0 83 | #define TCG_TARGET_HAS_movcond_i64 0 84 | #define TCG_TARGET_HAS_add2_i64 0 85 | #define TCG_TARGET_HAS_sub2_i64 0 86 | #define TCG_TARGET_HAS_mulu2_i64 0 87 | #define TCG_TARGET_HAS_muls2_i64 0 88 | 89 | enum { 90 | TCG_AREG0 = TCG_REG_X19, 91 | }; 92 | 93 | extern void flush_icache_range(tcg_target_ulong start, tcg_target_ulong stop); 94 | 95 | #endif /* TCG_TARGET_AARCH64 */ 96 | -------------------------------------------------------------------------------- /qemu/tcg/tcg-opc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny Code Generator for QEMU 3 | * 4 | * Copyright (c) 2008 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | * DEF(name, oargs, iargs, cargs, flags) 27 | */ 28 | 29 | /* predefined ops */ 30 | DEF(end, 0, 0, 0, 0) /* must be kept first */ 31 | DEF(nop, 0, 0, 0, 0) 32 | DEF(nop1, 0, 0, 1, 0) 33 | DEF(nop2, 0, 0, 2, 0) 34 | DEF(nop3, 0, 0, 3, 0) 35 | DEF(nopn, 0, 0, 1, 0) /* variable number of parameters */ 36 | 37 | DEF(discard, 1, 0, 0, 0) 38 | 39 | DEF(set_label, 0, 0, 1, 0) 40 | DEF(call, 0, 1, 2, TCG_OPF_SIDE_EFFECTS) /* variable number of parameters */ 41 | DEF(jmp, 0, 1, 0, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) 42 | DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) 43 | 44 | DEF(mov_i32, 1, 1, 0, 0) 45 | DEF(movi_i32, 1, 0, 1, 0) 46 | DEF(setcond_i32, 1, 2, 1, 0) 47 | /* load/store */ 48 | DEF(ld8u_i32, 1, 1, 1, 0) 49 | DEF(ld8s_i32, 1, 1, 1, 0) 50 | DEF(ld16u_i32, 1, 1, 1, 0) 51 | DEF(ld16s_i32, 1, 1, 1, 0) 52 | DEF(ld_i32, 1, 1, 1, 0) 53 | DEF(st8_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS) 54 | DEF(st16_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS) 55 | DEF(st_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS) 56 | /* arith */ 57 | DEF(add_i32, 1, 2, 0, 0) 58 | DEF(sub_i32, 1, 2, 0, 0) 59 | DEF(mul_i32, 1, 2, 0, 0) 60 | #if TCG_TARGET_HAS_div_i32 61 | DEF(div_i32, 1, 2, 0, 0) 62 | DEF(divu_i32, 1, 2, 0, 0) 63 | DEF(rem_i32, 1, 2, 0, 0) 64 | DEF(remu_i32, 1, 2, 0, 0) 65 | #endif 66 | #if TCG_TARGET_HAS_div2_i32 67 | DEF(div2_i32, 2, 3, 0, 0) 68 | DEF(divu2_i32, 2, 3, 0, 0) 69 | #endif 70 | DEF(and_i32, 1, 2, 0, 0) 71 | DEF(or_i32, 1, 2, 0, 0) 72 | DEF(xor_i32, 1, 2, 0, 0) 73 | /* shifts/rotates */ 74 | DEF(shl_i32, 1, 2, 0, 0) 75 | DEF(shr_i32, 1, 2, 0, 0) 76 | DEF(sar_i32, 1, 2, 0, 0) 77 | #if TCG_TARGET_HAS_rot_i32 78 | DEF(rotl_i32, 1, 2, 0, 0) 79 | DEF(rotr_i32, 1, 2, 0, 0) 80 | #endif 81 | #if TCG_TARGET_HAS_deposit_i32 82 | DEF(deposit_i32, 1, 2, 2, 0) 83 | #endif 84 | 85 | DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) 86 | #if TCG_TARGET_REG_BITS == 32 87 | DEF(add2_i32, 2, 4, 0, 0) 88 | DEF(sub2_i32, 2, 4, 0, 0) 89 | DEF(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) 90 | DEF(mulu2_i32, 2, 2, 0, 0) 91 | DEF(setcond2_i32, 1, 4, 1, 0) 92 | #endif 93 | #if TCG_TARGET_HAS_ext8s_i32 94 | DEF(ext8s_i32, 1, 1, 0, 0) 95 | #endif 96 | #if TCG_TARGET_HAS_ext16s_i32 97 | DEF(ext16s_i32, 1, 1, 0, 0) 98 | #endif 99 | #if TCG_TARGET_HAS_ext8u_i32 100 | DEF(ext8u_i32, 1, 1, 0, 0) 101 | #endif 102 | #if TCG_TARGET_HAS_ext16u_i32 103 | DEF(ext16u_i32, 1, 1, 0, 0) 104 | #endif 105 | #if TCG_TARGET_HAS_bswap16_i32 106 | DEF(bswap16_i32, 1, 1, 0, 0) 107 | #endif 108 | #if TCG_TARGET_HAS_bswap32_i32 109 | DEF(bswap32_i32, 1, 1, 0, 0) 110 | #endif 111 | #if TCG_TARGET_HAS_not_i32 112 | DEF(not_i32, 1, 1, 0, 0) 113 | #endif 114 | #if TCG_TARGET_HAS_neg_i32 115 | DEF(neg_i32, 1, 1, 0, 0) 116 | #endif 117 | #if TCG_TARGET_HAS_andc_i32 118 | DEF(andc_i32, 1, 2, 0, 0) 119 | #endif 120 | #if TCG_TARGET_HAS_orc_i32 121 | DEF(orc_i32, 1, 2, 0, 0) 122 | #endif 123 | #if TCG_TARGET_HAS_eqv_i32 124 | DEF(eqv_i32, 1, 2, 0, 0) 125 | #endif 126 | #if TCG_TARGET_HAS_nand_i32 127 | DEF(nand_i32, 1, 2, 0, 0) 128 | #endif 129 | #if TCG_TARGET_HAS_nor_i32 130 | DEF(nor_i32, 1, 2, 0, 0) 131 | #endif 132 | 133 | #if TCG_TARGET_REG_BITS == 64 134 | DEF(mov_i64, 1, 1, 0, 0) 135 | DEF(movi_i64, 1, 0, 1, 0) 136 | DEF(setcond_i64, 1, 2, 1, 0) 137 | /* load/store */ 138 | DEF(ld8u_i64, 1, 1, 1, 0) 139 | DEF(ld8s_i64, 1, 1, 1, 0) 140 | DEF(ld16u_i64, 1, 1, 1, 0) 141 | DEF(ld16s_i64, 1, 1, 1, 0) 142 | DEF(ld32u_i64, 1, 1, 1, 0) 143 | DEF(ld32s_i64, 1, 1, 1, 0) 144 | DEF(ld_i64, 1, 1, 1, 0) 145 | DEF(st8_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS) 146 | DEF(st16_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS) 147 | DEF(st32_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS) 148 | DEF(st_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS) 149 | /* arith */ 150 | DEF(add_i64, 1, 2, 0, 0) 151 | DEF(sub_i64, 1, 2, 0, 0) 152 | DEF(mul_i64, 1, 2, 0, 0) 153 | #if TCG_TARGET_HAS_div_i64 154 | DEF(div_i64, 1, 2, 0, 0) 155 | DEF(divu_i64, 1, 2, 0, 0) 156 | DEF(rem_i64, 1, 2, 0, 0) 157 | DEF(remu_i64, 1, 2, 0, 0) 158 | #endif 159 | #if TCG_TARGET_HAS_div2_i64 160 | DEF(div2_i64, 2, 3, 0, 0) 161 | DEF(divu2_i64, 2, 3, 0, 0) 162 | #endif 163 | DEF(and_i64, 1, 2, 0, 0) 164 | DEF(or_i64, 1, 2, 0, 0) 165 | DEF(xor_i64, 1, 2, 0, 0) 166 | /* shifts/rotates */ 167 | DEF(shl_i64, 1, 2, 0, 0) 168 | DEF(shr_i64, 1, 2, 0, 0) 169 | DEF(sar_i64, 1, 2, 0, 0) 170 | #if TCG_TARGET_HAS_rot_i64 171 | DEF(rotl_i64, 1, 2, 0, 0) 172 | DEF(rotr_i64, 1, 2, 0, 0) 173 | #endif 174 | #if TCG_TARGET_HAS_deposit_i64 175 | DEF(deposit_i64, 1, 2, 2, 0) 176 | #endif 177 | 178 | DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) 179 | #if TCG_TARGET_HAS_ext8s_i64 180 | DEF(ext8s_i64, 1, 1, 0, 0) 181 | #endif 182 | #if TCG_TARGET_HAS_ext16s_i64 183 | DEF(ext16s_i64, 1, 1, 0, 0) 184 | #endif 185 | #if TCG_TARGET_HAS_ext32s_i64 186 | DEF(ext32s_i64, 1, 1, 0, 0) 187 | #endif 188 | #if TCG_TARGET_HAS_ext8u_i64 189 | DEF(ext8u_i64, 1, 1, 0, 0) 190 | #endif 191 | #if TCG_TARGET_HAS_ext16u_i64 192 | DEF(ext16u_i64, 1, 1, 0, 0) 193 | #endif 194 | #if TCG_TARGET_HAS_ext32u_i64 195 | DEF(ext32u_i64, 1, 1, 0, 0) 196 | #endif 197 | #if TCG_TARGET_HAS_bswap16_i64 198 | DEF(bswap16_i64, 1, 1, 0, 0) 199 | #endif 200 | #if TCG_TARGET_HAS_bswap32_i64 201 | DEF(bswap32_i64, 1, 1, 0, 0) 202 | #endif 203 | #if TCG_TARGET_HAS_bswap64_i64 204 | DEF(bswap64_i64, 1, 1, 0, 0) 205 | #endif 206 | #if TCG_TARGET_HAS_not_i64 207 | DEF(not_i64, 1, 1, 0, 0) 208 | #endif 209 | #if TCG_TARGET_HAS_neg_i64 210 | DEF(neg_i64, 1, 1, 0, 0) 211 | #endif 212 | #if TCG_TARGET_HAS_andc_i64 213 | DEF(andc_i64, 1, 2, 0, 0) 214 | #endif 215 | #if TCG_TARGET_HAS_orc_i64 216 | DEF(orc_i64, 1, 2, 0, 0) 217 | #endif 218 | #if TCG_TARGET_HAS_eqv_i64 219 | DEF(eqv_i64, 1, 2, 0, 0) 220 | #endif 221 | #if TCG_TARGET_HAS_nand_i64 222 | DEF(nand_i64, 1, 2, 0, 0) 223 | #endif 224 | #if TCG_TARGET_HAS_nor_i64 225 | DEF(nor_i64, 1, 2, 0, 0) 226 | #endif 227 | #endif 228 | 229 | /* QEMU specific */ 230 | #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS 231 | DEF(debug_insn_start, 0, 0, 2, 0) 232 | #else 233 | DEF(debug_insn_start, 0, 0, 1, 0) 234 | #endif 235 | DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) 236 | DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) 237 | /* Note: even if TARGET_LONG_BITS is not defined, the INDEX_op 238 | constants must be defined */ 239 | #if TCG_TARGET_REG_BITS == 32 240 | #if TARGET_LONG_BITS == 32 241 | DEF(qemu_ld8u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 242 | #else 243 | DEF(qemu_ld8u, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 244 | #endif 245 | #if TARGET_LONG_BITS == 32 246 | DEF(qemu_ld8s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 247 | #else 248 | DEF(qemu_ld8s, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 249 | #endif 250 | #if TARGET_LONG_BITS == 32 251 | DEF(qemu_ld16u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 252 | #else 253 | DEF(qemu_ld16u, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 254 | #endif 255 | #if TARGET_LONG_BITS == 32 256 | DEF(qemu_ld16s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 257 | #else 258 | DEF(qemu_ld16s, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 259 | #endif 260 | #if TARGET_LONG_BITS == 32 261 | DEF(qemu_ld32, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 262 | #else 263 | DEF(qemu_ld32, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 264 | #endif 265 | #if TARGET_LONG_BITS == 32 266 | DEF(qemu_ld64, 2, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 267 | #else 268 | DEF(qemu_ld64, 2, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 269 | #endif 270 | 271 | #if TARGET_LONG_BITS == 32 272 | DEF(qemu_st8, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 273 | #else 274 | DEF(qemu_st8, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 275 | #endif 276 | #if TARGET_LONG_BITS == 32 277 | DEF(qemu_st16, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 278 | #else 279 | DEF(qemu_st16, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 280 | #endif 281 | #if TARGET_LONG_BITS == 32 282 | DEF(qemu_st32, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 283 | #else 284 | DEF(qemu_st32, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 285 | #endif 286 | #if TARGET_LONG_BITS == 32 287 | DEF(qemu_st64, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 288 | #else 289 | DEF(qemu_st64, 0, 4, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 290 | #endif 291 | 292 | #else /* TCG_TARGET_REG_BITS == 32 */ 293 | 294 | DEF(qemu_ld8u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 295 | DEF(qemu_ld8s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 296 | DEF(qemu_ld16u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 297 | DEF(qemu_ld16s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 298 | DEF(qemu_ld32, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 299 | DEF(qemu_ld32u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 300 | DEF(qemu_ld32s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 301 | DEF(qemu_ld64, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 302 | 303 | DEF(qemu_st8, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 304 | DEF(qemu_st16, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 305 | DEF(qemu_st32, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 306 | DEF(qemu_st64, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) 307 | 308 | #endif /* TCG_TARGET_REG_BITS != 32 */ 309 | 310 | #undef DEF 311 | -------------------------------------------------------------------------------- /qemu/tcg/tcg-runtime.h: -------------------------------------------------------------------------------- 1 | #ifndef TCG_RUNTIME_H 2 | #define TCG_RUNTIME_H 3 | 4 | /* tcg-runtime.c */ 5 | int32_t tcg_helper_div_i32(int32_t arg1, int32_t arg2); 6 | int32_t tcg_helper_rem_i32(int32_t arg1, int32_t arg2); 7 | uint32_t tcg_helper_divu_i32(uint32_t arg1, uint32_t arg2); 8 | uint32_t tcg_helper_remu_i32(uint32_t arg1, uint32_t arg2); 9 | 10 | int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2); 11 | int64_t tcg_helper_shr_i64(int64_t arg1, int64_t arg2); 12 | int64_t tcg_helper_sar_i64(int64_t arg1, int64_t arg2); 13 | int64_t tcg_helper_div_i64(int64_t arg1, int64_t arg2); 14 | int64_t tcg_helper_rem_i64(int64_t arg1, int64_t arg2); 15 | uint64_t tcg_helper_divu_i64(uint64_t arg1, uint64_t arg2); 16 | uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /qemu/translate-all.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Host code generation 3 | * 4 | * Copyright (c) 2003 Fabrice Bellard 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, see . 18 | */ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "config.h" 26 | 27 | #define NO_CPU_IO_DEFS 28 | #include "cpu.h" 29 | #include "disas.h" 30 | #include "tcg.h" 31 | //#include "qemu-timer.h" 32 | 33 | /* code generation context */ 34 | TCGContext tcg_ctx; 35 | 36 | uint16_t gen_opc_buf[OPC_BUF_SIZE]; 37 | TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE]; 38 | 39 | target_ulong gen_opc_pc[OPC_BUF_SIZE]; 40 | uint16_t gen_opc_icount[OPC_BUF_SIZE]; 41 | uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; 42 | 43 | void cpu_gen_init(void) 44 | { 45 | tcg_context_init(&tcg_ctx); 46 | } 47 | 48 | /* return non zero if the very first instruction is invalid so that 49 | the virtual CPU can trigger an exception. 50 | 51 | '*gen_code_size_ptr' contains the size of the generated code (host 52 | code). 53 | */ 54 | int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr) 55 | { 56 | TCGContext *s = &tcg_ctx; 57 | uint8_t *gen_code_buf; 58 | int gen_code_size; 59 | #ifdef CONFIG_PROFILER 60 | int64_t ti; 61 | #endif 62 | 63 | #ifdef CONFIG_PROFILER 64 | s->tb_count1++; /* includes aborted translations because of 65 | exceptions */ 66 | ti = profile_getclock(); 67 | #endif 68 | tcg_func_start(s); 69 | 70 | gen_intermediate_code(env, tb); 71 | 72 | /* generate machine code */ 73 | gen_code_buf = tb->tc_ptr; 74 | tb->tb_next_offset[0] = 0xffff; 75 | tb->tb_next_offset[1] = 0xffff; 76 | s->tb_next_offset = tb->tb_next_offset; 77 | #ifdef USE_DIRECT_JUMP 78 | s->tb_jmp_offset = tb->tb_jmp_offset; 79 | s->tb_next = NULL; 80 | #else 81 | s->tb_jmp_offset = NULL; 82 | s->tb_next = tb->tb_next; 83 | #endif 84 | 85 | #ifdef CONFIG_PROFILER 86 | s->tb_count++; 87 | s->interm_time += profile_getclock() - ti; 88 | s->code_time -= profile_getclock(); 89 | #endif 90 | gen_code_size = tcg_gen_code(s, gen_code_buf); 91 | *gen_code_size_ptr = gen_code_size; 92 | #ifdef CONFIG_PROFILER 93 | s->code_time += profile_getclock(); 94 | s->code_in_len += tb->size; 95 | s->code_out_len += gen_code_size; 96 | #endif 97 | 98 | #ifdef DEBUG_DISAS 99 | if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) { 100 | qemu_log("OUT: [size=%d]\n", *gen_code_size_ptr); 101 | log_disas(tb->tc_ptr, *gen_code_size_ptr); 102 | qemu_log("\n"); 103 | qemu_log_flush(); 104 | } 105 | #endif 106 | return 0; 107 | } 108 | 109 | /* The cpu state corresponding to 'searched_pc' is restored. 110 | */ 111 | int cpu_restore_state(TranslationBlock *tb, 112 | CPUState *env, unsigned long searched_pc) 113 | { 114 | TCGContext *s = &tcg_ctx; 115 | int j; 116 | unsigned long tc_ptr; 117 | #ifdef CONFIG_PROFILER 118 | int64_t ti; 119 | #endif 120 | 121 | #ifdef CONFIG_PROFILER 122 | ti = profile_getclock(); 123 | #endif 124 | tcg_func_start(s); 125 | 126 | gen_intermediate_code_pc(env, tb); 127 | 128 | #if 0 129 | if (use_icount) { 130 | /* Reset the cycle counter to the start of the block. */ 131 | env->icount_decr.u16.low += tb->icount; 132 | /* Clear the IO flag. */ 133 | env->can_do_io = 0; 134 | } 135 | #endif 136 | 137 | /* find opc index corresponding to search_pc */ 138 | tc_ptr = (unsigned long)tb->tc_ptr; 139 | if (searched_pc < tc_ptr) 140 | return -1; 141 | 142 | s->tb_next_offset = tb->tb_next_offset; 143 | #ifdef USE_DIRECT_JUMP 144 | s->tb_jmp_offset = tb->tb_jmp_offset; 145 | s->tb_next = NULL; 146 | #else 147 | s->tb_jmp_offset = NULL; 148 | s->tb_next = tb->tb_next; 149 | #endif 150 | j = tcg_gen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr); 151 | if (j < 0) 152 | return -1; 153 | /* now find start of instruction before */ 154 | while (gen_opc_instr_start[j] == 0) 155 | j--; 156 | env->icount_decr.u16.low -= gen_opc_icount[j]; 157 | 158 | restore_state_to_opc(env, tb, j); 159 | 160 | #ifdef CONFIG_PROFILER 161 | s->restore_time += profile_getclock() - ti; 162 | s->restore_count++; 163 | #endif 164 | return 0; 165 | } 166 | --------------------------------------------------------------------------------