[
  {
    "path": ".gitignore",
    "content": "# exclude all object files\nsrc/*.o\nsrc/riscvsim/*.o\nsrc/slirp/*.o\n\n# exclude all dependency files\nsrc/*.d\nsrc/riscvsim/*.d\nsrc/slirp/*.d\n\n# exclude stats, log and trace files\nsrc/*.csv\nsrc/*.log\nsrc/*.trace\n\n# exclude executables\nsrc/marss-riscv\nsrc/sim-stats-display\nsrc/build_filelist\nsrc/splitimg\n\n# exclude libraries\nsrc/*.so\nsrc/*.a\n"
  },
  {
    "path": ".gitmodules",
    "content": ""
  },
  {
    "path": "Changelog.md",
    "content": "# Version 4.1a\n\n - Added\n\t - Model a arbitrary fixed latency between LLC cache and Memory controller\n - Changed\n\t - For Ramulator and DRAMSim3, memory access request is split into MEM_BUS_WIDTH sized parts and latency for each part is queried\n - Fixed\n\t - Rounding mode (rm) must be calculated again before executing FP instruction during simulation\n\n# Version 4.0a\n\n - Added\n\t - Comprehensive logging support\n\t - Command-line option `-sim-file-path` to specify a top-level directory to store statistics and log files\n\t - Command-line option `-sim-file-prefix` to specify prefix appended to all simulator generated files\n\t - Command-line option `-sim-emulate-after-icount` to specify the number of instruction to simulate after starting simulation mode\n\t - [DRAMsim3](https://github.com/umd-memsys/DRAMSim3) support\n\t - [Ramulator](https://github.com/CMU-SAFARI/ramulator) support\n\t - Sample MARSS-RISCV configuration files for a 64-bit RISC-V In-order and Out-of-order SoC in [configs](./configs) folder\n\t - More performance counters to count different types of load instructions (byte, half-word, word, double-word)\n\t - Time-stamp to all the statistics files generated by the simulator\n\t - Specify latency in CPU cycles for RISC-V `SYSTEM` class instructions in the config file\n\t - Counter to track the number of CPU pipeline flushes\n\t - Counters to tracks each type of software exceptions and hardware interrupt processed during simulation\n\t - Parallel build support for Makefile\n\t - During the simulation, `mtime` is calculated using simulation clock cycles\n\t - Specify frequency for CPU and RTC device via the config file\n\t - Add option `flush_on_context_switch` in the config file to enable/disable flushing of BPU on a context switch\n\t - Start fetching the target from the next cycle on branch misprediction\n\t - Load for non-word quantities (byte and half-word) take an extra one cycle on cache-hit\n\t - Add function to invalidate entries in mem_request_queue on the miss-speculated path\n- Changed\n\t - Re-factor and modularize simulator code-base\n\t - STORE type instructions submit write-request to L1-data cache and exit memory stage in a single cycle\n\t - Delay for reading/writing page-table entries is now simulated via L1-Data cache\n\t - Print IPC for all the RISC-V CPU modes after simulation completes to the console and log file\n\t - In-order core doesn't support parallel execution in multiple functional units\n\t - Replace hot-cold LRU eviction policy with bit-PLRU eviction policy for BTB and caches\n\t - Improve the format of TinyEMU config file\n\t - Update [MARSS-RISCV Docs](https://marss-riscv-docs.readthedocs.io/en/latest/)\n\t - Update README.md\n\t - Page walk delays are simulated via L1 D$\n\t - Removed [DRAMsim2](https://github.com/umd-memsys/DRAMSim2) support\n - Fixed\n\t - Memory leaks\n\t - Don't start simulating DRAM access delay until cache lookup delay is simulated\n\t - Branch entry is added to BTB, only after the branch is resolved\n\n# Version 3.1a\n\n - Added\n\t - Print TLB stats to the terminal after the simulation completes\n\t - Specify latency for each FPU ALU instruction (`fadd`, `fsub`, `fmul`, `fdiv`, `fmin`, `fmax`, `fcvt`, `cvt`, `fle`, `flt`, `feq`, `fsgnj`, `fqsrt`, `fmv`, `fclass`) via TinyEMU config file \n\t - Figure showing the high-level overview of MARSS-RISCV in README.md \n- Changed\n\t - Simplify the base DRAM model\n\t\t - All memory accesses simulate a fixed latency `mem_access_latency`\n\t\t - Any subsequent accesses to the same physical page occupies a lower delay, which is roughly 60 percent of the fixed `mem_access_latency`\n\t\t - More info [here](https://marss-riscv-docs.readthedocs.io/en/latest/)\n\t - Parallel operation of functional units can be enabled or disabled in the in-order core via TinyEMU config file\n\t - Clean exception handling code\n\t - Simulate page table entry read/write delays directly via memory controller using a configurable fixed latency `pte_rw_latency`\n\t - Don't stall the pipeline stage for the write request to complete on the memory controller\n\t - Make FPU-ALU non-pipelined\n\t - Rename `dram_dispatch_queue` to`mem_request_queue`\n\t - Update [MARSS-RISCV Docs](https://marss-riscv-docs.readthedocs.io/en/latest/)\n\t - Update README.md\n\t - Update TinyEMU config file [here](https://cs.binghamton.edu/~marss-riscv/marss-riscv-images.tar.gz)\n - Fixed\n\t - memory leaks\n\n# Version 3.0a\n\n - Added\n\t - Support for separate RISC-V Bios and Kernel\n\t - Command line option `flush-sim-mem` to flush simulator memory hierarchy on every fresh simulation run\n\t - Command line option `sim-trace` to generate instruction commit trace during simulation\n\t - Distinct configurable read-hit and write-hit latency for all the caches\n\t - Return address stack (RAS)\n\t - Branch prediction and speculative execution support for out of order core\n\t - Print performance counters on terminal when the simulation completes\n\t - More performance counters:\n\t\t - Instruction types\n\t\t - ecall\n\t\t - page walks for loads, stores and instructions\n\t\t - memory controller delay for data and instructions\n\t\t - hardware interrupts\n - Changed\n\t - Port to TinyEMU version `2019-12-21`\n\t - For bimodal branch predictor, store prediction bits in a separate Branch history table (BHT)\n\t - For in-order core, non-memory instructions can forward their result from MEM stage in addition to EX stage\n\t - For in-order core, relaxed interlocking on WAW data hazard\n\t - Simplified out of order core design, ROB slots are now used as physical registers along with a single rename table and a single global issue queue\n - Fixed\n\t - Correctly calculated the rounding mode for floating pointing instruction decoding\n\t - Converted `c.addiw` result buffer into `int32_t` on 64-bit simulation\n\t - Set the data type to `unint64_t` for 64-bit simulation, for the buffer which holds the memory address for atomic instructions\n\t - Issue #13 and #14 (thanks to Okhotnikov Grigory)\n\n# Version 2.0a\n\n - Added\n\t - Added [DRAMSim2](https://github.com/umd-memsys/DRAMSim2) support\n - Changed\n\t - Flush all the CPU caches and DRAM models for every new simulation run\n - Fixed\n\t - Issue #8: useless cleaning of local variables\n\n# Version 1.1a\n - Added\n\t- Add 16550A UART support (thanks to Marc Gauthier)\n\t- Add a timestamp suffix to the stats file\n - Changed\n\t- Reworked the dram latency parameters to match the Sifive HiFive U540 Board\n\t- Increased the dram dispatch queue size from 32 to 64\n - Fixed\n\t- Calculation of hardware page walk latency\n\t- Miscalculation in page fault counters\n\t- Issue #2: memory leaks in copy_file\n\t- Issue #3: 'log' instead 'log2'\n"
  },
  {
    "path": "LICENSE.md",
    "content": "MIT License\n\nCopyright (c) 2016-2017 Fabrice Bellard\nCopyright (c) 2017-2019 Gaurav Kothari\nCopyright (c) 2018-2019 Parikshit Sarnaik\nCopyright (c) 2019 Göktürk Yüksek\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "## MARSS-RISCV: Micro-Architectural System Simulator for RISC-V\n\nMARSS-RISCV (Micro-ARchitectural System Simulator - RISCV) is an **open-source, cycle-level single-core full-system (Linux) micro-architectural simulator** for the [RISC-V](https://riscv.org/specifications/) ISA built on top of [TinyEMU emulator](https://bellard.org/tinyemu) developed by Fabrice Bellard and utilizes the configuration code, RISC-V CPU state, physical memory, MMU, and all the devices emulated by TinyEMU.\n\nIt consists of detailed cycle-level models of a generic RISC-V In-order and Out-of-order processor with a branch prediction unit, TLBs, cache-hierarchy, and a simplistic DRAM model. It comes integrated with [DRAMSim3](https://github.com/umd-memsys/DRAMSim3) and [Ramulator](https://github.com/CMU-SAFARI/ramulator), which are cycle-accurate DRAM simulators. It can simulate the entire RISC-V software stack (from the bootloader and kernel to the user level applications, including system calls) cycle-by-cycle along with the real-time I/O without any modifications and provides simulation statistics for all the RISC-V CPU privilege modes (user, supervisor, and machine). Hence, it makes MARSS-RISCV, a full system simulation framework that simulates an entire RISC-V system-on-a-chip (SoC) cycle-by-cycle.\n\nIt is currently being developed and maintained by [CAPS](https://github.com/bucaps/) (Computer Architecture and Power-Aware Systems Research Group) at the State University of New York at Binghamton. Our simulator is currently in alpha status as we are validating the cycle accuracy using various development boards. The figure below shows a high-level overview of the MARSS-RISCV simulation framework.\n\n<p align=\"center\">\n  <img width=\"400\" height=\"400\" src=\"./figures/marss-riscv-arch.svg\">\n</p>\n\n## Table of contents\n- [Features](#features)\n- [Getting started with the simulator running a Linux guest](#getting-started-with-the-simulator-running-a-linux-guest)\n- [Running full system simulations](#running-full-system-simulations)\n- [Viewing live simulation stats](#viewing-live-simulation-stats)\n- [Generating simulation trace](#generating-simulation-trace)\n- [Future work](#future-work)\n- [Technical notes](#technical-notes)\n- [Authors](#authors)\n- [Acknowledgment](#acknowledgment)\n- [License](#license)\n\n## Features \n- **Full system simulator** which simulates the entire system on a cycle-by-cyle basis, including the bootloader, kernel, libraries, interrupt handlers, and user-level applications\n- **Configurable RISC-V CPU** with cycle-level, in-order and out-of-order processor models\n- **Multiple execution units** with configurable latencies (execution units can be configured to run iteratively or in a pipelined fashion)\n- **Simulates memory access delay for instructions, data and page table walk** via three direct-mapped TLBs (for code, loads and stores), two-level cache hierarchy with various allocation and miss handling policies and following DRAM memory models: A simplistic base DRAM model (which simulates a fixed delay for every main memory access), [DRAMSim3](https://github.com/umd-memsys/DRAMSim3), and [Ramulator](https://github.com/CMU-SAFARI/ramulator)\n- **Branch predictor** which supports Bi-modal and 2-level adaptive (Gshare, Gselect, GAg, GAp, PAg, PAp) predictors and a Return address stack (RAS)\n- **RISC-V ISA support** includes `RV32GC` and `RV64GC` (user-level ISA version `2.2`, privileged architecture version `1.10`)\n- **Emulated devices** include standard platform-level interrupt controller (PLIC), core local interrupter (CLINT), real-time clock device (RTC), universal asynchronous receiver/transmitter (UART), VirtIO, NIC, block device, and 9P filesystem\n- **Single JSON configuration file** to configure TinyEMU and simulator parameters, specify RISC-V BIOS and kernel individually\n- **Easy to install, use and hack** with a small codebase\n\nFor more details regarding the microarchitecture of the simulated CPU, branch predictor, memory hierarchy and simulator configuration, refer to [MARSS-RISCV Docs](https://marss-riscv-docs.readthedocs.io/en/latest/)\n\n## Getting started with the simulator running a Linux guest\n\n### System requirements\n* 32-bit or 64-bit Linux machine\n* Libcurl, OpenSSL and SDL Libraries\n* Standard C and C++ compiler\n\n### Installing the dependencies\nMake sure that you have all the dependencies (`ssl`, `sdl`, and `curl` libraries) installed on the system. For Debian-based (including Ubuntu) systems, the packages are: `build-essential`, `libssl-dev`, `libsdl1.2-dev`, `libcurl4-openssl-dev`. \n```console\n$ sudo apt-get update\n$ sudo apt-get install build-essential\n$ sudo apt-get install libssl-dev\n$ sudo apt-get install libsdl1.2-dev\n$ sudo apt-get install libcurl4-openssl-dev\n```\n### Compiling the simulator\n\nFirst, clone the simulator repository:\n\n```console\n$ git clone https://github.com/bucaps/marss-riscv\n```\nThen, `cd` into the simulator source directory:\n\n```console\n$ cd marss-riscv/src/\n```\nSet the `CONFIG_XLEN` variable in the Makefile to the desired `XLEN` as required. Supported `XLEN` values are `32` and `64`. Default is `64`.\n\nThen, compile the simulator using:\n\n```console\n$ make\n```\n\n### Preparing the bootloader, kernel and userland image\nThe simplest way to start is by using a pre-built bootloader, kernel, and userland image. The pre-built 32-bit and 64-bit RISC-V userland, bootloader, and kernel are available here: [marss-riscv-images.tar.gz](https://cs.binghamton.edu/~marss-riscv/marss-riscv-images.tar.gz)\n\nThe userland image needs to be decompressed before running the simulator:\n\n```console\n$ wget https://cs.binghamton.edu/~marss-riscv/marss-riscv-images.tar.gz\n$ tar -xvzf marss-riscv-images.tar.gz\n$ cd marss-riscv-images/riscv64-unknown-linux-gnu/\n$ xz -d -k -T 0 riscv64.img.xz\n```\n\nWhen decompression finishes, jump to the marss-riscv `src` folder and launch the simulator with:\n\n```console\n$ ./marss-riscv ../configs/riscv64_inorder_soc.cfg\n```\n\nSimulation and TinyEMU SoC parameters are configured using the TinyEMU JSON configuration file provided in the [configs](/configs) directory. We have provided sample configuration files for 64-bit RISC-V single-core in-order and out-of-order SoC. The following table provides a summary of various simulation related command-line options supported by MARSS-RISCV.\n\n| Options                     | Arguments          | Description                                                                                                                                                                                                                                                                                      |\n|-----------------------------|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `-rw`                       | -                  | By default, the simulator will boot in `snapshot` mode, meaning it will **not** retain the file system changes after it is shut down. In order to persist the changes, pass `-rw` command-line argument to the simulator.                                                                        |\n| `-simstart`                 | -                  | By default, guest boots in emulation mode, to start TinyEMU (boot kernel) in simulation mode run with `-simstart` command-line option.                                                                                                                                                           |\n| `-sim-stats-display`        | `posix-shm-name`   | Dump simulation performance stats to a shared memory location `posix-shm-name`, read by sim-stats-display tool.  First, open a new terminal before executing the simulator and launch `sim-stats-display` tool with `posix-shm-name` as an argument.  Then start the simulator on a different terminal with `-sim-stats-display` command-line option with `posix-shm-name` as an argument. |\n| `-sim-mem-model`            | `base`, `dramsim3`, `ramulator` | To specify which memory model to use, run with command line option `-sim-mem-model` and specify either `base`, `dramsim3`, or `ramulator`. The default is `base`. For DRAMSim3 and Ramulator, the paths to `config file` can be specified in the TinyEMU config file.                                                  |\n| `-sim-flush-mem`            | -                  | Flush simulator memory hierarchy on every new simulation run                                                                                                                                                                                                                                     |\n| `-sim-flush-bpu`            | -                  | Flush branch prediction unit on every new simulation run                                                                                                                                                                                                                                         |\n| `-sim-file-path`            | `directory path`   | Path of the directory to store stats, log, dramsim3 stats, ramulator stats, and trace files. Default is current directory `.`, the user must create the directory before starting MARSS-RISCV.                                                                                                                                     |\n| `-sim-file-prefix`          | `prefix`           | Prefix appended to stats, log, and trace file names. Default prefix used for all the simulator generated files is `sim`. (E.g., sim_<timestamp>.csv (for stats),  sim.log, sim.trace)                                                                                                                                                                         |\n| `-sim-trace`                |                    | Generate instruction commit trace in during simulation. Trace is generated in file named `<sim-file-prefix>_trace.txt`                                                                                                                                                                           |\n| `-sim-emulate-after-icount` | `icount`           | Switch to emulation mode after simulating `icount` instructions every time simulation starts.                                                                                                                                                                                                    |\n\n\nIt may also be desirable to increase the userland image (has roughly 200MB of available free space by default). More information about how to increase the size of the userland image is in the `readme.txt` file, which comes with the [images archive](https://cs.binghamton.edu/~marss-riscv/marss-riscv-images.tar.gz).\n\nOnce the guest boots, we need to initialize the environment. Normally, this should happen automatically, but due to an unresolved bug, it needs to done explicitly:\n\n```console\n# export PYTHONPATH=/usr/lib64/python2.7/site-packages/\n# env-update\n```\n\nThe system is ready for use and has a working GCC compiler, ssh, git, and virtual network interface. However, there is no host-to-guest routing, so it is not possible to ssh into the guest.\n\nBy default, `Ctrl-C` will not kill the simulator. The command `halt` will cleanly shutdown the guest. Alternatively, pass the `-ctrlc` command-line argument to the simulator, which will allow it to be killed using `Ctrl-C`.\n\nAfter gaining access to the guest machine terminal, refer to the next section for running simulations.\n\n## Running full system simulations\n\n### Using checkpoints\nThe simulator supports two distinct custom instructions, `SIM_START()` and `SIM_STOP()`, which inform MARSS-RISCV to enable and disable simulation mode, respectively, when encountered during instruction processing.  To implement these instructions, we have used two different unused registers from user mode CSR address space, `0x800`, and `0x801`. When the simulation is disabled, MARSS-RISCV runs in the emulation mode. \n\nWith these two custom instructions as checkpoints, it is possible to simulate any section in the source code. However, after inserting these markers, the source code must be recompiled inside the guest OS using the installed GCC toolchain.  Alternatively, users can compile the programs on their host machine using the RISC-V toolchain and import them onto the disk image.\n\nAfter the simulator executes `SIM_STOP()` instruction, simulation mode is disabled, and all the performance stats are saved in the file `sim_stats_file` as configured in the simulator configuration file.  The code below shows a simple hello world program with checkpoints instructions. \n\n```c\n/* hello_world.c */\n\n#include <stdio.h>\n\n#define SIM_START() asm(\"csrs 0x800,zero\")\n#define SIM_STOP() asm(\"csrs  0x801,zero\")\n\nint main()\n{\n  SIM_START();\n  printf(\"Hello World\\n\");\n  SIM_STOP();\n  return 0;\n}\n```\n\n### Using the simulate script\nAlternatively, users can use the simulation script (`simulate.c`) provided [here](https://github.com/bucaps/marss-riscv-utils/blob/master/simulate.c), which forks a child process. The child enters the simulation mode and execs the command. The parent process waits for the child to complete and then switches MARSS-RISCV back to emulation mode. With this script, it is possible to simulate any program without the need to modify and recompile the source code. Since the child switches to simulation mode before calling `exec()`, `exec()` also runs in the simulation. Hence, performance statistics generated at the end of the simulation will also include stats for `exec()`.\n\n### Running benchmarks\nWe have provided a detailed step-by-step comprehensive tutorial [here](https://marss-riscv-docs.readthedocs.io/en/latest/sections/running-full-system.html) to run the benchmarks on the simulator. This tutorial configures MARSS-RISCV to simulate a simple 5-stage 32-bit in-order RISC-V processor and run [CoreMark](https://github.com/eembc/coremark), an industry-standard benchmark that measures the performance of central processing units (CPU) and embedded microcontrollers (MCU).\n\n## Viewing live simulation stats\nUsers can view live simulation stats using the provided `sim-stats-display` tool. First, open a new terminal before executing the simulator and launch `sim-stats-display` with a shared memory name of the user's choice as an argument:\n\n```console\n$ ./sim-stats-display marss-riscv-test-shm\n```\nThen launch the simulator on a different terminal with `-sim-stats-display marss-riscv-test-shm` command-line option.\n\n## Generating simulation trace\nTo generate instruction, commit trace of the programs running in the simulation, run MARSS-RISCV with `-sim-trace` command-line option.\n\nSample trace generated is shown below:\n```bash\ncycle=112 pc=0x6aaaadf8 insn=0x85be863a c.mv a2,a4 mode=PRV_U\ncycle=113 pc=0x6aaaadfa insn=0x250385be c.mv a1,a5 mode=PRV_U\ncycle=115 pc=0x6aaaadfc insn=0xfa842503 lw a0,s0,-88 mode=PRV_U\n\n```\n\n## Technical notes\nThis section refers to technical notes for [TinyEMU](https://bellard.org/tinyemu). For simulator specific technical details refer: [MARSS-RISCV Docs](https://marss-riscv-docs.readthedocs.io/en/latest/)\n\n### Floating point emulation\nThe floating-point emulation is bit-exact and supports all the specified instructions for 32-bit and 64-bit floating-point numbers. It uses the new SoftFP library.\n\n### HTIF console\nThe standard HTIF console uses registers at variable addresses, which are deduced by loading specific ELF symbols. TinyEMU does not rely on an ELF loader, so it is much simpler to use registers at fixed addresses (0x40008000). A small modification was made in the \"riscv-pk\" boot loader to support it. The HTIF console is only used to display boot messages and to power off the virtual system. The OS should use the VirtIO console.\n\n### Network usage\nThe easiest way is to use the \"user\" mode network driver. No specific configuration is necessary. TinyEMU also supports a \"tap\" network driver to redirect the network traffic from a VirtIO network adapter. You can look at the ``netinit.sh`` script to create the tap network interface and to redirect the virtual traffic to the Internet through a NAT. The exact configuration may depend on the Linux distribution and local firewall configuration. The TinyEMU configuration file must include:\n\n``eth0: { driver: \"tap\", ifname: \"tap0\" }``\n\nFurthermore, configure the network in the guest system with:\n```console\n$ ifconfig eth0 192.168.3.2\n$ route add -net 0.0.0.0 gw 192.168.3.1 eth0\n```\n\n### Network filesystem\nTinyEMU supports the VirtIO 9P filesystem to access local or remote filesystems. For remote filesystems, it makes HTTP requests to download the files. The protocol is compatible with the vfsync utility. In the ``mount`` command, ``/dev/rootN`` must be used as a device name where ``N`` is the index of the filesystem. When ``N=0``, it is omitted.\n\nThe build_filelist tool builds the file list from a root directory. A simple web server is enough to serve the files. The ``.preload`` file gives a list of files to preload when opening a given file.\n\n### Network block device\nTinyEMU supports an HTTP block device. The disk image is split into small files. Use the ``splitimg`` utility to generate images. The URL of the JSON blk.txt file must be provided as a disk image filename.\n\n## Authors\n* Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n* Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n\nTinyEMU:\n* Copyright (c) 2016-2019 Fabrice Bellard\n\n## Acknowledgment\n* This work was supported in part by DARPA through an award from the SSITH program. \n* Thanks to Fabrice Bellard for the development of TinyEMU. \n* We want to thank Gokturk Yuksek, Ravi Theja Gollapudi, and Kanad Ghose for assistance with the internal details of TinyEMU and the development of the MARSS-RISCV simulator.\n* Thanks to all the people working on the RISC-V project.\n* For DRAMSim3, refer [here](https://github.com/umd-memsys/DRAMSim3).\n* For Ramulator, refer [here](https://github.com/CMU-SAFARI/ramulator).\n\n## License\n* This project is licensed under the MIT License - refer to the [LICENSE.md](LICENSE.md) file for details.\n* The SLIRP library has a two clause BSD license.\n* DRAMSim3 has a MIT License.\n* Ramulator has a MIT License.\n"
  },
  {
    "path": "configs/riscv64_inorder_soc.cfg",
    "content": "/* VM configuration file */\n{\n\tversion: 1,\n\tmachine: \"riscv64\", /* riscv32, riscv64 */\n\tmemory_size: 2048, /* MB */\n\tbios: \"riscv64-unknown-linux-gnu/bbl64.bin\",\n\tkernel: \"riscv64-unknown-linux-gnu/kernel-riscv64.bin\",\n\tcmdline: \"console=hvc0 root=/dev/vda rw\",\n\tdrive0: { file: \"riscv64-unknown-linux-gnu/riscv64.img\" },\n\teth0: { driver: \"user\" },\n\n\tcore: {\n\t\tname: \"64-bit inorder riscv CPU\",\n\t\ttype: \"incore\", /* incore, oocore */\n\t\tcpu_freq_mhz: 1000,\n\t\trtc_freq_mhz: 10,\n\n\t\tincore : {\n\t\t\tnum_cpu_stages: 5, /* 5, 6 */\n\t\t},\n\n\t\toocore: {\n\t\t\tiq_size: 16,\n\t\t\tiq_issue_ports: 3,\n\t\t\trob_size: 64,\n\t\t\trob_commit_ports:4,\n\t\t\tlsq_size: 16,\n\t\t},\n\n\t\t/* Note: Latencies for functional units, caches and memory are specified in CPU cycles */\n\t\tfunctional_units: {\n\t\t\tnum_alu_stages: 1,\n\t\t\talu_stage_latency: \"1\",\n\t\n\t\t\tnum_mul_stages: 1,\n\t\t\tmul_stage_latency: \"4\",\n\t\n\t\t\tnum_div_stages: 1,\n\t\t\tdiv_stage_latency: \"67\",\n\t\n\t\t\t/* Note: This will create a pipelined FP-FMA unit with 4 stages with a\n\t\t\t * latency of 1 CPU cycle(s) per stage */\n\t\t\tnum_fpu_fma_stages: 4,\n\t\t\tfpu_fma_stage_latency: \"1,1,1,1\",\n\t\n\t\t\t/* Note: FP-ALU is non-pipelined */\n\t\t\tfpu_alu_stage_latency: {\n\t\t\t\tfadd: 2,\n\t\t\t\tfsub: 2,\n\t\t\t\tfmul: 2,\n\t\t\t\tfdiv: 8,\n\t\t\t\tfsqrt: 8,\n\t\t\t\tfsgnj: 2,\n\t\t\t\tfmin: 4,\n\t\t\t\tfmax: 4,\n\t\t\t\tfeq: 2,\n\t\t\t\tflt: 2,\n\t\t\t\tfle: 2,\n\t\t\t\tcvt: 2,\n\t\t\t\tfcvt: 2,\n\t\t\t\tfmv: 2,\n\t\t\t\tfclass: 1,\n\t\t\t},\n\n\t\t\t/* Latency for RISC-V SYSTEM opcode instructions (includes CSR and privileged instructions)*/\n\t\t\tsystem_insn_latency: 3,\n\t\t},\n\t\n\t\tbpu: {\n\t\t\tenable: \"true\", /* true, false */\n\t\t\tflush_on_context_switch: \"false\", /* true, false */\n\n\t\t\tbtb: {\n\t\t\t\tsize: 32,\n\t\t\t\tways: 2,\n\t\t\t\teviction_policy: \"lru\", /* lru, random */\n\t\t\t},\n\t\n\t\t\tbpu_type: \"bimodal\", /* bimodal, adaptive */\n\t\n\t\t\tbimodal: {\n\t\t\t\tbht_size: 256,\n\t\t\t},\n\t\n\t\t\tadaptive: {\n\t\t\t\tght_size: 1,\n\t\t\t\tpht_size: 1,\n\t\t\t\thistory_bits: 2,\n\t\t\t\taliasing_func_type: \"xor\", /* xor, and, none */\n\n\t\t\t    /* Given config for adaptive predictor will create a Gshare predictor:\n\t\t\t\t*\t1) global history table consisting of one entry, entry includes a 2-bit history register\n\t\t\t\t*\t2) pattern history table consisting of one entry, entry includes an array of 4 saturating counters\n\t\t\t\t* \t3) value of history register will be `xor` ed with branch PC to index into the array of saturating counters\n\t\t\t\t*/\n\t\t\t},\n\t\n\t\t\tras_size: 6, /* value 0 disables RAS */\n\t\t},\n\t\n\t\tcaches: {\n\t\t\tenable_l1_caches: \"true\", /* true, false */\n\t\t\tallocate_on_write_miss: \"true\", /* true, false */\n\t\t\twrite_policy: \"writeback\", /* writeback, writethrough */\n\t\t\tline_size: 64, /* Bytes */\n\t\n\t\t\ticache: {\n\t\t\t\tsize: 32, /* KB */\n\t\t\t\tways: 4,\n\t\t\t\tlatency: 1,\n\t\t\t\teviction: \"lru\", /* lru, random */\n\t\t\t},\n\t\n\t\t\tdcache: {\n\t\t\t\tsize: 32, /* KB */\n\t\t\t\tways: 8,\n\t\t\t\tlatency: 1,\n\t\t\t\teviction: \"lru\", /* lru, random */\n\t\t\t},\n\t\n\t\t\tl2_shared_cache: {\n\t\t\t\tenable: \"true\",\n\t\t\t\tsize: 256, /* KB */\n\t\t\t\tways: 16,\n\t\t\t\tlatency: 5,\n\t\t\t\teviction: \"lru\", /* lru, random */\n\t\t\t},\n\t\t},\n\t},\n\n\tmemory: {\n\t\ttlb_size: 32,\n\n\t\t/* Memory controller burst-length in bytes */ \n\t\t/* Note: This is automatically set to cache line size if caches are enabled */\n\t\tburst_length: 64, /* Bytes */\n\n\t\tbase_dram_model: {\n\t\t\tmem_access_latency: 50,\n\t\t},\n\n\t\tdramsim3: {\n\t\t\tconfig_file: \"DRAMsim3/configs/DDR4_4Gb_x16_2400.ini\",\n\t\t},\n\n\t\tramulator: {\n\t\t\tconfig_file: \"ramulator/configs/DDR4-config.cfg\",\n\t\t},\n\t},\n}"
  },
  {
    "path": "configs/riscv64_outoforder_soc.cfg",
    "content": "/* VM configuration file */\n{\n\tversion: 1,\n\tmachine: \"riscv64\", /* riscv32, riscv64 */\n\tmemory_size: 2048, /* MB */\n\tbios: \"riscv64-unknown-linux-gnu/bbl64.bin\",\n\tkernel: \"riscv64-unknown-linux-gnu/kernel-riscv64.bin\",\n\tcmdline: \"console=hvc0 root=/dev/vda rw\",\n\tdrive0: { file: \"riscv64-unknown-linux-gnu/riscv64.img\" },\n\teth0: { driver: \"user\" },\n\n\tcore: {\n\t\tname: \"64-bit out-of-order riscv CPU\",\n\t\ttype: \"oocore\", /* incore, oocore */\n\t\tcpu_freq_mhz: 1000,\n\t\trtc_freq_mhz: 10,\n\n\t\tincore : {\n\t\t\tnum_cpu_stages: 5, /* 5, 6 */\n\t\t},\n\n\t\toocore: {\n\t\t\tiq_size: 16,\n\t\t\tiq_issue_ports: 3,\n\t\t\trob_size: 64,\n\t\t\trob_commit_ports:4,\n\t\t\tlsq_size: 16,\n\t\t},\n\n\t\t/* Note: Latencies for functional units, caches and memory are specified in CPU cycles */\n\t\tfunctional_units: {\n\t\t\tnum_alu_stages: 1,\n\t\t\talu_stage_latency: \"1\",\n\n\t\t\tnum_mul_stages: 1,\n\t\t\tmul_stage_latency: \"4\",\n\n\t\t\tnum_div_stages: 1,\n\t\t\tdiv_stage_latency: \"67\",\n\n\t\t\t/* Note: This will create a pipelined FP-FMA unit with 4 stages with a\n\t\t\t * latency of 1 CPU cycle(s) per stage */\n\t\t\tnum_fpu_fma_stages: 4,\n\t\t\tfpu_fma_stage_latency: \"1,1,1,1\",\n\n\t\t\t/* Note: FP-ALU is non-pipelined */\n\t\t\tfpu_alu_stage_latency: {\n\t\t\t\tfadd: 2,\n\t\t\t\tfsub: 2,\n\t\t\t\tfmul: 2,\n\t\t\t\tfdiv: 8,\n\t\t\t\tfsqrt: 8,\n\t\t\t\tfsgnj: 2,\n\t\t\t\tfmin: 4,\n\t\t\t\tfmax: 4,\n\t\t\t\tfeq: 2,\n\t\t\t\tflt: 2,\n\t\t\t\tfle: 2,\n\t\t\t\tcvt: 2,\n\t\t\t\tfcvt: 2,\n\t\t\t\tfmv: 2,\n\t\t\t\tfclass: 1,\n\t\t\t},\n\n\t\t\t/* Latency for RISC-V SYSTEM opcode instructions (includes CSR and privileged instructions)*/\n\t\t\tsystem_insn_latency: 3,\n\t\t},\n\n\t\tbpu: {\n\t\t\tenable: \"true\", /* true, false */\n\t\t\tflush_on_context_switch: \"false\", /* true, false */\n\n\t\t\tbtb: {\n\t\t\t\tsize: 32,\n\t\t\t\tways: 2,\n\t\t\t\teviction_policy: \"lru\", /* lru, random */\n\t\t\t},\n\n\t\t\tbpu_type: \"bimodal\", /* bimodal, adaptive */\n\n\t\t\tbimodal: {\n\t\t\t\tbht_size: 256,\n\t\t\t},\n\n\t\t\tadaptive: {\n\t\t\t\tght_size: 1,\n\t\t\t\tpht_size: 1,\n\t\t\t\thistory_bits: 2,\n\t\t\t\taliasing_func_type: \"xor\", /* xor, and, none */\n\n\t\t\t    /* Given config for adaptive predictor will create a Gshare predictor:\n\t\t\t\t*\t1) global history table consisting of one entry, entry includes a 2-bit history register\n\t\t\t\t*\t2) pattern history table consisting of one entry, entry includes an array of 4 saturating counters\n\t\t\t\t* \t3) value of history register will be `xor` ed with branch PC to index into the array of saturating counters\n\t\t\t\t*/\n\t\t\t},\n\n\t\t\tras_size: 6, /* value 0 disables RAS */\n\t\t},\n\n\t\tcaches: {\n\t\t\tenable_l1_caches: \"true\", /* true, false */\n\t\t\tallocate_on_write_miss: \"true\", /* true, false */\n\t\t\twrite_policy: \"writeback\", /* writeback, writethrough */\n\t\t\tline_size: 64, /* Bytes */\n\n\t\t\ticache: {\n\t\t\t\tsize: 32, /* KB */\n\t\t\t\tways: 4,\n\t\t\t\tlatency: 1,\n\t\t\t\teviction: \"lru\", /* lru, random */\n\t\t\t},\n\n\t\t\tdcache: {\n\t\t\t\tsize: 32, /* KB */\n\t\t\t\tways: 8,\n\t\t\t\tlatency: 1,\n\t\t\t\teviction: \"lru\", /* lru, random */\n\t\t\t},\n\n\t\t\tl2_shared_cache: {\n\t\t\t\tenable: \"true\",\n\t\t\t\tsize: 256, /* KB */\n\t\t\t\tways: 16,\n\t\t\t\tlatency: 5,\n\t\t\t\teviction: \"lru\", /* lru, random */\n\t\t\t},\n\t\t},\n\t},\n\n\tmemory: {\n\t\ttlb_size: 32,\n\n\t\t/* Memory controller burst-length in bytes */ \n\t\t/* Note: This is automatically set to cache line size if caches are enabled */\n\t\tburst_length: 64, /* Bytes */\n\n\t\tbase_dram_model: {\n\t\t\tmem_access_latency: 50,\n\t\t},\n\n\t\tdramsim3: {\n\t\t\tconfig_file: \"DRAMsim3/configs/DDR4_4Gb_x16_2400.ini\",\n\t\t},\n\n\t\tramulator: {\n\t\t\tconfig_file: \"ramulator/configs/DDR4-config.cfg\",\n\t\t},\n\t},\n}"
  },
  {
    "path": "src/DRAMsim3/.clang-format",
    "content": "---\nLanguage:        Cpp\n# BasedOnStyle:  Google\nAccessModifierOffset: -1\nAlignAfterOpenBracket: Align\nAlignConsecutiveAssignments: false\nAlignConsecutiveDeclarations: false\nAlignEscapedNewlines: Left\nAlignOperands:   true\nAlignTrailingComments: true\nAllowAllParametersOfDeclarationOnNextLine: true\nAllowShortBlocksOnASingleLine: false\nAllowShortCaseLabelsOnASingleLine: false\nAllowShortFunctionsOnASingleLine: All\nAllowShortIfStatementsOnASingleLine: true\nAllowShortLoopsOnASingleLine: true\nAlwaysBreakAfterDefinitionReturnType: None\nAlwaysBreakAfterReturnType: None\nAlwaysBreakBeforeMultilineStrings: true\nAlwaysBreakTemplateDeclarations: true\nBinPackArguments: true\nBinPackParameters: true\nBraceWrapping:   \n  AfterClass:      false\n  AfterControlStatement: false\n  AfterEnum:       false\n  AfterFunction:   false\n  AfterNamespace:  false\n  AfterObjCDeclaration: false\n  AfterStruct:     false\n  AfterUnion:      false\n  AfterExternBlock: false\n  BeforeCatch:     false\n  BeforeElse:      false\n  IndentBraces:    false\n  SplitEmptyFunction: true\n  SplitEmptyRecord: true\n  SplitEmptyNamespace: true\nBreakBeforeBinaryOperators: None\nBreakBeforeBraces: Attach\nBreakBeforeInheritanceComma: false\nBreakBeforeTernaryOperators: true\nBreakConstructorInitializersBeforeComma: false\nBreakConstructorInitializers: BeforeColon\nBreakAfterJavaFieldAnnotations: false\nBreakStringLiterals: true\nColumnLimit:     80\nCommentPragmas:  '^ IWYU pragma:'\nCompactNamespaces: false\nConstructorInitializerAllOnOneLineOrOnePerLine: true\nConstructorInitializerIndentWidth: 4\nContinuationIndentWidth: 4\nCpp11BracedListStyle: true\nDerivePointerAlignment: true\nDisableFormat:   false\nExperimentalAutoDetectBinPacking: false\nFixNamespaceComments: true\nForEachMacros:   \n  - foreach\n  - Q_FOREACH\n  - BOOST_FOREACH\nIncludeBlocks:   Preserve\nIncludeCategories: \n  - Regex:           '^<ext/.*\\.h>'\n    Priority:        2\n  - Regex:           '^<.*\\.h>'\n    Priority:        1\n  - Regex:           '^<.*'\n    Priority:        2\n  - Regex:           '.*'\n    Priority:        3\nIncludeIsMainRegex: '([-_](test|unittest))?$'\nIndentCaseLabels: true\nIndentPPDirectives: None\nIndentWidth:     4\nIndentWrappedFunctionNames: false\nJavaScriptQuotes: Leave\nJavaScriptWrapImports: true\nKeepEmptyLinesAtTheStartOfBlocks: false\nMacroBlockBegin: ''\nMacroBlockEnd:   ''\nMaxEmptyLinesToKeep: 1\nNamespaceIndentation: None\nObjCBlockIndentWidth: 2\nObjCSpaceAfterProperty: false\nObjCSpaceBeforeProtocolList: false\nPenaltyBreakAssignment: 2\nPenaltyBreakBeforeFirstCallParameter: 1\nPenaltyBreakComment: 300\nPenaltyBreakFirstLessLess: 120\nPenaltyBreakString: 1000\nPenaltyExcessCharacter: 1000000\nPenaltyReturnTypeOnItsOwnLine: 200\nPointerAlignment: Left\nRawStringFormats: \n  - Delimiter:       pb\n    Language:        TextProto\n    BasedOnStyle:    google\nReflowComments:  true\nSortIncludes:    true\nSortUsingDeclarations: true\nSpaceAfterCStyleCast: false\nSpaceAfterTemplateKeyword: true\nSpaceBeforeAssignmentOperators: true\nSpaceBeforeParens: ControlStatements\nSpaceInEmptyParentheses: false\nSpacesBeforeTrailingComments: 2\nSpacesInAngles:  false\nSpacesInContainerLiterals: true\nSpacesInCStyleCastParentheses: false\nSpacesInParentheses: false\nSpacesInSquareBrackets: false\nStandard:        Auto\nTabWidth:        8\nUseTab:          Never\n...\n\n"
  },
  {
    "path": "src/DRAMsim3/.gitignore",
    "content": "# project files\nbuild/\ndebug_build/\ndata/\next/SuperLU_MT_3.1/\nobj\ndramsim3\ndramsim3test\ndramsim3main\n*.log\nrelease\n.idea\n*.pyc\n*.vh\n.vs/\n\n# Compiled Object files\n*.slo\n*.lo\n*.o\n*.obj\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Compiled Dynamic libraries\n*.so\n*.dylib\n*.dll\n\n# Fortran module files\n*.mod\n*.smod\n\n# Compiled Static libraries\n*.lai\n*.la\n*.a\n*.lib\n\n# Executables\n*.exe\n*.out\n*.app\n\n# IDEs / Editors\n.vscode/\n"
  },
  {
    "path": "src/DRAMsim3/.gitmodules",
    "content": "[submodule \"ext/SuperLU_MT_3.1\"]\n\tpath = ext/SuperLU_MT_3.1\n\turl = https://github.com/umd-memsys/SuperLU_MT_3.1.git\n\tignore = dirty\n"
  },
  {
    "path": "src/DRAMsim3/.travis.yml",
    "content": "dist: trusty\n#sudo: required\nsudo: false\n\nlanguage: cpp\nwarnings_are_errors: true\n\ncompiler:\n# - gcc\n - clang\n\n#addons:\n#  apt:\n#    packages:\n#      - gcc-4.9\n#      - clang-3.5\n#      - cmake\n\nscript:\n  - mkdir build\n  - cd build\n  - cmake ..\n  - make -j4\n"
  },
  {
    "path": "src/DRAMsim3/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.0.0)\nproject(dramsim3)\n\nset(default_build_type \"Release\")\nif(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)\n  message(STATUS \"Setting build type to '${default_build_type}' as none was specified.\")\n  set(CMAKE_BUILD_TYPE \"${default_build_type}\" CACHE\n      STRING \"Choose the type of build.\" FORCE)\n  # Set the possible values of build type for cmake-gui\n  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS\n    \"Debug\" \"Release\" \"MinSizeRel\" \"RelWithDebInfo\")\nendif()\n\nadd_library(inih INTERFACE)\ntarget_include_directories(inih INTERFACE ext/headers)\n\nadd_library(format INTERFACE)\ntarget_include_directories(format INTERFACE ext/fmt/include)\ntarget_compile_definitions(format INTERFACE FMT_HEADER_ONLY=1)\n\n# argparsing library, only used in main program not the library\nadd_library(args INTERFACE)\ntarget_include_directories(args INTERFACE ext/headers)\n\nadd_library(json INTERFACE)\ntarget_include_directories(json INTERFACE ext/headers)\n\n# Main DRAMSim Lib\nadd_library(dramsim3 SHARED\n    src/bankstate.cc\n    src/channel_state.cc\n    src/command_queue.cc\n    src/common.cc\n    src/configuration.cc\n    src/controller.cc\n    src/dram_system.cc\n    src/hmc.cc\n    src/refresh.cc\n    src/simple_stats.cc\n    src/timing.cc\n    src/memory_system.cc\n)\n\nif (THERMAL)\n    # dependency check\n    # sudo apt-get install libatlas-base-dev on ubuntu\n    find_package(BLAS REQUIRED)\n    find_package(OpenMP REQUIRED)\n    # YOU need to build superlu on your own. Do the following:\n    # git submodule update --init\n    # cd ext/SuperLU_MT_3.1 && make lib\n    find_library(SUPERLU\n        NAME superlu_mt_OPENMP libsuperlu_mt_OPENMP\n        HINTS ${PROJECT_SOURCE_DIR}/ext/SuperLU_MT_3.1/lib/\n    )\n\n    target_link_libraries(dramsim3\n        PRIVATE ${SUPERLU} f77blas atlas m ${OpenMP_C_FLAGS}\n    )\n    target_sources(dramsim3\n        PRIVATE src/thermal.cc src/sp_ienv.c src/thermal_solver.c\n    )\n    target_compile_options(dramsim3 PRIVATE -DTHERMAL -D_LONGINT -DAdd_ ${OpenMP_C_FLAGS})\n\n    add_executable(thermalreplay src/thermal_replay.cc)\n    target_link_libraries(thermalreplay dramsim3 inih)\n    target_compile_options(thermalreplay PRIVATE -DTHERMAL -D_LONGINT -DAdd_ ${OpenMP_C_FLAGS})\nendif (THERMAL)\n\nif (CMD_TRACE)\n    target_compile_options(dramsim3 PRIVATE -DCMD_TRACE)\nendif (CMD_TRACE)\n\nif (ADDR_TRACE)\n    target_compile_options(dramsim3 PRIVATE -DADDR_TRACE)\nendif (ADDR_TRACE)\n\n\ntarget_include_directories(dramsim3 INTERFACE src)\ntarget_compile_options(dramsim3 PRIVATE -Wall)\ntarget_link_libraries(dramsim3 PRIVATE inih format)\nset_target_properties(dramsim3 PROPERTIES\n    LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}\n    CXX_STANDARD 11\n    CXX_STANDARD_REQUIRED YES\n    CXX_EXTENSIONS NO\n)\n\n# trace CPU, .etc\nadd_executable(dramsim3main src/main.cc src/cpu.cc)\ntarget_link_libraries(dramsim3main PRIVATE dramsim3 args)\ntarget_compile_options(dramsim3main PRIVATE)\nset_target_properties(dramsim3main PROPERTIES\n    CXX_STANDARD 11\n    CXX_STANDARD_REQUIRED YES\n    CXX_EXTENSIONS NO\n)\n\n# Unit testing\nadd_library(Catch INTERFACE)\ntarget_include_directories(Catch INTERFACE ext/headers)\n\nadd_executable(dramsim3test EXCLUDE_FROM_ALL\n    tests/test_config.cc\n    tests/test_dramsys.cc\n    tests/test_hmcsys.cc # IDK somehow this can literally crush your computer\n)\ntarget_link_libraries(dramsim3test Catch dramsim3)\ntarget_include_directories(dramsim3test PRIVATE src/)\n\n# We have to use this custome command because there's a bug in cmake\n# that if you do `make test` it doesn't build your updated test files\n# so we're stucking with `make dramsim3test` for now\nadd_custom_command(\n    TARGET dramsim3test POST_BUILD\n    COMMAND dramsim3test\n    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}\n    DEPENDS dramsim3test dramsim3\n)\n"
  },
  {
    "path": "src/DRAMsim3/LICENSE",
    "content": "Copyright (c) 2019, University of Maryland Memory-Systems Research\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "src/DRAMsim3/Makefile",
    "content": "# ONLY use this makefile if you do NOT have a cmake 3.0+ version\n\nCC=gcc\nCXX=g++\n\nFMT_LIB_DIR=ext/fmt/include\nINI_LIB_DIR=ext/headers\nJSON_LIB_DIR=ext/headers\nARGS_LIB_DIR=ext/headers\n\nINC=-Isrc/ -I$(FMT_LIB_DIR) -I$(INI_LIB_DIR) -I$(ARGS_LIB_DIR) -I$(JSON_LIB_DIR)\nCXXFLAGS=-Wall -O2 -fPIC -std=c++11 $(INC) -DFMT_HEADER_ONLY=1\n\nLIB_NAME=libdramsim3.so\nEXE_NAME=dramsim3main.out\nSTATIC_LIB_NAME=libdramsim3.a\n\nSRCS = src/bankstate.cc src/channel_state.cc src/command_queue.cc src/common.cc \\\n\t\tsrc/configuration.cc src/controller.cc src/dram_system.cc src/hmc.cc \\\n\t\tsrc/memory_system.cc src/refresh.cc src/simple_stats.cc src/timing.cc\n\nEXE_SRCS = src/cpu.cc src/main.cc\n\nOBJECTS = $(addsuffix .o, $(basename $(SRCS)))\nEXE_OBJS = $(addsuffix .o, $(basename $(EXE_SRCS)))\nEXE_OBJS := $(EXE_OBJS) $(OBJECTS)\n\n\nall: $(LIB_NAME) $(EXE_NAME)\n\n$(EXE_NAME): $(EXE_OBJS)\n\t$(CXX) $(CXXFLAGS) -o $@ $^\n\n$(LIB_NAME): $(OBJECTS)\n\t$(CXX) -g -shared -Wl,-soname,$@ -o $@ $^\n\n$(STATIC_LIB_NAME): $(OBJECTS)\n\t$(AR) rcs  $@ $(OBJECTS)\n\n%.o : %.cc\n\t$(CXX)  $(CXXFLAGS) -o $@ -c $<\n\n%.o : %.c\n\t$(CC) -fPIC -O2 -o $@ -c $<\n\nclean:\n\t-rm -f $(EXE_OBJS) $(LIB_NAME) $(EXE_NAME)"
  },
  {
    "path": "src/DRAMsim3/README.md",
    "content": "[![Build Status](https://travis-ci.com/umd-memsys/DRAMsim3.svg?branch=master)](https://travis-ci.com/umd-memsys/DRAMsim3)\n\n# About DRAMsim3\n\nDRAMsim3 models the timing paramaters and memory controller behavior for several DRAM protocols such as DDR3, DDR4, LPDDR3, LPDDR4, GDDR5, GDDR6, HBM, HMC, STT-MRAM. It is implemented in C++ as an objected oriented model that includes a parameterized DRAM bank model, DRAM controllers, command queues and system-level interfaces to interact with a CPU simulator (GEM5, ZSim) or trace workloads. It is designed to be accurate, portable and parallel.\n    \nIf you use this simulator in your work, please consider cite:\n\n[1] S. Li, Z. Yang, D. Reddy, A. Srivastava and B. Jacob, \"DRAMsim3: a Cycle-accurate, Thermal-Capable DRAM Simulator,\" in IEEE Computer Architecture Letters. [Link](https://ieeexplore.ieee.org/document/8999595)\n\nSee [Related Work](#related-work) for more work done with this simulator.\n\n\n## Building and running the simulator\n\nThis simulator by default uses a CMake based build system.\nThe advantage in using a CMake based build system is portability and dependency management.\nWe require CMake 3.0+ to build this simulator.\nIf `cmake-3.0` is not available,\nwe also supply a Makefile to build the most basic version of the simulator.\n\n### Building\n\nDoing out of source builds with CMake is recommended to avoid the build files cluttering the main directory.\n\n```bash\n# cmake out of source build\nmkdir build\ncd build\ncmake ..\n\n# Build dramsim3 library and executables\nmake -j4\n\n# Alternatively, build with thermal module enabled\ncmake .. -DTHERMAL=1\n\n```\n\nThe build process creates `dramsim3main` and executables in the `build` directory.\nBy default, it also creates `libdramsim3.so` shared library in the project root directory.\n\n### Running\n\n```bash\n# help\n./build/dramsim3main -h\n\n# Running random stream with a config file\n./build/dramsim3main configs/DDR4_8Gb_x8_3200.ini --stream random -c 100000 \n\n# Running a trace file\n./build/dramsim3main configs/DDR4_8Gb_x8_3200.ini -c 100000 -t sample_trace.txt\n\n# Running with gem5\n--mem-type=dramsim3 --dramsim3-ini=configs/DDR4_4Gb_x4_2133.ini\n\n```\n\nThe output can be directed to another directory by `-o` option\nor can be configured in the config file.\nYou can control the verbosity in the config file as well.\n\n### Output Visualization\n\n`scripts/plot_stats.py` can visualize some of the output (requires `matplotlib`):\n\n```bash\n# generate histograms from overall output\npython3 scripts/plot_stats dramsim3.json\n\n# or\n# generate time series for a variety stats from epoch outputs\npython3 scripts/plot_stats dramsim3epoch.json\n```\n\nCurrently stats from all channels are squashed together for cleaner plotting.\n\n### Integration with other simulators\n\n**Gem5** integration: works with a forked Gem5 version, see https://github.com/umd-memsys/gem5 at `dramsim3` branch for reference.\n\n**SST** integration: see http://git.ece.umd.edu/shangli/sst-elements/tree/dramsim3 for reference. We will try to merge to official SST repo.\n\n**ZSim** integration: see http://git.ece.umd.edu/shangli/zsim/tree/master for reference.\n\n## Simulator Design\n\n### Code Structure\n\n```\n├── configs                 # Configs of various protocols that describe timing constraints and power consumption.\n├── ext                     # \n├── scripts                 # Tools and utilities\n├── src                     # DRAMsim3 source files\n├── tests                   # Tests of each model, includes a short example trace\n├── CMakeLists.txt\n├── Makefile\n├── LICENSE\n└── README.md\n\n├── src  \n    bankstate.cc: Records and manages DRAM bank timings and states which is modeled as a state machine.\n    channelstate.cc: Records and manages channel timings and states.\n    command_queue.cc: Maintains per-bank or per-rank FIFO queueing structures, determine which commands in the queues can be issued in this cycle.\n    configuration.cc: Initiates, manages system and DRAM parameters, including protocol, DRAM timings, address mapping policy and power parameters.\n    controller.cc: Maintains the per-channel controller, which manages a queue of pending memory transactions and issues corresponding DRAM commands, \n                   follows FR-FCFS policy.\n    cpu.cc: Implements 3 types of simple CPU: \n            1. Random, can handle random CPU requests at full speed, the entire parallelism of DRAM protocol can be exploited without limits from address mapping and scheduling pocilies. \n            2. Stream, provides a streaming prototype that is able to provide enough buffer hits.\n            3. Trace-based, consumes traces of workloads, feed the fetched transactions into the memory system.\n    dram_system.cc:  Initiates JEDEC or ideal DRAM system, registers the supplied callback function to let the front end driver know that the request is finished. \n    hmc.cc: Implements HMC system and interface, HMC requests are translates to DRAM requests here and a crossbar interconnect between the high-speed links and the memory controllers is modeled.\n    main.cc: Handles the main program loop that reads in simulation arguments, DRAM configurations and tick cycle forward.\n    memory_system.cc: A wrapper of dram_system and hmc.\n    refresh.cc: Raises refresh request based on per-rank refresh or per-bank refresh.\n    timing.cc: Initiate timing constraints.\n```\n\n## Experiments\n\n### Verilog Validation\n\nFirst we generate a DRAM command trace.\nThere is a `CMD_TRACE` macro and by default it's disabled.\nUse `cmake .. -DCMD_TRACE=1` to enable the command trace output build and then\nwhenever a simulation is performed the command trace file will be generated.\n\nNext, `scripts/validation.py` helps generate a Verilog workbench for Micron's Verilog model\nfrom the command trace file.\nCurrently DDR3, DDR4, and LPDDR configs are supported by this script.\n\nRun\n\n```bash\n./script/validataion.py DDR4.ini cmd.trace\n```\n\nTo generage Verilog workbench.\nOur workbench format is compatible with ModelSim Verilog simulator,\nother Verilog simulators may require a slightly different format.\n\n\n## Related Work\n\n[1] Li, S., Yang, Z., Reddy D., Srivastava, A. and Jacob, B., (2020) DRAMsim3: a Cycle-accurate, Thermal-Capable DRAM Simulator, IEEE Computer Architecture Letters.\n\n[2] Jagasivamani, M., Walden, C., Singh, D., Kang, L., Li, S., Asnaashari, M., ... & Yeung, D. (2019). Analyzing the Monolithic Integration of a ReRAM-Based Main Memory Into a CPU's Die. IEEE Micro, 39(6), 64-72.\n\n[3] Li, S., Reddy, D., & Jacob, B. (2018, October). A performance & power comparison of modern high-speed DRAM architectures. In Proceedings of the International Symposium on Memory Systems (pp. 341-353).\n\n[4] Li, S., Verdejo, R. S., Radojković, P., & Jacob, B. (2019, September). Rethinking cycle accurate DRAM simulation. In Proceedings of the International Symposium on Memory Systems (pp. 184-191).\n\n[5] Li, S., & Jacob, B. (2019, September). Statistical DRAM modeling. In Proceedings of the International Symposium on Memory Systems (pp. 521-530).\n\n[6] Li, S. (2019). Scalable and Accurate Memory System Simulation (Doctoral dissertation).\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_1Gb_x8_1333.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 16384\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 1.5\nAL = 0\nCL = 10\nCWL = 7\ntRCD = 10\ntRP = 10\ntRAS = 24\ntRFC = 74\ntREFI = 5200\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntWTR_S = 5\ntFAW = 20\ntWR = 10\ntCCD_S = 4\ntRTP = 5\ntCKE = 4\ntCKESR = 1\ntXS = 81\ntXP = 5\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 33\nIDD2P = 12\nIDD2N = 17\nIDD3P = 14\nIDD3N = 23\nIDD4W = 77\nIDD4R = 72\nIDD5AB = 155\nIDD6x = 12\n\n[system]\nchannel_size = 2048\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\ntrans_queue_size = 32\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\n\n[other]\nepoch_period = 666666\noutput_level = 1\n\n[thermal]\nloc_mapping = 30,30,30,29:27,26:13,12:3\npower_epoch_period = 10000; power epoch period (# cycle)\nchip_dim_x = 0.008; chip size in x dimension [m]\nchip_dim_y = 0.008; chip size in y dimension [m]\namb_temp = 40; The ambient temperature in [C]\nmat_dim_x = 512;\nmat_dim_y = 512;\nbank_order = 1; 0: x direction first, 1: y direction first\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_4Gb_x16_1600.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 32768\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 1.25\nAL = 0\nCL = 11\nCWL = 8\ntRCD = 11\ntRP = 11\ntRAS = 28\ntRFC = 208\ntRFC2 = 208\ntRFC4 = 208\nREFI = 6240\ntRPRE = 0\ntWPRE = 0\ntRRD_S = 5\ntRRD_L = 5\ntWTR_S = 6\ntWTR_L = 6\ntFAW = 32\ntWR = 12\ntWR2 = 12\ntRTP = 6\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 4\ntCKESR = 5\ntXS = 216\ntXP = 5\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 66\nIPP0 = 0.0\nIDD2P = 18\nIDD2N = 32\nIDD3P = 38\nIDD3N = 47\nIDD4W = 171\nIDD4R = 235\nIDD5AB = 235\nIDD6x = 20\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 800000\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_4Gb_x16_1866.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 32768\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 13\nCWL = 9\ntRCD = 13\ntRP = 13\ntRAS = 32\ntRFC = 243\ntRFC2 = 243\ntRFC4 = 243\nREFI = 7290\ntRPRE = 0\ntWPRE = 0\ntRRD_S = 6\ntRRD_L = 6\ntWTR_S = 7\ntWTR_L = 7\ntFAW = 33\ntWR = 15\ntWR2 = 15\ntRTP = 7\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 5\ntCKESR = 6\ntXS = 253\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 73\nIPP0 = 0.0\nIDD2P = 18\nIDD2N = 35\nIDD3P = 41\nIDD3N = 49\nIDD4W = 190\nIDD4R = 252\nIDD5AB = 242\nIDD6x = 20\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_4Gb_x4_1600.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 65536\ncolumns = 2048\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 1.25\nAL = 0\nCL = 11\nCWL = 8\ntRCD = 11\ntRP = 11\ntRAS = 28\ntRFC = 208\ntRFC2 = 208\ntRFC4 = 208\nREFI = 6240\ntRPRE = 0\ntWPRE = 0\ntRRD_S = 5\ntRRD_L = 5\ntWTR_S = 6\ntWTR_L = 6\ntFAW = 24\ntWR = 12\ntWR2 = 12\ntRTP = 6\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 4\ntCKESR = 5\ntXS = 216\ntXP = 5\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 55\nIPP0 = 0.0\nIDD2P = 18\nIDD2N = 32\nIDD3P = 38\nIDD3N = 38\nIDD4W = 118\nIDD4R = 147\nIDD5AB = 235\nIDD6x = 20\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 800000\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_4Gb_x4_1866.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 65536\ncolumns = 2048\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 13\nCWL = 9\ntRCD = 13\ntRP = 13\ntRAS = 32\ntRFC = 243\ntRFC2 = 243\ntRFC4 = 243\nREFI = 7290\ntRPRE = 0\ntWPRE = 0\ntRRD_S = 5\ntRRD_L = 5\ntWTR_S = 7\ntWTR_L = 7\ntFAW = 26\ntWR = 15\ntWR2 = 15\ntRTP = 6\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 5\ntCKESR = 6\ntXS = 253\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 62\nIPP0 = 0.0\nIDD2P = 18\nIDD2N = 35\nIDD3P = 41\nIDD3N = 41\nIDD4W = 133\nIDD4R = 164\nIDD5AB = 242\nIDD6x = 20\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_4Gb_x8_1600.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 1.25\nAL = 0\nCL = 11\nCWL = 8\ntRCD = 11\ntRP = 11\ntRAS = 28\ntRFC = 208\ntRFC2 = 208\ntRFC4 = 208\nREFI = 6240\ntRPRE = 0\ntWPRE = 0\ntRRD_S = 5\ntRRD_L = 5\ntWTR_S = 6\ntWTR_L = 6\ntFAW = 24\ntWR = 12\ntWR2 = 12\ntRTP = 6\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 4\ntCKESR = 5\ntXS = 216\ntXP = 5\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 55\nIPP0 = 0.0\nIDD2P = 18\nIDD2N = 32\nIDD3P = 38\nIDD3N = 38\nIDD4W = 125\nIDD4R = 157\nIDD5AB = 235\nIDD6x = 20\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 800000\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_4Gb_x8_1866.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 13\nCWL = 9\ntRCD = 13\ntRP = 13\ntRAS = 32\ntRFC = 243\ntRFC2 = 243\ntRFC4 = 243\nREFI = 7290\ntRPRE = 0\ntWPRE = 0\ntRRD_S = 5\ntRRD_L = 5\ntWTR_S = 7\ntWTR_L = 7\ntFAW = 26\ntWR = 15\ntWR2 = 15\ntRTP = 6\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 5\ntCKESR = 6\ntXS = 253\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 62\nIPP0 = 0.0\nIDD2P = 18\nIDD2N = 35\nIDD3P = 41\nIDD3N = 41\nIDD4W = 141\nIDD4R = 174\nIDD5AB = 242\nIDD6x = 20\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_8Gb_x16_1600.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 1.25\nAL = 0\nCL = 11\nCWL = 8\ntRCD = 11\ntRP = 11\ntRAS = 28\ntRFC = 280\ntRFC2 = 280\ntRFC4 = 280\nREFI = 6240\ntRPRE = 0\ntWPRE = 0\ntRRD_S = 6\ntRRD_L = 6\ntWTR_S = 6\ntWTR_L = 6\ntFAW = 32\ntWR = 12\ntWR2 = 12\ntRTP = 6\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 4\ntCKESR = 5\ntXS = 288\ntXP = 5\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 67\nIPP0 = 0.0\nIDD2P = 11\nIDD2N = 36\nIDD3P = 36\nIDD3N = 51\nIDD4W = 185\nIDD4R = 185\nIDD5AB = 270\nIDD6x = 24\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 800000\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_8Gb_x16_1866.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 13\nCWL = 9\ntRCD = 13\ntRP = 13\ntRAS = 32\ntRFC = 328\ntRFC2 = 328\ntRFC4 = 328\nREFI = 7290\ntRPRE = 0\ntWPRE = 0\ntRRD_S = 6\ntRRD_L = 6\ntWTR_S = 7\ntWTR_L = 7\ntFAW = 33\ntWR = 15\ntWR2 = 15\ntRTP = 7\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 5\ntCKESR = 6\ntXS = 338\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 69\nIPP0 = 0.0\nIDD2P = 11\nIDD2N = 38\nIDD3P = 38\nIDD3N = 53\nIDD4W = 195\nIDD4R = 195\nIDD5AB = 275\nIDD6x = 24\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_8Gb_x4_1600.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 65536\ncolumns = 4096\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 1.25\nAL = 0\nCL = 11\nCWL = 8\ntRCD = 11\ntRP = 11\ntRAS = 28\ntRFC = 280\ntRFC2 = 280\ntRFC4 = 280\nREFI = 6240\ntRPRE = 0\ntWPRE = 0\ntRRD_S = 6\ntRRD_L = 6\ntWTR_S = 6\ntWTR_L = 6\ntFAW = 32\ntWR = 12\ntWR2 = 12\ntRTP = 6\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 4\ntCKESR = 5\ntXS = 288\ntXP = 5\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 67\nIPP0 = 0.0\nIDD2P = 11\nIDD2N = 36\nIDD3P = 36\nIDD3N = 51\nIDD4W = 125\nIDD4R = 125\nIDD5AB = 245\nIDD6x = 24\n\n[system]\nchannel_size = 32768\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 800000\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_8Gb_x4_1866.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 65536\ncolumns = 4096\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 13\nCWL = 9\ntRCD = 13\ntRP = 13\ntRAS = 32\ntRFC = 328\ntRFC2 = 328\ntRFC4 = 328\nREFI = 7290\ntRPRE = 0\ntWPRE = 0\ntRRD_S = 6\ntRRD_L = 6\ntWTR_S = 7\ntWTR_L = 7\ntFAW = 33\ntWR = 15\ntWR2 = 15\ntRTP = 7\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 5\ntCKESR = 6\ntXS = 338\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 69\nIPP0 = 0.0\nIDD2P = 11\nIDD2N = 38\nIDD3P = 38\nIDD3N = 53\nIDD4W = 135\nIDD4R = 135\nIDD5AB = 250\nIDD6x = 24\n\n[system]\nchannel_size = 32768\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_8Gb_x8_1600.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 65536\ncolumns = 2048\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 1.25\nAL = 0\nCL = 11\nCWL = 8\ntRCD = 11\ntRP = 11\ntRAS = 28\ntRFC = 280\ntRFC2 = 280\ntRFC4 = 280\nREFI = 6240\ntRPRE = 0\ntWPRE = 0\ntRRD_S = 6\ntRRD_L = 6\ntWTR_S = 6\ntWTR_L = 6\ntFAW = 32\ntWR = 12\ntWR2 = 12\ntRTP = 6\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 4\ntCKESR = 5\ntXS = 288\ntXP = 5\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 67\nIPP0 = 0.0\nIDD2P = 11\nIDD2N = 36\nIDD3P = 36\nIDD3N = 51\nIDD4W = 125\nIDD4R = 125\nIDD5AB = 245\nIDD6x = 24\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 800000\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR3_8Gb_x8_1866.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 65536\ncolumns = 2048\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 13\nCWL = 9\ntRCD = 13\ntRP = 13\ntRAS = 32\ntRFC = 328\ntRFC2 = 328\ntRFC4 = 328\nREFI = 7290\ntRPRE = 0\ntWPRE = 0\ntRRD_S = 6\ntRRD_L = 6\ntWTR_S = 7\ntWTR_L = 7\ntFAW = 33\ntWR = 15\ntWR2 = 15\ntRTP = 7\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 5\ntCKESR = 6\ntXS = 338\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 69\nIPP0 = 0.0\nIDD2P = 11\nIDD2N = 38\nIDD3P = 38\nIDD3N = 53\nIDD4W = 135\nIDD4R = 135\nIDD5AB = 250\nIDD6x = 24\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x16_1866.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 13\nCWL = 10\ntRCD = 13\ntRP = 13\ntRAS = 32\ntRFC = 243\ntRFC2 = 150\ntRFC4 = 103\ntREFI = 7285\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 5\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 7\ntFAW = 28\ntWR = 14\ntWR2 = 15\ntRTP = 7\ntCCD_S = 4\ntCCD_L = 5\ntCKE = 5\ntCKESR = 6\ntXS = 253\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 65\nIPP0 = 3.6\nIDD2P = 27\nIDD2N = 40\nIDD3P = 40\nIDD3N = 55\nIDD4W = 220\nIDD4R = 180\nIDD5AB = 170\nIDD6x = 20\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x16_2133.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.94\nAL = 0\nCL = 16\nCWL = 11\ntRCD = 16\ntRP = 16\ntRAS = 36\ntRFC = 278\ntRFC2 = 171\ntRFC4 = 118\ntREFI = 8328\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 6\ntRRD_L = 7\ntWTR_S = 3\ntWTR_L = 8\ntFAW = 32\ntWR = 16\ntWR2 = 17\ntRTP = 8\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 289\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 65\nIPP0 = 3.6\nIDD2P = 27\nIDD2N = 42\nIDD3P = 40\nIDD3N = 55\nIDD4W = 250\nIDD4R = 195\nIDD5AB = 170\nIDD6x = 20\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1063829\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x16_2133_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.94\nAL = 0\nCL = 15\nCWL = 11\ntRCD = 15\ntRP = 15\ntRAS = 36\ntRFC = 278\ntRFC2 = 171\ntRFC4 = 118\ntREFI = 8328\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 6\ntRRD_L = 7\ntWTR_S = 3\ntWTR_L = 8\ntFAW = 32\ntWR = 16\ntWR2 = 17\ntRTP = 8\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 289\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 65\nIPP0 = 3.6\nIDD2P = 27\nIDD2N = 42\nIDD3P = 40\nIDD3N = 55\nIDD4W = 250\nIDD4R = 195\nIDD5AB = 170\nIDD6x = 20\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1063829\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x16_2400.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 17\nCWL = 12\ntRCD = 17\ntRP = 17\ntRAS = 39\ntRFC = 312\ntRFC2 = 192\ntRFC4 = 132\ntREFI = 9360\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 7\ntRRD_L = 8\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 36\ntWR = 18\ntWR2 = 19\ntRTP = 9\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 324\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 65\nIPP0 = 3.6\nIDD2P = 29\nIDD2N = 45\nIDD3P = 40\nIDD3N = 60\nIDD4W = 285\nIDD4R = 205\nIDD5AB = 175\nIDD6x = 20\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1204819\noutput_level = 0\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x16_2400_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 16\nCWL = 12\ntRCD = 16\ntRP = 16\ntRAS = 39\ntRFC = 312\ntRFC2 = 192\ntRFC4 = 132\ntREFI = 9360\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 7\ntRRD_L = 8\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 36\ntWR = 18\ntWR2 = 19\ntRTP = 9\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 324\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 65\nIPP0 = 3.6\nIDD2P = 29\nIDD2N = 45\nIDD3P = 40\nIDD3N = 60\nIDD4W = 285\nIDD4R = 205\nIDD5AB = 175\nIDD6x = 20\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1204819\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x16_2666.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.75\nAL = 0\nCL = 19\nCWL = 14\ntRCD = 19\ntRP = 19\ntRAS = 43\ntRFC = 347\ntRFC2 = 214\ntRFC4 = 147\ntREFI = 10398\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 7\ntRRD_L = 9\ntWTR_S = 4\ntWTR_L = 10\ntFAW = 40\ntWR = 20\ntWR2 = 21\ntRTP = 10\ntCCD_S = 4\ntCCD_L = 7\ntCKE = 7\ntCKESR = 8\ntXS = 360\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 70\nIPP0 = 3.6\nIDD2P = 34\nIDD2N = 50\nIDD3P = 40\nIDD3N = 65\nIDD4W = 310\nIDD4R = 225\nIDD5AB = 175\nIDD6x = 20\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1333333\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x16_2666_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.75\nAL = 0\nCL = 18\nCWL = 14\ntRCD = 18\ntRP = 18\ntRAS = 43\ntRFC = 347\ntRFC2 = 214\ntRFC4 = 147\ntREFI = 10398\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 7\ntRRD_L = 9\ntWTR_S = 4\ntWTR_L = 10\ntFAW = 40\ntWR = 20\ntWR2 = 21\ntRTP = 10\ntCCD_S = 4\ntCCD_L = 7\ntCKE = 7\ntCKESR = 8\ntXS = 360\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 70\nIPP0 = 3.6\nIDD2P = 34\nIDD2N = 50\nIDD3P = 40\nIDD3N = 65\nIDD4W = 310\nIDD4R = 225\nIDD5AB = 175\nIDD6x = 20\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1333333\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x4_1866.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 13\nCWL = 10\ntRCD = 13\ntRP = 13\ntRAS = 32\ntRFC = 243\ntRFC2 = 150\ntRFC4 = 103\ntREFI = 7285\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 5\ntWTR_S = 3\ntWTR_L = 7\ntFAW = 16\ntWR = 14\ntWR2 = 15\ntRTP = 7\ntCCD_S = 4\ntCCD_L = 5\ntCKE = 5\ntCKESR = 6\ntXS = 253\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 55\nIPP0 = 3.0\nIDD2P = 27\nIDD2N = 40\nIDD3P = 40\nIDD3N = 55\nIDD4W = 140\nIDD4R = 125\nIDD5AB = 170\nIDD6x = 20\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x4_2133.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.94\nAL = 0\nCL = 16\nCWL = 11\ntRCD = 16\ntRP = 16\ntRAS = 36\ntRFC = 278\ntRFC2 = 171\ntRFC4 = 118\ntREFI = 8328\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 8\ntFAW = 16\ntWR = 16\ntWR2 = 17\ntRTP = 8\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 289\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 55\nIPP0 = 3.0\nIDD2P = 27\nIDD2N = 42\nIDD3P = 40\nIDD3N = 55\nIDD4W = 155\nIDD4R = 135\nIDD5AB = 170\nIDD6x = 20\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1063829\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x4_2133_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.94\nAL = 0\nCL = 15\nCWL = 11\ntRCD = 15\ntRP = 15\ntRAS = 36\ntRFC = 278\ntRFC2 = 171\ntRFC4 = 118\ntREFI = 8328\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 8\ntFAW = 16\ntWR = 16\ntWR2 = 17\ntRTP = 8\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 289\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 55\nIPP0 = 3.0\nIDD2P = 27\nIDD2N = 42\nIDD3P = 40\nIDD3N = 55\nIDD4W = 155\nIDD4R = 135\nIDD5AB = 170\nIDD6x = 20\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1063829\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x4_2400.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 17\nCWL = 12\ntRCD = 17\ntRP = 17\ntRAS = 39\ntRFC = 312\ntRFC2 = 192\ntRFC4 = 132\ntREFI = 9360\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 16\ntWR = 18\ntWR2 = 19\ntRTP = 9\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 324\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 60\nIPP0 = 3.0\nIDD2P = 29\nIDD2N = 45\nIDD3P = 40\nIDD3N = 60\nIDD4W = 175\nIDD4R = 145\nIDD5AB = 175\nIDD6x = 20\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\ncmd_queue_size = 8\ntrans_queue_size = 32\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\n\n[other]\nepoch_period = 1204819\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x4_2400_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 16\nCWL = 12\ntRCD = 16\ntRP = 16\ntRAS = 39\ntRFC = 312\ntRFC2 = 192\ntRFC4 = 132\ntREFI = 9360\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 16\ntWR = 18\ntWR2 = 19\ntRTP = 9\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 324\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 60\nIPP0 = 3.0\nIDD2P = 29\nIDD2N = 45\nIDD3P = 40\nIDD3N = 60\nIDD4W = 175\nIDD4R = 145\nIDD5AB = 175\nIDD6x = 20\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1204819\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x4_2666.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.75\nAL = 0\nCL = 19\nCWL = 14\ntRCD = 19\ntRP = 19\ntRAS = 43\ntRFC = 347\ntRFC2 = 214\ntRFC4 = 147\ntREFI = 10398\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 7\ntWTR_S = 4\ntWTR_L = 10\ntFAW = 16\ntWR = 20\ntWR2 = 21\ntRTP = 10\ntCCD_S = 4\ntCCD_L = 7\ntCKE = 7\ntCKESR = 8\ntXS = 360\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 65\nIPP0 = 3.0\nIDD2P = 34\nIDD2N = 50\nIDD3P = 40\nIDD3N = 65\nIDD4W = 195\nIDD4R = 170\nIDD5AB = 175\nIDD6x = 20\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1333333\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x4_2666_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.75\nAL = 0\nCL = 18\nCWL = 14\ntRCD = 18\ntRP = 18\ntRAS = 43\ntRFC = 347\ntRFC2 = 214\ntRFC4 = 147\ntREFI = 10398\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 7\ntWTR_S = 4\ntWTR_L = 10\ntFAW = 16\ntWR = 20\ntWR2 = 21\ntRTP = 10\ntCCD_S = 4\ntCCD_L = 7\ntCKE = 7\ntCKESR = 8\ntXS = 360\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 65\nIPP0 = 3.0\nIDD2P = 34\nIDD2N = 50\nIDD3P = 40\nIDD3N = 65\nIDD4W = 195\nIDD4R = 170\nIDD5AB = 175\nIDD6x = 20\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1333333\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x8_1866.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 13\nCWL = 10\ntRCD = 13\ntRP = 13\ntRAS = 32\ntRFC = 243\ntRFC2 = 150\ntRFC4 = 103\ntREFI = 7285\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 5\ntWTR_S = 3\ntWTR_L = 7\ntFAW = 22\ntWR = 14\ntWR2 = 15\ntRTP = 7\ntCCD_S = 4\ntCCD_L = 5\ntCKE = 5\ntCKESR = 6\ntXS = 253\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 55\nIPP0 = 3.0\nIDD2P = 27\nIDD2N = 40\nIDD3P = 40\nIDD3N = 55\nIDD4W = 140\nIDD4R = 125\nIDD5AB = 170\nIDD6x = 20\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x8_2133.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.94\nAL = 0\nCL = 16\nCWL = 11\ntRCD = 16\ntRP = 16\ntRAS = 36\ntRFC = 278\ntRFC2 = 171\ntRFC4 = 118\ntREFI = 8328\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 8\ntFAW = 23\ntWR = 16\ntWR2 = 17\ntRTP = 8\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 289\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 55\nIPP0 = 3.0\nIDD2P = 27\nIDD2N = 42\nIDD3P = 40\nIDD3N = 55\nIDD4W = 155\nIDD4R = 135\nIDD5AB = 170\nIDD6x = 20\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1063829\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x8_2133_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.94\nAL = 0\nCL = 15\nCWL = 11\ntRCD = 15\ntRP = 15\ntRAS = 36\ntRFC = 278\ntRFC2 = 171\ntRFC4 = 118\ntREFI = 8328\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 8\ntFAW = 23\ntWR = 16\ntWR2 = 17\ntRTP = 8\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 289\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 55\nIPP0 = 3.0\nIDD2P = 27\nIDD2N = 42\nIDD3P = 40\nIDD3N = 55\nIDD4W = 155\nIDD4R = 135\nIDD5AB = 170\nIDD6x = 20\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1063829\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x8_2400.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 17\nCWL = 12\ntRCD = 17\ntRP = 17\ntRAS = 39\ntRFC = 312\ntRFC2 = 192\ntRFC4 = 132\ntREFI = 9360\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 26\ntWR = 18\ntWR2 = 19\ntRTP = 9\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 324\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 60\nIPP0 = 3.0\nIDD2P = 29\nIDD2N = 45\nIDD3P = 40\nIDD3N = 60\nIDD4W = 175\nIDD4R = 145\nIDD5AB = 175\nIDD6x = 20\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1204819\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x8_2400_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 16\nCWL = 12\ntRCD = 16\ntRP = 16\ntRAS = 39\ntRFC = 312\ntRFC2 = 192\ntRFC4 = 132\ntREFI = 9360\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 26\ntWR = 18\ntWR2 = 19\ntRTP = 9\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 324\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 60\nIPP0 = 3.0\nIDD2P = 29\nIDD2N = 45\nIDD3P = 40\nIDD3N = 60\nIDD4W = 175\nIDD4R = 145\nIDD5AB = 175\nIDD6x = 20\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1204819\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x8_2666.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.75\nAL = 0\nCL = 19\nCWL = 14\ntRCD = 19\ntRP = 19\ntRAS = 43\ntRFC = 347\ntRFC2 = 214\ntRFC4 = 147\ntREFI = 10398\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 7\ntWTR_S = 4\ntWTR_L = 10\ntFAW = 28\ntWR = 20\ntWR2 = 21\ntRTP = 10\ntCCD_S = 4\ntCCD_L = 7\ntCKE = 7\ntCKESR = 8\ntXS = 360\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 65\nIPP0 = 3.0\nIDD2P = 34\nIDD2N = 50\nIDD3P = 40\nIDD3N = 65\nIDD4W = 195\nIDD4R = 170\nIDD5AB = 175\nIDD6x = 20\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1333333\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_4Gb_x8_2666_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 32768\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.75\nAL = 0\nCL = 18\nCWL = 14\ntRCD = 18\ntRP = 18\ntRAS = 43\ntRFC = 347\ntRFC2 = 214\ntRFC4 = 147\ntREFI = 10398\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 7\ntWTR_S = 4\ntWTR_L = 10\ntFAW = 28\ntWR = 20\ntWR2 = 21\ntRTP = 10\ntCCD_S = 4\ntCCD_L = 7\ntCKE = 7\ntCKESR = 8\ntXS = 360\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 65\nIPP0 = 3.0\nIDD2P = 34\nIDD2N = 50\nIDD3P = 40\nIDD3N = 65\nIDD4W = 195\nIDD4R = 170\nIDD5AB = 175\nIDD6x = 20\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1333333\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x16_1866.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 13\nCWL = 10\ntRCD = 13\ntRP = 13\ntRAS = 32\ntRFC = 327\ntRFC2 = 243\ntRFC4 = 150\ntREFI = 7285\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 5\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 7\ntFAW = 28\ntWR = 14\ntWR2 = 15\ntRTP = 7\ntCCD_S = 4\ntCCD_L = 5\ntCKE = 5\ntCKESR = 6\ntXS = 337\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 75\nIPP0 = 4.0\nIDD2P = 25\nIDD2N = 33\nIDD3P = 39\nIDD3N = 44\nIDD4W = 225\nIDD4R = 225\nIDD5AB = 280\nIDD6x = 30\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x16_2133.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.94\nAL = 0\nCL = 16\nCWL = 11\ntRCD = 16\ntRP = 16\ntRAS = 36\ntRFC = 374\ntRFC2 = 278\ntRFC4 = 171\ntREFI = 8328\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 6\ntRRD_L = 7\ntWTR_S = 3\ntWTR_L = 8\ntFAW = 32\ntWR = 16\ntWR2 = 17\ntRTP = 8\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 385\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 75\nIPP0 = 4.0\nIDD2P = 25\nIDD2N = 33\nIDD3P = 39\nIDD3N = 44\nIDD4W = 225\nIDD4R = 225\nIDD5AB = 280\nIDD6x = 30\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1063829\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x16_2133_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.94\nAL = 0\nCL = 15\nCWL = 11\ntRCD = 15\ntRP = 15\ntRAS = 36\ntRFC = 374\ntRFC2 = 278\ntRFC4 = 171\ntREFI = 8328\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 6\ntRRD_L = 7\ntWTR_S = 3\ntWTR_L = 8\ntFAW = 32\ntWR = 16\ntWR2 = 17\ntRTP = 8\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 385\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 75\nIPP0 = 4.0\nIDD2P = 25\nIDD2N = 33\nIDD3P = 39\nIDD3N = 44\nIDD4W = 225\nIDD4R = 225\nIDD5AB = 280\nIDD6x = 30\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1063829\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x16_2400.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 17\nCWL = 12\ntRCD = 17\ntRP = 17\ntRAS = 39\ntRFC = 420\ntRFC2 = 312\ntRFC4 = 192\ntREFI = 9360\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 7\ntRRD_L = 8\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 36\ntWR = 18\ntWR2 = 19\ntRTP = 9\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 432\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 80\nIPP0 = 4.0\nIDD2P = 25\nIDD2N = 34\nIDD3P = 41\nIDD3N = 47\nIDD4W = 228\nIDD4R = 243\nIDD5AB = 280\nIDD6x = 30\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1204819\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x16_2400_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 16\nCWL = 12\ntRCD = 16\ntRP = 16\ntRAS = 39\ntRFC = 420\ntRFC2 = 312\ntRFC4 = 192\ntREFI = 9360\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 7\ntRRD_L = 8\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 36\ntWR = 18\ntWR2 = 19\ntRTP = 9\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 432\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 80\nIPP0 = 4.0\nIDD2P = 25\nIDD2N = 34\nIDD3P = 41\nIDD3N = 47\nIDD4W = 228\nIDD4R = 243\nIDD5AB = 280\nIDD6x = 30\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1204819\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x16_2666.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.75\nAL = 0\nCL = 19\nCWL = 14\ntRCD = 19\ntRP = 19\ntRAS = 43\ntRFC = 467\ntRFC2 = 347\ntRFC4 = 214\ntREFI = 10398\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 7\ntRRD_L = 9\ntWTR_S = 4\ntWTR_L = 10\ntFAW = 40\ntWR = 20\ntWR2 = 21\ntRTP = 10\ntCCD_S = 4\ntCCD_L = 7\ntCKE = 7\ntCKESR = 8\ntXS = 480\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 85\nIPP0 = 4.0\nIDD2P = 25\nIDD2N = 35\nIDD3P = 43\nIDD3N = 50\nIDD4W = 244\nIDD4R = 263\nIDD5AB = 280\nIDD6x = 30\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1333333\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x16_2666_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.75\nAL = 0\nCL = 18\nCWL = 14\ntRCD = 18\ntRP = 18\ntRAS = 43\ntRFC = 467\ntRFC2 = 347\ntRFC4 = 214\ntREFI = 10398\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 7\ntRRD_L = 9\ntWTR_S = 4\ntWTR_L = 10\ntFAW = 40\ntWR = 20\ntWR2 = 21\ntRTP = 10\ntCCD_S = 4\ntCCD_L = 7\ntCKE = 7\ntCKESR = 8\ntXS = 480\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 85\nIPP0 = 4.0\nIDD2P = 25\nIDD2N = 35\nIDD3P = 43\nIDD3N = 50\nIDD4W = 244\nIDD4R = 263\nIDD5AB = 280\nIDD6x = 30\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1333333\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x16_2933.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.68\nAL = 0\nCL = 21\nCWL = 16\ntRCD = 21\ntRP = 21\ntRAS = 47\ntRFC = 514\ntRFC2 = 382\ntRFC4 = 235\ntREFI = 11439\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 8\ntRRD_L = 10\ntWTR_S = 4\ntWTR_L = 11\ntFAW = 44\ntWR = 22\ntWR2 = 23\ntRTP = 11\ntCCD_S = 4\ntCCD_L = 8\ntCKE = 8\ntCKESR = 9\ntXS = 528\ntXP = 9\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 90\nIPP0 = 4.0\nIDD2P = 25\nIDD2N = 36\nIDD3P = 45\nIDD3N = 53\nIDD4W = 261\nIDD4R = 283\nIDD5AB = 280\nIDD6x = 30\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1470588\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x16_2933_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.68\nAL = 0\nCL = 20\nCWL = 16\ntRCD = 20\ntRP = 20\ntRAS = 47\ntRFC = 514\ntRFC2 = 382\ntRFC4 = 235\ntREFI = 11439\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 8\ntRRD_L = 10\ntWTR_S = 4\ntWTR_L = 11\ntFAW = 44\ntWR = 22\ntWR2 = 23\ntRTP = 11\ntCCD_S = 4\ntCCD_L = 8\ntCKE = 8\ntCKESR = 9\ntXS = 528\ntXP = 9\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 90\nIPP0 = 4.0\nIDD2P = 25\nIDD2N = 36\nIDD3P = 45\nIDD3N = 53\nIDD4W = 261\nIDD4R = 283\nIDD5AB = 280\nIDD6x = 30\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1470588\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x16_3200.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 0.63\nAL = 0\nCL = 22\nCWL = 16\ntRCD = 22\ntRP = 22\ntRAS = 52\ntRFC = 560\ntRFC2 = 416\ntRFC4 = 256\ntREFI = 12480\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 9\ntRRD_L = 11\ntWTR_S = 4\ntWTR_L = 12\ntFAW = 48\ntWR = 24\ntWR2 = 25\ntRTP = 12\ntCCD_S = 4\ntCCD_L = 8\ntCKE = 8\ntCKESR = 9\ntXS = 576\ntXP = 10\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 95\nIPP0 = 4.0\nIDD2P = 25\nIDD2N = 37\nIDD3P = 47\nIDD3N = 56\nIDD4W = 278\nIDD4R = 302\nIDD5AB = 280\nIDD6x = 30\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1587301\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x4_1866.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 131072\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 13\nCWL = 10\ntRCD = 13\ntRP = 13\ntRAS = 32\ntRFC = 327\ntRFC2 = 243\ntRFC4 = 150\ntREFI = 7285\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 5\ntWTR_S = 3\ntWTR_L = 7\ntFAW = 16\ntWR = 14\ntWR2 = 15\ntRTP = 7\ntCCD_S = 4\ntCCD_L = 5\ntCKE = 5\ntCKESR = 6\ntXS = 337\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 40\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 33\nIDD3P = 30\nIDD3N = 35\nIDD4W = 95\nIDD4R = 100\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 32768\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x4_2133.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 131072\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.94\nAL = 0\nCL = 16\nCWL = 11\ntRCD = 16\ntRP = 16\ntRAS = 36\ntRFC = 374\ntRFC2 = 278\ntRFC4 = 171\ntREFI = 8328\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 8\ntFAW = 16\ntWR = 16\ntWR2 = 17\ntRTP = 8\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 385\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 40\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 33\nIDD3P = 30\nIDD3N = 35\nIDD4W = 95\nIDD4R = 100\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 32768\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1063829\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x4_2133_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 131072\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.94\nAL = 0\nCL = 15\nCWL = 11\ntRCD = 15\ntRP = 15\ntRAS = 36\ntRFC = 374\ntRFC2 = 278\ntRFC4 = 171\ntREFI = 8328\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 8\ntFAW = 16\ntWR = 16\ntWR2 = 17\ntRTP = 8\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 385\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 40\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 33\nIDD3P = 30\nIDD3N = 35\nIDD4W = 95\nIDD4R = 100\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 32768\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1063829\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x4_2400.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 131072\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 17\nCWL = 12\ntRCD = 17\ntRP = 17\ntRAS = 39\ntRFC = 420\ntRFC2 = 312\ntRFC4 = 192\ntREFI = 9360\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 16\ntWR = 18\ntWR2 = 19\ntRTP = 9\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 432\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 43\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 34\nIDD3P = 32\nIDD3N = 38\nIDD4W = 103\nIDD4R = 110\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 32768\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1204819\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x4_2400_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 131072\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 16\nCWL = 12\ntRCD = 16\ntRP = 16\ntRAS = 39\ntRFC = 420\ntRFC2 = 312\ntRFC4 = 192\ntREFI = 9360\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 16\ntWR = 18\ntWR2 = 19\ntRTP = 9\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 432\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 43\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 34\nIDD3P = 32\nIDD3N = 38\nIDD4W = 103\nIDD4R = 110\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 32768\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1204819\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x4_2666.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 131072\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.75\nAL = 0\nCL = 19\nCWL = 14\ntRCD = 19\ntRP = 19\ntRAS = 43\ntRFC = 467\ntRFC2 = 347\ntRFC4 = 214\ntREFI = 10398\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 7\ntWTR_S = 4\ntWTR_L = 10\ntFAW = 16\ntWR = 20\ntWR2 = 21\ntRTP = 10\ntCCD_S = 4\ntCCD_L = 7\ntCKE = 7\ntCKESR = 8\ntXS = 480\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 46\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 35\nIDD3P = 34\nIDD3N = 41\nIDD4W = 112\nIDD4R = 121\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 32768\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1333333\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x4_2666_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 131072\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.75\nAL = 0\nCL = 18\nCWL = 14\ntRCD = 18\ntRP = 18\ntRAS = 43\ntRFC = 467\ntRFC2 = 347\ntRFC4 = 214\ntREFI = 10398\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 7\ntWTR_S = 4\ntWTR_L = 10\ntFAW = 16\ntWR = 20\ntWR2 = 21\ntRTP = 10\ntCCD_S = 4\ntCCD_L = 7\ntCKE = 7\ntCKESR = 8\ntXS = 480\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 46\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 35\nIDD3P = 34\nIDD3N = 41\nIDD4W = 112\nIDD4R = 121\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 32768\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1333333\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x4_2933.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 131072\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.68\nAL = 0\nCL = 21\nCWL = 16\ntRCD = 21\ntRP = 21\ntRAS = 47\ntRFC = 514\ntRFC2 = 382\ntRFC4 = 235\ntREFI = 11439\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 8\ntWTR_S = 4\ntWTR_L = 11\ntFAW = 16\ntWR = 22\ntWR2 = 23\ntRTP = 11\ntCCD_S = 4\ntCCD_L = 8\ntCKE = 8\ntCKESR = 9\ntXS = 528\ntXP = 9\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 49\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 36\nIDD3P = 36\nIDD3N = 44\nIDD4W = 121\nIDD4R = 132\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 32768\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1470588\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x4_2933_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 131072\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.68\nAL = 0\nCL = 20\nCWL = 16\ntRCD = 20\ntRP = 20\ntRAS = 47\ntRFC = 514\ntRFC2 = 382\ntRFC4 = 235\ntREFI = 11439\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 8\ntWTR_S = 4\ntWTR_L = 11\ntFAW = 16\ntWR = 22\ntWR2 = 23\ntRTP = 11\ntCCD_S = 4\ntCCD_L = 8\ntCKE = 8\ntCKESR = 9\ntXS = 528\ntXP = 9\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 49\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 36\nIDD3P = 36\nIDD3N = 44\nIDD4W = 121\nIDD4R = 132\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 32768\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1470588\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x4_3200.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 131072\ncolumns = 1024\ndevice_width = 4\nBL = 8\n\n[timing]\ntCK = 0.63\nAL = 0\nCL = 22\nCWL = 16\ntRCD = 22\ntRP = 22\ntRAS = 52\ntRFC = 560\ntRFC2 = 416\ntRFC4 = 256\ntREFI = 12480\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 8\ntWTR_S = 4\ntWTR_L = 12\ntFAW = 16\ntWR = 24\ntWR2 = 25\ntRTP = 12\ntCCD_S = 4\ntCCD_L = 8\ntCKE = 8\ntCKESR = 9\ntXS = 576\ntXP = 10\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 52\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 37\nIDD3P = 38\nIDD3N = 47\nIDD4W = 130\nIDD4R = 143\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 32768\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1587301\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x8_1866.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 13\nCWL = 10\ntRCD = 13\ntRP = 13\ntRAS = 32\ntRFC = 327\ntRFC2 = 243\ntRFC4 = 150\ntREFI = 7285\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 5\ntWTR_S = 3\ntWTR_L = 7\ntFAW = 22\ntWR = 14\ntWR2 = 15\ntRTP = 7\ntCCD_S = 4\ntCCD_L = 5\ntCKE = 5\ntCKESR = 6\ntXS = 337\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 45\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 33\nIDD3P = 35\nIDD3N = 40\nIDD4W = 115\nIDD4R = 125\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x8_2133.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.94\nAL = 0\nCL = 16\nCWL = 11\ntRCD = 16\ntRP = 16\ntRAS = 36\ntRFC = 374\ntRFC2 = 278\ntRFC4 = 171\ntREFI = 8328\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 8\ntFAW = 23\ntWR = 16\ntWR2 = 17\ntRTP = 8\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 385\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 45\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 33\nIDD3P = 35\nIDD3N = 40\nIDD4W = 115\nIDD4R = 125\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1063829\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x8_2133_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.94\nAL = 0\nCL = 15\nCWL = 11\ntRCD = 15\ntRP = 15\ntRAS = 36\ntRFC = 374\ntRFC2 = 278\ntRFC4 = 171\ntREFI = 8328\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 8\ntFAW = 23\ntWR = 16\ntWR2 = 17\ntRTP = 8\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 385\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 45\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 33\nIDD3P = 35\nIDD3N = 40\nIDD4W = 115\nIDD4R = 125\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1063829\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x8_2400.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 17\nCWL = 12\ntRCD = 17\ntRP = 17\ntRAS = 39\ntRFC = 420\ntRFC2 = 312\ntRFC4 = 192\ntREFI = 9360\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 26\ntWR = 18\ntWR2 = 19\ntRTP = 9\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 432\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 48\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 34\nIDD3P = 37\nIDD3N = 43\nIDD4W = 123\nIDD4R = 135\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1204819\noutput_level = 1\n\n[thermal]\nloc_mapping = 33,33,32-31,30-29,26:13-27-28,12:3\npower_epoch_period = 100000; power epoch period (# cycle)\nchip_dim_x = 0.008; chip size in x dimension [m]\nchip_dim_y = 0.008; chip size in y dimension [m]\namb_temp = 40; The ambient temperature in [C]\nmat_dim_x = 512;\nmat_dim_y = 512;\nbank_order = 0; 0: x direction first, 1: y direction first\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x8_2400_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 16\nCWL = 12\ntRCD = 16\ntRP = 16\ntRAS = 39\ntRFC = 420\ntRFC2 = 312\ntRFC4 = 192\ntREFI = 9360\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 26\ntWR = 18\ntWR2 = 19\ntRTP = 9\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 432\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 48\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 34\nIDD3P = 37\nIDD3N = 43\nIDD4W = 123\nIDD4R = 135\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1204819\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x8_2666.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.75\nAL = 0\nCL = 19\nCWL = 14\ntRCD = 19\ntRP = 19\ntRAS = 43\ntRFC = 467\ntRFC2 = 347\ntRFC4 = 214\ntREFI = 10398\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 7\ntWTR_S = 4\ntWTR_L = 10\ntFAW = 28\ntWR = 20\ntWR2 = 21\ntRTP = 10\ntCCD_S = 4\ntCCD_L = 7\ntCKE = 7\ntCKESR = 8\ntXS = 480\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 51\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 35\nIDD3P = 39\nIDD3N = 46\nIDD4W = 132\nIDD4R = 146\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1333333\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x8_2666_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.75\nAL = 0\nCL = 18\nCWL = 14\ntRCD = 18\ntRP = 18\ntRAS = 43\ntRFC = 467\ntRFC2 = 347\ntRFC4 = 214\ntREFI = 10398\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 7\ntWTR_S = 4\ntWTR_L = 10\ntFAW = 28\ntWR = 20\ntWR2 = 21\ntRTP = 10\ntCCD_S = 4\ntCCD_L = 7\ntCKE = 7\ntCKESR = 8\ntXS = 480\ntXP = 8\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 51\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 35\nIDD3P = 39\nIDD3N = 46\nIDD4W = 132\nIDD4R = 146\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1333333\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x8_2933.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.68\nAL = 0\nCL = 21\nCWL = 16\ntRCD = 21\ntRP = 21\ntRAS = 47\ntRFC = 514\ntRFC2 = 382\ntRFC4 = 235\ntREFI = 11439\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 8\ntWTR_S = 4\ntWTR_L = 11\ntFAW = 31\ntWR = 22\ntWR2 = 23\ntRTP = 11\ntCCD_S = 4\ntCCD_L = 8\ntCKE = 8\ntCKESR = 9\ntXS = 528\ntXP = 9\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 54\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 36\nIDD3P = 41\nIDD3N = 49\nIDD4W = 141\nIDD4R = 157\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1470588\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x8_2933_2.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.68\nAL = 0\nCL = 20\nCWL = 16\ntRCD = 20\ntRP = 20\ntRAS = 47\ntRFC = 514\ntRFC2 = 382\ntRFC4 = 235\ntREFI = 11439\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 8\ntWTR_S = 4\ntWTR_L = 11\ntFAW = 31\ntWR = 22\ntWR2 = 23\ntRTP = 11\ntCCD_S = 4\ntCCD_L = 8\ntCKE = 8\ntCKESR = 9\ntXS = 528\ntXP = 9\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 54\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 36\nIDD3P = 41\nIDD3N = 49\nIDD4W = 141\nIDD4R = 157\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1470588\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/DDR4_8Gb_x8_3200.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.63\nAL = 0\nCL = 22\nCWL = 16\ntRCD = 22\ntRP = 22\ntRAS = 52\ntRFC = 560\ntRFC2 = 416\ntRFC4 = 256\ntREFI = 12480\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 8\ntWTR_S = 4\ntWTR_L = 12\ntFAW = 34\ntWR = 24\ntWR2 = 25\ntRTP = 12\ntCCD_S = 4\ntCCD_L = 8\ntCKE = 8\ntCKESR = 9\ntXS = 576\ntXP = 10\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 57\nIPP0 = 3.0\nIDD2P = 25\nIDD2N = 37\nIDD3P = 43\nIDD3N = 52\nIDD4W = 150\nIDD4R = 168\nIDD5AB = 250\nIDD6x = 30\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1587301\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/GDDR5X_8Gb_x32.ini",
    "content": "[dram_structure]\nprotocol = GDDR5X\nbankgroups = 4\nbanks_per_group = 4\nrows = 16384\ncolumns = 64\ndevice_width = 32\nBL = 16\nbankgroup_enable = false\n\n[timing]\ntCK = 0.666 (1/1.5)\nCL = 24\nCWL = 7\ntRCDRD = 18\ntRCDWR = 15\ntRP = 18\ntRAS = 42\ntRFC = 98\ntREFI = 11699\ntRPRE = 1; read preamble\ntWPRE = 1; TODO figure this out, should be 1 or 2\ntRRD_S = 9\ntRRD_L = 9\ntWTR_S = 8\ntWTR_L = 8\ntFAW = 35\ntWR = 18\ntCCD_S = 2\ntCCD_L = 3\ntXS = 116\ntCKE = 16\ntCKSRE = 8\ntXP = 12\ntRTRS = 0\ntRTP_L = 3\ntRTP_S = 3\ntPPD = 2\nt32AW = 280\n\n[power]\nVDD = 1.35\nIDD0 = 500\nIDD2P = 220\nIDD2N = 260\nIDD3P = 330\nIDD3N = 480\nIDD4W = 2320\nIDD4R = 2160\nIDD5AB = 600\nIDD5PB = 60\nIDD6x = 65\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 128\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1501501\noutput_level = 1\n\n[thermal]\npower_epoch_period = 1000; power epoch period (# cycle)\nchip_dim_x = 0.008; chip size in x dimension [m]\nchip_dim_y = 0.008; chip size in y dimension [m]\namb_temp = 40; The ambient temperature in [C]\nmat_dim_x = 512;\nmat_dim_y = 512;\nbank_order = 1; 0: x direction first, 1: y direction first\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/GDDR5_1Gb_x32.ini",
    "content": "[dram_structure]\nprotocol = GDDR5\nbankgroups = 4\nbanks_per_group = 4\nrows = 4096\ncolumns = 64\ndevice_width = 32\nBL = 8\nbankgroup_enable = false\n\n[timing]\ntCK = 0.667\nCL = 24\nCWL = 7\ntRCDRD = 18\ntRCDWR = 15\ntRP = 18\ntRAS = 42\ntRFC = 98\ntREFI = 11699\ntRPRE = 1; read preamble\ntWPRE = 1; TODO figure this out, should be 1 or 2\ntRRD_S = 9\ntRRD_L = 9\ntWTR_S = 8\ntWTR_L = 8\ntFAW = 35\ntWR = 18\ntCCD_S = 2\ntCCD_L = 3\ntXS = 116\ntCKE = 16\ntCKESR = 8\ntXP = 12\ntRTRS = 0\ntRTP_L = 3\ntRTP_S = 3\ntPPD = 2\nt32AW = 280\n\n[power]\nVDD = 1.5\nIDD0 = 490\nIDD2P = 210\nIDD2N = 250\nIDD3P = 310\nIDD3N = 450\nIDD4W = 1160\nIDD4R = 1080\nIDD5AB = 450\nIDD5PB = 45\nIDD6x = 60\n\n[system]\nchannel_size = 1024\nchannels = 1\nbus_width = 256\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1499250\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/GDDR5_8Gb_x32.ini",
    "content": "[dram_structure]\nprotocol = GDDR5\nbankgroups = 4\nbanks_per_group = 4\nrows = 16384\ncolumns = 128\ndevice_width = 32\nBL = 8\nbankgroup_enable = false\n\n[timing]\ntCK = 0.667\nCL = 24\nCWL = 7\ntRCDRD = 24\ntRCDWR = 20\ntRP = 24\ntRAS = 56\ntRFC = 74\ntREFI = 3800\ntRPRE = 1; read preamble\ntWPRE = 1; TODO figure this out, should be 1 or 2\ntRRD_S = 10\ntRRD_L = 10\ntWTR_S = 10\ntWTR_L = 10\ntFAW = 40\ntWR = 24\ntCCD_S = 2\ntCCD_L = 3\ntXS = 94\ntCKESR = 2\ntXP = 12\ntRTRS = 1\ntRTP_L = 2\ntRTP_S = 2\ntPPD = 5\nt32AW = 360\ntRFCb = 30\ntREFIb = 238\n\n[power]\nVDD = 1.5\nIDD0 = 71\nIDD2P = 45\nIDD2N = 60\nIDD3P = 50\nIDD3N = 61\nIDD4W = 231\nIDD4R = 248\nIDD5AB = 286\nIDD5PB = 45\nIDD6x = 35\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 128\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1499250\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/GDDR6_8Gb_x16.ini",
    "content": "[dram_structure]\nprotocol = GDDR6\nbankgroups = 4\nbanks_per_group = 4\nrows = 16384\ncolumns = 128\ndevice_width = 16\nBL = 16\nbankgroup_enable = false\n\n[timing]\ntCK = 0.66\nCL = 24\nCWL = 16\ntRCDRD = 24\ntRCDWR = 20\ntRP = 24\ntRAS = 54\ntRFC = 126\ntREFI = 11862\ntRPRE = 1; read preamble\ntWPRE = 1; TODO figure this out, should be 1 or 2\ntRRD_S = 9\ntRRD_L = 9\ntWTR_S = 7\ntWTR_L = 7\ntFAW = 32\ntWR = 16\ntCCD_S = 3\ntCCD_L = 4\ntXS = 132\ntCKESR = 8\ntXP = 12\ntRTRS = 1\ntRTP_L = 3\ntRTP_S = 3\ntPPD = 2\nt32AW = 420\ntRFCb = 30\ntREFIb = 238\n\n[power]\nVDD = 1.35\nIDD0 = 71\nIDD2P = 45\nIDD2N = 60\nIDD3P = 50\nIDD3N = 61\nIDD4W = 231\nIDD4R = 248\nIDD5AB = 286\nIDD5PB = 45\nIDD6x = 35\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 128\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1499250\noutput_level = 1\n\n;16n prefetch"
  },
  {
    "path": "src/DRAMsim3/configs/HBM1_4Gb_x128.ini",
    "content": "[dram_structure]\nprotocol = HBM\nbankgroups = 4\nbanks_per_group = 4\nrows = 16384\ncolumns = 64\ndevice_width = 128\nBL = 4\nnum_dies = 4\n\n[timing]\ntCK = 2\nCL = 7\nCWL = 2\ntRCDRD = 7\ntRCDWR = 7\ntRP = 7\ntRAS = 17\ntRFC = 130\ntREFI = 1950\ntREFIb = 64\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 2\ntRRD_L = 3\ntWTR_S = 3\ntWTR_L = 4\ntFAW = 15\ntWR = 8\ntCCD_S = 1\ntCCD_L = 1\ntXS = 134\ntCKE = 4\ntCKSRE = 5\ntXP = 4\ntRTP_L = 3\ntRTP_S = 2\n\n[power]\nVDD = 1.2\nIDD0 = 65\nIDD2P = 28\nIDD2N = 40\nIDD3P = 40\nIDD3N = 55\nIDD4W = 440\nIDD4R = 360\nIDD5AB = 250\nIDD6x = 31\n\n[system]\nchannel_size = 512\nchannels = 8\nbus_width = 128\naddress_mapping = rorabgbachco\nqueue_structure = PER_BANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\nunified_queue = False\n\n[other]\nepoch_period = 500000\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/HBM2_4Gb_x128.ini",
    "content": "[dram_structure]\nprotocol = HBM\nbankgroups = 4\nbanks_per_group = 4\nrows = 16384\ncolumns = 64\ndevice_width = 128\nBL = 4\nnum_dies = 4\n\n[timing]\ntCK = 1\nCL = 14\nCWL = 4\ntRCDRD = 14\ntRCDWR = 14\ntRP = 14\ntRAS = 34\ntRFC = 260\ntREFI = 3900\ntREFIb = 128\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 6\ntWTR_L = 8\ntFAW = 30\ntWR = 16\ntCCD_S = 1\ntCCD_L = 2\ntXS = 268\ntCKE = 8\ntCKSRE = 10\ntXP = 8\ntRTP_L = 6\ntRTP_S = 4\n\n[power]\nVDD = 1.2\nIDD0 = 65\nIDD2P = 28\nIDD2N = 40\nIDD3P = 40\nIDD3N = 55\nIDD4W = 500\nIDD4R = 390\nIDD5AB = 250\nIDD6x = 31\n\n[system]\nchannel_size = 512\nchannels = 8\nbus_width = 128\naddress_mapping = rorabgbachco\nqueue_structure = PER_BANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\nunified_queue = False\n\n[other]\nepoch_period = 1000000\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/HBM2_8Gb_x128.ini",
    "content": "[dram_structure]\nprotocol = HBM\nbankgroups = 4\nbanks_per_group = 4\nrows = 32768\ncolumns = 64\ndevice_width = 128\nBL = 4\nnum_dies = 4\n\n[timing]\ntCK = 1\nCL = 14\nCWL = 4\ntRCDRD = 14\ntRCDWR = 14\ntRP = 14\ntRAS = 34\ntRFC = 260\ntREFI = 3900\ntREFIb = 128\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 6\ntWTR_L = 8\ntFAW = 30\ntWR = 16\ntCCD_S = 1\ntCCD_L = 2\ntXS = 268\ntCKE = 8\ntCKSRE = 10\ntXP = 8\ntRTP_L = 6\ntRTP_S = 4\n\n[power]\nVDD = 1.2\nIDD0 = 65\nIDD2P = 28\nIDD2N = 40\nIDD3P = 40\nIDD3N = 55\nIDD4W = 500\nIDD4R = 390\nIDD5AB = 250\nIDD6x = 31\n\n[system]\nchannel_size = 1024\nchannels = 8\nbus_width = 128\naddress_mapping = rorabgbachco\nqueue_structure = PER_BANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\nunified_queue = False\n\n[other]\nepoch_period = 1000000\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/HBM_4Gb_x128.ini",
    "content": "[dram_structure]\nprotocol = HBM\nbankgroups = 4\nbanks_per_group = 4\nrows = 16384\ncolumns = 64\ndevice_width = 128\nBL = 4\nnum_dies = 4\n\n[timing]\ntCK = 2\nAL = 0\nCL = 7\nCWL = 4\ntRCDRD = 7\ntRCDWR = 6\ntRP = 7\ntRAS = 17\ntRFC = \ntREFI = 1950\ntRPRE = 1; read preamble\ntWPRE = 1; TODO figure this out, should be 1 or 2\ntRRD_S = 4\ntRRD_L = 5\ntWTR_S = 2\ntWTR_L = 4\ntFAW = 20\ntWR = 8\ntCCD_S = 2\ntCCD_L = 3\ntXS = 0\ntCKSRE = 0\ntXP = 5\ntRTP_L = 7\ntRTP_S = 6\ntPPD = 5\nt32AW = 330\ntRFCb = \ntREFIb = \ntRREFD = \ntRFCPB = \n\n[power]\nVDD = 1.2\nIDD0 = 48\nIDD2P = 25\nIDD2N = 34\nIDD3P = 37\nIDD3N = 43\nIDD4W = 123\nIDD4R = 135\nIDD5AB = 250\nIDD6x = 31\n\n[system]\nchannel_size = 512\nchannels = 8\nbus_width = 128\naddress_mapping = rorabgbachco\nqueue_structure = PER_BANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\nunified_queue = False\n\n[other]\nepoch_period = 500000\noutput_level = 1\n\n[thermal]\npower_epoch_period = 10000; power epoch period (# cycle)\nlogic_bg_power = 5\nlogic_max_power = 25\nchip_dim_x = 0.008; chip size in x dimension [m]\nchip_dim_y = 0.008; chip size in y dimension [m]\namb_temp = 40; The ambient temperature in [C]\nmat_dim_x = 1024;\nmat_dim_y = 1024;\nbank_order = 1; 0: x direction first, 1: y direction first\nbank_layer_order = 0;\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/HMC2_8GB_4Lx16.ini",
    "content": "[hmc]\nnum_links = 4\nlink_width = 16\nlink_speed = 25000\nblock_size = 64\nxbar_queue_depth = 32\n\n[dram_structure]\nprotocol = HMC\nbankgroups = 1\nbanks_per_group = 16\nrows = 65536\ncolumns = 64\ndevice_width = 32\nnum_dies = 8\n\n[timing]\ntCK = 0.8\nCL = 17\nCWL = 17\ntRCD = 17\ntRP = 17\ntRAS = 34\ntRFC = 420\ntREFI = 9364; average periodic refresh interval, 3.9us\ntRRD_S = 6\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 3\ntFAW = 27\ntWR = 19\ntCCD_S = 6\ntCCD_L = 6\ntXS = 12\ntCKSRE = 1\ntXP = 8\ntRTP_L = 10\ntRTP_S = 10\ntRTRS = 0\n\n[power]\nVDD = 1.2\nIDD0 = 25\nIDD2P = 17\nIDD2N = 19\nIDD3P = 20\nIDD3N = 21\nIDD4W = 61\nIDD4R = 64\nIDD5AB = 150\nIDD6x = 21\n\n[system]\nchannel_size = 256\nchannels = 32\nbus_width = 32\naddress_mapping = rocorabgbach\nqueue_structure = PER_BANK\nrow_buf_policy = CLOSE_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\nunified_queue = True\n\n[thermal]\npower_epoch_period = 10000; power epoch period (# cycle)\nchip_dim_x = 0.008; chip size in x dimension [m]\nchip_dim_y = 0.008; chip size in y dimension [m]\namb_temp = 40; The ambient temperature in [C]\nmat_dim_x = 512;\nmat_dim_y = 512;\nbank_order = 1; 0: x direction first, 1: y direction first\nbank_layer_order = 0;\n\n[other]\nepoch_period = 1250000\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/HMC_2GB_4Lx16.ini",
    "content": "[hmc]\nnum_links = 4\nlink_width = 16\nlink_speed = 10000\nblock_size = 64\nxbar_queue_depth = 6\n\n[dram_structure]\nprotocol = HMC\nbankgroups = 1\nbanks_per_group = 8\nrows = 65536\ncolumns = 64\ndevice_width = 32\nnum_dies = 4\n\n[timing]\ntCK = 0.8\nCL = 17\nCWL = 17\ntRCD = 17\ntRP = 17\ntRAS = 34\ntRFC = 420\ntREFI = 9364; average periodic refresh interval, 3.9us\ntRRD_S = 4\ntRRD_L = 4\ntWTR_S = 3\ntWTR_L = 3\ntFAW = 27\ntWR = 17\ntCCD_S = 6\ntCCD_L = 6\ntXS = 12\ntCKSRE = 1\ntXP = 8\ntRTP_L = 8\ntRTP_S = 8\ntRTRS = 0\n\n[power]\nVDD = 1.2\nIDD0 = 25\nIDD2P = 17\nIDD2N = 19\nIDD3P = 20\nIDD3N = 21\nIDD4W = 61\nIDD4R = 64\nIDD5AB = 150\nIDD6x = 21\n\n[system]\nchannel_size = 128\nchannels = 16\nbus_width = 32\naddress_mapping = rocorabgbach\nqueue_structure = PER_BANK\nrow_buf_policy = CLOSE_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\nunified_queue = True\n\n[other]\nepoch_period = 1250000\noutput_level = 1\n\n[thermal]\npower_epoch_period = 10000; power epoch period (# cycle)\nchip_dim_x = 0.008; chip size in x dimension [m]\nchip_dim_y = 0.008; chip size in y dimension [m]\namb_temp = 40; The ambient temperature in [C]\nmat_dim_x = 512;\nmat_dim_y = 512;\nbank_order = 1; 0: x direction first, 1: y direction first\nbank_layer_order = 0;\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/HMC_2GB_4Lx16_dummy.ini",
    "content": "[hmc]\nnum_links = 4\nlink_width = 16\nlink_speed = 10000\nblock_size = 128\nxbar_queue_depth = 6\n\n[dram_structure]\nprotocol = HMC\nbankgroups = 1\nbanks_per_group = 8\nrows = 65536\ncolumns = 64\ndevice_width = 32\nBL = 2\nnum_dies = 4\n\n[timing]\ntCK = 0.8\nCL = 17\nCWL = 17\ntRCD = 17\ntRP = 17\ntRAS = 34\ntRFC = 420\ntREFI = 9364; average periodic refresh interval, 3.9us\ntRRD_S = 4\ntRRD_L = 4\ntWTR_S = 3\ntWTR_L = 3\ntFAW = 27\ntWR = 17\ntCCD_S = 6\ntCCD_L = 6\ntXS = 12\ntCKSRE = 1\ntXP = 8\ntRTP_L = 8\ntRTP_S = 8\ntRTRS = 0\n\n[power]\nVDD = 1.2\nIDD0 = 25\nIDD2P = 17\nIDD2N = 19\nIDD3P = 20\nIDD3N = 21\nIDD4W = 61\nIDD4R = 64\nIDD5AB = 150\nIDD6x = 21\n\n[system]\nchannel_size = 128\nchannels = 16\nbus_width = 32\naddress_mapping = rocorabgbach\nqueue_structure = PER_BANK\nrow_buf_policy = CLOSE_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\nunified_queue = True\n\n[other]\nepoch_period = 1250000\noutput_level = 1\n\n[thermal]\npower_epoch_period = 10000; power epoch period (# cycle)\nchip_dim_x = 0.008; chip size in x dimension [m]\nchip_dim_y = 0.008; chip size in y dimension [m]\namb_temp = 40; The ambient temperature in [C]\nmat_dim_x = 512;\nmat_dim_y = 512;\nbank_order = 1; 0: x direction first, 1: y direction first\nbank_layer_order = 0;\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/HMC_4GB_4Lx16.ini",
    "content": "[hmc]\nnum_links = 4\nlink_width = 16\nlink_speed = 15000\nblock_size = 64\nxbar_queue_depth = 6\n\n[dram_structure]\nprotocol = HMC\nbankgroups = 1\nbanks_per_group = 16\nrows = 65536\ncolumns = 64\ndevice_width = 32\nnum_dies = 4\n\n[timing]\ntCK = 0.8\nCL = 17\nCWL = 17\ntRCD = 17\ntRP = 17\ntRAS = 34\ntRFC = 420\ntREFI = 9364; average periodic refresh interval, 3.9us\ntRRD_S = 4\ntRRD_L = 4\ntWTR_S = 3\ntWTR_L = 3\ntFAW = 27\ntWR = 17\ntCCD_S = 6\ntCCD_L = 6\ntXS = 12\ntCKSRE = 1\ntXP = 8\ntRTP_L = 8\ntRTP_S = 8\ntRTRS = 0\n\n[power]\nVDD = 1.2\nIDD0 = 25\nIDD2P = 17\nIDD2N = 19\nIDD3P = 20\nIDD3N = 21\nIDD4W = 61\nIDD4R = 64\nIDD5AB = 150\nIDD6x = 21\n\n[system]\nchannel_size = 256\nchannels = 16\nbus_width = 32\naddress_mapping = rocorabgbach\nqueue_structure = PER_BANK\nrow_buf_policy = CLOSE_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\nunified_queue = True\n\n[other]\nepoch_period = 1250000\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/LPDDR3_8Gb_x32_1333.ini",
    "content": "[dram_structure]\nprotocol = LPDDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 32768\ncolumns = 1024\ndevice_width = 32\nBL = 8\n\n[timing]\ntCK = 1.5\nAL = 0\nCL = 10\nCWL = 8\ntRCD = 12\ntRP = 12\ntRAS = 28\ntRFC = 140\ntRFCb = 60\ntRFC2 = 140\ntRFC4 = 140\nREFI = 2600\ntREFIb = 325\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 7\ntRRD_L = 7\ntWTR_S = 5\ntWTR_L = 5\ntFAW = 34\ntWR = 10\ntWR2 = 10\ntRTP = 5\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 5\ntCKESR = 10\ntXS = 147\ntXP = 5\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 40.0\nIPP0 = 0\nIDD2P = 1.3\nIDD2N = 20.0\nIDD3P = 7\nIDD3N = 20.5\nIDD4W = 215\nIDD4R = 220\nIDD5AB = 150\nIDD6x = 20.5\n\n[system]\nchannel_size = 2048\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 666666\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/LPDDR3_8Gb_x32_1600.ini",
    "content": "[dram_structure]\nprotocol = LPDDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 32768\ncolumns = 1024\ndevice_width = 32\nBL = 8\n\n[timing]\ntCK = 1.25\nAL = 0\nCL = 12\nCWL = 9\ntRCD = 15\ntRP = 15\ntRAS = 34\ntRFC = 168\ntRFCb = 72\ntRFC2 = 168\ntRFC4 = 168\nREFI = 3120\ntREFIb = 390\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 8\ntRRD_L = 8\ntWTR_S = 6\ntWTR_L = 6\ntFAW = 40\ntWR = 12\ntWR2 = 12\ntRTP = 6\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 6\ntCKESR = 12\ntXS = 176\ntXP = 6\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 40.0\nIPP0 = 0\nIDD2P = 1.3\nIDD2N = 20.5\nIDD3P = 7\nIDD3N = 21.0\nIDD4W = 245\nIDD4R = 250\nIDD5AB = 150\nIDD6x = 21.0\n\n[system]\nchannel_size = 2048\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 800000\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/LPDDR3_8Gb_x32_1866.ini",
    "content": "[dram_structure]\nprotocol = LPDDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 32768\ncolumns = 1024\ndevice_width = 32\nBL = 8\n\n[timing]\ntCK = 1.07\nAL = 0\nCL = 14\nCWL = 11\ntRCD = 17\ntRP = 17\ntRAS = 40\ntRFC = 196\ntRFCb = 85\ntRFC2 = 196\ntRFC4 = 196\nREFI = 3645\ntREFIb = 456\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 10\ntRRD_L = 10\ntWTR_S = 7\ntWTR_L = 7\ntFAW = 47\ntWR = 15\ntWR2 = 15\ntRTP = 7\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 7\ntCKESR = 15\ntXS = 206\ntXP = 7\ntRTRS = 1\n\n[power]\nVDD = 1.2\nIDD0 = 41.5\nIPP0 = 0\nIDD2P = 1.3\nIDD2N = 21.5\nIDD3P = 7\nIDD3N = 22.0\nIDD4W = 285\nIDD4R = 290\nIDD5AB = 150\nIDD6x = 22.0\n\n[system]\nchannel_size = 2048\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 934579\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/LPDDR4_8Gb_x16_2400.ini",
    "content": "[dram_structure]\nprotocol = LPDDR4\nbankgroups = 2\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 16\nBL = 16\n\n[timing]\ntCK = 0.83\nAL = 0\nCL = 17\nCWL = 14\ntRCD = 15\ntRP = 15\ntRAS = 32\ntRFC = 392\ntRFC2 = 268\ntRFC4 = 172\ntREFI = 8660\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 8\ntRRD_L = 8\ntWTR_S = 8\ntWTR_L = 16\ntFAW = 32\ntWR = 30\ntWR2 = 32\ntRTP = 12\ntCCD_S = 4\ntCCD_L = 6\ntCKE = 6\ntCKESR = 7\ntXS = 432\ntXP = 6\ntRTRS = 1\ntPPD = 2\n\n[power]\nVDD = 1.2\nIDD0 = 80\nIPP0 = 4.0\nIDD2P = 25\nIDD2N = 34\nIDD3P = 41\nIDD3N = 47\nIDD4W = 228\nIDD4R = 243\nIDD5AB = 280\nIDD6x = 30\n\n[system]\nchannel_size = 8192\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrefresh_policy = RANK_LEVEL_STAGGERED\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 1204819\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/ST-1.2x.ini",
    "content": ";  (C) Copyright 2006-2018 Barcelona Supercomputing Center (BSC) \n;\n;The copyright holder is BSC-CNS, and the authorship correspond to Kazi Asifuzzaman, Rommel Sanchez Verdejo, and Petar Radojkovic. The complete explanation of the derivation of the data can be found in the following study: Kazi Asifuzzaman, Rommel Sanchez Verdejo, and Petar Radojkovic. 2017. Enabling a reliable STT-MRAM main memory simulation. In Proceedings of the International Symposium on Memory Systems (MEMSYS '17). Washington DC, USA, 283-292. DOI: https://doi.org/10.1145/3132402.3132416\n\n;Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n;1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n;2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.”\n\n; This configuration lists detailed timing parameters for STT-MRAM main memory, specifying a 1.2x deviation from respective DRAM timing parameters. Please note, the current parameters (IDD0, IDD1.. etc) DOES NOT correspond to STT-MRAM and should not be used for current/energy estimations.    \n\n[dram_structure]\nprotocol = DDR3  ; it's STT-MRAM, but using DDR3 protocol\nbankgroups = 1\nbanks_per_group = 8\nrows = 32768\ncolumns = 1024\ndevice_width = 8\nBL=4\n\n[timing]\ntCK = 1.25;\nCL = 11;\nCWL = 11\nAL = 0;\ntRCDRD=14 \ntRCDWR=14 \ntRP=14 \ntRAS=20\ntRFC = 1\ntREFI = 6240\ntRRD_S = 6\ntRRD_L = 6\ntWTR_S = 2\ntWTR_L = 2\ntFAW = 29\ntWR = 12\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 4\ntXP = 5\ntRTP_L = 6\ntRTP_S = 6\n; tRC=34\ntRTRS=1 \n\n; The following current parameters DOES NOT correspond to STT-MRAM, and should not be used used for current/energy estimations.\n[power]\nVDD = 1.5\nIDD0=1305;      \nIDD1=1395;     \nIDD2P=846;      \nIDD2Q=1030;     \nIDD2N=1050;     \nIDD3Pf=60;     \nIDD3Ps=60;      \nIDD3N=1310;    \nIDD4W=1765;     \nIDD4R=230;      \nIDD5=1940;     \nIDD6=246;       \nIDD6L=246;     \nIDD7=2160;      \n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 64\naddress_mapping = rorabgbachco\nqueue_structure = PER_RANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 16\ntrans_queue_size = 32\n\n[other]\nepoch_period = 100000\noutput_level = 1\n"
  },
  {
    "path": "src/DRAMsim3/configs/ST-1.5x.ini",
    "content": ";  (C) Copyright 2006-2018 Barcelona Supercomputing Center (BSC) \n;\n;The copyright holder is BSC-CNS, and the authorship correspond to Kazi Asifuzzaman, Rommel Sanchez Verdejo, and Petar Radojkovic. The complete explanation of the derivation of the data can be found in the following study: Kazi Asifuzzaman, Rommel Sanchez Verdejo, and Petar Radojkovic. 2017. Enabling a reliable STT-MRAM main memory simulation. In Proceedings of the International Symposium on Memory Systems (MEMSYS '17). Washington DC, USA, 283-292. DOI: https://doi.org/10.1145/3132402.3132416\n\n;Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n;1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n;2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.”\n\n; This configuration lists detailed timing parameters for STT-MRAM main memory, specifying a 1.5x deviation from respective DRAM timing parameters. Please note, the current parameters (IDD0, IDD1.. etc) DOES NOT correspond to STT-MRAM and should not be used for current/energy estimations.    \n\n[dram_structure]\nprotocol = DDR3  ; it's STT-MRAM, but using DDR3 protocol\nbankgroups = 1\nbanks_per_group = 8\nrows = 32768\ncolumns = 1024\ndevice_width = 8\nBL=4\n\n[timing]\ntCK = 1.25;\nCL = 11;\nCWL = 11\nAL = 0;\ntRCDRD=17\ntRCDWR=17\ntRP=17\ntRAS=23\ntRFC = 1\ntREFI = 6240\ntRRD_S = 8\ntRRD_L = 8\ntWTR_S = 6\ntWTR_L = 6\ntFAW = 36\ntWR = 12\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 4\ntXP = 5\ntRTP_L = 6\ntRTP_S = 6\n; tRC=40\ntRTRS=1\nREFRESH_PERIOD=7800; \n\n; The following current parameters DOES NOT correspond to STT-MRAM, and should not be used used for current/energy estimations.    \n[power]\nVDD=1.5\nIDD0=1305;      \nIDD1=1395;      \nIDD2P=846;      \nIDD2Q=1030;     \nIDD2N=1050;      \nIDD3Pf=60;      \nIDD3Ps=60;      \nIDD3N=1310;     \nIDD4W=1765;     \nIDD4R=230;      \nIDD5=1940;      \nIDD6=246;       \nIDD6L=246;      \nIDD7=2160;      \n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 64\naddress_mapping = rorabgbachco\nqueue_structure = PER_RANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 16\ntrans_queue_size = 32\n\n[other]\nepoch_period = 100000\noutput_level = 1\n"
  },
  {
    "path": "src/DRAMsim3/configs/ST-2.0x.ini",
    "content": ";  (C) Copyright 2006-2018 Barcelona Supercomputing Center (BSC) \n;\n;The copyright holder is BSC-CNS, and the authorship correspond to Kazi Asifuzzaman, Rommel Sanchez Verdejo, and Petar Radojkovic. The complete explanation of the derivation of the data can be found in the following study: Kazi Asifuzzaman, Rommel Sanchez Verdejo, and Petar Radojkovic. 2017. Enabling a reliable STT-MRAM main memory simulation. In Proceedings of the International Symposium on Memory Systems (MEMSYS '17). Washington DC, USA, 283-292. DOI: https://doi.org/10.1145/3132402.3132416\n\n;Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n;1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n;2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.”\n\n; This configuration lists detailed timing parameters for STT-MRAM main memory, specifying a 2x deviation from respective DRAM timing parameters. Please note, the current parameters (IDD0, IDD1.. etc) DOES NOT correspond to STT-MRAM and should not be used for current/energy estimations.    \n\n[dram_structure]\nprotocol = DDR3  ; it's STT-MRAM, but using DDR3 protocol\nbankgroups = 1\nbanks_per_group = 8\nrows = 32768\ncolumns = 1024\ndevice_width = 8\nBL=4\n\n[timing]\ntCK = 1.25;\nCL = 11;\nCWL = 11\nAL = 0;\ntRCDRD=22\ntRCDWR=22\ntRP=22\ntRAS=28\ntRFC = 1\ntREFI = 6240\ntRRD_S = 10\ntRRD_L = 10\ntWTR_S = 6\ntWTR_L = 6\ntFAW = 36\ntWR = 48\ntCCD_S = 4\ntCCD_L = 4\ntCKE = 4\ntXP = 5\ntRTP_L = 6\ntRTP_S = 6\n; tRC=50\ntRTRS=1\nREFRESH_PERIOD=7800\n\n; The following current parameters DOES NOT correspond to STT-MRAM, and should not be used used for current/energy estimations.\n[power]\nVDD=1.5; \nIDD0=1305;      \nIDD1=1395;      \nIDD2P=846;      \nIDD2Q=1030;     \nIDD2N=1050;     \nIDD3Pf=60;      \nIDD3Ps=60;      \nIDD3N=1310;     \nIDD4W=1765;     \nIDD4R=230;     \nIDD5=1940;     \nIDD6=246;      \nIDD6L=246;      \nIDD7=2160;      \n\n\n[system]\nchannel_size = 4096\nchannels = 1\nbus_width = 64\naddress_mapping = rorabgbachco\nqueue_structure = PER_RANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 16\ntrans_queue_size = 32\n\n[other]\nepoch_period = 100000\noutput_level = 1"
  },
  {
    "path": "src/DRAMsim3/configs/ddr3_debug.ini",
    "content": "[dram_structure]\nprotocol = DDR3\nbankgroups = 1\nbanks_per_group = 8\nrows = 16384\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 1.5\nAL = 0\nCL = 10\nCWL = 7\ntRCD = 10\ntRP = 10\ntRAS = 24\ntRFC = 74\ntREFI = 5200\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntWTR_S = 5\ntFAW = 20\ntWR = 10\ntCCD_S = 4\ntRTP = 5\ntCKE = 4\ntCKESR = 1\ntXS = 81\ntXP = 5\ntRTRS = 1\n\n[power]\nVDD = 1.35\nIDD0 = 33\nIDD2P = 12\nIDD2N = 17\nIDD3P = 14\nIDD3N = 23\nIDD4W = 77\nIDD4R = 72\nIDD5AB = 155\nIDD6x = 12\n\n[system]\nchannel_size = 2048\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nepoch_period = 666666\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/ddr4_debug.ini",
    "content": "[dram_structure]\nprotocol = DDR4\nbankgroups = 4\nbanks_per_group = 4\nrows = 65536\ncolumns = 1024\ndevice_width = 8\nBL = 8\n\n[timing]\ntCK = 0.833\nAL = 0\nCL = 16\nCWL = 16\ntRCD = 16\ntRP = 16\ntRAS = 39\ntRFC = 420\ntRFC2 = 312\ntRFC4 = 192\ntREFI = 9364\ntRPRE = 1\ntWPRE = 1\ntRRD_S = 4\ntRRD_L = 6\ntWTR_S = 3\ntWTR_L = 9\ntFAW = 26\ntWR = 19\ntWR2 = 1\ntCCD_S = 4\ntCCD_L = 6\ntXS = 12\ntCKSRE = 12\ntXP = 8\ntRFCb = 20\ntREFIb = 1950\nactivation_window_depth = 4\ntRREFD = 5\ntRTRS = 2\ntRTP = 10\ntCAS = 3\ntCWD = 3\n\n[power]\nVDD = 1.2\nIDD0 = 48\nIDD2P = 25\nIDD2N = 34\nIDD3P = 37\nIDD3N = 44.0\nIDD4W = 123\nIDD4R = 135\nIDD5AB = 250\nIDD6x = 31\n\n[system]\nchannel_size = 16384\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nvalidation_output = ddr4_verification.log\nepoch_period = 1200480\noutput_level = 1\n\n"
  },
  {
    "path": "src/DRAMsim3/configs/lpddr_2Gb_x16.ini",
    "content": "[dram_structure]\nprotocol = LPDDR\nbankgroups = 1\nbanks_per_group = 4\nrows = 16384\ncolumns = 2048\ndevice_width = 16\nBL = 8\n\n[timing]\ntCK = 4.8\nAL = 0\nCL = 3\nCWL = 3\ntRCD = 4\ntRP = 3\ntRAS = 9\ntRFC = 15\ntREFI = 1625\ntRPRE = 1\ntWPRE = 1\ntRRD_L = 3\ntWTR_L = 2\ntFAW = 4\ntWR = 3\ntCCD_L = 0\ntRTP = 0\ntXP = 2\ntCKE = 1\ntRTRS = 1\ntCMD = 1\nactivation_window_depth = 4\n\n[system]\nchannel_size = 1024\nchannels = 1\nbus_width = 64\naddress_mapping = rochrababgco\nqueue_structure = PER_BANK\nrow_buf_policy = OPEN_PAGE\ncmd_queue_size = 8\ntrans_queue_size = 32\n\n[other]\nvalidation_output = lpddr_verification.log\nepoch_period = 208333\noutput_level = 1\n\n[thermal]\npower_epoch_period = 10000; power epoch period (# cycle)\nchip_dim_x = 0.008; chip size in x dimension [m]\nchip_dim_y = 0.008; chip size in y dimension [m]\namb_temp = 40; The ambient temperature in [C]\nmat_dim_x = 512;\nmat_dim_y = 512;\nbank_order = 1; 0: x direction first, 1: y direction first\n\n"
  },
  {
    "path": "src/DRAMsim3/ext/fmt/LICENSE.rst",
    "content": "Copyright (c) 2012 - 2016, Victor Zverovich\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "src/DRAMsim3/ext/fmt/include/fmt/core.h",
    "content": "// Formatting library for C++ - the core API\n//\n// Copyright (c) 2012 - present, Victor Zverovich\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\n#ifndef FMT_CORE_H_\n#define FMT_CORE_H_\n\n#include <cassert>\n#include <cstdio>  // std::FILE\n#include <cstring>\n#include <iterator>\n#include <string>\n#include <type_traits>\n\n// The fmt library version in the form major * 10000 + minor * 100 + patch.\n#define FMT_VERSION 50202\n\n#ifdef __has_feature\n# define FMT_HAS_FEATURE(x) __has_feature(x)\n#else\n# define FMT_HAS_FEATURE(x) 0\n#endif\n\n#if defined(__has_include) && !defined(__INTELLISENSE__) && \\\n    !(defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1600)\n# define FMT_HAS_INCLUDE(x) __has_include(x)\n#else\n# define FMT_HAS_INCLUDE(x) 0\n#endif\n\n#ifdef __has_cpp_attribute\n# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)\n#else\n# define FMT_HAS_CPP_ATTRIBUTE(x) 0\n#endif\n\n#if defined(__GNUC__) && !defined(__clang__)\n# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n#else\n# define FMT_GCC_VERSION 0\n#endif\n\n#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)\n# define FMT_HAS_GXX_CXX11 FMT_GCC_VERSION\n#else\n# define FMT_HAS_GXX_CXX11 0\n#endif\n\n#ifdef _MSC_VER\n# define FMT_MSC_VER _MSC_VER\n#else\n# define FMT_MSC_VER 0\n#endif\n\n// Check if relaxed C++14 constexpr is supported.\n// GCC doesn't allow throw in constexpr until version 6 (bug 67371).\n#ifndef FMT_USE_CONSTEXPR\n# define FMT_USE_CONSTEXPR \\\n  (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1910 || \\\n   (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L))\n#endif\n#if FMT_USE_CONSTEXPR\n# define FMT_CONSTEXPR constexpr\n# define FMT_CONSTEXPR_DECL constexpr\n#else\n# define FMT_CONSTEXPR inline\n# define FMT_CONSTEXPR_DECL\n#endif\n\n#ifndef FMT_USE_CONSTEXPR11\n# define FMT_USE_CONSTEXPR11 \\\n    (FMT_USE_CONSTEXPR || FMT_GCC_VERSION >= 406 || FMT_MSC_VER >= 1900)\n#endif\n#if FMT_USE_CONSTEXPR11\n# define FMT_CONSTEXPR11 constexpr\n#else\n# define FMT_CONSTEXPR11\n#endif\n\n#ifndef FMT_OVERRIDE\n# if FMT_HAS_FEATURE(cxx_override) || \\\n     (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900\n#  define FMT_OVERRIDE override\n# else\n#  define FMT_OVERRIDE\n# endif\n#endif\n\n#if FMT_HAS_FEATURE(cxx_explicit_conversions) || \\\n    FMT_GCC_VERSION >= 405 || FMT_MSC_VER >= 1800\n# define FMT_USE_EXPLICIT 1\n# define FMT_EXPLICIT explicit\n#else\n# define FMT_USE_EXPLICIT 0\n# define FMT_EXPLICIT\n#endif\n\n#ifndef FMT_NULL\n# if FMT_HAS_FEATURE(cxx_nullptr) || \\\n   (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1600\n#  define FMT_NULL nullptr\n#  define FMT_USE_NULLPTR 1\n# else\n#  define FMT_NULL NULL\n# endif\n#endif\n#ifndef FMT_USE_NULLPTR\n# define FMT_USE_NULLPTR 0\n#endif\n\n// Check if exceptions are disabled.\n#if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \\\n    FMT_MSC_VER && !_HAS_EXCEPTIONS\n# define FMT_EXCEPTIONS 0\n#else\n# define FMT_EXCEPTIONS 1\n#endif\n\n// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature).\n#ifndef FMT_USE_NOEXCEPT\n# define FMT_USE_NOEXCEPT 0\n#endif\n\n#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \\\n    (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900\n# define FMT_DETECTED_NOEXCEPT noexcept\n# define FMT_HAS_CXX11_NOEXCEPT 1\n#else\n# define FMT_DETECTED_NOEXCEPT throw()\n# define FMT_HAS_CXX11_NOEXCEPT 0\n#endif\n\n#ifndef FMT_NOEXCEPT\n# if FMT_EXCEPTIONS || FMT_HAS_CXX11_NOEXCEPT\n#  define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT\n# else\n#  define FMT_NOEXCEPT\n# endif\n#endif\n\n#ifndef FMT_BEGIN_NAMESPACE\n# if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \\\n     FMT_MSC_VER >= 1900\n#  define FMT_INLINE_NAMESPACE inline namespace\n#  define FMT_END_NAMESPACE }}\n# else\n#  define FMT_INLINE_NAMESPACE namespace\n#  define FMT_END_NAMESPACE } using namespace v5; }\n# endif\n# define FMT_BEGIN_NAMESPACE namespace fmt { FMT_INLINE_NAMESPACE v5 {\n#endif\n\n#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)\n# ifdef FMT_EXPORT\n#  define FMT_API __declspec(dllexport)\n# elif defined(FMT_SHARED)\n#  define FMT_API __declspec(dllimport)\n# endif\n#endif\n#ifndef FMT_API\n# define FMT_API\n#endif\n\n#ifndef FMT_ASSERT\n# define FMT_ASSERT(condition, message) assert((condition) && message)\n#endif\n\n// libc++ supports string_view in pre-c++17.\n#if (FMT_HAS_INCLUDE(<string_view>) && \\\n      (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \\\n    (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)\n# include <string_view>\n# define FMT_STRING_VIEW std::basic_string_view\n#elif FMT_HAS_INCLUDE(<experimental/string_view>) && __cplusplus >= 201402L\n# include <experimental/string_view>\n# define FMT_STRING_VIEW std::experimental::basic_string_view\n#endif\n\n// std::result_of is defined in <functional> in gcc 4.4.\n#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 404\n# include <functional>\n#endif\n\nFMT_BEGIN_NAMESPACE\nnamespace internal {\n\n// An implementation of declval for pre-C++11 compilers such as gcc 4.\ntemplate <typename T>\ntypename std::add_rvalue_reference<T>::type declval() FMT_NOEXCEPT;\n\ntemplate <typename>\nstruct result_of;\n\ntemplate <typename F, typename... Args>\nstruct result_of<F(Args...)> {\n  // A workaround for gcc 4.4 that doesn't allow F to be a reference.\n  typedef typename std::result_of<\n    typename std::remove_reference<F>::type(Args...)>::type type;\n};\n\n// Casts nonnegative integer to unsigned.\ntemplate <typename Int>\nFMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value) {\n  FMT_ASSERT(value >= 0, \"negative value\");\n  return static_cast<typename std::make_unsigned<Int>::type>(value);\n}\n\n/** A contiguous memory buffer with an optional growing ability. */\ntemplate <typename T>\nclass basic_buffer {\n private:\n  basic_buffer(const basic_buffer &) = delete;\n  void operator=(const basic_buffer &) = delete;\n\n  T *ptr_;\n  std::size_t size_;\n  std::size_t capacity_;\n\n protected:\n  // Don't initialize ptr_ since it is not accessed to save a few cycles.\n  basic_buffer(std::size_t sz) FMT_NOEXCEPT: size_(sz), capacity_(sz) {}\n\n  basic_buffer(T *p = FMT_NULL, std::size_t sz = 0, std::size_t cap = 0)\n    FMT_NOEXCEPT: ptr_(p), size_(sz), capacity_(cap) {}\n\n  /** Sets the buffer data and capacity. */\n  void set(T *buf_data, std::size_t buf_capacity) FMT_NOEXCEPT {\n    ptr_ = buf_data;\n    capacity_ = buf_capacity;\n  }\n\n  /** Increases the buffer capacity to hold at least *capacity* elements. */\n  virtual void grow(std::size_t capacity) = 0;\n\n public:\n  typedef T value_type;\n  typedef const T &const_reference;\n\n  virtual ~basic_buffer() {}\n\n  T *begin() FMT_NOEXCEPT { return ptr_; }\n  T *end() FMT_NOEXCEPT { return ptr_ + size_; }\n\n  /** Returns the size of this buffer. */\n  std::size_t size() const FMT_NOEXCEPT { return size_; }\n\n  /** Returns the capacity of this buffer. */\n  std::size_t capacity() const FMT_NOEXCEPT { return capacity_; }\n\n  /** Returns a pointer to the buffer data. */\n  T *data() FMT_NOEXCEPT { return ptr_; }\n\n  /** Returns a pointer to the buffer data. */\n  const T *data() const FMT_NOEXCEPT { return ptr_; }\n\n  /**\n    Resizes the buffer. If T is a POD type new elements may not be initialized.\n   */\n  void resize(std::size_t new_size) {\n    reserve(new_size);\n    size_ = new_size;\n  }\n\n  /** Clears this buffer. */\n  void clear() { size_ = 0; }\n\n  /** Reserves space to store at least *capacity* elements. */\n  void reserve(std::size_t new_capacity) {\n    if (new_capacity > capacity_)\n      grow(new_capacity);\n  }\n\n  void push_back(const T &value) {\n    reserve(size_ + 1);\n    ptr_[size_++] = value;\n  }\n\n  /** Appends data to the end of the buffer. */\n  template <typename U>\n  void append(const U *begin, const U *end);\n\n  T &operator[](std::size_t index) { return ptr_[index]; }\n  const T &operator[](std::size_t index) const { return ptr_[index]; }\n};\n\ntypedef basic_buffer<char> buffer;\ntypedef basic_buffer<wchar_t> wbuffer;\n\n// A container-backed buffer.\ntemplate <typename Container>\nclass container_buffer : public basic_buffer<typename Container::value_type> {\n private:\n  Container &container_;\n\n protected:\n  void grow(std::size_t capacity) FMT_OVERRIDE {\n    container_.resize(capacity);\n    this->set(&container_[0], capacity);\n  }\n\n public:\n  explicit container_buffer(Container &c)\n    : basic_buffer<typename Container::value_type>(c.size()), container_(c) {}\n};\n\n// Extracts a reference to the container from back_insert_iterator.\ntemplate <typename Container>\ninline Container &get_container(std::back_insert_iterator<Container> it) {\n  typedef std::back_insert_iterator<Container> bi_iterator;\n  struct accessor: bi_iterator {\n    accessor(bi_iterator iter) : bi_iterator(iter) {}\n    using bi_iterator::container;\n  };\n  return *accessor(it).container;\n}\n\nstruct error_handler {\n  FMT_CONSTEXPR error_handler() {}\n  FMT_CONSTEXPR error_handler(const error_handler &) {}\n\n  // This function is intentionally not constexpr to give a compile-time error.\n  FMT_API void on_error(const char *message);\n};\n\ntemplate <typename T>\nstruct no_formatter_error : std::false_type {};\n}  // namespace internal\n\n#if FMT_GCC_VERSION && FMT_GCC_VERSION < 405\ntemplate <typename... T>\nstruct is_constructible: std::false_type {};\n#else\ntemplate <typename... T>\nstruct is_constructible : std::is_constructible<T...> {};\n#endif\n\n/**\n  An implementation of ``std::basic_string_view`` for pre-C++17. It provides a\n  subset of the API. ``fmt::basic_string_view`` is used for format strings even\n  if ``std::string_view`` is available to prevent issues when a library is\n  compiled with a different ``-std`` option than the client code (which is not\n  recommended).\n */\ntemplate <typename Char>\nclass basic_string_view {\n private:\n  const Char *data_;\n  size_t size_;\n\n public:\n  typedef Char char_type;\n  typedef const Char *iterator;\n\n  FMT_CONSTEXPR basic_string_view() FMT_NOEXCEPT : data_(FMT_NULL), size_(0) {}\n\n  /** Constructs a string reference object from a C string and a size. */\n  FMT_CONSTEXPR basic_string_view(const Char *s, size_t count) FMT_NOEXCEPT\n    : data_(s), size_(count) {}\n\n  /**\n    \\rst\n    Constructs a string reference object from a C string computing\n    the size with ``std::char_traits<Char>::length``.\n    \\endrst\n   */\n  basic_string_view(const Char *s)\n    : data_(s), size_(std::char_traits<Char>::length(s)) {}\n\n  /** Constructs a string reference from a ``std::basic_string`` object. */\n  template <typename Alloc>\n  FMT_CONSTEXPR basic_string_view(\n      const std::basic_string<Char, Alloc> &s) FMT_NOEXCEPT\n  : data_(s.data()), size_(s.size()) {}\n\n#ifdef FMT_STRING_VIEW\n  FMT_CONSTEXPR basic_string_view(FMT_STRING_VIEW<Char> s) FMT_NOEXCEPT\n  : data_(s.data()), size_(s.size()) {}\n#endif\n\n  /** Returns a pointer to the string data. */\n  FMT_CONSTEXPR const Char *data() const { return data_; }\n\n  /** Returns the string size. */\n  FMT_CONSTEXPR size_t size() const { return size_; }\n\n  FMT_CONSTEXPR iterator begin() const { return data_; }\n  FMT_CONSTEXPR iterator end() const { return data_ + size_; }\n\n  FMT_CONSTEXPR void remove_prefix(size_t n) {\n    data_ += n;\n    size_ -= n;\n  }\n\n  // Lexicographically compare this string reference to other.\n  int compare(basic_string_view other) const {\n    size_t str_size = size_ < other.size_ ? size_ : other.size_;\n    int result = std::char_traits<Char>::compare(data_, other.data_, str_size);\n    if (result == 0)\n      result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);\n    return result;\n  }\n\n  friend bool operator==(basic_string_view lhs, basic_string_view rhs) {\n    return lhs.compare(rhs) == 0;\n  }\n  friend bool operator!=(basic_string_view lhs, basic_string_view rhs) {\n    return lhs.compare(rhs) != 0;\n  }\n  friend bool operator<(basic_string_view lhs, basic_string_view rhs) {\n    return lhs.compare(rhs) < 0;\n  }\n  friend bool operator<=(basic_string_view lhs, basic_string_view rhs) {\n    return lhs.compare(rhs) <= 0;\n  }\n  friend bool operator>(basic_string_view lhs, basic_string_view rhs) {\n    return lhs.compare(rhs) > 0;\n  }\n  friend bool operator>=(basic_string_view lhs, basic_string_view rhs) {\n    return lhs.compare(rhs) >= 0;\n  }\n};\n\ntypedef basic_string_view<char> string_view;\ntypedef basic_string_view<wchar_t> wstring_view;\n\n/**\n  \\rst\n  The function ``to_string_view`` adapts non-intrusively any kind of string or\n  string-like type if the user provides a (possibly templated) overload of\n  ``to_string_view`` which takes an instance of the string class\n  ``StringType<Char>`` and returns a ``fmt::basic_string_view<Char>``.\n  The conversion function must live in the very same namespace as\n  ``StringType<Char>`` to be picked up by ADL. Non-templated string types\n  like f.e. QString must return a ``basic_string_view`` with a fixed matching\n  char type.\n\n  **Example**::\n\n    namespace my_ns {\n    inline string_view to_string_view(const my_string &s) {\n        return { s.data(), s.length() };\n    }\n    }\n\n    std::string message = fmt::format(my_string(\"The answer is {}\"), 42);\n  \\endrst\n */\ntemplate <typename Char>\ninline basic_string_view<Char>\n  to_string_view(basic_string_view<Char> s) { return s; }\n\ntemplate <typename Char>\ninline basic_string_view<Char>\n  to_string_view(const std::basic_string<Char> &s) { return s; }\n\ntemplate <typename Char>\ninline basic_string_view<Char> to_string_view(const Char *s) { return s; }\n\n#ifdef FMT_STRING_VIEW\ntemplate <typename Char>\ninline basic_string_view<Char>\n  to_string_view(FMT_STRING_VIEW<Char> s) { return s; }\n#endif\n\n// A base class for compile-time strings. It is defined in the fmt namespace to\n// make formatting functions visible via ADL, e.g. format(fmt(\"{}\"), 42).\nstruct compile_string {};\n\ntemplate <typename S>\nstruct is_compile_string : std::is_base_of<compile_string, S> {};\n\ntemplate <\n  typename S,\n  typename Enable = typename std::enable_if<is_compile_string<S>::value>::type>\nFMT_CONSTEXPR basic_string_view<typename S::char_type>\n  to_string_view(const S &s) { return s; }\n\ntemplate <typename Context>\nclass basic_format_arg;\n\ntemplate <typename Context>\nclass basic_format_args;\n\n// A formatter for objects of type T.\ntemplate <typename T, typename Char = char, typename Enable = void>\nstruct formatter {\n  static_assert(internal::no_formatter_error<T>::value,\n    \"don't know how to format the type, include fmt/ostream.h if it provides \"\n    \"an operator<< that should be used\");\n\n  // The following functions are not defined intentionally.\n  template <typename ParseContext>\n  typename ParseContext::iterator parse(ParseContext &);\n  template <typename FormatContext>\n  auto format(const T &val, FormatContext &ctx) -> decltype(ctx.out());\n};\n\ntemplate <typename T, typename Char, typename Enable = void>\nstruct convert_to_int: std::integral_constant<\n  bool, !std::is_arithmetic<T>::value && std::is_convertible<T, int>::value> {};\n\nnamespace internal {\n\nstruct dummy_string_view { typedef void char_type; };\ndummy_string_view to_string_view(...);\nusing fmt::v5::to_string_view;\n\n// Specifies whether S is a string type convertible to fmt::basic_string_view.\ntemplate <typename S>\nstruct is_string : std::integral_constant<bool, !std::is_same<\n    dummy_string_view, decltype(to_string_view(declval<S>()))>::value> {};\n\ntemplate <typename S>\nstruct char_t {\n  typedef decltype(to_string_view(declval<S>())) result;\n  typedef typename result::char_type type;\n};\n\ntemplate <typename Char>\nstruct named_arg_base;\n\ntemplate <typename T, typename Char>\nstruct named_arg;\n\nenum type {\n  none_type, named_arg_type,\n  // Integer types should go first,\n  int_type, uint_type, long_long_type, ulong_long_type, bool_type, char_type,\n  last_integer_type = char_type,\n  // followed by floating-point types.\n  double_type, long_double_type, last_numeric_type = long_double_type,\n  cstring_type, string_type, pointer_type, custom_type\n};\n\nFMT_CONSTEXPR bool is_integral(type t) {\n  FMT_ASSERT(t != internal::named_arg_type, \"invalid argument type\");\n  return t > internal::none_type && t <= internal::last_integer_type;\n}\n\nFMT_CONSTEXPR bool is_arithmetic(type t) {\n  FMT_ASSERT(t != internal::named_arg_type, \"invalid argument type\");\n  return t > internal::none_type && t <= internal::last_numeric_type;\n}\n\ntemplate <typename Char>\nstruct string_value {\n  const Char *value;\n  std::size_t size;\n};\n\ntemplate <typename Context>\nstruct custom_value {\n  const void *value;\n  void (*format)(const void *arg, Context &ctx);\n};\n\n// A formatting argument value.\ntemplate <typename Context>\nclass value {\n public:\n  typedef typename Context::char_type char_type;\n\n  union {\n    int int_value;\n    unsigned uint_value;\n    long long long_long_value;\n    unsigned long long ulong_long_value;\n    double double_value;\n    long double long_double_value;\n    const void *pointer;\n    string_value<char_type> string;\n    string_value<signed char> sstring;\n    string_value<unsigned char> ustring;\n    custom_value<Context> custom;\n  };\n\n  FMT_CONSTEXPR value(int val = 0) : int_value(val) {}\n  value(unsigned val) { uint_value = val; }\n  value(long long val) { long_long_value = val; }\n  value(unsigned long long val) { ulong_long_value = val; }\n  value(double val) { double_value = val; }\n  value(long double val) { long_double_value = val; }\n  value(const char_type *val) { string.value = val; }\n  value(const signed char *val) {\n    static_assert(std::is_same<char, char_type>::value,\n                  \"incompatible string types\");\n    sstring.value = val;\n  }\n  value(const unsigned char *val) {\n    static_assert(std::is_same<char, char_type>::value,\n                  \"incompatible string types\");\n    ustring.value = val;\n  }\n  value(basic_string_view<char_type> val) {\n    string.value = val.data();\n    string.size = val.size();\n  }\n  value(const void *val) { pointer = val; }\n\n  template <typename T>\n  explicit value(const T &val) {\n    custom.value = &val;\n    custom.format = &format_custom_arg<T>;\n  }\n\n  const named_arg_base<char_type> &as_named_arg() {\n    return *static_cast<const named_arg_base<char_type>*>(pointer);\n  }\n\n private:\n  // Formats an argument of a custom type, such as a user-defined class.\n  template <typename T>\n  static void format_custom_arg(const void *arg, Context &ctx) {\n    // Get the formatter type through the context to allow different contexts\n    // have different extension points, e.g. `formatter<T>` for `format` and\n    // `printf_formatter<T>` for `printf`.\n    typename Context::template formatter_type<T>::type f;\n    auto &&parse_ctx = ctx.parse_context();\n    parse_ctx.advance_to(f.parse(parse_ctx));\n    ctx.advance_to(f.format(*static_cast<const T*>(arg), ctx));\n  }\n};\n\n// Value initializer used to delay conversion to value and reduce memory churn.\ntemplate <typename Context, typename T, type TYPE>\nstruct init {\n  T val;\n  static const type type_tag = TYPE;\n\n  FMT_CONSTEXPR init(const T &v) : val(v) {}\n  FMT_CONSTEXPR operator value<Context>() const { return value<Context>(val); }\n};\n\ntemplate <typename Context, typename T>\nFMT_CONSTEXPR basic_format_arg<Context> make_arg(const T &value);\n\n#define FMT_MAKE_VALUE(TAG, ArgType, ValueType) \\\n  template <typename C> \\\n  FMT_CONSTEXPR init<C, ValueType, TAG> make_value(ArgType val) { \\\n    return static_cast<ValueType>(val); \\\n  }\n\n#define FMT_MAKE_VALUE_SAME(TAG, Type) \\\n  template <typename C> \\\n  FMT_CONSTEXPR init<C, Type, TAG> make_value(Type val) { return val; }\n\nFMT_MAKE_VALUE(bool_type, bool, int)\nFMT_MAKE_VALUE(int_type, short, int)\nFMT_MAKE_VALUE(uint_type, unsigned short, unsigned)\nFMT_MAKE_VALUE_SAME(int_type, int)\nFMT_MAKE_VALUE_SAME(uint_type, unsigned)\n\n// To minimize the number of types we need to deal with, long is translated\n// either to int or to long long depending on its size.\ntypedef std::conditional<sizeof(long) == sizeof(int), int, long long>::type\n        long_type;\nFMT_MAKE_VALUE(\n    (sizeof(long) == sizeof(int) ? int_type : long_long_type), long, long_type)\ntypedef std::conditional<sizeof(unsigned long) == sizeof(unsigned),\n                         unsigned, unsigned long long>::type ulong_type;\nFMT_MAKE_VALUE(\n    (sizeof(unsigned long) == sizeof(unsigned) ? uint_type : ulong_long_type),\n    unsigned long, ulong_type)\n\nFMT_MAKE_VALUE_SAME(long_long_type, long long)\nFMT_MAKE_VALUE_SAME(ulong_long_type, unsigned long long)\nFMT_MAKE_VALUE(int_type, signed char, int)\nFMT_MAKE_VALUE(uint_type, unsigned char, unsigned)\n\n// This doesn't use FMT_MAKE_VALUE because of ambiguity in gcc 4.4.\ntemplate <typename C, typename Char>\nFMT_CONSTEXPR typename std::enable_if<\n  std::is_same<typename C::char_type, Char>::value,\n  init<C, int, char_type>>::type make_value(Char val) { return val; }\n\ntemplate <typename C>\nFMT_CONSTEXPR typename std::enable_if<\n  !std::is_same<typename C::char_type, char>::value,\n  init<C, int, char_type>>::type make_value(char val) { return val; }\n\nFMT_MAKE_VALUE(double_type, float, double)\nFMT_MAKE_VALUE_SAME(double_type, double)\nFMT_MAKE_VALUE_SAME(long_double_type, long double)\n\n// Formatting of wide strings into a narrow buffer and multibyte strings\n// into a wide buffer is disallowed (https://github.com/fmtlib/fmt/pull/606).\nFMT_MAKE_VALUE(cstring_type, typename C::char_type*,\n               const typename C::char_type*)\nFMT_MAKE_VALUE(cstring_type, const typename C::char_type*,\n               const typename C::char_type*)\n\nFMT_MAKE_VALUE(cstring_type, signed char*, const signed char*)\nFMT_MAKE_VALUE_SAME(cstring_type, const signed char*)\nFMT_MAKE_VALUE(cstring_type, unsigned char*, const unsigned char*)\nFMT_MAKE_VALUE_SAME(cstring_type, const unsigned char*)\nFMT_MAKE_VALUE_SAME(string_type, basic_string_view<typename C::char_type>)\nFMT_MAKE_VALUE(string_type,\n               typename basic_string_view<typename C::char_type>::type,\n               basic_string_view<typename C::char_type>)\nFMT_MAKE_VALUE(string_type, const std::basic_string<typename C::char_type>&,\n               basic_string_view<typename C::char_type>)\nFMT_MAKE_VALUE(pointer_type, void*, const void*)\nFMT_MAKE_VALUE_SAME(pointer_type, const void*)\n\n#if FMT_USE_NULLPTR\nFMT_MAKE_VALUE(pointer_type, std::nullptr_t, const void*)\n#endif\n\n// Formatting of arbitrary pointers is disallowed. If you want to output a\n// pointer cast it to \"void *\" or \"const void *\". In particular, this forbids\n// formatting of \"[const] volatile char *\" which is printed as bool by\n// iostreams.\ntemplate <typename C, typename T>\ntypename std::enable_if<!std::is_same<T, typename C::char_type>::value>::type\n    make_value(const T *) {\n  static_assert(!sizeof(T), \"formatting of non-void pointers is disallowed\");\n}\n\ntemplate <typename C, typename T>\ninline typename std::enable_if<\n    std::is_enum<T>::value && convert_to_int<T, typename C::char_type>::value,\n    init<C, int, int_type>>::type\n  make_value(const T &val) { return static_cast<int>(val); }\n\ntemplate <typename C, typename T, typename Char = typename C::char_type>\ninline typename std::enable_if<\n    is_constructible<basic_string_view<Char>, T>::value &&\n    !internal::is_string<T>::value,\n    init<C, basic_string_view<Char>, string_type>>::type\n  make_value(const T &val) { return basic_string_view<Char>(val); }\n\ntemplate <typename C, typename T, typename Char = typename C::char_type>\ninline typename std::enable_if<\n    !convert_to_int<T, Char>::value && !std::is_same<T, Char>::value &&\n    !std::is_convertible<T, basic_string_view<Char>>::value &&\n    !is_constructible<basic_string_view<Char>, T>::value &&\n    !internal::is_string<T>::value,\n    // Implicit conversion to std::string is not handled here because it's\n    // unsafe: https://github.com/fmtlib/fmt/issues/729\n    init<C, const T &, custom_type>>::type\n  make_value(const T &val) { return val; }\n\ntemplate <typename C, typename T>\ninit<C, const void*, named_arg_type>\n    make_value(const named_arg<T, typename C::char_type> &val) {\n  basic_format_arg<C> arg = make_arg<C>(val.value);\n  std::memcpy(val.data, &arg, sizeof(arg));\n  return static_cast<const void*>(&val);\n}\n\ntemplate <typename C, typename S>\nFMT_CONSTEXPR11 typename std::enable_if<\n  internal::is_string<S>::value,\n  init<C, basic_string_view<typename C::char_type>, string_type>>::type\n    make_value(const S &val) {\n  // Handle adapted strings.\n  static_assert(std::is_same<\n    typename C::char_type, typename internal::char_t<S>::type>::value,\n    \"mismatch between char-types of context and argument\");\n  return to_string_view(val);\n}\n\n// Maximum number of arguments with packed types.\nenum { max_packed_args = 15 };\n\ntemplate <typename Context>\nclass arg_map;\n}  // namespace internal\n\n// A formatting argument. It is a trivially copyable/constructible type to\n// allow storage in basic_memory_buffer.\ntemplate <typename Context>\nclass basic_format_arg {\n private:\n  internal::value<Context> value_;\n  internal::type type_;\n\n  template <typename ContextType, typename T>\n  friend FMT_CONSTEXPR basic_format_arg<ContextType>\n    internal::make_arg(const T &value);\n\n  template <typename Visitor, typename Ctx>\n  friend FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type\n    visit_format_arg(Visitor &&vis, const basic_format_arg<Ctx> &arg);\n\n  friend class basic_format_args<Context>;\n  friend class internal::arg_map<Context>;\n\n  typedef typename Context::char_type char_type;\n\n public:\n  class handle {\n   public:\n    explicit handle(internal::custom_value<Context> custom): custom_(custom) {}\n\n    void format(Context &ctx) const { custom_.format(custom_.value, ctx); }\n\n   private:\n    internal::custom_value<Context> custom_;\n  };\n\n  FMT_CONSTEXPR basic_format_arg() : type_(internal::none_type) {}\n\n  FMT_EXPLICIT operator bool() const FMT_NOEXCEPT {\n    return type_ != internal::none_type;\n  }\n\n  internal::type type() const { return type_; }\n\n  bool is_integral() const { return internal::is_integral(type_); }\n  bool is_arithmetic() const { return internal::is_arithmetic(type_); }\n};\n\nstruct monostate {};\n\n/**\n  \\rst\n  Visits an argument dispatching to the appropriate visit method based on\n  the argument type. For example, if the argument type is ``double`` then\n  ``vis(value)`` will be called with the value of type ``double``.\n  \\endrst\n */\ntemplate <typename Visitor, typename Context>\nFMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type\n    visit_format_arg(Visitor &&vis, const basic_format_arg<Context> &arg) {\n  typedef typename Context::char_type char_type;\n  switch (arg.type_) {\n  case internal::none_type:\n    break;\n  case internal::named_arg_type:\n    FMT_ASSERT(false, \"invalid argument type\");\n    break;\n  case internal::int_type:\n    return vis(arg.value_.int_value);\n  case internal::uint_type:\n    return vis(arg.value_.uint_value);\n  case internal::long_long_type:\n    return vis(arg.value_.long_long_value);\n  case internal::ulong_long_type:\n    return vis(arg.value_.ulong_long_value);\n  case internal::bool_type:\n    return vis(arg.value_.int_value != 0);\n  case internal::char_type:\n    return vis(static_cast<char_type>(arg.value_.int_value));\n  case internal::double_type:\n    return vis(arg.value_.double_value);\n  case internal::long_double_type:\n    return vis(arg.value_.long_double_value);\n  case internal::cstring_type:\n    return vis(arg.value_.string.value);\n  case internal::string_type:\n    return vis(basic_string_view<char_type>(\n                 arg.value_.string.value, arg.value_.string.size));\n  case internal::pointer_type:\n    return vis(arg.value_.pointer);\n  case internal::custom_type:\n    return vis(typename basic_format_arg<Context>::handle(arg.value_.custom));\n  }\n  return vis(monostate());\n}\n\ntemplate <typename Visitor, typename Context>\nFMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type\n    visit(Visitor &&vis, const basic_format_arg<Context> &arg) {\n  return visit_format_arg(std::forward<Visitor>(vis), arg);\n}\n\n// Parsing context consisting of a format string range being parsed and an\n// argument counter for automatic indexing.\ntemplate <typename Char, typename ErrorHandler = internal::error_handler>\nclass basic_parse_context : private ErrorHandler {\n private:\n  basic_string_view<Char> format_str_;\n  int next_arg_id_;\n\n public:\n  typedef Char char_type;\n  typedef typename basic_string_view<Char>::iterator iterator;\n\n  explicit FMT_CONSTEXPR basic_parse_context(\n      basic_string_view<Char> format_str, ErrorHandler eh = ErrorHandler())\n    : ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {}\n\n  // Returns an iterator to the beginning of the format string range being\n  // parsed.\n  FMT_CONSTEXPR iterator begin() const FMT_NOEXCEPT {\n    return format_str_.begin();\n  }\n\n  // Returns an iterator past the end of the format string range being parsed.\n  FMT_CONSTEXPR iterator end() const FMT_NOEXCEPT { return format_str_.end(); }\n\n  // Advances the begin iterator to ``it``.\n  FMT_CONSTEXPR void advance_to(iterator it) {\n    format_str_.remove_prefix(internal::to_unsigned(it - begin()));\n  }\n\n  // Returns the next argument index.\n  FMT_CONSTEXPR unsigned next_arg_id();\n\n  FMT_CONSTEXPR bool check_arg_id(unsigned) {\n    if (next_arg_id_ > 0) {\n      on_error(\"cannot switch from automatic to manual argument indexing\");\n      return false;\n    }\n    next_arg_id_ = -1;\n    return true;\n  }\n  void check_arg_id(basic_string_view<Char>) {}\n\n  FMT_CONSTEXPR void on_error(const char *message) {\n    ErrorHandler::on_error(message);\n  }\n\n  FMT_CONSTEXPR ErrorHandler error_handler() const { return *this; }\n};\n\ntypedef basic_parse_context<char> parse_context;\ntypedef basic_parse_context<wchar_t> wparse_context;\n\nnamespace internal {\n// A map from argument names to their values for named arguments.\ntemplate <typename Context>\nclass arg_map {\n private:\n  arg_map(const arg_map &) = delete;\n  void operator=(const arg_map &) = delete;\n\n  typedef typename Context::char_type char_type;\n\n  struct entry {\n    basic_string_view<char_type> name;\n    basic_format_arg<Context> arg;\n  };\n\n  entry *map_;\n  unsigned size_;\n\n  void push_back(value<Context> val) {\n    const internal::named_arg_base<char_type> &named = val.as_named_arg();\n    map_[size_] = entry{named.name, named.template deserialize<Context>()};\n    ++size_;\n  }\n\n public:\n  arg_map() : map_(FMT_NULL), size_(0) {}\n  void init(const basic_format_args<Context> &args);\n  ~arg_map() { delete [] map_; }\n\n  basic_format_arg<Context> find(basic_string_view<char_type> name) const {\n    // The list is unsorted, so just return the first matching name.\n    for (entry *it = map_, *end = map_ + size_; it != end; ++it) {\n      if (it->name == name)\n        return it->arg;\n    }\n    return {};\n  }\n};\n\n// A type-erased reference to an std::locale to avoid heavy <locale> include.\nclass locale_ref {\n private:\n  const void *locale_;  // A type-erased pointer to std::locale.\n  friend class locale;\n\n public:\n  locale_ref() : locale_(FMT_NULL) {}\n\n  template <typename Locale>\n  explicit locale_ref(const Locale &loc);\n\n  template <typename Locale>\n  Locale get() const;\n};\n\ntemplate <typename OutputIt, typename Context, typename Char>\nclass context_base {\n public:\n  typedef OutputIt iterator;\n\n private:\n  basic_parse_context<Char> parse_context_;\n  iterator out_;\n  basic_format_args<Context> args_;\n  locale_ref loc_;\n\n protected:\n  typedef Char char_type;\n  typedef basic_format_arg<Context> format_arg;\n\n  context_base(OutputIt out, basic_string_view<char_type> format_str,\n               basic_format_args<Context> ctx_args,\n               locale_ref loc = locale_ref())\n  : parse_context_(format_str), out_(out), args_(ctx_args), loc_(loc) {}\n\n  // Returns the argument with specified index.\n  format_arg do_get_arg(unsigned arg_id) {\n    format_arg arg = args_.get(arg_id);\n    if (!arg)\n      parse_context_.on_error(\"argument index out of range\");\n    return arg;\n  }\n\n  // Checks if manual indexing is used and returns the argument with\n  // specified index.\n  format_arg get_arg(unsigned arg_id) {\n    return this->parse_context().check_arg_id(arg_id) ?\n      this->do_get_arg(arg_id) : format_arg();\n  }\n\n public:\n  basic_parse_context<char_type> &parse_context() { return parse_context_; }\n  basic_format_args<Context> args() const { return args_; }\n\n  internal::error_handler error_handler() {\n    return parse_context_.error_handler();\n  }\n\n  void on_error(const char *message) { parse_context_.on_error(message); }\n\n  // Returns an iterator to the beginning of the output range.\n  iterator out() { return out_; }\n  iterator begin() { return out_; }  // deprecated\n\n  // Advances the begin iterator to ``it``.\n  void advance_to(iterator it) { out_ = it; }\n\n  locale_ref locale() { return loc_; }\n};\n\ntemplate <typename Context, typename T>\nstruct get_type {\n  typedef decltype(make_value<Context>(\n        declval<typename std::decay<T>::type&>())) value_type;\n  static const type value = value_type::type_tag;\n};\n\ntemplate <typename Context>\nFMT_CONSTEXPR11 unsigned long long get_types() { return 0; }\n\ntemplate <typename Context, typename Arg, typename... Args>\nFMT_CONSTEXPR11 unsigned long long get_types() {\n  return get_type<Context, Arg>::value | (get_types<Context, Args...>() << 4);\n}\n\ntemplate <typename Context, typename T>\nFMT_CONSTEXPR basic_format_arg<Context> make_arg(const T &value) {\n  basic_format_arg<Context> arg;\n  arg.type_ = get_type<Context, T>::value;\n  arg.value_ = make_value<Context>(value);\n  return arg;\n}\n\ntemplate <bool IS_PACKED, typename Context, typename T>\ninline typename std::enable_if<IS_PACKED, value<Context>>::type\n    make_arg(const T &value) {\n  return make_value<Context>(value);\n}\n\ntemplate <bool IS_PACKED, typename Context, typename T>\ninline typename std::enable_if<!IS_PACKED, basic_format_arg<Context>>::type\n    make_arg(const T &value) {\n  return make_arg<Context>(value);\n}\n}  // namespace internal\n\n// Formatting context.\ntemplate <typename OutputIt, typename Char>\nclass basic_format_context :\n  public internal::context_base<\n    OutputIt, basic_format_context<OutputIt, Char>, Char> {\n public:\n  /** The character type for the output. */\n  typedef Char char_type;\n\n  // using formatter_type = formatter<T, char_type>;\n  template <typename T>\n  struct formatter_type { typedef formatter<T, char_type> type; };\n\n private:\n  internal::arg_map<basic_format_context> map_;\n\n  basic_format_context(const basic_format_context &) = delete;\n  void operator=(const basic_format_context &) = delete;\n\n  typedef internal::context_base<OutputIt, basic_format_context, Char> base;\n  typedef typename base::format_arg format_arg;\n  using base::get_arg;\n\n public:\n  using typename base::iterator;\n\n  /**\n   Constructs a ``basic_format_context`` object. References to the arguments are\n   stored in the object so make sure they have appropriate lifetimes.\n   */\n  basic_format_context(OutputIt out, basic_string_view<char_type> format_str,\n                       basic_format_args<basic_format_context> ctx_args,\n                       internal::locale_ref loc = internal::locale_ref())\n    : base(out, format_str, ctx_args, loc) {}\n\n  format_arg next_arg() {\n    return this->do_get_arg(this->parse_context().next_arg_id());\n  }\n  format_arg get_arg(unsigned arg_id) { return this->do_get_arg(arg_id); }\n\n  // Checks if manual indexing is used and returns the argument with the\n  // specified name.\n  format_arg get_arg(basic_string_view<char_type> name);\n};\n\ntemplate <typename Char>\nstruct buffer_context {\n  typedef basic_format_context<\n    std::back_insert_iterator<internal::basic_buffer<Char>>, Char> type;\n};\ntypedef buffer_context<char>::type format_context;\ntypedef buffer_context<wchar_t>::type wformat_context;\n\n/**\n  \\rst\n  An array of references to arguments. It can be implicitly converted into\n  `~fmt::basic_format_args` for passing into type-erased formatting functions\n  such as `~fmt::vformat`.\n  \\endrst\n */\ntemplate <typename Context, typename ...Args>\nclass format_arg_store {\n private:\n  static const size_t NUM_ARGS = sizeof...(Args);\n\n  // Packed is a macro on MinGW so use IS_PACKED instead.\n  static const bool IS_PACKED = NUM_ARGS < internal::max_packed_args;\n\n  typedef typename std::conditional<IS_PACKED,\n    internal::value<Context>, basic_format_arg<Context>>::type value_type;\n\n  // If the arguments are not packed, add one more element to mark the end.\n  static const size_t DATA_SIZE =\n          NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1);\n  value_type data_[DATA_SIZE];\n\n  friend class basic_format_args<Context>;\n\n  static FMT_CONSTEXPR11 long long get_types() {\n    return IS_PACKED ?\n      static_cast<long long>(internal::get_types<Context, Args...>()) :\n      -static_cast<long long>(NUM_ARGS);\n  }\n\n public:\n#if FMT_USE_CONSTEXPR11\n  static FMT_CONSTEXPR11 long long TYPES = get_types();\n#else\n  static const long long TYPES;\n#endif\n\n#if (FMT_GCC_VERSION && FMT_GCC_VERSION <= 405) || \\\n    (FMT_MSC_VER && FMT_MSC_VER <= 1800)\n  // Workaround array initialization issues in gcc <= 4.5 and MSVC <= 2013.\n  format_arg_store(const Args &... args) {\n    value_type init[DATA_SIZE] =\n      {internal::make_arg<IS_PACKED, Context>(args)...};\n    std::memcpy(data_, init, sizeof(init));\n  }\n#else\n  format_arg_store(const Args &... args)\n    : data_{internal::make_arg<IS_PACKED, Context>(args)...} {}\n#endif\n};\n\n#if !FMT_USE_CONSTEXPR11\ntemplate <typename Context, typename ...Args>\nconst long long format_arg_store<Context, Args...>::TYPES = get_types();\n#endif\n\n/**\n  \\rst\n  Constructs an `~fmt::format_arg_store` object that contains references to\n  arguments and can be implicitly converted to `~fmt::format_args`. `Context`\n  can be omitted in which case it defaults to `~fmt::context`.\n  \\endrst\n */\ntemplate <typename Context, typename ...Args>\ninline format_arg_store<Context, Args...>\n  make_format_args(const Args &... args) { return {args...}; }\n\ntemplate <typename ...Args>\ninline format_arg_store<format_context, Args...>\n  make_format_args(const Args &... args) { return {args...}; }\n\n/** Formatting arguments. */\ntemplate <typename Context>\nclass basic_format_args {\n public:\n  typedef unsigned size_type;\n  typedef basic_format_arg<Context>  format_arg;\n\n private:\n  // To reduce compiled code size per formatting function call, types of first\n  // max_packed_args arguments are passed in the types_ field.\n  unsigned long long types_;\n  union {\n    // If the number of arguments is less than max_packed_args, the argument\n    // values are stored in values_, otherwise they are stored in args_.\n    // This is done to reduce compiled code size as storing larger objects\n    // may require more code (at least on x86-64) even if the same amount of\n    // data is actually copied to stack. It saves ~10% on the bloat test.\n    const internal::value<Context> *values_;\n    const format_arg *args_;\n  };\n\n  typename internal::type type(unsigned index) const {\n    unsigned shift = index * 4;\n    unsigned long long mask = 0xf;\n    return static_cast<typename internal::type>(\n      (types_ & (mask << shift)) >> shift);\n  }\n\n  friend class internal::arg_map<Context>;\n\n  void set_data(const internal::value<Context> *values) { values_ = values; }\n  void set_data(const format_arg *args) { args_ = args; }\n\n  format_arg do_get(size_type index) const {\n    format_arg arg;\n    long long signed_types = static_cast<long long>(types_);\n    if (signed_types < 0) {\n      unsigned long long num_args =\n          static_cast<unsigned long long>(-signed_types);\n      if (index < num_args)\n        arg = args_[index];\n      return arg;\n    }\n    if (index > internal::max_packed_args)\n      return arg;\n    arg.type_ = type(index);\n    if (arg.type_ == internal::none_type)\n      return arg;\n    internal::value<Context> &val = arg.value_;\n    val = values_[index];\n    return arg;\n  }\n\n public:\n  basic_format_args() : types_(0) {}\n\n  /**\n   \\rst\n   Constructs a `basic_format_args` object from `~fmt::format_arg_store`.\n   \\endrst\n   */\n  template <typename... Args>\n  basic_format_args(const format_arg_store<Context, Args...> &store)\n  : types_(static_cast<unsigned long long>(store.TYPES)) {\n    set_data(store.data_);\n  }\n\n  /**\n   \\rst\n   Constructs a `basic_format_args` object from a dynamic set of arguments.\n   \\endrst\n   */\n  basic_format_args(const format_arg *args, size_type count)\n  : types_(-static_cast<int64_t>(count)) {\n    set_data(args);\n  }\n\n  /** Returns the argument at specified index. */\n  format_arg get(size_type index) const {\n    format_arg arg = do_get(index);\n    if (arg.type_ == internal::named_arg_type)\n      arg = arg.value_.as_named_arg().template deserialize<Context>();\n    return arg;\n  }\n\n  unsigned max_size() const {\n    long long signed_types = static_cast<long long>(types_);\n    return static_cast<unsigned>(\n        signed_types < 0 ?\n        -signed_types : static_cast<long long>(internal::max_packed_args));\n  }\n};\n\n/** An alias to ``basic_format_args<context>``. */\n// It is a separate type rather than a typedef to make symbols readable.\nstruct format_args : basic_format_args<format_context> {\n  template <typename ...Args>\n  format_args(Args &&... arg)\n  : basic_format_args<format_context>(std::forward<Args>(arg)...) {}\n};\nstruct wformat_args : basic_format_args<wformat_context> {\n  template <typename ...Args>\n  wformat_args(Args &&... arg)\n  : basic_format_args<wformat_context>(std::forward<Args>(arg)...) {}\n};\n\n#ifndef FMT_USE_ALIAS_TEMPLATES\n# define FMT_USE_ALIAS_TEMPLATES FMT_HAS_FEATURE(cxx_alias_templates)\n#endif\n#if FMT_USE_ALIAS_TEMPLATES\n/** String's character type. */\ntemplate <typename S>\nusing char_t = typename std::enable_if<internal::is_string<S>::value,\n  typename internal::char_t<S>::type>::type;\n#define FMT_CHAR(S) fmt::char_t<S>\n\ntemplate <typename S, typename T>\nusing enable_if_string_t =\n  typename std::enable_if<internal::is_string<S>::value, T>::type;\n#define FMT_ENABLE_IF_STRING(S, T) enable_if_string_t<S, T>\n#else\ntemplate <typename S>\nstruct char_t : std::enable_if<\n    internal::is_string<S>::value, typename internal::char_t<S>::type> {};\n#define FMT_CHAR(S) typename char_t<S>::type\n\n#define FMT_ENABLE_IF_STRING(S, T) \\\n  typename std::enable_if<internal::is_string<S>::value, T>::type\n#endif\n\nnamespace internal {\ntemplate <typename Char>\nstruct named_arg_base {\n  basic_string_view<Char> name;\n\n  // Serialized value<context>.\n  mutable char data[\n    sizeof(basic_format_arg<typename buffer_context<Char>::type>)];\n\n  named_arg_base(basic_string_view<Char> nm) : name(nm) {}\n\n  template <typename Context>\n  basic_format_arg<Context> deserialize() const {\n    basic_format_arg<Context> arg;\n    std::memcpy(&arg, data, sizeof(basic_format_arg<Context>));\n    return arg;\n  }\n};\n\ntemplate <typename T, typename Char>\nstruct named_arg : named_arg_base<Char> {\n  const T &value;\n\n  named_arg(basic_string_view<Char> name, const T &val)\n    : named_arg_base<Char>(name), value(val) {}\n};\n\ntemplate <typename... Args, typename S>\ninline typename std::enable_if<!is_compile_string<S>::value>::type\n  check_format_string(const S &) {}\ntemplate <typename... Args, typename S>\ntypename std::enable_if<is_compile_string<S>::value>::type\n  check_format_string(S);\n\ntemplate <typename S, typename... Args>\nstruct checked_args : format_arg_store<\n  typename buffer_context<FMT_CHAR(S)>::type, Args...> {\n  typedef typename buffer_context<FMT_CHAR(S)>::type context;\n\n  checked_args(const S &format_str, const Args &... args):\n    format_arg_store<context, Args...>(args...) {\n    internal::check_format_string<Args...>(format_str);\n  }\n\n  basic_format_args<context> operator*() const { return *this; }\n};\n\ntemplate <typename Char>\nstd::basic_string<Char> vformat(\n  basic_string_view<Char> format_str,\n  basic_format_args<typename buffer_context<Char>::type> args);\n\ntemplate <typename Char>\ntypename buffer_context<Char>::type::iterator vformat_to(\n  internal::basic_buffer<Char> &buf, basic_string_view<Char> format_str,\n  basic_format_args<typename buffer_context<Char>::type> args);\n}\n\n/**\n  \\rst\n  Returns a named argument to be used in a formatting function.\n\n  **Example**::\n\n    fmt::print(\"Elapsed time: {s:.2f} seconds\", fmt::arg(\"s\", 1.23));\n  \\endrst\n */\ntemplate <typename T>\ninline internal::named_arg<T, char> arg(string_view name, const T &arg) {\n  return {name, arg};\n}\n\ntemplate <typename T>\ninline internal::named_arg<T, wchar_t> arg(wstring_view name, const T &arg) {\n  return {name, arg};\n}\n\n// Disable nested named arguments, e.g. ``arg(\"a\", arg(\"b\", 42))``.\ntemplate <typename S, typename T, typename Char>\nvoid arg(S, internal::named_arg<T, Char>) = delete;\n\ntemplate <typename Container>\nstruct is_contiguous: std::false_type {};\n\ntemplate <typename Char>\nstruct is_contiguous<std::basic_string<Char> >: std::true_type {};\n\ntemplate <typename Char>\nstruct is_contiguous<internal::basic_buffer<Char> >: std::true_type {};\n\n/** Formats a string and writes the output to ``out``. */\ntemplate <typename Container, typename S>\ntypename std::enable_if<\n    is_contiguous<Container>::value, std::back_insert_iterator<Container>>::type\n  vformat_to(\n    std::back_insert_iterator<Container> out,\n    const S &format_str,\n    basic_format_args<typename buffer_context<FMT_CHAR(S)>::type> args) {\n  internal::container_buffer<Container> buf(internal::get_container(out));\n  internal::vformat_to(buf, to_string_view(format_str), args);\n  return out;\n}\n\ntemplate <typename Container, typename S, typename... Args>\ninline typename std::enable_if<\n  is_contiguous<Container>::value && internal::is_string<S>::value,\n  std::back_insert_iterator<Container>>::type\n    format_to(std::back_insert_iterator<Container> out, const S &format_str,\n              const Args &... args) {\n  internal::checked_args<S, Args...> ca(format_str, args...);\n  return vformat_to(out, to_string_view(format_str), *ca);\n}\n\ntemplate <typename S, typename Char = FMT_CHAR(S)>\ninline std::basic_string<Char> vformat(\n    const S &format_str,\n    basic_format_args<typename buffer_context<Char>::type> args) {\n  return internal::vformat(to_string_view(format_str), args);\n}\n\n/**\n  \\rst\n  Formats arguments and returns the result as a string.\n\n  **Example**::\n\n    #include <fmt/core.h>\n    std::string message = fmt::format(\"The answer is {}\", 42);\n  \\endrst\n*/\ntemplate <typename S, typename... Args>\ninline std::basic_string<FMT_CHAR(S)> format(\n    const S &format_str, const Args &... args) {\n  return internal::vformat(\n    to_string_view(format_str),\n    *internal::checked_args<S, Args...>(format_str, args...));\n}\n\nFMT_API void vprint(std::FILE *f, string_view format_str, format_args args);\nFMT_API void vprint(std::FILE *f, wstring_view format_str, wformat_args args);\n\n/**\n  \\rst\n  Prints formatted data to the file *f*. For wide format strings,\n  *f* should be in wide-oriented mode set via ``fwide(f, 1)`` or\n  ``_setmode(_fileno(f), _O_U8TEXT)`` on Windows.\n\n  **Example**::\n\n    fmt::print(stderr, \"Don't {}!\", \"panic\");\n  \\endrst\n */\ntemplate <typename S, typename... Args>\ninline FMT_ENABLE_IF_STRING(S, void)\n    print(std::FILE *f, const S &format_str, const Args &... args) {\n  vprint(f, to_string_view(format_str),\n         internal::checked_args<S, Args...>(format_str, args...));\n}\n\nFMT_API void vprint(string_view format_str, format_args args);\nFMT_API void vprint(wstring_view format_str, wformat_args args);\n\n/**\n  \\rst\n  Prints formatted data to ``stdout``.\n\n  **Example**::\n\n    fmt::print(\"Elapsed time: {0:.2f} seconds\", 1.23);\n  \\endrst\n */\ntemplate <typename S, typename... Args>\ninline FMT_ENABLE_IF_STRING(S, void)\n    print(const S &format_str, const Args &... args) {\n  vprint(to_string_view(format_str),\n         internal::checked_args<S, Args...>(format_str, args...));\n}\nFMT_END_NAMESPACE\n\n#endif  // FMT_CORE_H_\n"
  },
  {
    "path": "src/DRAMsim3/ext/fmt/include/fmt/format-inl.h",
    "content": "// Formatting library for C++\n//\n// Copyright (c) 2012 - 2016, Victor Zverovich\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\n#ifndef FMT_FORMAT_INL_H_\n#define FMT_FORMAT_INL_H_\n\n#include \"format.h\"\n\n#include <string.h>\n\n#include <cctype>\n#include <cerrno>\n#include <climits>\n#include <cmath>\n#include <cstdarg>\n#include <cstddef>  // for std::ptrdiff_t\n#include <cstring>  // for std::memmove\n#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)\n# include <locale>\n#endif\n\n#if FMT_USE_WINDOWS_H\n# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)\n#  define WIN32_LEAN_AND_MEAN\n# endif\n# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)\n#  include <windows.h>\n# else\n#  define NOMINMAX\n#  include <windows.h>\n#  undef NOMINMAX\n# endif\n#endif\n\n#if FMT_EXCEPTIONS\n# define FMT_TRY try\n# define FMT_CATCH(x) catch (x)\n#else\n# define FMT_TRY if (true)\n# define FMT_CATCH(x) if (false)\n#endif\n\n#ifdef _MSC_VER\n# pragma warning(push)\n# pragma warning(disable: 4127)  // conditional expression is constant\n# pragma warning(disable: 4702)  // unreachable code\n// Disable deprecation warning for strerror. The latter is not called but\n// MSVC fails to detect it.\n# pragma warning(disable: 4996)\n#endif\n\n// Dummy implementations of strerror_r and strerror_s called if corresponding\n// system functions are not available.\ninline fmt::internal::null<> strerror_r(int, char *, ...) {\n  return fmt::internal::null<>();\n}\ninline fmt::internal::null<> strerror_s(char *, std::size_t, ...) {\n  return fmt::internal::null<>();\n}\n\nFMT_BEGIN_NAMESPACE\n\nnamespace {\n\n#ifndef _MSC_VER\n# define FMT_SNPRINTF snprintf\n#else  // _MSC_VER\ninline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {\n  va_list args;\n  va_start(args, format);\n  int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);\n  va_end(args);\n  return result;\n}\n# define FMT_SNPRINTF fmt_snprintf\n#endif  // _MSC_VER\n\n#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)\n# define FMT_SWPRINTF snwprintf\n#else\n# define FMT_SWPRINTF swprintf\n#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)\n\ntypedef void (*FormatFunc)(internal::buffer &, int, string_view);\n\n// Portable thread-safe version of strerror.\n// Sets buffer to point to a string describing the error code.\n// This can be either a pointer to a string stored in buffer,\n// or a pointer to some static immutable string.\n// Returns one of the following values:\n//   0      - success\n//   ERANGE - buffer is not large enough to store the error message\n//   other  - failure\n// Buffer should be at least of size 1.\nint safe_strerror(\n    int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {\n  FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, \"invalid buffer\");\n\n  class dispatcher {\n   private:\n    int error_code_;\n    char *&buffer_;\n    std::size_t buffer_size_;\n\n    // A noop assignment operator to avoid bogus warnings.\n    void operator=(const dispatcher &) {}\n\n    // Handle the result of XSI-compliant version of strerror_r.\n    int handle(int result) {\n      // glibc versions before 2.13 return result in errno.\n      return result == -1 ? errno : result;\n    }\n\n    // Handle the result of GNU-specific version of strerror_r.\n    int handle(char *message) {\n      // If the buffer is full then the message is probably truncated.\n      if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)\n        return ERANGE;\n      buffer_ = message;\n      return 0;\n    }\n\n    // Handle the case when strerror_r is not available.\n    int handle(internal::null<>) {\n      return fallback(strerror_s(buffer_, buffer_size_, error_code_));\n    }\n\n    // Fallback to strerror_s when strerror_r is not available.\n    int fallback(int result) {\n      // If the buffer is full then the message is probably truncated.\n      return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?\n            ERANGE : result;\n    }\n\n    // Fallback to strerror if strerror_r and strerror_s are not available.\n    int fallback(internal::null<>) {\n      errno = 0;\n      buffer_ = strerror(error_code_);\n      return errno;\n    }\n\n   public:\n    dispatcher(int err_code, char *&buf, std::size_t buf_size)\n      : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}\n\n    int run() {\n      return handle(strerror_r(error_code_, buffer_, buffer_size_));\n    }\n  };\n  return dispatcher(error_code, buffer, buffer_size).run();\n}\n\nvoid format_error_code(internal::buffer &out, int error_code,\n                       string_view message) FMT_NOEXCEPT {\n  // Report error code making sure that the output fits into\n  // inline_buffer_size to avoid dynamic memory allocation and potential\n  // bad_alloc.\n  out.resize(0);\n  static const char SEP[] = \": \";\n  static const char ERROR_STR[] = \"error \";\n  // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.\n  std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;\n  typedef internal::int_traits<int>::main_type main_type;\n  main_type abs_value = static_cast<main_type>(error_code);\n  if (internal::is_negative(error_code)) {\n    abs_value = 0 - abs_value;\n    ++error_code_size;\n  }\n  error_code_size += internal::count_digits(abs_value);\n  writer w(out);\n  if (message.size() <= inline_buffer_size - error_code_size) {\n    w.write(message);\n    w.write(SEP);\n  }\n  w.write(ERROR_STR);\n  w.write(error_code);\n  assert(out.size() <= inline_buffer_size);\n}\n\nvoid report_error(FormatFunc func, int error_code,\n                  string_view message) FMT_NOEXCEPT {\n  memory_buffer full_message;\n  func(full_message, error_code, message);\n  // Use Writer::data instead of Writer::c_str to avoid potential memory\n  // allocation.\n  std::fwrite(full_message.data(), full_message.size(), 1, stderr);\n  std::fputc('\\n', stderr);\n}\n}  // namespace\n\nFMT_FUNC size_t internal::count_code_points(basic_string_view<char8_t> s) {\n  const char8_t *data = s.data();\n  size_t num_code_points = 0;\n  for (size_t i = 0, size = s.size(); i != size; ++i) {\n    if ((data[i] & 0xc0) != 0x80)\n      ++num_code_points;\n  }\n  return num_code_points;\n}\n\n#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)\nnamespace internal {\n\ntemplate <typename Locale>\nlocale_ref::locale_ref(const Locale &loc) : locale_(&loc) {\n  static_assert(std::is_same<Locale, std::locale>::value, \"\");\n}\n\ntemplate <typename Locale>\nLocale locale_ref::get() const {\n  static_assert(std::is_same<Locale, std::locale>::value, \"\");\n  return locale_ ? *static_cast<const std::locale*>(locale_) : std::locale();\n}\n\ntemplate <typename Char>\nFMT_FUNC Char thousands_sep_impl(locale_ref loc) {\n  return std::use_facet<std::numpunct<Char> >(\n    loc.get<std::locale>()).thousands_sep();\n}\n}\n#else\ntemplate <typename Char>\nFMT_FUNC Char internal::thousands_sep(locale_ref) {\n  return FMT_STATIC_THOUSANDS_SEPARATOR;\n}\n#endif\n\nFMT_FUNC void system_error::init(\n    int err_code, string_view format_str, format_args args) {\n  error_code_ = err_code;\n  memory_buffer buffer;\n  format_system_error(buffer, err_code, vformat(format_str, args));\n  std::runtime_error &base = *this;\n  base = std::runtime_error(to_string(buffer));\n}\n\nnamespace internal {\ntemplate <typename T>\nint char_traits<char>::format_float(\n    char *buffer, std::size_t size, const char *format, int precision, T value) {\n  return precision < 0 ?\n      FMT_SNPRINTF(buffer, size, format, value) :\n      FMT_SNPRINTF(buffer, size, format, precision, value);\n}\n\ntemplate <typename T>\nint char_traits<wchar_t>::format_float(\n    wchar_t *buffer, std::size_t size, const wchar_t *format, int precision,\n    T value) {\n  return precision < 0 ?\n      FMT_SWPRINTF(buffer, size, format, value) :\n      FMT_SWPRINTF(buffer, size, format, precision, value);\n}\n\ntemplate <typename T>\nconst char basic_data<T>::DIGITS[] =\n    \"0001020304050607080910111213141516171819\"\n    \"2021222324252627282930313233343536373839\"\n    \"4041424344454647484950515253545556575859\"\n    \"6061626364656667686970717273747576777879\"\n    \"8081828384858687888990919293949596979899\";\n\n#define FMT_POWERS_OF_10(factor) \\\n  factor * 10, \\\n  factor * 100, \\\n  factor * 1000, \\\n  factor * 10000, \\\n  factor * 100000, \\\n  factor * 1000000, \\\n  factor * 10000000, \\\n  factor * 100000000, \\\n  factor * 1000000000\n\ntemplate <typename T>\nconst uint32_t basic_data<T>::POWERS_OF_10_32[] = {\n  1, FMT_POWERS_OF_10(1)\n};\n\ntemplate <typename T>\nconst uint32_t basic_data<T>::ZERO_OR_POWERS_OF_10_32[] = {\n  0, FMT_POWERS_OF_10(1)\n};\n\ntemplate <typename T>\nconst uint64_t basic_data<T>::ZERO_OR_POWERS_OF_10_64[] = {\n  0,\n  FMT_POWERS_OF_10(1),\n  FMT_POWERS_OF_10(1000000000ull),\n  10000000000000000000ull\n};\n\n// Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.\n// These are generated by support/compute-powers.py.\ntemplate <typename T>\nconst uint64_t basic_data<T>::POW10_SIGNIFICANDS[] = {\n  0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76,\n  0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df,\n  0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c,\n  0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,\n  0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57,\n  0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7,\n  0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e,\n  0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,\n  0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126,\n  0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053,\n  0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f,\n  0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,\n  0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06,\n  0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb,\n  0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000,\n  0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,\n  0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068,\n  0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8,\n  0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758,\n  0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,\n  0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d,\n  0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25,\n  0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2,\n  0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,\n  0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410,\n  0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129,\n  0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85,\n  0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,\n  0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b,\n};\n\n// Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding\n// to significands above.\ntemplate <typename T>\nconst int16_t basic_data<T>::POW10_EXPONENTS[] = {\n  -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007,  -980,  -954,\n   -927,  -901,  -874,  -847,  -821,  -794,  -768,  -741,  -715,  -688,  -661,\n   -635,  -608,  -582,  -555,  -529,  -502,  -475,  -449,  -422,  -396,  -369,\n   -343,  -316,  -289,  -263,  -236,  -210,  -183,  -157,  -130,  -103,   -77,\n    -50,   -24,     3,    30,    56,    83,   109,   136,   162,   189,   216,\n    242,   269,   295,   322,   348,   375,   402,   428,   455,   481,   508,\n    534,   561,   588,   614,   641,   667,   694,   720,   747,   774,   800,\n    827,   853,   880,   907,   933,   960,   986,  1013,  1039,  1066\n};\n\ntemplate <typename T> const char basic_data<T>::FOREGROUND_COLOR[] = \"\\x1b[38;2;\";\ntemplate <typename T> const char basic_data<T>::BACKGROUND_COLOR[] = \"\\x1b[48;2;\";\ntemplate <typename T> const char basic_data<T>::RESET_COLOR[] = \"\\x1b[0m\";\ntemplate <typename T> const wchar_t basic_data<T>::WRESET_COLOR[] = L\"\\x1b[0m\";\n\n// A handmade floating-point number f * pow(2, e).\nclass fp {\n private:\n  typedef uint64_t significand_type;\n\n  // All sizes are in bits.\n  static FMT_CONSTEXPR_DECL const int char_size =\n    std::numeric_limits<unsigned char>::digits;\n  // Subtract 1 to account for an implicit most significant bit in the\n  // normalized form.\n  static FMT_CONSTEXPR_DECL const int double_significand_size =\n    std::numeric_limits<double>::digits - 1;\n  static FMT_CONSTEXPR_DECL const uint64_t implicit_bit =\n    1ull << double_significand_size;\n\n public:\n  significand_type f;\n  int e;\n\n  static FMT_CONSTEXPR_DECL const int significand_size =\n    sizeof(significand_type) * char_size;\n\n  fp(): f(0), e(0) {}\n  fp(uint64_t f, int e): f(f), e(e) {}\n\n  // Constructs fp from an IEEE754 double. It is a template to prevent compile\n  // errors on platforms where double is not IEEE754.\n  template <typename Double>\n  explicit fp(Double d) {\n    // Assume double is in the format [sign][exponent][significand].\n    typedef std::numeric_limits<Double> limits;\n    const int double_size = static_cast<int>(sizeof(Double) * char_size);\n    const int exponent_size =\n      double_size - double_significand_size - 1;  // -1 for sign\n    const uint64_t significand_mask = implicit_bit - 1;\n    const uint64_t exponent_mask = (~0ull >> 1) & ~significand_mask;\n    const int exponent_bias = (1 << exponent_size) - limits::max_exponent - 1;\n    auto u = bit_cast<uint64_t>(d);\n    auto biased_e = (u & exponent_mask) >> double_significand_size;\n    f = u & significand_mask;\n    if (biased_e != 0)\n      f += implicit_bit;\n    else\n      biased_e = 1;  // Subnormals use biased exponent 1 (min exponent).\n    e = static_cast<int>(biased_e - exponent_bias - double_significand_size);\n  }\n\n  // Normalizes the value converted from double and multiplied by (1 << SHIFT).\n  template <int SHIFT = 0>\n  void normalize() {\n    // Handle subnormals.\n    auto shifted_implicit_bit = implicit_bit << SHIFT;\n    while ((f & shifted_implicit_bit) == 0) {\n      f <<= 1;\n      --e;\n    }\n    // Subtract 1 to account for hidden bit.\n    auto offset = significand_size - double_significand_size - SHIFT - 1;\n    f <<= offset;\n    e -= offset;\n  }\n\n  // Compute lower and upper boundaries (m^- and m^+ in the Grisu paper), where\n  // a boundary is a value half way between the number and its predecessor\n  // (lower) or successor (upper). The upper boundary is normalized and lower\n  // has the same exponent but may be not normalized.\n  void compute_boundaries(fp &lower, fp &upper) const {\n    lower = f == implicit_bit ?\n          fp((f << 2) - 1, e - 2) : fp((f << 1) - 1, e - 1);\n    upper = fp((f << 1) + 1, e - 1);\n    upper.normalize<1>();  // 1 is to account for the exponent shift above.\n    lower.f <<= lower.e - upper.e;\n    lower.e = upper.e;\n  }\n};\n\n// Returns an fp number representing x - y. Result may not be normalized.\ninline fp operator-(fp x, fp y) {\n  FMT_ASSERT(x.f >= y.f && x.e == y.e, \"invalid operands\");\n  return fp(x.f - y.f, x.e);\n}\n\n// Computes an fp number r with r.f = x.f * y.f / pow(2, 64) rounded to nearest\n// with half-up tie breaking, r.e = x.e + y.e + 64. Result may not be normalized.\nFMT_API fp operator*(fp x, fp y);\n\n// Returns cached power (of 10) c_k = c_k.f * pow(2, c_k.e) such that its\n// (binary) exponent satisfies min_exponent <= c_k.e <= min_exponent + 3.\nFMT_API fp get_cached_power(int min_exponent, int &pow10_exponent);\n\nFMT_FUNC fp operator*(fp x, fp y) {\n  // Multiply 32-bit parts of significands.\n  uint64_t mask = (1ULL << 32) - 1;\n  uint64_t a = x.f >> 32, b = x.f & mask;\n  uint64_t c = y.f >> 32, d = y.f & mask;\n  uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;\n  // Compute mid 64-bit of result and round.\n  uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);\n  return fp(ac + (ad >> 32) + (bc >> 32) + (mid >> 32), x.e + y.e + 64);\n}\n\nFMT_FUNC fp get_cached_power(int min_exponent, int &pow10_exponent) {\n  const double one_over_log2_10 = 0.30102999566398114;  // 1 / log2(10)\n  int index = static_cast<int>(std::ceil(\n        (min_exponent + fp::significand_size - 1) * one_over_log2_10));\n  // Decimal exponent of the first (smallest) cached power of 10.\n  const int first_dec_exp = -348;\n  // Difference between 2 consecutive decimal exponents in cached powers of 10.\n  const int dec_exp_step = 8;\n  index = (index - first_dec_exp - 1) / dec_exp_step + 1;\n  pow10_exponent = first_dec_exp + index * dec_exp_step;\n  return fp(data::POW10_SIGNIFICANDS[index], data::POW10_EXPONENTS[index]);\n}\n\nFMT_FUNC bool grisu2_round(\n    char *buffer, size_t &size, size_t max_digits, uint64_t delta,\n    uint64_t remainder, uint64_t exp, uint64_t diff, int &exp10) {\n  while (remainder < diff && delta - remainder >= exp &&\n        (remainder + exp < diff || diff - remainder > remainder + exp - diff)) {\n    --buffer[size - 1];\n    remainder += exp;\n  }\n  if (size > max_digits) {\n    --size;\n    ++exp10;\n    if (buffer[size] >= '5')\n      return false;\n  }\n  return true;\n}\n\n// Generates output using Grisu2 digit-gen algorithm.\nFMT_FUNC bool grisu2_gen_digits(\n    char *buffer, size_t &size, uint32_t hi, uint64_t lo, int &exp,\n    uint64_t delta, const fp &one, const fp &diff, size_t max_digits) {\n  // Generate digits for the most significant part (hi).\n  while (exp > 0) {\n    uint32_t digit = 0;\n    // This optimization by miloyip reduces the number of integer divisions by\n    // one per iteration.\n    switch (exp) {\n    case 10: digit = hi / 1000000000; hi %= 1000000000; break;\n    case  9: digit = hi /  100000000; hi %=  100000000; break;\n    case  8: digit = hi /   10000000; hi %=   10000000; break;\n    case  7: digit = hi /    1000000; hi %=    1000000; break;\n    case  6: digit = hi /     100000; hi %=     100000; break;\n    case  5: digit = hi /      10000; hi %=      10000; break;\n    case  4: digit = hi /       1000; hi %=       1000; break;\n    case  3: digit = hi /        100; hi %=        100; break;\n    case  2: digit = hi /         10; hi %=         10; break;\n    case  1: digit = hi;              hi =           0; break;\n    default:\n      FMT_ASSERT(false, \"invalid number of digits\");\n    }\n    if (digit != 0 || size != 0)\n      buffer[size++] = static_cast<char>('0' + digit);\n    --exp;\n    uint64_t remainder = (static_cast<uint64_t>(hi) << -one.e) + lo;\n    if (remainder <= delta || size > max_digits) {\n      return grisu2_round(\n            buffer, size, max_digits, delta, remainder,\n            static_cast<uint64_t>(data::POWERS_OF_10_32[exp]) << -one.e,\n            diff.f, exp);\n    }\n  }\n  // Generate digits for the least significant part (lo).\n  for (;;) {\n    lo *= 10;\n    delta *= 10;\n    char digit = static_cast<char>(lo >> -one.e);\n    if (digit != 0 || size != 0)\n      buffer[size++] = static_cast<char>('0' + digit);\n    lo &= one.f - 1;\n    --exp;\n    if (lo < delta || size > max_digits) {\n      return grisu2_round(buffer, size, max_digits, delta, lo, one.f,\n                          diff.f * data::POWERS_OF_10_32[-exp], exp);\n    }\n  }\n}\n\n#if FMT_CLANG_VERSION\n# define FMT_FALLTHROUGH [[clang::fallthrough]];\n#elif FMT_GCC_VERSION >= 700\n# define FMT_FALLTHROUGH [[gnu::fallthrough]];\n#else\n# define FMT_FALLTHROUGH\n#endif\n\nstruct gen_digits_params {\n  unsigned num_digits;\n  bool fixed;\n  bool upper;\n  bool trailing_zeros;\n};\n\nstruct prettify_handler {\n  char *data;\n  size_t size;\n  buffer &buf;\n\n  explicit prettify_handler(buffer &b, size_t n)\n    : data(b.data()), size(n), buf(b) {}\n  ~prettify_handler() {\n    assert(buf.size() >= size);\n    buf.resize(size);\n  }\n\n  template <typename F>\n  void insert(size_t pos, size_t n, F f) {\n    std::memmove(data + pos + n, data + pos, size - pos);\n    f(data + pos);\n    size += n;\n  }\n\n  void insert(size_t pos, char c) {\n    std::memmove(data + pos + 1, data + pos, size - pos);\n    data[pos] = c;\n    ++size;\n  }\n\n  void append(size_t n, char c) {\n    std::uninitialized_fill_n(data + size, n, c);\n    size += n;\n  }\n\n  void append(char c) { data[size++] = c; }\n\n  void remove_trailing(char c) {\n    while (data[size - 1] == c) --size;\n  }\n};\n\n// Writes the exponent exp in the form \"[+-]d{2,3}\" to buffer.\ntemplate <typename Handler>\nFMT_FUNC void write_exponent(int exp, Handler &&h) {\n  FMT_ASSERT(-1000 < exp && exp < 1000, \"exponent out of range\");\n  if (exp < 0) {\n    h.append('-');\n    exp = -exp;\n  } else {\n    h.append('+');\n  }\n  if (exp >= 100) {\n    h.append(static_cast<char>('0' + exp / 100));\n    exp %= 100;\n    const char *d = data::DIGITS + exp * 2;\n    h.append(d[0]);\n    h.append(d[1]);\n  } else {\n    const char *d = data::DIGITS + exp * 2;\n    h.append(d[0]);\n    h.append(d[1]);\n  }\n}\n\nstruct fill {\n  size_t n;\n  void operator()(char *buffer) const {\n    buffer[0] = '0';\n    buffer[1] = '.';\n    std::uninitialized_fill_n(buffer + 2, n, '0');\n  }\n};\n\n// The number is given as v = f * pow(10, exp), where f has size digits.\ntemplate <typename Handler>\nFMT_FUNC void grisu2_prettify(const gen_digits_params &params,\n                              size_t size, int exp, Handler &&handler) {\n  if (!params.fixed) {\n    // Insert a decimal point after the first digit and add an exponent.\n    handler.insert(1, '.');\n    exp += static_cast<int>(size) - 1;\n    if (size < params.num_digits)\n      handler.append(params.num_digits - size, '0');\n    handler.append(params.upper ? 'E' : 'e');\n    write_exponent(exp, handler);\n    return;\n  }\n  // pow(10, full_exp - 1) <= v <= pow(10, full_exp).\n  int int_size = static_cast<int>(size);\n  int full_exp = int_size + exp;\n  const int exp_threshold = 21;\n  if (int_size <= full_exp && full_exp <= exp_threshold) {\n    // 1234e7 -> 12340000000[.0+]\n    handler.append(full_exp - int_size, '0');\n    int num_zeros = static_cast<int>(params.num_digits) - full_exp;\n    if (num_zeros > 0 && params.trailing_zeros) {\n      handler.append('.');\n      handler.append(num_zeros, '0');\n    }\n  } else if (full_exp > 0) {\n    // 1234e-2 -> 12.34[0+]\n    handler.insert(full_exp, '.');\n    if (!params.trailing_zeros) {\n      // Remove trailing zeros.\n      handler.remove_trailing('0');\n    } else if (params.num_digits > size) {\n      // Add trailing zeros.\n      size_t num_zeros = params.num_digits - size;\n      handler.append(num_zeros, '0');\n    }\n  } else {\n    // 1234e-6 -> 0.001234\n    handler.insert(0, 2 - full_exp, fill{to_unsigned(-full_exp)});\n  }\n}\n\nstruct char_counter {\n  size_t size;\n\n  template <typename F>\n  void insert(size_t, size_t n, F) { size += n; }\n  void insert(size_t, char) { ++size; }\n  void append(size_t n, char) { size += n; }\n  void append(char) { ++size; }\n  void remove_trailing(char) {}\n};\n\n// Converts format specifiers into parameters for digit generation and computes\n// output buffer size for a number in the range [pow(10, exp - 1), pow(10, exp)\n// or 0 if exp == 1.\nFMT_FUNC gen_digits_params process_specs(const core_format_specs &specs,\n                                         int exp, buffer &buf) {\n  auto params = gen_digits_params();\n  int num_digits = specs.precision >= 0 ? specs.precision : 6;\n  switch (specs.type) {\n  case 'G':\n    params.upper = true;\n    FMT_FALLTHROUGH\n  case '\\0': case 'g':\n    params.trailing_zeros = (specs.flags & HASH_FLAG) != 0;\n    if (-4 <= exp && exp < num_digits + 1) {\n      params.fixed = true;\n      if (!specs.type && params.trailing_zeros && exp >= 0)\n        num_digits = exp + 1;\n    }\n    break;\n  case 'F':\n    params.upper = true;\n    FMT_FALLTHROUGH\n  case 'f': {\n    params.fixed = true;\n    params.trailing_zeros = true;\n    int adjusted_min_digits = num_digits + exp;\n    if (adjusted_min_digits > 0)\n      num_digits = adjusted_min_digits;\n    break;\n  }\n  case 'E':\n    params.upper = true;\n    FMT_FALLTHROUGH\n  case 'e':\n    ++num_digits;\n    break;\n  }\n  params.num_digits = to_unsigned(num_digits);\n  char_counter counter{params.num_digits};\n  grisu2_prettify(params, params.num_digits, exp - num_digits, counter);\n  buf.resize(counter.size);\n  return params;\n}\n\ntemplate <typename Double>\nFMT_FUNC typename std::enable_if<sizeof(Double) == sizeof(uint64_t), bool>::type\n    grisu2_format(Double value, buffer &buf, core_format_specs specs) {\n  FMT_ASSERT(value >= 0, \"value is negative\");\n  if (value == 0) {\n    gen_digits_params params = process_specs(specs, 1, buf);\n    const size_t size = 1;\n    buf[0] = '0';\n    grisu2_prettify(params, size, 0, prettify_handler(buf, size));\n    return true;\n  }\n\n  fp fp_value(value);\n  fp lower, upper;  // w^- and w^+ in the Grisu paper.\n  fp_value.compute_boundaries(lower, upper);\n\n  // Find a cached power of 10 close to 1 / upper and use it to scale upper.\n  const int min_exp = -60;  // alpha in Grisu.\n  int cached_exp = 0;  // K in Grisu.\n  auto cached_pow = get_cached_power(  // \\tilde{c}_{-k} in Grisu.\n      min_exp - (upper.e + fp::significand_size), cached_exp);\n  cached_exp = -cached_exp;\n  upper = upper * cached_pow;  // \\tilde{M}^+ in Grisu.\n  --upper.f;  // \\tilde{M}^+ - 1 ulp -> M^+_{\\downarrow}.\n  fp one(1ull << -upper.e, upper.e);\n  // hi (p1 in Grisu) contains the most significant digits of scaled_upper.\n  // hi = floor(upper / one).\n  uint32_t hi = static_cast<uint32_t>(upper.f >> -one.e);\n  int exp = static_cast<int>(count_digits(hi));  // kappa in Grisu.\n  gen_digits_params params = process_specs(specs, cached_exp + exp, buf);\n  fp_value.normalize();\n  fp scaled_value = fp_value * cached_pow;\n  lower = lower * cached_pow;  // \\tilde{M}^- in Grisu.\n  ++lower.f;  // \\tilde{M}^- + 1 ulp -> M^-_{\\uparrow}.\n  uint64_t delta = upper.f - lower.f;\n  fp diff = upper - scaled_value; // wp_w in Grisu.\n  // lo (p2 in Grisu) contains the least significants digits of scaled_upper.\n  // lo = supper % one.\n  uint64_t lo = upper.f & (one.f - 1);\n  size_t size = 0;\n  if (!grisu2_gen_digits(buf.data(), size, hi, lo, exp, delta, one, diff,\n                         params.num_digits)) {\n    buf.clear();\n    return false;\n  }\n  grisu2_prettify(params, size, cached_exp + exp, prettify_handler(buf, size));\n  return true;\n}\n\ntemplate <typename Double>\nvoid sprintf_format(Double value, internal::buffer &buffer,\n                    core_format_specs spec) {\n  // Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail.\n  FMT_ASSERT(buffer.capacity() != 0, \"empty buffer\");\n\n  // Build format string.\n  enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg\n  char format[MAX_FORMAT_SIZE];\n  char *format_ptr = format;\n  *format_ptr++ = '%';\n  if (spec.has(HASH_FLAG))\n    *format_ptr++ = '#';\n  if (spec.precision >= 0) {\n    *format_ptr++ = '.';\n    *format_ptr++ = '*';\n  }\n  if (std::is_same<Double, long double>::value)\n    *format_ptr++ = 'L';\n  *format_ptr++ = spec.type;\n  *format_ptr = '\\0';\n\n  // Format using snprintf.\n  char *start = FMT_NULL;\n  for (;;) {\n    std::size_t buffer_size = buffer.capacity();\n    start = &buffer[0];\n    int result = internal::char_traits<char>::format_float(\n        start, buffer_size, format, spec.precision, value);\n    if (result >= 0) {\n      unsigned n = internal::to_unsigned(result);\n      if (n < buffer.capacity()) {\n        buffer.resize(n);\n        break;  // The buffer is large enough - continue with formatting.\n      }\n      buffer.reserve(n + 1);\n    } else {\n      // If result is negative we ask to increase the capacity by at least 1,\n      // but as std::vector, the buffer grows exponentially.\n      buffer.reserve(buffer.capacity() + 1);\n    }\n  }\n}\n}  // namespace internal\n\n#if FMT_USE_WINDOWS_H\n\nFMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {\n  static const char ERROR_MSG[] = \"cannot convert string from UTF-8 to UTF-16\";\n  if (s.size() > INT_MAX)\n    FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG));\n  int s_size = static_cast<int>(s.size());\n  if (s_size == 0) {\n    // MultiByteToWideChar does not support zero length, handle separately.\n    buffer_.resize(1);\n    buffer_[0] = 0;\n    return;\n  }\n\n  int length = MultiByteToWideChar(\n      CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);\n  if (length == 0)\n    FMT_THROW(windows_error(GetLastError(), ERROR_MSG));\n  buffer_.resize(length + 1);\n  length = MultiByteToWideChar(\n    CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);\n  if (length == 0)\n    FMT_THROW(windows_error(GetLastError(), ERROR_MSG));\n  buffer_[length] = 0;\n}\n\nFMT_FUNC internal::utf16_to_utf8::utf16_to_utf8(wstring_view s) {\n  if (int error_code = convert(s)) {\n    FMT_THROW(windows_error(error_code,\n        \"cannot convert string from UTF-16 to UTF-8\"));\n  }\n}\n\nFMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) {\n  if (s.size() > INT_MAX)\n    return ERROR_INVALID_PARAMETER;\n  int s_size = static_cast<int>(s.size());\n  if (s_size == 0) {\n    // WideCharToMultiByte does not support zero length, handle separately.\n    buffer_.resize(1);\n    buffer_[0] = 0;\n    return 0;\n  }\n\n  int length = WideCharToMultiByte(\n        CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);\n  if (length == 0)\n    return GetLastError();\n  buffer_.resize(length + 1);\n  length = WideCharToMultiByte(\n    CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);\n  if (length == 0)\n    return GetLastError();\n  buffer_[length] = 0;\n  return 0;\n}\n\nFMT_FUNC void windows_error::init(\n    int err_code, string_view format_str, format_args args) {\n  error_code_ = err_code;\n  memory_buffer buffer;\n  internal::format_windows_error(buffer, err_code, vformat(format_str, args));\n  std::runtime_error &base = *this;\n  base = std::runtime_error(to_string(buffer));\n}\n\nFMT_FUNC void internal::format_windows_error(\n    internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {\n  FMT_TRY {\n    wmemory_buffer buf;\n    buf.resize(inline_buffer_size);\n    for (;;) {\n      wchar_t *system_message = &buf[0];\n      int result = FormatMessageW(\n          FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\n          FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\n          system_message, static_cast<uint32_t>(buf.size()), FMT_NULL);\n      if (result != 0) {\n        utf16_to_utf8 utf8_message;\n        if (utf8_message.convert(system_message) == ERROR_SUCCESS) {\n          writer w(out);\n          w.write(message);\n          w.write(\": \");\n          w.write(utf8_message);\n          return;\n        }\n        break;\n      }\n      if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)\n        break;  // Can't get error message, report error code instead.\n      buf.resize(buf.size() * 2);\n    }\n  } FMT_CATCH(...) {}\n  format_error_code(out, error_code, message);\n}\n\n#endif  // FMT_USE_WINDOWS_H\n\nFMT_FUNC void format_system_error(\n    internal::buffer &out, int error_code, string_view message) FMT_NOEXCEPT {\n  FMT_TRY {\n    memory_buffer buf;\n    buf.resize(inline_buffer_size);\n    for (;;) {\n      char *system_message = &buf[0];\n      int result = safe_strerror(error_code, system_message, buf.size());\n      if (result == 0) {\n        writer w(out);\n        w.write(message);\n        w.write(\": \");\n        w.write(system_message);\n        return;\n      }\n      if (result != ERANGE)\n        break;  // Can't get error message, report error code instead.\n      buf.resize(buf.size() * 2);\n    }\n  } FMT_CATCH(...) {}\n  format_error_code(out, error_code, message);\n}\n\nFMT_FUNC void internal::error_handler::on_error(const char *message) {\n  FMT_THROW(format_error(message));\n}\n\nFMT_FUNC void report_system_error(\n    int error_code, fmt::string_view message) FMT_NOEXCEPT {\n  report_error(format_system_error, error_code, message);\n}\n\n#if FMT_USE_WINDOWS_H\nFMT_FUNC void report_windows_error(\n    int error_code, fmt::string_view message) FMT_NOEXCEPT {\n  report_error(internal::format_windows_error, error_code, message);\n}\n#endif\n\nFMT_FUNC void vprint(std::FILE *f, string_view format_str, format_args args) {\n  memory_buffer buffer;\n  internal::vformat_to(buffer, format_str,\n                       basic_format_args<buffer_context<char>::type>(args));\n  std::fwrite(buffer.data(), 1, buffer.size(), f);\n}\n\nFMT_FUNC void vprint(std::FILE *f, wstring_view format_str, wformat_args args) {\n  wmemory_buffer buffer;\n  internal::vformat_to(buffer, format_str, args);\n  std::fwrite(buffer.data(), sizeof(wchar_t), buffer.size(), f);\n}\n\nFMT_FUNC void vprint(string_view format_str, format_args args) {\n  vprint(stdout, format_str, args);\n}\n\nFMT_FUNC void vprint(wstring_view format_str, wformat_args args) {\n  vprint(stdout, format_str, args);\n}\n\nFMT_END_NAMESPACE\n\n#ifdef _MSC_VER\n# pragma warning(pop)\n#endif\n\n#endif  // FMT_FORMAT_INL_H_\n"
  },
  {
    "path": "src/DRAMsim3/ext/fmt/include/fmt/format.h",
    "content": "/*\n Formatting library for C++\n\n Copyright (c) 2012 - present, Victor Zverovich\n All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n\n 1. Redistributions of source code must retain the above copyright notice, this\n    list of conditions and the following disclaimer.\n 2. Redistributions in binary form must reproduce the above copyright notice,\n    this list of conditions and the following disclaimer in the documentation\n    and/or other materials provided with the distribution.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\n ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef FMT_FORMAT_H_\n#define FMT_FORMAT_H_\n\n#include <algorithm>\n#include <cassert>\n#include <cmath>\n#include <cstring>\n#include <limits>\n#include <memory>\n#include <stdexcept>\n#include <stdint.h>\n\n#ifdef __clang__\n# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)\n#else\n# define FMT_CLANG_VERSION 0\n#endif\n\n#ifdef __INTEL_COMPILER\n# define FMT_ICC_VERSION __INTEL_COMPILER\n#elif defined(__ICL)\n# define FMT_ICC_VERSION __ICL\n#else\n# define FMT_ICC_VERSION 0\n#endif\n\n#ifdef __NVCC__\n# define FMT_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__)\n#else\n# define FMT_CUDA_VERSION 0\n#endif\n\n#include \"core.h\"\n\n#if FMT_GCC_VERSION >= 406 || FMT_CLANG_VERSION\n# pragma GCC diagnostic push\n\n// Disable the warning about declaration shadowing because it affects too\n// many valid cases.\n# pragma GCC diagnostic ignored \"-Wshadow\"\n\n// Disable the warning about implicit conversions that may change the sign of\n// an integer; silencing it otherwise would require many explicit casts.\n# pragma GCC diagnostic ignored \"-Wsign-conversion\"\n#endif\n\n# if FMT_CLANG_VERSION\n#  pragma GCC diagnostic ignored \"-Wgnu-string-literal-operator-template\"\n# endif\n\n#ifdef _SECURE_SCL\n# define FMT_SECURE_SCL _SECURE_SCL\n#else\n# define FMT_SECURE_SCL 0\n#endif\n\n#if FMT_SECURE_SCL\n# include <iterator>\n#endif\n\n#ifdef __has_builtin\n# define FMT_HAS_BUILTIN(x) __has_builtin(x)\n#else\n# define FMT_HAS_BUILTIN(x) 0\n#endif\n\n#ifdef __GNUC_LIBSTD__\n# define FMT_GNUC_LIBSTD_VERSION (__GNUC_LIBSTD__ * 100 + __GNUC_LIBSTD_MINOR__)\n#endif\n\n#ifndef FMT_THROW\n# if FMT_EXCEPTIONS\n#  if FMT_MSC_VER\nFMT_BEGIN_NAMESPACE\nnamespace internal {\ntemplate <typename Exception>\ninline void do_throw(const Exception &x) {\n  // Silence unreachable code warnings in MSVC because these are nearly\n  // impossible to fix in a generic code.\n  volatile bool b = true;\n  if (b)\n    throw x;\n}\n}\nFMT_END_NAMESPACE\n#   define FMT_THROW(x) fmt::internal::do_throw(x)\n#  else\n#   define FMT_THROW(x) throw x\n#  endif\n# else\n#  define FMT_THROW(x) do { static_cast<void>(sizeof(x)); assert(false); } while(false);\n# endif\n#endif\n\n#ifndef FMT_USE_USER_DEFINED_LITERALS\n// For Intel's compiler and NVIDIA's compiler both it and the system gcc/msc\n// must support UDLs.\n# if (FMT_HAS_FEATURE(cxx_user_literals) || \\\n      FMT_GCC_VERSION >= 407 || FMT_MSC_VER >= 1900) && \\\n      (!(FMT_ICC_VERSION || FMT_CUDA_VERSION) || \\\n       FMT_ICC_VERSION >= 1500 || FMT_CUDA_VERSION >= 700)\n#  define FMT_USE_USER_DEFINED_LITERALS 1\n# else\n#  define FMT_USE_USER_DEFINED_LITERALS 0\n# endif\n#endif\n\n// EDG C++ Front End based compilers (icc, nvcc) do not currently support UDL\n// templates.\n#if FMT_USE_USER_DEFINED_LITERALS && \\\n    FMT_ICC_VERSION == 0 && \\\n    FMT_CUDA_VERSION == 0 && \\\n    ((FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L) || \\\n    (defined(FMT_CLANG_VERSION) && FMT_CLANG_VERSION >= 304))\n# define FMT_UDL_TEMPLATE 1\n#else\n# define FMT_UDL_TEMPLATE 0\n#endif\n\n#ifndef FMT_USE_EXTERN_TEMPLATES\n# ifndef FMT_HEADER_ONLY\n#  define FMT_USE_EXTERN_TEMPLATES \\\n     ((FMT_CLANG_VERSION >= 209 && __cplusplus >= 201103L) || \\\n      (FMT_GCC_VERSION >= 303 && FMT_HAS_GXX_CXX11))\n# else\n#  define FMT_USE_EXTERN_TEMPLATES 0\n# endif\n#endif\n\n#if FMT_HAS_GXX_CXX11 || FMT_HAS_FEATURE(cxx_trailing_return) || \\\n    FMT_MSC_VER >= 1600\n# define FMT_USE_TRAILING_RETURN 1\n#else\n# define FMT_USE_TRAILING_RETURN 0\n#endif\n\n#ifndef FMT_USE_GRISU\n# define FMT_USE_GRISU 0\n//# define FMT_USE_GRISU std::numeric_limits<double>::is_iec559\n#endif\n\n// __builtin_clz is broken in clang with Microsoft CodeGen:\n// https://github.com/fmtlib/fmt/issues/519\n#ifndef _MSC_VER\n# if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz)\n#  define FMT_BUILTIN_CLZ(n) __builtin_clz(n)\n# endif\n\n# if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll)\n#  define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)\n# endif\n#endif\n\n// Some compilers masquerade as both MSVC and GCC-likes or otherwise support\n// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the\n// MSVC intrinsics if the clz and clzll builtins are not available.\n#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(_MANAGED)\n# include <intrin.h>  // _BitScanReverse, _BitScanReverse64\n\nFMT_BEGIN_NAMESPACE\nnamespace internal {\n// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.\n# ifndef __clang__\n#  pragma intrinsic(_BitScanReverse)\n# endif\ninline uint32_t clz(uint32_t x) {\n  unsigned long r = 0;\n  _BitScanReverse(&r, x);\n\n  assert(x != 0);\n  // Static analysis complains about using uninitialized data\n  // \"r\", but the only way that can happen is if \"x\" is 0,\n  // which the callers guarantee to not happen.\n# pragma warning(suppress: 6102)\n  return 31 - r;\n}\n# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n)\n\n# if defined(_WIN64) && !defined(__clang__)\n#  pragma intrinsic(_BitScanReverse64)\n# endif\n\ninline uint32_t clzll(uint64_t x) {\n  unsigned long r = 0;\n# ifdef _WIN64\n  _BitScanReverse64(&r, x);\n# else\n  // Scan the high 32 bits.\n  if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))\n    return 63 - (r + 32);\n\n  // Scan the low 32 bits.\n  _BitScanReverse(&r, static_cast<uint32_t>(x));\n# endif\n\n  assert(x != 0);\n  // Static analysis complains about using uninitialized data\n  // \"r\", but the only way that can happen is if \"x\" is 0,\n  // which the callers guarantee to not happen.\n# pragma warning(suppress: 6102)\n  return 63 - r;\n}\n# define FMT_BUILTIN_CLZLL(n) fmt::internal::clzll(n)\n}\nFMT_END_NAMESPACE\n#endif\n\nFMT_BEGIN_NAMESPACE\nnamespace internal {\n\n// An equivalent of `*reinterpret_cast<Dest*>(&source)` that doesn't produce\n// undefined behavior (e.g. due to type aliasing).\n// Example: uint64_t d = bit_cast<uint64_t>(2.718);\ntemplate <typename Dest, typename Source>\ninline Dest bit_cast(const Source& source) {\n  static_assert(sizeof(Dest) == sizeof(Source), \"size mismatch\");\n  Dest dest;\n  std::memcpy(&dest, &source, sizeof(dest));\n  return dest;\n}\n\n// An implementation of begin and end for pre-C++11 compilers such as gcc 4.\ntemplate <typename C>\nFMT_CONSTEXPR auto begin(const C &c) -> decltype(c.begin()) {\n  return c.begin();\n}\ntemplate <typename T, std::size_t N>\nFMT_CONSTEXPR T *begin(T (&array)[N]) FMT_NOEXCEPT { return array; }\ntemplate <typename C>\nFMT_CONSTEXPR auto end(const C &c) -> decltype(c.end()) { return c.end(); }\ntemplate <typename T, std::size_t N>\nFMT_CONSTEXPR T *end(T (&array)[N]) FMT_NOEXCEPT { return array + N; }\n\n// For std::result_of in gcc 4.4.\ntemplate <typename Result>\nstruct function {\n  template <typename T>\n  struct result { typedef Result type; };\n};\n\nstruct dummy_int {\n  int data[2];\n  operator int() const { return 0; }\n};\ntypedef std::numeric_limits<internal::dummy_int> fputil;\n\n// Dummy implementations of system functions called if the latter are not\n// available.\ninline dummy_int isinf(...) { return dummy_int(); }\ninline dummy_int _finite(...) { return dummy_int(); }\ninline dummy_int isnan(...) { return dummy_int(); }\ninline dummy_int _isnan(...) { return dummy_int(); }\n\ntemplate <typename Allocator>\ntypename Allocator::value_type *allocate(Allocator& alloc, std::size_t n) {\n#if __cplusplus >= 201103L || FMT_MSC_VER >= 1700\n  return std::allocator_traits<Allocator>::allocate(alloc, n);\n#else\n  return alloc.allocate(n);\n#endif\n}\n\n// A helper function to suppress bogus \"conditional expression is constant\"\n// warnings.\ntemplate <typename T>\ninline T const_check(T value) { return value; }\n}  // namespace internal\nFMT_END_NAMESPACE\n\nnamespace std {\n// Standard permits specialization of std::numeric_limits. This specialization\n// is used to resolve ambiguity between isinf and std::isinf in glibc:\n// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48891\n// and the same for isnan.\ntemplate <>\nclass numeric_limits<fmt::internal::dummy_int> :\n    public std::numeric_limits<int> {\n public:\n  // Portable version of isinf.\n  template <typename T>\n  static bool isinfinity(T x) {\n    using namespace fmt::internal;\n    // The resolution \"priority\" is:\n    // isinf macro > std::isinf > ::isinf > fmt::internal::isinf\n    if (const_check(sizeof(isinf(x)) != sizeof(dummy_int)))\n      return isinf(x) != 0;\n    return !_finite(static_cast<double>(x));\n  }\n\n  // Portable version of isnan.\n  template <typename T>\n  static bool isnotanumber(T x) {\n    using namespace fmt::internal;\n    if (const_check(sizeof(isnan(x)) != sizeof(fmt::internal::dummy_int)))\n      return isnan(x) != 0;\n    return _isnan(static_cast<double>(x)) != 0;\n  }\n};\n}  // namespace std\n\nFMT_BEGIN_NAMESPACE\ntemplate <typename Range>\nclass basic_writer;\n\ntemplate <typename OutputIt, typename T = typename OutputIt::value_type>\nclass output_range {\n private:\n  OutputIt it_;\n\n  // Unused yet.\n  typedef void sentinel;\n  sentinel end() const;\n\n public:\n  typedef OutputIt iterator;\n  typedef T value_type;\n\n  explicit output_range(OutputIt it): it_(it) {}\n  OutputIt begin() const { return it_; }\n};\n\n// A range where begin() returns back_insert_iterator.\ntemplate <typename Container>\nclass back_insert_range:\n    public output_range<std::back_insert_iterator<Container>> {\n  typedef output_range<std::back_insert_iterator<Container>> base;\n public:\n  typedef typename Container::value_type value_type;\n\n  back_insert_range(Container &c): base(std::back_inserter(c)) {}\n  back_insert_range(typename base::iterator it): base(it) {}\n};\n\ntypedef basic_writer<back_insert_range<internal::buffer>> writer;\ntypedef basic_writer<back_insert_range<internal::wbuffer>> wwriter;\n\n/** A formatting error such as invalid format string. */\nclass format_error : public std::runtime_error {\n public:\n  explicit format_error(const char *message)\n  : std::runtime_error(message) {}\n\n  explicit format_error(const std::string &message)\n  : std::runtime_error(message) {}\n};\n\nnamespace internal {\n\n#if FMT_SECURE_SCL\ntemplate <typename T>\nstruct checked { typedef stdext::checked_array_iterator<T*> type; };\n\n// Make a checked iterator to avoid warnings on MSVC.\ntemplate <typename T>\ninline stdext::checked_array_iterator<T*> make_checked(T *p, std::size_t size) {\n  return {p, size};\n}\n#else\ntemplate <typename T>\nstruct checked { typedef T *type; };\ntemplate <typename T>\ninline T *make_checked(T *p, std::size_t) { return p; }\n#endif\n\ntemplate <typename T>\ntemplate <typename U>\nvoid basic_buffer<T>::append(const U *begin, const U *end) {\n  std::size_t new_size = size_ + internal::to_unsigned(end - begin);\n  reserve(new_size);\n  std::uninitialized_copy(begin, end,\n                          internal::make_checked(ptr_, capacity_) + size_);\n  size_ = new_size;\n}\n}  // namespace internal\n\n// A UTF-8 code unit type.\nenum char8_t: unsigned char {};\n\n// A UTF-8 string view.\nclass u8string_view : public basic_string_view<char8_t> {\n public:\n  typedef char8_t char_type;\n\n  u8string_view(const char *s):\n    basic_string_view<char8_t>(reinterpret_cast<const char8_t*>(s)) {}\n  u8string_view(const char *s, size_t count) FMT_NOEXCEPT:\n    basic_string_view<char8_t>(reinterpret_cast<const char8_t*>(s), count) {}\n};\n\n#if FMT_USE_USER_DEFINED_LITERALS\ninline namespace literals {\ninline u8string_view operator\"\" _u(const char *s, std::size_t n) {\n  return {s, n};\n}\n}\n#endif\n\n// The number of characters to store in the basic_memory_buffer object itself\n// to avoid dynamic memory allocation.\nenum { inline_buffer_size = 500 };\n\n/**\n  \\rst\n  A dynamically growing memory buffer for trivially copyable/constructible types\n  with the first ``SIZE`` elements stored in the object itself.\n\n  You can use one of the following typedefs for common character types:\n\n  +----------------+------------------------------+\n  | Type           | Definition                   |\n  +================+==============================+\n  | memory_buffer  | basic_memory_buffer<char>    |\n  +----------------+------------------------------+\n  | wmemory_buffer | basic_memory_buffer<wchar_t> |\n  +----------------+------------------------------+\n\n  **Example**::\n\n     fmt::memory_buffer out;\n     format_to(out, \"The answer is {}.\", 42);\n\n  This will append the following output to the ``out`` object:\n\n  .. code-block:: none\n\n     The answer is 42.\n\n  The output can be converted to an ``std::string`` with ``to_string(out)``.\n  \\endrst\n */\ntemplate <typename T, std::size_t SIZE = inline_buffer_size,\n          typename Allocator = std::allocator<T> >\nclass basic_memory_buffer: private Allocator, public internal::basic_buffer<T> {\n private:\n  T store_[SIZE];\n\n  // Deallocate memory allocated by the buffer.\n  void deallocate() {\n    T* data = this->data();\n    if (data != store_) Allocator::deallocate(data, this->capacity());\n  }\n\n protected:\n  void grow(std::size_t size) FMT_OVERRIDE;\n\n public:\n  explicit basic_memory_buffer(const Allocator &alloc = Allocator())\n      : Allocator(alloc) {\n    this->set(store_, SIZE);\n  }\n  ~basic_memory_buffer() { deallocate(); }\n\n private:\n  // Move data from other to this buffer.\n  void move(basic_memory_buffer &other) {\n    Allocator &this_alloc = *this, &other_alloc = other;\n    this_alloc = std::move(other_alloc);\n    T* data = other.data();\n    std::size_t size = other.size(), capacity = other.capacity();\n    if (data == other.store_) {\n      this->set(store_, capacity);\n      std::uninitialized_copy(other.store_, other.store_ + size,\n                              internal::make_checked(store_, capacity));\n    } else {\n      this->set(data, capacity);\n      // Set pointer to the inline array so that delete is not called\n      // when deallocating.\n      other.set(other.store_, 0);\n    }\n    this->resize(size);\n  }\n\n public:\n  /**\n    \\rst\n    Constructs a :class:`fmt::basic_memory_buffer` object moving the content\n    of the other object to it.\n    \\endrst\n   */\n  basic_memory_buffer(basic_memory_buffer &&other) {\n    move(other);\n  }\n\n  /**\n    \\rst\n    Moves the content of the other ``basic_memory_buffer`` object to this one.\n    \\endrst\n   */\n  basic_memory_buffer &operator=(basic_memory_buffer &&other) {\n    assert(this != &other);\n    deallocate();\n    move(other);\n    return *this;\n  }\n\n  // Returns a copy of the allocator associated with this buffer.\n  Allocator get_allocator() const { return *this; }\n};\n\ntemplate <typename T, std::size_t SIZE, typename Allocator>\nvoid basic_memory_buffer<T, SIZE, Allocator>::grow(std::size_t size) {\n  std::size_t old_capacity = this->capacity();\n  std::size_t new_capacity = old_capacity + old_capacity / 2;\n  if (size > new_capacity)\n      new_capacity = size;\n  T *old_data = this->data();\n  T *new_data = internal::allocate<Allocator>(*this, new_capacity);\n  // The following code doesn't throw, so the raw pointer above doesn't leak.\n  std::uninitialized_copy(old_data, old_data + this->size(),\n                          internal::make_checked(new_data, new_capacity));\n  this->set(new_data, new_capacity);\n  // deallocate must not throw according to the standard, but even if it does,\n  // the buffer already uses the new storage and will deallocate it in\n  // destructor.\n  if (old_data != store_)\n    Allocator::deallocate(old_data, old_capacity);\n}\n\ntypedef basic_memory_buffer<char> memory_buffer;\ntypedef basic_memory_buffer<wchar_t> wmemory_buffer;\n\nnamespace internal {\n\ntemplate <typename Char>\nstruct char_traits;\n\ntemplate <>\nstruct char_traits<char> {\n  // Formats a floating-point number.\n  template <typename T>\n  FMT_API static int format_float(char *buffer, std::size_t size,\n      const char *format, int precision, T value);\n};\n\ntemplate <>\nstruct char_traits<wchar_t> {\n  template <typename T>\n  FMT_API static int format_float(wchar_t *buffer, std::size_t size,\n      const wchar_t *format, int precision, T value);\n};\n\n#if FMT_USE_EXTERN_TEMPLATES\nextern template int char_traits<char>::format_float<double>(\n    char *buffer, std::size_t size, const char* format, int precision,\n    double value);\nextern template int char_traits<char>::format_float<long double>(\n    char *buffer, std::size_t size, const char* format, int precision,\n    long double value);\n\nextern template int char_traits<wchar_t>::format_float<double>(\n    wchar_t *buffer, std::size_t size, const wchar_t* format, int precision,\n    double value);\nextern template int char_traits<wchar_t>::format_float<long double>(\n    wchar_t *buffer, std::size_t size, const wchar_t* format, int precision,\n    long double value);\n#endif\n\ntemplate <typename Container>\ninline typename std::enable_if<\n  is_contiguous<Container>::value,\n  typename checked<typename Container::value_type>::type>::type\n    reserve(std::back_insert_iterator<Container> &it, std::size_t n) {\n  Container &c = internal::get_container(it);\n  std::size_t size = c.size();\n  c.resize(size + n);\n  return make_checked(&c[size], n);\n}\n\ntemplate <typename Iterator>\ninline Iterator &reserve(Iterator &it, std::size_t) { return it; }\n\ntemplate <typename Char>\nclass null_terminating_iterator;\n\ntemplate <typename Char>\nFMT_CONSTEXPR_DECL const Char *pointer_from(null_terminating_iterator<Char> it);\n\n// An iterator that produces a null terminator on *end. This simplifies parsing\n// and allows comparing the performance of processing a null-terminated string\n// vs string_view.\ntemplate <typename Char>\nclass null_terminating_iterator {\n public:\n  typedef std::ptrdiff_t difference_type;\n  typedef Char value_type;\n  typedef const Char* pointer;\n  typedef const Char& reference;\n  typedef std::random_access_iterator_tag iterator_category;\n\n  null_terminating_iterator() : ptr_(0), end_(0) {}\n\n  FMT_CONSTEXPR null_terminating_iterator(const Char *ptr, const Char *end)\n    : ptr_(ptr), end_(end) {}\n\n  template <typename Range>\n  FMT_CONSTEXPR explicit null_terminating_iterator(const Range &r)\n    : ptr_(r.begin()), end_(r.end()) {}\n\n  FMT_CONSTEXPR null_terminating_iterator &operator=(const Char *ptr) {\n    assert(ptr <= end_);\n    ptr_ = ptr;\n    return *this;\n  }\n\n  FMT_CONSTEXPR Char operator*() const {\n    return ptr_ != end_ ? *ptr_ : Char();\n  }\n\n  FMT_CONSTEXPR null_terminating_iterator operator++() {\n    ++ptr_;\n    return *this;\n  }\n\n  FMT_CONSTEXPR null_terminating_iterator operator++(int) {\n    null_terminating_iterator result(*this);\n    ++ptr_;\n    return result;\n  }\n\n  FMT_CONSTEXPR null_terminating_iterator operator--() {\n    --ptr_;\n    return *this;\n  }\n\n  FMT_CONSTEXPR null_terminating_iterator operator+(difference_type n) {\n    return null_terminating_iterator(ptr_ + n, end_);\n  }\n\n  FMT_CONSTEXPR null_terminating_iterator operator-(difference_type n) {\n    return null_terminating_iterator(ptr_ - n, end_);\n  }\n\n  FMT_CONSTEXPR null_terminating_iterator operator+=(difference_type n) {\n    ptr_ += n;\n    return *this;\n  }\n\n  FMT_CONSTEXPR difference_type operator-(\n      null_terminating_iterator other) const {\n    return ptr_ - other.ptr_;\n  }\n\n  FMT_CONSTEXPR bool operator!=(null_terminating_iterator other) const {\n    return ptr_ != other.ptr_;\n  }\n\n  bool operator>=(null_terminating_iterator other) const {\n    return ptr_ >= other.ptr_;\n  }\n\n  // This should be a friend specialization pointer_from<Char> but the latter\n  // doesn't compile by gcc 5.1 due to a compiler bug.\n  template <typename CharT>\n  friend FMT_CONSTEXPR_DECL const CharT *pointer_from(\n      null_terminating_iterator<CharT> it);\n\n private:\n  const Char *ptr_;\n  const Char *end_;\n};\n\ntemplate <typename T>\nFMT_CONSTEXPR const T *pointer_from(const T *p) { return p; }\n\ntemplate <typename Char>\nFMT_CONSTEXPR const Char *pointer_from(null_terminating_iterator<Char> it) {\n  return it.ptr_;\n}\n\n// An output iterator that counts the number of objects written to it and\n// discards them.\ntemplate <typename T>\nclass counting_iterator {\n private:\n  std::size_t count_;\n  mutable T blackhole_;\n\n public:\n  typedef std::output_iterator_tag iterator_category;\n  typedef T value_type;\n  typedef std::ptrdiff_t difference_type;\n  typedef T* pointer;\n  typedef T& reference;\n  typedef counting_iterator _Unchecked_type;  // Mark iterator as checked.\n\n  counting_iterator(): count_(0) {}\n\n  std::size_t count() const { return count_; }\n\n  counting_iterator& operator++() {\n    ++count_;\n    return *this;\n  }\n\n  counting_iterator operator++(int) {\n    auto it = *this;\n    ++*this;\n    return it;\n  }\n\n  T &operator*() const { return blackhole_; }\n};\n\ntemplate <typename OutputIt>\nclass truncating_iterator_base {\n protected:\n  OutputIt out_;\n  std::size_t limit_;\n  std::size_t count_;\n\n  truncating_iterator_base(OutputIt out, std::size_t limit)\n    : out_(out), limit_(limit), count_(0) {}\n\n public:\n  typedef std::output_iterator_tag iterator_category;\n  typedef void difference_type;\n  typedef void pointer;\n  typedef void reference;\n  typedef truncating_iterator_base _Unchecked_type; // Mark iterator as checked.\n\n  OutputIt base() const { return out_; }\n  std::size_t count() const { return count_; }\n};\n\n// An output iterator that truncates the output and counts the number of objects\n// written to it.\ntemplate <typename OutputIt, typename Enable = typename std::is_void<\n    typename std::iterator_traits<OutputIt>::value_type>::type>\nclass truncating_iterator;\n\ntemplate <typename OutputIt>\nclass truncating_iterator<OutputIt, std::false_type>:\n  public truncating_iterator_base<OutputIt> {\n  typedef std::iterator_traits<OutputIt> traits;\n\n  mutable typename traits::value_type blackhole_;\n\n public:\n  typedef typename traits::value_type value_type;\n\n  truncating_iterator(OutputIt out, std::size_t limit)\n    : truncating_iterator_base<OutputIt>(out, limit) {}\n\n  truncating_iterator& operator++() {\n    if (this->count_++ < this->limit_)\n      ++this->out_;\n    return *this;\n  }\n\n  truncating_iterator operator++(int) {\n    auto it = *this;\n    ++*this;\n    return it;\n  }\n\n  value_type& operator*() const {\n    return this->count_ < this->limit_ ? *this->out_ : blackhole_;\n  }\n};\n\ntemplate <typename OutputIt>\nclass truncating_iterator<OutputIt, std::true_type>:\n  public truncating_iterator_base<OutputIt> {\n public:\n  typedef typename OutputIt::container_type::value_type value_type;\n\n  truncating_iterator(OutputIt out, std::size_t limit)\n    : truncating_iterator_base<OutputIt>(out, limit) {}\n\n  truncating_iterator& operator=(value_type val) {\n    if (this->count_++ < this->limit_)\n      this->out_ = val;\n    return *this;\n  }\n\n  truncating_iterator& operator++() { return *this; }\n  truncating_iterator& operator++(int) { return *this; }\n  truncating_iterator& operator*() { return *this; }\n};\n\n// Returns true if value is negative, false otherwise.\n// Same as (value < 0) but doesn't produce warnings if T is an unsigned type.\ntemplate <typename T>\nFMT_CONSTEXPR typename std::enable_if<\n    std::numeric_limits<T>::is_signed, bool>::type is_negative(T value) {\n  return value < 0;\n}\ntemplate <typename T>\nFMT_CONSTEXPR typename std::enable_if<\n    !std::numeric_limits<T>::is_signed, bool>::type is_negative(T) {\n  return false;\n}\n\ntemplate <typename T>\nstruct int_traits {\n  // Smallest of uint32_t and uint64_t that is large enough to represent\n  // all values of T.\n  typedef typename std::conditional<\n    std::numeric_limits<T>::digits <= 32, uint32_t, uint64_t>::type main_type;\n};\n\n// Static data is placed in this class template to allow header-only\n// configuration.\ntemplate <typename T = void>\nstruct FMT_API basic_data {\n  static const uint32_t POWERS_OF_10_32[];\n  static const uint32_t ZERO_OR_POWERS_OF_10_32[];\n  static const uint64_t ZERO_OR_POWERS_OF_10_64[];\n  static const uint64_t POW10_SIGNIFICANDS[];\n  static const int16_t POW10_EXPONENTS[];\n  static const char DIGITS[];\n  static const char FOREGROUND_COLOR[];\n  static const char BACKGROUND_COLOR[];\n  static const char RESET_COLOR[];\n  static const wchar_t WRESET_COLOR[];\n};\n\n#if FMT_USE_EXTERN_TEMPLATES\nextern template struct basic_data<void>;\n#endif\n\ntypedef basic_data<> data;\n\n#ifdef FMT_BUILTIN_CLZLL\n// Returns the number of decimal digits in n. Leading zeros are not counted\n// except for n == 0 in which case count_digits returns 1.\ninline unsigned count_digits(uint64_t n) {\n  // Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10\n  // and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits.\n  int t = (64 - FMT_BUILTIN_CLZLL(n | 1)) * 1233 >> 12;\n  return to_unsigned(t) - (n < data::ZERO_OR_POWERS_OF_10_64[t]) + 1;\n}\n#else\n// Fallback version of count_digits used when __builtin_clz is not available.\ninline unsigned count_digits(uint64_t n) {\n  unsigned count = 1;\n  for (;;) {\n    // Integer division is slow so do it for a group of four digits instead\n    // of for every digit. The idea comes from the talk by Alexandrescu\n    // \"Three Optimization Tips for C++\". See speed-test for a comparison.\n    if (n < 10) return count;\n    if (n < 100) return count + 1;\n    if (n < 1000) return count + 2;\n    if (n < 10000) return count + 3;\n    n /= 10000u;\n    count += 4;\n  }\n}\n#endif\n\ntemplate <typename Char>\ninline size_t count_code_points(basic_string_view<Char> s) { return s.size(); }\n\n// Counts the number of code points in a UTF-8 string.\nFMT_API size_t count_code_points(basic_string_view<char8_t> s);\n\ninline char8_t to_char8_t(char c) { return static_cast<char8_t>(c); }\n\ntemplate <typename InputIt, typename OutChar>\nstruct needs_conversion: std::integral_constant<bool,\n  std::is_same<\n    typename std::iterator_traits<InputIt>::value_type, char>::value &&\n  std::is_same<OutChar, char8_t>::value> {};\n\ntemplate <typename OutChar, typename InputIt, typename OutputIt>\ntypename std::enable_if<\n  !needs_conversion<InputIt, OutChar>::value, OutputIt>::type\n    copy_str(InputIt begin, InputIt end, OutputIt it) {\n  return std::copy(begin, end, it);\n}\n\ntemplate <typename OutChar, typename InputIt, typename OutputIt>\ntypename std::enable_if<\n  needs_conversion<InputIt, OutChar>::value, OutputIt>::type\n    copy_str(InputIt begin, InputIt end, OutputIt it) {\n  return std::transform(begin, end, it, to_char8_t);\n}\n\n#if FMT_HAS_CPP_ATTRIBUTE(always_inline)\n# define FMT_ALWAYS_INLINE __attribute__((always_inline))\n#else\n# define FMT_ALWAYS_INLINE\n#endif\n\ntemplate <typename Handler>\ninline char *lg(uint32_t n, Handler h) FMT_ALWAYS_INLINE;\n\n// Computes g = floor(log10(n)) and calls h.on<g>(n);\ntemplate <typename Handler>\ninline char *lg(uint32_t n, Handler h) {\n  return n < 100 ? n < 10 ? h.template on<0>(n) : h.template on<1>(n)\n                 : n < 1000000\n                       ? n < 10000 ? n < 1000 ? h.template on<2>(n)\n                                              : h.template on<3>(n)\n                                   : n < 100000 ? h.template on<4>(n)\n                                                : h.template on<5>(n)\n                       : n < 100000000 ? n < 10000000 ? h.template on<6>(n)\n                                                      : h.template on<7>(n)\n                                       : n < 1000000000 ? h.template on<8>(n)\n                                                        : h.template on<9>(n);\n}\n\n// An lg handler that formats a decimal number.\n// Usage: lg(n, decimal_formatter(buffer));\nclass decimal_formatter {\n private:\n  char *buffer_;\n\n  void write_pair(unsigned N, uint32_t index) {\n    std::memcpy(buffer_ + N, data::DIGITS + index * 2, 2);\n  }\n\n public:\n  explicit decimal_formatter(char *buf) : buffer_(buf) {}\n\n  template <unsigned N> char *on(uint32_t u) {\n    if (N == 0) {\n      *buffer_ = static_cast<char>(u) + '0';\n    } else if (N == 1) {\n      write_pair(0, u);\n    } else {\n      // The idea of using 4.32 fixed-point numbers is based on\n      // https://github.com/jeaiii/itoa\n      unsigned n = N - 1;\n      unsigned a = n / 5 * n * 53 / 16;\n      uint64_t t = ((1ULL << (32 + a)) /\n                   data::ZERO_OR_POWERS_OF_10_32[n] + 1 - n / 9);\n      t = ((t * u) >> a) + n / 5 * 4;\n      write_pair(0, t >> 32);\n      for (unsigned i = 2; i < N; i += 2) {\n        t = 100ULL * static_cast<uint32_t>(t);\n        write_pair(i, t >> 32);\n      }\n      if (N % 2 == 0) {\n        buffer_[N] = static_cast<char>(\n          (10ULL * static_cast<uint32_t>(t)) >> 32) + '0';\n      }\n    }\n    return buffer_ += N + 1;\n  }\n};\n\n// An lg handler that formats a decimal number with a terminating null.\nclass decimal_formatter_null : public decimal_formatter {\n public:\n  explicit decimal_formatter_null(char *buf) : decimal_formatter(buf) {}\n\n  template <unsigned N> char *on(uint32_t u) {\n    char *buf = decimal_formatter::on<N>(u);\n    *buf = '\\0';\n    return buf;\n  }\n};\n\n#ifdef FMT_BUILTIN_CLZ\n// Optional version of count_digits for better performance on 32-bit platforms.\ninline unsigned count_digits(uint32_t n) {\n  int t = (32 - FMT_BUILTIN_CLZ(n | 1)) * 1233 >> 12;\n  return to_unsigned(t) - (n < data::ZERO_OR_POWERS_OF_10_32[t]) + 1;\n}\n#endif\n\n// A functor that doesn't add a thousands separator.\nstruct no_thousands_sep {\n  typedef char char_type;\n\n  template <typename Char>\n  void operator()(Char *) {}\n\n  enum { size = 0 };\n};\n\n// A functor that adds a thousands separator.\ntemplate <typename Char>\nclass add_thousands_sep {\n private:\n  basic_string_view<Char> sep_;\n\n  // Index of a decimal digit with the least significant digit having index 0.\n  unsigned digit_index_;\n\n public:\n  typedef Char char_type;\n\n  explicit add_thousands_sep(basic_string_view<Char> sep)\n    : sep_(sep), digit_index_(0) {}\n\n  void operator()(Char *&buffer) {\n    if (++digit_index_ % 3 != 0)\n      return;\n    buffer -= sep_.size();\n    std::uninitialized_copy(sep_.data(), sep_.data() + sep_.size(),\n                            internal::make_checked(buffer, sep_.size()));\n  }\n\n  enum { size = 1 };\n};\n\ntemplate <typename Char>\nFMT_API Char thousands_sep_impl(locale_ref loc);\n\ntemplate <typename Char>\ninline Char thousands_sep(locale_ref loc) {\n  return Char(thousands_sep_impl<char>(loc));\n}\n\ntemplate <>\ninline wchar_t thousands_sep(locale_ref loc) {\n  return thousands_sep_impl<wchar_t>(loc);\n}\n\n// Formats a decimal unsigned integer value writing into buffer.\n// thousands_sep is a functor that is called after writing each char to\n// add a thousands separator if necessary.\ntemplate <typename UInt, typename Char, typename ThousandsSep>\ninline Char *format_decimal(Char *buffer, UInt value, unsigned num_digits,\n                            ThousandsSep thousands_sep) {\n  buffer += num_digits;\n  Char *end = buffer;\n  while (value >= 100) {\n    // Integer division is slow so do it for a group of two digits instead\n    // of for every digit. The idea comes from the talk by Alexandrescu\n    // \"Three Optimization Tips for C++\". See speed-test for a comparison.\n    unsigned index = static_cast<unsigned>((value % 100) * 2);\n    value /= 100;\n    *--buffer = static_cast<Char>(data::DIGITS[index + 1]);\n    thousands_sep(buffer);\n    *--buffer = static_cast<Char>(data::DIGITS[index]);\n    thousands_sep(buffer);\n  }\n  if (value < 10) {\n    *--buffer = static_cast<Char>('0' + value);\n    return end;\n  }\n  unsigned index = static_cast<unsigned>(value * 2);\n  *--buffer = static_cast<Char>(data::DIGITS[index + 1]);\n  thousands_sep(buffer);\n  *--buffer = static_cast<Char>(data::DIGITS[index]);\n  return end;\n}\n\ntemplate <typename OutChar, typename UInt, typename Iterator,\n          typename ThousandsSep>\ninline Iterator format_decimal(\n    Iterator out, UInt value, unsigned num_digits, ThousandsSep sep) {\n  typedef typename ThousandsSep::char_type char_type;\n  // Buffer should be large enough to hold all digits (<= digits10 + 1).\n  enum { max_size = std::numeric_limits<UInt>::digits10 + 1 };\n  FMT_ASSERT(ThousandsSep::size <= 1, \"invalid separator\");\n  char_type buffer[max_size + max_size / 3];\n  auto end = format_decimal(buffer, value, num_digits, sep);\n  return internal::copy_str<OutChar>(buffer, end, out);\n}\n\ntemplate <typename OutChar, typename It, typename UInt>\ninline It format_decimal(It out, UInt value, unsigned num_digits) {\n  return format_decimal<OutChar>(out, value, num_digits, no_thousands_sep());\n}\n\ntemplate <unsigned BASE_BITS, typename Char, typename UInt>\ninline Char *format_uint(Char *buffer, UInt value, unsigned num_digits,\n                         bool upper = false) {\n  buffer += num_digits;\n  Char *end = buffer;\n  do {\n    const char *digits = upper ? \"0123456789ABCDEF\" : \"0123456789abcdef\";\n    unsigned digit = (value & ((1 << BASE_BITS) - 1));\n    *--buffer = static_cast<Char>(BASE_BITS < 4 ? '0' + digit : digits[digit]);\n  } while ((value >>= BASE_BITS) != 0);\n  return end;\n}\n\ntemplate <unsigned BASE_BITS, typename Char, typename It, typename UInt>\ninline It format_uint(It out, UInt value, unsigned num_digits,\n                      bool upper = false) {\n  // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1)\n  // and null.\n  char buffer[std::numeric_limits<UInt>::digits / BASE_BITS + 2];\n  format_uint<BASE_BITS>(buffer, value, num_digits, upper);\n  return internal::copy_str<Char>(buffer, buffer + num_digits, out);\n}\n\n#ifndef _WIN32\n# define FMT_USE_WINDOWS_H 0\n#elif !defined(FMT_USE_WINDOWS_H)\n# define FMT_USE_WINDOWS_H 1\n#endif\n\n// Define FMT_USE_WINDOWS_H to 0 to disable use of windows.h.\n// All the functionality that relies on it will be disabled too.\n#if FMT_USE_WINDOWS_H\n// A converter from UTF-8 to UTF-16.\n// It is only provided for Windows since other systems support UTF-8 natively.\nclass utf8_to_utf16 {\n private:\n  wmemory_buffer buffer_;\n\n public:\n  FMT_API explicit utf8_to_utf16(string_view s);\n  operator wstring_view() const { return wstring_view(&buffer_[0], size()); }\n  size_t size() const { return buffer_.size() - 1; }\n  const wchar_t *c_str() const { return &buffer_[0]; }\n  std::wstring str() const { return std::wstring(&buffer_[0], size()); }\n};\n\n// A converter from UTF-16 to UTF-8.\n// It is only provided for Windows since other systems support UTF-8 natively.\nclass utf16_to_utf8 {\n private:\n  memory_buffer buffer_;\n\n public:\n  utf16_to_utf8() {}\n  FMT_API explicit utf16_to_utf8(wstring_view s);\n  operator string_view() const { return string_view(&buffer_[0], size()); }\n  size_t size() const { return buffer_.size() - 1; }\n  const char *c_str() const { return &buffer_[0]; }\n  std::string str() const { return std::string(&buffer_[0], size()); }\n\n  // Performs conversion returning a system error code instead of\n  // throwing exception on conversion error. This method may still throw\n  // in case of memory allocation error.\n  FMT_API int convert(wstring_view s);\n};\n\nFMT_API void format_windows_error(fmt::internal::buffer &out, int error_code,\n                                  fmt::string_view message) FMT_NOEXCEPT;\n#endif\n\ntemplate <typename T = void>\nstruct null {};\n}  // namespace internal\n\nenum alignment {\n  ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC\n};\n\n// Flags.\nenum { SIGN_FLAG = 1, PLUS_FLAG = 2, MINUS_FLAG = 4, HASH_FLAG = 8 };\n\n// An alignment specifier.\nstruct align_spec {\n  unsigned width_;\n  // Fill is always wchar_t and cast to char if necessary to avoid having\n  // two specialization of AlignSpec and its subclasses.\n  wchar_t fill_;\n  alignment align_;\n\n  FMT_CONSTEXPR align_spec() : width_(0), fill_(' '), align_(ALIGN_DEFAULT) {}\n  FMT_CONSTEXPR unsigned width() const { return width_; }\n  FMT_CONSTEXPR wchar_t fill() const { return fill_; }\n  FMT_CONSTEXPR alignment align() const { return align_; }\n};\n\nstruct core_format_specs {\n  int precision;\n  uint_least8_t flags;\n  char type;\n\n  FMT_CONSTEXPR core_format_specs() : precision(-1), flags(0), type(0) {}\n  FMT_CONSTEXPR bool has(unsigned f) const { return (flags & f) != 0; }\n};\n\n// Format specifiers.\ntemplate <typename Char>\nstruct basic_format_specs : align_spec, core_format_specs {\n  FMT_CONSTEXPR basic_format_specs() {}\n};\n\ntypedef basic_format_specs<char> format_specs;\n\ntemplate <typename Char, typename ErrorHandler>\nFMT_CONSTEXPR unsigned basic_parse_context<Char, ErrorHandler>::next_arg_id() {\n  if (next_arg_id_ >= 0)\n    return internal::to_unsigned(next_arg_id_++);\n  on_error(\"cannot switch from manual to automatic argument indexing\");\n  return 0;\n}\n\nnamespace internal {\n\n// Formats value using Grisu2 algorithm:\n// https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf\ntemplate <typename Double>\nFMT_API typename std::enable_if<sizeof(Double) == sizeof(uint64_t), bool>::type\n  grisu2_format(Double value, buffer &buf, core_format_specs);\ntemplate <typename Double>\ninline typename std::enable_if<sizeof(Double) != sizeof(uint64_t), bool>::type\n  grisu2_format(Double, buffer &, core_format_specs) { return false; }\n\ntemplate <typename Double>\nvoid sprintf_format(Double, internal::buffer &, core_format_specs);\n\ntemplate <typename Handler>\nFMT_CONSTEXPR void handle_int_type_spec(char spec, Handler &&handler) {\n  switch (spec) {\n  case 0: case 'd':\n    handler.on_dec();\n    break;\n  case 'x': case 'X':\n    handler.on_hex();\n    break;\n  case 'b': case 'B':\n    handler.on_bin();\n    break;\n  case 'o':\n    handler.on_oct();\n    break;\n  case 'n':\n    handler.on_num();\n    break;\n  default:\n    handler.on_error();\n  }\n}\n\ntemplate <typename Handler>\nFMT_CONSTEXPR void handle_float_type_spec(char spec, Handler &&handler) {\n  switch (spec) {\n  case 0: case 'g': case 'G':\n    handler.on_general();\n    break;\n  case 'e': case 'E':\n    handler.on_exp();\n    break;\n  case 'f': case 'F':\n    handler.on_fixed();\n    break;\n   case 'a': case 'A':\n    handler.on_hex();\n    break;\n  default:\n    handler.on_error();\n    break;\n  }\n}\n\ntemplate <typename Char, typename Handler>\nFMT_CONSTEXPR void handle_char_specs(\n    const basic_format_specs<Char> *specs, Handler &&handler) {\n  if (!specs) return handler.on_char();\n  if (specs->type && specs->type != 'c') return handler.on_int();\n  if (specs->align() == ALIGN_NUMERIC || specs->flags != 0)\n    handler.on_error(\"invalid format specifier for char\");\n  handler.on_char();\n}\n\ntemplate <typename Char, typename Handler>\nFMT_CONSTEXPR void handle_cstring_type_spec(Char spec, Handler &&handler) {\n  if (spec == 0 || spec == 's')\n    handler.on_string();\n  else if (spec == 'p')\n    handler.on_pointer();\n  else\n    handler.on_error(\"invalid type specifier\");\n}\n\ntemplate <typename Char, typename ErrorHandler>\nFMT_CONSTEXPR void check_string_type_spec(Char spec, ErrorHandler &&eh) {\n  if (spec != 0 && spec != 's')\n    eh.on_error(\"invalid type specifier\");\n}\n\ntemplate <typename Char, typename ErrorHandler>\nFMT_CONSTEXPR void check_pointer_type_spec(Char spec, ErrorHandler &&eh) {\n  if (spec != 0 && spec != 'p')\n    eh.on_error(\"invalid type specifier\");\n}\n\ntemplate <typename ErrorHandler>\nclass int_type_checker : private ErrorHandler {\n public:\n  FMT_CONSTEXPR explicit int_type_checker(ErrorHandler eh) : ErrorHandler(eh) {}\n\n  FMT_CONSTEXPR void on_dec() {}\n  FMT_CONSTEXPR void on_hex() {}\n  FMT_CONSTEXPR void on_bin() {}\n  FMT_CONSTEXPR void on_oct() {}\n  FMT_CONSTEXPR void on_num() {}\n\n  FMT_CONSTEXPR void on_error() {\n    ErrorHandler::on_error(\"invalid type specifier\");\n  }\n};\n\ntemplate <typename ErrorHandler>\nclass float_type_checker : private ErrorHandler {\n public:\n  FMT_CONSTEXPR explicit float_type_checker(ErrorHandler eh)\n    : ErrorHandler(eh) {}\n\n  FMT_CONSTEXPR void on_general() {}\n  FMT_CONSTEXPR void on_exp() {}\n  FMT_CONSTEXPR void on_fixed() {}\n  FMT_CONSTEXPR void on_hex() {}\n\n  FMT_CONSTEXPR void on_error() {\n    ErrorHandler::on_error(\"invalid type specifier\");\n  }\n};\n\ntemplate <typename ErrorHandler>\nclass char_specs_checker : public ErrorHandler {\n private:\n  char type_;\n\n public:\n  FMT_CONSTEXPR char_specs_checker(char type, ErrorHandler eh)\n    : ErrorHandler(eh), type_(type) {}\n\n  FMT_CONSTEXPR void on_int() {\n    handle_int_type_spec(type_, int_type_checker<ErrorHandler>(*this));\n  }\n  FMT_CONSTEXPR void on_char() {}\n};\n\ntemplate <typename ErrorHandler>\nclass cstring_type_checker : public ErrorHandler {\n public:\n  FMT_CONSTEXPR explicit cstring_type_checker(ErrorHandler eh)\n    : ErrorHandler(eh) {}\n\n  FMT_CONSTEXPR void on_string() {}\n  FMT_CONSTEXPR void on_pointer() {}\n};\n\ntemplate <typename Context>\nvoid arg_map<Context>::init(const basic_format_args<Context> &args) {\n  if (map_)\n    return;\n  map_ = new entry[args.max_size()];\n  bool use_values = args.type(max_packed_args - 1) == internal::none_type;\n  if (use_values) {\n    for (unsigned i = 0;/*nothing*/; ++i) {\n      internal::type arg_type = args.type(i);\n      switch (arg_type) {\n        case internal::none_type:\n          return;\n        case internal::named_arg_type:\n          push_back(args.values_[i]);\n          break;\n        default:\n          break; // Do nothing.\n      }\n    }\n  }\n  for (unsigned i = 0; ; ++i) {\n    switch (args.args_[i].type_) {\n      case internal::none_type:\n        return;\n      case internal::named_arg_type:\n        push_back(args.args_[i].value_);\n        break;\n      default:\n        break; // Do nothing.\n    }\n  }\n}\n\ntemplate <typename Range>\nclass arg_formatter_base {\n public:\n  typedef typename Range::value_type char_type;\n  typedef decltype(internal::declval<Range>().begin()) iterator;\n  typedef basic_format_specs<char_type> format_specs;\n\n private:\n  typedef basic_writer<Range> writer_type;\n  writer_type writer_;\n  format_specs *specs_;\n\n  struct char_writer {\n    char_type value;\n\n    size_t size() const { return 1; }\n    size_t width() const { return 1; }\n\n    template <typename It>\n    void operator()(It &&it) const { *it++ = value; }\n  };\n\n  void write_char(char_type value) {\n    if (specs_)\n      writer_.write_padded(*specs_, char_writer{value});\n    else\n      writer_.write(value);\n  }\n\n  void write_pointer(const void *p) {\n    format_specs specs = specs_ ? *specs_ : format_specs();\n    specs.flags = HASH_FLAG;\n    specs.type = 'x';\n    writer_.write_int(reinterpret_cast<uintptr_t>(p), specs);\n  }\n\n protected:\n  writer_type &writer() { return writer_; }\n  format_specs *spec() { return specs_; }\n  iterator out() { return writer_.out(); }\n\n  void write(bool value) {\n    string_view sv(value ? \"true\" : \"false\");\n    specs_ ? writer_.write_str(sv, *specs_) : writer_.write(sv);\n  }\n\n  void write(const char_type *value) {\n    if (!value)\n      FMT_THROW(format_error(\"string pointer is null\"));\n    auto length = std::char_traits<char_type>::length(value);\n    basic_string_view<char_type> sv(value, length);\n    specs_ ? writer_.write_str(sv, *specs_) : writer_.write(sv);\n  }\n\n public:\n  arg_formatter_base(Range r, format_specs *s, locale_ref loc)\n    : writer_(r, loc), specs_(s) {}\n\n  iterator operator()(monostate) {\n    FMT_ASSERT(false, \"invalid argument type\");\n    return out();\n  }\n\n  template <typename T>\n  typename std::enable_if<\n    std::is_integral<T>::value || std::is_same<T, char_type>::value,\n    iterator>::type operator()(T value) {\n    // MSVC2013 fails to compile separate overloads for bool and char_type so\n    // use std::is_same instead.\n    if (std::is_same<T, bool>::value) {\n      if (specs_ && specs_->type)\n        return (*this)(value ? 1 : 0);\n      write(value != 0);\n    } else if (std::is_same<T, char_type>::value) {\n      internal::handle_char_specs(\n        specs_, char_spec_handler(*this, static_cast<char_type>(value)));\n    } else {\n      specs_ ? writer_.write_int(value, *specs_) : writer_.write(value);\n    }\n    return out();\n  }\n\n  template <typename T>\n  typename std::enable_if<std::is_floating_point<T>::value, iterator>::type\n      operator()(T value) {\n    writer_.write_double(value, specs_ ? *specs_ : format_specs());\n    return out();\n  }\n\n  struct char_spec_handler : internal::error_handler {\n    arg_formatter_base &formatter;\n    char_type value;\n\n    char_spec_handler(arg_formatter_base& f, char_type val)\n      : formatter(f), value(val) {}\n\n    void on_int() {\n      if (formatter.specs_)\n        formatter.writer_.write_int(value, *formatter.specs_);\n      else\n        formatter.writer_.write(value);\n    }\n    void on_char() { formatter.write_char(value); }\n  };\n\n  struct cstring_spec_handler : internal::error_handler {\n    arg_formatter_base &formatter;\n    const char_type *value;\n\n    cstring_spec_handler(arg_formatter_base &f, const char_type *val)\n      : formatter(f), value(val) {}\n\n    void on_string() { formatter.write(value); }\n    void on_pointer() { formatter.write_pointer(value); }\n  };\n\n  iterator operator()(const char_type *value) {\n    if (!specs_) return write(value), out();\n    internal::handle_cstring_type_spec(\n          specs_->type, cstring_spec_handler(*this, value));\n    return out();\n  }\n\n  iterator operator()(basic_string_view<char_type> value) {\n    if (specs_) {\n      internal::check_string_type_spec(\n            specs_->type, internal::error_handler());\n      writer_.write_str(value, *specs_);\n    } else {\n      writer_.write(value);\n    }\n    return out();\n  }\n\n  iterator operator()(const void *value) {\n    if (specs_)\n      check_pointer_type_spec(specs_->type, internal::error_handler());\n    write_pointer(value);\n    return out();\n  }\n};\n\ntemplate <typename Char>\nFMT_CONSTEXPR bool is_name_start(Char c) {\n  return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;\n}\n\n// DEPRECATED: Parses the input as an unsigned integer. This function assumes\n// that the first character is a digit and presence of a non-digit character at\n// the end.\n// it: an iterator pointing to the beginning of the input range.\ntemplate <typename Iterator, typename ErrorHandler>\nFMT_CONSTEXPR unsigned parse_nonnegative_int(Iterator &it, ErrorHandler &&eh) {\n  assert('0' <= *it && *it <= '9');\n  if (*it == '0') {\n    ++it;\n    return 0;\n  }\n  unsigned value = 0;\n  // Convert to unsigned to prevent a warning.\n  unsigned max_int = (std::numeric_limits<int>::max)();\n  unsigned big = max_int / 10;\n  do {\n    // Check for overflow.\n    if (value > big) {\n      value = max_int + 1;\n      break;\n    }\n    value = value * 10 + unsigned(*it - '0');\n    // Workaround for MSVC \"setup_exception stack overflow\" error:\n    auto next = it;\n    ++next;\n    it = next;\n  } while ('0' <= *it && *it <= '9');\n  if (value > max_int)\n    eh.on_error(\"number is too big\");\n  return value;\n}\n\n// Parses the range [begin, end) as an unsigned integer. This function assumes\n// that the range is non-empty and the first character is a digit.\ntemplate <typename Char, typename ErrorHandler>\nFMT_CONSTEXPR unsigned parse_nonnegative_int(\n    const Char *&begin, const Char *end, ErrorHandler &&eh) {\n  assert(begin != end && '0' <= *begin && *begin <= '9');\n  if (*begin == '0') {\n    ++begin;\n    return 0;\n  }\n  unsigned value = 0;\n  // Convert to unsigned to prevent a warning.\n  unsigned max_int = (std::numeric_limits<int>::max)();\n  unsigned big = max_int / 10;\n  do {\n    // Check for overflow.\n    if (value > big) {\n      value = max_int + 1;\n      break;\n    }\n    value = value * 10 + unsigned(*begin - '0');\n    ++begin;\n  } while (begin != end && '0' <= *begin && *begin <= '9');\n  if (value > max_int)\n    eh.on_error(\"number is too big\");\n  return value;\n}\n\ntemplate <typename Char, typename Context>\nclass custom_formatter: public function<bool> {\n private:\n  Context &ctx_;\n\n public:\n  explicit custom_formatter(Context &ctx): ctx_(ctx) {}\n\n  bool operator()(typename basic_format_arg<Context>::handle h) const {\n    h.format(ctx_);\n    return true;\n  }\n\n  template <typename T>\n  bool operator()(T) const { return false; }\n};\n\ntemplate <typename T>\nstruct is_integer {\n  enum {\n    value = std::is_integral<T>::value && !std::is_same<T, bool>::value &&\n            !std::is_same<T, char>::value && !std::is_same<T, wchar_t>::value\n  };\n};\n\ntemplate <typename ErrorHandler>\nclass width_checker: public function<unsigned long long> {\n public:\n  explicit FMT_CONSTEXPR width_checker(ErrorHandler &eh) : handler_(eh) {}\n\n  template <typename T>\n  FMT_CONSTEXPR\n  typename std::enable_if<\n      is_integer<T>::value, unsigned long long>::type operator()(T value) {\n    if (is_negative(value))\n      handler_.on_error(\"negative width\");\n    return static_cast<unsigned long long>(value);\n  }\n\n  template <typename T>\n  FMT_CONSTEXPR typename std::enable_if<\n      !is_integer<T>::value, unsigned long long>::type operator()(T) {\n    handler_.on_error(\"width is not integer\");\n    return 0;\n  }\n\n private:\n  ErrorHandler &handler_;\n};\n\ntemplate <typename ErrorHandler>\nclass precision_checker: public function<unsigned long long> {\n public:\n  explicit FMT_CONSTEXPR precision_checker(ErrorHandler &eh) : handler_(eh) {}\n\n  template <typename T>\n  FMT_CONSTEXPR typename std::enable_if<\n      is_integer<T>::value, unsigned long long>::type operator()(T value) {\n    if (is_negative(value))\n      handler_.on_error(\"negative precision\");\n    return static_cast<unsigned long long>(value);\n  }\n\n  template <typename T>\n  FMT_CONSTEXPR typename std::enable_if<\n      !is_integer<T>::value, unsigned long long>::type operator()(T) {\n    handler_.on_error(\"precision is not integer\");\n    return 0;\n  }\n\n private:\n  ErrorHandler &handler_;\n};\n\n// A format specifier handler that sets fields in basic_format_specs.\ntemplate <typename Char>\nclass specs_setter {\n public:\n  explicit FMT_CONSTEXPR specs_setter(basic_format_specs<Char> &specs):\n    specs_(specs) {}\n\n  FMT_CONSTEXPR specs_setter(const specs_setter &other): specs_(other.specs_) {}\n\n  FMT_CONSTEXPR void on_align(alignment align) { specs_.align_ = align; }\n  FMT_CONSTEXPR void on_fill(Char fill) { specs_.fill_ = fill; }\n  FMT_CONSTEXPR void on_plus() { specs_.flags |= SIGN_FLAG | PLUS_FLAG; }\n  FMT_CONSTEXPR void on_minus() { specs_.flags |= MINUS_FLAG; }\n  FMT_CONSTEXPR void on_space() { specs_.flags |= SIGN_FLAG; }\n  FMT_CONSTEXPR void on_hash() { specs_.flags |= HASH_FLAG; }\n\n  FMT_CONSTEXPR void on_zero() {\n    specs_.align_ = ALIGN_NUMERIC;\n    specs_.fill_ = '0';\n  }\n\n  FMT_CONSTEXPR void on_width(unsigned width) { specs_.width_ = width; }\n  FMT_CONSTEXPR void on_precision(unsigned precision) {\n    specs_.precision = static_cast<int>(precision);\n  }\n  FMT_CONSTEXPR void end_precision() {}\n\n  FMT_CONSTEXPR void on_type(Char type) {\n    specs_.type = static_cast<char>(type);\n  }\n\n protected:\n  basic_format_specs<Char> &specs_;\n};\n\n// A format specifier handler that checks if specifiers are consistent with the\n// argument type.\ntemplate <typename Handler>\nclass specs_checker : public Handler {\n public:\n  FMT_CONSTEXPR specs_checker(const Handler& handler, internal::type arg_type)\n    : Handler(handler), arg_type_(arg_type) {}\n\n  FMT_CONSTEXPR specs_checker(const specs_checker &other)\n    : Handler(other), arg_type_(other.arg_type_) {}\n\n  FMT_CONSTEXPR void on_align(alignment align) {\n    if (align == ALIGN_NUMERIC)\n      require_numeric_argument();\n    Handler::on_align(align);\n  }\n\n  FMT_CONSTEXPR void on_plus() {\n    check_sign();\n    Handler::on_plus();\n  }\n\n  FMT_CONSTEXPR void on_minus() {\n    check_sign();\n    Handler::on_minus();\n  }\n\n  FMT_CONSTEXPR void on_space() {\n    check_sign();\n    Handler::on_space();\n  }\n\n  FMT_CONSTEXPR void on_hash() {\n    require_numeric_argument();\n    Handler::on_hash();\n  }\n\n  FMT_CONSTEXPR void on_zero() {\n    require_numeric_argument();\n    Handler::on_zero();\n  }\n\n  FMT_CONSTEXPR void end_precision() {\n    if (is_integral(arg_type_) || arg_type_ == pointer_type)\n      this->on_error(\"precision not allowed for this argument type\");\n  }\n\n private:\n  FMT_CONSTEXPR void require_numeric_argument() {\n    if (!is_arithmetic(arg_type_))\n      this->on_error(\"format specifier requires numeric argument\");\n  }\n\n  FMT_CONSTEXPR void check_sign() {\n    require_numeric_argument();\n    if (is_integral(arg_type_) && arg_type_ != int_type &&\n        arg_type_ != long_long_type && arg_type_ != internal::char_type) {\n      this->on_error(\"format specifier requires signed argument\");\n    }\n  }\n\n  internal::type arg_type_;\n};\n\ntemplate <template <typename> class Handler, typename T,\n          typename Context, typename ErrorHandler>\nFMT_CONSTEXPR void set_dynamic_spec(\n    T &value, basic_format_arg<Context> arg, ErrorHandler eh) {\n  unsigned long long big_value =\n      visit_format_arg(Handler<ErrorHandler>(eh), arg);\n  if (big_value > to_unsigned((std::numeric_limits<int>::max)()))\n    eh.on_error(\"number is too big\");\n  value = static_cast<T>(big_value);\n}\n\nstruct auto_id {};\n\n// The standard format specifier handler with checking.\ntemplate <typename Context>\nclass specs_handler: public specs_setter<typename Context::char_type> {\n public:\n  typedef typename Context::char_type char_type;\n\n  FMT_CONSTEXPR specs_handler(\n      basic_format_specs<char_type> &specs, Context &ctx)\n    : specs_setter<char_type>(specs), context_(ctx) {}\n\n  template <typename Id>\n  FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {\n    set_dynamic_spec<width_checker>(\n          this->specs_.width_, get_arg(arg_id), context_.error_handler());\n  }\n\n  template <typename Id>\n  FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {\n    set_dynamic_spec<precision_checker>(\n          this->specs_.precision, get_arg(arg_id), context_.error_handler());\n  }\n\n  void on_error(const char *message) {\n    context_.on_error(message);\n  }\n\n private:\n  FMT_CONSTEXPR basic_format_arg<Context> get_arg(auto_id) {\n    return context_.next_arg();\n  }\n\n  template <typename Id>\n  FMT_CONSTEXPR basic_format_arg<Context> get_arg(Id arg_id) {\n    context_.parse_context().check_arg_id(arg_id);\n    return context_.get_arg(arg_id);\n  }\n\n  Context &context_;\n};\n\n// An argument reference.\ntemplate <typename Char>\nstruct arg_ref {\n  enum Kind { NONE, INDEX, NAME };\n\n  FMT_CONSTEXPR arg_ref() : kind(NONE), index(0) {}\n  FMT_CONSTEXPR explicit arg_ref(unsigned index) : kind(INDEX), index(index) {}\n  explicit arg_ref(basic_string_view<Char> nm) : kind(NAME) {\n    name = {nm.data(), nm.size()};\n  }\n\n  FMT_CONSTEXPR arg_ref &operator=(unsigned idx) {\n    kind = INDEX;\n    index = idx;\n    return *this;\n  }\n\n  Kind kind;\n  union {\n    unsigned index;\n    string_value<Char> name;  // This is not string_view because of gcc 4.4.\n  };\n};\n\n// Format specifiers with width and precision resolved at formatting rather\n// than parsing time to allow re-using the same parsed specifiers with\n// differents sets of arguments (precompilation of format strings).\ntemplate <typename Char>\nstruct dynamic_format_specs : basic_format_specs<Char> {\n  arg_ref<Char> width_ref;\n  arg_ref<Char> precision_ref;\n};\n\n// Format spec handler that saves references to arguments representing dynamic\n// width and precision to be resolved at formatting time.\ntemplate <typename ParseContext>\nclass dynamic_specs_handler :\n    public specs_setter<typename ParseContext::char_type> {\n public:\n  typedef typename ParseContext::char_type char_type;\n\n  FMT_CONSTEXPR dynamic_specs_handler(\n      dynamic_format_specs<char_type> &specs, ParseContext &ctx)\n    : specs_setter<char_type>(specs), specs_(specs), context_(ctx) {}\n\n  FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler &other)\n    : specs_setter<char_type>(other),\n      specs_(other.specs_), context_(other.context_) {}\n\n  template <typename Id>\n  FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {\n    specs_.width_ref = make_arg_ref(arg_id);\n  }\n\n  template <typename Id>\n  FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {\n    specs_.precision_ref = make_arg_ref(arg_id);\n  }\n\n  FMT_CONSTEXPR void on_error(const char *message) {\n    context_.on_error(message);\n  }\n\n private:\n  typedef arg_ref<char_type> arg_ref_type;\n\n  template <typename Id>\n  FMT_CONSTEXPR arg_ref_type make_arg_ref(Id arg_id) {\n    context_.check_arg_id(arg_id);\n    return arg_ref_type(arg_id);\n  }\n\n  FMT_CONSTEXPR arg_ref_type make_arg_ref(auto_id) {\n    return arg_ref_type(context_.next_arg_id());\n  }\n\n  dynamic_format_specs<char_type> &specs_;\n  ParseContext &context_;\n};\n\ntemplate <typename Iterator, typename IDHandler>\nFMT_CONSTEXPR Iterator parse_arg_id(Iterator it, IDHandler &&handler) {\n  typedef typename std::iterator_traits<Iterator>::value_type char_type;\n  char_type c = *it;\n  if (c == '}' || c == ':') {\n    handler();\n    return it;\n  }\n  if (c >= '0' && c <= '9') {\n    unsigned index = parse_nonnegative_int(it, handler);\n    if (*it != '}' && *it != ':') {\n      handler.on_error(\"invalid format string\");\n      return it;\n    }\n    handler(index);\n    return it;\n  }\n  if (!is_name_start(c)) {\n    handler.on_error(\"invalid format string\");\n    return it;\n  }\n  auto start = it;\n  do {\n    c = *++it;\n  } while (is_name_start(c) || ('0' <= c && c <= '9'));\n  handler(basic_string_view<char_type>(\n            pointer_from(start), to_unsigned(it - start)));\n  return it;\n}\n\ntemplate <typename Char, typename IDHandler>\nFMT_CONSTEXPR const Char *parse_arg_id(\n    const Char *begin, const Char *end, IDHandler &&handler) {\n  assert(begin != end);\n  Char c = *begin;\n  if (c == '}' || c == ':')\n    return handler(), begin;\n  if (c >= '0' && c <= '9') {\n    unsigned index = parse_nonnegative_int(begin, end, handler);\n    if (begin == end || (*begin != '}' && *begin != ':'))\n      return handler.on_error(\"invalid format string\"), begin;\n    handler(index);\n    return begin;\n  }\n  if (!is_name_start(c))\n    return handler.on_error(\"invalid format string\"), begin;\n  auto it = begin;\n  do {\n    c = *++it;\n  } while (it != end && (is_name_start(c) || ('0' <= c && c <= '9')));\n  handler(basic_string_view<Char>(begin, to_unsigned(it - begin)));\n  return it;\n}\n\n// Adapts SpecHandler to IDHandler API for dynamic width.\ntemplate <typename SpecHandler, typename Char>\nstruct width_adapter {\n  explicit FMT_CONSTEXPR width_adapter(SpecHandler &h) : handler(h) {}\n\n  FMT_CONSTEXPR void operator()() { handler.on_dynamic_width(auto_id()); }\n  FMT_CONSTEXPR void operator()(unsigned id) { handler.on_dynamic_width(id); }\n  FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {\n    handler.on_dynamic_width(id);\n  }\n\n  FMT_CONSTEXPR void on_error(const char *message) {\n    handler.on_error(message);\n  }\n\n  SpecHandler &handler;\n};\n\n// Adapts SpecHandler to IDHandler API for dynamic precision.\ntemplate <typename SpecHandler, typename Char>\nstruct precision_adapter {\n  explicit FMT_CONSTEXPR precision_adapter(SpecHandler &h) : handler(h) {}\n\n  FMT_CONSTEXPR void operator()() { handler.on_dynamic_precision(auto_id()); }\n  FMT_CONSTEXPR void operator()(unsigned id) {\n    handler.on_dynamic_precision(id);\n  }\n  FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {\n    handler.on_dynamic_precision(id);\n  }\n\n  FMT_CONSTEXPR void on_error(const char *message) { handler.on_error(message); }\n\n  SpecHandler &handler;\n};\n\n// Parses standard format specifiers and sends notifications about parsed\n// components to handler.\n// it: an iterator pointing to the beginning of a null-terminated range of\n//     characters, possibly emulated via null_terminating_iterator, representing\n//     format specifiers.\ntemplate <typename Iterator, typename SpecHandler>\nFMT_CONSTEXPR Iterator parse_format_specs(Iterator it, SpecHandler &&handler) {\n  typedef typename std::iterator_traits<Iterator>::value_type char_type;\n  char_type c = *it;\n  if (c == '}' || !c)\n    return it;\n\n  // Parse fill and alignment.\n  alignment align = ALIGN_DEFAULT;\n  int i = 1;\n  do {\n    auto p = it + i;\n    switch (static_cast<char>(*p)) {\n    case '<':\n      align = ALIGN_LEFT;\n      break;\n    case '>':\n      align = ALIGN_RIGHT;\n      break;\n    case '=':\n      align = ALIGN_NUMERIC;\n      break;\n    case '^':\n      align = ALIGN_CENTER;\n      break;\n    }\n    if (align != ALIGN_DEFAULT) {\n      if (p != it) {\n        if (c == '{') {\n          handler.on_error(\"invalid fill character '{'\");\n          return it;\n        }\n        it += 2;\n        handler.on_fill(c);\n      } else ++it;\n      handler.on_align(align);\n      break;\n    }\n  } while (--i >= 0);\n\n  // Parse sign.\n  switch (static_cast<char>(*it)) {\n  case '+':\n    handler.on_plus();\n    ++it;\n    break;\n  case '-':\n    handler.on_minus();\n    ++it;\n    break;\n  case ' ':\n    handler.on_space();\n    ++it;\n    break;\n  }\n\n  if (*it == '#') {\n    handler.on_hash();\n    ++it;\n  }\n\n  // Parse zero flag.\n  if (*it == '0') {\n    handler.on_zero();\n    ++it;\n  }\n\n  // Parse width.\n  if ('0' <= *it && *it <= '9') {\n    handler.on_width(parse_nonnegative_int(it, handler));\n  } else if (*it == '{') {\n    it = parse_arg_id(it + 1, width_adapter<SpecHandler, char_type>(handler));\n    if (*it++ != '}') {\n      handler.on_error(\"invalid format string\");\n      return it;\n    }\n  }\n\n  // Parse precision.\n  if (*it == '.') {\n    ++it;\n    if ('0' <= *it && *it <= '9') {\n      handler.on_precision(parse_nonnegative_int(it, handler));\n    } else if (*it == '{') {\n      it = parse_arg_id(\n            it + 1, precision_adapter<SpecHandler, char_type>(handler));\n      if (*it++ != '}') {\n        handler.on_error(\"invalid format string\");\n        return it;\n      }\n    } else {\n      handler.on_error(\"missing precision specifier\");\n      return it;\n    }\n    handler.end_precision();\n  }\n\n  // Parse type.\n  if (*it != '}' && *it)\n    handler.on_type(*it++);\n  return it;\n}\n\n// Return the result via the out param to workaround gcc bug 77539.\ntemplate <bool IS_CONSTEXPR, typename T, typename Ptr = const T*>\nFMT_CONSTEXPR bool find(Ptr first, Ptr last, T value, Ptr &out) {\n  for (out = first; out != last; ++out) {\n    if (*out == value)\n      return true;\n  }\n  return false;\n}\n\ntemplate <>\ninline bool find<false, char>(\n    const char *first, const char *last, char value, const char *&out) {\n  out = static_cast<const char*>(std::memchr(first, value, last - first));\n  return out != FMT_NULL;\n}\n\ntemplate <typename Handler, typename Char>\nstruct id_adapter {\n  FMT_CONSTEXPR void operator()() { handler.on_arg_id(); }\n  FMT_CONSTEXPR void operator()(unsigned id) { handler.on_arg_id(id); }\n  FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {\n    handler.on_arg_id(id);\n  }\n  FMT_CONSTEXPR void on_error(const char *message) {\n    handler.on_error(message);\n  }\n  Handler &handler;\n};\n\ntemplate <bool IS_CONSTEXPR, typename Char, typename Handler>\nFMT_CONSTEXPR void parse_format_string(\n        basic_string_view<Char> format_str, Handler &&handler) {\n  struct writer {\n    FMT_CONSTEXPR void operator()(const Char *begin, const Char *end) {\n      if (begin == end) return;\n      for (;;) {\n        const Char *p = FMT_NULL;\n        if (!find<IS_CONSTEXPR>(begin, end, '}', p))\n          return handler_.on_text(begin, end);\n        ++p;\n        if (p == end || *p != '}')\n          return handler_.on_error(\"unmatched '}' in format string\");\n        handler_.on_text(begin, p);\n        begin = p + 1;\n      }\n    }\n    Handler &handler_;\n  } write{handler};\n  auto begin = format_str.data();\n  auto end = begin + format_str.size();\n  while (begin != end) {\n    // Doing two passes with memchr (one for '{' and another for '}') is up to\n    // 2.5x faster than the naive one-pass implementation on big format strings.\n    const Char *p = begin;\n    if (*begin != '{' && !find<IS_CONSTEXPR>(begin, end, '{', p))\n      return write(begin, end);\n    write(begin, p);\n    ++p;\n    if (p == end)\n      return handler.on_error(\"invalid format string\");\n    if (static_cast<char>(*p) == '}') {\n      handler.on_arg_id();\n      handler.on_replacement_field(p);\n    } else if (*p == '{') {\n      handler.on_text(p, p + 1);\n    } else {\n      p = parse_arg_id(p, end, id_adapter<Handler, Char>{handler});\n      Char c = p != end ? *p : Char();\n      if (c == '}') {\n        handler.on_replacement_field(p);\n      } else if (c == ':') {\n        internal::null_terminating_iterator<Char> it(p + 1, end);\n        it = handler.on_format_specs(it);\n        if (*it != '}')\n          return handler.on_error(\"unknown format specifier\");\n        p = pointer_from(it);\n      } else {\n        return handler.on_error(\"missing '}' in format string\");\n      }\n    }\n    begin = p + 1;\n  }\n}\n\ntemplate <typename T, typename ParseContext>\nFMT_CONSTEXPR const typename ParseContext::char_type *\n    parse_format_specs(ParseContext &ctx) {\n  // GCC 7.2 requires initializer.\n  formatter<T, typename ParseContext::char_type> f{};\n  return f.parse(ctx);\n}\n\ntemplate <typename Char, typename ErrorHandler, typename... Args>\nclass format_string_checker {\n public:\n  explicit FMT_CONSTEXPR format_string_checker(\n      basic_string_view<Char> format_str, ErrorHandler eh)\n    : arg_id_(-1), context_(format_str, eh),\n      parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}\n\n  typedef internal::null_terminating_iterator<Char> iterator;\n\n  FMT_CONSTEXPR void on_text(const Char *, const Char *) {}\n\n  FMT_CONSTEXPR void on_arg_id() {\n    arg_id_ = context_.next_arg_id();\n    check_arg_id();\n  }\n  FMT_CONSTEXPR void on_arg_id(unsigned id) {\n    arg_id_ = id;\n    context_.check_arg_id(id);\n    check_arg_id();\n  }\n  FMT_CONSTEXPR void on_arg_id(basic_string_view<Char>) {}\n\n  FMT_CONSTEXPR void on_replacement_field(const Char *) {}\n\n  FMT_CONSTEXPR const Char *on_format_specs(iterator it) {\n    auto p = pointer_from(it);\n    context_.advance_to(p);\n    return to_unsigned(arg_id_) < NUM_ARGS ?\n          parse_funcs_[arg_id_](context_) : p;\n  }\n\n  FMT_CONSTEXPR void on_error(const char *message) {\n    context_.on_error(message);\n  }\n\n private:\n  typedef basic_parse_context<Char, ErrorHandler> parse_context_type;\n  enum { NUM_ARGS = sizeof...(Args) };\n\n  FMT_CONSTEXPR void check_arg_id() {\n    if (internal::to_unsigned(arg_id_) >= NUM_ARGS)\n      context_.on_error(\"argument index out of range\");\n  }\n\n  // Format specifier parsing function.\n  typedef const Char *(*parse_func)(parse_context_type &);\n\n  int arg_id_;\n  parse_context_type context_;\n  parse_func parse_funcs_[NUM_ARGS > 0 ? NUM_ARGS : 1];\n};\n\ntemplate <typename Char, typename ErrorHandler, typename... Args>\nFMT_CONSTEXPR bool do_check_format_string(\n    basic_string_view<Char> s, ErrorHandler eh = ErrorHandler()) {\n  format_string_checker<Char, ErrorHandler, Args...> checker(s, eh);\n  parse_format_string<true>(s, checker);\n  return true;\n}\n\ntemplate <typename... Args, typename S>\ntypename std::enable_if<is_compile_string<S>::value>::type\n    check_format_string(S format_str) {\n  typedef typename S::char_type char_t;\n  FMT_CONSTEXPR_DECL bool invalid_format = internal::do_check_format_string<\n      char_t, internal::error_handler, Args...>(to_string_view(format_str));\n  (void)invalid_format;\n}\n\n// Specifies whether to format T using the standard formatter.\n// It is not possible to use get_type in formatter specialization directly\n// because of a bug in MSVC.\ntemplate <typename Context, typename T>\nstruct format_type :\n  std::integral_constant<bool, get_type<Context, T>::value != custom_type> {};\n\ntemplate <template <typename> class Handler, typename Spec, typename Context>\nvoid handle_dynamic_spec(\n    Spec &value, arg_ref<typename Context::char_type> ref, Context &ctx) {\n  typedef typename Context::char_type char_type;\n  switch (ref.kind) {\n  case arg_ref<char_type>::NONE:\n    break;\n  case arg_ref<char_type>::INDEX:\n    internal::set_dynamic_spec<Handler>(\n          value, ctx.get_arg(ref.index), ctx.error_handler());\n    break;\n  case arg_ref<char_type>::NAME:\n    internal::set_dynamic_spec<Handler>(\n          value, ctx.get_arg({ref.name.value, ref.name.size}),\n          ctx.error_handler());\n    break;\n  }\n}\n}  // namespace internal\n\n/** The default argument formatter. */\ntemplate <typename Range>\nclass arg_formatter:\n  public internal::function<\n    typename internal::arg_formatter_base<Range>::iterator>,\n  public internal::arg_formatter_base<Range> {\n private:\n  typedef typename Range::value_type char_type;\n  typedef internal::arg_formatter_base<Range> base;\n  typedef basic_format_context<typename base::iterator, char_type> context_type;\n\n  context_type &ctx_;\n\n public:\n  typedef Range range;\n  typedef typename base::iterator iterator;\n  typedef typename base::format_specs format_specs;\n\n  /**\n    \\rst\n    Constructs an argument formatter object.\n    *ctx* is a reference to the formatting context,\n    *spec* contains format specifier information for standard argument types.\n    \\endrst\n   */\n  explicit arg_formatter(context_type &ctx, format_specs *spec = FMT_NULL)\n  : base(Range(ctx.out()), spec, ctx.locale()), ctx_(ctx) {}\n\n  // Deprecated.\n  arg_formatter(context_type &ctx, format_specs &spec)\n  : base(Range(ctx.out()), &spec), ctx_(ctx) {}\n\n  using base::operator();\n\n  /** Formats an argument of a user-defined type. */\n  iterator operator()(typename basic_format_arg<context_type>::handle handle) {\n    handle.format(ctx_);\n    return this->out();\n  }\n};\n\n/**\n An error returned by an operating system or a language runtime,\n for example a file opening error.\n*/\nclass system_error : public std::runtime_error {\n private:\n  FMT_API void init(int err_code, string_view format_str, format_args args);\n\n protected:\n  int error_code_;\n\n  system_error() : std::runtime_error(\"\") {}\n\n public:\n  /**\n   \\rst\n   Constructs a :class:`fmt::system_error` object with a description\n   formatted with `fmt::format_system_error`. *message* and additional\n   arguments passed into the constructor are formatted similarly to\n   `fmt::format`.\n\n   **Example**::\n\n     // This throws a system_error with the description\n     //   cannot open file 'madeup': No such file or directory\n     // or similar (system message may vary).\n     const char *filename = \"madeup\";\n     std::FILE *file = std::fopen(filename, \"r\");\n     if (!file)\n       throw fmt::system_error(errno, \"cannot open file '{}'\", filename);\n   \\endrst\n  */\n  template <typename... Args>\n  system_error(int error_code, string_view message, const Args &... args)\n    : std::runtime_error(\"\") {\n    init(error_code, message, make_format_args(args...));\n  }\n\n  int error_code() const { return error_code_; }\n};\n\n/**\n  \\rst\n  Formats an error returned by an operating system or a language runtime,\n  for example a file opening error, and writes it to *out* in the following\n  form:\n\n  .. parsed-literal::\n     *<message>*: *<system-message>*\n\n  where *<message>* is the passed message and *<system-message>* is\n  the system message corresponding to the error code.\n  *error_code* is a system error code as given by ``errno``.\n  If *error_code* is not a valid error code such as -1, the system message\n  may look like \"Unknown error -1\" and is platform-dependent.\n  \\endrst\n */\nFMT_API void format_system_error(internal::buffer &out, int error_code,\n                                 fmt::string_view message) FMT_NOEXCEPT;\n\n/**\n  This template provides operations for formatting and writing data into a\n  character range.\n */\ntemplate <typename Range>\nclass basic_writer {\n public:\n  typedef typename Range::value_type char_type;\n  typedef decltype(internal::declval<Range>().begin()) iterator;\n  typedef basic_format_specs<char_type> format_specs;\n\n private:\n  iterator out_;  // Output iterator.\n  internal::locale_ref locale_;\n\n  iterator out() const { return out_; }\n\n  // Attempts to reserve space for n extra characters in the output range.\n  // Returns a pointer to the reserved range or a reference to out_.\n  auto reserve(std::size_t n) -> decltype(internal::reserve(out_, n)) {\n    return internal::reserve(out_, n);\n  }\n\n  // Writes a value in the format\n  //   <left-padding><value><right-padding>\n  // where <value> is written by f(it).\n  template <typename F>\n  void write_padded(const align_spec &spec, F &&f);\n\n  template <typename F>\n  struct padded_int_writer {\n    size_t size_;\n    string_view prefix;\n    char_type fill;\n    std::size_t padding;\n    F f;\n\n    size_t size() const { return size_; }\n    size_t width() const { return size_; }\n\n    template <typename It>\n    void operator()(It &&it) const {\n      if (prefix.size() != 0)\n        it = internal::copy_str<char_type>(prefix.begin(), prefix.end(), it);\n      it = std::fill_n(it, padding, fill);\n      f(it);\n    }\n  };\n\n  // Writes an integer in the format\n  //   <left-padding><prefix><numeric-padding><digits><right-padding>\n  // where <digits> are written by f(it).\n  template <typename Spec, typename F>\n  void write_int(unsigned num_digits, string_view prefix,\n                 const Spec &spec, F f) {\n    std::size_t size = prefix.size() + num_digits;\n    char_type fill = static_cast<char_type>(spec.fill());\n    std::size_t padding = 0;\n    if (spec.align() == ALIGN_NUMERIC) {\n      if (spec.width() > size) {\n        padding = spec.width() - size;\n        size = spec.width();\n      }\n    } else if (spec.precision > static_cast<int>(num_digits)) {\n      size = prefix.size() + internal::to_unsigned(spec.precision);\n      padding = internal::to_unsigned(spec.precision) - num_digits;\n      fill = static_cast<char_type>('0');\n    }\n    align_spec as = spec;\n    if (spec.align() == ALIGN_DEFAULT)\n      as.align_ = ALIGN_RIGHT;\n    write_padded(as, padded_int_writer<F>{size, prefix, fill, padding, f});\n  }\n\n  // Writes a decimal integer.\n  template <typename Int>\n  void write_decimal(Int value) {\n    typedef typename internal::int_traits<Int>::main_type main_type;\n    main_type abs_value = static_cast<main_type>(value);\n    bool is_negative = internal::is_negative(value);\n    if (is_negative)\n      abs_value = 0 - abs_value;\n    unsigned num_digits = internal::count_digits(abs_value);\n    auto &&it = reserve((is_negative ? 1 : 0) + num_digits);\n    if (is_negative)\n      *it++ = static_cast<char_type>('-');\n    it = internal::format_decimal<char_type>(it, abs_value, num_digits);\n  }\n\n  // The handle_int_type_spec handler that writes an integer.\n  template <typename Int, typename Spec>\n  struct int_writer {\n    typedef typename internal::int_traits<Int>::main_type unsigned_type;\n\n    basic_writer<Range> &writer;\n    const Spec &spec;\n    unsigned_type abs_value;\n    char prefix[4];\n    unsigned prefix_size;\n\n    string_view get_prefix() const { return string_view(prefix, prefix_size); }\n\n    // Counts the number of digits in abs_value. BITS = log2(radix).\n    template <unsigned BITS>\n    unsigned count_digits() const {\n      unsigned_type n = abs_value;\n      unsigned num_digits = 0;\n      do {\n        ++num_digits;\n      } while ((n >>= BITS) != 0);\n      return num_digits;\n    }\n\n    int_writer(basic_writer<Range> &w, Int value, const Spec &s)\n      : writer(w), spec(s), abs_value(static_cast<unsigned_type>(value)),\n        prefix_size(0) {\n      if (internal::is_negative(value)) {\n        prefix[0] = '-';\n        ++prefix_size;\n        abs_value = 0 - abs_value;\n      } else if (spec.has(SIGN_FLAG)) {\n        prefix[0] = spec.has(PLUS_FLAG) ? '+' : ' ';\n        ++prefix_size;\n      }\n    }\n\n    struct dec_writer {\n      unsigned_type abs_value;\n      unsigned num_digits;\n\n      template <typename It>\n      void operator()(It &&it) const {\n        it = internal::format_decimal<char_type>(it, abs_value, num_digits);\n      }\n    };\n\n    void on_dec() {\n      unsigned num_digits = internal::count_digits(abs_value);\n      writer.write_int(num_digits, get_prefix(), spec,\n                       dec_writer{abs_value, num_digits});\n    }\n\n    struct hex_writer {\n      int_writer &self;\n      unsigned num_digits;\n\n      template <typename It>\n      void operator()(It &&it) const {\n        it = internal::format_uint<4, char_type>(\n              it, self.abs_value, num_digits, self.spec.type != 'x');\n      }\n    };\n\n    void on_hex() {\n      if (spec.has(HASH_FLAG)) {\n        prefix[prefix_size++] = '0';\n        prefix[prefix_size++] = static_cast<char>(spec.type);\n      }\n      unsigned num_digits = count_digits<4>();\n      writer.write_int(num_digits, get_prefix(), spec,\n                       hex_writer{*this, num_digits});\n    }\n\n    template <int BITS>\n    struct bin_writer {\n      unsigned_type abs_value;\n      unsigned num_digits;\n\n      template <typename It>\n      void operator()(It &&it) const {\n        it = internal::format_uint<BITS, char_type>(it, abs_value, num_digits);\n      }\n    };\n\n    void on_bin() {\n      if (spec.has(HASH_FLAG)) {\n        prefix[prefix_size++] = '0';\n        prefix[prefix_size++] = static_cast<char>(spec.type);\n      }\n      unsigned num_digits = count_digits<1>();\n      writer.write_int(num_digits, get_prefix(), spec,\n                       bin_writer<1>{abs_value, num_digits});\n    }\n\n    void on_oct() {\n      unsigned num_digits = count_digits<3>();\n      if (spec.has(HASH_FLAG) &&\n          spec.precision <= static_cast<int>(num_digits)) {\n        // Octal prefix '0' is counted as a digit, so only add it if precision\n        // is not greater than the number of digits.\n        prefix[prefix_size++] = '0';\n      }\n      writer.write_int(num_digits, get_prefix(), spec,\n                       bin_writer<3>{abs_value, num_digits});\n    }\n\n    enum { SEP_SIZE = 1 };\n\n    struct num_writer {\n      unsigned_type abs_value;\n      unsigned size;\n      char_type sep;\n\n      template <typename It>\n      void operator()(It &&it) const {\n        basic_string_view<char_type> s(&sep, SEP_SIZE);\n        it = internal::format_decimal<char_type>(\n              it, abs_value, size, internal::add_thousands_sep<char_type>(s));\n      }\n    };\n\n    void on_num() {\n      unsigned num_digits = internal::count_digits(abs_value);\n      char_type sep = internal::thousands_sep<char_type>(writer.locale_);\n      unsigned size = num_digits + SEP_SIZE * ((num_digits - 1) / 3);\n      writer.write_int(size, get_prefix(), spec,\n                       num_writer{abs_value, size, sep});\n    }\n\n    void on_error() {\n      FMT_THROW(format_error(\"invalid type specifier\"));\n    }\n  };\n\n  // Writes a formatted integer.\n  template <typename T, typename Spec>\n  void write_int(T value, const Spec &spec) {\n    internal::handle_int_type_spec(spec.type,\n                                   int_writer<T, Spec>(*this, value, spec));\n  }\n\n  enum {INF_SIZE = 3}; // This is an enum to workaround a bug in MSVC.\n\n  struct inf_or_nan_writer {\n    char sign;\n    const char *str;\n\n    size_t size() const {\n      return static_cast<std::size_t>(INF_SIZE + (sign ? 1 : 0));\n    }\n    size_t width() const { return size(); }\n\n    template <typename It>\n    void operator()(It &&it) const {\n      if (sign)\n        *it++ = static_cast<char_type>(sign);\n      it = internal::copy_str<char_type>(\n            str, str + static_cast<std::size_t>(INF_SIZE), it);\n    }\n  };\n\n  struct double_writer {\n    size_t n;\n    char sign;\n    internal::buffer &buffer;\n\n    size_t size() const { return buffer.size() + (sign ? 1 : 0); }\n    size_t width() const { return size(); }\n\n    template <typename It>\n    void operator()(It &&it) {\n      if (sign) {\n        *it++ = static_cast<char_type>(sign);\n        --n;\n      }\n      it = internal::copy_str<char_type>(buffer.begin(), buffer.end(), it);\n    }\n  };\n\n  // Formats a floating-point number (double or long double).\n  template <typename T>\n  void write_double(T value, const format_specs &spec);\n\n  template <typename Char>\n  struct str_writer {\n    const Char *s;\n    size_t size_;\n\n    size_t size() const { return size_; }\n    size_t width() const {\n      return internal::count_code_points(basic_string_view<Char>(s, size_));\n    }\n\n    template <typename It>\n    void operator()(It &&it) const {\n      it = internal::copy_str<char_type>(s, s + size_, it);\n    }\n  };\n\n  // Writes a formatted string.\n  template <typename Char>\n  void write_str(const Char *s, std::size_t size, const align_spec &spec) {\n    write_padded(spec, str_writer<Char>{s, size});\n  }\n\n  template <typename Char>\n  void write_str(basic_string_view<Char> str, const format_specs &spec);\n\n  template <typename Char>\n  friend class internal::arg_formatter_base;\n\n public:\n  /** Constructs a ``basic_writer`` object. */\n  explicit basic_writer(\n      Range out, internal::locale_ref loc = internal::locale_ref())\n    : out_(out.begin()), locale_(loc) {}\n\n  void write(int value) { write_decimal(value); }\n  void write(long value) { write_decimal(value); }\n  void write(long long value) { write_decimal(value); }\n\n  void write(unsigned value) { write_decimal(value); }\n  void write(unsigned long value) { write_decimal(value); }\n  void write(unsigned long long value) { write_decimal(value); }\n\n  /**\n    \\rst\n    Formats *value* and writes it to the buffer.\n    \\endrst\n   */\n  template <typename T, typename FormatSpec, typename... FormatSpecs>\n  typename std::enable_if<std::is_integral<T>::value, void>::type\n      write(T value, FormatSpec spec, FormatSpecs... specs) {\n    format_specs s(spec, specs...);\n    s.align_ = ALIGN_RIGHT;\n    write_int(value, s);\n  }\n\n  void write(double value) {\n    write_double(value, format_specs());\n  }\n\n  /**\n    \\rst\n    Formats *value* using the general format for floating-point numbers\n    (``'g'``) and writes it to the buffer.\n    \\endrst\n   */\n  void write(long double value) {\n    write_double(value, format_specs());\n  }\n\n  /** Writes a character to the buffer. */\n  void write(char value) {\n    *reserve(1) = value;\n  }\n  void write(wchar_t value) {\n    static_assert(std::is_same<char_type, wchar_t>::value, \"\");\n    *reserve(1) = value;\n  }\n\n  /**\n    \\rst\n    Writes *value* to the buffer.\n    \\endrst\n   */\n  void write(string_view value) {\n    auto &&it = reserve(value.size());\n    it = internal::copy_str<char_type>(value.begin(), value.end(), it);\n  }\n  void write(wstring_view value) {\n    static_assert(std::is_same<char_type, wchar_t>::value, \"\");\n    auto &&it = reserve(value.size());\n    it = std::copy(value.begin(), value.end(), it);\n  }\n\n  template <typename... FormatSpecs>\n  void write(basic_string_view<char_type> str, FormatSpecs... specs) {\n    write_str(str, format_specs(specs...));\n  }\n\n  template <typename T>\n  typename std::enable_if<std::is_same<T, void>::value>::type\n      write(const T *p) {\n    format_specs specs;\n    specs.flags = HASH_FLAG;\n    specs.type = 'x';\n    write_int(reinterpret_cast<uintptr_t>(p), specs);\n  }\n};\n\ntemplate <typename Range>\ntemplate <typename F>\nvoid basic_writer<Range>::write_padded(const align_spec &spec, F &&f) {\n  unsigned width = spec.width(); // User-perceived width (in code points).\n  size_t size = f.size(); // The number of code units.\n  size_t num_code_points = width != 0 ? f.width() : size;\n  if (width <= num_code_points)\n    return f(reserve(size));\n  auto &&it = reserve(width + (size - num_code_points));\n  char_type fill = static_cast<char_type>(spec.fill());\n  std::size_t padding = width - num_code_points;\n  if (spec.align() == ALIGN_RIGHT) {\n    it = std::fill_n(it, padding, fill);\n    f(it);\n  } else if (spec.align() == ALIGN_CENTER) {\n    std::size_t left_padding = padding / 2;\n    it = std::fill_n(it, left_padding, fill);\n    f(it);\n    it = std::fill_n(it, padding - left_padding, fill);\n  } else {\n    f(it);\n    it = std::fill_n(it, padding, fill);\n  }\n}\n\ntemplate <typename Range>\ntemplate <typename Char>\nvoid basic_writer<Range>::write_str(\n    basic_string_view<Char> s, const format_specs &spec) {\n  const Char *data = s.data();\n  std::size_t size = s.size();\n  if (spec.precision >= 0 && internal::to_unsigned(spec.precision) < size)\n    size = internal::to_unsigned(spec.precision);\n  write_str(data, size, spec);\n}\n\nstruct float_spec_handler {\n  char type;\n  bool upper;\n\n  explicit float_spec_handler(char t) : type(t), upper(false) {}\n\n  void on_general() {\n    if (type == 'G')\n      upper = true;\n    else\n      type = 'g';\n  }\n\n  void on_exp() {\n    if (type == 'E')\n      upper = true;\n  }\n\n  void on_fixed() {\n    if (type == 'F') {\n      upper = true;\n#if FMT_MSC_VER\n      // MSVC's printf doesn't support 'F'.\n      type = 'f';\n#endif\n    }\n  }\n\n  void on_hex() {\n    if (type == 'A')\n      upper = true;\n  }\n\n  void on_error() {\n    FMT_THROW(format_error(\"invalid type specifier\"));\n  }\n};\n\ntemplate <typename Range>\ntemplate <typename T>\nvoid basic_writer<Range>::write_double(T value, const format_specs &spec) {\n  // Check type.\n  float_spec_handler handler(static_cast<char>(spec.type));\n  internal::handle_float_type_spec(handler.type, handler);\n\n  char sign = 0;\n  // Use signbit instead of value < 0 because the latter is always\n  // false for NaN.\n  if (std::signbit(value)) {\n    sign = '-';\n    value = -value;\n  } else if (spec.has(SIGN_FLAG)) {\n    sign = spec.has(PLUS_FLAG) ? '+' : ' ';\n  }\n\n  struct write_inf_or_nan_t {\n    basic_writer &writer;\n    format_specs spec;\n    char sign;\n    void operator()(const char *str) const {\n      writer.write_padded(spec, inf_or_nan_writer{sign, str});\n    }\n  } write_inf_or_nan = {*this, spec, sign};\n\n  // Format NaN and ininity ourselves because sprintf's output is not consistent\n  // across platforms.\n  if (internal::fputil::isnotanumber(value))\n    return write_inf_or_nan(handler.upper ? \"NAN\" : \"nan\");\n  if (internal::fputil::isinfinity(value))\n    return write_inf_or_nan(handler.upper ? \"INF\" : \"inf\");\n\n  memory_buffer buffer;\n  bool use_grisu = FMT_USE_GRISU && sizeof(T) <= sizeof(double) &&\n      spec.type != 'a' && spec.type != 'A' &&\n      internal::grisu2_format(static_cast<double>(value), buffer, spec);\n  if (!use_grisu) {\n    format_specs normalized_spec(spec);\n    normalized_spec.type = handler.type;\n    internal::sprintf_format(value, buffer, normalized_spec);\n  }\n  size_t n = buffer.size();\n  align_spec as = spec;\n  if (spec.align() == ALIGN_NUMERIC) {\n    if (sign) {\n      auto &&it = reserve(1);\n      *it++ = static_cast<char_type>(sign);\n      sign = 0;\n      if (as.width_)\n        --as.width_;\n    }\n    as.align_ = ALIGN_RIGHT;\n  } else {\n    if (spec.align() == ALIGN_DEFAULT)\n      as.align_ = ALIGN_RIGHT;\n    if (sign)\n      ++n;\n  }\n  write_padded(as, double_writer{n, sign, buffer});\n}\n\n// Reports a system error without throwing an exception.\n// Can be used to report errors from destructors.\nFMT_API void report_system_error(int error_code,\n                                 string_view message) FMT_NOEXCEPT;\n\n#if FMT_USE_WINDOWS_H\n\n/** A Windows error. */\nclass windows_error : public system_error {\n private:\n  FMT_API void init(int error_code, string_view format_str, format_args args);\n\n public:\n  /**\n   \\rst\n   Constructs a :class:`fmt::windows_error` object with the description\n   of the form\n\n   .. parsed-literal::\n     *<message>*: *<system-message>*\n\n   where *<message>* is the formatted message and *<system-message>* is the\n   system message corresponding to the error code.\n   *error_code* is a Windows error code as given by ``GetLastError``.\n   If *error_code* is not a valid error code such as -1, the system message\n   will look like \"error -1\".\n\n   **Example**::\n\n     // This throws a windows_error with the description\n     //   cannot open file 'madeup': The system cannot find the file specified.\n     // or similar (system message may vary).\n     const char *filename = \"madeup\";\n     LPOFSTRUCT of = LPOFSTRUCT();\n     HFILE file = OpenFile(filename, &of, OF_READ);\n     if (file == HFILE_ERROR) {\n       throw fmt::windows_error(GetLastError(),\n                                \"cannot open file '{}'\", filename);\n     }\n   \\endrst\n  */\n  template <typename... Args>\n  windows_error(int error_code, string_view message, const Args &... args) {\n    init(error_code, message, make_format_args(args...));\n  }\n};\n\n// Reports a Windows error without throwing an exception.\n// Can be used to report errors from destructors.\nFMT_API void report_windows_error(int error_code,\n                                  string_view message) FMT_NOEXCEPT;\n\n#endif\n\n/** Fast integer formatter. */\nclass format_int {\n private:\n  // Buffer should be large enough to hold all digits (digits10 + 1),\n  // a sign and a null character.\n  enum {BUFFER_SIZE = std::numeric_limits<unsigned long long>::digits10 + 3};\n  mutable char buffer_[BUFFER_SIZE];\n  char *str_;\n\n  // Formats value in reverse and returns a pointer to the beginning.\n  char *format_decimal(unsigned long long value) {\n    char *ptr = buffer_ + BUFFER_SIZE - 1;\n    while (value >= 100) {\n      // Integer division is slow so do it for a group of two digits instead\n      // of for every digit. The idea comes from the talk by Alexandrescu\n      // \"Three Optimization Tips for C++\". See speed-test for a comparison.\n      unsigned index = static_cast<unsigned>((value % 100) * 2);\n      value /= 100;\n      *--ptr = internal::data::DIGITS[index + 1];\n      *--ptr = internal::data::DIGITS[index];\n    }\n    if (value < 10) {\n      *--ptr = static_cast<char>('0' + value);\n      return ptr;\n    }\n    unsigned index = static_cast<unsigned>(value * 2);\n    *--ptr = internal::data::DIGITS[index + 1];\n    *--ptr = internal::data::DIGITS[index];\n    return ptr;\n  }\n\n  void format_signed(long long value) {\n    unsigned long long abs_value = static_cast<unsigned long long>(value);\n    bool negative = value < 0;\n    if (negative)\n      abs_value = 0 - abs_value;\n    str_ = format_decimal(abs_value);\n    if (negative)\n      *--str_ = '-';\n  }\n\n public:\n  explicit format_int(int value) { format_signed(value); }\n  explicit format_int(long value) { format_signed(value); }\n  explicit format_int(long long value) { format_signed(value); }\n  explicit format_int(unsigned value) : str_(format_decimal(value)) {}\n  explicit format_int(unsigned long value) : str_(format_decimal(value)) {}\n  explicit format_int(unsigned long long value) : str_(format_decimal(value)) {}\n\n  /** Returns the number of characters written to the output buffer. */\n  std::size_t size() const {\n    return internal::to_unsigned(buffer_ - str_ + BUFFER_SIZE - 1);\n  }\n\n  /**\n    Returns a pointer to the output buffer content. No terminating null\n    character is appended.\n   */\n  const char *data() const { return str_; }\n\n  /**\n    Returns a pointer to the output buffer content with terminating null\n    character appended.\n   */\n  const char *c_str() const {\n    buffer_[BUFFER_SIZE - 1] = '\\0';\n    return str_;\n  }\n\n  /**\n    \\rst\n    Returns the content of the output buffer as an ``std::string``.\n    \\endrst\n   */\n  std::string str() const { return std::string(str_, size()); }\n};\n\n// Formats a decimal integer value writing into buffer and returns\n// a pointer to the end of the formatted string. This function doesn't\n// write a terminating null character.\ntemplate <typename T>\ninline void format_decimal(char *&buffer, T value) {\n  typedef typename internal::int_traits<T>::main_type main_type;\n  main_type abs_value = static_cast<main_type>(value);\n  if (internal::is_negative(value)) {\n    *buffer++ = '-';\n    abs_value = 0 - abs_value;\n  }\n  if (abs_value < 100) {\n    if (abs_value < 10) {\n      *buffer++ = static_cast<char>('0' + abs_value);\n      return;\n    }\n    unsigned index = static_cast<unsigned>(abs_value * 2);\n    *buffer++ = internal::data::DIGITS[index];\n    *buffer++ = internal::data::DIGITS[index + 1];\n    return;\n  }\n  unsigned num_digits = internal::count_digits(abs_value);\n  internal::format_decimal<char>(buffer, abs_value, num_digits);\n  buffer += num_digits;\n}\n\n// Formatter of objects of type T.\ntemplate <typename T, typename Char>\nstruct formatter<\n    T, Char,\n    typename std::enable_if<internal::format_type<\n        typename buffer_context<Char>::type, T>::value>::type> {\n\n  // Parses format specifiers stopping either at the end of the range or at the\n  // terminating '}'.\n  template <typename ParseContext>\n  FMT_CONSTEXPR typename ParseContext::iterator parse(ParseContext &ctx) {\n    auto it = internal::null_terminating_iterator<Char>(ctx);\n    typedef internal::dynamic_specs_handler<ParseContext> handler_type;\n    auto type = internal::get_type<\n      typename buffer_context<Char>::type, T>::value;\n    internal::specs_checker<handler_type>\n        handler(handler_type(specs_, ctx), type);\n    it = parse_format_specs(it, handler);\n    auto type_spec = specs_.type;\n    auto eh = ctx.error_handler();\n    switch (type) {\n    case internal::none_type:\n    case internal::named_arg_type:\n      FMT_ASSERT(false, \"invalid argument type\");\n      break;\n    case internal::int_type:\n    case internal::uint_type:\n    case internal::long_long_type:\n    case internal::ulong_long_type:\n    case internal::bool_type:\n      handle_int_type_spec(\n            type_spec, internal::int_type_checker<decltype(eh)>(eh));\n      break;\n    case internal::char_type:\n      handle_char_specs(\n          &specs_,\n          internal::char_specs_checker<decltype(eh)>(type_spec, eh));\n      break;\n    case internal::double_type:\n    case internal::long_double_type:\n      handle_float_type_spec(\n            type_spec, internal::float_type_checker<decltype(eh)>(eh));\n      break;\n    case internal::cstring_type:\n      internal::handle_cstring_type_spec(\n            type_spec, internal::cstring_type_checker<decltype(eh)>(eh));\n      break;\n    case internal::string_type:\n      internal::check_string_type_spec(type_spec, eh);\n      break;\n    case internal::pointer_type:\n      internal::check_pointer_type_spec(type_spec, eh);\n      break;\n    case internal::custom_type:\n      // Custom format specifiers should be checked in parse functions of\n      // formatter specializations.\n      break;\n    }\n    return pointer_from(it);\n  }\n\n  template <typename FormatContext>\n  auto format(const T &val, FormatContext &ctx) -> decltype(ctx.out()) {\n    internal::handle_dynamic_spec<internal::width_checker>(\n      specs_.width_, specs_.width_ref, ctx);\n    internal::handle_dynamic_spec<internal::precision_checker>(\n      specs_.precision, specs_.precision_ref, ctx);\n    typedef output_range<typename FormatContext::iterator,\n                         typename FormatContext::char_type> range_type;\n    return visit_format_arg(arg_formatter<range_type>(ctx, &specs_),\n                      internal::make_arg<FormatContext>(val));\n  }\n\n private:\n  internal::dynamic_format_specs<Char> specs_;\n};\n\n// A formatter for types known only at run time such as variant alternatives.\n//\n// Usage:\n//   typedef std::variant<int, std::string> variant;\n//   template <>\n//   struct formatter<variant>: dynamic_formatter<> {\n//     void format(buffer &buf, const variant &v, context &ctx) {\n//       visit([&](const auto &val) { format(buf, val, ctx); }, v);\n//     }\n//   };\ntemplate <typename Char = char>\nclass dynamic_formatter {\n private:\n  struct null_handler: internal::error_handler {\n    void on_align(alignment) {}\n    void on_plus() {}\n    void on_minus() {}\n    void on_space() {}\n    void on_hash() {}\n  };\n\n public:\n  template <typename ParseContext>\n  auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {\n    auto it = internal::null_terminating_iterator<Char>(ctx);\n    // Checks are deferred to formatting time when the argument type is known.\n    internal::dynamic_specs_handler<ParseContext> handler(specs_, ctx);\n    it = parse_format_specs(it, handler);\n    return pointer_from(it);\n  }\n\n  template <typename T, typename FormatContext>\n  auto format(const T &val, FormatContext &ctx) -> decltype(ctx.out()) {\n    handle_specs(ctx);\n    internal::specs_checker<null_handler>\n        checker(null_handler(), internal::get_type<FormatContext, T>::value);\n    checker.on_align(specs_.align());\n    if (specs_.flags == 0);  // Do nothing.\n    else if (specs_.has(SIGN_FLAG))\n      specs_.has(PLUS_FLAG) ? checker.on_plus() : checker.on_space();\n    else if (specs_.has(MINUS_FLAG))\n      checker.on_minus();\n    else if (specs_.has(HASH_FLAG))\n      checker.on_hash();\n    if (specs_.precision != -1)\n      checker.end_precision();\n    typedef output_range<typename FormatContext::iterator,\n                         typename FormatContext::char_type> range;\n    visit_format_arg(arg_formatter<range>(ctx, &specs_),\n               internal::make_arg<FormatContext>(val));\n    return ctx.out();\n  }\n\n private:\n  template <typename Context>\n  void handle_specs(Context &ctx) {\n    internal::handle_dynamic_spec<internal::width_checker>(\n      specs_.width_, specs_.width_ref, ctx);\n    internal::handle_dynamic_spec<internal::precision_checker>(\n      specs_.precision, specs_.precision_ref, ctx);\n  }\n\n  internal::dynamic_format_specs<Char> specs_;\n};\n\ntemplate <typename Range, typename Char>\ntypename basic_format_context<Range, Char>::format_arg\n  basic_format_context<Range, Char>::get_arg(\n    basic_string_view<char_type> name) {\n  map_.init(this->args());\n  format_arg arg = map_.find(name);\n  if (arg.type() == internal::none_type)\n    this->on_error(\"argument not found\");\n  return arg;\n}\n\ntemplate <typename ArgFormatter, typename Char, typename Context>\nstruct format_handler : internal::error_handler {\n  typedef internal::null_terminating_iterator<Char> iterator;\n  typedef typename ArgFormatter::range range;\n\n  format_handler(range r, basic_string_view<Char> str,\n                 basic_format_args<Context> format_args,\n                 internal::locale_ref loc)\n    : context(r.begin(), str, format_args, loc) {}\n\n  void on_text(const Char *begin, const Char *end) {\n    auto size = internal::to_unsigned(end - begin);\n    auto out = context.out();\n    auto &&it = internal::reserve(out, size);\n    it = std::copy_n(begin, size, it);\n    context.advance_to(out);\n  }\n\n  void on_arg_id() { arg = context.next_arg(); }\n  void on_arg_id(unsigned id) {\n    context.parse_context().check_arg_id(id);\n    arg = context.get_arg(id);\n  }\n  void on_arg_id(basic_string_view<Char> id) {\n    arg = context.get_arg(id);\n  }\n\n  void on_replacement_field(const Char *p) {\n    context.parse_context().advance_to(p);\n    internal::custom_formatter<Char, Context> f(context);\n    if (!visit_format_arg(f, arg))\n      context.advance_to(visit_format_arg(ArgFormatter(context), arg));\n  }\n\n  iterator on_format_specs(iterator it) {\n    auto &parse_ctx = context.parse_context();\n    parse_ctx.advance_to(pointer_from(it));\n    internal::custom_formatter<Char, Context> f(context);\n    if (visit_format_arg(f, arg))\n      return iterator(parse_ctx);\n    basic_format_specs<Char> specs;\n    using internal::specs_handler;\n    internal::specs_checker<specs_handler<Context>>\n        handler(specs_handler<Context>(specs, context), arg.type());\n    it = parse_format_specs(it, handler);\n    if (*it != '}')\n      on_error(\"missing '}' in format string\");\n    parse_ctx.advance_to(pointer_from(it));\n    context.advance_to(visit_format_arg(ArgFormatter(context, &specs), arg));\n    return it;\n  }\n\n  Context context;\n  basic_format_arg<Context> arg;\n};\n\n/** Formats arguments and writes the output to the range. */\ntemplate <typename ArgFormatter, typename Char, typename Context>\ntypename Context::iterator vformat_to(\n    typename ArgFormatter::range out,\n    basic_string_view<Char> format_str,\n    basic_format_args<Context> args,\n    internal::locale_ref loc = internal::locale_ref()) {\n  format_handler<ArgFormatter, Char, Context> h(out, format_str, args, loc);\n  internal::parse_format_string<false>(format_str, h);\n  return h.context.out();\n}\n\n// Casts ``p`` to ``const void*`` for pointer formatting.\n// Example:\n//   auto s = format(\"{}\", ptr(p));\ntemplate <typename T>\ninline const void *ptr(const T *p) { return p; }\n\ntemplate <typename It, typename Char>\nstruct arg_join {\n  It begin;\n  It end;\n  basic_string_view<Char> sep;\n\n  arg_join(It begin, It end, basic_string_view<Char> sep)\n    : begin(begin), end(end), sep(sep) {}\n};\n\ntemplate <typename It, typename Char>\nstruct formatter<arg_join<It, Char>, Char>:\n    formatter<typename std::iterator_traits<It>::value_type, Char> {\n  template <typename FormatContext>\n  auto format(const arg_join<It, Char> &value, FormatContext &ctx)\n      -> decltype(ctx.out()) {\n    typedef formatter<typename std::iterator_traits<It>::value_type, Char> base;\n    auto it = value.begin;\n    auto out = ctx.out();\n    if (it != value.end) {\n      out = base::format(*it++, ctx);\n      while (it != value.end) {\n        out = std::copy(value.sep.begin(), value.sep.end(), out);\n        ctx.advance_to(out);\n        out = base::format(*it++, ctx);\n      }\n    }\n    return out;\n  }\n};\n\ntemplate <typename It>\narg_join<It, char> join(It begin, It end, string_view sep) {\n  return arg_join<It, char>(begin, end, sep);\n}\n\ntemplate <typename It>\narg_join<It, wchar_t> join(It begin, It end, wstring_view sep) {\n  return arg_join<It, wchar_t>(begin, end, sep);\n}\n\n// The following causes ICE in gcc 4.4.\n#if FMT_USE_TRAILING_RETURN && (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 405)\ntemplate <typename Range>\nauto join(const Range &range, string_view sep)\n    -> arg_join<decltype(internal::begin(range)), char> {\n  return join(internal::begin(range), internal::end(range), sep);\n}\n\ntemplate <typename Range>\nauto join(const Range &range, wstring_view sep)\n    -> arg_join<decltype(internal::begin(range)), wchar_t> {\n  return join(internal::begin(range), internal::end(range), sep);\n}\n#endif\n\n/**\n  \\rst\n  Converts *value* to ``std::string`` using the default format for type *T*.\n  It doesn't support user-defined types with custom formatters.\n\n  **Example**::\n\n    #include <fmt/format.h>\n\n    std::string answer = fmt::to_string(42);\n  \\endrst\n */\ntemplate <typename T>\nstd::string to_string(const T &value) {\n  std::string str;\n  internal::container_buffer<std::string> buf(str);\n  writer(buf).write(value);\n  return str;\n}\n\n/**\n  Converts *value* to ``std::wstring`` using the default format for type *T*.\n */\ntemplate <typename T>\nstd::wstring to_wstring(const T &value) {\n  std::wstring str;\n  internal::container_buffer<std::wstring> buf(str);\n  wwriter(buf).write(value);\n  return str;\n}\n\ntemplate <typename Char, std::size_t SIZE>\nstd::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE> &buf) {\n  return std::basic_string<Char>(buf.data(), buf.size());\n}\n\ntemplate <typename Char>\ntypename buffer_context<Char>::type::iterator internal::vformat_to(\n    internal::basic_buffer<Char> &buf, basic_string_view<Char> format_str,\n    basic_format_args<typename buffer_context<Char>::type> args) {\n  typedef back_insert_range<internal::basic_buffer<Char> > range;\n  return vformat_to<arg_formatter<range>>(\n    buf, to_string_view(format_str), args);\n}\n\ntemplate <typename S, typename Char = FMT_CHAR(S)>\ninline typename buffer_context<Char>::type::iterator vformat_to(\n    internal::basic_buffer<Char> &buf, const S &format_str,\n    basic_format_args<typename buffer_context<Char>::type> args) {\n  return internal::vformat_to(buf, to_string_view(format_str), args);\n}\n\ntemplate <\n    typename S, typename... Args,\n    std::size_t SIZE = inline_buffer_size,\n    typename Char = typename internal::char_t<S>::type>\ninline typename buffer_context<Char>::type::iterator format_to(\n    basic_memory_buffer<Char, SIZE> &buf, const S &format_str,\n    const Args &... args) {\n  internal::check_format_string<Args...>(format_str);\n  typedef typename buffer_context<Char>::type context;\n  format_arg_store<context, Args...> as{args...};\n  return internal::vformat_to(buf, to_string_view(format_str),\n                              basic_format_args<context>(as));\n}\n\nnamespace internal {\n\n// Detect the iterator category of *any* given type in a SFINAE-friendly way.\n// Unfortunately, older implementations of std::iterator_traits are not safe\n// for use in a SFINAE-context.\n\n// the gist of C++17's void_t magic\ntemplate<typename... Ts>\nstruct void_ { typedef void type; };\n\ntemplate <typename T, typename Enable = void>\nstruct it_category : std::false_type {};\n\ntemplate <typename T>\nstruct it_category<T*> { typedef std::random_access_iterator_tag type; };\n\ntemplate <typename T>\nstruct it_category<T, typename void_<typename T::iterator_category>::type> {\n  typedef typename T::iterator_category type;\n};\n\n// Detect if *any* given type models the OutputIterator concept.\ntemplate <typename It>\nclass is_output_iterator {\n  // Check for mutability because all iterator categories derived from\n  // std::input_iterator_tag *may* also meet the requirements of an\n  // OutputIterator, thereby falling into the category of 'mutable iterators'\n  // [iterator.requirements.general] clause 4.\n  // The compiler reveals this property only at the point of *actually\n  // dereferencing* the iterator!\n  template <typename U>\n  static decltype(*(internal::declval<U>())) test(std::input_iterator_tag);\n  template <typename U>\n  static char& test(std::output_iterator_tag);\n  template <typename U>\n  static const char& test(...);\n\n  typedef decltype(test<It>(typename it_category<It>::type{})) type;\n  typedef typename std::remove_reference<type>::type result;\n public:\n  static const bool value = !std::is_const<result>::value;\n};\n} // internal\n\ntemplate <typename OutputIt, typename Char = char>\n//using format_context_t = basic_format_context<OutputIt, Char>;\nstruct format_context_t { typedef basic_format_context<OutputIt, Char> type; };\n\ntemplate <typename OutputIt, typename Char = char>\n//using format_args_t = basic_format_args<format_context_t<OutputIt, Char>>;\nstruct format_args_t {\n  typedef basic_format_args<\n    typename format_context_t<OutputIt, Char>::type> type;\n};\n\ntemplate <typename String, typename OutputIt, typename... Args>\ninline typename std::enable_if<internal::is_output_iterator<OutputIt>::value,\n                               OutputIt>::type\n    vformat_to(OutputIt out, const String &format_str,\n    typename format_args_t<OutputIt, FMT_CHAR(String)>::type args) {\n  typedef output_range<OutputIt, FMT_CHAR(String)> range;\n  return vformat_to<arg_formatter<range>>(range(out),\n                                          to_string_view(format_str), args);\n}\n\n/**\n \\rst\n Formats arguments, writes the result to the output iterator ``out`` and returns\n the iterator past the end of the output range.\n\n **Example**::\n\n   std::vector<char> out;\n   fmt::format_to(std::back_inserter(out), \"{}\", 42);\n \\endrst\n */\ntemplate <typename OutputIt, typename S, typename... Args>\ninline typename std::enable_if<\n    internal::is_string<S>::value &&\n    internal::is_output_iterator<OutputIt>::value, OutputIt>::type\n    format_to(OutputIt out, const S &format_str, const Args &... args) {\n  internal::check_format_string<Args...>(format_str);\n  typedef typename format_context_t<OutputIt, FMT_CHAR(S)>::type context;\n  format_arg_store<context, Args...> as{args...};\n  return vformat_to(out, to_string_view(format_str),\n                    basic_format_args<context>(as));\n}\n\ntemplate <typename OutputIt>\nstruct format_to_n_result {\n  /** Iterator past the end of the output range. */\n  OutputIt out;\n  /** Total (not truncated) output size. */\n  std::size_t size;\n};\n\ntemplate <typename OutputIt, typename Char = typename OutputIt::value_type>\nstruct format_to_n_context :\n  format_context_t<fmt::internal::truncating_iterator<OutputIt>, Char> {};\n\ntemplate <typename OutputIt, typename Char = typename OutputIt::value_type>\nstruct format_to_n_args {\n  typedef basic_format_args<\n    typename format_to_n_context<OutputIt, Char>::type> type;\n};\n\ntemplate <typename OutputIt, typename Char, typename ...Args>\ninline format_arg_store<\n  typename format_to_n_context<OutputIt, Char>::type, Args...>\n    make_format_to_n_args(const Args &... args) {\n  return format_arg_store<\n    typename format_to_n_context<OutputIt, Char>::type, Args...>(args...);\n}\n\ntemplate <typename OutputIt, typename Char, typename... Args>\ninline typename std::enable_if<\n    internal::is_output_iterator<OutputIt>::value,\n    format_to_n_result<OutputIt>>::type vformat_to_n(\n    OutputIt out, std::size_t n, basic_string_view<Char> format_str,\n    typename format_to_n_args<OutputIt, Char>::type args) {\n  typedef internal::truncating_iterator<OutputIt> It;\n  auto it = vformat_to(It(out, n), format_str, args);\n  return {it.base(), it.count()};\n}\n\n/**\n \\rst\n Formats arguments, writes up to ``n`` characters of the result to the output\n iterator ``out`` and returns the total output size and the iterator past the\n end of the output range.\n \\endrst\n */\ntemplate <typename OutputIt, typename S, typename... Args>\ninline typename std::enable_if<\n    internal::is_string<S>::value &&\n    internal::is_output_iterator<OutputIt>::value,\n    format_to_n_result<OutputIt>>::type\n    format_to_n(OutputIt out, std::size_t n, const S &format_str,\n                const Args &... args) {\n  internal::check_format_string<Args...>(format_str);\n  typedef FMT_CHAR(S) Char;\n  format_arg_store<\n      typename format_to_n_context<OutputIt, Char>::type, Args...> as(args...);\n  return vformat_to_n(out, n, to_string_view(format_str),\n                      typename format_to_n_args<OutputIt, Char>::type(as));\n}\n\ntemplate <typename Char>\ninline std::basic_string<Char> internal::vformat(\n    basic_string_view<Char> format_str,\n    basic_format_args<typename buffer_context<Char>::type> args) {\n  basic_memory_buffer<Char> buffer;\n  internal::vformat_to(buffer, format_str, args);\n  return fmt::to_string(buffer);\n}\n\n/**\n  Returns the number of characters in the output of\n  ``format(format_str, args...)``.\n */\ntemplate <typename... Args>\ninline std::size_t formatted_size(string_view format_str,\n                                  const Args &... args) {\n  auto it = format_to(internal::counting_iterator<char>(), format_str, args...);\n  return it.count();\n}\n\n#if FMT_USE_USER_DEFINED_LITERALS\nnamespace internal {\n\n# if FMT_UDL_TEMPLATE\ntemplate <typename Char, Char... CHARS>\nclass udl_formatter {\n public:\n  template <typename... Args>\n  std::basic_string<Char> operator()(const Args &... args) const {\n    FMT_CONSTEXPR_DECL Char s[] = {CHARS..., '\\0'};\n    FMT_CONSTEXPR_DECL bool invalid_format =\n        do_check_format_string<Char, error_handler, Args...>(\n          basic_string_view<Char>(s, sizeof...(CHARS)));\n    (void)invalid_format;\n    return format(s, args...);\n  }\n};\n# else\ntemplate <typename Char>\nstruct udl_formatter {\n  const Char *str;\n\n  template <typename... Args>\n  auto operator()(Args &&... args) const\n                  -> decltype(format(str, std::forward<Args>(args)...)) {\n    return format(str, std::forward<Args>(args)...);\n  }\n};\n# endif // FMT_UDL_TEMPLATE\n\ntemplate <typename Char>\nstruct udl_arg {\n  const Char *str;\n\n  template <typename T>\n  named_arg<T, Char> operator=(T &&value) const {\n    return {str, std::forward<T>(value)};\n  }\n};\n\n} // namespace internal\n\ninline namespace literals {\n\n# if FMT_UDL_TEMPLATE\ntemplate <typename Char, Char... CHARS>\nFMT_CONSTEXPR internal::udl_formatter<Char, CHARS...> operator\"\"_format() {\n  return {};\n}\n# else\n/**\n  \\rst\n  User-defined literal equivalent of :func:`fmt::format`.\n\n  **Example**::\n\n    using namespace fmt::literals;\n    std::string message = \"The answer is {}\"_format(42);\n  \\endrst\n */\ninline internal::udl_formatter<char>\noperator\"\" _format(const char *s, std::size_t) { return {s}; }\ninline internal::udl_formatter<wchar_t>\noperator\"\" _format(const wchar_t *s, std::size_t) { return {s}; }\n# endif // FMT_UDL_TEMPLATE\n\n/**\n  \\rst\n  User-defined literal equivalent of :func:`fmt::arg`.\n\n  **Example**::\n\n    using namespace fmt::literals;\n    fmt::print(\"Elapsed time: {s:.2f} seconds\", \"s\"_a=1.23);\n  \\endrst\n */\ninline internal::udl_arg<char>\noperator\"\" _a(const char *s, std::size_t) { return {s}; }\ninline internal::udl_arg<wchar_t>\noperator\"\" _a(const wchar_t *s, std::size_t) { return {s}; }\n} // inline namespace literals\n#endif // FMT_USE_USER_DEFINED_LITERALS\nFMT_END_NAMESPACE\n\n#define FMT_STRING(s) [] { \\\n    typedef typename std::remove_cv<std::remove_pointer< \\\n      typename std::decay<decltype(s)>::type>::type>::type ct; \\\n    struct str : fmt::compile_string { \\\n      typedef ct char_type; \\\n      FMT_CONSTEXPR operator fmt::basic_string_view<ct>() const { \\\n        return {s, sizeof(s) / sizeof(ct) - 1}; \\\n      } \\\n    }; \\\n    return str{}; \\\n  }()\n\n#if defined(FMT_STRING_ALIAS) && FMT_STRING_ALIAS\n/**\n  \\rst\n  Constructs a compile-time format string. This macro is disabled by default to\n  prevent potential name collisions. To enable it define ``FMT_STRING_ALIAS`` to\n  1 before including ``fmt/format.h``.\n\n  **Example**::\n\n    #define FMT_STRING_ALIAS 1\n    #include <fmt/format.h>\n    // A compile-time error because 'd' is an invalid specifier for strings.\n    std::string s = format(fmt(\"{:d}\"), \"foo\");\n  \\endrst\n */\n# define fmt(s) FMT_STRING(s)\n#endif\n\n#ifdef FMT_HEADER_ONLY\n# define FMT_FUNC inline\n# include \"format-inl.h\"\n#else\n# define FMT_FUNC\n#endif\n\n// Restore warnings.\n#if FMT_GCC_VERSION >= 406 || FMT_CLANG_VERSION\n# pragma GCC diagnostic pop\n#endif\n\n#endif  // FMT_FORMAT_H_\n"
  },
  {
    "path": "src/DRAMsim3/ext/headers/INIHLICENSE.txt",
    "content": "\nThe \"inih\" library is distributed under the New BSD license:\n\nCopyright (c) 2009, Ben Hoyt\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of Ben Hoyt nor the names of its contributors\n      may be used to endorse or promote products derived from this software\n      without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY BEN HOYT ''AS IS'' AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL BEN HOYT BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "src/DRAMsim3/ext/headers/INIReader.h",
    "content": "// Read an INI file into easy-to-access name/value pairs.\n\n// inih and INIReader are released under the New BSD license (see LICENSE.txt).\n// Go to the project home page for more info:\n//\n// https://github.com/benhoyt/inih\n/* inih -- simple .INI file parser\n\ninih is released under the New BSD license (see LICENSE.txt). Go to the project\nhome page for more info:\n\nhttps://github.com/benhoyt/inih\n\n*/\n\n#ifndef __INI_H__\n#define __INI_H__\n\n/* Make this header file easier to include in C++ code */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdio.h>\n\n/* Typedef for prototype of handler function. */\ntypedef int (*ini_handler)(void* user, const char* section,\n                           const char* name, const char* value);\n\n/* Typedef for prototype of fgets-style reader function. */\ntypedef char* (*ini_reader)(char* str, int num, void* stream);\n\n/* Parse given INI-style file. May have [section]s, name=value pairs\n   (whitespace stripped), and comments starting with ';' (semicolon). Section\n   is \"\" if name=value pair parsed before any section heading. name:value\n   pairs are also supported as a concession to Python's configparser.\n\n   For each name=value pair parsed, call handler function with given user\n   pointer as well as section, name, and value (data only valid for duration\n   of handler call). Handler should return nonzero on success, zero on error.\n\n   Returns 0 on success, line number of first error on parse error (doesn't\n   stop on first error), -1 on file open error, or -2 on memory allocation\n   error (only when INI_USE_STACK is zero).\n*/\nint ini_parse(const char* filename, ini_handler handler, void* user);\n\n/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't\n   close the file when it's finished -- the caller must do that. */\nint ini_parse_file(FILE* file, ini_handler handler, void* user);\n\n/* Same as ini_parse(), but takes an ini_reader function pointer instead of\n   filename. Used for implementing custom or string-based I/O. */\nint ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,\n                     void* user);\n\n/* Nonzero to allow multi-line value parsing, in the style of Python's\n   configparser. If allowed, ini_parse() will call the handler with the same\n   name for each subsequent line parsed. */\n#ifndef INI_ALLOW_MULTILINE\n#define INI_ALLOW_MULTILINE 1\n#endif\n\n/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of\n   the file. See http://code.google.com/p/inih/issues/detail?id=21 */\n#ifndef INI_ALLOW_BOM\n#define INI_ALLOW_BOM 1\n#endif\n\n/* Nonzero to allow inline comments (with valid inline comment characters\n   specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match\n   Python 3.2+ configparser behaviour. */\n#ifndef INI_ALLOW_INLINE_COMMENTS\n#define INI_ALLOW_INLINE_COMMENTS 1\n#endif\n#ifndef INI_INLINE_COMMENT_PREFIXES\n#define INI_INLINE_COMMENT_PREFIXES \";\"\n#endif\n\n/* Nonzero to use stack, zero to use heap (malloc/free). */\n#ifndef INI_USE_STACK\n#define INI_USE_STACK 1\n#endif\n\n/* Stop parsing on first error (default is to keep parsing). */\n#ifndef INI_STOP_ON_FIRST_ERROR\n#define INI_STOP_ON_FIRST_ERROR 0\n#endif\n\n/* Maximum line length for any line in INI file. */\n#ifndef INI_MAX_LINE\n#define INI_MAX_LINE 200\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n/* inih -- simple .INI file parser\n\ninih is released under the New BSD license (see LICENSE.txt). Go to the project\nhome page for more info:\n\nhttps://github.com/benhoyt/inih\n\n*/\n\n#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)\n#define _CRT_SECURE_NO_WARNINGS\n#endif\n\n#include <stdio.h>\n#include <ctype.h>\n#include <string.h>\n\n#if !INI_USE_STACK\n#include <stdlib.h>\n#endif\n\n#define MAX_SECTION 50\n#define MAX_NAME 50\n\n/* Strip whitespace chars off end of given string, in place. Return s. */\ninline static char* rstrip(char* s)\n{\n    char* p = s + strlen(s);\n    while (p > s && isspace((unsigned char)(*--p)))\n        *p = '\\0';\n    return s;\n}\n\n/* Return pointer to first non-whitespace char in given string. */\ninline static char* lskip(const char* s)\n{\n    while (*s && isspace((unsigned char)(*s)))\n        s++;\n    return (char*)s;\n}\n\n/* Return pointer to first char (of chars) or inline comment in given string,\n   or pointer to null at end of string if neither found. Inline comment must\n   be prefixed by a whitespace character to register as a comment. */\ninline static char* find_chars_or_comment(const char* s, const char* chars)\n{\n#if INI_ALLOW_INLINE_COMMENTS\n    int was_space = 0;\n    while (*s && (!chars || !strchr(chars, *s)) &&\n           !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) {\n        was_space = isspace((unsigned char)(*s));\n        s++;\n    }\n#else\n    while (*s && (!chars || !strchr(chars, *s))) {\n        s++;\n    }\n#endif\n    return (char*)s;\n}\n\n/* Version of strncpy that ensures dest (size bytes) is null-terminated. */\ninline static char* strncpy0(char* dest, const char* src, size_t size)\n{\n    strncpy(dest, src, size);\n    dest[size - 1] = '\\0';\n    return dest;\n}\n\n/* See documentation in header file. */\ninline int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,\n                     void* user)\n{\n    /* Uses a fair bit of stack (use heap instead if you need to) */\n#if INI_USE_STACK\n    char line[INI_MAX_LINE];\n#else\n    char* line;\n#endif\n    char section[MAX_SECTION] = \"\";\n    char prev_name[MAX_NAME] = \"\";\n\n    char* start;\n    char* end;\n    char* name;\n    char* value;\n    int lineno = 0;\n    int error = 0;\n\n#if !INI_USE_STACK\n    line = (char*)malloc(INI_MAX_LINE);\n    if (!line) {\n        return -2;\n    }\n#endif\n\n    /* Scan through stream line by line */\n    while (reader(line, INI_MAX_LINE, stream) != NULL) {\n        lineno++;\n\n        start = line;\n#if INI_ALLOW_BOM\n        if (lineno == 1 && (unsigned char)start[0] == 0xEF &&\n                           (unsigned char)start[1] == 0xBB &&\n                           (unsigned char)start[2] == 0xBF) {\n            start += 3;\n        }\n#endif\n        start = lskip(rstrip(start));\n\n        if (*start == ';' || *start == '#') {\n            /* Per Python configparser, allow both ; and # comments at the\n               start of a line */\n        }\n#if INI_ALLOW_MULTILINE\n        else if (*prev_name && *start && start > line) {\n\n#if INI_ALLOW_INLINE_COMMENTS\n        end = find_chars_or_comment(start, NULL);\n        if (*end)\n            *end = '\\0';\n        rstrip(start);\n#endif\n\n            /* Non-blank line with leading whitespace, treat as continuation\n               of previous name's value (as per Python configparser). */\n            if (!handler(user, section, prev_name, start) && !error)\n                error = lineno;\n        }\n#endif\n        else if (*start == '[') {\n            /* A \"[section]\" line */\n            end = find_chars_or_comment(start + 1, \"]\");\n            if (*end == ']') {\n                *end = '\\0';\n                strncpy0(section, start + 1, sizeof(section));\n                *prev_name = '\\0';\n            }\n            else if (!error) {\n                /* No ']' found on section line */\n                error = lineno;\n            }\n        }\n        else if (*start) {\n            /* Not a comment, must be a name[=:]value pair */\n            end = find_chars_or_comment(start, \"=:\");\n            if (*end == '=' || *end == ':') {\n                *end = '\\0';\n                name = rstrip(start);\n                value = lskip(end + 1);\n#if INI_ALLOW_INLINE_COMMENTS\n                end = find_chars_or_comment(value, NULL);\n                if (*end)\n                    *end = '\\0';\n#endif\n                rstrip(value);\n\n                /* Valid name[=:]value pair found, call handler */\n                strncpy0(prev_name, name, sizeof(prev_name));\n                if (!handler(user, section, name, value) && !error)\n                    error = lineno;\n            }\n            else if (!error) {\n                /* No '=' or ':' found on name[=:]value line */\n                error = lineno;\n            }\n        }\n\n#if INI_STOP_ON_FIRST_ERROR\n        if (error)\n            break;\n#endif\n    }\n\n#if !INI_USE_STACK\n    free(line);\n#endif\n\n    return error;\n}\n\n/* See documentation in header file. */\ninline int ini_parse_file(FILE* file, ini_handler handler, void* user)\n{\n    return ini_parse_stream((ini_reader)fgets, file, handler, user);\n}\n\n/* See documentation in header file. */\ninline int ini_parse(const char* filename, ini_handler handler, void* user)\n{\n    FILE* file;\n    int error;\n\n    file = fopen(filename, \"r\");\n    if (!file)\n        return -1;\n    error = ini_parse_file(file, handler, user);\n    fclose(file);\n    return error;\n}\n\n#endif /* __INI_H__ */\n\n\n#ifndef __INIREADER_H__\n#define __INIREADER_H__\n\n#include <map>\n#include <set>\n#include <string>\n\n// Read an INI file into easy-to-access name/value pairs. (Note that I've gone\n// for simplicity here rather than speed, but it should be pretty decent.)\nclass INIReader\n{\npublic:\n    // Empty Constructor\n    INIReader() {};\n\n    // Construct INIReader and parse given filename. See ini.h for more info\n    // about the parsing.\n    INIReader(std::string filename);\n\n    // Return the result of ini_parse(), i.e., 0 on success, line number of\n    // first error on parse error, or -1 on file open error.\n    int ParseError() const;\n\n    // Return the list of sections found in ini file\n    const std::set<std::string>& Sections() const;\n\n    // Get a string value from INI file, returning default_value if not found.\n    std::string Get(std::string section, std::string name,\n                    std::string default_value) const;\n\n    // Get an integer (long) value from INI file, returning default_value if\n    // not found or not a valid integer (decimal \"1234\", \"-1234\", or hex \"0x4d2\").\n    long GetInteger(std::string section, std::string name, long default_value) const;\n\n    // Get a real (floating point double) value from INI file, returning\n    // default_value if not found or not a valid floating point value\n    // according to strtod().\n    double GetReal(std::string section, std::string name, double default_value) const;\n\n    // Get a boolean value from INI file, returning default_value if not found or if\n    // not a valid true/false value. Valid true values are \"true\", \"yes\", \"on\", \"1\",\n    // and valid false values are \"false\", \"no\", \"off\", \"0\" (not case sensitive).\n    bool GetBoolean(std::string section, std::string name, bool default_value) const;\n\nprotected:\n    int _error;\n    std::map<std::string, std::string> _values;\n    std::set<std::string> _sections;\n    static std::string MakeKey(std::string section, std::string name);\n    static int ValueHandler(void* user, const char* section, const char* name,\n                            const char* value);\n};\n\n#endif  // __INIREADER_H__\n\n\n#ifndef __INIREADER__\n#define __INIREADER__\n\n#include <algorithm>\n#include <cctype>\n#include <cstdlib>\n\nusing std::string;\n\ninline INIReader::INIReader(string filename)\n{\n    _error = ini_parse(filename.c_str(), ValueHandler, this);\n}\n\ninline int INIReader::ParseError() const\n{\n    return _error;\n}\n\ninline const std::set<string>& INIReader::Sections() const\n{\n    return _sections;\n}\n\ninline string INIReader::Get(string section, string name, string default_value) const\n{\n    string key = MakeKey(section, name);\n    return _values.count(key) ? _values.at(key) : default_value;\n}\n\ninline long INIReader::GetInteger(string section, string name, long default_value) const\n{\n    string valstr = Get(section, name, \"\");\n    const char* value = valstr.c_str();\n    char* end;\n    // This parses \"1234\" (decimal) and also \"0x4D2\" (hex)\n    long n = strtol(value, &end, 0);\n    return end > value ? n : default_value;\n}\n\ninline double INIReader::GetReal(string section, string name, double default_value) const\n{\n    string valstr = Get(section, name, \"\");\n    const char* value = valstr.c_str();\n    char* end;\n    double n = strtod(value, &end);\n    return end > value ? n : default_value;\n}\n\ninline bool INIReader::GetBoolean(string section, string name, bool default_value) const\n{\n    string valstr = Get(section, name, \"\");\n    // Convert to lower case to make string comparisons case-insensitive\n    std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower);\n    if (valstr == \"true\" || valstr == \"yes\" || valstr == \"on\" || valstr == \"1\")\n        return true;\n    else if (valstr == \"false\" || valstr == \"no\" || valstr == \"off\" || valstr == \"0\")\n        return false;\n    else\n        return default_value;\n}\n\ninline string INIReader::MakeKey(string section, string name)\n{\n    string key = section + \"=\" + name;\n    // Convert to lower case to make section/name lookups case-insensitive\n    std::transform(key.begin(), key.end(), key.begin(), ::tolower);\n    return key;\n}\n\ninline int INIReader::ValueHandler(void* user, const char* section, const char* name,\n                            const char* value)\n{\n    INIReader* reader = (INIReader*)user;\n    string key = MakeKey(section, name);\n    if (reader->_values[key].size() > 0)\n        reader->_values[key] += \"\\n\";\n    reader->_values[key] += value;\n    reader->_sections.insert(section);\n    return 1;\n}\n\n#endif  // __INIREADER__\n"
  },
  {
    "path": "src/DRAMsim3/ext/headers/args.hxx",
    "content": "/* Copyright (c) 2016 Taylor C. Richberger <taywee@gmx.com>\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/** \\file args.hxx\n * \\brief this single-header lets you use all of the args functionality\n *\n * The important stuff is done inside the args namespace\n */\n\n#ifndef ARGS_HXX\n#define ARGS_HXX\n\n#include <algorithm>\n#include <exception>\n#include <functional>\n#include <sstream>\n#include <string>\n#include <tuple>\n#include <vector>\n#include <unordered_map>\n#include <unordered_set>\n#include <type_traits>\n\n#ifdef ARGS_TESTNAMESPACE\nnamespace argstest\n{\n#else\n\n/** \\namespace args\n * \\brief contains all the functionality of the args library\n */\nnamespace args\n{\n#endif\n    /** Getter to grab the value from the argument type.\n     *\n     * If the Get() function of the type returns a reference, so does this, and\n     * the value will be modifiable.\n     */\n    template <typename Option>\n    auto get(Option &option_) -> decltype(option_.Get())\n    {\n        return option_.Get();\n    }\n\n    /** (INTERNAL) Count UTF-8 glyphs\n     *\n     * This is not reliable, and will fail for combinatory glyphs, but it's\n     * good enough here for now.\n     *\n     * \\param string The string to count glyphs from\n     * \\return The UTF-8 glyphs in the string\n     */\n    std::string::size_type Glyphs(const std::string &string_)\n    {\n        std::string::size_type length = 0;\n        for (const char c: string_)\n        {\n            if ((c & 0xc0) != 0x80)\n            {\n                ++length;\n            }\n        }\n        return length;\n    }\n\n    /** (INTERNAL) Wrap a string into a vector of lines\n     *\n     * This is quick and hacky, but works well enough.  You can specify a\n     * different width for the first line\n     *\n     * \\param width The width of the body\n     * \\param the widtho f the first line, defaults to the width of the body\n     * \\return the vector of lines\n     */\n    std::vector<std::string> Wrap(const std::string &in, const std::string::size_type width, std::string::size_type firstlinewidth = 0)\n    {\n        // Preserve existing line breaks\n        const auto newlineloc = in.find('\\n');\n        if (newlineloc != in.npos)\n        {\n            auto first = Wrap(std::string(in, 0, newlineloc), width);\n            auto second = Wrap(std::string(in, newlineloc + 1), width);\n            first.insert(\n                std::end(first),\n                std::make_move_iterator(std::begin(second)),\n                std::make_move_iterator(std::end(second)));\n            return first;\n        }\n        if (firstlinewidth == 0)\n        {\n            firstlinewidth = width;\n        }\n        auto currentwidth = firstlinewidth;\n\n        std::istringstream stream(in);\n        std::vector<std::string> output;\n        std::ostringstream line;\n        std::string::size_type linesize = 0;\n        while (stream)\n        {\n            std::string item;\n            stream >> item;\n            auto itemsize = Glyphs(item);\n            if ((linesize + 1 + itemsize) > currentwidth)\n            {\n                if (linesize > 0)\n                {\n                    output.push_back(line.str());\n                    line.str(std::string());\n                    linesize = 0;\n                    currentwidth = width;\n                }\n            }\n            if (itemsize > 0)\n            {\n                if (linesize)\n                {\n                    ++linesize;\n                    line << \" \";\n                }\n                line << item;\n                linesize += itemsize;\n            }\n        }\n        if (linesize > 0)\n        {\n            output.push_back(line.str());\n        }\n        return output;\n    }\n\n#ifdef ARGS_NOEXCEPT\n    /// Error class, for when ARGS_NOEXCEPT is defined\n    enum class Error\n    {\n        None,\n        Usage,\n        Parse,\n        Validation,\n        Map,\n        Extra,\n        Help\n    };\n#else\n    /** Base error class\n     */\n    class Error : public std::runtime_error\n    {\n        public:\n            Error(const std::string &problem) : std::runtime_error(problem) {}\n            virtual ~Error() {};\n    };\n\n    /** Errors that occur during usage\n     */\n    class UsageError : public Error\n    {\n        public:\n            UsageError(const std::string &problem) : Error(problem) {}\n            virtual ~UsageError() {};\n    };\n\n    /** Errors that occur during regular parsing\n     */\n    class ParseError : public Error\n    {\n        public:\n            ParseError(const std::string &problem) : Error(problem) {}\n            virtual ~ParseError() {};\n    };\n\n    /** Errors that are detected from group validation after parsing finishes\n     */\n    class ValidationError : public Error\n    {\n        public:\n            ValidationError(const std::string &problem) : Error(problem) {}\n            virtual ~ValidationError() {};\n    };\n\n    /** Errors in map lookups\n     */\n    class MapError : public ParseError\n    {\n        public:\n            MapError(const std::string &problem) : ParseError(problem) {}\n            virtual ~MapError() {};\n    };\n\n    /** Error that occurs when a singular flag is specified multiple times\n     */\n    class ExtraError : public ParseError\n    {\n        public:\n            ExtraError(const std::string &problem) : ParseError(problem) {}\n            virtual ~ExtraError() {};\n    };\n\n    /** An exception that indicates that the user has requested help\n     */\n    class Help : public Error\n    {\n        public:\n            Help(const std::string &flag) : Error(flag) {}\n            virtual ~Help() {};\n    };\n#endif\n\n    /** A simple unified option type for unified initializer lists for the Matcher class.\n     */\n    struct EitherFlag\n    {\n        const bool isShort;\n        const char shortFlag;\n        const std::string longFlag;\n        EitherFlag(const std::string &flag) : isShort(false), shortFlag(), longFlag(flag) {}\n        EitherFlag(const char *flag) : isShort(false), shortFlag(), longFlag(flag) {}\n        EitherFlag(const char flag) : isShort(true), shortFlag(flag), longFlag() {}\n\n        /** Get just the long flags from an initializer list of EitherFlags\n         */\n        static std::unordered_set<std::string> GetLong(std::initializer_list<EitherFlag> flags)\n        {\n            std::unordered_set<std::string>  longFlags;\n            for (const EitherFlag &flag: flags)\n            {\n                if (!flag.isShort)\n                {\n                    longFlags.insert(flag.longFlag);\n                }\n            }\n            return longFlags;\n        }\n\n        /** Get just the short flags from an initializer list of EitherFlags\n         */\n        static std::unordered_set<char> GetShort(std::initializer_list<EitherFlag> flags)\n        {\n            std::unordered_set<char>  shortFlags;\n            for (const EitherFlag &flag: flags)\n            {\n                if (flag.isShort)\n                {\n                    shortFlags.insert(flag.shortFlag);\n                }\n            }\n            return shortFlags;\n        }\n    };\n\n\n\n    /** A class of \"matchers\", specifying short and flags that can possibly be\n     * matched.\n     *\n     * This is supposed to be constructed and then passed in, not used directly\n     * from user code.\n     */\n    class Matcher\n    {\n        private:\n            const std::unordered_set<char> shortFlags;\n            const std::unordered_set<std::string> longFlags;\n\n        public:\n            /** Specify short and long flags separately as iterators\n             *\n             * ex: `args::Matcher(shortFlags.begin(), shortFlags.end(), longFlags.begin(), longFlags.end())`\n             */\n            template <typename ShortIt, typename LongIt>\n            Matcher(ShortIt shortFlagsStart, ShortIt shortFlagsEnd, LongIt longFlagsStart, LongIt longFlagsEnd) :\n                shortFlags(shortFlagsStart, shortFlagsEnd),\n                longFlags(longFlagsStart, longFlagsEnd)\n            {}\n\n            /** Specify short and long flags separately as iterables\n             *\n             * ex: `args::Matcher(shortFlags, longFlags)`\n             */\n            template <typename Short, typename Long>\n            Matcher(Short &&shortIn, Long &&longIn) :\n                shortFlags(std::begin(shortIn), std::end(shortIn)), longFlags(std::begin(longIn), std::end(longIn))\n            {}\n\n            /** Specify a mixed single initializer-list of both short and long flags\n             *\n             * This is the fancy one.  It takes a single initializer list of\n             * any number of any mixed kinds of flags.  Chars are\n             * automatically interpreted as short flags, and strings are\n             * automatically interpreted as long flags:\n             *\n             *     args::Matcher{'a'}\n             *     args::Matcher{\"foo\"}\n             *     args::Matcher{'h', \"help\"}\n             *     args::Matcher{\"foo\", 'f', 'F', \"FoO\"}\n             */\n            Matcher(std::initializer_list<EitherFlag> in) :\n                shortFlags(EitherFlag::GetShort(in)), longFlags(EitherFlag::GetLong(in)) {}\n\n            Matcher(Matcher &&other) : shortFlags(std::move(other.shortFlags)), longFlags(std::move(other.longFlags))\n            {}\n\n            ~Matcher() {}\n\n            /** (INTERNAL) Check if there is a match of a short flag\n             */\n            bool Match(const char flag) const\n            {\n                return shortFlags.find(flag) != shortFlags.end();\n            }\n\n            /** (INTERNAL) Check if there is a match of a long flag\n             */\n            bool Match(const std::string &flag) const\n            {\n                return longFlags.find(flag) != longFlags.end();\n            }\n\n            /** (INTERNAL) Get all flag strings as a vector, with the prefixes embedded\n             */\n            std::vector<std::string> GetFlagStrings(const std::string &shortPrefix, const std::string &longPrefix) const\n            {\n                std::vector<std::string> flagStrings;\n                flagStrings.reserve(shortFlags.size() + longFlags.size());\n                for (const char flag: shortFlags)\n                {\n                    flagStrings.emplace_back(shortPrefix + std::string(1, flag));\n                }\n                for (const std::string &flag: longFlags)\n                {\n                    flagStrings.emplace_back(longPrefix + flag);\n                }\n                return flagStrings;\n            }\n\n            /** (INTERNAL) Get all flag strings as a vector, with the prefixes and names embedded\n             */\n            std::vector<std::string> GetFlagStrings(const std::string &shortPrefix, const std::string &longPrefix, const std::string &name, const std::string &shortSeparator, const std::string longSeparator) const\n            {\n                const std::string bracedname(std::string(\"[\") + name + \"]\");\n                std::vector<std::string> flagStrings;\n                flagStrings.reserve(shortFlags.size() + longFlags.size());\n                for (const char flag: shortFlags)\n                {\n                    flagStrings.emplace_back(shortPrefix + std::string(1, flag) + shortSeparator + bracedname);\n                }\n                for (const std::string &flag: longFlags)\n                {\n                    flagStrings.emplace_back(longPrefix + flag + longSeparator + bracedname);\n                }\n                return flagStrings;\n            }\n    };\n\n    /** Base class for all match types\n     */\n    class Base\n    {\n        protected:\n            bool matched;\n            const std::string help;\n#ifdef ARGS_NOEXCEPT\n            /// Only for ARGS_NOEXCEPT\n            Error error;\n#endif\n\n        public:\n            Base(const std::string &help_) : matched(false), help(help_) {}\n            virtual ~Base() {}\n\n            virtual bool Matched() const noexcept\n            {\n                return matched;\n            }\n\n            operator bool() const noexcept\n            {\n                return Matched();\n            }\n\n            virtual std::tuple<std::string, std::string> GetDescription(const std::string &shortPrefix, const std::string &longPrefix, const std::string &shortSeparator, const std::string &longSeparator) const\n            {\n                std::tuple<std::string, std::string> description;\n                std::get<1>(description) = help;\n                return description;\n            }\n\n            virtual void Reset() noexcept\n            {\n                matched = false;\n#ifdef ARGS_NOEXCEPT\n                error = Error::None;\n#endif\n            }\n\n#ifdef ARGS_NOEXCEPT\n            /// Only for ARGS_NOEXCEPT\n            virtual Error GetError() const\n            {\n                return error;\n            }\n#endif\n    };\n\n    /** Base class for all match types that have a name\n     */\n    class NamedBase : public Base\n    {\n        protected:\n            const std::string name;\n            bool kickout;\n\n        public:\n            NamedBase(const std::string &name_, const std::string &help_) : Base(help_), name(name_), kickout(false) {}\n            virtual ~NamedBase() {}\n\n            virtual std::tuple<std::string, std::string> GetDescription(const std::string &shortPrefix, const std::string &longPrefi, const std::string &shortSeparator, const std::string &longSeparator) const override\n            {\n                std::tuple<std::string, std::string> description;\n                std::get<0>(description) = Name();\n                std::get<1>(description) = help;\n                return description;\n            }\n            virtual std::string Name() const\n            {\n                return name;\n            }\n\n            /// Sets a kick-out value for building subparsers\n            void KickOut(bool kickout_) noexcept\n            {\n                this->kickout = kickout_;\n            }\n\n            /// Gets the kick-out value for building subparsers\n            bool KickOut() const noexcept\n            {\n                return kickout;\n            }\n    };\n\n    /** Base class for all flag options\n     */\n    class FlagBase : public NamedBase\n    {\n        private:\n            const bool extraError;\n\n        protected:\n            const Matcher matcher;\n\n        public:\n            FlagBase(const std::string &name_, const std::string &help_, Matcher &&matcher_, const bool extraError_ = false) : NamedBase(name_, help_), extraError(extraError_), matcher(std::move(matcher_)) {}\n\n            virtual ~FlagBase() {}\n\n            virtual FlagBase *Match(const std::string &flag)\n            {\n                if (matcher.Match(flag))\n                {\n                    if (extraError && matched)\n                    {\n#ifdef ARGS_NOEXCEPT\n                        error = Error::Extra;\n#else\n                        std::ostringstream problem;\n                        problem << \"Flag '\" << flag << \"' was passed multiple times, but is only allowed to be passed once\";\n                        throw ExtraError(problem.str());\n#endif\n                    }\n                    matched = true;\n                    return this;\n                }\n                return nullptr;\n            }\n\n            virtual FlagBase *Match(const char flag)\n            {\n                if (matcher.Match(flag))\n                {\n                    if (extraError && matched)\n                    {\n#ifdef ARGS_NOEXCEPT\n                        error = Error::Extra;\n#else\n                        std::ostringstream problem;\n                        problem << \"Flag '\" << flag << \"' was passed multiple times, but is only allowed to be passed once\";\n                        throw ExtraError(problem.str());\n#endif\n                    }\n                    matched = true;\n                    return this;\n                }\n                return nullptr;\n            }\n\n            virtual std::tuple<std::string, std::string> GetDescription(const std::string &shortPrefix, const std::string &longPrefix, const std::string &shortSeparator, const std::string &longSeparator) const override\n            {\n                std::tuple<std::string, std::string> description;\n                const auto flagStrings = matcher.GetFlagStrings(shortPrefix, longPrefix);\n                std::ostringstream flagstream;\n                for (auto it = std::begin(flagStrings); it != std::end(flagStrings); ++it)\n                {\n                    if (it != std::begin(flagStrings))\n                    {\n                        flagstream << \", \";\n                    }\n                    flagstream << *it;\n                }\n                std::get<0>(description) = flagstream.str();\n                std::get<1>(description) = help;\n                return description;\n            }\n    };\n\n    /** Base class for value-accepting flag options\n     */\n    class ValueFlagBase : public FlagBase\n    {\n        public:\n            ValueFlagBase(const std::string &name_, const std::string &help_, Matcher &&matcher_, const bool extraError_ = false) : FlagBase(name_, help_, std::move(matcher_), extraError_) {}\n            virtual ~ValueFlagBase() {}\n            virtual void ParseValue(const std::string &value) = 0;\n\n            virtual std::tuple<std::string, std::string> GetDescription(const std::string &shortPrefix, const std::string &longPrefix, const std::string &shortSeparator, const std::string &longSeparator) const override\n            {\n                std::tuple<std::string, std::string> description;\n                const auto flagStrings = matcher.GetFlagStrings(shortPrefix, longPrefix, Name(), shortSeparator, longSeparator);\n                std::ostringstream flagstream;\n                for (auto it = std::begin(flagStrings); it != std::end(flagStrings); ++it)\n                {\n                    if (it != std::begin(flagStrings))\n                    {\n                        flagstream << \", \";\n                    }\n                    flagstream << *it;\n                }\n                std::get<0>(description) = flagstream.str();\n                std::get<1>(description) = help;\n                return description;\n            }\n    };\n\n    /** Base class for positional options\n     */\n    class PositionalBase : public NamedBase\n    {\n        protected:\n            bool ready;\n\n        public:\n            PositionalBase(const std::string &name_, const std::string &help_) : NamedBase(name_, help_), ready(true) {}\n            virtual ~PositionalBase() {}\n\n            bool Ready()\n            {\n                return ready;\n            }\n\n            virtual void ParseValue(const std::string &value_) = 0;\n\n            virtual void Reset() noexcept override\n            {\n                matched = false;\n                ready = true;\n#ifdef ARGS_NOEXCEPT\n                error = Error::None;\n#endif\n            }\n    };\n\n    /** Class for all kinds of validating groups, including ArgumentParser\n     */\n    class Group : public Base\n    {\n        private:\n            std::vector<Base*> children;\n            std::function<bool(const Group &)> validator;\n\n        public:\n            /** Default validators\n             */\n            struct Validators\n            {\n                static bool Xor(const Group &group)\n                {\n                    return group.MatchedChildren() == 1;\n                }\n\n                static bool AtLeastOne(const Group &group)\n                {\n                    return group.MatchedChildren() >= 1;\n                }\n\n                static bool AtMostOne(const Group &group)\n                {\n                    return group.MatchedChildren() <= 1;\n                }\n\n                static bool All(const Group &group)\n                {\n                    return group.Children().size() == group.MatchedChildren();\n                }\n\n                static bool AllOrNone(const Group &group)\n                {\n                    return (All(group) || None(group));\n                }\n\n                static bool AllChildGroups(const Group &group)\n                {\n                    return std::find_if(std::begin(group.Children()), std::end(group.Children()), [](const Base* child) -> bool {\n                            return dynamic_cast<const Group *>(child) && !child->Matched();\n                            }) == std::end(group.Children());\n                }\n\n                static bool DontCare(const Group &group)\n                {\n                    return true;\n                }\n\n                static bool CareTooMuch(const Group &group)\n                {\n                    return false;\n                }\n\n                static bool None(const Group &group)\n                {\n                    return group.MatchedChildren() == 0;\n                }\n            };\n            /// If help is empty, this group will not be printed in help output\n            Group(const std::string &help_ = std::string(), const std::function<bool(const Group &)> &validator_ = Validators::DontCare) : Base(help_), validator(validator_) {}\n            /// If help is empty, this group will not be printed in help output\n            Group(Group &group_, const std::string &help_ = std::string(), const std::function<bool(const Group &)> &validator_ = Validators::DontCare) : Base(help_), validator(validator_)\n            {\n                group_.Add(*this);\n            }\n            virtual ~Group() {}\n\n            /** Return the first FlagBase that matches flag, or nullptr\n             *\n             * \\param flag The flag with prefixes stripped\n             * \\return the first matching FlagBase pointer, or nullptr if there is no match\n             */\n            template <typename T>\n            FlagBase *Match(const T &flag)\n            {\n                for (Base *child: children)\n                {\n                    if (FlagBase *flagBase = dynamic_cast<FlagBase *>(child))\n                    {\n                        if (FlagBase *match = flagBase->Match(flag))\n                        {\n                            return match;\n                        }\n                    } else if (Group *group = dynamic_cast<Group *>(child))\n                    {\n                        if (FlagBase *match = group->Match(flag))\n                        {\n                            return match;\n                        }\n                    }\n                }\n                return nullptr;\n            }\n\n            /** Get the next ready positional, or nullptr if there is none\n             *\n             * \\return the first ready PositionalBase pointer, or nullptr if there is no match\n             */\n            PositionalBase *GetNextPositional()\n            {\n                for (Base *child: children)\n                {\n                    auto next = dynamic_cast<PositionalBase *>(child);\n                    auto group = dynamic_cast<Group *>(child);\n                    if (group)\n                    {\n                        next = group->GetNextPositional();\n                    }\n                    if (next && next->Ready())\n                    {\n                        return next;\n                    }\n                }\n                return nullptr;\n            }\n\n            /** Get whether this has any FlagBase children\n             *\n             * \\return Whether or not there are any FlagBase children\n             */\n            bool HasFlag() const\n            {\n                for (Base *child: children)\n                {\n                    if (dynamic_cast<FlagBase *>(child))\n                    {\n                        return true;\n                    }\n                    if (auto group = dynamic_cast<Group *>(child))\n                    {\n                        if (group->HasFlag())\n                        {\n                            return true;\n                        }\n                    }\n                }\n                return false;\n            }\n\n            /** Append a child to this Group.\n             */\n            void Add(Base &child)\n            {\n                children.emplace_back(&child);\n            }\n\n            /** Get all this group's children\n             */\n            const std::vector<Base *> &Children() const\n            {\n                return children;\n            }\n\n            /** Count the number of matched children this group has\n             */\n            std::vector<Base *>::size_type MatchedChildren() const\n            {\n                return std::count_if(std::begin(children), std::end(children), [](const Base *child){return child->Matched();});\n            }\n\n            /** Whether or not this group matches validation\n             */\n            virtual bool Matched() const noexcept override\n            {\n                return validator(*this);\n            }\n\n            /** Get validation\n             */\n            bool Get() const\n            {\n                return Matched();\n            }\n\n            /** Get all the child descriptions for help generation\n             */\n            std::vector<std::tuple<std::string, std::string, unsigned int>> GetChildDescriptions(const std::string &shortPrefix, const std::string &longPrefix, const std::string &shortSeparator, const std::string &longSeparator, const unsigned int indent = 0) const\n            {\n                std::vector<std::tuple<std::string, std::string, unsigned int>> descriptions;\n                for (const auto &child: children)\n                {\n                    if (const auto group = dynamic_cast<Group *>(child))\n                    {\n                        // Push that group description on the back if not empty\n                        unsigned char addindent = 0;\n                        if (!group->help.empty())\n                        {\n                            descriptions.emplace_back(group->help, \"\", indent);\n                            addindent = 1;\n                        }\n                        auto groupDescriptions = group->GetChildDescriptions(shortPrefix, longPrefix, shortSeparator, longSeparator, indent + addindent);\n                        descriptions.insert(\n                            std::end(descriptions),\n                            std::make_move_iterator(std::begin(groupDescriptions)),\n                            std::make_move_iterator(std::end(groupDescriptions)));\n                    } else if (const auto named = dynamic_cast<NamedBase *>(child))\n                    {\n                        const auto description = named->GetDescription(shortPrefix, longPrefix, shortSeparator, longSeparator);\n                        descriptions.emplace_back(std::get<0>(description), std::get<1>(description), indent);\n                    }\n                }\n                return descriptions;\n            }\n\n            /** Get the names of positional parameters\n             */\n            std::vector<std::string> GetPosNames() const\n            {\n                std::vector <std::string> names;\n                for (const auto &child: children)\n                {\n                    if (const Group *group = dynamic_cast<Group *>(child))\n                    {\n                        auto groupNames = group->GetPosNames();\n                        names.insert(\n                            std::end(names),\n                            std::make_move_iterator(std::begin(groupNames)),\n                            std::make_move_iterator(std::end(groupNames)));\n                    } else if (const PositionalBase *pos = dynamic_cast<PositionalBase *>(child))\n                    {\n                        names.emplace_back(pos->Name());\n                    }\n                }\n                return names;\n            }\n\n            virtual void Reset() noexcept override\n            {\n                for (auto &child: children)\n                {\n                    child->Reset();\n                }\n#ifdef ARGS_NOEXCEPT\n                error = Error::None;\n#endif\n            }\n\n#ifdef ARGS_NOEXCEPT\n            /// Only for ARGS_NOEXCEPT\n            virtual Error GetError() const override\n            {\n                if (error != Error::None)\n                {\n                    return error;\n                }\n\n                auto it = std::find_if(std::begin(children), std::end(children), [](const Base *child){return child->GetError() != Error::None;});\n                if (it == std::end(children))\n                {\n                    return Error::None;\n                } else\n                {\n                    return (*it)->GetError();\n                }\n            }\n#endif\n\n    };\n\n    /** The main user facing command line argument parser class\n     */\n    class ArgumentParser : public Group\n    {\n        private:\n            std::string prog;\n            std::string proglinePostfix;\n            std::string description;\n            std::string epilog;\n\n            std::string longprefix;\n            std::string shortprefix;\n\n            std::string longseparator;\n\n            std::string terminator;\n\n            bool allowJoinedShortValue;\n            bool allowJoinedLongValue;\n            bool allowSeparateShortValue;\n            bool allowSeparateLongValue;\n\n        public:\n            /** A simple structure of parameters for easy user-modifyable help menus\n             */\n            struct HelpParams\n            {\n                /** The width of the help menu\n                 */\n                unsigned int width = 80;\n                /** The indent of the program line\n                 */\n                unsigned int progindent = 2;\n                /** The indent of the program trailing lines for long parameters\n                 */\n                unsigned int progtailindent = 4;\n                /** The indent of the description and epilogs\n                 */\n                unsigned int descriptionindent = 4;\n                /** The indent of the flags\n                 */\n                unsigned int flagindent = 6;\n                /** The indent of the flag descriptions\n                 */\n                unsigned int helpindent = 40;\n                /** The additional indent each group adds\n                 */\n                unsigned int eachgroupindent = 2;\n\n                /** The minimum gutter between each flag and its help\n                 */\n                unsigned int gutter = 1;\n\n                /** Show the terminator when both options and positional parameters are present\n                 */\n                bool showTerminator = true;\n\n                /** Show the {OPTIONS} on the prog line when this is true\n                 */\n                bool showProglineOptions = true;\n\n                /** Show the positionals on the prog line when this is true\n                 */\n                bool showProglinePositionals = true;\n            } helpParams;\n            ArgumentParser(const std::string &description_, const std::string &epilog_ = std::string()) :\n                Group(\"\", Group::Validators::AllChildGroups),\n                description(description_),\n                epilog(epilog_),\n                longprefix(\"--\"),\n                shortprefix(\"-\"),\n                longseparator(\"=\"),\n                terminator(\"--\"),\n                allowJoinedShortValue(true),\n                allowJoinedLongValue(true),\n                allowSeparateShortValue(true),\n                allowSeparateLongValue(true) {}\n\n            /** The program name for help generation\n             */\n            const std::string &Prog() const\n            { return prog; }\n            /** The program name for help generation\n             */\n            void Prog(const std::string &prog_)\n            { this->prog = prog_; }\n\n            /** The description that appears on the prog line after options\n             */\n            const std::string &ProglinePostfix() const\n            { return proglinePostfix; }\n            /** The description that appears on the prog line after options\n             */\n            void ProglinePostfix(const std::string &proglinePostfix_)\n            { this->proglinePostfix = proglinePostfix_; }\n\n            /** The description that appears above options\n             */\n            const std::string &Description() const\n            { return description; }\n            /** The description that appears above options\n             */\n            void Description(const std::string &description_)\n            { this->description = description_; }\n            \n            /** The description that appears below options\n             */\n            const std::string &Epilog() const\n            { return epilog; }\n            /** The description that appears below options\n             */\n            void Epilog(const std::string &epilog_)\n            { this->epilog = epilog_; }\n\n            /** The prefix for long flags\n             */\n            const std::string &LongPrefix() const\n            { return longprefix; }\n            /** The prefix for long flags\n             */\n            void LongPrefix(const std::string &longprefix_)\n            { this->longprefix = longprefix_; }\n\n            /** The prefix for short flags\n             */\n            const std::string &ShortPrefix() const\n            { return shortprefix; }\n            /** The prefix for short flags\n             */\n            void ShortPrefix(const std::string &shortprefix_)\n            { this->shortprefix = shortprefix_; }\n\n            /** The separator for long flags\n             */\n            const std::string &LongSeparator() const\n            { return longseparator; }\n            /** The separator for long flags\n             */\n            void LongSeparator(const std::string &longseparator_)\n            {\n                if (longseparator_.empty())\n                {\n#ifdef ARGS_NOEXCEPT\n                    error = Error::Usage;\n#else\n                    throw UsageError(\"longseparator can not be set to empty\");\n#endif\n                } else\n                {\n                    this->longseparator = longseparator_;\n                }\n            }\n\n            /** The terminator that forcibly separates flags from positionals\n             */\n            const std::string &Terminator() const\n            { return terminator; }\n            /** The terminator that forcibly separates flags from positionals\n             */\n            void Terminator(const std::string &terminator_)\n            { this->terminator = terminator_; }\n\n            /** Get the current argument separation parameters.\n             *\n             * See SetArgumentSeparations for details on what each one means.\n             */\n            void GetArgumentSeparations(\n                bool &allowJoinedShortValue_,\n                bool &allowJoinedLongValue_,\n                bool &allowSeparateShortValue_,\n                bool &allowSeparateLongValue_) const\n            {\n                allowJoinedShortValue_ = this->allowJoinedShortValue;\n                allowJoinedLongValue_ = this->allowJoinedLongValue;\n                allowSeparateShortValue_ = this->allowSeparateShortValue;\n                allowSeparateLongValue_ = this->allowSeparateLongValue;\n            }\n\n            /** Change allowed option separation.\n             *\n             * \\param allowJoinedShortValue Allow a short flag that accepts an argument to be passed its argument immediately next to it (ie. in the same argv field)\n             * \\param allowJoinedLongValue Allow a long flag that accepts an argument to be passed its argument separated by the longseparator (ie. in the same argv field)\n             * \\param allowSeparateShortValue Allow a short flag that accepts an argument to be passed its argument separated by whitespace (ie. in the next argv field)\n             * \\param allowSeparateLongValue Allow a long flag that accepts an argument to be passed its argument separated by whitespace (ie. in the next argv field)\n             */\n            void SetArgumentSeparations(\n                const bool allowJoinedShortValue_,\n                const bool allowJoinedLongValue_,\n                const bool allowSeparateShortValue_,\n                const bool allowSeparateLongValue_)\n            {\n                this->allowJoinedShortValue = allowJoinedShortValue_;\n                this->allowJoinedLongValue = allowJoinedLongValue_;\n                this->allowSeparateShortValue = allowSeparateShortValue_;\n                this->allowSeparateLongValue = allowSeparateLongValue_;\n            }\n\n            /** Pass the help menu into an ostream\n             */\n            void Help(std::ostream &help) const\n            {\n                bool hasoptions = false;\n                bool hasarguments = false;\n\n                const auto description_text = Wrap(this->description, helpParams.width - helpParams.descriptionindent);\n                const auto epilog_text = Wrap(this->epilog, helpParams.width - helpParams.descriptionindent);\n                std::ostringstream prognameline;\n                prognameline << prog;\n                if (HasFlag())\n                {\n                    hasoptions = true;\n                    if (helpParams.showProglineOptions)\n                    {\n                        prognameline << \" {OPTIONS}\";\n                    }\n                }\n                for (const std::string &posname: GetPosNames())\n                {\n                    hasarguments = true;\n                    if (helpParams.showProglinePositionals)\n                    {\n                        prognameline << \" [\" << posname << ']';\n                    }\n                }\n                if (!proglinePostfix.empty())\n                {\n                    prognameline << ' ' << proglinePostfix;\n                }\n                const auto proglines = Wrap(prognameline.str(), helpParams.width - (helpParams.progindent + 4), helpParams.width - helpParams.progindent);\n                auto progit = std::begin(proglines);\n                if (progit != std::end(proglines))\n                {\n                    help << std::string(helpParams.progindent, ' ') << *progit << '\\n';\n                    ++progit;\n                }\n                for (; progit != std::end(proglines); ++progit)\n                {\n                    help << std::string(helpParams.progtailindent, ' ') << *progit << '\\n';\n                }\n\n                help << '\\n';\n\n                for (const auto &line: description_text)\n                {\n                    help << std::string(helpParams.descriptionindent, ' ') << line << \"\\n\";\n                }\n                help << \"\\n\";\n                help << std::string(helpParams.progindent, ' ') << \"OPTIONS:\\n\\n\";\n                for (const auto &desc: GetChildDescriptions(shortprefix, longprefix, allowJoinedShortValue ? \"\" : \" \", allowJoinedLongValue ? longseparator : \" \"))\n                {\n                    const auto groupindent = std::get<2>(desc) * helpParams.eachgroupindent;\n                    const auto flags = Wrap(std::get<0>(desc), helpParams.width - (helpParams.flagindent + helpParams.helpindent + helpParams.gutter));\n                    const auto info = Wrap(std::get<1>(desc), helpParams.width - (helpParams.helpindent + groupindent));\n\n                    std::string::size_type flagssize = 0;\n                    for (auto flagsit = std::begin(flags); flagsit != std::end(flags); ++flagsit)\n                    {\n                        if (flagsit != std::begin(flags))\n                        {\n                            help << '\\n';\n                        }\n                        help << std::string(groupindent + helpParams.flagindent, ' ') << *flagsit;\n                        flagssize = Glyphs(*flagsit);\n                    }\n\n                    auto infoit = std::begin(info);\n                    // groupindent is on both sides of this inequality, and therefore can be removed\n                    if ((helpParams.flagindent + flagssize + helpParams.gutter) > helpParams.helpindent || infoit == std::end(info))\n                    {\n                        help << '\\n';\n                    } else\n                    {\n                        // groupindent is on both sides of the minus sign, and therefore doesn't actually need to be in here\n                        help << std::string(helpParams.helpindent - (helpParams.flagindent + flagssize), ' ') << *infoit << '\\n';\n                        ++infoit;\n                    }\n                    for (; infoit != std::end(info); ++infoit)\n                    {\n                        help << std::string(groupindent + helpParams.helpindent, ' ') << *infoit << '\\n';\n                    }\n                }\n                if (hasoptions && hasarguments && helpParams.showTerminator)\n                {\n                    for (const auto &item: Wrap(std::string(\"\\\"\") + terminator + \"\\\" can be used to terminate flag options and force all following arguments to be treated as positional options\", helpParams.width - helpParams.flagindent))\n                    {\n                        help << std::string(helpParams.flagindent, ' ') << item << '\\n';\n                    }\n                }\n\n                help << \"\\n\";\n                for (const auto &line: epilog_text)\n                {\n                    help << std::string(helpParams.descriptionindent, ' ') << line << \"\\n\";\n                }\n            }\n\n            /** Generate a help menu as a string.\n             *\n             * \\return the help text as a single string\n             */\n            std::string Help() const\n            {\n                std::ostringstream help;\n                Help(help);\n                return help.str();\n            }\n\n            /** Parse all arguments.\n             *\n             * \\param begin an iterator to the beginning of the argument list\n             * \\param end an iterator to the past-the-end element of the argument list\n             * \\return the iterator after the last parsed value.  Only useful for kick-out\n             */\n            template <typename It>\n            It ParseArgs(It begin, It end)\n            {\n                // Reset all Matched statuses and errors\n                Reset();\n                bool terminated = false;\n\n                // Check all arg chunks\n                for (auto it = begin; it != end; ++it)\n                {\n                    const auto &chunk = *it;\n\n                    if (!terminated && chunk == terminator)\n                    {\n                        terminated = true;\n                    // If a long arg was found\n                    } else if (!terminated && chunk.find(longprefix) == 0 && chunk.size() > longprefix.size())\n                    {\n                        const auto argchunk = chunk.substr(longprefix.size());\n                        // Try to separate it, in case of a separator:\n                        const auto separator = longseparator.empty() ? argchunk.npos : argchunk.find(longseparator);\n                        // If the separator is in the argument, separate it.\n                        const auto arg = (separator != argchunk.npos ?\n                            std::string(argchunk, 0, separator)\n                            : argchunk);\n\n                        if (auto base = Match(arg))\n                        {\n                            if (auto argbase = dynamic_cast<ValueFlagBase *>(base))\n                            {\n                                if (separator != argchunk.npos)\n                                {\n                                    if (allowJoinedLongValue)\n                                    {\n                                        argbase->ParseValue(argchunk.substr(separator + longseparator.size()));\n                                    } else\n                                    {\n#ifdef ARGS_NOEXCEPT\n                                        error = Error::Parse;\n                                        return it;\n#else\n                                        std::ostringstream problem;\n                                        problem << \"Flag '\" << arg << \"' was passed a joined argument, but these are disallowed\";\n                                        throw ParseError(problem.str());\n#endif\n                                    }\n                                } else\n                                {\n                                    ++it;\n                                    if (it == end)\n                                    {\n#ifdef ARGS_NOEXCEPT\n                                        error = Error::Parse;\n                                        return it;\n#else\n                                        std::ostringstream problem;\n                                        problem << \"Flag '\" << arg << \"' requires an argument but received none\";\n                                        throw ParseError(problem.str());\n#endif\n                                    }\n\n                                    if (allowSeparateLongValue)\n                                    {\n                                        argbase->ParseValue(*it);\n                                    } else\n                                    {\n#ifdef ARGS_NOEXCEPT\n                                        error = Error::Parse;\n                                        return it;\n#else\n                                        std::ostringstream problem;\n                                        problem << \"Flag '\" << arg << \"' was passed a separate argument, but these are disallowed\";\n                                        throw ParseError(problem.str());\n#endif\n                                    }\n                                }\n                            } else if (separator != argchunk.npos)\n                            {\n#ifdef ARGS_NOEXCEPT\n                                error = Error::Parse;\n                                return it;\n#else\n                                std::ostringstream problem;\n                                problem << \"Passed an argument into a non-argument flag: \" << chunk;\n                                throw ParseError(problem.str());\n#endif\n                            }\n\n                            if (base->KickOut())\n                            {\n                                return ++it;\n                            }\n                        } else\n                        {\n#ifdef ARGS_NOEXCEPT\n                            error = Error::Parse;\n                            return it;\n#else\n                            std::ostringstream problem;\n                            problem << \"Flag could not be matched: \" << arg;\n                            throw ParseError(problem.str());\n#endif\n                        }\n                        // Check short args\n                    } else if (!terminated && chunk.find(shortprefix) == 0 && chunk.size() > shortprefix.size())\n                    {\n                        const auto argchunk = chunk.substr(shortprefix.size());\n                        for (auto argit = std::begin(argchunk); argit != std::end(argchunk); ++argit)\n                        {\n                            const auto arg = *argit;\n\n                            if (auto base = Match(arg))\n                            {\n                                if (auto argbase = dynamic_cast<ValueFlagBase *>(base))\n                                {\n                                    const std::string value(++argit, std::end(argchunk));\n                                    if (!value.empty())\n                                    {\n                                        if (allowJoinedShortValue)\n                                        {\n                                            argbase->ParseValue(value);\n                                        } else\n                                        {\n#ifdef ARGS_NOEXCEPT\n                                            error = Error::Parse;\n                                            return it;\n#else\n                                            std::ostringstream problem;\n                                            problem << \"Flag '\" << arg << \"' was passed a joined argument, but these are disallowed\";\n                                            throw ParseError(problem.str());\n#endif\n                                        }\n                                    } else\n                                    {\n                                        ++it;\n                                        if (it == end)\n                                        {\n#ifdef ARGS_NOEXCEPT\n                                            error = Error::Parse;\n                                            return it;\n#else\n                                            std::ostringstream problem;\n                                            problem << \"Flag '\" << arg << \"' requires an argument but received none\";\n                                            throw ParseError(problem.str());\n#endif\n                                        }\n\n                                        if (allowSeparateShortValue)\n                                        {\n                                            argbase->ParseValue(*it);\n                                        } else\n                                        {\n#ifdef ARGS_NOEXCEPT\n                                            error = Error::Parse;\n                                            return it;\n#else\n                                            std::ostringstream problem;\n                                            problem << \"Flag '\" << arg << \"' was passed a separate argument, but these are disallowed\";\n                                            throw ParseError(problem.str());\n#endif\n                                        }\n                                    }\n                                    // Because this argchunk is done regardless\n                                    break;\n                                }\n\n                                if (base->KickOut())\n                                {\n                                    return ++it;\n                                }\n                            } else\n                            {\n#ifdef ARGS_NOEXCEPT\n                                error = Error::Parse;\n                                return it;\n#else\n                                std::ostringstream problem;\n                                problem << \"Flag could not be matched: '\" << arg << \"'\";\n                                throw ParseError(problem.str());\n#endif\n                            }\n                        }\n                    } else\n                    {\n                        auto pos = GetNextPositional();\n                        if (pos)\n                        {\n                            pos->ParseValue(chunk);\n\n                            if (pos->KickOut())\n                            {\n                                return ++it;\n                            }\n                        } else\n                        {\n#ifdef ARGS_NOEXCEPT\n                            error = Error::Parse;\n                            return it;\n#else\n                            std::ostringstream problem;\n                            problem << \"Passed in argument, but no positional arguments were ready to receive it: \" << chunk;\n                            throw ParseError(problem.str());\n#endif\n                        }\n                    }\n                }\n                if (!Matched())\n                {\n#ifdef ARGS_NOEXCEPT\n                    error = Error::Validation;\n#else\n                    std::ostringstream problem;\n                    problem << \"Group validation failed somewhere!\";\n                    throw ValidationError(problem.str());\n#endif\n                }\n                return end;\n            }\n\n            /** Parse all arguments.\n             *\n             * \\param args an iterable of the arguments\n             * \\return the iterator after the last parsed value.  Only useful for kick-out\n             */\n            template <typename T>\n            auto ParseArgs(const T &args) -> decltype(std::begin(args))\n            {\n                return ParseArgs(std::begin(args), std::end(args));\n            }\n\n            /** Convenience function to parse the CLI from argc and argv\n             *\n             * Just assigns the program name and vectorizes arguments for passing into ParseArgs()\n             *\n             * \\return whether or not all arguments were parsed.  This works for detecting kick-out, but is generally useless as it can't do anything with it.\n             */\n            bool ParseCLI(const int argc, const char * const * argv)\n            {\n                if (prog.empty())\n                {\n                    prog.assign(argv[0]);\n                }\n                const std::vector<std::string> args(argv + 1, argv + argc);\n                return ParseArgs(args) == std::end(args);\n            }\n    };\n\n    std::ostream &operator<<(std::ostream &os, const ArgumentParser &parser)\n    {\n        parser.Help(os);\n        return os;\n    }\n\n    /** Boolean argument matcher\n     */\n    class Flag : public FlagBase\n    {\n        public:\n            Flag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const bool extraError_ = false): FlagBase(name_, help_, std::move(matcher_), extraError_)\n            {\n                group_.Add(*this);\n            }\n\n            virtual ~Flag() {}\n\n            /** Get whether this was matched\n             */\n            bool Get() const\n            {\n                return Matched();\n            }\n    };\n\n    /** Help flag class\n     *\n     * Works like a regular flag, but throws an instance of Help when it is matched\n     */\n    class HelpFlag : public Flag\n    {\n        public:\n            HelpFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_): Flag(group_, name_, help_, std::move(matcher_)) {}\n\n            virtual ~HelpFlag() {}\n\n            virtual FlagBase *Match(const std::string &arg) override\n            {\n                if (FlagBase::Match(arg))\n                {\n#ifdef ARGS_NOEXCEPT\n                    error = Error::Help;\n#else\n                    throw Help(arg);\n#endif\n                    return this;\n                }\n                return nullptr;\n            }\n\n            virtual FlagBase *Match(const char arg) override\n            {\n                if (FlagBase::Match(arg))\n                {\n#ifdef ARGS_NOEXCEPT\n                    error = Error::Help;\n#else\n                    throw Help(std::string(1, arg));\n#endif\n                    return this;\n                }\n                return nullptr;\n            }\n\n            /** Get whether this was matched\n             */\n            bool Get() const noexcept\n            {\n                return Matched();\n            }\n    };\n\n    /** A flag class that simply counts the number of times it's matched\n     */\n    class CounterFlag : public Flag\n    {\n        private:\n            const int startcount;\n            int count;\n\n        public:\n            CounterFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const int startcount_ = 0): Flag(group_, name_, help_, std::move(matcher_)), startcount(startcount_), count(startcount_) {}\n\n            virtual ~CounterFlag() {}\n\n            virtual FlagBase *Match(const std::string &arg) override\n            {\n                auto me = FlagBase::Match(arg);\n                if (me)\n                {\n                    ++count;\n                }\n                return me;\n            }\n\n            virtual FlagBase *Match(const char arg) override\n            {\n                auto me = FlagBase::Match(arg);\n                if (me)\n                {\n                    ++count;\n                }\n                return me;\n            }\n\n            /** Get the count\n             */\n            int &Get() noexcept\n            {\n                return count;\n            }\n\n            virtual void Reset() noexcept override\n            {\n                FlagBase::Reset();\n                count = startcount;\n            }\n    };\n\n    /** A default Reader class for argument classes\n     *\n     * Simply uses a std::istringstream to read into the destination type, and\n     * raises a ParseError if there are any characters left.\n     */\n    template <typename T>\n    struct ValueReader\n    {\n        bool operator ()(const std::string &name, const std::string &value, T &destination)\n        {\n            std::istringstream ss(value);\n            ss >> destination;\n\n            if (ss.rdbuf()->in_avail() > 0)\n            {\n#ifdef ARGS_NOEXCEPT\n                return false;\n#else\n                std::ostringstream problem;\n                problem << \"Argument '\" << name << \"' received invalid value type '\" << value << \"'\";\n                throw ParseError(problem.str());\n#endif\n            }\n            return true;\n        }\n    };\n\n    /** std::string specialization for ValueReader\n     *\n     * By default, stream extraction into a string splits on white spaces, and\n     * it is more efficient to ust copy a string into the destination.\n     */\n    template <>\n    struct ValueReader<std::string>\n    {\n        bool operator()(const std::string &name, const std::string &value, std::string &destination)\n        {\n            destination.assign(value);\n            return true;\n        }\n    };\n\n    /** An argument-accepting flag class\n     * \n     * \\tparam T the type to extract the argument as\n     * \\tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)\n     */\n    template <\n        typename T,\n        typename Reader = ValueReader<T>>\n    class ValueFlag : public ValueFlagBase\n    {\n        private:\n            T value;\n            Reader reader;\n\n        public:\n\n            ValueFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const T &defaultValue_ = T(), const bool extraError_ = false): ValueFlagBase(name_, help_, std::move(matcher_), extraError_), value(defaultValue_)\n            {\n                group_.Add(*this);\n            }\n\n            virtual ~ValueFlag() {}\n\n            virtual void ParseValue(const std::string &value_) override\n            {\n#ifdef ARGS_NOEXCEPT\n                if (!reader(name, value_, this->value))\n                {\n                    error = Error::Parse;\n                }\n#else\n                reader(name, value_, this->value);\n#endif\n            }\n\n            /** Get the value\n             */\n            T &Get() noexcept\n            {\n                return value;\n            }\n    };\n\n    /** An argument-accepting flag class that pushes the found values into a list\n     * \n     * \\tparam T the type to extract the argument as\n     * \\tparam List the list type that houses the values\n     * \\tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)\n     */\n    template <\n        typename T,\n        template <typename...> class List = std::vector,\n        typename Reader = ValueReader<T>>\n    class ValueFlagList : public ValueFlagBase\n    {\n        private:\n            List<T> values;\n            Reader reader;\n\n        public:\n\n            ValueFlagList(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const List<T> &defaultValues_ = List<T>()): ValueFlagBase(name_, help_, std::move(matcher_)), values(defaultValues_)\n            {\n                group_.Add(*this);\n            }\n\n            virtual ~ValueFlagList() {}\n\n            virtual void ParseValue(const std::string &value_) override\n            {\n                T v;\n#ifdef ARGS_NOEXCEPT\n                if (!reader(name, value_, v))\n                {\n                    error = Error::Parse;\n                }\n#else\n                reader(name, value_, v);\n#endif\n                values.insert(std::end(values), v);\n            }\n\n            /** Get the values\n             */\n            List<T> &Get() noexcept\n            {\n                return values;\n            }\n\n            virtual std::string Name() const override\n            {\n                return name + std::string(\"...\");\n            }\n\n            virtual void Reset() noexcept override\n            {\n                ValueFlagBase::Reset();\n                values.clear();\n            }\n    };\n\n    /** A mapping value flag class\n     * \n     * \\tparam K the type to extract the argument as\n     * \\tparam T the type to store the result as\n     * \\tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)\n     * \\tparam Map The Map type.  Should operate like std::map or std::unordered_map\n     */\n    template <\n        typename K,\n        typename T,\n        typename Reader = ValueReader<K>,\n        template <typename...> class Map = std::unordered_map>\n    class MapFlag : public ValueFlagBase\n    {\n        private:\n            const Map<K, T> map;\n            T value;\n            Reader reader;\n\n        public:\n\n            MapFlag(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const Map<K, T> &map_, const T &defaultValue_ = T(), const bool extraError_ = false): ValueFlagBase(name_, help_, std::move(matcher_), extraError_), map(map_), value(defaultValue_)\n            {\n                group_.Add(*this);\n            }\n\n            virtual ~MapFlag() {}\n\n            virtual void ParseValue(const std::string &value_) override\n            {\n                K key;\n#ifdef ARGS_NOEXCEPT\n                if (!reader(name, value_, key))\n                {\n                    error = Error::Parse;\n                }\n#else\n                reader(name, value_, key);\n#endif\n                auto it = map.find(key);\n                if (it == std::end(map))\n                {\n#ifdef ARGS_NOEXCEPT\n                    error = Error::Map;\n#else\n                    std::ostringstream problem;\n                    problem << \"Could not find key '\" << key << \"' in map for arg '\" << name << \"'\";\n                    throw MapError(problem.str());\n#endif\n                } else\n                {\n                    this->value = it->second;\n                }\n            }\n\n            /** Get the value\n             */\n            T &Get() noexcept\n            {\n                return value;\n            }\n    };\n\n    /** A mapping value flag list class\n     * \n     * \\tparam K the type to extract the argument as\n     * \\tparam T the type to store the result as\n     * \\tparam List the list type that houses the values\n     * \\tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)\n     * \\tparam Map The Map type.  Should operate like std::map or std::unordered_map\n     */\n    template <\n        typename K,\n        typename T,\n        template <typename...> class List = std::vector,\n        typename Reader = ValueReader<K>,\n        template <typename...> class Map = std::unordered_map>\n    class MapFlagList : public ValueFlagBase\n    {\n        private:\n            const Map<K, T> map;\n            List<T> values;\n            Reader reader;\n\n        public:\n\n            MapFlagList(Group &group_, const std::string &name_, const std::string &help_, Matcher &&matcher_, const Map<K, T> &map_, const List<T> &defaultValues_ = List<T>()): ValueFlagBase(name_, help_, std::move(matcher_)), map(map_), values(defaultValues_)\n            {\n                group_.Add(*this);\n            }\n\n            virtual ~MapFlagList() {}\n\n            virtual void ParseValue(const std::string &value) override\n            {\n                K key;\n#ifdef ARGS_NOEXCEPT\n                if (!reader(name, value, key))\n                {\n                    error = Error::Parse;\n                }\n#else\n                reader(name, value, key);\n#endif\n                auto it = map.find(key);\n                if (it == std::end(map))\n                {\n#ifdef ARGS_NOEXCEPT\n                    error = Error::Map;\n#else\n                    std::ostringstream problem;\n                    problem << \"Could not find key '\" << key << \"' in map for arg '\" << name << \"'\";\n                    throw MapError(problem.str());\n#endif\n                } else\n                {\n                    this->values.emplace_back(it->second);\n                }\n            }\n\n            /** Get the value\n             */\n            List<T> &Get() noexcept\n            {\n                return values;\n            }\n\n            virtual std::string Name() const override\n            {\n                return name + std::string(\"...\");\n            }\n\n            virtual void Reset() noexcept override\n            {\n                ValueFlagBase::Reset();\n                values.clear();\n            }\n    };\n\n    /** A positional argument class\n     *\n     * \\tparam T the type to extract the argument as\n     * \\tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)\n     */\n    template <\n        typename T,\n        typename Reader = ValueReader<T>>\n    class Positional : public PositionalBase\n    {\n        private:\n            T value;\n            Reader reader;\n        public:\n            Positional(Group &group_, const std::string &name_, const std::string &help_, const T &defaultValue_ = T()): PositionalBase(name_, help_), value(defaultValue_)\n            {\n                group_.Add(*this);\n            }\n\n            virtual ~Positional() {}\n\n            virtual void ParseValue(const std::string &value_) override\n            {\n#ifdef ARGS_NOEXCEPT\n                if (!reader(name, value_, this->value))\n                {\n                    error = Error::Parse;\n                }\n#else\n                reader(name, value_, this->value);\n#endif\n                ready = false;\n                matched = true;\n            }\n\n            /** Get the value\n             */\n            T &Get() noexcept\n            {\n                return value;\n            }\n    };\n\n    /** A positional argument class that pushes the found values into a list\n     * \n     * \\tparam T the type to extract the argument as\n     * \\tparam List the list type that houses the values\n     * \\tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)\n     */\n    template <\n        typename T,\n        template <typename...> class List = std::vector,\n        typename Reader = ValueReader<T>>\n    class PositionalList : public PositionalBase\n    {\n        private:\n            List<T> values;\n            Reader reader;\n\n        public:\n            PositionalList(Group &group_, const std::string &name_, const std::string &help_, const List<T> &defaultValues_ = List<T>()): PositionalBase(name_, help_), values(defaultValues_)\n            {\n                group_.Add(*this);\n            }\n\n            virtual ~PositionalList() {}\n\n            virtual void ParseValue(const std::string &value_) override\n            {\n                T v;\n#ifdef ARGS_NOEXCEPT\n                if (!reader(name, value_, v))\n                {\n                    error = Error::Parse;\n                }\n#else\n                reader(name, value_, v);\n#endif\n                values.insert(std::end(values), v);\n                matched = true;\n            }\n\n            virtual std::string Name() const override\n            {\n                return name + std::string(\"...\");\n            }\n\n            /** Get the values\n             */\n            List<T> &Get() noexcept\n            {\n                return values;\n            }\n\n            virtual void Reset() noexcept override\n            {\n                PositionalBase::Reset();\n                values.clear();\n            }\n    };\n\n    /** A positional argument mapping class\n     * \n     * \\tparam K the type to extract the argument as\n     * \\tparam T the type to store the result as\n     * \\tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)\n     * \\tparam Map The Map type.  Should operate like std::map or std::unordered_map\n     */\n    template <\n        typename K,\n        typename T,\n        typename Reader = ValueReader<K>,\n        template <typename...> class Map = std::unordered_map>\n    class MapPositional : public PositionalBase\n    {\n        private:\n            const Map<K, T> map;\n            T value;\n            Reader reader;\n\n        public:\n\n            MapPositional(Group &group_, const std::string &name_, const std::string &help_, const Map<K, T> &map_, const T &defaultValue_ = T()): PositionalBase(name_, help_), map(map_), value(defaultValue_)\n            {\n                group_.Add(*this);\n            }\n\n            virtual ~MapPositional() {}\n\n            virtual void ParseValue(const std::string &value_) override\n            {\n                K key;\n#ifdef ARGS_NOEXCEPT\n                if (!reader(name, value_, key))\n                {\n                    error = Error::Parse;\n                }\n#else\n                reader(name, value_, key);\n#endif\n                auto it = map.find(key);\n                if (it == std::end(map))\n                {\n#ifdef ARGS_NOEXCEPT\n                    error = Error::Map;\n#else\n                    std::ostringstream problem;\n                    problem << \"Could not find key '\" << key << \"' in map for arg '\" << name << \"'\";\n                    throw MapError(problem.str());\n#endif\n                } else\n                {\n                    this->value = it->second;\n                    ready = false;\n                    matched = true;\n                }\n            }\n\n            /** Get the value\n             */\n            T &Get() noexcept\n            {\n                return value;\n            }\n    };\n\n    /** A positional argument mapping list class\n     * \n     * \\tparam K the type to extract the argument as\n     * \\tparam T the type to store the result as\n     * \\tparam List the list type that houses the values\n     * \\tparam Reader The functor type used to read the argument, taking the name, value, and destination reference with operator(), and returning a bool (if ARGS_NOEXCEPT is defined)\n     * \\tparam Map The Map type.  Should operate like std::map or std::unordered_map\n     */\n    template <\n        typename K,\n        typename T,\n        template <typename...> class List = std::vector,\n        typename Reader = ValueReader<K>,\n        template <typename...> class Map = std::unordered_map>\n    class MapPositionalList : public PositionalBase\n    {\n        private:\n            const Map<K, T> map;\n            List<T> values;\n            Reader reader;\n\n        public:\n\n            MapPositionalList(Group &group_, const std::string &name_, const std::string &help_, const Map<K, T> &map_, const List<T> &defaultValues_ = List<T>()): PositionalBase(name_, help_), map(map_), values(defaultValues_)\n            {\n                group_.Add(*this);\n            }\n\n            virtual ~MapPositionalList() {}\n\n            virtual void ParseValue(const std::string &value_) override\n            {\n                K key;\n#ifdef ARGS_NOEXCEPT\n                if (!reader(name, value_, key))\n                {\n                    error = Error::Parse;\n                }\n#else\n                reader(name, value_, key);\n#endif\n                auto it = map.find(key);\n                if (it == std::end(map))\n                {\n#ifdef ARGS_NOEXCEPT\n                    error = Error::Map;\n#else\n                    std::ostringstream problem;\n                    problem << \"Could not find key '\" << key << \"' in map for arg '\" << name << \"'\";\n                    throw MapError(problem.str());\n#endif\n                } else\n                {\n                    this->values.emplace_back(it->second);\n                    matched = true;\n                }\n            }\n\n            /** Get the value\n             */\n            List<T> &Get() noexcept\n            {\n                return values;\n            }\n\n            virtual std::string Name() const override\n            {\n                return name + std::string(\"...\");\n            }\n\n            virtual void Reset() noexcept override\n            {\n                PositionalBase::Reset();\n                values.clear();\n            }\n    };\n}\n\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/ext/headers/catch.hpp",
    "content": "/*\n *  Catch v2.7.0\n *  Generated: 2019-03-07 21:34:30.252164\n *  ----------------------------------------------------------\n *  This file has been merged from multiple headers. Please don't edit it directly\n *  Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved.\n *\n *  Distributed under the Boost Software License, Version 1.0. (See accompanying\n *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n */\n#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n// start catch.hpp\n\n\n#define CATCH_VERSION_MAJOR 2\n#define CATCH_VERSION_MINOR 7\n#define CATCH_VERSION_PATCH 0\n\n#ifdef __clang__\n#    pragma clang system_header\n#elif defined __GNUC__\n#    pragma GCC system_header\n#endif\n\n// start catch_suppress_warnings.h\n\n#ifdef __clang__\n#   ifdef __ICC // icpc defines the __clang__ macro\n#       pragma warning(push)\n#       pragma warning(disable: 161 1682)\n#   else // __ICC\n#       pragma clang diagnostic push\n#       pragma clang diagnostic ignored \"-Wpadded\"\n#       pragma clang diagnostic ignored \"-Wswitch-enum\"\n#       pragma clang diagnostic ignored \"-Wcovered-switch-default\"\n#    endif\n#elif defined __GNUC__\n     // Because REQUIREs trigger GCC's -Wparentheses, and because still\n     // supported version of g++ have only buggy support for _Pragmas,\n     // Wparentheses have to be suppressed globally.\n#    pragma GCC diagnostic ignored \"-Wparentheses\" // See #674 for details\n\n#    pragma GCC diagnostic push\n#    pragma GCC diagnostic ignored \"-Wunused-variable\"\n#    pragma GCC diagnostic ignored \"-Wpadded\"\n#endif\n// end catch_suppress_warnings.h\n#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)\n#  define CATCH_IMPL\n#  define CATCH_CONFIG_ALL_PARTS\n#endif\n\n// In the impl file, we want to have access to all parts of the headers\n// Can also be used to sanely support PCHs\n#if defined(CATCH_CONFIG_ALL_PARTS)\n#  define CATCH_CONFIG_EXTERNAL_INTERFACES\n#  if defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#    undef CATCH_CONFIG_DISABLE_MATCHERS\n#  endif\n#  if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)\n#    define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER\n#  endif\n#endif\n\n#if !defined(CATCH_CONFIG_IMPL_ONLY)\n// start catch_platform.h\n\n#ifdef __APPLE__\n# include <TargetConditionals.h>\n# if TARGET_OS_OSX == 1\n#  define CATCH_PLATFORM_MAC\n# elif TARGET_OS_IPHONE == 1\n#  define CATCH_PLATFORM_IPHONE\n# endif\n\n#elif defined(linux) || defined(__linux) || defined(__linux__)\n#  define CATCH_PLATFORM_LINUX\n\n#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)\n#  define CATCH_PLATFORM_WINDOWS\n#endif\n\n// end catch_platform.h\n\n#ifdef CATCH_IMPL\n#  ifndef CLARA_CONFIG_MAIN\n#    define CLARA_CONFIG_MAIN_NOT_DEFINED\n#    define CLARA_CONFIG_MAIN\n#  endif\n#endif\n\n// start catch_user_interfaces.h\n\nnamespace Catch {\n    unsigned int rngSeed();\n}\n\n// end catch_user_interfaces.h\n// start catch_tag_alias_autoregistrar.h\n\n// start catch_common.h\n\n// start catch_compiler_capabilities.h\n\n// Detect a number of compiler features - by compiler\n// The following features are defined:\n//\n// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?\n// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?\n// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?\n// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?\n// ****************\n// Note to maintainers: if new toggles are added please document them\n// in configuration.md, too\n// ****************\n\n// In general each macro has a _NO_<feature name> form\n// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.\n// Many features, at point of detection, define an _INTERNAL_ macro, so they\n// can be combined, en-mass, with the _NO_ forms later.\n\n#ifdef __cplusplus\n\n#  if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)\n#    define CATCH_CPP14_OR_GREATER\n#  endif\n\n#  if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)\n#    define CATCH_CPP17_OR_GREATER\n#  endif\n\n#endif\n\n#if defined(CATCH_CPP17_OR_GREATER)\n#  define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS\n#endif\n\n#ifdef __clang__\n\n#       define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \\\n            _Pragma( \"clang diagnostic push\" ) \\\n            _Pragma( \"clang diagnostic ignored \\\"-Wexit-time-destructors\\\"\" ) \\\n            _Pragma( \"clang diagnostic ignored \\\"-Wglobal-constructors\\\"\")\n#       define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \\\n            _Pragma( \"clang diagnostic pop\" )\n\n#       define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \\\n            _Pragma( \"clang diagnostic push\" ) \\\n            _Pragma( \"clang diagnostic ignored \\\"-Wparentheses\\\"\" )\n#       define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \\\n            _Pragma( \"clang diagnostic pop\" )\n\n#       define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \\\n            _Pragma( \"clang diagnostic push\" ) \\\n            _Pragma( \"clang diagnostic ignored \\\"-Wunused-variable\\\"\" )\n#       define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \\\n            _Pragma( \"clang diagnostic pop\" )\n\n#endif // __clang__\n\n////////////////////////////////////////////////////////////////////////////////\n// Assume that non-Windows platforms support posix signals by default\n#if !defined(CATCH_PLATFORM_WINDOWS)\n    #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// We know some environments not to support full POSIX signals\n#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)\n    #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS\n#endif\n\n#ifdef __OS400__\n#       define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS\n#       define CATCH_CONFIG_COLOUR_NONE\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// Android somehow still does not support std::to_string\n#if defined(__ANDROID__)\n#    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// Not all Windows environments support SEH properly\n#if defined(__MINGW32__)\n#    define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// PS4\n#if defined(__ORBIS__)\n#    define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// Cygwin\n#ifdef __CYGWIN__\n\n// Required for some versions of Cygwin to declare gettimeofday\n// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin\n#   define _BSD_SOURCE\n// some versions of cygwin (most) do not support std::to_string. Use the libstd check.\n// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813\n# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \\\n\t       && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))\n\n#\tdefine CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING\n\n# endif\n#endif // __CYGWIN__\n\n////////////////////////////////////////////////////////////////////////////////\n// Visual C++\n#ifdef _MSC_VER\n\n#  if _MSC_VER >= 1900 // Visual Studio 2015 or newer\n#    define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS\n#  endif\n\n// Universal Windows platform does not support SEH\n// Or console colours (or console at all...)\n#  if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)\n#    define CATCH_CONFIG_COLOUR_NONE\n#  else\n#    define CATCH_INTERNAL_CONFIG_WINDOWS_SEH\n#  endif\n\n// MSVC traditional preprocessor needs some workaround for __VA_ARGS__\n// _MSVC_TRADITIONAL == 0 means new conformant preprocessor\n// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor\n#  if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)\n#    define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n#  endif\n\n#endif // _MSC_VER\n\n////////////////////////////////////////////////////////////////////////////////\n// Check if we are compiled with -fno-exceptions or equivalent\n#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)\n#  define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// DJGPP\n#ifdef __DJGPP__\n#  define CATCH_INTERNAL_CONFIG_NO_WCHAR\n#endif // __DJGPP__\n\n////////////////////////////////////////////////////////////////////////////////\n// Embarcadero C++Build\n#if defined(__BORLANDC__)\n    #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n\n// Use of __COUNTER__ is suppressed during code analysis in\n// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly\n// handled by it.\n// Otherwise all supported compilers support COUNTER macro,\n// but user still might want to turn it off\n#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )\n    #define CATCH_INTERNAL_CONFIG_COUNTER\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// Check if string_view is available and usable\n// The check is split apart to work around v140 (VS2015) preprocessor issue...\n#if defined(__has_include)\n#if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)\n#    define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW\n#endif\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// Check if optional is available and usable\n#if defined(__has_include)\n#  if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)\n#    define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL\n#  endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)\n#endif // __has_include\n\n////////////////////////////////////////////////////////////////////////////////\n// Check if variant is available and usable\n#if defined(__has_include)\n#  if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)\n#    if defined(__clang__) && (__clang_major__ < 8)\n       // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852\n       // fix should be in clang 8, workaround in libstdc++ 8.2\n#      include <ciso646>\n#      if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)\n#        define CATCH_CONFIG_NO_CPP17_VARIANT\n#      else\n#        define CATCH_INTERNAL_CONFIG_CPP17_VARIANT\n#      endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)\n#    else\n#      define CATCH_INTERNAL_CONFIG_CPP17_VARIANT\n#    endif // defined(__clang__) && (__clang_major__ < 8)\n#  endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)\n#endif // __has_include\n\n#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)\n#   define CATCH_CONFIG_COUNTER\n#endif\n#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)\n#   define CATCH_CONFIG_WINDOWS_SEH\n#endif\n// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.\n#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)\n#   define CATCH_CONFIG_POSIX_SIGNALS\n#endif\n// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.\n#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)\n#   define CATCH_CONFIG_WCHAR\n#endif\n\n#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)\n#    define CATCH_CONFIG_CPP11_TO_STRING\n#endif\n\n#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)\n#  define CATCH_CONFIG_CPP17_OPTIONAL\n#endif\n\n#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)\n#  define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS\n#endif\n\n#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)\n#  define CATCH_CONFIG_CPP17_STRING_VIEW\n#endif\n\n#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)\n#  define CATCH_CONFIG_CPP17_VARIANT\n#endif\n\n#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)\n#  define CATCH_INTERNAL_CONFIG_NEW_CAPTURE\n#endif\n\n#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)\n#  define CATCH_CONFIG_NEW_CAPTURE\n#endif\n\n#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)\n#  define CATCH_CONFIG_DISABLE_EXCEPTIONS\n#endif\n\n#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)\n#  define CATCH_CONFIG_POLYFILL_ISNAN\n#endif\n\n#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)\n#   define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS\n#   define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS\n#endif\n#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)\n#   define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS\n#   define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\n#endif\n#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)\n#   define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS\n#   define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS\n#endif\n\n#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)\n#define CATCH_TRY if ((true))\n#define CATCH_CATCH_ALL if ((false))\n#define CATCH_CATCH_ANON(type) if ((false))\n#else\n#define CATCH_TRY try\n#define CATCH_CATCH_ALL catch (...)\n#define CATCH_CATCH_ANON(type) catch (type)\n#endif\n\n#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)\n#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n#endif\n\n// end catch_compiler_capabilities.h\n#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line\n#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )\n#ifdef CATCH_CONFIG_COUNTER\n#  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )\n#else\n#  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )\n#endif\n\n#include <iosfwd>\n#include <string>\n#include <cstdint>\n\n// We need a dummy global operator<< so we can bring it into Catch namespace later\nstruct Catch_global_namespace_dummy {};\nstd::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);\n\nnamespace Catch {\n\n    struct CaseSensitive { enum Choice {\n        Yes,\n        No\n    }; };\n\n    class NonCopyable {\n        NonCopyable( NonCopyable const& )              = delete;\n        NonCopyable( NonCopyable && )                  = delete;\n        NonCopyable& operator = ( NonCopyable const& ) = delete;\n        NonCopyable& operator = ( NonCopyable && )     = delete;\n\n    protected:\n        NonCopyable();\n        virtual ~NonCopyable();\n    };\n\n    struct SourceLineInfo {\n\n        SourceLineInfo() = delete;\n        SourceLineInfo( char const* _file, std::size_t _line ) noexcept\n        :   file( _file ),\n            line( _line )\n        {}\n\n        SourceLineInfo( SourceLineInfo const& other )            = default;\n        SourceLineInfo& operator = ( SourceLineInfo const& )     = default;\n        SourceLineInfo( SourceLineInfo&& )              noexcept = default;\n        SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;\n\n        bool empty() const noexcept;\n        bool operator == ( SourceLineInfo const& other ) const noexcept;\n        bool operator < ( SourceLineInfo const& other ) const noexcept;\n\n        char const* file;\n        std::size_t line;\n    };\n\n    std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );\n\n    // Bring in operator<< from global namespace into Catch namespace\n    // This is necessary because the overload of operator<< above makes\n    // lookup stop at namespace Catch\n    using ::operator<<;\n\n    // Use this in variadic streaming macros to allow\n    //    >> +StreamEndStop\n    // as well as\n    //    >> stuff +StreamEndStop\n    struct StreamEndStop {\n        std::string operator+() const;\n    };\n    template<typename T>\n    T const& operator + ( T const& value, StreamEndStop ) {\n        return value;\n    }\n}\n\n#define CATCH_INTERNAL_LINEINFO \\\n    ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )\n\n// end catch_common.h\nnamespace Catch {\n\n    struct RegistrarForTagAliases {\n        RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );\n    };\n\n} // end namespace Catch\n\n#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \\\n    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \\\n    namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \\\n    CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\n\n// end catch_tag_alias_autoregistrar.h\n// start catch_test_registry.h\n\n// start catch_interfaces_testcase.h\n\n#include <vector>\n\nnamespace Catch {\n\n    class TestSpec;\n\n    struct ITestInvoker {\n        virtual void invoke () const = 0;\n        virtual ~ITestInvoker();\n    };\n\n    class TestCase;\n    struct IConfig;\n\n    struct ITestCaseRegistry {\n        virtual ~ITestCaseRegistry();\n        virtual std::vector<TestCase> const& getAllTests() const = 0;\n        virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;\n    };\n\n    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );\n    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );\n    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );\n\n}\n\n// end catch_interfaces_testcase.h\n// start catch_stringref.h\n\n#include <cstddef>\n#include <string>\n#include <iosfwd>\n\nnamespace Catch {\n\n    /// A non-owning string class (similar to the forthcoming std::string_view)\n    /// Note that, because a StringRef may be a substring of another string,\n    /// it may not be null terminated. c_str() must return a null terminated\n    /// string, however, and so the StringRef will internally take ownership\n    /// (taking a copy), if necessary. In theory this ownership is not externally\n    /// visible - but it does mean (substring) StringRefs should not be shared between\n    /// threads.\n    class StringRef {\n    public:\n        using size_type = std::size_t;\n\n    private:\n        friend struct StringRefTestAccess;\n\n        char const* m_start;\n        size_type m_size;\n\n        char* m_data = nullptr;\n\n        void takeOwnership();\n\n        static constexpr char const* const s_empty = \"\";\n\n    public: // construction/ assignment\n        StringRef() noexcept\n        :   StringRef( s_empty, 0 )\n        {}\n\n        StringRef( StringRef const& other ) noexcept\n        :   m_start( other.m_start ),\n            m_size( other.m_size )\n        {}\n\n        StringRef( StringRef&& other ) noexcept\n        :   m_start( other.m_start ),\n            m_size( other.m_size ),\n            m_data( other.m_data )\n        {\n            other.m_data = nullptr;\n        }\n\n        StringRef( char const* rawChars ) noexcept;\n\n        StringRef( char const* rawChars, size_type size ) noexcept\n        :   m_start( rawChars ),\n            m_size( size )\n        {}\n\n        StringRef( std::string const& stdString ) noexcept\n        :   m_start( stdString.c_str() ),\n            m_size( stdString.size() )\n        {}\n\n        ~StringRef() noexcept {\n            delete[] m_data;\n        }\n\n        auto operator = ( StringRef const &other ) noexcept -> StringRef& {\n            delete[] m_data;\n            m_data = nullptr;\n            m_start = other.m_start;\n            m_size = other.m_size;\n            return *this;\n        }\n\n        operator std::string() const;\n\n        void swap( StringRef& other ) noexcept;\n\n    public: // operators\n        auto operator == ( StringRef const& other ) const noexcept -> bool;\n        auto operator != ( StringRef const& other ) const noexcept -> bool;\n\n        auto operator[] ( size_type index ) const noexcept -> char;\n\n    public: // named queries\n        auto empty() const noexcept -> bool {\n            return m_size == 0;\n        }\n        auto size() const noexcept -> size_type {\n            return m_size;\n        }\n\n        auto numberOfCharacters() const noexcept -> size_type;\n        auto c_str() const -> char const*;\n\n    public: // substrings and searches\n        auto substr( size_type start, size_type size ) const noexcept -> StringRef;\n\n        // Returns the current start pointer.\n        // Note that the pointer can change when if the StringRef is a substring\n        auto currentData() const noexcept -> char const*;\n\n    private: // ownership queries - may not be consistent between calls\n        auto isOwned() const noexcept -> bool;\n        auto isSubstring() const noexcept -> bool;\n    };\n\n    auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string;\n    auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string;\n    auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string;\n\n    auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;\n    auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;\n\n    inline auto operator \"\" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {\n        return StringRef( rawChars, size );\n    }\n\n} // namespace Catch\n\ninline auto operator \"\" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {\n    return Catch::StringRef( rawChars, size );\n}\n\n// end catch_stringref.h\n// start catch_type_traits.hpp\n\n\n#include <type_traits>\n\nnamespace Catch{\n\n#ifdef CATCH_CPP17_OR_GREATER\n\ttemplate <typename...>\n\tinline constexpr auto is_unique = std::true_type{};\n\n\ttemplate <typename T, typename... Rest>\n\tinline constexpr auto is_unique<T, Rest...> = std::bool_constant<\n\t\t(!std::is_same_v<T, Rest> && ...) && is_unique<Rest...>\n\t>{};\n#else\n\ntemplate <typename...>\nstruct is_unique : std::true_type{};\n\ntemplate <typename T0, typename T1, typename... Rest>\nstruct is_unique<T0, T1, Rest...> : std::integral_constant\n<bool,\n     !std::is_same<T0, T1>::value\n     && is_unique<T0, Rest...>::value\n     && is_unique<T1, Rest...>::value\n>{};\n\n#endif\n}\n\n// end catch_type_traits.hpp\n// start catch_preprocessor.hpp\n\n\n#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__\n#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))\n#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))\n#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))\n#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))\n#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))\n\n#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__\n// MSVC needs more evaluations\n#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))\n#define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))\n#else\n#define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL5(__VA_ARGS__)\n#endif\n\n#define CATCH_REC_END(...)\n#define CATCH_REC_OUT\n\n#define CATCH_EMPTY()\n#define CATCH_DEFER(id) id CATCH_EMPTY()\n\n#define CATCH_REC_GET_END2() 0, CATCH_REC_END\n#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2\n#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1\n#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT\n#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)\n#define CATCH_REC_NEXT(test, next)  CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)\n\n#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )\n#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )\n#define CATCH_REC_LIST2(f, x, peek, ...)   f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )\n\n#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )\n#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ )\n#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...)   f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )\n\n// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,\n// and passes userdata as the first parameter to each invocation,\n// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)\n#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))\n\n#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))\n\n#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)\n#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__\n#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__\n#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF\n#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)\n#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__\n#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))\n#else\n// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF\n#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)\n#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__\n#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)\n#endif\n\n#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)\n\n#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, __VA_ARGS__)\n#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name \" - \" #__VA_ARGS__\n#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name,...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))\n#else\n// MSVC is adding extra space and needs more calls to properly remove ()\n#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name \" -\" #__VA_ARGS__\n#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, __VA_ARGS__)\n#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))\n#endif\n\n#define INTERNAL_CATCH_MAKE_TYPE_LIST(types) Catch::TypeList<INTERNAL_CATCH_REMOVE_PARENS(types)>\n\n#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(types)\\\n    CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,INTERNAL_CATCH_REMOVE_PARENS(types))\n\n// end catch_preprocessor.hpp\n// start catch_meta.hpp\n\n\n#include <type_traits>\n\nnamespace Catch {\ntemplate< typename... >\nstruct TypeList {};\n\ntemplate< typename... >\nstruct append;\n\ntemplate< template<typename...> class L1\n    , typename...E1\n    , template<typename...> class L2\n    , typename...E2\n>\nstruct append< L1<E1...>, L2<E2...> > {\n    using type = L1<E1..., E2...>;\n};\n\ntemplate< template<typename...> class L1\n    , typename...E1\n    , template<typename...> class L2\n    , typename...E2\n    , typename...Rest\n>\nstruct append< L1<E1...>, L2<E2...>, Rest...> {\n    using type = typename append< L1<E1..., E2...>, Rest... >::type;\n};\n\ntemplate< template<typename...> class\n    , typename...\n>\nstruct rewrap;\n\ntemplate< template<typename...> class Container\n    , template<typename...> class List\n    , typename...elems\n>\nstruct rewrap<Container, List<elems...>> {\n    using type = TypeList< Container< elems... > >;\n};\n\ntemplate< template<typename...> class Container\n    , template<typename...> class List\n    , class...Elems\n    , typename...Elements>\n    struct rewrap<Container, List<Elems...>, Elements...> {\n    using type = typename append<TypeList<Container<Elems...>>, typename rewrap<Container, Elements...>::type>::type;\n};\n\ntemplate< template<typename...> class...Containers >\nstruct combine {\n    template< typename...Types >\n    struct with_types {\n        template< template <typename...> class Final >\n        struct into {\n            using type = typename append<Final<>, typename rewrap<Containers, Types...>::type...>::type;\n        };\n    };\n};\n\ntemplate<typename T>\nstruct always_false : std::false_type {};\n\n} // namespace Catch\n\n// end catch_meta.hpp\nnamespace Catch {\n\ntemplate<typename C>\nclass TestInvokerAsMethod : public ITestInvoker {\n    void (C::*m_testAsMethod)();\npublic:\n    TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}\n\n    void invoke() const override {\n        C obj;\n        (obj.*m_testAsMethod)();\n    }\n};\n\nauto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*;\n\ntemplate<typename C>\nauto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {\n    return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod );\n}\n\nstruct NameAndTags {\n    NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;\n    StringRef name;\n    StringRef tags;\n};\n\nstruct AutoReg : NonCopyable {\n    AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;\n    ~AutoReg();\n};\n\n} // end namespace Catch\n\n#if defined(CATCH_CONFIG_DISABLE)\n    #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \\\n        static void TestName()\n    #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \\\n        namespace{                        \\\n            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \\\n                void test();              \\\n            };                            \\\n        }                                 \\\n        void TestName::test()\n    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( TestName, ... )  \\\n        template<typename TestType>                                             \\\n        static void TestName()\n    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... )    \\\n        namespace{                                                                                  \\\n            template<typename TestType>                                                             \\\n            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) {     \\\n                void test();                                                                        \\\n            };                                                                                      \\\n        }                                                                                           \\\n        template<typename TestType>                                                                 \\\n        void TestName::test()\n#endif\n\n    ///////////////////////////////////////////////////////////////////////////////\n    #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \\\n        static void TestName(); \\\n        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \\\n        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \\\n        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \\\n        static void TestName()\n    #define INTERNAL_CATCH_TESTCASE( ... ) \\\n        INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )\n\n    ///////////////////////////////////////////////////////////////////////////////\n    #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \\\n        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \\\n        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, \"&\" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \\\n        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\n\n    ///////////////////////////////////////////////////////////////////////////////\n    #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\\\n        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \\\n        namespace{ \\\n            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \\\n                void test(); \\\n            }; \\\n            Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \\\n        } \\\n        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \\\n        void TestName::test()\n    #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \\\n        INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )\n\n    ///////////////////////////////////////////////////////////////////////////////\n    #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \\\n        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \\\n        Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \\\n        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\n\n    ///////////////////////////////////////////////////////////////////////////////\n    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, ... )\\\n        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \\\n        template<typename TestType> \\\n        static void TestFunc();\\\n        namespace {\\\n            template<typename...Types> \\\n            struct TestName{\\\n                template<typename...Ts> \\\n                TestName(Ts...names){\\\n                    CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \\\n                    using expander = int[];\\\n                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \\\n                }\\\n            };\\\n            INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, __VA_ARGS__) \\\n        }\\\n        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \\\n        template<typename TestType> \\\n        static void TestFunc()\n\n#if defined(CATCH_CPP17_OR_GREATER)\n#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>,\"Duplicate type detected in declaration of template test case\");\n#else\n#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>::value,\"Duplicate type detected in declaration of template test case\");\n#endif\n\n#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \\\n        INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ )\n#else\n    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \\\n        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) )\n#endif\n\n    #define INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, ...)\\\n        static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\\\n            TestName<CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)>(CATCH_REC_LIST_UD(INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME,Name, __VA_ARGS__));\\\n            return 0;\\\n        }();\n\n    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, TmplTypes, TypesList) \\\n        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                      \\\n        template<typename TestType> static void TestFuncName();       \\\n        namespace {                                                   \\\n            template<typename... Types>                               \\\n            struct TestName {                                         \\\n                TestName() {                                          \\\n                    CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)       \\\n                    int index = 0;                                    \\\n                    using expander = int[];                           \\\n                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\\\n                    constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\\\n                    constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\\\n                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name \" - \" + std::string(tmpl_types[index / num_types]) + \"<\" + std::string(types_list[index % num_types]) + \">\", Tags } ), index++, 0)... };/* NOLINT */\\\n                }                                                     \\\n            };                                                        \\\n            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \\\n                using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)> \\\n                            ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestName>::type; \\\n                TestInit();                                           \\\n                return 0;                                             \\\n            }();                                                      \\\n        }                                                             \\\n        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS                    \\\n        template<typename TestType>                                   \\\n        static void TestFuncName()\n\n#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\\\n        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ),Name,Tags,__VA_ARGS__)\n#else\n    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\\\n        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) )\n#endif\n\n    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, ... ) \\\n        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \\\n        namespace{ \\\n            template<typename TestType> \\\n            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \\\n                void test();\\\n            };\\\n            template<typename...Types> \\\n            struct TestNameClass{\\\n                template<typename...Ts> \\\n                TestNameClass(Ts...names){\\\n                    CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \\\n                    using expander = int[];\\\n                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \\\n                }\\\n            };\\\n            INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestNameClass, Name, __VA_ARGS__)\\\n        }\\\n        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\\\n        template<typename TestType> \\\n        void TestName<TestType>::test()\n\n#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \\\n        INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ )\n#else\n    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \\\n        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ ) )\n#endif\n\n    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, TmplTypes, TypesList)\\\n        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \\\n        template<typename TestType> \\\n            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \\\n                void test();\\\n            };\\\n        namespace {\\\n            template<typename...Types>\\\n            struct TestNameClass{\\\n                TestNameClass(){\\\n                    CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\\\n                    int index = 0;\\\n                    using expander = int[];\\\n                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\\\n                    constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\\\n                    constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\\\n                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name \" - \" + std::string(tmpl_types[index / num_types]) + \"<\" + std::string(types_list[index % num_types]) + \">\", Tags } ), index++, 0)... };/* NOLINT */ \\\n                }\\\n            };\\\n            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\\\n                using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>\\\n                            ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestNameClass>::type;\\\n                TestInit();\\\n                return 0;\\\n            }(); \\\n        }\\\n        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \\\n        template<typename TestType> \\\n        void TestName<TestType>::test()\n\n#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\\\n        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ )\n#else\n    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\\\n        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ ) )\n#endif\n\n// end catch_test_registry.h\n// start catch_capture.hpp\n\n// start catch_assertionhandler.h\n\n// start catch_assertioninfo.h\n\n// start catch_result_type.h\n\nnamespace Catch {\n\n    // ResultWas::OfType enum\n    struct ResultWas { enum OfType {\n        Unknown = -1,\n        Ok = 0,\n        Info = 1,\n        Warning = 2,\n\n        FailureBit = 0x10,\n\n        ExpressionFailed = FailureBit | 1,\n        ExplicitFailure = FailureBit | 2,\n\n        Exception = 0x100 | FailureBit,\n\n        ThrewException = Exception | 1,\n        DidntThrowException = Exception | 2,\n\n        FatalErrorCondition = 0x200 | FailureBit\n\n    }; };\n\n    bool isOk( ResultWas::OfType resultType );\n    bool isJustInfo( int flags );\n\n    // ResultDisposition::Flags enum\n    struct ResultDisposition { enum Flags {\n        Normal = 0x01,\n\n        ContinueOnFailure = 0x02,   // Failures fail test, but execution continues\n        FalseTest = 0x04,           // Prefix expression with !\n        SuppressFail = 0x08         // Failures are reported but do not fail the test\n    }; };\n\n    ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs );\n\n    bool shouldContinueOnFailure( int flags );\n    inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }\n    bool shouldSuppressFailure( int flags );\n\n} // end namespace Catch\n\n// end catch_result_type.h\nnamespace Catch {\n\n    struct AssertionInfo\n    {\n        StringRef macroName;\n        SourceLineInfo lineInfo;\n        StringRef capturedExpression;\n        ResultDisposition::Flags resultDisposition;\n\n        // We want to delete this constructor but a compiler bug in 4.8 means\n        // the struct is then treated as non-aggregate\n        //AssertionInfo() = delete;\n    };\n\n} // end namespace Catch\n\n// end catch_assertioninfo.h\n// start catch_decomposer.h\n\n// start catch_tostring.h\n\n#include <vector>\n#include <cstddef>\n#include <type_traits>\n#include <string>\n// start catch_stream.h\n\n#include <iosfwd>\n#include <cstddef>\n#include <ostream>\n\nnamespace Catch {\n\n    std::ostream& cout();\n    std::ostream& cerr();\n    std::ostream& clog();\n\n    class StringRef;\n\n    struct IStream {\n        virtual ~IStream();\n        virtual std::ostream& stream() const = 0;\n    };\n\n    auto makeStream( StringRef const &filename ) -> IStream const*;\n\n    class ReusableStringStream {\n        std::size_t m_index;\n        std::ostream* m_oss;\n    public:\n        ReusableStringStream();\n        ~ReusableStringStream();\n\n        auto str() const -> std::string;\n\n        template<typename T>\n        auto operator << ( T const& value ) -> ReusableStringStream& {\n            *m_oss << value;\n            return *this;\n        }\n        auto get() -> std::ostream& { return *m_oss; }\n    };\n}\n\n// end catch_stream.h\n\n#ifdef CATCH_CONFIG_CPP17_STRING_VIEW\n#include <string_view>\n#endif\n\n#ifdef __OBJC__\n// start catch_objc_arc.hpp\n\n#import <Foundation/Foundation.h>\n\n#ifdef __has_feature\n#define CATCH_ARC_ENABLED __has_feature(objc_arc)\n#else\n#define CATCH_ARC_ENABLED 0\n#endif\n\nvoid arcSafeRelease( NSObject* obj );\nid performOptionalSelector( id obj, SEL sel );\n\n#if !CATCH_ARC_ENABLED\ninline void arcSafeRelease( NSObject* obj ) {\n    [obj release];\n}\ninline id performOptionalSelector( id obj, SEL sel ) {\n    if( [obj respondsToSelector: sel] )\n        return [obj performSelector: sel];\n    return nil;\n}\n#define CATCH_UNSAFE_UNRETAINED\n#define CATCH_ARC_STRONG\n#else\ninline void arcSafeRelease( NSObject* ){}\ninline id performOptionalSelector( id obj, SEL sel ) {\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Warc-performSelector-leaks\"\n#endif\n    if( [obj respondsToSelector: sel] )\n        return [obj performSelector: sel];\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n    return nil;\n}\n#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained\n#define CATCH_ARC_STRONG __strong\n#endif\n\n// end catch_objc_arc.hpp\n#endif\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless\n#endif\n\nnamespace Catch {\n    namespace Detail {\n\n        extern const std::string unprintableString;\n\n        std::string rawMemoryToString( const void *object, std::size_t size );\n\n        template<typename T>\n        std::string rawMemoryToString( const T& object ) {\n          return rawMemoryToString( &object, sizeof(object) );\n        }\n\n        template<typename T>\n        class IsStreamInsertable {\n            template<typename SS, typename TT>\n            static auto test(int)\n                -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());\n\n            template<typename, typename>\n            static auto test(...)->std::false_type;\n\n        public:\n            static const bool value = decltype(test<std::ostream, const T&>(0))::value;\n        };\n\n        template<typename E>\n        std::string convertUnknownEnumToString( E e );\n\n        template<typename T>\n        typename std::enable_if<\n            !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,\n        std::string>::type convertUnstreamable( T const& ) {\n            return Detail::unprintableString;\n        }\n        template<typename T>\n        typename std::enable_if<\n            !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,\n         std::string>::type convertUnstreamable(T const& ex) {\n            return ex.what();\n        }\n\n        template<typename T>\n        typename std::enable_if<\n            std::is_enum<T>::value\n        , std::string>::type convertUnstreamable( T const& value ) {\n            return convertUnknownEnumToString( value );\n        }\n\n#if defined(_MANAGED)\n        //! Convert a CLR string to a utf8 std::string\n        template<typename T>\n        std::string clrReferenceToString( T^ ref ) {\n            if (ref == nullptr)\n                return std::string(\"null\");\n            auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());\n            cli::pin_ptr<System::Byte> p = &bytes[0];\n            return std::string(reinterpret_cast<char const *>(p), bytes->Length);\n        }\n#endif\n\n    } // namespace Detail\n\n    // If we decide for C++14, change these to enable_if_ts\n    template <typename T, typename = void>\n    struct StringMaker {\n        template <typename Fake = T>\n        static\n        typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type\n            convert(const Fake& value) {\n                ReusableStringStream rss;\n                // NB: call using the function-like syntax to avoid ambiguity with\n                // user-defined templated operator<< under clang.\n                rss.operator<<(value);\n                return rss.str();\n        }\n\n        template <typename Fake = T>\n        static\n        typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type\n            convert( const Fake& value ) {\n#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)\n            return Detail::convertUnstreamable(value);\n#else\n            return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);\n#endif\n        }\n    };\n\n    namespace Detail {\n\n        // This function dispatches all stringification requests inside of Catch.\n        // Should be preferably called fully qualified, like ::Catch::Detail::stringify\n        template <typename T>\n        std::string stringify(const T& e) {\n            return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e);\n        }\n\n        template<typename E>\n        std::string convertUnknownEnumToString( E e ) {\n            return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e));\n        }\n\n#if defined(_MANAGED)\n        template <typename T>\n        std::string stringify( T^ e ) {\n            return ::Catch::StringMaker<T^>::convert(e);\n        }\n#endif\n\n    } // namespace Detail\n\n    // Some predefined specializations\n\n    template<>\n    struct StringMaker<std::string> {\n        static std::string convert(const std::string& str);\n    };\n\n#ifdef CATCH_CONFIG_CPP17_STRING_VIEW\n    template<>\n    struct StringMaker<std::string_view> {\n        static std::string convert(std::string_view str);\n    };\n#endif\n\n    template<>\n    struct StringMaker<char const *> {\n        static std::string convert(char const * str);\n    };\n    template<>\n    struct StringMaker<char *> {\n        static std::string convert(char * str);\n    };\n\n#ifdef CATCH_CONFIG_WCHAR\n    template<>\n    struct StringMaker<std::wstring> {\n        static std::string convert(const std::wstring& wstr);\n    };\n\n# ifdef CATCH_CONFIG_CPP17_STRING_VIEW\n    template<>\n    struct StringMaker<std::wstring_view> {\n        static std::string convert(std::wstring_view str);\n    };\n# endif\n\n    template<>\n    struct StringMaker<wchar_t const *> {\n        static std::string convert(wchar_t const * str);\n    };\n    template<>\n    struct StringMaker<wchar_t *> {\n        static std::string convert(wchar_t * str);\n    };\n#endif\n\n    // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,\n    //      while keeping string semantics?\n    template<int SZ>\n    struct StringMaker<char[SZ]> {\n        static std::string convert(char const* str) {\n            return ::Catch::Detail::stringify(std::string{ str });\n        }\n    };\n    template<int SZ>\n    struct StringMaker<signed char[SZ]> {\n        static std::string convert(signed char const* str) {\n            return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });\n        }\n    };\n    template<int SZ>\n    struct StringMaker<unsigned char[SZ]> {\n        static std::string convert(unsigned char const* str) {\n            return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });\n        }\n    };\n\n    template<>\n    struct StringMaker<int> {\n        static std::string convert(int value);\n    };\n    template<>\n    struct StringMaker<long> {\n        static std::string convert(long value);\n    };\n    template<>\n    struct StringMaker<long long> {\n        static std::string convert(long long value);\n    };\n    template<>\n    struct StringMaker<unsigned int> {\n        static std::string convert(unsigned int value);\n    };\n    template<>\n    struct StringMaker<unsigned long> {\n        static std::string convert(unsigned long value);\n    };\n    template<>\n    struct StringMaker<unsigned long long> {\n        static std::string convert(unsigned long long value);\n    };\n\n    template<>\n    struct StringMaker<bool> {\n        static std::string convert(bool b);\n    };\n\n    template<>\n    struct StringMaker<char> {\n        static std::string convert(char c);\n    };\n    template<>\n    struct StringMaker<signed char> {\n        static std::string convert(signed char c);\n    };\n    template<>\n    struct StringMaker<unsigned char> {\n        static std::string convert(unsigned char c);\n    };\n\n    template<>\n    struct StringMaker<std::nullptr_t> {\n        static std::string convert(std::nullptr_t);\n    };\n\n    template<>\n    struct StringMaker<float> {\n        static std::string convert(float value);\n    };\n    template<>\n    struct StringMaker<double> {\n        static std::string convert(double value);\n    };\n\n    template <typename T>\n    struct StringMaker<T*> {\n        template <typename U>\n        static std::string convert(U* p) {\n            if (p) {\n                return ::Catch::Detail::rawMemoryToString(p);\n            } else {\n                return \"nullptr\";\n            }\n        }\n    };\n\n    template <typename R, typename C>\n    struct StringMaker<R C::*> {\n        static std::string convert(R C::* p) {\n            if (p) {\n                return ::Catch::Detail::rawMemoryToString(p);\n            } else {\n                return \"nullptr\";\n            }\n        }\n    };\n\n#if defined(_MANAGED)\n    template <typename T>\n    struct StringMaker<T^> {\n        static std::string convert( T^ ref ) {\n            return ::Catch::Detail::clrReferenceToString(ref);\n        }\n    };\n#endif\n\n    namespace Detail {\n        template<typename InputIterator>\n        std::string rangeToString(InputIterator first, InputIterator last) {\n            ReusableStringStream rss;\n            rss << \"{ \";\n            if (first != last) {\n                rss << ::Catch::Detail::stringify(*first);\n                for (++first; first != last; ++first)\n                    rss << \", \" << ::Catch::Detail::stringify(*first);\n            }\n            rss << \" }\";\n            return rss.str();\n        }\n    }\n\n#ifdef __OBJC__\n    template<>\n    struct StringMaker<NSString*> {\n        static std::string convert(NSString * nsstring) {\n            if (!nsstring)\n                return \"nil\";\n            return std::string(\"@\") + [nsstring UTF8String];\n        }\n    };\n    template<>\n    struct StringMaker<NSObject*> {\n        static std::string convert(NSObject* nsObject) {\n            return ::Catch::Detail::stringify([nsObject description]);\n        }\n\n    };\n    namespace Detail {\n        inline std::string stringify( NSString* nsstring ) {\n            return StringMaker<NSString*>::convert( nsstring );\n        }\n\n    } // namespace Detail\n#endif // __OBJC__\n\n} // namespace Catch\n\n//////////////////////////////////////////////////////\n// Separate std-lib types stringification, so it can be selectively enabled\n// This means that we do not bring in\n\n#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)\n#  define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER\n#  define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER\n#  define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER\n#  define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER\n#  define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER\n#endif\n\n// Separate std::pair specialization\n#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)\n#include <utility>\nnamespace Catch {\n    template<typename T1, typename T2>\n    struct StringMaker<std::pair<T1, T2> > {\n        static std::string convert(const std::pair<T1, T2>& pair) {\n            ReusableStringStream rss;\n            rss << \"{ \"\n                << ::Catch::Detail::stringify(pair.first)\n                << \", \"\n                << ::Catch::Detail::stringify(pair.second)\n                << \" }\";\n            return rss.str();\n        }\n    };\n}\n#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER\n\n#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)\n#include <optional>\nnamespace Catch {\n    template<typename T>\n    struct StringMaker<std::optional<T> > {\n        static std::string convert(const std::optional<T>& optional) {\n            ReusableStringStream rss;\n            if (optional.has_value()) {\n                rss << ::Catch::Detail::stringify(*optional);\n            } else {\n                rss << \"{ }\";\n            }\n            return rss.str();\n        }\n    };\n}\n#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER\n\n// Separate std::tuple specialization\n#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)\n#include <tuple>\nnamespace Catch {\n    namespace Detail {\n        template<\n            typename Tuple,\n            std::size_t N = 0,\n            bool = (N < std::tuple_size<Tuple>::value)\n            >\n            struct TupleElementPrinter {\n            static void print(const Tuple& tuple, std::ostream& os) {\n                os << (N ? \", \" : \" \")\n                    << ::Catch::Detail::stringify(std::get<N>(tuple));\n                TupleElementPrinter<Tuple, N + 1>::print(tuple, os);\n            }\n        };\n\n        template<\n            typename Tuple,\n            std::size_t N\n        >\n            struct TupleElementPrinter<Tuple, N, false> {\n            static void print(const Tuple&, std::ostream&) {}\n        };\n\n    }\n\n    template<typename ...Types>\n    struct StringMaker<std::tuple<Types...>> {\n        static std::string convert(const std::tuple<Types...>& tuple) {\n            ReusableStringStream rss;\n            rss << '{';\n            Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());\n            rss << \" }\";\n            return rss.str();\n        }\n    };\n}\n#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER\n\n#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)\n#include <variant>\nnamespace Catch {\n    template<>\n    struct StringMaker<std::monostate> {\n        static std::string convert(const std::monostate&) {\n            return \"{ }\";\n        }\n    };\n\n    template<typename... Elements>\n    struct StringMaker<std::variant<Elements...>> {\n        static std::string convert(const std::variant<Elements...>& variant) {\n            if (variant.valueless_by_exception()) {\n                return \"{valueless variant}\";\n            } else {\n                return std::visit(\n                    [](const auto& value) {\n                        return ::Catch::Detail::stringify(value);\n                    },\n                    variant\n                );\n            }\n        }\n    };\n}\n#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER\n\nnamespace Catch {\n    struct not_this_one {}; // Tag type for detecting which begin/ end are being selected\n\n    // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace\n    using std::begin;\n    using std::end;\n\n    not_this_one begin( ... );\n    not_this_one end( ... );\n\n    template <typename T>\n    struct is_range {\n        static const bool value =\n            !std::is_same<decltype(begin(std::declval<T>())), not_this_one>::value &&\n            !std::is_same<decltype(end(std::declval<T>())), not_this_one>::value;\n    };\n\n#if defined(_MANAGED) // Managed types are never ranges\n    template <typename T>\n    struct is_range<T^> {\n        static const bool value = false;\n    };\n#endif\n\n    template<typename Range>\n    std::string rangeToString( Range const& range ) {\n        return ::Catch::Detail::rangeToString( begin( range ), end( range ) );\n    }\n\n    // Handle vector<bool> specially\n    template<typename Allocator>\n    std::string rangeToString( std::vector<bool, Allocator> const& v ) {\n        ReusableStringStream rss;\n        rss << \"{ \";\n        bool first = true;\n        for( bool b : v ) {\n            if( first )\n                first = false;\n            else\n                rss << \", \";\n            rss << ::Catch::Detail::stringify( b );\n        }\n        rss << \" }\";\n        return rss.str();\n    }\n\n    template<typename R>\n    struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {\n        static std::string convert( R const& range ) {\n            return rangeToString( range );\n        }\n    };\n\n    template <typename T, int SZ>\n    struct StringMaker<T[SZ]> {\n        static std::string convert(T const(&arr)[SZ]) {\n            return rangeToString(arr);\n        }\n    };\n\n} // namespace Catch\n\n// Separate std::chrono::duration specialization\n#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)\n#include <ctime>\n#include <ratio>\n#include <chrono>\n\nnamespace Catch {\n\ntemplate <class Ratio>\nstruct ratio_string {\n    static std::string symbol();\n};\n\ntemplate <class Ratio>\nstd::string ratio_string<Ratio>::symbol() {\n    Catch::ReusableStringStream rss;\n    rss << '[' << Ratio::num << '/'\n        << Ratio::den << ']';\n    return rss.str();\n}\ntemplate <>\nstruct ratio_string<std::atto> {\n    static std::string symbol();\n};\ntemplate <>\nstruct ratio_string<std::femto> {\n    static std::string symbol();\n};\ntemplate <>\nstruct ratio_string<std::pico> {\n    static std::string symbol();\n};\ntemplate <>\nstruct ratio_string<std::nano> {\n    static std::string symbol();\n};\ntemplate <>\nstruct ratio_string<std::micro> {\n    static std::string symbol();\n};\ntemplate <>\nstruct ratio_string<std::milli> {\n    static std::string symbol();\n};\n\n    ////////////\n    // std::chrono::duration specializations\n    template<typename Value, typename Ratio>\n    struct StringMaker<std::chrono::duration<Value, Ratio>> {\n        static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {\n            ReusableStringStream rss;\n            rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';\n            return rss.str();\n        }\n    };\n    template<typename Value>\n    struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {\n        static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {\n            ReusableStringStream rss;\n            rss << duration.count() << \" s\";\n            return rss.str();\n        }\n    };\n    template<typename Value>\n    struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {\n        static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {\n            ReusableStringStream rss;\n            rss << duration.count() << \" m\";\n            return rss.str();\n        }\n    };\n    template<typename Value>\n    struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {\n        static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {\n            ReusableStringStream rss;\n            rss << duration.count() << \" h\";\n            return rss.str();\n        }\n    };\n\n    ////////////\n    // std::chrono::time_point specialization\n    // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>\n    template<typename Clock, typename Duration>\n    struct StringMaker<std::chrono::time_point<Clock, Duration>> {\n        static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {\n            return ::Catch::Detail::stringify(time_point.time_since_epoch()) + \" since epoch\";\n        }\n    };\n    // std::chrono::time_point<system_clock> specialization\n    template<typename Duration>\n    struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {\n        static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {\n            auto converted = std::chrono::system_clock::to_time_t(time_point);\n\n#ifdef _MSC_VER\n            std::tm timeInfo = {};\n            gmtime_s(&timeInfo, &converted);\n#else\n            std::tm* timeInfo = std::gmtime(&converted);\n#endif\n\n            auto const timeStampSize = sizeof(\"2017-01-16T17:06:45Z\");\n            char timeStamp[timeStampSize];\n            const char * const fmt = \"%Y-%m-%dT%H:%M:%SZ\";\n\n#ifdef _MSC_VER\n            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);\n#else\n            std::strftime(timeStamp, timeStampSize, fmt, timeInfo);\n#endif\n            return std::string(timeStamp);\n        }\n    };\n}\n#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER\n\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\n// end catch_tostring.h\n#include <iosfwd>\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable:4389) // '==' : signed/unsigned mismatch\n#pragma warning(disable:4018) // more \"signed/unsigned mismatch\"\n#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)\n#pragma warning(disable:4180) // qualifier applied to function type has no meaning\n#pragma warning(disable:4800) // Forcing result to true or false\n#endif\n\nnamespace Catch {\n\n    struct ITransientExpression {\n        auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }\n        auto getResult() const -> bool { return m_result; }\n        virtual void streamReconstructedExpression( std::ostream &os ) const = 0;\n\n        ITransientExpression( bool isBinaryExpression, bool result )\n        :   m_isBinaryExpression( isBinaryExpression ),\n            m_result( result )\n        {}\n\n        // We don't actually need a virtual destructor, but many static analysers\n        // complain if it's not here :-(\n        virtual ~ITransientExpression();\n\n        bool m_isBinaryExpression;\n        bool m_result;\n\n    };\n\n    void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );\n\n    template<typename LhsT, typename RhsT>\n    class BinaryExpr  : public ITransientExpression {\n        LhsT m_lhs;\n        StringRef m_op;\n        RhsT m_rhs;\n\n        void streamReconstructedExpression( std::ostream &os ) const override {\n            formatReconstructedExpression\n                    ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );\n        }\n\n    public:\n        BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )\n        :   ITransientExpression{ true, comparisonResult },\n            m_lhs( lhs ),\n            m_op( op ),\n            m_rhs( rhs )\n        {}\n\n        template<typename T>\n        auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {\n            static_assert(always_false<T>::value,\n            \"chained comparisons are not supported inside assertions, \"\n            \"wrap the expression inside parentheses, or decompose it\");\n        }\n\n        template<typename T>\n        auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {\n            static_assert(always_false<T>::value,\n            \"chained comparisons are not supported inside assertions, \"\n            \"wrap the expression inside parentheses, or decompose it\");\n        }\n\n        template<typename T>\n        auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {\n            static_assert(always_false<T>::value,\n            \"chained comparisons are not supported inside assertions, \"\n            \"wrap the expression inside parentheses, or decompose it\");\n        }\n\n        template<typename T>\n        auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {\n            static_assert(always_false<T>::value,\n            \"chained comparisons are not supported inside assertions, \"\n            \"wrap the expression inside parentheses, or decompose it\");\n        }\n\n        template<typename T>\n        auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {\n            static_assert(always_false<T>::value,\n            \"chained comparisons are not supported inside assertions, \"\n            \"wrap the expression inside parentheses, or decompose it\");\n        }\n\n        template<typename T>\n        auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {\n            static_assert(always_false<T>::value,\n            \"chained comparisons are not supported inside assertions, \"\n            \"wrap the expression inside parentheses, or decompose it\");\n        }\n\n        template<typename T>\n        auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {\n            static_assert(always_false<T>::value,\n            \"chained comparisons are not supported inside assertions, \"\n            \"wrap the expression inside parentheses, or decompose it\");\n        }\n\n        template<typename T>\n        auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {\n            static_assert(always_false<T>::value,\n            \"chained comparisons are not supported inside assertions, \"\n            \"wrap the expression inside parentheses, or decompose it\");\n        }\n    };\n\n    template<typename LhsT>\n    class UnaryExpr : public ITransientExpression {\n        LhsT m_lhs;\n\n        void streamReconstructedExpression( std::ostream &os ) const override {\n            os << Catch::Detail::stringify( m_lhs );\n        }\n\n    public:\n        explicit UnaryExpr( LhsT lhs )\n        :   ITransientExpression{ false, static_cast<bool>(lhs) },\n            m_lhs( lhs )\n        {}\n    };\n\n    // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)\n    template<typename LhsT, typename RhsT>\n    auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); }\n    template<typename T>\n    auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }\n    template<typename T>\n    auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }\n    template<typename T>\n    auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }\n    template<typename T>\n    auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }\n\n    template<typename LhsT, typename RhsT>\n    auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }\n    template<typename T>\n    auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }\n    template<typename T>\n    auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }\n    template<typename T>\n    auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }\n    template<typename T>\n    auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }\n\n    template<typename LhsT>\n    class ExprLhs {\n        LhsT m_lhs;\n    public:\n        explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}\n\n        template<typename RhsT>\n        auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {\n            return { compareEqual( m_lhs, rhs ), m_lhs, \"==\", rhs };\n        }\n        auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {\n            return { m_lhs == rhs, m_lhs, \"==\", rhs };\n        }\n\n        template<typename RhsT>\n        auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {\n            return { compareNotEqual( m_lhs, rhs ), m_lhs, \"!=\", rhs };\n        }\n        auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {\n            return { m_lhs != rhs, m_lhs, \"!=\", rhs };\n        }\n\n        template<typename RhsT>\n        auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {\n            return { static_cast<bool>(m_lhs > rhs), m_lhs, \">\", rhs };\n        }\n        template<typename RhsT>\n        auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {\n            return { static_cast<bool>(m_lhs < rhs), m_lhs, \"<\", rhs };\n        }\n        template<typename RhsT>\n        auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {\n            return { static_cast<bool>(m_lhs >= rhs), m_lhs, \">=\", rhs };\n        }\n        template<typename RhsT>\n        auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {\n            return { static_cast<bool>(m_lhs <= rhs), m_lhs, \"<=\", rhs };\n        }\n\n        template<typename RhsT>\n        auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {\n            static_assert(always_false<RhsT>::value,\n            \"operator&& is not supported inside assertions, \"\n            \"wrap the expression inside parentheses, or decompose it\");\n        }\n\n        template<typename RhsT>\n        auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {\n            static_assert(always_false<RhsT>::value,\n            \"operator|| is not supported inside assertions, \"\n            \"wrap the expression inside parentheses, or decompose it\");\n        }\n\n        auto makeUnaryExpr() const -> UnaryExpr<LhsT> {\n            return UnaryExpr<LhsT>{ m_lhs };\n        }\n    };\n\n    void handleExpression( ITransientExpression const& expr );\n\n    template<typename T>\n    void handleExpression( ExprLhs<T> const& expr ) {\n        handleExpression( expr.makeUnaryExpr() );\n    }\n\n    struct Decomposer {\n        template<typename T>\n        auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {\n            return ExprLhs<T const&>{ lhs };\n        }\n\n        auto operator <=( bool value ) -> ExprLhs<bool> {\n            return ExprLhs<bool>{ value };\n        }\n    };\n\n} // end namespace Catch\n\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\n// end catch_decomposer.h\n// start catch_interfaces_capture.h\n\n#include <string>\n\nnamespace Catch {\n\n    class AssertionResult;\n    struct AssertionInfo;\n    struct SectionInfo;\n    struct SectionEndInfo;\n    struct MessageInfo;\n    struct MessageBuilder;\n    struct Counts;\n    struct BenchmarkInfo;\n    struct BenchmarkStats;\n    struct AssertionReaction;\n    struct SourceLineInfo;\n\n    struct ITransientExpression;\n    struct IGeneratorTracker;\n\n    struct IResultCapture {\n\n        virtual ~IResultCapture();\n\n        virtual bool sectionStarted(    SectionInfo const& sectionInfo,\n                                        Counts& assertions ) = 0;\n        virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;\n        virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;\n\n        virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;\n\n        virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;\n        virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0;\n\n        virtual void pushScopedMessage( MessageInfo const& message ) = 0;\n        virtual void popScopedMessage( MessageInfo const& message ) = 0;\n\n        virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0;\n\n        virtual void handleFatalErrorCondition( StringRef message ) = 0;\n\n        virtual void handleExpr\n                (   AssertionInfo const& info,\n                    ITransientExpression const& expr,\n                    AssertionReaction& reaction ) = 0;\n        virtual void handleMessage\n                (   AssertionInfo const& info,\n                    ResultWas::OfType resultType,\n                    StringRef const& message,\n                    AssertionReaction& reaction ) = 0;\n        virtual void handleUnexpectedExceptionNotThrown\n                (   AssertionInfo const& info,\n                    AssertionReaction& reaction ) = 0;\n        virtual void handleUnexpectedInflightException\n                (   AssertionInfo const& info,\n                    std::string const& message,\n                    AssertionReaction& reaction ) = 0;\n        virtual void handleIncomplete\n                (   AssertionInfo const& info ) = 0;\n        virtual void handleNonExpr\n                (   AssertionInfo const &info,\n                    ResultWas::OfType resultType,\n                    AssertionReaction &reaction ) = 0;\n\n        virtual bool lastAssertionPassed() = 0;\n        virtual void assertionPassed() = 0;\n\n        // Deprecated, do not use:\n        virtual std::string getCurrentTestName() const = 0;\n        virtual const AssertionResult* getLastResult() const = 0;\n        virtual void exceptionEarlyReported() = 0;\n    };\n\n    IResultCapture& getResultCapture();\n}\n\n// end catch_interfaces_capture.h\nnamespace Catch {\n\n    struct TestFailureException{};\n    struct AssertionResultData;\n    struct IResultCapture;\n    class RunContext;\n\n    class LazyExpression {\n        friend class AssertionHandler;\n        friend struct AssertionStats;\n        friend class RunContext;\n\n        ITransientExpression const* m_transientExpression = nullptr;\n        bool m_isNegated;\n    public:\n        LazyExpression( bool isNegated );\n        LazyExpression( LazyExpression const& other );\n        LazyExpression& operator = ( LazyExpression const& ) = delete;\n\n        explicit operator bool() const;\n\n        friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;\n    };\n\n    struct AssertionReaction {\n        bool shouldDebugBreak = false;\n        bool shouldThrow = false;\n    };\n\n    class AssertionHandler {\n        AssertionInfo m_assertionInfo;\n        AssertionReaction m_reaction;\n        bool m_completed = false;\n        IResultCapture& m_resultCapture;\n\n    public:\n        AssertionHandler\n            (   StringRef const& macroName,\n                SourceLineInfo const& lineInfo,\n                StringRef capturedExpression,\n                ResultDisposition::Flags resultDisposition );\n        ~AssertionHandler() {\n            if ( !m_completed ) {\n                m_resultCapture.handleIncomplete( m_assertionInfo );\n            }\n        }\n\n        template<typename T>\n        void handleExpr( ExprLhs<T> const& expr ) {\n            handleExpr( expr.makeUnaryExpr() );\n        }\n        void handleExpr( ITransientExpression const& expr );\n\n        void handleMessage(ResultWas::OfType resultType, StringRef const& message);\n\n        void handleExceptionThrownAsExpected();\n        void handleUnexpectedExceptionNotThrown();\n        void handleExceptionNotThrownAsExpected();\n        void handleThrowingCallSkipped();\n        void handleUnexpectedInflightException();\n\n        void complete();\n        void setCompleted();\n\n        // query\n        auto allowThrows() const -> bool;\n    };\n\n    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString );\n\n} // namespace Catch\n\n// end catch_assertionhandler.h\n// start catch_message.h\n\n#include <string>\n#include <vector>\n\nnamespace Catch {\n\n    struct MessageInfo {\n        MessageInfo(    StringRef const& _macroName,\n                        SourceLineInfo const& _lineInfo,\n                        ResultWas::OfType _type );\n\n        StringRef macroName;\n        std::string message;\n        SourceLineInfo lineInfo;\n        ResultWas::OfType type;\n        unsigned int sequence;\n\n        bool operator == ( MessageInfo const& other ) const;\n        bool operator < ( MessageInfo const& other ) const;\n    private:\n        static unsigned int globalCount;\n    };\n\n    struct MessageStream {\n\n        template<typename T>\n        MessageStream& operator << ( T const& value ) {\n            m_stream << value;\n            return *this;\n        }\n\n        ReusableStringStream m_stream;\n    };\n\n    struct MessageBuilder : MessageStream {\n        MessageBuilder( StringRef const& macroName,\n                        SourceLineInfo const& lineInfo,\n                        ResultWas::OfType type );\n\n        template<typename T>\n        MessageBuilder& operator << ( T const& value ) {\n            m_stream << value;\n            return *this;\n        }\n\n        MessageInfo m_info;\n    };\n\n    class ScopedMessage {\n    public:\n        explicit ScopedMessage( MessageBuilder const& builder );\n        ScopedMessage( ScopedMessage& duplicate ) = delete;\n        ScopedMessage( ScopedMessage&& old );\n        ~ScopedMessage();\n\n        MessageInfo m_info;\n        bool m_moved;\n    };\n\n    class Capturer {\n        std::vector<MessageInfo> m_messages;\n        IResultCapture& m_resultCapture = getResultCapture();\n        size_t m_captured = 0;\n    public:\n        Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );\n        ~Capturer();\n\n        void captureValue( size_t index, std::string const& value );\n\n        template<typename T>\n        void captureValues( size_t index, T const& value ) {\n            captureValue( index, Catch::Detail::stringify( value ) );\n        }\n\n        template<typename T, typename... Ts>\n        void captureValues( size_t index, T const& value, Ts const&... values ) {\n            captureValue( index, Catch::Detail::stringify(value) );\n            captureValues( index+1, values... );\n        }\n    };\n\n} // end namespace Catch\n\n// end catch_message.h\n#if !defined(CATCH_CONFIG_DISABLE)\n\n#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)\n  #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__\n#else\n  #define CATCH_INTERNAL_STRINGIFY(...) \"Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION\"\n#endif\n\n#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)\n\n///////////////////////////////////////////////////////////////////////////////\n// Another way to speed-up compilation is to omit local try-catch for REQUIRE*\n// macros.\n#define INTERNAL_CATCH_TRY\n#define INTERNAL_CATCH_CATCH( capturer )\n\n#else // CATCH_CONFIG_FAST_COMPILE\n\n#define INTERNAL_CATCH_TRY try\n#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }\n\n#endif\n\n#define INTERNAL_CATCH_REACT( handler ) handler.complete();\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \\\n    do { \\\n        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \\\n        INTERNAL_CATCH_TRY { \\\n            CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \\\n            catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \\\n            CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \\\n        } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \\\n        INTERNAL_CATCH_REACT( catchAssertionHandler ) \\\n    } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look\n    // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \\\n    INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \\\n    if( Catch::getResultCapture().lastAssertionPassed() )\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \\\n    INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \\\n    if( !Catch::getResultCapture().lastAssertionPassed() )\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \\\n    do { \\\n        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \\\n        try { \\\n            static_cast<void>(__VA_ARGS__); \\\n            catchAssertionHandler.handleExceptionNotThrownAsExpected(); \\\n        } \\\n        catch( ... ) { \\\n            catchAssertionHandler.handleUnexpectedInflightException(); \\\n        } \\\n        INTERNAL_CATCH_REACT( catchAssertionHandler ) \\\n    } while( false )\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \\\n    do { \\\n        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \\\n        if( catchAssertionHandler.allowThrows() ) \\\n            try { \\\n                static_cast<void>(__VA_ARGS__); \\\n                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \\\n            } \\\n            catch( ... ) { \\\n                catchAssertionHandler.handleExceptionThrownAsExpected(); \\\n            } \\\n        else \\\n            catchAssertionHandler.handleThrowingCallSkipped(); \\\n        INTERNAL_CATCH_REACT( catchAssertionHandler ) \\\n    } while( false )\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \\\n    do { \\\n        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) \", \" CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \\\n        if( catchAssertionHandler.allowThrows() ) \\\n            try { \\\n                static_cast<void>(expr); \\\n                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \\\n            } \\\n            catch( exceptionType const& ) { \\\n                catchAssertionHandler.handleExceptionThrownAsExpected(); \\\n            } \\\n            catch( ... ) { \\\n                catchAssertionHandler.handleUnexpectedInflightException(); \\\n            } \\\n        else \\\n            catchAssertionHandler.handleThrowingCallSkipped(); \\\n        INTERNAL_CATCH_REACT( catchAssertionHandler ) \\\n    } while( false )\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \\\n    do { \\\n        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \\\n        catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \\\n        INTERNAL_CATCH_REACT( catchAssertionHandler ) \\\n    } while( false )\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \\\n    auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \\\n    varName.captureValues( 0, __VA_ARGS__ )\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CATCH_INFO( macroName, log ) \\\n    Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \\\n    Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )\n\n///////////////////////////////////////////////////////////////////////////////\n// Although this is matcher-based, it can be used with just a string\n#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \\\n    do { \\\n        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) \", \" CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \\\n        if( catchAssertionHandler.allowThrows() ) \\\n            try { \\\n                static_cast<void>(__VA_ARGS__); \\\n                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \\\n            } \\\n            catch( ... ) { \\\n                Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \\\n            } \\\n        else \\\n            catchAssertionHandler.handleThrowingCallSkipped(); \\\n        INTERNAL_CATCH_REACT( catchAssertionHandler ) \\\n    } while( false )\n\n#endif // CATCH_CONFIG_DISABLE\n\n// end catch_capture.hpp\n// start catch_section.h\n\n// start catch_section_info.h\n\n// start catch_totals.h\n\n#include <cstddef>\n\nnamespace Catch {\n\n    struct Counts {\n        Counts operator - ( Counts const& other ) const;\n        Counts& operator += ( Counts const& other );\n\n        std::size_t total() const;\n        bool allPassed() const;\n        bool allOk() const;\n\n        std::size_t passed = 0;\n        std::size_t failed = 0;\n        std::size_t failedButOk = 0;\n    };\n\n    struct Totals {\n\n        Totals operator - ( Totals const& other ) const;\n        Totals& operator += ( Totals const& other );\n\n        Totals delta( Totals const& prevTotals ) const;\n\n        int error = 0;\n        Counts assertions;\n        Counts testCases;\n    };\n}\n\n// end catch_totals.h\n#include <string>\n\nnamespace Catch {\n\n    struct SectionInfo {\n        SectionInfo\n            (   SourceLineInfo const& _lineInfo,\n                std::string const& _name );\n\n        // Deprecated\n        SectionInfo\n            (   SourceLineInfo const& _lineInfo,\n                std::string const& _name,\n                std::string const& ) : SectionInfo( _lineInfo, _name ) {}\n\n        std::string name;\n        std::string description; // !Deprecated: this will always be empty\n        SourceLineInfo lineInfo;\n    };\n\n    struct SectionEndInfo {\n        SectionInfo sectionInfo;\n        Counts prevAssertions;\n        double durationInSeconds;\n    };\n\n} // end namespace Catch\n\n// end catch_section_info.h\n// start catch_timer.h\n\n#include <cstdint>\n\nnamespace Catch {\n\n    auto getCurrentNanosecondsSinceEpoch() -> uint64_t;\n    auto getEstimatedClockResolution() -> uint64_t;\n\n    class Timer {\n        uint64_t m_nanoseconds = 0;\n    public:\n        void start();\n        auto getElapsedNanoseconds() const -> uint64_t;\n        auto getElapsedMicroseconds() const -> uint64_t;\n        auto getElapsedMilliseconds() const -> unsigned int;\n        auto getElapsedSeconds() const -> double;\n    };\n\n} // namespace Catch\n\n// end catch_timer.h\n#include <string>\n\nnamespace Catch {\n\n    class Section : NonCopyable {\n    public:\n        Section( SectionInfo const& info );\n        ~Section();\n\n        // This indicates whether the section should be executed or not\n        explicit operator bool() const;\n\n    private:\n        SectionInfo m_info;\n\n        std::string m_name;\n        Counts m_assertions;\n        bool m_sectionIncluded;\n        Timer m_timer;\n    };\n\n} // end namespace Catch\n\n#define INTERNAL_CATCH_SECTION( ... ) \\\n    CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \\\n    if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \\\n    CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS\n\n#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \\\n    CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \\\n    if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \\\n    CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS\n\n// end catch_section.h\n// start catch_benchmark.h\n\n#include <cstdint>\n#include <string>\n\nnamespace Catch {\n\n    class BenchmarkLooper {\n\n        std::string m_name;\n        std::size_t m_count = 0;\n        std::size_t m_iterationsToRun = 1;\n        uint64_t m_resolution;\n        Timer m_timer;\n\n        static auto getResolution() -> uint64_t;\n    public:\n        // Keep most of this inline as it's on the code path that is being timed\n        BenchmarkLooper( StringRef name )\n        :   m_name( name ),\n            m_resolution( getResolution() )\n        {\n            reportStart();\n            m_timer.start();\n        }\n\n        explicit operator bool() {\n            if( m_count < m_iterationsToRun )\n                return true;\n            return needsMoreIterations();\n        }\n\n        void increment() {\n            ++m_count;\n        }\n\n        void reportStart();\n        auto needsMoreIterations() -> bool;\n    };\n\n} // end namespace Catch\n\n#define BENCHMARK( name ) \\\n    for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() )\n\n// end catch_benchmark.h\n// start catch_interfaces_exception.h\n\n// start catch_interfaces_registry_hub.h\n\n#include <string>\n#include <memory>\n\nnamespace Catch {\n\n    class TestCase;\n    struct ITestCaseRegistry;\n    struct IExceptionTranslatorRegistry;\n    struct IExceptionTranslator;\n    struct IReporterRegistry;\n    struct IReporterFactory;\n    struct ITagAliasRegistry;\n    class StartupExceptionRegistry;\n\n    using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;\n\n    struct IRegistryHub {\n        virtual ~IRegistryHub();\n\n        virtual IReporterRegistry const& getReporterRegistry() const = 0;\n        virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;\n        virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;\n\n        virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;\n\n        virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;\n    };\n\n    struct IMutableRegistryHub {\n        virtual ~IMutableRegistryHub();\n        virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0;\n        virtual void registerListener( IReporterFactoryPtr const& factory ) = 0;\n        virtual void registerTest( TestCase const& testInfo ) = 0;\n        virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;\n        virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;\n        virtual void registerStartupException() noexcept = 0;\n    };\n\n    IRegistryHub const& getRegistryHub();\n    IMutableRegistryHub& getMutableRegistryHub();\n    void cleanUp();\n    std::string translateActiveException();\n\n}\n\n// end catch_interfaces_registry_hub.h\n#if defined(CATCH_CONFIG_DISABLE)\n    #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \\\n        static std::string translatorName( signature )\n#endif\n\n#include <exception>\n#include <string>\n#include <vector>\n\nnamespace Catch {\n    using exceptionTranslateFunction = std::string(*)();\n\n    struct IExceptionTranslator;\n    using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>;\n\n    struct IExceptionTranslator {\n        virtual ~IExceptionTranslator();\n        virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;\n    };\n\n    struct IExceptionTranslatorRegistry {\n        virtual ~IExceptionTranslatorRegistry();\n\n        virtual std::string translateActiveException() const = 0;\n    };\n\n    class ExceptionTranslatorRegistrar {\n        template<typename T>\n        class ExceptionTranslator : public IExceptionTranslator {\n        public:\n\n            ExceptionTranslator( std::string(*translateFunction)( T& ) )\n            : m_translateFunction( translateFunction )\n            {}\n\n            std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {\n                try {\n                    if( it == itEnd )\n                        std::rethrow_exception(std::current_exception());\n                    else\n                        return (*it)->translate( it+1, itEnd );\n                }\n                catch( T& ex ) {\n                    return m_translateFunction( ex );\n                }\n            }\n\n        protected:\n            std::string(*m_translateFunction)( T& );\n        };\n\n    public:\n        template<typename T>\n        ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {\n            getMutableRegistryHub().registerTranslator\n                ( new ExceptionTranslator<T>( translateFunction ) );\n        }\n    };\n}\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \\\n    static std::string translatorName( signature ); \\\n    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \\\n    namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \\\n    CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \\\n    static std::string translatorName( signature )\n\n#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )\n\n// end catch_interfaces_exception.h\n// start catch_approx.h\n\n#include <type_traits>\n\nnamespace Catch {\nnamespace Detail {\n\n    class Approx {\n    private:\n        bool equalityComparisonImpl(double other) const;\n        // Validates the new margin (margin >= 0)\n        // out-of-line to avoid including stdexcept in the header\n        void setMargin(double margin);\n        // Validates the new epsilon (0 < epsilon < 1)\n        // out-of-line to avoid including stdexcept in the header\n        void setEpsilon(double epsilon);\n\n    public:\n        explicit Approx ( double value );\n\n        static Approx custom();\n\n        Approx operator-() const;\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        Approx operator()( T const& value ) {\n            Approx approx( static_cast<double>(value) );\n            approx.m_epsilon = m_epsilon;\n            approx.m_margin = m_margin;\n            approx.m_scale = m_scale;\n            return approx;\n        }\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        explicit Approx( T const& value ): Approx(static_cast<double>(value))\n        {}\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        friend bool operator == ( const T& lhs, Approx const& rhs ) {\n            auto lhs_v = static_cast<double>(lhs);\n            return rhs.equalityComparisonImpl(lhs_v);\n        }\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        friend bool operator == ( Approx const& lhs, const T& rhs ) {\n            return operator==( rhs, lhs );\n        }\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        friend bool operator != ( T const& lhs, Approx const& rhs ) {\n            return !operator==( lhs, rhs );\n        }\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        friend bool operator != ( Approx const& lhs, T const& rhs ) {\n            return !operator==( rhs, lhs );\n        }\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        friend bool operator <= ( T const& lhs, Approx const& rhs ) {\n            return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;\n        }\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        friend bool operator <= ( Approx const& lhs, T const& rhs ) {\n            return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;\n        }\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        friend bool operator >= ( T const& lhs, Approx const& rhs ) {\n            return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;\n        }\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        friend bool operator >= ( Approx const& lhs, T const& rhs ) {\n            return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;\n        }\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        Approx& epsilon( T const& newEpsilon ) {\n            double epsilonAsDouble = static_cast<double>(newEpsilon);\n            setEpsilon(epsilonAsDouble);\n            return *this;\n        }\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        Approx& margin( T const& newMargin ) {\n            double marginAsDouble = static_cast<double>(newMargin);\n            setMargin(marginAsDouble);\n            return *this;\n        }\n\n        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>\n        Approx& scale( T const& newScale ) {\n            m_scale = static_cast<double>(newScale);\n            return *this;\n        }\n\n        std::string toString() const;\n\n    private:\n        double m_epsilon;\n        double m_margin;\n        double m_scale;\n        double m_value;\n    };\n} // end namespace Detail\n\nnamespace literals {\n    Detail::Approx operator \"\" _a(long double val);\n    Detail::Approx operator \"\" _a(unsigned long long val);\n} // end namespace literals\n\ntemplate<>\nstruct StringMaker<Catch::Detail::Approx> {\n    static std::string convert(Catch::Detail::Approx const& value);\n};\n\n} // end namespace Catch\n\n// end catch_approx.h\n// start catch_string_manip.h\n\n#include <string>\n#include <iosfwd>\n\nnamespace Catch {\n\n    bool startsWith( std::string const& s, std::string const& prefix );\n    bool startsWith( std::string const& s, char prefix );\n    bool endsWith( std::string const& s, std::string const& suffix );\n    bool endsWith( std::string const& s, char suffix );\n    bool contains( std::string const& s, std::string const& infix );\n    void toLowerInPlace( std::string& s );\n    std::string toLower( std::string const& s );\n    std::string trim( std::string const& str );\n    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );\n\n    struct pluralise {\n        pluralise( std::size_t count, std::string const& label );\n\n        friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );\n\n        std::size_t m_count;\n        std::string m_label;\n    };\n}\n\n// end catch_string_manip.h\n#ifndef CATCH_CONFIG_DISABLE_MATCHERS\n// start catch_capture_matchers.h\n\n// start catch_matchers.h\n\n#include <string>\n#include <vector>\n\nnamespace Catch {\nnamespace Matchers {\n    namespace Impl {\n\n        template<typename ArgT> struct MatchAllOf;\n        template<typename ArgT> struct MatchAnyOf;\n        template<typename ArgT> struct MatchNotOf;\n\n        class MatcherUntypedBase {\n        public:\n            MatcherUntypedBase() = default;\n            MatcherUntypedBase ( MatcherUntypedBase const& ) = default;\n            MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete;\n            std::string toString() const;\n\n        protected:\n            virtual ~MatcherUntypedBase();\n            virtual std::string describe() const = 0;\n            mutable std::string m_cachedToString;\n        };\n\n#ifdef __clang__\n#    pragma clang diagnostic push\n#    pragma clang diagnostic ignored \"-Wnon-virtual-dtor\"\n#endif\n\n        template<typename ObjectT>\n        struct MatcherMethod {\n            virtual bool match( ObjectT const& arg ) const = 0;\n        };\n\n#ifdef __clang__\n#    pragma clang diagnostic pop\n#endif\n\n        template<typename T>\n        struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> {\n\n            MatchAllOf<T> operator && ( MatcherBase const& other ) const;\n            MatchAnyOf<T> operator || ( MatcherBase const& other ) const;\n            MatchNotOf<T> operator ! () const;\n        };\n\n        template<typename ArgT>\n        struct MatchAllOf : MatcherBase<ArgT> {\n            bool match( ArgT const& arg ) const override {\n                for( auto matcher : m_matchers ) {\n                    if (!matcher->match(arg))\n                        return false;\n                }\n                return true;\n            }\n            std::string describe() const override {\n                std::string description;\n                description.reserve( 4 + m_matchers.size()*32 );\n                description += \"( \";\n                bool first = true;\n                for( auto matcher : m_matchers ) {\n                    if( first )\n                        first = false;\n                    else\n                        description += \" and \";\n                    description += matcher->toString();\n                }\n                description += \" )\";\n                return description;\n            }\n\n            MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {\n                m_matchers.push_back( &other );\n                return *this;\n            }\n\n            std::vector<MatcherBase<ArgT> const*> m_matchers;\n        };\n        template<typename ArgT>\n        struct MatchAnyOf : MatcherBase<ArgT> {\n\n            bool match( ArgT const& arg ) const override {\n                for( auto matcher : m_matchers ) {\n                    if (matcher->match(arg))\n                        return true;\n                }\n                return false;\n            }\n            std::string describe() const override {\n                std::string description;\n                description.reserve( 4 + m_matchers.size()*32 );\n                description += \"( \";\n                bool first = true;\n                for( auto matcher : m_matchers ) {\n                    if( first )\n                        first = false;\n                    else\n                        description += \" or \";\n                    description += matcher->toString();\n                }\n                description += \" )\";\n                return description;\n            }\n\n            MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {\n                m_matchers.push_back( &other );\n                return *this;\n            }\n\n            std::vector<MatcherBase<ArgT> const*> m_matchers;\n        };\n\n        template<typename ArgT>\n        struct MatchNotOf : MatcherBase<ArgT> {\n\n            MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}\n\n            bool match( ArgT const& arg ) const override {\n                return !m_underlyingMatcher.match( arg );\n            }\n\n            std::string describe() const override {\n                return \"not \" + m_underlyingMatcher.toString();\n            }\n            MatcherBase<ArgT> const& m_underlyingMatcher;\n        };\n\n        template<typename T>\n        MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const {\n            return MatchAllOf<T>() && *this && other;\n        }\n        template<typename T>\n        MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const {\n            return MatchAnyOf<T>() || *this || other;\n        }\n        template<typename T>\n        MatchNotOf<T> MatcherBase<T>::operator ! () const {\n            return MatchNotOf<T>( *this );\n        }\n\n    } // namespace Impl\n\n} // namespace Matchers\n\nusing namespace Matchers;\nusing Matchers::Impl::MatcherBase;\n\n} // namespace Catch\n\n// end catch_matchers.h\n// start catch_matchers_floating.h\n\n#include <type_traits>\n#include <cmath>\n\nnamespace Catch {\nnamespace Matchers {\n\n    namespace Floating {\n\n        enum class FloatingPointKind : uint8_t;\n\n        struct WithinAbsMatcher : MatcherBase<double> {\n            WithinAbsMatcher(double target, double margin);\n            bool match(double const& matchee) const override;\n            std::string describe() const override;\n        private:\n            double m_target;\n            double m_margin;\n        };\n\n        struct WithinUlpsMatcher : MatcherBase<double> {\n            WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType);\n            bool match(double const& matchee) const override;\n            std::string describe() const override;\n        private:\n            double m_target;\n            int m_ulps;\n            FloatingPointKind m_type;\n        };\n\n    } // namespace Floating\n\n    // The following functions create the actual matcher objects.\n    // This allows the types to be inferred\n    Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff);\n    Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff);\n    Floating::WithinAbsMatcher WithinAbs(double target, double margin);\n\n} // namespace Matchers\n} // namespace Catch\n\n// end catch_matchers_floating.h\n// start catch_matchers_generic.hpp\n\n#include <functional>\n#include <string>\n\nnamespace Catch {\nnamespace Matchers {\nnamespace Generic {\n\nnamespace Detail {\n    std::string finalizeDescription(const std::string& desc);\n}\n\ntemplate <typename T>\nclass PredicateMatcher : public MatcherBase<T> {\n    std::function<bool(T const&)> m_predicate;\n    std::string m_description;\npublic:\n\n    PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)\n        :m_predicate(std::move(elem)),\n        m_description(Detail::finalizeDescription(descr))\n    {}\n\n    bool match( T const& item ) const override {\n        return m_predicate(item);\n    }\n\n    std::string describe() const override {\n        return m_description;\n    }\n};\n\n} // namespace Generic\n\n    // The following functions create the actual matcher objects.\n    // The user has to explicitly specify type to the function, because\n    // infering std::function<bool(T const&)> is hard (but possible) and\n    // requires a lot of TMP.\n    template<typename T>\n    Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = \"\") {\n        return Generic::PredicateMatcher<T>(predicate, description);\n    }\n\n} // namespace Matchers\n} // namespace Catch\n\n// end catch_matchers_generic.hpp\n// start catch_matchers_string.h\n\n#include <string>\n\nnamespace Catch {\nnamespace Matchers {\n\n    namespace StdString {\n\n        struct CasedString\n        {\n            CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );\n            std::string adjustString( std::string const& str ) const;\n            std::string caseSensitivitySuffix() const;\n\n            CaseSensitive::Choice m_caseSensitivity;\n            std::string m_str;\n        };\n\n        struct StringMatcherBase : MatcherBase<std::string> {\n            StringMatcherBase( std::string const& operation, CasedString const& comparator );\n            std::string describe() const override;\n\n            CasedString m_comparator;\n            std::string m_operation;\n        };\n\n        struct EqualsMatcher : StringMatcherBase {\n            EqualsMatcher( CasedString const& comparator );\n            bool match( std::string const& source ) const override;\n        };\n        struct ContainsMatcher : StringMatcherBase {\n            ContainsMatcher( CasedString const& comparator );\n            bool match( std::string const& source ) const override;\n        };\n        struct StartsWithMatcher : StringMatcherBase {\n            StartsWithMatcher( CasedString const& comparator );\n            bool match( std::string const& source ) const override;\n        };\n        struct EndsWithMatcher : StringMatcherBase {\n            EndsWithMatcher( CasedString const& comparator );\n            bool match( std::string const& source ) const override;\n        };\n\n        struct RegexMatcher : MatcherBase<std::string> {\n            RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity );\n            bool match( std::string const& matchee ) const override;\n            std::string describe() const override;\n\n        private:\n            std::string m_regex;\n            CaseSensitive::Choice m_caseSensitivity;\n        };\n\n    } // namespace StdString\n\n    // The following functions create the actual matcher objects.\n    // This allows the types to be inferred\n\n    StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );\n    StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );\n    StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );\n    StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );\n    StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );\n\n} // namespace Matchers\n} // namespace Catch\n\n// end catch_matchers_string.h\n// start catch_matchers_vector.h\n\n#include <algorithm>\n\nnamespace Catch {\nnamespace Matchers {\n\n    namespace Vector {\n        namespace Detail {\n            template <typename InputIterator, typename T>\n            size_t count(InputIterator first, InputIterator last, T const& item) {\n                size_t cnt = 0;\n                for (; first != last; ++first) {\n                    if (*first == item) {\n                        ++cnt;\n                    }\n                }\n                return cnt;\n            }\n            template <typename InputIterator, typename T>\n            bool contains(InputIterator first, InputIterator last, T const& item) {\n                for (; first != last; ++first) {\n                    if (*first == item) {\n                        return true;\n                    }\n                }\n                return false;\n            }\n        }\n\n        template<typename T>\n        struct ContainsElementMatcher : MatcherBase<std::vector<T>> {\n\n            ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}\n\n            bool match(std::vector<T> const &v) const override {\n                for (auto const& el : v) {\n                    if (el == m_comparator) {\n                        return true;\n                    }\n                }\n                return false;\n            }\n\n            std::string describe() const override {\n                return \"Contains: \" + ::Catch::Detail::stringify( m_comparator );\n            }\n\n            T const& m_comparator;\n        };\n\n        template<typename T>\n        struct ContainsMatcher : MatcherBase<std::vector<T>> {\n\n            ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}\n\n            bool match(std::vector<T> const &v) const override {\n                // !TBD: see note in EqualsMatcher\n                if (m_comparator.size() > v.size())\n                    return false;\n                for (auto const& comparator : m_comparator) {\n                    auto present = false;\n                    for (const auto& el : v) {\n                        if (el == comparator) {\n                            present = true;\n                            break;\n                        }\n                    }\n                    if (!present) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n            std::string describe() const override {\n                return \"Contains: \" + ::Catch::Detail::stringify( m_comparator );\n            }\n\n            std::vector<T> const& m_comparator;\n        };\n\n        template<typename T>\n        struct EqualsMatcher : MatcherBase<std::vector<T>> {\n\n            EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}\n\n            bool match(std::vector<T> const &v) const override {\n                // !TBD: This currently works if all elements can be compared using !=\n                // - a more general approach would be via a compare template that defaults\n                // to using !=. but could be specialised for, e.g. std::vector<T> etc\n                // - then just call that directly\n                if (m_comparator.size() != v.size())\n                    return false;\n                for (std::size_t i = 0; i < v.size(); ++i)\n                    if (m_comparator[i] != v[i])\n                        return false;\n                return true;\n            }\n            std::string describe() const override {\n                return \"Equals: \" + ::Catch::Detail::stringify( m_comparator );\n            }\n            std::vector<T> const& m_comparator;\n        };\n\n        template<typename T>\n        struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {\n            UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}\n            bool match(std::vector<T> const& vec) const override {\n                // Note: This is a reimplementation of std::is_permutation,\n                //       because I don't want to include <algorithm> inside the common path\n                if (m_target.size() != vec.size()) {\n                    return false;\n                }\n                auto lfirst = m_target.begin(), llast = m_target.end();\n                auto rfirst = vec.begin(), rlast = vec.end();\n                // Cut common prefix to optimize checking of permuted parts\n                while (lfirst != llast && *lfirst == *rfirst) {\n                    ++lfirst; ++rfirst;\n                }\n                if (lfirst == llast) {\n                    return true;\n                }\n\n                for (auto mid = lfirst; mid != llast; ++mid) {\n                    // Skip already counted items\n                    if (Detail::contains(lfirst, mid, *mid)) {\n                        continue;\n                    }\n                    size_t num_vec = Detail::count(rfirst, rlast, *mid);\n                    if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) {\n                        return false;\n                    }\n                }\n\n                return true;\n            }\n\n            std::string describe() const override {\n                return \"UnorderedEquals: \" + ::Catch::Detail::stringify(m_target);\n            }\n        private:\n            std::vector<T> const& m_target;\n        };\n\n    } // namespace Vector\n\n    // The following functions create the actual matcher objects.\n    // This allows the types to be inferred\n\n    template<typename T>\n    Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {\n        return Vector::ContainsMatcher<T>( comparator );\n    }\n\n    template<typename T>\n    Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {\n        return Vector::ContainsElementMatcher<T>( comparator );\n    }\n\n    template<typename T>\n    Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {\n        return Vector::EqualsMatcher<T>( comparator );\n    }\n\n    template<typename T>\n    Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {\n        return Vector::UnorderedEqualsMatcher<T>(target);\n    }\n\n} // namespace Matchers\n} // namespace Catch\n\n// end catch_matchers_vector.h\nnamespace Catch {\n\n    template<typename ArgT, typename MatcherT>\n    class MatchExpr : public ITransientExpression {\n        ArgT const& m_arg;\n        MatcherT m_matcher;\n        StringRef m_matcherString;\n    public:\n        MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString )\n        :   ITransientExpression{ true, matcher.match( arg ) },\n            m_arg( arg ),\n            m_matcher( matcher ),\n            m_matcherString( matcherString )\n        {}\n\n        void streamReconstructedExpression( std::ostream &os ) const override {\n            auto matcherAsString = m_matcher.toString();\n            os << Catch::Detail::stringify( m_arg ) << ' ';\n            if( matcherAsString == Detail::unprintableString )\n                os << m_matcherString;\n            else\n                os << matcherAsString;\n        }\n    };\n\n    using StringMatcher = Matchers::Impl::MatcherBase<std::string>;\n\n    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  );\n\n    template<typename ArgT, typename MatcherT>\n    auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString  ) -> MatchExpr<ArgT, MatcherT> {\n        return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );\n    }\n\n} // namespace Catch\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \\\n    do { \\\n        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) \", \" CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \\\n        INTERNAL_CATCH_TRY { \\\n            catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \\\n        } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \\\n        INTERNAL_CATCH_REACT( catchAssertionHandler ) \\\n    } while( false )\n\n///////////////////////////////////////////////////////////////////////////////\n#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \\\n    do { \\\n        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) \", \" CATCH_INTERNAL_STRINGIFY(exceptionType) \", \" CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \\\n        if( catchAssertionHandler.allowThrows() ) \\\n            try { \\\n                static_cast<void>(__VA_ARGS__ ); \\\n                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \\\n            } \\\n            catch( exceptionType const& ex ) { \\\n                catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \\\n            } \\\n            catch( ... ) { \\\n                catchAssertionHandler.handleUnexpectedInflightException(); \\\n            } \\\n        else \\\n            catchAssertionHandler.handleThrowingCallSkipped(); \\\n        INTERNAL_CATCH_REACT( catchAssertionHandler ) \\\n    } while( false )\n\n// end catch_capture_matchers.h\n#endif\n// start catch_generators.hpp\n\n// start catch_interfaces_generatortracker.h\n\n\n#include <memory>\n\nnamespace Catch {\n\n    namespace Generators {\n        class GeneratorUntypedBase {\n        public:\n            GeneratorUntypedBase() = default;\n            virtual ~GeneratorUntypedBase();\n            // Attempts to move the generator to the next element\n             //\n             // Returns true iff the move succeeded (and a valid element\n             // can be retrieved).\n            virtual bool next() = 0;\n        };\n        using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>;\n\n    } // namespace Generators\n\n    struct IGeneratorTracker {\n        virtual ~IGeneratorTracker();\n        virtual auto hasGenerator() const -> bool = 0;\n        virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;\n        virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;\n    };\n\n} // namespace Catch\n\n// end catch_interfaces_generatortracker.h\n// start catch_enforce.h\n\n#include <stdexcept>\n\nnamespace Catch {\n#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)\n    template <typename Ex>\n    [[noreturn]]\n    void throw_exception(Ex const& e) {\n        throw e;\n    }\n#else // ^^ Exceptions are enabled //  Exceptions are disabled vv\n    [[noreturn]]\n    void throw_exception(std::exception const& e);\n#endif\n} // namespace Catch;\n\n#define CATCH_PREPARE_EXCEPTION( type, msg ) \\\n    type( ( Catch::ReusableStringStream() << msg ).str() )\n#define CATCH_INTERNAL_ERROR( msg ) \\\n    Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << \": Internal Catch error: \" << msg))\n#define CATCH_ERROR( msg ) \\\n    Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg ))\n#define CATCH_RUNTIME_ERROR( msg ) \\\n    Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg ))\n#define CATCH_ENFORCE( condition, msg ) \\\n    do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)\n\n// end catch_enforce.h\n#include <memory>\n#include <vector>\n#include <cassert>\n\n#include <utility>\n#include <exception>\n\nnamespace Catch {\n\nclass GeneratorException : public std::exception {\n    const char* const m_msg = \"\";\n\npublic:\n    GeneratorException(const char* msg):\n        m_msg(msg)\n    {}\n\n    const char* what() const noexcept override final;\n};\n\nnamespace Generators {\n\n    // !TBD move this into its own location?\n    namespace pf{\n        template<typename T, typename... Args>\n        std::unique_ptr<T> make_unique( Args&&... args ) {\n            return std::unique_ptr<T>(new T(std::forward<Args>(args)...));\n        }\n    }\n\n    template<typename T>\n    struct IGenerator : GeneratorUntypedBase {\n        virtual ~IGenerator() = default;\n\n        // Returns the current element of the generator\n        //\n        // \\Precondition The generator is either freshly constructed,\n        // or the last call to `next()` returned true\n        virtual T const& get() const = 0;\n        using type = T;\n    };\n\n    template<typename T>\n    class SingleValueGenerator final : public IGenerator<T> {\n        T m_value;\n    public:\n        SingleValueGenerator(T const& value) : m_value( value ) {}\n        SingleValueGenerator(T&& value) : m_value(std::move(value)) {}\n\n        T const& get() const override {\n            return m_value;\n        }\n        bool next() override {\n            return false;\n        }\n    };\n\n    template<typename T>\n    class FixedValuesGenerator final : public IGenerator<T> {\n        std::vector<T> m_values;\n        size_t m_idx = 0;\n    public:\n        FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}\n\n        T const& get() const override {\n            return m_values[m_idx];\n        }\n        bool next() override {\n            ++m_idx;\n            return m_idx < m_values.size();\n        }\n    };\n\n    template <typename T>\n    class GeneratorWrapper final {\n        std::unique_ptr<IGenerator<T>> m_generator;\n    public:\n        GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator):\n            m_generator(std::move(generator))\n        {}\n        T const& get() const {\n            return m_generator->get();\n        }\n        bool next() {\n            return m_generator->next();\n        }\n    };\n\n    template <typename T>\n    GeneratorWrapper<T> value(T&& value) {\n        return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value)));\n    }\n    template <typename T>\n    GeneratorWrapper<T> values(std::initializer_list<T> values) {\n        return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values));\n    }\n\n    template<typename T>\n    class Generators : public IGenerator<T> {\n        std::vector<GeneratorWrapper<T>> m_generators;\n        size_t m_current = 0;\n\n        void populate(GeneratorWrapper<T>&& generator) {\n            m_generators.emplace_back(std::move(generator));\n        }\n        void populate(T&& val) {\n            m_generators.emplace_back(value(std::move(val)));\n        }\n        template<typename U>\n        void populate(U&& val) {\n            populate(T(std::move(val)));\n        }\n        template<typename U, typename... Gs>\n        void populate(U&& valueOrGenerator, Gs... moreGenerators) {\n            populate(std::forward<U>(valueOrGenerator));\n            populate(std::forward<Gs>(moreGenerators)...);\n        }\n\n    public:\n        template <typename... Gs>\n        Generators(Gs... moreGenerators) {\n            m_generators.reserve(sizeof...(Gs));\n            populate(std::forward<Gs>(moreGenerators)...);\n        }\n\n        T const& get() const override {\n            return m_generators[m_current].get();\n        }\n\n        bool next() override {\n            if (m_current >= m_generators.size()) {\n                return false;\n            }\n            const bool current_status = m_generators[m_current].next();\n            if (!current_status) {\n                ++m_current;\n            }\n            return m_current < m_generators.size();\n        }\n    };\n\n    template<typename... Ts>\n    GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) {\n        return values<std::tuple<Ts...>>( tuples );\n    }\n\n    // Tag type to signal that a generator sequence should convert arguments to a specific type\n    template <typename T>\n    struct as {};\n\n    template<typename T, typename... Gs>\n    auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> {\n        return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);\n    }\n    template<typename T>\n    auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {\n        return Generators<T>(std::move(generator));\n    }\n    template<typename T, typename... Gs>\n    auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {\n        return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );\n    }\n    template<typename T, typename U, typename... Gs>\n    auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> {\n        return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );\n    }\n\n    auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;\n\n    template<typename L>\n    // Note: The type after -> is weird, because VS2015 cannot parse\n    //       the expression used in the typedef inside, when it is in\n    //       return type. Yeah.\n    auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {\n        using UnderlyingType = typename decltype(generatorExpression())::type;\n\n        IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );\n        if (!tracker.hasGenerator()) {\n            tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));\n        }\n\n        auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() );\n        return generator.get();\n    }\n\n} // namespace Generators\n} // namespace Catch\n\n#define GENERATE( ... ) \\\n    Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )\n\n// end catch_generators.hpp\n// start catch_generators_generic.hpp\n\nnamespace Catch {\nnamespace Generators {\n\n    template <typename T>\n    class TakeGenerator : public IGenerator<T> {\n        GeneratorWrapper<T> m_generator;\n        size_t m_returned = 0;\n        size_t m_target;\n    public:\n        TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):\n            m_generator(std::move(generator)),\n            m_target(target)\n        {\n            assert(target != 0 && \"Empty generators are not allowed\");\n        }\n        T const& get() const override {\n            return m_generator.get();\n        }\n        bool next() override {\n            ++m_returned;\n            if (m_returned >= m_target) {\n                return false;\n            }\n\n            const auto success = m_generator.next();\n            // If the underlying generator does not contain enough values\n            // then we cut short as well\n            if (!success) {\n                m_returned = m_target;\n            }\n            return success;\n        }\n    };\n\n    template <typename T>\n    GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {\n        return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));\n    }\n\n    template <typename T, typename Predicate>\n    class FilterGenerator : public IGenerator<T> {\n        GeneratorWrapper<T> m_generator;\n        Predicate m_predicate;\n    public:\n        template <typename P = Predicate>\n        FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):\n            m_generator(std::move(generator)),\n            m_predicate(std::forward<P>(pred))\n        {\n            if (!m_predicate(m_generator.get())) {\n                // It might happen that there are no values that pass the\n                // filter. In that case we throw an exception.\n                auto has_initial_value = next();\n                if (!has_initial_value) {\n                    Catch::throw_exception(GeneratorException(\"No valid value found in filtered generator\"));\n                }\n            }\n        }\n\n        T const& get() const override {\n            return m_generator.get();\n        }\n\n        bool next() override {\n            bool success = m_generator.next();\n            if (!success) {\n                return false;\n            }\n            while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);\n            return success;\n        }\n    };\n\n    template <typename T, typename Predicate>\n    GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {\n        return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));\n    }\n\n    template <typename T>\n    class RepeatGenerator : public IGenerator<T> {\n        GeneratorWrapper<T> m_generator;\n        mutable std::vector<T> m_returned;\n        size_t m_target_repeats;\n        size_t m_current_repeat = 0;\n        size_t m_repeat_index = 0;\n    public:\n        RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):\n            m_generator(std::move(generator)),\n            m_target_repeats(repeats)\n        {\n            assert(m_target_repeats > 0 && \"Repeat generator must repeat at least once\");\n        }\n\n        T const& get() const override {\n            if (m_current_repeat == 0) {\n                m_returned.push_back(m_generator.get());\n                return m_returned.back();\n            }\n            return m_returned[m_repeat_index];\n        }\n\n        bool next() override {\n            // There are 2 basic cases:\n            // 1) We are still reading the generator\n            // 2) We are reading our own cache\n\n            // In the first case, we need to poke the underlying generator.\n            // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache\n            if (m_current_repeat == 0) {\n                const auto success = m_generator.next();\n                if (!success) {\n                    ++m_current_repeat;\n                }\n                return m_current_repeat < m_target_repeats;\n            }\n\n            // In the second case, we need to move indices forward and check that we haven't run up against the end\n            ++m_repeat_index;\n            if (m_repeat_index == m_returned.size()) {\n                m_repeat_index = 0;\n                ++m_current_repeat;\n            }\n            return m_current_repeat < m_target_repeats;\n        }\n    };\n\n    template <typename T>\n    GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {\n        return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));\n    }\n\n    template <typename T, typename U, typename Func>\n    class MapGenerator : public IGenerator<T> {\n        // TBD: provide static assert for mapping function, for friendly error message\n        GeneratorWrapper<U> m_generator;\n        Func m_function;\n        // To avoid returning dangling reference, we have to save the values\n        T m_cache;\n    public:\n        template <typename F2 = Func>\n        MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :\n            m_generator(std::move(generator)),\n            m_function(std::forward<F2>(function)),\n            m_cache(m_function(m_generator.get()))\n        {}\n\n        T const& get() const override {\n            return m_cache;\n        }\n        bool next() override {\n            const auto success = m_generator.next();\n            if (success) {\n                m_cache = m_function(m_generator.get());\n            }\n            return success;\n        }\n    };\n\n    template <typename T, typename U, typename Func>\n    GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {\n        return GeneratorWrapper<T>(\n            pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))\n        );\n    }\n    template <typename T, typename Func>\n    GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<T>&& generator) {\n        return GeneratorWrapper<T>(\n            pf::make_unique<MapGenerator<T, T, Func>>(std::forward<Func>(function), std::move(generator))\n        );\n    }\n\n    template <typename T>\n    class ChunkGenerator final : public IGenerator<std::vector<T>> {\n        std::vector<T> m_chunk;\n        size_t m_chunk_size;\n        GeneratorWrapper<T> m_generator;\n        bool m_used_up = false;\n    public:\n        ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :\n            m_chunk_size(size), m_generator(std::move(generator))\n        {\n            m_chunk.reserve(m_chunk_size);\n            m_chunk.push_back(m_generator.get());\n            for (size_t i = 1; i < m_chunk_size; ++i) {\n                if (!m_generator.next()) {\n                    Catch::throw_exception(GeneratorException(\"Not enough values to initialize the first chunk\"));\n                }\n                m_chunk.push_back(m_generator.get());\n            }\n        }\n        std::vector<T> const& get() const override {\n            return m_chunk;\n        }\n        bool next() override {\n            m_chunk.clear();\n            for (size_t idx = 0; idx < m_chunk_size; ++idx) {\n                if (!m_generator.next()) {\n                    return false;\n                }\n                m_chunk.push_back(m_generator.get());\n            }\n            return true;\n        }\n    };\n\n    template <typename T>\n    GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) {\n        return GeneratorWrapper<std::vector<T>>(\n            pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))\n        );\n    }\n\n} // namespace Generators\n} // namespace Catch\n\n// end catch_generators_generic.hpp\n// start catch_generators_specific.hpp\n\n// start catch_context.h\n\n#include <memory>\n\nnamespace Catch {\n\n    struct IResultCapture;\n    struct IRunner;\n    struct IConfig;\n    struct IMutableContext;\n\n    using IConfigPtr = std::shared_ptr<IConfig const>;\n\n    struct IContext\n    {\n        virtual ~IContext();\n\n        virtual IResultCapture* getResultCapture() = 0;\n        virtual IRunner* getRunner() = 0;\n        virtual IConfigPtr const& getConfig() const = 0;\n    };\n\n    struct IMutableContext : IContext\n    {\n        virtual ~IMutableContext();\n        virtual void setResultCapture( IResultCapture* resultCapture ) = 0;\n        virtual void setRunner( IRunner* runner ) = 0;\n        virtual void setConfig( IConfigPtr const& config ) = 0;\n\n    private:\n        static IMutableContext *currentContext;\n        friend IMutableContext& getCurrentMutableContext();\n        friend void cleanUpContext();\n        static void createContext();\n    };\n\n    inline IMutableContext& getCurrentMutableContext()\n    {\n        if( !IMutableContext::currentContext )\n            IMutableContext::createContext();\n        return *IMutableContext::currentContext;\n    }\n\n    inline IContext& getCurrentContext()\n    {\n        return getCurrentMutableContext();\n    }\n\n    void cleanUpContext();\n}\n\n// end catch_context.h\n// start catch_interfaces_config.h\n\n#include <iosfwd>\n#include <string>\n#include <vector>\n#include <memory>\n\nnamespace Catch {\n\n    enum class Verbosity {\n        Quiet = 0,\n        Normal,\n        High\n    };\n\n    struct WarnAbout { enum What {\n        Nothing = 0x00,\n        NoAssertions = 0x01,\n        NoTests = 0x02\n    }; };\n\n    struct ShowDurations { enum OrNot {\n        DefaultForReporter,\n        Always,\n        Never\n    }; };\n    struct RunTests { enum InWhatOrder {\n        InDeclarationOrder,\n        InLexicographicalOrder,\n        InRandomOrder\n    }; };\n    struct UseColour { enum YesOrNo {\n        Auto,\n        Yes,\n        No\n    }; };\n    struct WaitForKeypress { enum When {\n        Never,\n        BeforeStart = 1,\n        BeforeExit = 2,\n        BeforeStartAndExit = BeforeStart | BeforeExit\n    }; };\n\n    class TestSpec;\n\n    struct IConfig : NonCopyable {\n\n        virtual ~IConfig();\n\n        virtual bool allowThrows() const = 0;\n        virtual std::ostream& stream() const = 0;\n        virtual std::string name() const = 0;\n        virtual bool includeSuccessfulResults() const = 0;\n        virtual bool shouldDebugBreak() const = 0;\n        virtual bool warnAboutMissingAssertions() const = 0;\n        virtual bool warnAboutNoTests() const = 0;\n        virtual int abortAfter() const = 0;\n        virtual bool showInvisibles() const = 0;\n        virtual ShowDurations::OrNot showDurations() const = 0;\n        virtual TestSpec const& testSpec() const = 0;\n        virtual bool hasTestFilters() const = 0;\n        virtual RunTests::InWhatOrder runOrder() const = 0;\n        virtual unsigned int rngSeed() const = 0;\n        virtual int benchmarkResolutionMultiple() const = 0;\n        virtual UseColour::YesOrNo useColour() const = 0;\n        virtual std::vector<std::string> const& getSectionsToRun() const = 0;\n        virtual Verbosity verbosity() const = 0;\n    };\n\n    using IConfigPtr = std::shared_ptr<IConfig const>;\n}\n\n// end catch_interfaces_config.h\n#include <random>\n\nnamespace Catch {\nnamespace Generators {\n\ntemplate <typename Float>\nclass RandomFloatingGenerator final : public IGenerator<Float> {\n    // FIXME: What is the right seed?\n    std::minstd_rand m_rand;\n    std::uniform_real_distribution<Float> m_dist;\n    Float m_current_number;\npublic:\n\n    RandomFloatingGenerator(Float a, Float b):\n        m_rand(getCurrentContext().getConfig()->rngSeed()),\n        m_dist(a, b) {\n        static_cast<void>(next());\n    }\n\n    Float const& get() const override {\n        return m_current_number;\n    }\n    bool next() override {\n        m_current_number = m_dist(m_rand);\n        return true;\n    }\n};\n\ntemplate <typename Integer>\nclass RandomIntegerGenerator final : public IGenerator<Integer> {\n    std::minstd_rand m_rand;\n    std::uniform_int_distribution<Integer> m_dist;\n    Integer m_current_number;\npublic:\n\n    RandomIntegerGenerator(Integer a, Integer b):\n        m_rand(getCurrentContext().getConfig()->rngSeed()),\n        m_dist(a, b) {\n        static_cast<void>(next());\n    }\n\n    Integer const& get() const override {\n        return m_current_number;\n    }\n    bool next() override {\n        m_current_number = m_dist(m_rand);\n        return true;\n    }\n};\n\n// TODO: Ideally this would be also constrained against the various char types,\n//       but I don't expect users to run into that in practice.\ntemplate <typename T>\ntypename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value,\nGeneratorWrapper<T>>::type\nrandom(T a, T b) {\n    return GeneratorWrapper<T>(\n        pf::make_unique<RandomIntegerGenerator<T>>(a, b)\n    );\n}\n\ntemplate <typename T>\ntypename std::enable_if<std::is_floating_point<T>::value,\nGeneratorWrapper<T>>::type\nrandom(T a, T b) {\n    return GeneratorWrapper<T>(\n        pf::make_unique<RandomFloatingGenerator<T>>(a, b)\n    );\n}\n\ntemplate <typename T>\nclass RangeGenerator final : public IGenerator<T> {\n    T m_current;\n    T m_end;\n    T m_step;\n    bool m_positive;\n\npublic:\n    RangeGenerator(T const& start, T const& end, T const& step):\n        m_current(start),\n        m_end(end),\n        m_step(step),\n        m_positive(m_step > T(0))\n    {\n        assert(m_current != m_end && \"Range start and end cannot be equal\");\n        assert(m_step != T(0) && \"Step size cannot be zero\");\n        assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && \"Step moves away from end\");\n    }\n\n    RangeGenerator(T const& start, T const& end):\n        RangeGenerator(start, end, (start < end) ? T(1) : T(-1))\n    {}\n\n    T const& get() const override {\n        return m_current;\n    }\n\n    bool next() override {\n        m_current += m_step;\n        return (m_positive) ? (m_current < m_end) : (m_current > m_end);\n    }\n};\n\ntemplate <typename T>\nGeneratorWrapper<T> range(T const& start, T const& end, T const& step) {\n    static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, \"Type must be an integer\");\n    return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));\n}\n\ntemplate <typename T>\nGeneratorWrapper<T> range(T const& start, T const& end) {\n    static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, \"Type must be an integer\");\n    return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end));\n}\n\n} // namespace Generators\n} // namespace Catch\n\n// end catch_generators_specific.hpp\n\n// These files are included here so the single_include script doesn't put them\n// in the conditionally compiled sections\n// start catch_test_case_info.h\n\n#include <string>\n#include <vector>\n#include <memory>\n\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wpadded\"\n#endif\n\nnamespace Catch {\n\n    struct ITestInvoker;\n\n    struct TestCaseInfo {\n        enum SpecialProperties{\n            None = 0,\n            IsHidden = 1 << 1,\n            ShouldFail = 1 << 2,\n            MayFail = 1 << 3,\n            Throws = 1 << 4,\n            NonPortable = 1 << 5,\n            Benchmark = 1 << 6\n        };\n\n        TestCaseInfo(   std::string const& _name,\n                        std::string const& _className,\n                        std::string const& _description,\n                        std::vector<std::string> const& _tags,\n                        SourceLineInfo const& _lineInfo );\n\n        friend void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags );\n\n        bool isHidden() const;\n        bool throws() const;\n        bool okToFail() const;\n        bool expectedToFail() const;\n\n        std::string tagsAsString() const;\n\n        std::string name;\n        std::string className;\n        std::string description;\n        std::vector<std::string> tags;\n        std::vector<std::string> lcaseTags;\n        SourceLineInfo lineInfo;\n        SpecialProperties properties;\n    };\n\n    class TestCase : public TestCaseInfo {\n    public:\n\n        TestCase( ITestInvoker* testCase, TestCaseInfo&& info );\n\n        TestCase withName( std::string const& _newName ) const;\n\n        void invoke() const;\n\n        TestCaseInfo const& getTestCaseInfo() const;\n\n        bool operator == ( TestCase const& other ) const;\n        bool operator < ( TestCase const& other ) const;\n\n    private:\n        std::shared_ptr<ITestInvoker> test;\n    };\n\n    TestCase makeTestCase(  ITestInvoker* testCase,\n                            std::string const& className,\n                            NameAndTags const& nameAndTags,\n                            SourceLineInfo const& lineInfo );\n}\n\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\n// end catch_test_case_info.h\n// start catch_interfaces_runner.h\n\nnamespace Catch {\n\n    struct IRunner {\n        virtual ~IRunner();\n        virtual bool aborting() const = 0;\n    };\n}\n\n// end catch_interfaces_runner.h\n\n#ifdef __OBJC__\n// start catch_objc.hpp\n\n#import <objc/runtime.h>\n\n#include <string>\n\n// NB. Any general catch headers included here must be included\n// in catch.hpp first to make sure they are included by the single\n// header for non obj-usage\n\n///////////////////////////////////////////////////////////////////////////////\n// This protocol is really only here for (self) documenting purposes, since\n// all its methods are optional.\n@protocol OcFixture\n\n@optional\n\n-(void) setUp;\n-(void) tearDown;\n\n@end\n\nnamespace Catch {\n\n    class OcMethod : public ITestInvoker {\n\n    public:\n        OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}\n\n        virtual void invoke() const {\n            id obj = [[m_cls alloc] init];\n\n            performOptionalSelector( obj, @selector(setUp)  );\n            performOptionalSelector( obj, m_sel );\n            performOptionalSelector( obj, @selector(tearDown)  );\n\n            arcSafeRelease( obj );\n        }\n    private:\n        virtual ~OcMethod() {}\n\n        Class m_cls;\n        SEL m_sel;\n    };\n\n    namespace Detail{\n\n        inline std::string getAnnotation(   Class cls,\n                                            std::string const& annotationName,\n                                            std::string const& testCaseName ) {\n            NSString* selStr = [[NSString alloc] initWithFormat:@\"Catch_%s_%s\", annotationName.c_str(), testCaseName.c_str()];\n            SEL sel = NSSelectorFromString( selStr );\n            arcSafeRelease( selStr );\n            id value = performOptionalSelector( cls, sel );\n            if( value )\n                return [(NSString*)value UTF8String];\n            return \"\";\n        }\n    }\n\n    inline std::size_t registerTestMethods() {\n        std::size_t noTestMethods = 0;\n        int noClasses = objc_getClassList( nullptr, 0 );\n\n        Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);\n        objc_getClassList( classes, noClasses );\n\n        for( int c = 0; c < noClasses; c++ ) {\n            Class cls = classes[c];\n            {\n                u_int count;\n                Method* methods = class_copyMethodList( cls, &count );\n                for( u_int m = 0; m < count ; m++ ) {\n                    SEL selector = method_getName(methods[m]);\n                    std::string methodName = sel_getName(selector);\n                    if( startsWith( methodName, \"Catch_TestCase_\" ) ) {\n                        std::string testCaseName = methodName.substr( 15 );\n                        std::string name = Detail::getAnnotation( cls, \"Name\", testCaseName );\n                        std::string desc = Detail::getAnnotation( cls, \"Description\", testCaseName );\n                        const char* className = class_getName( cls );\n\n                        getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo(\"\",0) ) );\n                        noTestMethods++;\n                    }\n                }\n                free(methods);\n            }\n        }\n        return noTestMethods;\n    }\n\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n\n    namespace Matchers {\n        namespace Impl {\n        namespace NSStringMatchers {\n\n            struct StringHolder : MatcherBase<NSString*>{\n                StringHolder( NSString* substr ) : m_substr( [substr copy] ){}\n                StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}\n                StringHolder() {\n                    arcSafeRelease( m_substr );\n                }\n\n                bool match( NSString* arg ) const override {\n                    return false;\n                }\n\n                NSString* CATCH_ARC_STRONG m_substr;\n            };\n\n            struct Equals : StringHolder {\n                Equals( NSString* substr ) : StringHolder( substr ){}\n\n                bool match( NSString* str ) const override {\n                    return  (str != nil || m_substr == nil ) &&\n                            [str isEqualToString:m_substr];\n                }\n\n                std::string describe() const override {\n                    return \"equals string: \" + Catch::Detail::stringify( m_substr );\n                }\n            };\n\n            struct Contains : StringHolder {\n                Contains( NSString* substr ) : StringHolder( substr ){}\n\n                bool match( NSString* str ) const {\n                    return  (str != nil || m_substr == nil ) &&\n                            [str rangeOfString:m_substr].location != NSNotFound;\n                }\n\n                std::string describe() const override {\n                    return \"contains string: \" + Catch::Detail::stringify( m_substr );\n                }\n            };\n\n            struct StartsWith : StringHolder {\n                StartsWith( NSString* substr ) : StringHolder( substr ){}\n\n                bool match( NSString* str ) const override {\n                    return  (str != nil || m_substr == nil ) &&\n                            [str rangeOfString:m_substr].location == 0;\n                }\n\n                std::string describe() const override {\n                    return \"starts with: \" + Catch::Detail::stringify( m_substr );\n                }\n            };\n            struct EndsWith : StringHolder {\n                EndsWith( NSString* substr ) : StringHolder( substr ){}\n\n                bool match( NSString* str ) const override {\n                    return  (str != nil || m_substr == nil ) &&\n                            [str rangeOfString:m_substr].location == [str length] - [m_substr length];\n                }\n\n                std::string describe() const override {\n                    return \"ends with: \" + Catch::Detail::stringify( m_substr );\n                }\n            };\n\n        } // namespace NSStringMatchers\n        } // namespace Impl\n\n        inline Impl::NSStringMatchers::Equals\n            Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }\n\n        inline Impl::NSStringMatchers::Contains\n            Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }\n\n        inline Impl::NSStringMatchers::StartsWith\n            StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }\n\n        inline Impl::NSStringMatchers::EndsWith\n            EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }\n\n    } // namespace Matchers\n\n    using namespace Matchers;\n\n#endif // CATCH_CONFIG_DISABLE_MATCHERS\n\n} // namespace Catch\n\n///////////////////////////////////////////////////////////////////////////////\n#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix\n#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \\\n+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \\\n{ \\\nreturn @ name; \\\n} \\\n+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \\\n{ \\\nreturn @ desc; \\\n} \\\n-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix )\n\n#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ )\n\n// end catch_objc.hpp\n#endif\n\n#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES\n// start catch_external_interfaces.h\n\n// start catch_reporter_bases.hpp\n\n// start catch_interfaces_reporter.h\n\n// start catch_config.hpp\n\n// start catch_test_spec_parser.h\n\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wpadded\"\n#endif\n\n// start catch_test_spec.h\n\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wpadded\"\n#endif\n\n// start catch_wildcard_pattern.h\n\nnamespace Catch\n{\n    class WildcardPattern {\n        enum WildcardPosition {\n            NoWildcard = 0,\n            WildcardAtStart = 1,\n            WildcardAtEnd = 2,\n            WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd\n        };\n\n    public:\n\n        WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity );\n        virtual ~WildcardPattern() = default;\n        virtual bool matches( std::string const& str ) const;\n\n    private:\n        std::string adjustCase( std::string const& str ) const;\n        CaseSensitive::Choice m_caseSensitivity;\n        WildcardPosition m_wildcard = NoWildcard;\n        std::string m_pattern;\n    };\n}\n\n// end catch_wildcard_pattern.h\n#include <string>\n#include <vector>\n#include <memory>\n\nnamespace Catch {\n\n    class TestSpec {\n        struct Pattern {\n            virtual ~Pattern();\n            virtual bool matches( TestCaseInfo const& testCase ) const = 0;\n        };\n        using PatternPtr = std::shared_ptr<Pattern>;\n\n        class NamePattern : public Pattern {\n        public:\n            NamePattern( std::string const& name );\n            virtual ~NamePattern();\n            virtual bool matches( TestCaseInfo const& testCase ) const override;\n        private:\n            WildcardPattern m_wildcardPattern;\n        };\n\n        class TagPattern : public Pattern {\n        public:\n            TagPattern( std::string const& tag );\n            virtual ~TagPattern();\n            virtual bool matches( TestCaseInfo const& testCase ) const override;\n        private:\n            std::string m_tag;\n        };\n\n        class ExcludedPattern : public Pattern {\n        public:\n            ExcludedPattern( PatternPtr const& underlyingPattern );\n            virtual ~ExcludedPattern();\n            virtual bool matches( TestCaseInfo const& testCase ) const override;\n        private:\n            PatternPtr m_underlyingPattern;\n        };\n\n        struct Filter {\n            std::vector<PatternPtr> m_patterns;\n\n            bool matches( TestCaseInfo const& testCase ) const;\n        };\n\n    public:\n        bool hasFilters() const;\n        bool matches( TestCaseInfo const& testCase ) const;\n\n    private:\n        std::vector<Filter> m_filters;\n\n        friend class TestSpecParser;\n    };\n}\n\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\n// end catch_test_spec.h\n// start catch_interfaces_tag_alias_registry.h\n\n#include <string>\n\nnamespace Catch {\n\n    struct TagAlias;\n\n    struct ITagAliasRegistry {\n        virtual ~ITagAliasRegistry();\n        // Nullptr if not present\n        virtual TagAlias const* find( std::string const& alias ) const = 0;\n        virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;\n\n        static ITagAliasRegistry const& get();\n    };\n\n} // end namespace Catch\n\n// end catch_interfaces_tag_alias_registry.h\nnamespace Catch {\n\n    class TestSpecParser {\n        enum Mode{ None, Name, QuotedName, Tag, EscapedName };\n        Mode m_mode = None;\n        bool m_exclusion = false;\n        std::size_t m_start = std::string::npos, m_pos = 0;\n        std::string m_arg;\n        std::vector<std::size_t> m_escapeChars;\n        TestSpec::Filter m_currentFilter;\n        TestSpec m_testSpec;\n        ITagAliasRegistry const* m_tagAliases = nullptr;\n\n    public:\n        TestSpecParser( ITagAliasRegistry const& tagAliases );\n\n        TestSpecParser& parse( std::string const& arg );\n        TestSpec testSpec();\n\n    private:\n        void visitChar( char c );\n        void startNewMode( Mode mode, std::size_t start );\n        void escape();\n        std::string subString() const;\n\n        template<typename T>\n        void addPattern() {\n            std::string token = subString();\n            for( std::size_t i = 0; i < m_escapeChars.size(); ++i )\n                token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );\n            m_escapeChars.clear();\n            if( startsWith( token, \"exclude:\" ) ) {\n                m_exclusion = true;\n                token = token.substr( 8 );\n            }\n            if( !token.empty() ) {\n                TestSpec::PatternPtr pattern = std::make_shared<T>( token );\n                if( m_exclusion )\n                    pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );\n                m_currentFilter.m_patterns.push_back( pattern );\n            }\n            m_exclusion = false;\n            m_mode = None;\n        }\n\n        void addFilter();\n    };\n    TestSpec parseTestSpec( std::string const& arg );\n\n} // namespace Catch\n\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\n// end catch_test_spec_parser.h\n// Libstdc++ doesn't like incomplete classes for unique_ptr\n\n#include <memory>\n#include <vector>\n#include <string>\n\n#ifndef CATCH_CONFIG_CONSOLE_WIDTH\n#define CATCH_CONFIG_CONSOLE_WIDTH 80\n#endif\n\nnamespace Catch {\n\n    struct IStream;\n\n    struct ConfigData {\n        bool listTests = false;\n        bool listTags = false;\n        bool listReporters = false;\n        bool listTestNamesOnly = false;\n\n        bool showSuccessfulTests = false;\n        bool shouldDebugBreak = false;\n        bool noThrow = false;\n        bool showHelp = false;\n        bool showInvisibles = false;\n        bool filenamesAsTags = false;\n        bool libIdentify = false;\n\n        int abortAfter = -1;\n        unsigned int rngSeed = 0;\n        int benchmarkResolutionMultiple = 100;\n\n        Verbosity verbosity = Verbosity::Normal;\n        WarnAbout::What warnings = WarnAbout::Nothing;\n        ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;\n        RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;\n        UseColour::YesOrNo useColour = UseColour::Auto;\n        WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;\n\n        std::string outputFilename;\n        std::string name;\n        std::string processName;\n#ifndef CATCH_CONFIG_DEFAULT_REPORTER\n#define CATCH_CONFIG_DEFAULT_REPORTER \"console\"\n#endif\n        std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;\n#undef CATCH_CONFIG_DEFAULT_REPORTER\n\n        std::vector<std::string> testsOrTags;\n        std::vector<std::string> sectionsToRun;\n    };\n\n    class Config : public IConfig {\n    public:\n\n        Config() = default;\n        Config( ConfigData const& data );\n        virtual ~Config() = default;\n\n        std::string const& getFilename() const;\n\n        bool listTests() const;\n        bool listTestNamesOnly() const;\n        bool listTags() const;\n        bool listReporters() const;\n\n        std::string getProcessName() const;\n        std::string const& getReporterName() const;\n\n        std::vector<std::string> const& getTestsOrTags() const;\n        std::vector<std::string> const& getSectionsToRun() const override;\n\n        virtual TestSpec const& testSpec() const override;\n        bool hasTestFilters() const override;\n\n        bool showHelp() const;\n\n        // IConfig interface\n        bool allowThrows() const override;\n        std::ostream& stream() const override;\n        std::string name() const override;\n        bool includeSuccessfulResults() const override;\n        bool warnAboutMissingAssertions() const override;\n        bool warnAboutNoTests() const override;\n        ShowDurations::OrNot showDurations() const override;\n        RunTests::InWhatOrder runOrder() const override;\n        unsigned int rngSeed() const override;\n        int benchmarkResolutionMultiple() const override;\n        UseColour::YesOrNo useColour() const override;\n        bool shouldDebugBreak() const override;\n        int abortAfter() const override;\n        bool showInvisibles() const override;\n        Verbosity verbosity() const override;\n\n    private:\n\n        IStream const* openStream();\n        ConfigData m_data;\n\n        std::unique_ptr<IStream const> m_stream;\n        TestSpec m_testSpec;\n        bool m_hasTestFilters = false;\n    };\n\n} // end namespace Catch\n\n// end catch_config.hpp\n// start catch_assertionresult.h\n\n#include <string>\n\nnamespace Catch {\n\n    struct AssertionResultData\n    {\n        AssertionResultData() = delete;\n\n        AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );\n\n        std::string message;\n        mutable std::string reconstructedExpression;\n        LazyExpression lazyExpression;\n        ResultWas::OfType resultType;\n\n        std::string reconstructExpression() const;\n    };\n\n    class AssertionResult {\n    public:\n        AssertionResult() = delete;\n        AssertionResult( AssertionInfo const& info, AssertionResultData const& data );\n\n        bool isOk() const;\n        bool succeeded() const;\n        ResultWas::OfType getResultType() const;\n        bool hasExpression() const;\n        bool hasMessage() const;\n        std::string getExpression() const;\n        std::string getExpressionInMacro() const;\n        bool hasExpandedExpression() const;\n        std::string getExpandedExpression() const;\n        std::string getMessage() const;\n        SourceLineInfo getSourceInfo() const;\n        StringRef getTestMacroName() const;\n\n    //protected:\n        AssertionInfo m_info;\n        AssertionResultData m_resultData;\n    };\n\n} // end namespace Catch\n\n// end catch_assertionresult.h\n// start catch_option.hpp\n\nnamespace Catch {\n\n    // An optional type\n    template<typename T>\n    class Option {\n    public:\n        Option() : nullableValue( nullptr ) {}\n        Option( T const& _value )\n        : nullableValue( new( storage ) T( _value ) )\n        {}\n        Option( Option const& _other )\n        : nullableValue( _other ? new( storage ) T( *_other ) : nullptr )\n        {}\n\n        ~Option() {\n            reset();\n        }\n\n        Option& operator= ( Option const& _other ) {\n            if( &_other != this ) {\n                reset();\n                if( _other )\n                    nullableValue = new( storage ) T( *_other );\n            }\n            return *this;\n        }\n        Option& operator = ( T const& _value ) {\n            reset();\n            nullableValue = new( storage ) T( _value );\n            return *this;\n        }\n\n        void reset() {\n            if( nullableValue )\n                nullableValue->~T();\n            nullableValue = nullptr;\n        }\n\n        T& operator*() { return *nullableValue; }\n        T const& operator*() const { return *nullableValue; }\n        T* operator->() { return nullableValue; }\n        const T* operator->() const { return nullableValue; }\n\n        T valueOr( T const& defaultValue ) const {\n            return nullableValue ? *nullableValue : defaultValue;\n        }\n\n        bool some() const { return nullableValue != nullptr; }\n        bool none() const { return nullableValue == nullptr; }\n\n        bool operator !() const { return nullableValue == nullptr; }\n        explicit operator bool() const {\n            return some();\n        }\n\n    private:\n        T *nullableValue;\n        alignas(alignof(T)) char storage[sizeof(T)];\n    };\n\n} // end namespace Catch\n\n// end catch_option.hpp\n#include <string>\n#include <iosfwd>\n#include <map>\n#include <set>\n#include <memory>\n\nnamespace Catch {\n\n    struct ReporterConfig {\n        explicit ReporterConfig( IConfigPtr const& _fullConfig );\n\n        ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream );\n\n        std::ostream& stream() const;\n        IConfigPtr fullConfig() const;\n\n    private:\n        std::ostream* m_stream;\n        IConfigPtr m_fullConfig;\n    };\n\n    struct ReporterPreferences {\n        bool shouldRedirectStdOut = false;\n        bool shouldReportAllAssertions = false;\n    };\n\n    template<typename T>\n    struct LazyStat : Option<T> {\n        LazyStat& operator=( T const& _value ) {\n            Option<T>::operator=( _value );\n            used = false;\n            return *this;\n        }\n        void reset() {\n            Option<T>::reset();\n            used = false;\n        }\n        bool used = false;\n    };\n\n    struct TestRunInfo {\n        TestRunInfo( std::string const& _name );\n        std::string name;\n    };\n    struct GroupInfo {\n        GroupInfo(  std::string const& _name,\n                    std::size_t _groupIndex,\n                    std::size_t _groupsCount );\n\n        std::string name;\n        std::size_t groupIndex;\n        std::size_t groupsCounts;\n    };\n\n    struct AssertionStats {\n        AssertionStats( AssertionResult const& _assertionResult,\n                        std::vector<MessageInfo> const& _infoMessages,\n                        Totals const& _totals );\n\n        AssertionStats( AssertionStats const& )              = default;\n        AssertionStats( AssertionStats && )                  = default;\n        AssertionStats& operator = ( AssertionStats const& ) = delete;\n        AssertionStats& operator = ( AssertionStats && )     = delete;\n        virtual ~AssertionStats();\n\n        AssertionResult assertionResult;\n        std::vector<MessageInfo> infoMessages;\n        Totals totals;\n    };\n\n    struct SectionStats {\n        SectionStats(   SectionInfo const& _sectionInfo,\n                        Counts const& _assertions,\n                        double _durationInSeconds,\n                        bool _missingAssertions );\n        SectionStats( SectionStats const& )              = default;\n        SectionStats( SectionStats && )                  = default;\n        SectionStats& operator = ( SectionStats const& ) = default;\n        SectionStats& operator = ( SectionStats && )     = default;\n        virtual ~SectionStats();\n\n        SectionInfo sectionInfo;\n        Counts assertions;\n        double durationInSeconds;\n        bool missingAssertions;\n    };\n\n    struct TestCaseStats {\n        TestCaseStats(  TestCaseInfo const& _testInfo,\n                        Totals const& _totals,\n                        std::string const& _stdOut,\n                        std::string const& _stdErr,\n                        bool _aborting );\n\n        TestCaseStats( TestCaseStats const& )              = default;\n        TestCaseStats( TestCaseStats && )                  = default;\n        TestCaseStats& operator = ( TestCaseStats const& ) = default;\n        TestCaseStats& operator = ( TestCaseStats && )     = default;\n        virtual ~TestCaseStats();\n\n        TestCaseInfo testInfo;\n        Totals totals;\n        std::string stdOut;\n        std::string stdErr;\n        bool aborting;\n    };\n\n    struct TestGroupStats {\n        TestGroupStats( GroupInfo const& _groupInfo,\n                        Totals const& _totals,\n                        bool _aborting );\n        TestGroupStats( GroupInfo const& _groupInfo );\n\n        TestGroupStats( TestGroupStats const& )              = default;\n        TestGroupStats( TestGroupStats && )                  = default;\n        TestGroupStats& operator = ( TestGroupStats const& ) = default;\n        TestGroupStats& operator = ( TestGroupStats && )     = default;\n        virtual ~TestGroupStats();\n\n        GroupInfo groupInfo;\n        Totals totals;\n        bool aborting;\n    };\n\n    struct TestRunStats {\n        TestRunStats(   TestRunInfo const& _runInfo,\n                        Totals const& _totals,\n                        bool _aborting );\n\n        TestRunStats( TestRunStats const& )              = default;\n        TestRunStats( TestRunStats && )                  = default;\n        TestRunStats& operator = ( TestRunStats const& ) = default;\n        TestRunStats& operator = ( TestRunStats && )     = default;\n        virtual ~TestRunStats();\n\n        TestRunInfo runInfo;\n        Totals totals;\n        bool aborting;\n    };\n\n    struct BenchmarkInfo {\n        std::string name;\n    };\n    struct BenchmarkStats {\n        BenchmarkInfo info;\n        std::size_t iterations;\n        uint64_t elapsedTimeInNanoseconds;\n    };\n\n    struct IStreamingReporter {\n        virtual ~IStreamingReporter() = default;\n\n        // Implementing class must also provide the following static methods:\n        // static std::string getDescription();\n        // static std::set<Verbosity> getSupportedVerbosities()\n\n        virtual ReporterPreferences getPreferences() const = 0;\n\n        virtual void noMatchingTestCases( std::string const& spec ) = 0;\n\n        virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;\n        virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;\n\n        virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;\n        virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;\n\n        // *** experimental ***\n        virtual void benchmarkStarting( BenchmarkInfo const& ) {}\n\n        virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;\n\n        // The return value indicates if the messages buffer should be cleared:\n        virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;\n\n        // *** experimental ***\n        virtual void benchmarkEnded( BenchmarkStats const& ) {}\n\n        virtual void sectionEnded( SectionStats const& sectionStats ) = 0;\n        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;\n        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;\n        virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;\n\n        virtual void skipTest( TestCaseInfo const& testInfo ) = 0;\n\n        // Default empty implementation provided\n        virtual void fatalErrorEncountered( StringRef name );\n\n        virtual bool isMulti() const;\n    };\n    using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;\n\n    struct IReporterFactory {\n        virtual ~IReporterFactory();\n        virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0;\n        virtual std::string getDescription() const = 0;\n    };\n    using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;\n\n    struct IReporterRegistry {\n        using FactoryMap = std::map<std::string, IReporterFactoryPtr>;\n        using Listeners = std::vector<IReporterFactoryPtr>;\n\n        virtual ~IReporterRegistry();\n        virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0;\n        virtual FactoryMap const& getFactories() const = 0;\n        virtual Listeners const& getListeners() const = 0;\n    };\n\n} // end namespace Catch\n\n// end catch_interfaces_reporter.h\n#include <algorithm>\n#include <cstring>\n#include <cfloat>\n#include <cstdio>\n#include <cassert>\n#include <memory>\n#include <ostream>\n\nnamespace Catch {\n    void prepareExpandedExpression(AssertionResult& result);\n\n    // Returns double formatted as %.3f (format expected on output)\n    std::string getFormattedDuration( double duration );\n\n    template<typename DerivedT>\n    struct StreamingReporterBase : IStreamingReporter {\n\n        StreamingReporterBase( ReporterConfig const& _config )\n        :   m_config( _config.fullConfig() ),\n            stream( _config.stream() )\n        {\n            m_reporterPrefs.shouldRedirectStdOut = false;\n            if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )\n                CATCH_ERROR( \"Verbosity level not supported by this reporter\" );\n        }\n\n        ReporterPreferences getPreferences() const override {\n            return m_reporterPrefs;\n        }\n\n        static std::set<Verbosity> getSupportedVerbosities() {\n            return { Verbosity::Normal };\n        }\n\n        ~StreamingReporterBase() override = default;\n\n        void noMatchingTestCases(std::string const&) override {}\n\n        void testRunStarting(TestRunInfo const& _testRunInfo) override {\n            currentTestRunInfo = _testRunInfo;\n        }\n        void testGroupStarting(GroupInfo const& _groupInfo) override {\n            currentGroupInfo = _groupInfo;\n        }\n\n        void testCaseStarting(TestCaseInfo const& _testInfo) override  {\n            currentTestCaseInfo = _testInfo;\n        }\n        void sectionStarting(SectionInfo const& _sectionInfo) override {\n            m_sectionStack.push_back(_sectionInfo);\n        }\n\n        void sectionEnded(SectionStats const& /* _sectionStats */) override {\n            m_sectionStack.pop_back();\n        }\n        void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {\n            currentTestCaseInfo.reset();\n        }\n        void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override {\n            currentGroupInfo.reset();\n        }\n        void testRunEnded(TestRunStats const& /* _testRunStats */) override {\n            currentTestCaseInfo.reset();\n            currentGroupInfo.reset();\n            currentTestRunInfo.reset();\n        }\n\n        void skipTest(TestCaseInfo const&) override {\n            // Don't do anything with this by default.\n            // It can optionally be overridden in the derived class.\n        }\n\n        IConfigPtr m_config;\n        std::ostream& stream;\n\n        LazyStat<TestRunInfo> currentTestRunInfo;\n        LazyStat<GroupInfo> currentGroupInfo;\n        LazyStat<TestCaseInfo> currentTestCaseInfo;\n\n        std::vector<SectionInfo> m_sectionStack;\n        ReporterPreferences m_reporterPrefs;\n    };\n\n    template<typename DerivedT>\n    struct CumulativeReporterBase : IStreamingReporter {\n        template<typename T, typename ChildNodeT>\n        struct Node {\n            explicit Node( T const& _value ) : value( _value ) {}\n            virtual ~Node() {}\n\n            using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;\n            T value;\n            ChildNodes children;\n        };\n        struct SectionNode {\n            explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}\n            virtual ~SectionNode() = default;\n\n            bool operator == (SectionNode const& other) const {\n                return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;\n            }\n            bool operator == (std::shared_ptr<SectionNode> const& other) const {\n                return operator==(*other);\n            }\n\n            SectionStats stats;\n            using ChildSections = std::vector<std::shared_ptr<SectionNode>>;\n            using Assertions = std::vector<AssertionStats>;\n            ChildSections childSections;\n            Assertions assertions;\n            std::string stdOut;\n            std::string stdErr;\n        };\n\n        struct BySectionInfo {\n            BySectionInfo( SectionInfo const& other ) : m_other( other ) {}\n            BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}\n            bool operator() (std::shared_ptr<SectionNode> const& node) const {\n                return ((node->stats.sectionInfo.name == m_other.name) &&\n                        (node->stats.sectionInfo.lineInfo == m_other.lineInfo));\n            }\n            void operator=(BySectionInfo const&) = delete;\n\n        private:\n            SectionInfo const& m_other;\n        };\n\n        using TestCaseNode = Node<TestCaseStats, SectionNode>;\n        using TestGroupNode = Node<TestGroupStats, TestCaseNode>;\n        using TestRunNode = Node<TestRunStats, TestGroupNode>;\n\n        CumulativeReporterBase( ReporterConfig const& _config )\n        :   m_config( _config.fullConfig() ),\n            stream( _config.stream() )\n        {\n            m_reporterPrefs.shouldRedirectStdOut = false;\n            if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )\n                CATCH_ERROR( \"Verbosity level not supported by this reporter\" );\n        }\n        ~CumulativeReporterBase() override = default;\n\n        ReporterPreferences getPreferences() const override {\n            return m_reporterPrefs;\n        }\n\n        static std::set<Verbosity> getSupportedVerbosities() {\n            return { Verbosity::Normal };\n        }\n\n        void testRunStarting( TestRunInfo const& ) override {}\n        void testGroupStarting( GroupInfo const& ) override {}\n\n        void testCaseStarting( TestCaseInfo const& ) override {}\n\n        void sectionStarting( SectionInfo const& sectionInfo ) override {\n            SectionStats incompleteStats( sectionInfo, Counts(), 0, false );\n            std::shared_ptr<SectionNode> node;\n            if( m_sectionStack.empty() ) {\n                if( !m_rootSection )\n                    m_rootSection = std::make_shared<SectionNode>( incompleteStats );\n                node = m_rootSection;\n            }\n            else {\n                SectionNode& parentNode = *m_sectionStack.back();\n                auto it =\n                    std::find_if(   parentNode.childSections.begin(),\n                                    parentNode.childSections.end(),\n                                    BySectionInfo( sectionInfo ) );\n                if( it == parentNode.childSections.end() ) {\n                    node = std::make_shared<SectionNode>( incompleteStats );\n                    parentNode.childSections.push_back( node );\n                }\n                else\n                    node = *it;\n            }\n            m_sectionStack.push_back( node );\n            m_deepestSection = std::move(node);\n        }\n\n        void assertionStarting(AssertionInfo const&) override {}\n\n        bool assertionEnded(AssertionStats const& assertionStats) override {\n            assert(!m_sectionStack.empty());\n            // AssertionResult holds a pointer to a temporary DecomposedExpression,\n            // which getExpandedExpression() calls to build the expression string.\n            // Our section stack copy of the assertionResult will likely outlive the\n            // temporary, so it must be expanded or discarded now to avoid calling\n            // a destroyed object later.\n            prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) );\n            SectionNode& sectionNode = *m_sectionStack.back();\n            sectionNode.assertions.push_back(assertionStats);\n            return true;\n        }\n        void sectionEnded(SectionStats const& sectionStats) override {\n            assert(!m_sectionStack.empty());\n            SectionNode& node = *m_sectionStack.back();\n            node.stats = sectionStats;\n            m_sectionStack.pop_back();\n        }\n        void testCaseEnded(TestCaseStats const& testCaseStats) override {\n            auto node = std::make_shared<TestCaseNode>(testCaseStats);\n            assert(m_sectionStack.size() == 0);\n            node->children.push_back(m_rootSection);\n            m_testCases.push_back(node);\n            m_rootSection.reset();\n\n            assert(m_deepestSection);\n            m_deepestSection->stdOut = testCaseStats.stdOut;\n            m_deepestSection->stdErr = testCaseStats.stdErr;\n        }\n        void testGroupEnded(TestGroupStats const& testGroupStats) override {\n            auto node = std::make_shared<TestGroupNode>(testGroupStats);\n            node->children.swap(m_testCases);\n            m_testGroups.push_back(node);\n        }\n        void testRunEnded(TestRunStats const& testRunStats) override {\n            auto node = std::make_shared<TestRunNode>(testRunStats);\n            node->children.swap(m_testGroups);\n            m_testRuns.push_back(node);\n            testRunEndedCumulative();\n        }\n        virtual void testRunEndedCumulative() = 0;\n\n        void skipTest(TestCaseInfo const&) override {}\n\n        IConfigPtr m_config;\n        std::ostream& stream;\n        std::vector<AssertionStats> m_assertions;\n        std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;\n        std::vector<std::shared_ptr<TestCaseNode>> m_testCases;\n        std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;\n\n        std::vector<std::shared_ptr<TestRunNode>> m_testRuns;\n\n        std::shared_ptr<SectionNode> m_rootSection;\n        std::shared_ptr<SectionNode> m_deepestSection;\n        std::vector<std::shared_ptr<SectionNode>> m_sectionStack;\n        ReporterPreferences m_reporterPrefs;\n    };\n\n    template<char C>\n    char const* getLineOfChars() {\n        static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};\n        if( !*line ) {\n            std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );\n            line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;\n        }\n        return line;\n    }\n\n    struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {\n        TestEventListenerBase( ReporterConfig const& _config );\n\n        static std::set<Verbosity> getSupportedVerbosities();\n\n        void assertionStarting(AssertionInfo const&) override;\n        bool assertionEnded(AssertionStats const&) override;\n    };\n\n} // end namespace Catch\n\n// end catch_reporter_bases.hpp\n// start catch_console_colour.h\n\nnamespace Catch {\n\n    struct Colour {\n        enum Code {\n            None = 0,\n\n            White,\n            Red,\n            Green,\n            Blue,\n            Cyan,\n            Yellow,\n            Grey,\n\n            Bright = 0x10,\n\n            BrightRed = Bright | Red,\n            BrightGreen = Bright | Green,\n            LightGrey = Bright | Grey,\n            BrightWhite = Bright | White,\n            BrightYellow = Bright | Yellow,\n\n            // By intention\n            FileName = LightGrey,\n            Warning = BrightYellow,\n            ResultError = BrightRed,\n            ResultSuccess = BrightGreen,\n            ResultExpectedFailure = Warning,\n\n            Error = BrightRed,\n            Success = Green,\n\n            OriginalExpression = Cyan,\n            ReconstructedExpression = BrightYellow,\n\n            SecondaryText = LightGrey,\n            Headers = White\n        };\n\n        // Use constructed object for RAII guard\n        Colour( Code _colourCode );\n        Colour( Colour&& other ) noexcept;\n        Colour& operator=( Colour&& other ) noexcept;\n        ~Colour();\n\n        // Use static method for one-shot changes\n        static void use( Code _colourCode );\n\n    private:\n        bool m_moved = false;\n    };\n\n    std::ostream& operator << ( std::ostream& os, Colour const& );\n\n} // end namespace Catch\n\n// end catch_console_colour.h\n// start catch_reporter_registrars.hpp\n\n\nnamespace Catch {\n\n    template<typename T>\n    class ReporterRegistrar {\n\n        class ReporterFactory : public IReporterFactory {\n\n            virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {\n                return std::unique_ptr<T>( new T( config ) );\n            }\n\n            virtual std::string getDescription() const override {\n                return T::getDescription();\n            }\n        };\n\n    public:\n\n        explicit ReporterRegistrar( std::string const& name ) {\n            getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() );\n        }\n    };\n\n    template<typename T>\n    class ListenerRegistrar {\n\n        class ListenerFactory : public IReporterFactory {\n\n            virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {\n                return std::unique_ptr<T>( new T( config ) );\n            }\n            virtual std::string getDescription() const override {\n                return std::string();\n            }\n        };\n\n    public:\n\n        ListenerRegistrar() {\n            getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() );\n        }\n    };\n}\n\n#if !defined(CATCH_CONFIG_DISABLE)\n\n#define CATCH_REGISTER_REPORTER( name, reporterType ) \\\n    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS          \\\n    namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \\\n    CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\n\n#define CATCH_REGISTER_LISTENER( listenerType ) \\\n     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS   \\\n     namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \\\n     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS\n#else // CATCH_CONFIG_DISABLE\n\n#define CATCH_REGISTER_REPORTER(name, reporterType)\n#define CATCH_REGISTER_LISTENER(listenerType)\n\n#endif // CATCH_CONFIG_DISABLE\n\n// end catch_reporter_registrars.hpp\n// Allow users to base their work off existing reporters\n// start catch_reporter_compact.h\n\nnamespace Catch {\n\n    struct CompactReporter : StreamingReporterBase<CompactReporter> {\n\n        using StreamingReporterBase::StreamingReporterBase;\n\n        ~CompactReporter() override;\n\n        static std::string getDescription();\n\n        ReporterPreferences getPreferences() const override;\n\n        void noMatchingTestCases(std::string const& spec) override;\n\n        void assertionStarting(AssertionInfo const&) override;\n\n        bool assertionEnded(AssertionStats const& _assertionStats) override;\n\n        void sectionEnded(SectionStats const& _sectionStats) override;\n\n        void testRunEnded(TestRunStats const& _testRunStats) override;\n\n    };\n\n} // end namespace Catch\n\n// end catch_reporter_compact.h\n// start catch_reporter_console.h\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch\n                              // Note that 4062 (not all labels are handled\n                              // and default is missing) is enabled\n#endif\n\nnamespace Catch {\n    // Fwd decls\n    struct SummaryColumn;\n    class TablePrinter;\n\n    struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {\n        std::unique_ptr<TablePrinter> m_tablePrinter;\n\n        ConsoleReporter(ReporterConfig const& config);\n        ~ConsoleReporter() override;\n        static std::string getDescription();\n\n        void noMatchingTestCases(std::string const& spec) override;\n\n        void assertionStarting(AssertionInfo const&) override;\n\n        bool assertionEnded(AssertionStats const& _assertionStats) override;\n\n        void sectionStarting(SectionInfo const& _sectionInfo) override;\n        void sectionEnded(SectionStats const& _sectionStats) override;\n\n        void benchmarkStarting(BenchmarkInfo const& info) override;\n        void benchmarkEnded(BenchmarkStats const& stats) override;\n\n        void testCaseEnded(TestCaseStats const& _testCaseStats) override;\n        void testGroupEnded(TestGroupStats const& _testGroupStats) override;\n        void testRunEnded(TestRunStats const& _testRunStats) override;\n\n    private:\n\n        void lazyPrint();\n\n        void lazyPrintWithoutClosingBenchmarkTable();\n        void lazyPrintRunInfo();\n        void lazyPrintGroupInfo();\n        void printTestCaseAndSectionHeader();\n\n        void printClosedHeader(std::string const& _name);\n        void printOpenHeader(std::string const& _name);\n\n        // if string has a : in first line will set indent to follow it on\n        // subsequent lines\n        void printHeaderString(std::string const& _string, std::size_t indent = 0);\n\n        void printTotals(Totals const& totals);\n        void printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row);\n\n        void printTotalsDivider(Totals const& totals);\n        void printSummaryDivider();\n\n    private:\n        bool m_headerPrinted = false;\n    };\n\n} // end namespace Catch\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n// end catch_reporter_console.h\n// start catch_reporter_junit.h\n\n// start catch_xmlwriter.h\n\n#include <vector>\n\nnamespace Catch {\n\n    class XmlEncode {\n    public:\n        enum ForWhat { ForTextNodes, ForAttributes };\n\n        XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes );\n\n        void encodeTo( std::ostream& os ) const;\n\n        friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );\n\n    private:\n        std::string m_str;\n        ForWhat m_forWhat;\n    };\n\n    class XmlWriter {\n    public:\n\n        class ScopedElement {\n        public:\n            ScopedElement( XmlWriter* writer );\n\n            ScopedElement( ScopedElement&& other ) noexcept;\n            ScopedElement& operator=( ScopedElement&& other ) noexcept;\n\n            ~ScopedElement();\n\n            ScopedElement& writeText( std::string const& text, bool indent = true );\n\n            template<typename T>\n            ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {\n                m_writer->writeAttribute( name, attribute );\n                return *this;\n            }\n\n        private:\n            mutable XmlWriter* m_writer = nullptr;\n        };\n\n        XmlWriter( std::ostream& os = Catch::cout() );\n        ~XmlWriter();\n\n        XmlWriter( XmlWriter const& ) = delete;\n        XmlWriter& operator=( XmlWriter const& ) = delete;\n\n        XmlWriter& startElement( std::string const& name );\n\n        ScopedElement scopedElement( std::string const& name );\n\n        XmlWriter& endElement();\n\n        XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );\n\n        XmlWriter& writeAttribute( std::string const& name, bool attribute );\n\n        template<typename T>\n        XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {\n            ReusableStringStream rss;\n            rss << attribute;\n            return writeAttribute( name, rss.str() );\n        }\n\n        XmlWriter& writeText( std::string const& text, bool indent = true );\n\n        XmlWriter& writeComment( std::string const& text );\n\n        void writeStylesheetRef( std::string const& url );\n\n        XmlWriter& writeBlankLine();\n\n        void ensureTagClosed();\n\n    private:\n\n        void writeDeclaration();\n\n        void newlineIfNecessary();\n\n        bool m_tagIsOpen = false;\n        bool m_needsNewline = false;\n        std::vector<std::string> m_tags;\n        std::string m_indent;\n        std::ostream& m_os;\n    };\n\n}\n\n// end catch_xmlwriter.h\nnamespace Catch {\n\n    class JunitReporter : public CumulativeReporterBase<JunitReporter> {\n    public:\n        JunitReporter(ReporterConfig const& _config);\n\n        ~JunitReporter() override;\n\n        static std::string getDescription();\n\n        void noMatchingTestCases(std::string const& /*spec*/) override;\n\n        void testRunStarting(TestRunInfo const& runInfo) override;\n\n        void testGroupStarting(GroupInfo const& groupInfo) override;\n\n        void testCaseStarting(TestCaseInfo const& testCaseInfo) override;\n        bool assertionEnded(AssertionStats const& assertionStats) override;\n\n        void testCaseEnded(TestCaseStats const& testCaseStats) override;\n\n        void testGroupEnded(TestGroupStats const& testGroupStats) override;\n\n        void testRunEndedCumulative() override;\n\n        void writeGroup(TestGroupNode const& groupNode, double suiteTime);\n\n        void writeTestCase(TestCaseNode const& testCaseNode);\n\n        void writeSection(std::string const& className,\n                          std::string const& rootName,\n                          SectionNode const& sectionNode);\n\n        void writeAssertions(SectionNode const& sectionNode);\n        void writeAssertion(AssertionStats const& stats);\n\n        XmlWriter xml;\n        Timer suiteTimer;\n        std::string stdOutForSuite;\n        std::string stdErrForSuite;\n        unsigned int unexpectedExceptions = 0;\n        bool m_okToFail = false;\n    };\n\n} // end namespace Catch\n\n// end catch_reporter_junit.h\n// start catch_reporter_xml.h\n\nnamespace Catch {\n    class XmlReporter : public StreamingReporterBase<XmlReporter> {\n    public:\n        XmlReporter(ReporterConfig const& _config);\n\n        ~XmlReporter() override;\n\n        static std::string getDescription();\n\n        virtual std::string getStylesheetRef() const;\n\n        void writeSourceInfo(SourceLineInfo const& sourceInfo);\n\n    public: // StreamingReporterBase\n\n        void noMatchingTestCases(std::string const& s) override;\n\n        void testRunStarting(TestRunInfo const& testInfo) override;\n\n        void testGroupStarting(GroupInfo const& groupInfo) override;\n\n        void testCaseStarting(TestCaseInfo const& testInfo) override;\n\n        void sectionStarting(SectionInfo const& sectionInfo) override;\n\n        void assertionStarting(AssertionInfo const&) override;\n\n        bool assertionEnded(AssertionStats const& assertionStats) override;\n\n        void sectionEnded(SectionStats const& sectionStats) override;\n\n        void testCaseEnded(TestCaseStats const& testCaseStats) override;\n\n        void testGroupEnded(TestGroupStats const& testGroupStats) override;\n\n        void testRunEnded(TestRunStats const& testRunStats) override;\n\n    private:\n        Timer m_testCaseTimer;\n        XmlWriter m_xml;\n        int m_sectionDepth = 0;\n    };\n\n} // end namespace Catch\n\n// end catch_reporter_xml.h\n\n// end catch_external_interfaces.h\n#endif\n\n#endif // ! CATCH_CONFIG_IMPL_ONLY\n\n#ifdef CATCH_IMPL\n// start catch_impl.hpp\n\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wweak-vtables\"\n#endif\n\n// Keep these here for external reporters\n// start catch_test_case_tracker.h\n\n#include <string>\n#include <vector>\n#include <memory>\n\nnamespace Catch {\nnamespace TestCaseTracking {\n\n    struct NameAndLocation {\n        std::string name;\n        SourceLineInfo location;\n\n        NameAndLocation( std::string const& _name, SourceLineInfo const& _location );\n    };\n\n    struct ITracker;\n\n    using ITrackerPtr = std::shared_ptr<ITracker>;\n\n    struct ITracker {\n        virtual ~ITracker();\n\n        // static queries\n        virtual NameAndLocation const& nameAndLocation() const = 0;\n\n        // dynamic queries\n        virtual bool isComplete() const = 0; // Successfully completed or failed\n        virtual bool isSuccessfullyCompleted() const = 0;\n        virtual bool isOpen() const = 0; // Started but not complete\n        virtual bool hasChildren() const = 0;\n\n        virtual ITracker& parent() = 0;\n\n        // actions\n        virtual void close() = 0; // Successfully complete\n        virtual void fail() = 0;\n        virtual void markAsNeedingAnotherRun() = 0;\n\n        virtual void addChild( ITrackerPtr const& child ) = 0;\n        virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0;\n        virtual void openChild() = 0;\n\n        // Debug/ checking\n        virtual bool isSectionTracker() const = 0;\n        virtual bool isGeneratorTracker() const = 0;\n    };\n\n    class TrackerContext {\n\n        enum RunState {\n            NotStarted,\n            Executing,\n            CompletedCycle\n        };\n\n        ITrackerPtr m_rootTracker;\n        ITracker* m_currentTracker = nullptr;\n        RunState m_runState = NotStarted;\n\n    public:\n\n        static TrackerContext& instance();\n\n        ITracker& startRun();\n        void endRun();\n\n        void startCycle();\n        void completeCycle();\n\n        bool completedCycle() const;\n        ITracker& currentTracker();\n        void setCurrentTracker( ITracker* tracker );\n    };\n\n    class TrackerBase : public ITracker {\n    protected:\n        enum CycleState {\n            NotStarted,\n            Executing,\n            ExecutingChildren,\n            NeedsAnotherRun,\n            CompletedSuccessfully,\n            Failed\n        };\n\n        using Children = std::vector<ITrackerPtr>;\n        NameAndLocation m_nameAndLocation;\n        TrackerContext& m_ctx;\n        ITracker* m_parent;\n        Children m_children;\n        CycleState m_runState = NotStarted;\n\n    public:\n        TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );\n\n        NameAndLocation const& nameAndLocation() const override;\n        bool isComplete() const override;\n        bool isSuccessfullyCompleted() const override;\n        bool isOpen() const override;\n        bool hasChildren() const override;\n\n        void addChild( ITrackerPtr const& child ) override;\n\n        ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override;\n        ITracker& parent() override;\n\n        void openChild() override;\n\n        bool isSectionTracker() const override;\n        bool isGeneratorTracker() const override;\n\n        void open();\n\n        void close() override;\n        void fail() override;\n        void markAsNeedingAnotherRun() override;\n\n    private:\n        void moveToParent();\n        void moveToThis();\n    };\n\n    class SectionTracker : public TrackerBase {\n        std::vector<std::string> m_filters;\n    public:\n        SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );\n\n        bool isSectionTracker() const override;\n\n        bool isComplete() const override;\n\n        static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );\n\n        void tryOpen();\n\n        void addInitialFilters( std::vector<std::string> const& filters );\n        void addNextFilters( std::vector<std::string> const& filters );\n    };\n\n} // namespace TestCaseTracking\n\nusing TestCaseTracking::ITracker;\nusing TestCaseTracking::TrackerContext;\nusing TestCaseTracking::SectionTracker;\n\n} // namespace Catch\n\n// end catch_test_case_tracker.h\n\n// start catch_leak_detector.h\n\nnamespace Catch {\n\n    struct LeakDetector {\n        LeakDetector();\n        ~LeakDetector();\n    };\n\n}\n// end catch_leak_detector.h\n// Cpp files will be included in the single-header file here\n// start catch_approx.cpp\n\n#include <cmath>\n#include <limits>\n\nnamespace {\n\n// Performs equivalent check of std::fabs(lhs - rhs) <= margin\n// But without the subtraction to allow for INFINITY in comparison\nbool marginComparison(double lhs, double rhs, double margin) {\n    return (lhs + margin >= rhs) && (rhs + margin >= lhs);\n}\n\n}\n\nnamespace Catch {\nnamespace Detail {\n\n    Approx::Approx ( double value )\n    :   m_epsilon( std::numeric_limits<float>::epsilon()*100 ),\n        m_margin( 0.0 ),\n        m_scale( 0.0 ),\n        m_value( value )\n    {}\n\n    Approx Approx::custom() {\n        return Approx( 0 );\n    }\n\n    Approx Approx::operator-() const {\n        auto temp(*this);\n        temp.m_value = -temp.m_value;\n        return temp;\n    }\n\n    std::string Approx::toString() const {\n        ReusableStringStream rss;\n        rss << \"Approx( \" << ::Catch::Detail::stringify( m_value ) << \" )\";\n        return rss.str();\n    }\n\n    bool Approx::equalityComparisonImpl(const double other) const {\n        // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value\n        // Thanks to Richard Harris for his help refining the scaled margin value\n        return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));\n    }\n\n    void Approx::setMargin(double margin) {\n        CATCH_ENFORCE(margin >= 0,\n            \"Invalid Approx::margin: \" << margin << '.'\n            << \" Approx::Margin has to be non-negative.\");\n        m_margin = margin;\n    }\n\n    void Approx::setEpsilon(double epsilon) {\n        CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0,\n            \"Invalid Approx::epsilon: \" << epsilon << '.'\n            << \" Approx::epsilon has to be in [0, 1]\");\n        m_epsilon = epsilon;\n    }\n\n} // end namespace Detail\n\nnamespace literals {\n    Detail::Approx operator \"\" _a(long double val) {\n        return Detail::Approx(val);\n    }\n    Detail::Approx operator \"\" _a(unsigned long long val) {\n        return Detail::Approx(val);\n    }\n} // end namespace literals\n\nstd::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {\n    return value.toString();\n}\n\n} // end namespace Catch\n// end catch_approx.cpp\n// start catch_assertionhandler.cpp\n\n// start catch_debugger.h\n\nnamespace Catch {\n    bool isDebuggerActive();\n}\n\n#ifdef CATCH_PLATFORM_MAC\n\n    #define CATCH_TRAP() __asm__(\"int $3\\n\" : : ) /* NOLINT */\n\n#elif defined(CATCH_PLATFORM_LINUX)\n    // If we can use inline assembler, do it because this allows us to break\n    // directly at the location of the failing check instead of breaking inside\n    // raise() called from it, i.e. one stack frame below.\n    #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))\n        #define CATCH_TRAP() asm volatile (\"int $3\") /* NOLINT */\n    #else // Fall back to the generic way.\n        #include <signal.h>\n\n        #define CATCH_TRAP() raise(SIGTRAP)\n    #endif\n#elif defined(_MSC_VER)\n    #define CATCH_TRAP() __debugbreak()\n#elif defined(__MINGW32__)\n    extern \"C\" __declspec(dllimport) void __stdcall DebugBreak();\n    #define CATCH_TRAP() DebugBreak()\n#endif\n\n#ifdef CATCH_TRAP\n    #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()\n#else\n    #define CATCH_BREAK_INTO_DEBUGGER() []{}()\n#endif\n\n// end catch_debugger.h\n// start catch_run_context.h\n\n// start catch_fatal_condition.h\n\n// start catch_windows_h_proxy.h\n\n\n#if defined(CATCH_PLATFORM_WINDOWS)\n\n#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)\n#  define CATCH_DEFINED_NOMINMAX\n#  define NOMINMAX\n#endif\n#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)\n#  define CATCH_DEFINED_WIN32_LEAN_AND_MEAN\n#  define WIN32_LEAN_AND_MEAN\n#endif\n\n#ifdef __AFXDLL\n#include <AfxWin.h>\n#else\n#include <windows.h>\n#endif\n\n#ifdef CATCH_DEFINED_NOMINMAX\n#  undef NOMINMAX\n#endif\n#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN\n#  undef WIN32_LEAN_AND_MEAN\n#endif\n\n#endif // defined(CATCH_PLATFORM_WINDOWS)\n\n// end catch_windows_h_proxy.h\n#if defined( CATCH_CONFIG_WINDOWS_SEH )\n\nnamespace Catch {\n\n    struct FatalConditionHandler {\n\n        static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);\n        FatalConditionHandler();\n        static void reset();\n        ~FatalConditionHandler();\n\n    private:\n        static bool isSet;\n        static ULONG guaranteeSize;\n        static PVOID exceptionHandlerHandle;\n    };\n\n} // namespace Catch\n\n#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )\n\n#include <signal.h>\n\nnamespace Catch {\n\n    struct FatalConditionHandler {\n\n        static bool isSet;\n        static struct sigaction oldSigActions[];\n        static stack_t oldSigStack;\n        static char altStackMem[];\n\n        static void handleSignal( int sig );\n\n        FatalConditionHandler();\n        ~FatalConditionHandler();\n        static void reset();\n    };\n\n} // namespace Catch\n\n#else\n\nnamespace Catch {\n    struct FatalConditionHandler {\n        void reset();\n    };\n}\n\n#endif\n\n// end catch_fatal_condition.h\n#include <string>\n\nnamespace Catch {\n\n    struct IMutableContext;\n\n    ///////////////////////////////////////////////////////////////////////////\n\n    class RunContext : public IResultCapture, public IRunner {\n\n    public:\n        RunContext( RunContext const& ) = delete;\n        RunContext& operator =( RunContext const& ) = delete;\n\n        explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter );\n\n        ~RunContext() override;\n\n        void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount );\n        void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount );\n\n        Totals runTest(TestCase const& testCase);\n\n        IConfigPtr config() const;\n        IStreamingReporter& reporter() const;\n\n    public: // IResultCapture\n\n        // Assertion handlers\n        void handleExpr\n                (   AssertionInfo const& info,\n                    ITransientExpression const& expr,\n                    AssertionReaction& reaction ) override;\n        void handleMessage\n                (   AssertionInfo const& info,\n                    ResultWas::OfType resultType,\n                    StringRef const& message,\n                    AssertionReaction& reaction ) override;\n        void handleUnexpectedExceptionNotThrown\n                (   AssertionInfo const& info,\n                    AssertionReaction& reaction ) override;\n        void handleUnexpectedInflightException\n                (   AssertionInfo const& info,\n                    std::string const& message,\n                    AssertionReaction& reaction ) override;\n        void handleIncomplete\n                (   AssertionInfo const& info ) override;\n        void handleNonExpr\n                (   AssertionInfo const &info,\n                    ResultWas::OfType resultType,\n                    AssertionReaction &reaction ) override;\n\n        bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override;\n\n        void sectionEnded( SectionEndInfo const& endInfo ) override;\n        void sectionEndedEarly( SectionEndInfo const& endInfo ) override;\n\n        auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override;\n\n        void benchmarkStarting( BenchmarkInfo const& info ) override;\n        void benchmarkEnded( BenchmarkStats const& stats ) override;\n\n        void pushScopedMessage( MessageInfo const& message ) override;\n        void popScopedMessage( MessageInfo const& message ) override;\n\n        void emplaceUnscopedMessage( MessageBuilder const& builder ) override;\n\n        std::string getCurrentTestName() const override;\n\n        const AssertionResult* getLastResult() const override;\n\n        void exceptionEarlyReported() override;\n\n        void handleFatalErrorCondition( StringRef message ) override;\n\n        bool lastAssertionPassed() override;\n\n        void assertionPassed() override;\n\n    public:\n        // !TBD We need to do this another way!\n        bool aborting() const final;\n\n    private:\n\n        void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr );\n        void invokeActiveTestCase();\n\n        void resetAssertionInfo();\n        bool testForMissingAssertions( Counts& assertions );\n\n        void assertionEnded( AssertionResult const& result );\n        void reportExpr\n                (   AssertionInfo const &info,\n                    ResultWas::OfType resultType,\n                    ITransientExpression const *expr,\n                    bool negated );\n\n        void populateReaction( AssertionReaction& reaction );\n\n    private:\n\n        void handleUnfinishedSections();\n\n        TestRunInfo m_runInfo;\n        IMutableContext& m_context;\n        TestCase const* m_activeTestCase = nullptr;\n        ITracker* m_testCaseTracker = nullptr;\n        Option<AssertionResult> m_lastResult;\n\n        IConfigPtr m_config;\n        Totals m_totals;\n        IStreamingReporterPtr m_reporter;\n        std::vector<MessageInfo> m_messages;\n        std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */\n        AssertionInfo m_lastAssertionInfo;\n        std::vector<SectionEndInfo> m_unfinishedSections;\n        std::vector<ITracker*> m_activeSections;\n        TrackerContext m_trackerContext;\n        bool m_lastAssertionPassed = false;\n        bool m_shouldReportUnexpected = true;\n        bool m_includeSuccessfulResults;\n    };\n\n} // end namespace Catch\n\n// end catch_run_context.h\nnamespace Catch {\n\n    namespace {\n        auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {\n            expr.streamReconstructedExpression( os );\n            return os;\n        }\n    }\n\n    LazyExpression::LazyExpression( bool isNegated )\n    :   m_isNegated( isNegated )\n    {}\n\n    LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {}\n\n    LazyExpression::operator bool() const {\n        return m_transientExpression != nullptr;\n    }\n\n    auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& {\n        if( lazyExpr.m_isNegated )\n            os << \"!\";\n\n        if( lazyExpr ) {\n            if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )\n                os << \"(\" << *lazyExpr.m_transientExpression << \")\";\n            else\n                os << *lazyExpr.m_transientExpression;\n        }\n        else {\n            os << \"{** error - unchecked empty expression requested **}\";\n        }\n        return os;\n    }\n\n    AssertionHandler::AssertionHandler\n        (   StringRef const& macroName,\n            SourceLineInfo const& lineInfo,\n            StringRef capturedExpression,\n            ResultDisposition::Flags resultDisposition )\n    :   m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },\n        m_resultCapture( getResultCapture() )\n    {}\n\n    void AssertionHandler::handleExpr( ITransientExpression const& expr ) {\n        m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );\n    }\n    void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) {\n        m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );\n    }\n\n    auto AssertionHandler::allowThrows() const -> bool {\n        return getCurrentContext().getConfig()->allowThrows();\n    }\n\n    void AssertionHandler::complete() {\n        setCompleted();\n        if( m_reaction.shouldDebugBreak ) {\n\n            // If you find your debugger stopping you here then go one level up on the\n            // call-stack for the code that caused it (typically a failed assertion)\n\n            // (To go back to the test and change execution, jump over the throw, next)\n            CATCH_BREAK_INTO_DEBUGGER();\n        }\n        if (m_reaction.shouldThrow) {\n#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)\n            throw Catch::TestFailureException();\n#else\n            CATCH_ERROR( \"Test failure requires aborting test!\" );\n#endif\n        }\n    }\n    void AssertionHandler::setCompleted() {\n        m_completed = true;\n    }\n\n    void AssertionHandler::handleUnexpectedInflightException() {\n        m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );\n    }\n\n    void AssertionHandler::handleExceptionThrownAsExpected() {\n        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);\n    }\n    void AssertionHandler::handleExceptionNotThrownAsExpected() {\n        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);\n    }\n\n    void AssertionHandler::handleUnexpectedExceptionNotThrown() {\n        m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );\n    }\n\n    void AssertionHandler::handleThrowingCallSkipped() {\n        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);\n    }\n\n    // This is the overload that takes a string and infers the Equals matcher from it\n    // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp\n    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString  ) {\n        handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );\n    }\n\n} // namespace Catch\n// end catch_assertionhandler.cpp\n// start catch_assertionresult.cpp\n\nnamespace Catch {\n    AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression):\n        lazyExpression(_lazyExpression),\n        resultType(_resultType) {}\n\n    std::string AssertionResultData::reconstructExpression() const {\n\n        if( reconstructedExpression.empty() ) {\n            if( lazyExpression ) {\n                ReusableStringStream rss;\n                rss << lazyExpression;\n                reconstructedExpression = rss.str();\n            }\n        }\n        return reconstructedExpression;\n    }\n\n    AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )\n    :   m_info( info ),\n        m_resultData( data )\n    {}\n\n    // Result was a success\n    bool AssertionResult::succeeded() const {\n        return Catch::isOk( m_resultData.resultType );\n    }\n\n    // Result was a success, or failure is suppressed\n    bool AssertionResult::isOk() const {\n        return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );\n    }\n\n    ResultWas::OfType AssertionResult::getResultType() const {\n        return m_resultData.resultType;\n    }\n\n    bool AssertionResult::hasExpression() const {\n        return m_info.capturedExpression[0] != 0;\n    }\n\n    bool AssertionResult::hasMessage() const {\n        return !m_resultData.message.empty();\n    }\n\n    std::string AssertionResult::getExpression() const {\n        if( isFalseTest( m_info.resultDisposition ) )\n            return \"!(\" + m_info.capturedExpression + \")\";\n        else\n            return m_info.capturedExpression;\n    }\n\n    std::string AssertionResult::getExpressionInMacro() const {\n        std::string expr;\n        if( m_info.macroName[0] == 0 )\n            expr = m_info.capturedExpression;\n        else {\n            expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );\n            expr += m_info.macroName;\n            expr += \"( \";\n            expr += m_info.capturedExpression;\n            expr += \" )\";\n        }\n        return expr;\n    }\n\n    bool AssertionResult::hasExpandedExpression() const {\n        return hasExpression() && getExpandedExpression() != getExpression();\n    }\n\n    std::string AssertionResult::getExpandedExpression() const {\n        std::string expr = m_resultData.reconstructExpression();\n        return expr.empty()\n                ? getExpression()\n                : expr;\n    }\n\n    std::string AssertionResult::getMessage() const {\n        return m_resultData.message;\n    }\n    SourceLineInfo AssertionResult::getSourceInfo() const {\n        return m_info.lineInfo;\n    }\n\n    StringRef AssertionResult::getTestMacroName() const {\n        return m_info.macroName;\n    }\n\n} // end namespace Catch\n// end catch_assertionresult.cpp\n// start catch_benchmark.cpp\n\nnamespace Catch {\n\n    auto BenchmarkLooper::getResolution() -> uint64_t {\n        return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple();\n    }\n\n    void BenchmarkLooper::reportStart() {\n        getResultCapture().benchmarkStarting( { m_name } );\n    }\n    auto BenchmarkLooper::needsMoreIterations() -> bool {\n        auto elapsed = m_timer.getElapsedNanoseconds();\n\n        // Exponentially increasing iterations until we're confident in our timer resolution\n        if( elapsed < m_resolution ) {\n            m_iterationsToRun *= 10;\n            return true;\n        }\n\n        getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } );\n        return false;\n    }\n\n} // end namespace Catch\n// end catch_benchmark.cpp\n// start catch_capture_matchers.cpp\n\nnamespace Catch {\n\n    using StringMatcher = Matchers::Impl::MatcherBase<std::string>;\n\n    // This is the general overload that takes a any string matcher\n    // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers\n    // the Equals matcher (so the header does not mention matchers)\n    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  ) {\n        std::string exceptionMessage = Catch::translateActiveException();\n        MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );\n        handler.handleExpr( expr );\n    }\n\n} // namespace Catch\n// end catch_capture_matchers.cpp\n// start catch_commandline.cpp\n\n// start catch_commandline.h\n\n// start catch_clara.h\n\n// Use Catch's value for console width (store Clara's off to the side, if present)\n#ifdef CLARA_CONFIG_CONSOLE_WIDTH\n#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH\n#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH\n#endif\n#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1\n\n#ifdef __clang__\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wweak-vtables\"\n#pragma clang diagnostic ignored \"-Wexit-time-destructors\"\n#pragma clang diagnostic ignored \"-Wshadow\"\n#endif\n\n// start clara.hpp\n// Copyright 2017 Two Blue Cubes Ltd. All rights reserved.\n//\n// Distributed under the Boost Software License, Version 1.0. (See accompanying\n// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n//\n// See https://github.com/philsquared/Clara for more details\n\n// Clara v1.1.5\n\n\n#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH\n#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80\n#endif\n\n#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH\n#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH\n#endif\n\n#ifndef CLARA_CONFIG_OPTIONAL_TYPE\n#ifdef __has_include\n#if __has_include(<optional>) && __cplusplus >= 201703L\n#include <optional>\n#define CLARA_CONFIG_OPTIONAL_TYPE std::optional\n#endif\n#endif\n#endif\n\n// ----------- #included from clara_textflow.hpp -----------\n\n// TextFlowCpp\n//\n// A single-header library for wrapping and laying out basic text, by Phil Nash\n//\n// Distributed under the Boost Software License, Version 1.0. (See accompanying\n// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n//\n// This project is hosted at https://github.com/philsquared/textflowcpp\n\n\n#include <cassert>\n#include <ostream>\n#include <sstream>\n#include <vector>\n\n#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH\n#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80\n#endif\n\nnamespace Catch {\nnamespace clara {\nnamespace TextFlow {\n\ninline auto isWhitespace(char c) -> bool {\n\tstatic std::string chars = \" \\t\\n\\r\";\n\treturn chars.find(c) != std::string::npos;\n}\ninline auto isBreakableBefore(char c) -> bool {\n\tstatic std::string chars = \"[({<|\";\n\treturn chars.find(c) != std::string::npos;\n}\ninline auto isBreakableAfter(char c) -> bool {\n\tstatic std::string chars = \"])}>.,:;*+-=&/\\\\\";\n\treturn chars.find(c) != std::string::npos;\n}\n\nclass Columns;\n\nclass Column {\n\tstd::vector<std::string> m_strings;\n\tsize_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;\n\tsize_t m_indent = 0;\n\tsize_t m_initialIndent = std::string::npos;\n\npublic:\n\tclass iterator {\n\t\tfriend Column;\n\n\t\tColumn const& m_column;\n\t\tsize_t m_stringIndex = 0;\n\t\tsize_t m_pos = 0;\n\n\t\tsize_t m_len = 0;\n\t\tsize_t m_end = 0;\n\t\tbool m_suffix = false;\n\n\t\titerator(Column const& column, size_t stringIndex)\n\t\t\t: m_column(column),\n\t\t\tm_stringIndex(stringIndex) {}\n\n\t\tauto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }\n\n\t\tauto isBoundary(size_t at) const -> bool {\n\t\t\tassert(at > 0);\n\t\t\tassert(at <= line().size());\n\n\t\t\treturn at == line().size() ||\n\t\t\t\t(isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||\n\t\t\t\tisBreakableBefore(line()[at]) ||\n\t\t\t\tisBreakableAfter(line()[at - 1]);\n\t\t}\n\n\t\tvoid calcLength() {\n\t\t\tassert(m_stringIndex < m_column.m_strings.size());\n\n\t\t\tm_suffix = false;\n\t\t\tauto width = m_column.m_width - indent();\n\t\t\tm_end = m_pos;\n\t\t\twhile (m_end < line().size() && line()[m_end] != '\\n')\n\t\t\t\t++m_end;\n\n\t\t\tif (m_end < m_pos + width) {\n\t\t\t\tm_len = m_end - m_pos;\n\t\t\t} else {\n\t\t\t\tsize_t len = width;\n\t\t\t\twhile (len > 0 && !isBoundary(m_pos + len))\n\t\t\t\t\t--len;\n\t\t\t\twhile (len > 0 && isWhitespace(line()[m_pos + len - 1]))\n\t\t\t\t\t--len;\n\n\t\t\t\tif (len > 0) {\n\t\t\t\t\tm_len = len;\n\t\t\t\t} else {\n\t\t\t\t\tm_suffix = true;\n\t\t\t\t\tm_len = width - 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tauto indent() const -> size_t {\n\t\t\tauto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;\n\t\t\treturn initial == std::string::npos ? m_column.m_indent : initial;\n\t\t}\n\n\t\tauto addIndentAndSuffix(std::string const &plain) const -> std::string {\n\t\t\treturn std::string(indent(), ' ') + (m_suffix ? plain + \"-\" : plain);\n\t\t}\n\n\tpublic:\n\t\tusing difference_type = std::ptrdiff_t;\n\t\tusing value_type = std::string;\n\t\tusing pointer = value_type * ;\n\t\tusing reference = value_type & ;\n\t\tusing iterator_category = std::forward_iterator_tag;\n\n\t\texplicit iterator(Column const& column) : m_column(column) {\n\t\t\tassert(m_column.m_width > m_column.m_indent);\n\t\t\tassert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);\n\t\t\tcalcLength();\n\t\t\tif (m_len == 0)\n\t\t\t\tm_stringIndex++; // Empty string\n\t\t}\n\n\t\tauto operator *() const -> std::string {\n\t\t\tassert(m_stringIndex < m_column.m_strings.size());\n\t\t\tassert(m_pos <= m_end);\n\t\t\treturn addIndentAndSuffix(line().substr(m_pos, m_len));\n\t\t}\n\n\t\tauto operator ++() -> iterator& {\n\t\t\tm_pos += m_len;\n\t\t\tif (m_pos < line().size() && line()[m_pos] == '\\n')\n\t\t\t\tm_pos += 1;\n\t\t\telse\n\t\t\t\twhile (m_pos < line().size() && isWhitespace(line()[m_pos]))\n\t\t\t\t\t++m_pos;\n\n\t\t\tif (m_pos == line().size()) {\n\t\t\t\tm_pos = 0;\n\t\t\t\t++m_stringIndex;\n\t\t\t}\n\t\t\tif (m_stringIndex < m_column.m_strings.size())\n\t\t\t\tcalcLength();\n\t\t\treturn *this;\n\t\t}\n\t\tauto operator ++(int) -> iterator {\n\t\t\titerator prev(*this);\n\t\t\toperator++();\n\t\t\treturn prev;\n\t\t}\n\n\t\tauto operator ==(iterator const& other) const -> bool {\n\t\t\treturn\n\t\t\t\tm_pos == other.m_pos &&\n\t\t\t\tm_stringIndex == other.m_stringIndex &&\n\t\t\t\t&m_column == &other.m_column;\n\t\t}\n\t\tauto operator !=(iterator const& other) const -> bool {\n\t\t\treturn !operator==(other);\n\t\t}\n\t};\n\tusing const_iterator = iterator;\n\n\texplicit Column(std::string const& text) { m_strings.push_back(text); }\n\n\tauto width(size_t newWidth) -> Column& {\n\t\tassert(newWidth > 0);\n\t\tm_width = newWidth;\n\t\treturn *this;\n\t}\n\tauto indent(size_t newIndent) -> Column& {\n\t\tm_indent = newIndent;\n\t\treturn *this;\n\t}\n\tauto initialIndent(size_t newIndent) -> Column& {\n\t\tm_initialIndent = newIndent;\n\t\treturn *this;\n\t}\n\n\tauto width() const -> size_t { return m_width; }\n\tauto begin() const -> iterator { return iterator(*this); }\n\tauto end() const -> iterator { return { *this, m_strings.size() }; }\n\n\tinline friend std::ostream& operator << (std::ostream& os, Column const& col) {\n\t\tbool first = true;\n\t\tfor (auto line : col) {\n\t\t\tif (first)\n\t\t\t\tfirst = false;\n\t\t\telse\n\t\t\t\tos << \"\\n\";\n\t\t\tos << line;\n\t\t}\n\t\treturn os;\n\t}\n\n\tauto operator + (Column const& other)->Columns;\n\n\tauto toString() const -> std::string {\n\t\tstd::ostringstream oss;\n\t\toss << *this;\n\t\treturn oss.str();\n\t}\n};\n\nclass Spacer : public Column {\n\npublic:\n\texplicit Spacer(size_t spaceWidth) : Column(\"\") {\n\t\twidth(spaceWidth);\n\t}\n};\n\nclass Columns {\n\tstd::vector<Column> m_columns;\n\npublic:\n\n\tclass iterator {\n\t\tfriend Columns;\n\t\tstruct EndTag {};\n\n\t\tstd::vector<Column> const& m_columns;\n\t\tstd::vector<Column::iterator> m_iterators;\n\t\tsize_t m_activeIterators;\n\n\t\titerator(Columns const& columns, EndTag)\n\t\t\t: m_columns(columns.m_columns),\n\t\t\tm_activeIterators(0) {\n\t\t\tm_iterators.reserve(m_columns.size());\n\n\t\t\tfor (auto const& col : m_columns)\n\t\t\t\tm_iterators.push_back(col.end());\n\t\t}\n\n\tpublic:\n\t\tusing difference_type = std::ptrdiff_t;\n\t\tusing value_type = std::string;\n\t\tusing pointer = value_type * ;\n\t\tusing reference = value_type & ;\n\t\tusing iterator_category = std::forward_iterator_tag;\n\n\t\texplicit iterator(Columns const& columns)\n\t\t\t: m_columns(columns.m_columns),\n\t\t\tm_activeIterators(m_columns.size()) {\n\t\t\tm_iterators.reserve(m_columns.size());\n\n\t\t\tfor (auto const& col : m_columns)\n\t\t\t\tm_iterators.push_back(col.begin());\n\t\t}\n\n\t\tauto operator ==(iterator const& other) const -> bool {\n\t\t\treturn m_iterators == other.m_iterators;\n\t\t}\n\t\tauto operator !=(iterator const& other) const -> bool {\n\t\t\treturn m_iterators != other.m_iterators;\n\t\t}\n\t\tauto operator *() const -> std::string {\n\t\t\tstd::string row, padding;\n\n\t\t\tfor (size_t i = 0; i < m_columns.size(); ++i) {\n\t\t\t\tauto width = m_columns[i].width();\n\t\t\t\tif (m_iterators[i] != m_columns[i].end()) {\n\t\t\t\t\tstd::string col = *m_iterators[i];\n\t\t\t\t\trow += padding + col;\n\t\t\t\t\tif (col.size() < width)\n\t\t\t\t\t\tpadding = std::string(width - col.size(), ' ');\n\t\t\t\t\telse\n\t\t\t\t\t\tpadding = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpadding += std::string(width, ' ');\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn row;\n\t\t}\n\t\tauto operator ++() -> iterator& {\n\t\t\tfor (size_t i = 0; i < m_columns.size(); ++i) {\n\t\t\t\tif (m_iterators[i] != m_columns[i].end())\n\t\t\t\t\t++m_iterators[i];\n\t\t\t}\n\t\t\treturn *this;\n\t\t}\n\t\tauto operator ++(int) -> iterator {\n\t\t\titerator prev(*this);\n\t\t\toperator++();\n\t\t\treturn prev;\n\t\t}\n\t};\n\tusing const_iterator = iterator;\n\n\tauto begin() const -> iterator { return iterator(*this); }\n\tauto end() const -> iterator { return { *this, iterator::EndTag() }; }\n\n\tauto operator += (Column const& col) -> Columns& {\n\t\tm_columns.push_back(col);\n\t\treturn *this;\n\t}\n\tauto operator + (Column const& col) -> Columns {\n\t\tColumns combined = *this;\n\t\tcombined += col;\n\t\treturn combined;\n\t}\n\n\tinline friend std::ostream& operator << (std::ostream& os, Columns const& cols) {\n\n\t\tbool first = true;\n\t\tfor (auto line : cols) {\n\t\t\tif (first)\n\t\t\t\tfirst = false;\n\t\t\telse\n\t\t\t\tos << \"\\n\";\n\t\t\tos << line;\n\t\t}\n\t\treturn os;\n\t}\n\n\tauto toString() const -> std::string {\n\t\tstd::ostringstream oss;\n\t\toss << *this;\n\t\treturn oss.str();\n\t}\n};\n\ninline auto Column::operator + (Column const& other) -> Columns {\n\tColumns cols;\n\tcols += *this;\n\tcols += other;\n\treturn cols;\n}\n}\n\n}\n}\n\n// ----------- end of #include from clara_textflow.hpp -----------\n// ........... back in clara.hpp\n\n#include <cctype>\n#include <string>\n#include <memory>\n#include <set>\n#include <algorithm>\n\n#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )\n#define CATCH_PLATFORM_WINDOWS\n#endif\n\nnamespace Catch { namespace clara {\nnamespace detail {\n\n    // Traits for extracting arg and return type of lambdas (for single argument lambdas)\n    template<typename L>\n    struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};\n\n    template<typename ClassT, typename ReturnT, typename... Args>\n    struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {\n        static const bool isValid = false;\n    };\n\n    template<typename ClassT, typename ReturnT, typename ArgT>\n    struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {\n        static const bool isValid = true;\n        using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;\n        using ReturnType = ReturnT;\n    };\n\n    class TokenStream;\n\n    // Transport for raw args (copied from main args, or supplied via init list for testing)\n    class Args {\n        friend TokenStream;\n        std::string m_exeName;\n        std::vector<std::string> m_args;\n\n    public:\n        Args( int argc, char const* const* argv )\n            : m_exeName(argv[0]),\n              m_args(argv + 1, argv + argc) {}\n\n        Args( std::initializer_list<std::string> args )\n        :   m_exeName( *args.begin() ),\n            m_args( args.begin()+1, args.end() )\n        {}\n\n        auto exeName() const -> std::string {\n            return m_exeName;\n        }\n    };\n\n    // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string\n    // may encode an option + its argument if the : or = form is used\n    enum class TokenType {\n        Option, Argument\n    };\n    struct Token {\n        TokenType type;\n        std::string token;\n    };\n\n    inline auto isOptPrefix( char c ) -> bool {\n        return c == '-'\n#ifdef CATCH_PLATFORM_WINDOWS\n            || c == '/'\n#endif\n        ;\n    }\n\n    // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled\n    class TokenStream {\n        using Iterator = std::vector<std::string>::const_iterator;\n        Iterator it;\n        Iterator itEnd;\n        std::vector<Token> m_tokenBuffer;\n\n        void loadBuffer() {\n            m_tokenBuffer.resize( 0 );\n\n            // Skip any empty strings\n            while( it != itEnd && it->empty() )\n                ++it;\n\n            if( it != itEnd ) {\n                auto const &next = *it;\n                if( isOptPrefix( next[0] ) ) {\n                    auto delimiterPos = next.find_first_of( \" :=\" );\n                    if( delimiterPos != std::string::npos ) {\n                        m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );\n                        m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );\n                    } else {\n                        if( next[1] != '-' && next.size() > 2 ) {\n                            std::string opt = \"- \";\n                            for( size_t i = 1; i < next.size(); ++i ) {\n                                opt[1] = next[i];\n                                m_tokenBuffer.push_back( { TokenType::Option, opt } );\n                            }\n                        } else {\n                            m_tokenBuffer.push_back( { TokenType::Option, next } );\n                        }\n                    }\n                } else {\n                    m_tokenBuffer.push_back( { TokenType::Argument, next } );\n                }\n            }\n        }\n\n    public:\n        explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}\n\n        TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {\n            loadBuffer();\n        }\n\n        explicit operator bool() const {\n            return !m_tokenBuffer.empty() || it != itEnd;\n        }\n\n        auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }\n\n        auto operator*() const -> Token {\n            assert( !m_tokenBuffer.empty() );\n            return m_tokenBuffer.front();\n        }\n\n        auto operator->() const -> Token const * {\n            assert( !m_tokenBuffer.empty() );\n            return &m_tokenBuffer.front();\n        }\n\n        auto operator++() -> TokenStream & {\n            if( m_tokenBuffer.size() >= 2 ) {\n                m_tokenBuffer.erase( m_tokenBuffer.begin() );\n            } else {\n                if( it != itEnd )\n                    ++it;\n                loadBuffer();\n            }\n            return *this;\n        }\n    };\n\n    class ResultBase {\n    public:\n        enum Type {\n            Ok, LogicError, RuntimeError\n        };\n\n    protected:\n        ResultBase( Type type ) : m_type( type ) {}\n        virtual ~ResultBase() = default;\n\n        virtual void enforceOk() const = 0;\n\n        Type m_type;\n    };\n\n    template<typename T>\n    class ResultValueBase : public ResultBase {\n    public:\n        auto value() const -> T const & {\n            enforceOk();\n            return m_value;\n        }\n\n    protected:\n        ResultValueBase( Type type ) : ResultBase( type ) {}\n\n        ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) {\n            if( m_type == ResultBase::Ok )\n                new( &m_value ) T( other.m_value );\n        }\n\n        ResultValueBase( Type, T const &value ) : ResultBase( Ok ) {\n            new( &m_value ) T( value );\n        }\n\n        auto operator=( ResultValueBase const &other ) -> ResultValueBase & {\n            if( m_type == ResultBase::Ok )\n                m_value.~T();\n            ResultBase::operator=(other);\n            if( m_type == ResultBase::Ok )\n                new( &m_value ) T( other.m_value );\n            return *this;\n        }\n\n        ~ResultValueBase() override {\n            if( m_type == Ok )\n                m_value.~T();\n        }\n\n        union {\n            T m_value;\n        };\n    };\n\n    template<>\n    class ResultValueBase<void> : public ResultBase {\n    protected:\n        using ResultBase::ResultBase;\n    };\n\n    template<typename T = void>\n    class BasicResult : public ResultValueBase<T> {\n    public:\n        template<typename U>\n        explicit BasicResult( BasicResult<U> const &other )\n        :   ResultValueBase<T>( other.type() ),\n            m_errorMessage( other.errorMessage() )\n        {\n            assert( type() != ResultBase::Ok );\n        }\n\n        template<typename U>\n        static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; }\n        static auto ok() -> BasicResult { return { ResultBase::Ok }; }\n        static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; }\n        static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; }\n\n        explicit operator bool() const { return m_type == ResultBase::Ok; }\n        auto type() const -> ResultBase::Type { return m_type; }\n        auto errorMessage() const -> std::string { return m_errorMessage; }\n\n    protected:\n        void enforceOk() const override {\n\n            // Errors shouldn't reach this point, but if they do\n            // the actual error message will be in m_errorMessage\n            assert( m_type != ResultBase::LogicError );\n            assert( m_type != ResultBase::RuntimeError );\n            if( m_type != ResultBase::Ok )\n                std::abort();\n        }\n\n        std::string m_errorMessage; // Only populated if resultType is an error\n\n        BasicResult( ResultBase::Type type, std::string const &message )\n        :   ResultValueBase<T>(type),\n            m_errorMessage(message)\n        {\n            assert( m_type != ResultBase::Ok );\n        }\n\n        using ResultValueBase<T>::ResultValueBase;\n        using ResultBase::m_type;\n    };\n\n    enum class ParseResultType {\n        Matched, NoMatch, ShortCircuitAll, ShortCircuitSame\n    };\n\n    class ParseState {\n    public:\n\n        ParseState( ParseResultType type, TokenStream const &remainingTokens )\n        : m_type(type),\n          m_remainingTokens( remainingTokens )\n        {}\n\n        auto type() const -> ParseResultType { return m_type; }\n        auto remainingTokens() const -> TokenStream { return m_remainingTokens; }\n\n    private:\n        ParseResultType m_type;\n        TokenStream m_remainingTokens;\n    };\n\n    using Result = BasicResult<void>;\n    using ParserResult = BasicResult<ParseResultType>;\n    using InternalParseResult = BasicResult<ParseState>;\n\n    struct HelpColumns {\n        std::string left;\n        std::string right;\n    };\n\n    template<typename T>\n    inline auto convertInto( std::string const &source, T& target ) -> ParserResult {\n        std::stringstream ss;\n        ss << source;\n        ss >> target;\n        if( ss.fail() )\n            return ParserResult::runtimeError( \"Unable to convert '\" + source + \"' to destination type\" );\n        else\n            return ParserResult::ok( ParseResultType::Matched );\n    }\n    inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult {\n        target = source;\n        return ParserResult::ok( ParseResultType::Matched );\n    }\n    inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {\n        std::string srcLC = source;\n        std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( std::tolower(c) ); } );\n        if (srcLC == \"y\" || srcLC == \"1\" || srcLC == \"true\" || srcLC == \"yes\" || srcLC == \"on\")\n            target = true;\n        else if (srcLC == \"n\" || srcLC == \"0\" || srcLC == \"false\" || srcLC == \"no\" || srcLC == \"off\")\n            target = false;\n        else\n            return ParserResult::runtimeError( \"Expected a boolean value but did not recognise: '\" + source + \"'\" );\n        return ParserResult::ok( ParseResultType::Matched );\n    }\n#ifdef CLARA_CONFIG_OPTIONAL_TYPE\n    template<typename T>\n    inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {\n        T temp;\n        auto result = convertInto( source, temp );\n        if( result )\n            target = std::move(temp);\n        return result;\n    }\n#endif // CLARA_CONFIG_OPTIONAL_TYPE\n\n    struct NonCopyable {\n        NonCopyable() = default;\n        NonCopyable( NonCopyable const & ) = delete;\n        NonCopyable( NonCopyable && ) = delete;\n        NonCopyable &operator=( NonCopyable const & ) = delete;\n        NonCopyable &operator=( NonCopyable && ) = delete;\n    };\n\n    struct BoundRef : NonCopyable {\n        virtual ~BoundRef() = default;\n        virtual auto isContainer() const -> bool { return false; }\n        virtual auto isFlag() const -> bool { return false; }\n    };\n    struct BoundValueRefBase : BoundRef {\n        virtual auto setValue( std::string const &arg ) -> ParserResult = 0;\n    };\n    struct BoundFlagRefBase : BoundRef {\n        virtual auto setFlag( bool flag ) -> ParserResult = 0;\n        virtual auto isFlag() const -> bool { return true; }\n    };\n\n    template<typename T>\n    struct BoundValueRef : BoundValueRefBase {\n        T &m_ref;\n\n        explicit BoundValueRef( T &ref ) : m_ref( ref ) {}\n\n        auto setValue( std::string const &arg ) -> ParserResult override {\n            return convertInto( arg, m_ref );\n        }\n    };\n\n    template<typename T>\n    struct BoundValueRef<std::vector<T>> : BoundValueRefBase {\n        std::vector<T> &m_ref;\n\n        explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}\n\n        auto isContainer() const -> bool override { return true; }\n\n        auto setValue( std::string const &arg ) -> ParserResult override {\n            T temp;\n            auto result = convertInto( arg, temp );\n            if( result )\n                m_ref.push_back( temp );\n            return result;\n        }\n    };\n\n    struct BoundFlagRef : BoundFlagRefBase {\n        bool &m_ref;\n\n        explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {}\n\n        auto setFlag( bool flag ) -> ParserResult override {\n            m_ref = flag;\n            return ParserResult::ok( ParseResultType::Matched );\n        }\n    };\n\n    template<typename ReturnType>\n    struct LambdaInvoker {\n        static_assert( std::is_same<ReturnType, ParserResult>::value, \"Lambda must return void or clara::ParserResult\" );\n\n        template<typename L, typename ArgType>\n        static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {\n            return lambda( arg );\n        }\n    };\n\n    template<>\n    struct LambdaInvoker<void> {\n        template<typename L, typename ArgType>\n        static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {\n            lambda( arg );\n            return ParserResult::ok( ParseResultType::Matched );\n        }\n    };\n\n    template<typename ArgType, typename L>\n    inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {\n        ArgType temp{};\n        auto result = convertInto( arg, temp );\n        return !result\n           ? result\n           : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );\n    }\n\n    template<typename L>\n    struct BoundLambda : BoundValueRefBase {\n        L m_lambda;\n\n        static_assert( UnaryLambdaTraits<L>::isValid, \"Supplied lambda must take exactly one argument\" );\n        explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {}\n\n        auto setValue( std::string const &arg ) -> ParserResult override {\n            return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );\n        }\n    };\n\n    template<typename L>\n    struct BoundFlagLambda : BoundFlagRefBase {\n        L m_lambda;\n\n        static_assert( UnaryLambdaTraits<L>::isValid, \"Supplied lambda must take exactly one argument\" );\n        static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, \"flags must be boolean\" );\n\n        explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {}\n\n        auto setFlag( bool flag ) -> ParserResult override {\n            return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );\n        }\n    };\n\n    enum class Optionality { Optional, Required };\n\n    struct Parser;\n\n    class ParserBase {\n    public:\n        virtual ~ParserBase() = default;\n        virtual auto validate() const -> Result { return Result::ok(); }\n        virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult  = 0;\n        virtual auto cardinality() const -> size_t { return 1; }\n\n        auto parse( Args const &args ) const -> InternalParseResult {\n            return parse( args.exeName(), TokenStream( args ) );\n        }\n    };\n\n    template<typename DerivedT>\n    class ComposableParserImpl : public ParserBase {\n    public:\n        template<typename T>\n        auto operator|( T const &other ) const -> Parser;\n\n\t\ttemplate<typename T>\n        auto operator+( T const &other ) const -> Parser;\n    };\n\n    // Common code and state for Args and Opts\n    template<typename DerivedT>\n    class ParserRefImpl : public ComposableParserImpl<DerivedT> {\n    protected:\n        Optionality m_optionality = Optionality::Optional;\n        std::shared_ptr<BoundRef> m_ref;\n        std::string m_hint;\n        std::string m_description;\n\n        explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}\n\n    public:\n        template<typename T>\n        ParserRefImpl( T &ref, std::string const &hint )\n        :   m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),\n            m_hint( hint )\n        {}\n\n        template<typename LambdaT>\n        ParserRefImpl( LambdaT const &ref, std::string const &hint )\n        :   m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),\n            m_hint(hint)\n        {}\n\n        auto operator()( std::string const &description ) -> DerivedT & {\n            m_description = description;\n            return static_cast<DerivedT &>( *this );\n        }\n\n        auto optional() -> DerivedT & {\n            m_optionality = Optionality::Optional;\n            return static_cast<DerivedT &>( *this );\n        };\n\n        auto required() -> DerivedT & {\n            m_optionality = Optionality::Required;\n            return static_cast<DerivedT &>( *this );\n        };\n\n        auto isOptional() const -> bool {\n            return m_optionality == Optionality::Optional;\n        }\n\n        auto cardinality() const -> size_t override {\n            if( m_ref->isContainer() )\n                return 0;\n            else\n                return 1;\n        }\n\n        auto hint() const -> std::string { return m_hint; }\n    };\n\n    class ExeName : public ComposableParserImpl<ExeName> {\n        std::shared_ptr<std::string> m_name;\n        std::shared_ptr<BoundValueRefBase> m_ref;\n\n        template<typename LambdaT>\n        static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {\n            return std::make_shared<BoundLambda<LambdaT>>( lambda) ;\n        }\n\n    public:\n        ExeName() : m_name( std::make_shared<std::string>( \"<executable>\" ) ) {}\n\n        explicit ExeName( std::string &ref ) : ExeName() {\n            m_ref = std::make_shared<BoundValueRef<std::string>>( ref );\n        }\n\n        template<typename LambdaT>\n        explicit ExeName( LambdaT const& lambda ) : ExeName() {\n            m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda );\n        }\n\n        // The exe name is not parsed out of the normal tokens, but is handled specially\n        auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {\n            return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );\n        }\n\n        auto name() const -> std::string { return *m_name; }\n        auto set( std::string const& newName ) -> ParserResult {\n\n            auto lastSlash = newName.find_last_of( \"\\\\/\" );\n            auto filename = ( lastSlash == std::string::npos )\n                    ? newName\n                    : newName.substr( lastSlash+1 );\n\n            *m_name = filename;\n            if( m_ref )\n                return m_ref->setValue( filename );\n            else\n                return ParserResult::ok( ParseResultType::Matched );\n        }\n    };\n\n    class Arg : public ParserRefImpl<Arg> {\n    public:\n        using ParserRefImpl::ParserRefImpl;\n\n        auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override {\n            auto validationResult = validate();\n            if( !validationResult )\n                return InternalParseResult( validationResult );\n\n            auto remainingTokens = tokens;\n            auto const &token = *remainingTokens;\n            if( token.type != TokenType::Argument )\n                return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );\n\n            assert( !m_ref->isFlag() );\n            auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );\n\n            auto result = valueRef->setValue( remainingTokens->token );\n            if( !result )\n                return InternalParseResult( result );\n            else\n                return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );\n        }\n    };\n\n    inline auto normaliseOpt( std::string const &optName ) -> std::string {\n#ifdef CATCH_PLATFORM_WINDOWS\n        if( optName[0] == '/' )\n            return \"-\" + optName.substr( 1 );\n        else\n#endif\n            return optName;\n    }\n\n    class Opt : public ParserRefImpl<Opt> {\n    protected:\n        std::vector<std::string> m_optNames;\n\n    public:\n        template<typename LambdaT>\n        explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}\n\n        explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {}\n\n        template<typename LambdaT>\n        Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}\n\n        template<typename T>\n        Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}\n\n        auto operator[]( std::string const &optName ) -> Opt & {\n            m_optNames.push_back( optName );\n            return *this;\n        }\n\n        auto getHelpColumns() const -> std::vector<HelpColumns> {\n            std::ostringstream oss;\n            bool first = true;\n            for( auto const &opt : m_optNames ) {\n                if (first)\n                    first = false;\n                else\n                    oss << \", \";\n                oss << opt;\n            }\n            if( !m_hint.empty() )\n                oss << \" <\" << m_hint << \">\";\n            return { { oss.str(), m_description } };\n        }\n\n        auto isMatch( std::string const &optToken ) const -> bool {\n            auto normalisedToken = normaliseOpt( optToken );\n            for( auto const &name : m_optNames ) {\n                if( normaliseOpt( name ) == normalisedToken )\n                    return true;\n            }\n            return false;\n        }\n\n        using ParserBase::parse;\n\n        auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {\n            auto validationResult = validate();\n            if( !validationResult )\n                return InternalParseResult( validationResult );\n\n            auto remainingTokens = tokens;\n            if( remainingTokens && remainingTokens->type == TokenType::Option ) {\n                auto const &token = *remainingTokens;\n                if( isMatch(token.token ) ) {\n                    if( m_ref->isFlag() ) {\n                        auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );\n                        auto result = flagRef->setFlag( true );\n                        if( !result )\n                            return InternalParseResult( result );\n                        if( result.value() == ParseResultType::ShortCircuitAll )\n                            return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );\n                    } else {\n                        auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );\n                        ++remainingTokens;\n                        if( !remainingTokens )\n                            return InternalParseResult::runtimeError( \"Expected argument following \" + token.token );\n                        auto const &argToken = *remainingTokens;\n                        if( argToken.type != TokenType::Argument )\n                            return InternalParseResult::runtimeError( \"Expected argument following \" + token.token );\n                        auto result = valueRef->setValue( argToken.token );\n                        if( !result )\n                            return InternalParseResult( result );\n                        if( result.value() == ParseResultType::ShortCircuitAll )\n                            return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );\n                    }\n                    return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );\n                }\n            }\n            return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );\n        }\n\n        auto validate() const -> Result override {\n            if( m_optNames.empty() )\n                return Result::logicError( \"No options supplied to Opt\" );\n            for( auto const &name : m_optNames ) {\n                if( name.empty() )\n                    return Result::logicError( \"Option name cannot be empty\" );\n#ifdef CATCH_PLATFORM_WINDOWS\n                if( name[0] != '-' && name[0] != '/' )\n                    return Result::logicError( \"Option name must begin with '-' or '/'\" );\n#else\n                if( name[0] != '-' )\n                    return Result::logicError( \"Option name must begin with '-'\" );\n#endif\n            }\n            return ParserRefImpl::validate();\n        }\n    };\n\n    struct Help : Opt {\n        Help( bool &showHelpFlag )\n        :   Opt([&]( bool flag ) {\n                showHelpFlag = flag;\n                return ParserResult::ok( ParseResultType::ShortCircuitAll );\n            })\n        {\n            static_cast<Opt &>( *this )\n                    (\"display usage information\")\n                    [\"-?\"][\"-h\"][\"--help\"]\n                    .optional();\n        }\n    };\n\n    struct Parser : ParserBase {\n\n        mutable ExeName m_exeName;\n        std::vector<Opt> m_options;\n        std::vector<Arg> m_args;\n\n        auto operator|=( ExeName const &exeName ) -> Parser & {\n            m_exeName = exeName;\n            return *this;\n        }\n\n        auto operator|=( Arg const &arg ) -> Parser & {\n            m_args.push_back(arg);\n            return *this;\n        }\n\n        auto operator|=( Opt const &opt ) -> Parser & {\n            m_options.push_back(opt);\n            return *this;\n        }\n\n        auto operator|=( Parser const &other ) -> Parser & {\n            m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());\n            m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());\n            return *this;\n        }\n\n        template<typename T>\n        auto operator|( T const &other ) const -> Parser {\n            return Parser( *this ) |= other;\n        }\n\n        // Forward deprecated interface with '+' instead of '|'\n        template<typename T>\n        auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }\n        template<typename T>\n        auto operator+( T const &other ) const -> Parser { return operator|( other ); }\n\n        auto getHelpColumns() const -> std::vector<HelpColumns> {\n            std::vector<HelpColumns> cols;\n            for (auto const &o : m_options) {\n                auto childCols = o.getHelpColumns();\n                cols.insert( cols.end(), childCols.begin(), childCols.end() );\n            }\n            return cols;\n        }\n\n        void writeToStream( std::ostream &os ) const {\n            if (!m_exeName.name().empty()) {\n                os << \"usage:\\n\" << \"  \" << m_exeName.name() << \" \";\n                bool required = true, first = true;\n                for( auto const &arg : m_args ) {\n                    if (first)\n                        first = false;\n                    else\n                        os << \" \";\n                    if( arg.isOptional() && required ) {\n                        os << \"[\";\n                        required = false;\n                    }\n                    os << \"<\" << arg.hint() << \">\";\n                    if( arg.cardinality() == 0 )\n                        os << \" ... \";\n                }\n                if( !required )\n                    os << \"]\";\n                if( !m_options.empty() )\n                    os << \" options\";\n                os << \"\\n\\nwhere options are:\" << std::endl;\n            }\n\n            auto rows = getHelpColumns();\n            size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;\n            size_t optWidth = 0;\n            for( auto const &cols : rows )\n                optWidth = (std::max)(optWidth, cols.left.size() + 2);\n\n            optWidth = (std::min)(optWidth, consoleWidth/2);\n\n            for( auto const &cols : rows ) {\n                auto row =\n                        TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +\n                        TextFlow::Spacer(4) +\n                        TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );\n                os << row << std::endl;\n            }\n        }\n\n        friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& {\n            parser.writeToStream( os );\n            return os;\n        }\n\n        auto validate() const -> Result override {\n            for( auto const &opt : m_options ) {\n                auto result = opt.validate();\n                if( !result )\n                    return result;\n            }\n            for( auto const &arg : m_args ) {\n                auto result = arg.validate();\n                if( !result )\n                    return result;\n            }\n            return Result::ok();\n        }\n\n        using ParserBase::parse;\n\n        auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override {\n\n            struct ParserInfo {\n                ParserBase const* parser = nullptr;\n                size_t count = 0;\n            };\n            const size_t totalParsers = m_options.size() + m_args.size();\n            assert( totalParsers < 512 );\n            // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do\n            ParserInfo parseInfos[512];\n\n            {\n                size_t i = 0;\n                for (auto const &opt : m_options) parseInfos[i++].parser = &opt;\n                for (auto const &arg : m_args) parseInfos[i++].parser = &arg;\n            }\n\n            m_exeName.set( exeName );\n\n            auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );\n            while( result.value().remainingTokens() ) {\n                bool tokenParsed = false;\n\n                for( size_t i = 0; i < totalParsers; ++i ) {\n                    auto&  parseInfo = parseInfos[i];\n                    if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {\n                        result = parseInfo.parser->parse(exeName, result.value().remainingTokens());\n                        if (!result)\n                            return result;\n                        if (result.value().type() != ParseResultType::NoMatch) {\n                            tokenParsed = true;\n                            ++parseInfo.count;\n                            break;\n                        }\n                    }\n                }\n\n                if( result.value().type() == ParseResultType::ShortCircuitAll )\n                    return result;\n                if( !tokenParsed )\n                    return InternalParseResult::runtimeError( \"Unrecognised token: \" + result.value().remainingTokens()->token );\n            }\n            // !TBD Check missing required options\n            return result;\n        }\n    };\n\n    template<typename DerivedT>\n    template<typename T>\n    auto ComposableParserImpl<DerivedT>::operator|( T const &other ) const -> Parser {\n        return Parser() | static_cast<DerivedT const &>( *this ) | other;\n    }\n} // namespace detail\n\n// A Combined parser\nusing detail::Parser;\n\n// A parser for options\nusing detail::Opt;\n\n// A parser for arguments\nusing detail::Arg;\n\n// Wrapper for argc, argv from main()\nusing detail::Args;\n\n// Specifies the name of the executable\nusing detail::ExeName;\n\n// Convenience wrapper for option parser that specifies the help option\nusing detail::Help;\n\n// enum of result types from a parse\nusing detail::ParseResultType;\n\n// Result type for parser operation\nusing detail::ParserResult;\n\n}} // namespace Catch::clara\n\n// end clara.hpp\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\n// Restore Clara's value for console width, if present\n#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH\n#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH\n#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH\n#endif\n\n// end catch_clara.h\nnamespace Catch {\n\n    clara::Parser makeCommandLineParser( ConfigData& config );\n\n} // end namespace Catch\n\n// end catch_commandline.h\n#include <fstream>\n#include <ctime>\n\nnamespace Catch {\n\n    clara::Parser makeCommandLineParser( ConfigData& config ) {\n\n        using namespace clara;\n\n        auto const setWarning = [&]( std::string const& warning ) {\n                auto warningSet = [&]() {\n                    if( warning == \"NoAssertions\" )\n                        return WarnAbout::NoAssertions;\n\n                    if ( warning == \"NoTests\" )\n                        return WarnAbout::NoTests;\n\n                    return WarnAbout::Nothing;\n                }();\n\n                if (warningSet == WarnAbout::Nothing)\n                    return ParserResult::runtimeError( \"Unrecognised warning: '\" + warning + \"'\" );\n                config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet );\n                return ParserResult::ok( ParseResultType::Matched );\n            };\n        auto const loadTestNamesFromFile = [&]( std::string const& filename ) {\n                std::ifstream f( filename.c_str() );\n                if( !f.is_open() )\n                    return ParserResult::runtimeError( \"Unable to load input file: '\" + filename + \"'\" );\n\n                std::string line;\n                while( std::getline( f, line ) ) {\n                    line = trim(line);\n                    if( !line.empty() && !startsWith( line, '#' ) ) {\n                        if( !startsWith( line, '\"' ) )\n                            line = '\"' + line + '\"';\n                        config.testsOrTags.push_back( line + ',' );\n                    }\n                }\n                return ParserResult::ok( ParseResultType::Matched );\n            };\n        auto const setTestOrder = [&]( std::string const& order ) {\n                if( startsWith( \"declared\", order ) )\n                    config.runOrder = RunTests::InDeclarationOrder;\n                else if( startsWith( \"lexical\", order ) )\n                    config.runOrder = RunTests::InLexicographicalOrder;\n                else if( startsWith( \"random\", order ) )\n                    config.runOrder = RunTests::InRandomOrder;\n                else\n                    return clara::ParserResult::runtimeError( \"Unrecognised ordering: '\" + order + \"'\" );\n                return ParserResult::ok( ParseResultType::Matched );\n            };\n        auto const setRngSeed = [&]( std::string const& seed ) {\n                if( seed != \"time\" )\n                    return clara::detail::convertInto( seed, config.rngSeed );\n                config.rngSeed = static_cast<unsigned int>( std::time(nullptr) );\n                return ParserResult::ok( ParseResultType::Matched );\n            };\n        auto const setColourUsage = [&]( std::string const& useColour ) {\n                    auto mode = toLower( useColour );\n\n                    if( mode == \"yes\" )\n                        config.useColour = UseColour::Yes;\n                    else if( mode == \"no\" )\n                        config.useColour = UseColour::No;\n                    else if( mode == \"auto\" )\n                        config.useColour = UseColour::Auto;\n                    else\n                        return ParserResult::runtimeError( \"colour mode must be one of: auto, yes or no. '\" + useColour + \"' not recognised\" );\n                return ParserResult::ok( ParseResultType::Matched );\n            };\n        auto const setWaitForKeypress = [&]( std::string const& keypress ) {\n                auto keypressLc = toLower( keypress );\n                if( keypressLc == \"start\" )\n                    config.waitForKeypress = WaitForKeypress::BeforeStart;\n                else if( keypressLc == \"exit\" )\n                    config.waitForKeypress = WaitForKeypress::BeforeExit;\n                else if( keypressLc == \"both\" )\n                    config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;\n                else\n                    return ParserResult::runtimeError( \"keypress argument must be one of: start, exit or both. '\" + keypress + \"' not recognised\" );\n            return ParserResult::ok( ParseResultType::Matched );\n            };\n        auto const setVerbosity = [&]( std::string const& verbosity ) {\n            auto lcVerbosity = toLower( verbosity );\n            if( lcVerbosity == \"quiet\" )\n                config.verbosity = Verbosity::Quiet;\n            else if( lcVerbosity == \"normal\" )\n                config.verbosity = Verbosity::Normal;\n            else if( lcVerbosity == \"high\" )\n                config.verbosity = Verbosity::High;\n            else\n                return ParserResult::runtimeError( \"Unrecognised verbosity, '\" + verbosity + \"'\" );\n            return ParserResult::ok( ParseResultType::Matched );\n        };\n        auto const setReporter = [&]( std::string const& reporter ) {\n            IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();\n\n            auto lcReporter = toLower( reporter );\n            auto result = factories.find( lcReporter );\n\n            if( factories.end() != result )\n                config.reporterName = lcReporter;\n            else\n                return ParserResult::runtimeError( \"Unrecognized reporter, '\" + reporter + \"'. Check available with --list-reporters\" );\n            return ParserResult::ok( ParseResultType::Matched );\n        };\n\n        auto cli\n            = ExeName( config.processName )\n            | Help( config.showHelp )\n            | Opt( config.listTests )\n                [\"-l\"][\"--list-tests\"]\n                ( \"list all/matching test cases\" )\n            | Opt( config.listTags )\n                [\"-t\"][\"--list-tags\"]\n                ( \"list all/matching tags\" )\n            | Opt( config.showSuccessfulTests )\n                [\"-s\"][\"--success\"]\n                ( \"include successful tests in output\" )\n            | Opt( config.shouldDebugBreak )\n                [\"-b\"][\"--break\"]\n                ( \"break into debugger on failure\" )\n            | Opt( config.noThrow )\n                [\"-e\"][\"--nothrow\"]\n                ( \"skip exception tests\" )\n            | Opt( config.showInvisibles )\n                [\"-i\"][\"--invisibles\"]\n                ( \"show invisibles (tabs, newlines)\" )\n            | Opt( config.outputFilename, \"filename\" )\n                [\"-o\"][\"--out\"]\n                ( \"output filename\" )\n            | Opt( setReporter, \"name\" )\n                [\"-r\"][\"--reporter\"]\n                ( \"reporter to use (defaults to console)\" )\n            | Opt( config.name, \"name\" )\n                [\"-n\"][\"--name\"]\n                ( \"suite name\" )\n            | Opt( [&]( bool ){ config.abortAfter = 1; } )\n                [\"-a\"][\"--abort\"]\n                ( \"abort at first failure\" )\n            | Opt( [&]( int x ){ config.abortAfter = x; }, \"no. failures\" )\n                [\"-x\"][\"--abortx\"]\n                ( \"abort after x failures\" )\n            | Opt( setWarning, \"warning name\" )\n                [\"-w\"][\"--warn\"]\n                ( \"enable warnings\" )\n            | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, \"yes|no\" )\n                [\"-d\"][\"--durations\"]\n                ( \"show test durations\" )\n            | Opt( loadTestNamesFromFile, \"filename\" )\n                [\"-f\"][\"--input-file\"]\n                ( \"load test names to run from a file\" )\n            | Opt( config.filenamesAsTags )\n                [\"-#\"][\"--filenames-as-tags\"]\n                ( \"adds a tag for the filename\" )\n            | Opt( config.sectionsToRun, \"section name\" )\n                [\"-c\"][\"--section\"]\n                ( \"specify section to run\" )\n            | Opt( setVerbosity, \"quiet|normal|high\" )\n                [\"-v\"][\"--verbosity\"]\n                ( \"set output verbosity\" )\n            | Opt( config.listTestNamesOnly )\n                [\"--list-test-names-only\"]\n                ( \"list all/matching test cases names only\" )\n            | Opt( config.listReporters )\n                [\"--list-reporters\"]\n                ( \"list all reporters\" )\n            | Opt( setTestOrder, \"decl|lex|rand\" )\n                [\"--order\"]\n                ( \"test case order (defaults to decl)\" )\n            | Opt( setRngSeed, \"'time'|number\" )\n                [\"--rng-seed\"]\n                ( \"set a specific seed for random numbers\" )\n            | Opt( setColourUsage, \"yes|no\" )\n                [\"--use-colour\"]\n                ( \"should output be colourised\" )\n            | Opt( config.libIdentify )\n                [\"--libidentify\"]\n                ( \"report name and version according to libidentify standard\" )\n            | Opt( setWaitForKeypress, \"start|exit|both\" )\n                [\"--wait-for-keypress\"]\n                ( \"waits for a keypress before exiting\" )\n            | Opt( config.benchmarkResolutionMultiple, \"multiplier\" )\n                [\"--benchmark-resolution-multiple\"]\n                ( \"multiple of clock resolution to run benchmarks\" )\n\n            | Arg( config.testsOrTags, \"test name|pattern|tags\" )\n                ( \"which test or tests to use\" );\n\n        return cli;\n    }\n\n} // end namespace Catch\n// end catch_commandline.cpp\n// start catch_common.cpp\n\n#include <cstring>\n#include <ostream>\n\nnamespace Catch {\n\n    bool SourceLineInfo::empty() const noexcept {\n        return file[0] == '\\0';\n    }\n    bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {\n        return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);\n    }\n    bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {\n        // We can assume that the same file will usually have the same pointer.\n        // Thus, if the pointers are the same, there is no point in calling the strcmp\n        return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0));\n    }\n\n    std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {\n#ifndef __GNUG__\n        os << info.file << '(' << info.line << ')';\n#else\n        os << info.file << ':' << info.line;\n#endif\n        return os;\n    }\n\n    std::string StreamEndStop::operator+() const {\n        return std::string();\n    }\n\n    NonCopyable::NonCopyable() = default;\n    NonCopyable::~NonCopyable() = default;\n\n}\n// end catch_common.cpp\n// start catch_config.cpp\n\nnamespace Catch {\n\n    Config::Config( ConfigData const& data )\n    :   m_data( data ),\n        m_stream( openStream() )\n    {\n        TestSpecParser parser(ITagAliasRegistry::get());\n        if (data.testsOrTags.empty()) {\n            parser.parse(\"~[.]\"); // All not hidden tests\n        }\n        else {\n            m_hasTestFilters = true;\n            for( auto const& testOrTags : data.testsOrTags )\n                parser.parse( testOrTags );\n        }\n        m_testSpec = parser.testSpec();\n    }\n\n    std::string const& Config::getFilename() const {\n        return m_data.outputFilename ;\n    }\n\n    bool Config::listTests() const          { return m_data.listTests; }\n    bool Config::listTestNamesOnly() const  { return m_data.listTestNamesOnly; }\n    bool Config::listTags() const           { return m_data.listTags; }\n    bool Config::listReporters() const      { return m_data.listReporters; }\n\n    std::string Config::getProcessName() const { return m_data.processName; }\n    std::string const& Config::getReporterName() const { return m_data.reporterName; }\n\n    std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }\n    std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }\n\n    TestSpec const& Config::testSpec() const { return m_testSpec; }\n    bool Config::hasTestFilters() const { return m_hasTestFilters; }\n\n    bool Config::showHelp() const { return m_data.showHelp; }\n\n    // IConfig interface\n    bool Config::allowThrows() const                   { return !m_data.noThrow; }\n    std::ostream& Config::stream() const               { return m_stream->stream(); }\n    std::string Config::name() const                   { return m_data.name.empty() ? m_data.processName : m_data.name; }\n    bool Config::includeSuccessfulResults() const      { return m_data.showSuccessfulTests; }\n    bool Config::warnAboutMissingAssertions() const    { return !!(m_data.warnings & WarnAbout::NoAssertions); }\n    bool Config::warnAboutNoTests() const              { return !!(m_data.warnings & WarnAbout::NoTests); }\n    ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }\n    RunTests::InWhatOrder Config::runOrder() const     { return m_data.runOrder; }\n    unsigned int Config::rngSeed() const               { return m_data.rngSeed; }\n    int Config::benchmarkResolutionMultiple() const    { return m_data.benchmarkResolutionMultiple; }\n    UseColour::YesOrNo Config::useColour() const       { return m_data.useColour; }\n    bool Config::shouldDebugBreak() const              { return m_data.shouldDebugBreak; }\n    int Config::abortAfter() const                     { return m_data.abortAfter; }\n    bool Config::showInvisibles() const                { return m_data.showInvisibles; }\n    Verbosity Config::verbosity() const                { return m_data.verbosity; }\n\n    IStream const* Config::openStream() {\n        return Catch::makeStream(m_data.outputFilename);\n    }\n\n} // end namespace Catch\n// end catch_config.cpp\n// start catch_console_colour.cpp\n\n#if defined(__clang__)\n#    pragma clang diagnostic push\n#    pragma clang diagnostic ignored \"-Wexit-time-destructors\"\n#endif\n\n// start catch_errno_guard.h\n\nnamespace Catch {\n\n    class ErrnoGuard {\n    public:\n        ErrnoGuard();\n        ~ErrnoGuard();\n    private:\n        int m_oldErrno;\n    };\n\n}\n\n// end catch_errno_guard.h\n#include <sstream>\n\nnamespace Catch {\n    namespace {\n\n        struct IColourImpl {\n            virtual ~IColourImpl() = default;\n            virtual void use( Colour::Code _colourCode ) = 0;\n        };\n\n        struct NoColourImpl : IColourImpl {\n            void use( Colour::Code ) {}\n\n            static IColourImpl* instance() {\n                static NoColourImpl s_instance;\n                return &s_instance;\n            }\n        };\n\n    } // anon namespace\n} // namespace Catch\n\n#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )\n#   ifdef CATCH_PLATFORM_WINDOWS\n#       define CATCH_CONFIG_COLOUR_WINDOWS\n#   else\n#       define CATCH_CONFIG_COLOUR_ANSI\n#   endif\n#endif\n\n#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////\n\nnamespace Catch {\nnamespace {\n\n    class Win32ColourImpl : public IColourImpl {\n    public:\n        Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )\n        {\n            CONSOLE_SCREEN_BUFFER_INFO csbiInfo;\n            GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );\n            originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );\n            originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );\n        }\n\n        virtual void use( Colour::Code _colourCode ) override {\n            switch( _colourCode ) {\n                case Colour::None:      return setTextAttribute( originalForegroundAttributes );\n                case Colour::White:     return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );\n                case Colour::Red:       return setTextAttribute( FOREGROUND_RED );\n                case Colour::Green:     return setTextAttribute( FOREGROUND_GREEN );\n                case Colour::Blue:      return setTextAttribute( FOREGROUND_BLUE );\n                case Colour::Cyan:      return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );\n                case Colour::Yellow:    return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );\n                case Colour::Grey:      return setTextAttribute( 0 );\n\n                case Colour::LightGrey:     return setTextAttribute( FOREGROUND_INTENSITY );\n                case Colour::BrightRed:     return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );\n                case Colour::BrightGreen:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );\n                case Colour::BrightWhite:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );\n                case Colour::BrightYellow:  return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );\n\n                case Colour::Bright: CATCH_INTERNAL_ERROR( \"not a colour\" );\n\n                default:\n                    CATCH_ERROR( \"Unknown colour requested\" );\n            }\n        }\n\n    private:\n        void setTextAttribute( WORD _textAttribute ) {\n            SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );\n        }\n        HANDLE stdoutHandle;\n        WORD originalForegroundAttributes;\n        WORD originalBackgroundAttributes;\n    };\n\n    IColourImpl* platformColourInstance() {\n        static Win32ColourImpl s_instance;\n\n        IConfigPtr config = getCurrentContext().getConfig();\n        UseColour::YesOrNo colourMode = config\n            ? config->useColour()\n            : UseColour::Auto;\n        if( colourMode == UseColour::Auto )\n            colourMode = UseColour::Yes;\n        return colourMode == UseColour::Yes\n            ? &s_instance\n            : NoColourImpl::instance();\n    }\n\n} // end anon namespace\n} // end namespace Catch\n\n#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////\n\n#include <unistd.h>\n\nnamespace Catch {\nnamespace {\n\n    // use POSIX/ ANSI console terminal codes\n    // Thanks to Adam Strzelecki for original contribution\n    // (http://github.com/nanoant)\n    // https://github.com/philsquared/Catch/pull/131\n    class PosixColourImpl : public IColourImpl {\n    public:\n        virtual void use( Colour::Code _colourCode ) override {\n            switch( _colourCode ) {\n                case Colour::None:\n                case Colour::White:     return setColour( \"[0m\" );\n                case Colour::Red:       return setColour( \"[0;31m\" );\n                case Colour::Green:     return setColour( \"[0;32m\" );\n                case Colour::Blue:      return setColour( \"[0;34m\" );\n                case Colour::Cyan:      return setColour( \"[0;36m\" );\n                case Colour::Yellow:    return setColour( \"[0;33m\" );\n                case Colour::Grey:      return setColour( \"[1;30m\" );\n\n                case Colour::LightGrey:     return setColour( \"[0;37m\" );\n                case Colour::BrightRed:     return setColour( \"[1;31m\" );\n                case Colour::BrightGreen:   return setColour( \"[1;32m\" );\n                case Colour::BrightWhite:   return setColour( \"[1;37m\" );\n                case Colour::BrightYellow:  return setColour( \"[1;33m\" );\n\n                case Colour::Bright: CATCH_INTERNAL_ERROR( \"not a colour\" );\n                default: CATCH_INTERNAL_ERROR( \"Unknown colour requested\" );\n            }\n        }\n        static IColourImpl* instance() {\n            static PosixColourImpl s_instance;\n            return &s_instance;\n        }\n\n    private:\n        void setColour( const char* _escapeCode ) {\n            getCurrentContext().getConfig()->stream()\n                << '\\033' << _escapeCode;\n        }\n    };\n\n    bool useColourOnPlatform() {\n        return\n#ifdef CATCH_PLATFORM_MAC\n            !isDebuggerActive() &&\n#endif\n#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))\n            isatty(STDOUT_FILENO)\n#else\n            false\n#endif\n            ;\n    }\n    IColourImpl* platformColourInstance() {\n        ErrnoGuard guard;\n        IConfigPtr config = getCurrentContext().getConfig();\n        UseColour::YesOrNo colourMode = config\n            ? config->useColour()\n            : UseColour::Auto;\n        if( colourMode == UseColour::Auto )\n            colourMode = useColourOnPlatform()\n                ? UseColour::Yes\n                : UseColour::No;\n        return colourMode == UseColour::Yes\n            ? PosixColourImpl::instance()\n            : NoColourImpl::instance();\n    }\n\n} // end anon namespace\n} // end namespace Catch\n\n#else  // not Windows or ANSI ///////////////////////////////////////////////\n\nnamespace Catch {\n\n    static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }\n\n} // end namespace Catch\n\n#endif // Windows/ ANSI/ None\n\nnamespace Catch {\n\n    Colour::Colour( Code _colourCode ) { use( _colourCode ); }\n    Colour::Colour( Colour&& rhs ) noexcept {\n        m_moved = rhs.m_moved;\n        rhs.m_moved = true;\n    }\n    Colour& Colour::operator=( Colour&& rhs ) noexcept {\n        m_moved = rhs.m_moved;\n        rhs.m_moved  = true;\n        return *this;\n    }\n\n    Colour::~Colour(){ if( !m_moved ) use( None ); }\n\n    void Colour::use( Code _colourCode ) {\n        static IColourImpl* impl = platformColourInstance();\n        impl->use( _colourCode );\n    }\n\n    std::ostream& operator << ( std::ostream& os, Colour const& ) {\n        return os;\n    }\n\n} // end namespace Catch\n\n#if defined(__clang__)\n#    pragma clang diagnostic pop\n#endif\n\n// end catch_console_colour.cpp\n// start catch_context.cpp\n\nnamespace Catch {\n\n    class Context : public IMutableContext, NonCopyable {\n\n    public: // IContext\n        virtual IResultCapture* getResultCapture() override {\n            return m_resultCapture;\n        }\n        virtual IRunner* getRunner() override {\n            return m_runner;\n        }\n\n        virtual IConfigPtr const& getConfig() const override {\n            return m_config;\n        }\n\n        virtual ~Context() override;\n\n    public: // IMutableContext\n        virtual void setResultCapture( IResultCapture* resultCapture ) override {\n            m_resultCapture = resultCapture;\n        }\n        virtual void setRunner( IRunner* runner ) override {\n            m_runner = runner;\n        }\n        virtual void setConfig( IConfigPtr const& config ) override {\n            m_config = config;\n        }\n\n        friend IMutableContext& getCurrentMutableContext();\n\n    private:\n        IConfigPtr m_config;\n        IRunner* m_runner = nullptr;\n        IResultCapture* m_resultCapture = nullptr;\n    };\n\n    IMutableContext *IMutableContext::currentContext = nullptr;\n\n    void IMutableContext::createContext()\n    {\n        currentContext = new Context();\n    }\n\n    void cleanUpContext() {\n        delete IMutableContext::currentContext;\n        IMutableContext::currentContext = nullptr;\n    }\n    IContext::~IContext() = default;\n    IMutableContext::~IMutableContext() = default;\n    Context::~Context() = default;\n}\n// end catch_context.cpp\n// start catch_debug_console.cpp\n\n// start catch_debug_console.h\n\n#include <string>\n\nnamespace Catch {\n    void writeToDebugConsole( std::string const& text );\n}\n\n// end catch_debug_console.h\n#ifdef CATCH_PLATFORM_WINDOWS\n\n    namespace Catch {\n        void writeToDebugConsole( std::string const& text ) {\n            ::OutputDebugStringA( text.c_str() );\n        }\n    }\n\n#else\n\n    namespace Catch {\n        void writeToDebugConsole( std::string const& text ) {\n            // !TBD: Need a version for Mac/ XCode and other IDEs\n            Catch::cout() << text;\n        }\n    }\n\n#endif // Platform\n// end catch_debug_console.cpp\n// start catch_debugger.cpp\n\n#ifdef CATCH_PLATFORM_MAC\n\n#  include <assert.h>\n#  include <stdbool.h>\n#  include <sys/types.h>\n#  include <unistd.h>\n#  include <sys/sysctl.h>\n#  include <cstddef>\n#  include <ostream>\n\nnamespace Catch {\n\n        // The following function is taken directly from the following technical note:\n        // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html\n\n        // Returns true if the current process is being debugged (either\n        // running under the debugger or has a debugger attached post facto).\n        bool isDebuggerActive(){\n\n            int                 mib[4];\n            struct kinfo_proc   info;\n            std::size_t         size;\n\n            // Initialize the flags so that, if sysctl fails for some bizarre\n            // reason, we get a predictable result.\n\n            info.kp_proc.p_flag = 0;\n\n            // Initialize mib, which tells sysctl the info we want, in this case\n            // we're looking for information about a specific process ID.\n\n            mib[0] = CTL_KERN;\n            mib[1] = KERN_PROC;\n            mib[2] = KERN_PROC_PID;\n            mib[3] = getpid();\n\n            // Call sysctl.\n\n            size = sizeof(info);\n            if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) {\n                Catch::cerr() << \"\\n** Call to sysctl failed - unable to determine if debugger is active **\\n\" << std::endl;\n                return false;\n            }\n\n            // We're being debugged if the P_TRACED flag is set.\n\n            return ( (info.kp_proc.p_flag & P_TRACED) != 0 );\n        }\n    } // namespace Catch\n\n#elif defined(CATCH_PLATFORM_LINUX)\n    #include <fstream>\n    #include <string>\n\n    namespace Catch{\n        // The standard POSIX way of detecting a debugger is to attempt to\n        // ptrace() the process, but this needs to be done from a child and not\n        // this process itself to still allow attaching to this process later\n        // if wanted, so is rather heavy. Under Linux we have the PID of the\n        // \"debugger\" (which doesn't need to be gdb, of course, it could also\n        // be strace, for example) in /proc/$PID/status, so just get it from\n        // there instead.\n        bool isDebuggerActive(){\n            // Libstdc++ has a bug, where std::ifstream sets errno to 0\n            // This way our users can properly assert over errno values\n            ErrnoGuard guard;\n            std::ifstream in(\"/proc/self/status\");\n            for( std::string line; std::getline(in, line); ) {\n                static const int PREFIX_LEN = 11;\n                if( line.compare(0, PREFIX_LEN, \"TracerPid:\\t\") == 0 ) {\n                    // We're traced if the PID is not 0 and no other PID starts\n                    // with 0 digit, so it's enough to check for just a single\n                    // character.\n                    return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';\n                }\n            }\n\n            return false;\n        }\n    } // namespace Catch\n#elif defined(_MSC_VER)\n    extern \"C\" __declspec(dllimport) int __stdcall IsDebuggerPresent();\n    namespace Catch {\n        bool isDebuggerActive() {\n            return IsDebuggerPresent() != 0;\n        }\n    }\n#elif defined(__MINGW32__)\n    extern \"C\" __declspec(dllimport) int __stdcall IsDebuggerPresent();\n    namespace Catch {\n        bool isDebuggerActive() {\n            return IsDebuggerPresent() != 0;\n        }\n    }\n#else\n    namespace Catch {\n       bool isDebuggerActive() { return false; }\n    }\n#endif // Platform\n// end catch_debugger.cpp\n// start catch_decomposer.cpp\n\nnamespace Catch {\n\n    ITransientExpression::~ITransientExpression() = default;\n\n    void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {\n        if( lhs.size() + rhs.size() < 40 &&\n                lhs.find('\\n') == std::string::npos &&\n                rhs.find('\\n') == std::string::npos )\n            os << lhs << \" \" << op << \" \" << rhs;\n        else\n            os << lhs << \"\\n\" << op << \"\\n\" << rhs;\n    }\n}\n// end catch_decomposer.cpp\n// start catch_enforce.cpp\n\nnamespace Catch {\n#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)\n    [[noreturn]]\n    void throw_exception(std::exception const& e) {\n        Catch::cerr() << \"Catch will terminate because it needed to throw an exception.\\n\"\n                      << \"The message was: \" << e.what() << '\\n';\n        std::terminate();\n    }\n#endif\n} // namespace Catch;\n// end catch_enforce.cpp\n// start catch_errno_guard.cpp\n\n#include <cerrno>\n\nnamespace Catch {\n        ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}\n        ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }\n}\n// end catch_errno_guard.cpp\n// start catch_exception_translator_registry.cpp\n\n// start catch_exception_translator_registry.h\n\n#include <vector>\n#include <string>\n#include <memory>\n\nnamespace Catch {\n\n    class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {\n    public:\n        ~ExceptionTranslatorRegistry();\n        virtual void registerTranslator( const IExceptionTranslator* translator );\n        virtual std::string translateActiveException() const override;\n        std::string tryTranslators() const;\n\n    private:\n        std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;\n    };\n}\n\n// end catch_exception_translator_registry.h\n#ifdef __OBJC__\n#import \"Foundation/Foundation.h\"\n#endif\n\nnamespace Catch {\n\n    ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {\n    }\n\n    void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) {\n        m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );\n    }\n\n#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)\n    std::string ExceptionTranslatorRegistry::translateActiveException() const {\n        try {\n#ifdef __OBJC__\n            // In Objective-C try objective-c exceptions first\n            @try {\n                return tryTranslators();\n            }\n            @catch (NSException *exception) {\n                return Catch::Detail::stringify( [exception description] );\n            }\n#else\n            // Compiling a mixed mode project with MSVC means that CLR\n            // exceptions will be caught in (...) as well. However, these\n            // do not fill-in std::current_exception and thus lead to crash\n            // when attempting rethrow.\n            // /EHa switch also causes structured exceptions to be caught\n            // here, but they fill-in current_exception properly, so\n            // at worst the output should be a little weird, instead of\n            // causing a crash.\n            if (std::current_exception() == nullptr) {\n                return \"Non C++ exception. Possibly a CLR exception.\";\n            }\n            return tryTranslators();\n#endif\n        }\n        catch( TestFailureException& ) {\n            std::rethrow_exception(std::current_exception());\n        }\n        catch( std::exception& ex ) {\n            return ex.what();\n        }\n        catch( std::string& msg ) {\n            return msg;\n        }\n        catch( const char* msg ) {\n            return msg;\n        }\n        catch(...) {\n            return \"Unknown exception\";\n        }\n    }\n\n    std::string ExceptionTranslatorRegistry::tryTranslators() const {\n        if (m_translators.empty()) {\n            std::rethrow_exception(std::current_exception());\n        } else {\n            return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());\n        }\n    }\n\n#else // ^^ Exceptions are enabled // Exceptions are disabled vv\n    std::string ExceptionTranslatorRegistry::translateActiveException() const {\n        CATCH_INTERNAL_ERROR(\"Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!\");\n    }\n\n    std::string ExceptionTranslatorRegistry::tryTranslators() const {\n        CATCH_INTERNAL_ERROR(\"Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!\");\n    }\n#endif\n\n}\n// end catch_exception_translator_registry.cpp\n// start catch_fatal_condition.cpp\n\n#if defined(__GNUC__)\n#    pragma GCC diagnostic push\n#    pragma GCC diagnostic ignored \"-Wmissing-field-initializers\"\n#endif\n\n#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )\n\nnamespace {\n    // Report the error condition\n    void reportFatal( char const * const message ) {\n        Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );\n    }\n}\n\n#endif // signals/SEH handling\n\n#if defined( CATCH_CONFIG_WINDOWS_SEH )\n\nnamespace Catch {\n    struct SignalDefs { DWORD id; const char* name; };\n\n    // There is no 1-1 mapping between signals and windows exceptions.\n    // Windows can easily distinguish between SO and SigSegV,\n    // but SigInt, SigTerm, etc are handled differently.\n    static SignalDefs signalDefs[] = {\n        { EXCEPTION_ILLEGAL_INSTRUCTION,  \"SIGILL - Illegal instruction signal\" },\n        { EXCEPTION_STACK_OVERFLOW, \"SIGSEGV - Stack overflow\" },\n        { EXCEPTION_ACCESS_VIOLATION, \"SIGSEGV - Segmentation violation signal\" },\n        { EXCEPTION_INT_DIVIDE_BY_ZERO, \"Divide by zero error\" },\n    };\n\n    LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {\n        for (auto const& def : signalDefs) {\n            if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {\n                reportFatal(def.name);\n            }\n        }\n        // If its not an exception we care about, pass it along.\n        // This stops us from eating debugger breaks etc.\n        return EXCEPTION_CONTINUE_SEARCH;\n    }\n\n    FatalConditionHandler::FatalConditionHandler() {\n        isSet = true;\n        // 32k seems enough for Catch to handle stack overflow,\n        // but the value was found experimentally, so there is no strong guarantee\n        guaranteeSize = 32 * 1024;\n        exceptionHandlerHandle = nullptr;\n        // Register as first handler in current chain\n        exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);\n        // Pass in guarantee size to be filled\n        SetThreadStackGuarantee(&guaranteeSize);\n    }\n\n    void FatalConditionHandler::reset() {\n        if (isSet) {\n            RemoveVectoredExceptionHandler(exceptionHandlerHandle);\n            SetThreadStackGuarantee(&guaranteeSize);\n            exceptionHandlerHandle = nullptr;\n            isSet = false;\n        }\n    }\n\n    FatalConditionHandler::~FatalConditionHandler() {\n        reset();\n    }\n\nbool FatalConditionHandler::isSet = false;\nULONG FatalConditionHandler::guaranteeSize = 0;\nPVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;\n\n} // namespace Catch\n\n#elif defined( CATCH_CONFIG_POSIX_SIGNALS )\n\nnamespace Catch {\n\n    struct SignalDefs {\n        int id;\n        const char* name;\n    };\n\n    // 32kb for the alternate stack seems to be sufficient. However, this value\n    // is experimentally determined, so that's not guaranteed.\n    constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;\n\n    static SignalDefs signalDefs[] = {\n        { SIGINT,  \"SIGINT - Terminal interrupt signal\" },\n        { SIGILL,  \"SIGILL - Illegal instruction signal\" },\n        { SIGFPE,  \"SIGFPE - Floating point error signal\" },\n        { SIGSEGV, \"SIGSEGV - Segmentation violation signal\" },\n        { SIGTERM, \"SIGTERM - Termination request signal\" },\n        { SIGABRT, \"SIGABRT - Abort (abnormal termination) signal\" }\n    };\n\n    void FatalConditionHandler::handleSignal( int sig ) {\n        char const * name = \"<unknown signal>\";\n        for (auto const& def : signalDefs) {\n            if (sig == def.id) {\n                name = def.name;\n                break;\n            }\n        }\n        reset();\n        reportFatal(name);\n        raise( sig );\n    }\n\n    FatalConditionHandler::FatalConditionHandler() {\n        isSet = true;\n        stack_t sigStack;\n        sigStack.ss_sp = altStackMem;\n        sigStack.ss_size = sigStackSize;\n        sigStack.ss_flags = 0;\n        sigaltstack(&sigStack, &oldSigStack);\n        struct sigaction sa = { };\n\n        sa.sa_handler = handleSignal;\n        sa.sa_flags = SA_ONSTACK;\n        for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {\n            sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);\n        }\n    }\n\n    FatalConditionHandler::~FatalConditionHandler() {\n        reset();\n    }\n\n    void FatalConditionHandler::reset() {\n        if( isSet ) {\n            // Set signals back to previous values -- hopefully nobody overwrote them in the meantime\n            for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {\n                sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);\n            }\n            // Return the old stack\n            sigaltstack(&oldSigStack, nullptr);\n            isSet = false;\n        }\n    }\n\n    bool FatalConditionHandler::isSet = false;\n    struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};\n    stack_t FatalConditionHandler::oldSigStack = {};\n    char FatalConditionHandler::altStackMem[sigStackSize] = {};\n\n} // namespace Catch\n\n#else\n\nnamespace Catch {\n    void FatalConditionHandler::reset() {}\n}\n\n#endif // signals/SEH handling\n\n#if defined(__GNUC__)\n#    pragma GCC diagnostic pop\n#endif\n// end catch_fatal_condition.cpp\n// start catch_generators.cpp\n\n// start catch_random_number_generator.h\n\n#include <algorithm>\n#include <random>\n\nnamespace Catch {\n\n    struct IConfig;\n\n    std::mt19937& rng();\n    void seedRng( IConfig const& config );\n    unsigned int rngSeed();\n\n}\n\n// end catch_random_number_generator.h\n#include <limits>\n#include <set>\n\nnamespace Catch {\n\nIGeneratorTracker::~IGeneratorTracker() {}\n\nconst char* GeneratorException::what() const noexcept {\n    return m_msg;\n}\n\nnamespace Generators {\n\n    GeneratorUntypedBase::~GeneratorUntypedBase() {}\n\n    auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {\n        return getResultCapture().acquireGeneratorTracker( lineInfo );\n    }\n\n} // namespace Generators\n} // namespace Catch\n// end catch_generators.cpp\n// start catch_interfaces_capture.cpp\n\nnamespace Catch {\n    IResultCapture::~IResultCapture() = default;\n}\n// end catch_interfaces_capture.cpp\n// start catch_interfaces_config.cpp\n\nnamespace Catch {\n    IConfig::~IConfig() = default;\n}\n// end catch_interfaces_config.cpp\n// start catch_interfaces_exception.cpp\n\nnamespace Catch {\n    IExceptionTranslator::~IExceptionTranslator() = default;\n    IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default;\n}\n// end catch_interfaces_exception.cpp\n// start catch_interfaces_registry_hub.cpp\n\nnamespace Catch {\n    IRegistryHub::~IRegistryHub() = default;\n    IMutableRegistryHub::~IMutableRegistryHub() = default;\n}\n// end catch_interfaces_registry_hub.cpp\n// start catch_interfaces_reporter.cpp\n\n// start catch_reporter_listening.h\n\nnamespace Catch {\n\n    class ListeningReporter : public IStreamingReporter {\n        using Reporters = std::vector<IStreamingReporterPtr>;\n        Reporters m_listeners;\n        IStreamingReporterPtr m_reporter = nullptr;\n        ReporterPreferences m_preferences;\n\n    public:\n        ListeningReporter();\n\n        void addListener( IStreamingReporterPtr&& listener );\n        void addReporter( IStreamingReporterPtr&& reporter );\n\n    public: // IStreamingReporter\n\n        ReporterPreferences getPreferences() const override;\n\n        void noMatchingTestCases( std::string const& spec ) override;\n\n        static std::set<Verbosity> getSupportedVerbosities();\n\n        void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;\n        void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override;\n\n        void testRunStarting( TestRunInfo const& testRunInfo ) override;\n        void testGroupStarting( GroupInfo const& groupInfo ) override;\n        void testCaseStarting( TestCaseInfo const& testInfo ) override;\n        void sectionStarting( SectionInfo const& sectionInfo ) override;\n        void assertionStarting( AssertionInfo const& assertionInfo ) override;\n\n        // The return value indicates if the messages buffer should be cleared:\n        bool assertionEnded( AssertionStats const& assertionStats ) override;\n        void sectionEnded( SectionStats const& sectionStats ) override;\n        void testCaseEnded( TestCaseStats const& testCaseStats ) override;\n        void testGroupEnded( TestGroupStats const& testGroupStats ) override;\n        void testRunEnded( TestRunStats const& testRunStats ) override;\n\n        void skipTest( TestCaseInfo const& testInfo ) override;\n        bool isMulti() const override;\n\n    };\n\n} // end namespace Catch\n\n// end catch_reporter_listening.h\nnamespace Catch {\n\n    ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig )\n    :   m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}\n\n    ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream )\n    :   m_stream( &_stream ), m_fullConfig( _fullConfig ) {}\n\n    std::ostream& ReporterConfig::stream() const { return *m_stream; }\n    IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; }\n\n    TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {}\n\n    GroupInfo::GroupInfo(  std::string const& _name,\n                           std::size_t _groupIndex,\n                           std::size_t _groupsCount )\n    :   name( _name ),\n        groupIndex( _groupIndex ),\n        groupsCounts( _groupsCount )\n    {}\n\n     AssertionStats::AssertionStats( AssertionResult const& _assertionResult,\n                                     std::vector<MessageInfo> const& _infoMessages,\n                                     Totals const& _totals )\n    :   assertionResult( _assertionResult ),\n        infoMessages( _infoMessages ),\n        totals( _totals )\n    {\n        assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;\n\n        if( assertionResult.hasMessage() ) {\n            // Copy message into messages list.\n            // !TBD This should have been done earlier, somewhere\n            MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );\n            builder << assertionResult.getMessage();\n            builder.m_info.message = builder.m_stream.str();\n\n            infoMessages.push_back( builder.m_info );\n        }\n    }\n\n     AssertionStats::~AssertionStats() = default;\n\n    SectionStats::SectionStats(  SectionInfo const& _sectionInfo,\n                                 Counts const& _assertions,\n                                 double _durationInSeconds,\n                                 bool _missingAssertions )\n    :   sectionInfo( _sectionInfo ),\n        assertions( _assertions ),\n        durationInSeconds( _durationInSeconds ),\n        missingAssertions( _missingAssertions )\n    {}\n\n    SectionStats::~SectionStats() = default;\n\n    TestCaseStats::TestCaseStats(  TestCaseInfo const& _testInfo,\n                                   Totals const& _totals,\n                                   std::string const& _stdOut,\n                                   std::string const& _stdErr,\n                                   bool _aborting )\n    : testInfo( _testInfo ),\n        totals( _totals ),\n        stdOut( _stdOut ),\n        stdErr( _stdErr ),\n        aborting( _aborting )\n    {}\n\n    TestCaseStats::~TestCaseStats() = default;\n\n    TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo,\n                                    Totals const& _totals,\n                                    bool _aborting )\n    :   groupInfo( _groupInfo ),\n        totals( _totals ),\n        aborting( _aborting )\n    {}\n\n    TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo )\n    :   groupInfo( _groupInfo ),\n        aborting( false )\n    {}\n\n    TestGroupStats::~TestGroupStats() = default;\n\n    TestRunStats::TestRunStats(   TestRunInfo const& _runInfo,\n                    Totals const& _totals,\n                    bool _aborting )\n    :   runInfo( _runInfo ),\n        totals( _totals ),\n        aborting( _aborting )\n    {}\n\n    TestRunStats::~TestRunStats() = default;\n\n    void IStreamingReporter::fatalErrorEncountered( StringRef ) {}\n    bool IStreamingReporter::isMulti() const { return false; }\n\n    IReporterFactory::~IReporterFactory() = default;\n    IReporterRegistry::~IReporterRegistry() = default;\n\n} // end namespace Catch\n// end catch_interfaces_reporter.cpp\n// start catch_interfaces_runner.cpp\n\nnamespace Catch {\n    IRunner::~IRunner() = default;\n}\n// end catch_interfaces_runner.cpp\n// start catch_interfaces_testcase.cpp\n\nnamespace Catch {\n    ITestInvoker::~ITestInvoker() = default;\n    ITestCaseRegistry::~ITestCaseRegistry() = default;\n}\n// end catch_interfaces_testcase.cpp\n// start catch_leak_detector.cpp\n\n#ifdef CATCH_CONFIG_WINDOWS_CRTDBG\n#include <crtdbg.h>\n\nnamespace Catch {\n\n    LeakDetector::LeakDetector() {\n        int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);\n        flag |= _CRTDBG_LEAK_CHECK_DF;\n        flag |= _CRTDBG_ALLOC_MEM_DF;\n        _CrtSetDbgFlag(flag);\n        _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);\n        _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);\n        // Change this to leaking allocation's number to break there\n        _CrtSetBreakAlloc(-1);\n    }\n}\n\n#else\n\n    Catch::LeakDetector::LeakDetector() {}\n\n#endif\n\nCatch::LeakDetector::~LeakDetector() {\n    Catch::cleanUp();\n}\n// end catch_leak_detector.cpp\n// start catch_list.cpp\n\n// start catch_list.h\n\n#include <set>\n\nnamespace Catch {\n\n    std::size_t listTests( Config const& config );\n\n    std::size_t listTestsNamesOnly( Config const& config );\n\n    struct TagInfo {\n        void add( std::string const& spelling );\n        std::string all() const;\n\n        std::set<std::string> spellings;\n        std::size_t count = 0;\n    };\n\n    std::size_t listTags( Config const& config );\n\n    std::size_t listReporters();\n\n    Option<std::size_t> list( std::shared_ptr<Config> const& config );\n\n} // end namespace Catch\n\n// end catch_list.h\n// start catch_text.h\n\nnamespace Catch {\n    using namespace clara::TextFlow;\n}\n\n// end catch_text.h\n#include <limits>\n#include <algorithm>\n#include <iomanip>\n\nnamespace Catch {\n\n    std::size_t listTests( Config const& config ) {\n        TestSpec testSpec = config.testSpec();\n        if( config.hasTestFilters() )\n            Catch::cout() << \"Matching test cases:\\n\";\n        else {\n            Catch::cout() << \"All available test cases:\\n\";\n        }\n\n        auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );\n        for( auto const& testCaseInfo : matchedTestCases ) {\n            Colour::Code colour = testCaseInfo.isHidden()\n                ? Colour::SecondaryText\n                : Colour::None;\n            Colour colourGuard( colour );\n\n            Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << \"\\n\";\n            if( config.verbosity() >= Verbosity::High ) {\n                Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl;\n                std::string description = testCaseInfo.description;\n                if( description.empty() )\n                    description = \"(NO DESCRIPTION)\";\n                Catch::cout() << Column( description ).indent(4) << std::endl;\n            }\n            if( !testCaseInfo.tags.empty() )\n                Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << \"\\n\";\n        }\n\n        if( !config.hasTestFilters() )\n            Catch::cout() << pluralise( matchedTestCases.size(), \"test case\" ) << '\\n' << std::endl;\n        else\n            Catch::cout() << pluralise( matchedTestCases.size(), \"matching test case\" ) << '\\n' << std::endl;\n        return matchedTestCases.size();\n    }\n\n    std::size_t listTestsNamesOnly( Config const& config ) {\n        TestSpec testSpec = config.testSpec();\n        std::size_t matchedTests = 0;\n        std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );\n        for( auto const& testCaseInfo : matchedTestCases ) {\n            matchedTests++;\n            if( startsWith( testCaseInfo.name, '#' ) )\n               Catch::cout() << '\"' << testCaseInfo.name << '\"';\n            else\n               Catch::cout() << testCaseInfo.name;\n            if ( config.verbosity() >= Verbosity::High )\n                Catch::cout() << \"\\t@\" << testCaseInfo.lineInfo;\n            Catch::cout() << std::endl;\n        }\n        return matchedTests;\n    }\n\n    void TagInfo::add( std::string const& spelling ) {\n        ++count;\n        spellings.insert( spelling );\n    }\n\n    std::string TagInfo::all() const {\n        std::string out;\n        for( auto const& spelling : spellings )\n            out += \"[\" + spelling + \"]\";\n        return out;\n    }\n\n    std::size_t listTags( Config const& config ) {\n        TestSpec testSpec = config.testSpec();\n        if( config.hasTestFilters() )\n            Catch::cout() << \"Tags for matching test cases:\\n\";\n        else {\n            Catch::cout() << \"All available tags:\\n\";\n        }\n\n        std::map<std::string, TagInfo> tagCounts;\n\n        std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );\n        for( auto const& testCase : matchedTestCases ) {\n            for( auto const& tagName : testCase.getTestCaseInfo().tags ) {\n                std::string lcaseTagName = toLower( tagName );\n                auto countIt = tagCounts.find( lcaseTagName );\n                if( countIt == tagCounts.end() )\n                    countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;\n                countIt->second.add( tagName );\n            }\n        }\n\n        for( auto const& tagCount : tagCounts ) {\n            ReusableStringStream rss;\n            rss << \"  \" << std::setw(2) << tagCount.second.count << \"  \";\n            auto str = rss.str();\n            auto wrapper = Column( tagCount.second.all() )\n                                                    .initialIndent( 0 )\n                                                    .indent( str.size() )\n                                                    .width( CATCH_CONFIG_CONSOLE_WIDTH-10 );\n            Catch::cout() << str << wrapper << '\\n';\n        }\n        Catch::cout() << pluralise( tagCounts.size(), \"tag\" ) << '\\n' << std::endl;\n        return tagCounts.size();\n    }\n\n    std::size_t listReporters() {\n        Catch::cout() << \"Available reporters:\\n\";\n        IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();\n        std::size_t maxNameLen = 0;\n        for( auto const& factoryKvp : factories )\n            maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() );\n\n        for( auto const& factoryKvp : factories ) {\n            Catch::cout()\n                    << Column( factoryKvp.first + \":\" )\n                            .indent(2)\n                            .width( 5+maxNameLen )\n                    +  Column( factoryKvp.second->getDescription() )\n                            .initialIndent(0)\n                            .indent(2)\n                            .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )\n                    << \"\\n\";\n        }\n        Catch::cout() << std::endl;\n        return factories.size();\n    }\n\n    Option<std::size_t> list( std::shared_ptr<Config> const& config ) {\n        Option<std::size_t> listedCount;\n        getCurrentMutableContext().setConfig( config );\n        if( config->listTests() )\n            listedCount = listedCount.valueOr(0) + listTests( *config );\n        if( config->listTestNamesOnly() )\n            listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config );\n        if( config->listTags() )\n            listedCount = listedCount.valueOr(0) + listTags( *config );\n        if( config->listReporters() )\n            listedCount = listedCount.valueOr(0) + listReporters();\n        return listedCount;\n    }\n\n} // end namespace Catch\n// end catch_list.cpp\n// start catch_matchers.cpp\n\nnamespace Catch {\nnamespace Matchers {\n    namespace Impl {\n\n        std::string MatcherUntypedBase::toString() const {\n            if( m_cachedToString.empty() )\n                m_cachedToString = describe();\n            return m_cachedToString;\n        }\n\n        MatcherUntypedBase::~MatcherUntypedBase() = default;\n\n    } // namespace Impl\n} // namespace Matchers\n\nusing namespace Matchers;\nusing Matchers::Impl::MatcherBase;\n\n} // namespace Catch\n// end catch_matchers.cpp\n// start catch_matchers_floating.cpp\n\n// start catch_polyfills.hpp\n\nnamespace Catch {\n    bool isnan(float f);\n    bool isnan(double d);\n}\n\n// end catch_polyfills.hpp\n// start catch_to_string.hpp\n\n#include <string>\n\nnamespace Catch {\n    template <typename T>\n    std::string to_string(T const& t) {\n#if defined(CATCH_CONFIG_CPP11_TO_STRING)\n        return std::to_string(t);\n#else\n        ReusableStringStream rss;\n        rss << t;\n        return rss.str();\n#endif\n    }\n} // end namespace Catch\n\n// end catch_to_string.hpp\n#include <cstdlib>\n#include <cstdint>\n#include <cstring>\n\nnamespace Catch {\nnamespace Matchers {\nnamespace Floating {\nenum class FloatingPointKind : uint8_t {\n    Float,\n    Double\n};\n}\n}\n}\n\nnamespace {\n\ntemplate <typename T>\nstruct Converter;\n\ntemplate <>\nstruct Converter<float> {\n    static_assert(sizeof(float) == sizeof(int32_t), \"Important ULP matcher assumption violated\");\n    Converter(float f) {\n        std::memcpy(&i, &f, sizeof(f));\n    }\n    int32_t i;\n};\n\ntemplate <>\nstruct Converter<double> {\n    static_assert(sizeof(double) == sizeof(int64_t), \"Important ULP matcher assumption violated\");\n    Converter(double d) {\n        std::memcpy(&i, &d, sizeof(d));\n    }\n    int64_t i;\n};\n\ntemplate <typename T>\nauto convert(T t) -> Converter<T> {\n    return Converter<T>(t);\n}\n\ntemplate <typename FP>\nbool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) {\n    // Comparison with NaN should always be false.\n    // This way we can rule it out before getting into the ugly details\n    if (Catch::isnan(lhs) || Catch::isnan(rhs)) {\n        return false;\n    }\n\n    auto lc = convert(lhs);\n    auto rc = convert(rhs);\n\n    if ((lc.i < 0) != (rc.i < 0)) {\n        // Potentially we can have +0 and -0\n        return lhs == rhs;\n    }\n\n    auto ulpDiff = std::abs(lc.i - rc.i);\n    return ulpDiff <= maxUlpDiff;\n}\n\n}\n\nnamespace Catch {\nnamespace Matchers {\nnamespace Floating {\n    WithinAbsMatcher::WithinAbsMatcher(double target, double margin)\n        :m_target{ target }, m_margin{ margin } {\n        CATCH_ENFORCE(margin >= 0, \"Invalid margin: \" << margin << '.'\n            << \" Margin has to be non-negative.\");\n    }\n\n    // Performs equivalent check of std::fabs(lhs - rhs) <= margin\n    // But without the subtraction to allow for INFINITY in comparison\n    bool WithinAbsMatcher::match(double const& matchee) const {\n        return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);\n    }\n\n    std::string WithinAbsMatcher::describe() const {\n        return \"is within \" + ::Catch::Detail::stringify(m_margin) + \" of \" + ::Catch::Detail::stringify(m_target);\n    }\n\n    WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)\n        :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {\n        CATCH_ENFORCE(ulps >= 0, \"Invalid ULP setting: \" << ulps << '.'\n            << \" ULPs have to be non-negative.\");\n    }\n\n#if defined(__clang__)\n#pragma clang diagnostic push\n// Clang <3.5 reports on the default branch in the switch below\n#pragma clang diagnostic ignored \"-Wunreachable-code\"\n#endif\n\n    bool WithinUlpsMatcher::match(double const& matchee) const {\n        switch (m_type) {\n        case FloatingPointKind::Float:\n            return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);\n        case FloatingPointKind::Double:\n            return almostEqualUlps<double>(matchee, m_target, m_ulps);\n        default:\n            CATCH_INTERNAL_ERROR( \"Unknown FloatingPointKind value\" );\n        }\n    }\n\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n\n    std::string WithinUlpsMatcher::describe() const {\n        return \"is within \" + Catch::to_string(m_ulps) + \" ULPs of \" + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? \"f\" : \"\");\n    }\n\n}// namespace Floating\n\nFloating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff) {\n    return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);\n}\n\nFloating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff) {\n    return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);\n}\n\nFloating::WithinAbsMatcher WithinAbs(double target, double margin) {\n    return Floating::WithinAbsMatcher(target, margin);\n}\n\n} // namespace Matchers\n} // namespace Catch\n\n// end catch_matchers_floating.cpp\n// start catch_matchers_generic.cpp\n\nstd::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) {\n    if (desc.empty()) {\n        return \"matches undescribed predicate\";\n    } else {\n        return \"matches predicate: \\\"\" + desc + '\"';\n    }\n}\n// end catch_matchers_generic.cpp\n// start catch_matchers_string.cpp\n\n#include <regex>\n\nnamespace Catch {\nnamespace Matchers {\n\n    namespace StdString {\n\n        CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )\n        :   m_caseSensitivity( caseSensitivity ),\n            m_str( adjustString( str ) )\n        {}\n        std::string CasedString::adjustString( std::string const& str ) const {\n            return m_caseSensitivity == CaseSensitive::No\n                   ? toLower( str )\n                   : str;\n        }\n        std::string CasedString::caseSensitivitySuffix() const {\n            return m_caseSensitivity == CaseSensitive::No\n                   ? \" (case insensitive)\"\n                   : std::string();\n        }\n\n        StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )\n        : m_comparator( comparator ),\n          m_operation( operation ) {\n        }\n\n        std::string StringMatcherBase::describe() const {\n            std::string description;\n            description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +\n                                        m_comparator.caseSensitivitySuffix().size());\n            description += m_operation;\n            description += \": \\\"\";\n            description += m_comparator.m_str;\n            description += \"\\\"\";\n            description += m_comparator.caseSensitivitySuffix();\n            return description;\n        }\n\n        EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( \"equals\", comparator ) {}\n\n        bool EqualsMatcher::match( std::string const& source ) const {\n            return m_comparator.adjustString( source ) == m_comparator.m_str;\n        }\n\n        ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( \"contains\", comparator ) {}\n\n        bool ContainsMatcher::match( std::string const& source ) const {\n            return contains( m_comparator.adjustString( source ), m_comparator.m_str );\n        }\n\n        StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( \"starts with\", comparator ) {}\n\n        bool StartsWithMatcher::match( std::string const& source ) const {\n            return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );\n        }\n\n        EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( \"ends with\", comparator ) {}\n\n        bool EndsWithMatcher::match( std::string const& source ) const {\n            return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );\n        }\n\n        RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {}\n\n        bool RegexMatcher::match(std::string const& matchee) const {\n            auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway\n            if (m_caseSensitivity == CaseSensitive::Choice::No) {\n                flags |= std::regex::icase;\n            }\n            auto reg = std::regex(m_regex, flags);\n            return std::regex_match(matchee, reg);\n        }\n\n        std::string RegexMatcher::describe() const {\n            return \"matches \" + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? \" case sensitively\" : \" case insensitively\");\n        }\n\n    } // namespace StdString\n\n    StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {\n        return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );\n    }\n    StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {\n        return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );\n    }\n    StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {\n        return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );\n    }\n    StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {\n        return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );\n    }\n\n    StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) {\n        return StdString::RegexMatcher(regex, caseSensitivity);\n    }\n\n} // namespace Matchers\n} // namespace Catch\n// end catch_matchers_string.cpp\n// start catch_message.cpp\n\n// start catch_uncaught_exceptions.h\n\nnamespace Catch {\n    bool uncaught_exceptions();\n} // end namespace Catch\n\n// end catch_uncaught_exceptions.h\n#include <cassert>\n#include <stack>\n\nnamespace Catch {\n\n    MessageInfo::MessageInfo(   StringRef const& _macroName,\n                                SourceLineInfo const& _lineInfo,\n                                ResultWas::OfType _type )\n    :   macroName( _macroName ),\n        lineInfo( _lineInfo ),\n        type( _type ),\n        sequence( ++globalCount )\n    {}\n\n    bool MessageInfo::operator==( MessageInfo const& other ) const {\n        return sequence == other.sequence;\n    }\n\n    bool MessageInfo::operator<( MessageInfo const& other ) const {\n        return sequence < other.sequence;\n    }\n\n    // This may need protecting if threading support is added\n    unsigned int MessageInfo::globalCount = 0;\n\n    ////////////////////////////////////////////////////////////////////////////\n\n    Catch::MessageBuilder::MessageBuilder( StringRef const& macroName,\n                                           SourceLineInfo const& lineInfo,\n                                           ResultWas::OfType type )\n        :m_info(macroName, lineInfo, type) {}\n\n    ////////////////////////////////////////////////////////////////////////////\n\n    ScopedMessage::ScopedMessage( MessageBuilder const& builder )\n    : m_info( builder.m_info ), m_moved()\n    {\n        m_info.message = builder.m_stream.str();\n        getResultCapture().pushScopedMessage( m_info );\n    }\n\n    ScopedMessage::ScopedMessage( ScopedMessage&& old )\n    : m_info( old.m_info ), m_moved()\n    {\n        old.m_moved = true;\n    }\n\n    ScopedMessage::~ScopedMessage() {\n        if ( !uncaught_exceptions() && !m_moved ){\n            getResultCapture().popScopedMessage(m_info);\n        }\n    }\n\n    Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {\n        auto trimmed = [&] (size_t start, size_t end) {\n            while (names[start] == ',' || isspace(names[start])) {\n                ++start;\n            }\n            while (names[end] == ',' || isspace(names[end])) {\n                --end;\n            }\n            return names.substr(start, end - start + 1);\n        };\n\n        size_t start = 0;\n        std::stack<char> openings;\n        for (size_t pos = 0; pos < names.size(); ++pos) {\n            char c = names[pos];\n            switch (c) {\n            case '[':\n            case '{':\n            case '(':\n            // It is basically impossible to disambiguate between\n            // comparison and start of template args in this context\n//            case '<':\n                openings.push(c);\n                break;\n            case ']':\n            case '}':\n            case ')':\n//           case '>':\n                openings.pop();\n                break;\n            case ',':\n                if (start != pos && openings.size() == 0) {\n                    m_messages.emplace_back(macroName, lineInfo, resultType);\n                    m_messages.back().message = trimmed(start, pos);\n                    m_messages.back().message += \" := \";\n                    start = pos;\n                }\n            }\n        }\n        assert(openings.size() == 0 && \"Mismatched openings\");\n        m_messages.emplace_back(macroName, lineInfo, resultType);\n        m_messages.back().message = trimmed(start, names.size() - 1);\n        m_messages.back().message += \" := \";\n    }\n    Capturer::~Capturer() {\n        if ( !uncaught_exceptions() ){\n            assert( m_captured == m_messages.size() );\n            for( size_t i = 0; i < m_captured; ++i  )\n                m_resultCapture.popScopedMessage( m_messages[i] );\n        }\n    }\n\n    void Capturer::captureValue( size_t index, std::string const& value ) {\n        assert( index < m_messages.size() );\n        m_messages[index].message += value;\n        m_resultCapture.pushScopedMessage( m_messages[index] );\n        m_captured++;\n    }\n\n} // end namespace Catch\n// end catch_message.cpp\n// start catch_output_redirect.cpp\n\n// start catch_output_redirect.h\n#ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H\n#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H\n\n#include <cstdio>\n#include <iosfwd>\n#include <string>\n\nnamespace Catch {\n\n    class RedirectedStream {\n        std::ostream& m_originalStream;\n        std::ostream& m_redirectionStream;\n        std::streambuf* m_prevBuf;\n\n    public:\n        RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );\n        ~RedirectedStream();\n    };\n\n    class RedirectedStdOut {\n        ReusableStringStream m_rss;\n        RedirectedStream m_cout;\n    public:\n        RedirectedStdOut();\n        auto str() const -> std::string;\n    };\n\n    // StdErr has two constituent streams in C++, std::cerr and std::clog\n    // This means that we need to redirect 2 streams into 1 to keep proper\n    // order of writes\n    class RedirectedStdErr {\n        ReusableStringStream m_rss;\n        RedirectedStream m_cerr;\n        RedirectedStream m_clog;\n    public:\n        RedirectedStdErr();\n        auto str() const -> std::string;\n    };\n\n    class RedirectedStreams {\n    public:\n        RedirectedStreams(RedirectedStreams const&) = delete;\n        RedirectedStreams& operator=(RedirectedStreams const&) = delete;\n        RedirectedStreams(RedirectedStreams&&) = delete;\n        RedirectedStreams& operator=(RedirectedStreams&&) = delete;\n\n        RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);\n        ~RedirectedStreams();\n    private:\n        std::string& m_redirectedCout;\n        std::string& m_redirectedCerr;\n        RedirectedStdOut m_redirectedStdOut;\n        RedirectedStdErr m_redirectedStdErr;\n    };\n\n#if defined(CATCH_CONFIG_NEW_CAPTURE)\n\n    // Windows's implementation of std::tmpfile is terrible (it tries\n    // to create a file inside system folder, thus requiring elevated\n    // privileges for the binary), so we have to use tmpnam(_s) and\n    // create the file ourselves there.\n    class TempFile {\n    public:\n        TempFile(TempFile const&) = delete;\n        TempFile& operator=(TempFile const&) = delete;\n        TempFile(TempFile&&) = delete;\n        TempFile& operator=(TempFile&&) = delete;\n\n        TempFile();\n        ~TempFile();\n\n        std::FILE* getFile();\n        std::string getContents();\n\n    private:\n        std::FILE* m_file = nullptr;\n    #if defined(_MSC_VER)\n        char m_buffer[L_tmpnam] = { 0 };\n    #endif\n    };\n\n    class OutputRedirect {\n    public:\n        OutputRedirect(OutputRedirect const&) = delete;\n        OutputRedirect& operator=(OutputRedirect const&) = delete;\n        OutputRedirect(OutputRedirect&&) = delete;\n        OutputRedirect& operator=(OutputRedirect&&) = delete;\n\n        OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);\n        ~OutputRedirect();\n\n    private:\n        int m_originalStdout = -1;\n        int m_originalStderr = -1;\n        TempFile m_stdoutFile;\n        TempFile m_stderrFile;\n        std::string& m_stdoutDest;\n        std::string& m_stderrDest;\n    };\n\n#endif\n\n} // end namespace Catch\n\n#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H\n// end catch_output_redirect.h\n#include <cstdio>\n#include <cstring>\n#include <fstream>\n#include <sstream>\n#include <stdexcept>\n\n#if defined(CATCH_CONFIG_NEW_CAPTURE)\n    #if defined(_MSC_VER)\n    #include <io.h>      //_dup and _dup2\n    #define dup _dup\n    #define dup2 _dup2\n    #define fileno _fileno\n    #else\n    #include <unistd.h>  // dup and dup2\n    #endif\n#endif\n\nnamespace Catch {\n\n    RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )\n    :   m_originalStream( originalStream ),\n        m_redirectionStream( redirectionStream ),\n        m_prevBuf( m_originalStream.rdbuf() )\n    {\n        m_originalStream.rdbuf( m_redirectionStream.rdbuf() );\n    }\n\n    RedirectedStream::~RedirectedStream() {\n        m_originalStream.rdbuf( m_prevBuf );\n    }\n\n    RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}\n    auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); }\n\n    RedirectedStdErr::RedirectedStdErr()\n    :   m_cerr( Catch::cerr(), m_rss.get() ),\n        m_clog( Catch::clog(), m_rss.get() )\n    {}\n    auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }\n\n    RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)\n    :   m_redirectedCout(redirectedCout),\n        m_redirectedCerr(redirectedCerr)\n    {}\n\n    RedirectedStreams::~RedirectedStreams() {\n        m_redirectedCout += m_redirectedStdOut.str();\n        m_redirectedCerr += m_redirectedStdErr.str();\n    }\n\n#if defined(CATCH_CONFIG_NEW_CAPTURE)\n\n#if defined(_MSC_VER)\n    TempFile::TempFile() {\n        if (tmpnam_s(m_buffer)) {\n            CATCH_RUNTIME_ERROR(\"Could not get a temp filename\");\n        }\n        if (fopen_s(&m_file, m_buffer, \"w\")) {\n            char buffer[100];\n            if (strerror_s(buffer, errno)) {\n                CATCH_RUNTIME_ERROR(\"Could not translate errno to a string\");\n            }\n            CATCH_RUNTIME_ERROR(\"Coul dnot open the temp file: '\" << m_buffer << \"' because: \" << buffer);\n        }\n    }\n#else\n    TempFile::TempFile() {\n        m_file = std::tmpfile();\n        if (!m_file) {\n            CATCH_RUNTIME_ERROR(\"Could not create a temp file.\");\n        }\n    }\n\n#endif\n\n    TempFile::~TempFile() {\n         // TBD: What to do about errors here?\n         std::fclose(m_file);\n         // We manually create the file on Windows only, on Linux\n         // it will be autodeleted\n#if defined(_MSC_VER)\n         std::remove(m_buffer);\n#endif\n    }\n\n    FILE* TempFile::getFile() {\n        return m_file;\n    }\n\n    std::string TempFile::getContents() {\n        std::stringstream sstr;\n        char buffer[100] = {};\n        std::rewind(m_file);\n        while (std::fgets(buffer, sizeof(buffer), m_file)) {\n            sstr << buffer;\n        }\n        return sstr.str();\n    }\n\n    OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :\n        m_originalStdout(dup(1)),\n        m_originalStderr(dup(2)),\n        m_stdoutDest(stdout_dest),\n        m_stderrDest(stderr_dest) {\n        dup2(fileno(m_stdoutFile.getFile()), 1);\n        dup2(fileno(m_stderrFile.getFile()), 2);\n    }\n\n    OutputRedirect::~OutputRedirect() {\n        Catch::cout() << std::flush;\n        fflush(stdout);\n        // Since we support overriding these streams, we flush cerr\n        // even though std::cerr is unbuffered\n        Catch::cerr() << std::flush;\n        Catch::clog() << std::flush;\n        fflush(stderr);\n\n        dup2(m_originalStdout, 1);\n        dup2(m_originalStderr, 2);\n\n        m_stdoutDest += m_stdoutFile.getContents();\n        m_stderrDest += m_stderrFile.getContents();\n    }\n\n#endif // CATCH_CONFIG_NEW_CAPTURE\n\n} // namespace Catch\n\n#if defined(CATCH_CONFIG_NEW_CAPTURE)\n    #if defined(_MSC_VER)\n    #undef dup\n    #undef dup2\n    #undef fileno\n    #endif\n#endif\n// end catch_output_redirect.cpp\n// start catch_polyfills.cpp\n\n#include <cmath>\n\nnamespace Catch {\n\n#if !defined(CATCH_CONFIG_POLYFILL_ISNAN)\n    bool isnan(float f) {\n        return std::isnan(f);\n    }\n    bool isnan(double d) {\n        return std::isnan(d);\n    }\n#else\n    // For now we only use this for embarcadero\n    bool isnan(float f) {\n        return std::_isnan(f);\n    }\n    bool isnan(double d) {\n        return std::_isnan(d);\n    }\n#endif\n\n} // end namespace Catch\n// end catch_polyfills.cpp\n// start catch_random_number_generator.cpp\n\nnamespace Catch {\n\n    std::mt19937& rng() {\n        static std::mt19937 s_rng;\n        return s_rng;\n    }\n\n    void seedRng( IConfig const& config ) {\n        if( config.rngSeed() != 0 ) {\n            std::srand( config.rngSeed() );\n            rng().seed( config.rngSeed() );\n        }\n    }\n\n    unsigned int rngSeed() {\n        return getCurrentContext().getConfig()->rngSeed();\n    }\n}\n// end catch_random_number_generator.cpp\n// start catch_registry_hub.cpp\n\n// start catch_test_case_registry_impl.h\n\n#include <vector>\n#include <set>\n#include <algorithm>\n#include <ios>\n\nnamespace Catch {\n\n    class TestCase;\n    struct IConfig;\n\n    std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );\n    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );\n\n    void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );\n\n    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );\n    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );\n\n    class TestRegistry : public ITestCaseRegistry {\n    public:\n        virtual ~TestRegistry() = default;\n\n        virtual void registerTest( TestCase const& testCase );\n\n        std::vector<TestCase> const& getAllTests() const override;\n        std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override;\n\n    private:\n        std::vector<TestCase> m_functions;\n        mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;\n        mutable std::vector<TestCase> m_sortedFunctions;\n        std::size_t m_unnamedCount = 0;\n        std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised\n    };\n\n    ///////////////////////////////////////////////////////////////////////////\n\n    class TestInvokerAsFunction : public ITestInvoker {\n        void(*m_testAsFunction)();\n    public:\n        TestInvokerAsFunction( void(*testAsFunction)() ) noexcept;\n\n        void invoke() const override;\n    };\n\n    std::string extractClassName( StringRef const& classOrQualifiedMethodName );\n\n    ///////////////////////////////////////////////////////////////////////////\n\n} // end namespace Catch\n\n// end catch_test_case_registry_impl.h\n// start catch_reporter_registry.h\n\n#include <map>\n\nnamespace Catch {\n\n    class ReporterRegistry : public IReporterRegistry {\n\n    public:\n\n        ~ReporterRegistry() override;\n\n        IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override;\n\n        void registerReporter( std::string const& name, IReporterFactoryPtr const& factory );\n        void registerListener( IReporterFactoryPtr const& factory );\n\n        FactoryMap const& getFactories() const override;\n        Listeners const& getListeners() const override;\n\n    private:\n        FactoryMap m_factories;\n        Listeners m_listeners;\n    };\n}\n\n// end catch_reporter_registry.h\n// start catch_tag_alias_registry.h\n\n// start catch_tag_alias.h\n\n#include <string>\n\nnamespace Catch {\n\n    struct TagAlias {\n        TagAlias(std::string const& _tag, SourceLineInfo _lineInfo);\n\n        std::string tag;\n        SourceLineInfo lineInfo;\n    };\n\n} // end namespace Catch\n\n// end catch_tag_alias.h\n#include <map>\n\nnamespace Catch {\n\n    class TagAliasRegistry : public ITagAliasRegistry {\n    public:\n        ~TagAliasRegistry() override;\n        TagAlias const* find( std::string const& alias ) const override;\n        std::string expandAliases( std::string const& unexpandedTestSpec ) const override;\n        void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );\n\n    private:\n        std::map<std::string, TagAlias> m_registry;\n    };\n\n} // end namespace Catch\n\n// end catch_tag_alias_registry.h\n// start catch_startup_exception_registry.h\n\n#include <vector>\n#include <exception>\n\nnamespace Catch {\n\n    class StartupExceptionRegistry {\n    public:\n        void add(std::exception_ptr const& exception) noexcept;\n        std::vector<std::exception_ptr> const& getExceptions() const noexcept;\n    private:\n        std::vector<std::exception_ptr> m_exceptions;\n    };\n\n} // end namespace Catch\n\n// end catch_startup_exception_registry.h\n// start catch_singletons.hpp\n\nnamespace Catch {\n\n    struct ISingleton {\n        virtual ~ISingleton();\n    };\n\n    void addSingleton( ISingleton* singleton );\n    void cleanupSingletons();\n\n    template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>\n    class Singleton : SingletonImplT, public ISingleton {\n\n        static auto getInternal() -> Singleton* {\n            static Singleton* s_instance = nullptr;\n            if( !s_instance ) {\n                s_instance = new Singleton;\n                addSingleton( s_instance );\n            }\n            return s_instance;\n        }\n\n    public:\n        static auto get() -> InterfaceT const& {\n            return *getInternal();\n        }\n        static auto getMutable() -> MutableInterfaceT& {\n            return *getInternal();\n        }\n    };\n\n} // namespace Catch\n\n// end catch_singletons.hpp\nnamespace Catch {\n\n    namespace {\n\n        class RegistryHub : public IRegistryHub, public IMutableRegistryHub,\n                            private NonCopyable {\n\n        public: // IRegistryHub\n            RegistryHub() = default;\n            IReporterRegistry const& getReporterRegistry() const override {\n                return m_reporterRegistry;\n            }\n            ITestCaseRegistry const& getTestCaseRegistry() const override {\n                return m_testCaseRegistry;\n            }\n            IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override {\n                return m_exceptionTranslatorRegistry;\n            }\n            ITagAliasRegistry const& getTagAliasRegistry() const override {\n                return m_tagAliasRegistry;\n            }\n            StartupExceptionRegistry const& getStartupExceptionRegistry() const override {\n                return m_exceptionRegistry;\n            }\n\n        public: // IMutableRegistryHub\n            void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override {\n                m_reporterRegistry.registerReporter( name, factory );\n            }\n            void registerListener( IReporterFactoryPtr const& factory ) override {\n                m_reporterRegistry.registerListener( factory );\n            }\n            void registerTest( TestCase const& testInfo ) override {\n                m_testCaseRegistry.registerTest( testInfo );\n            }\n            void registerTranslator( const IExceptionTranslator* translator ) override {\n                m_exceptionTranslatorRegistry.registerTranslator( translator );\n            }\n            void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override {\n                m_tagAliasRegistry.add( alias, tag, lineInfo );\n            }\n            void registerStartupException() noexcept override {\n                m_exceptionRegistry.add(std::current_exception());\n            }\n\n        private:\n            TestRegistry m_testCaseRegistry;\n            ReporterRegistry m_reporterRegistry;\n            ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;\n            TagAliasRegistry m_tagAliasRegistry;\n            StartupExceptionRegistry m_exceptionRegistry;\n        };\n    }\n\n    using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;\n\n    IRegistryHub const& getRegistryHub() {\n        return RegistryHubSingleton::get();\n    }\n    IMutableRegistryHub& getMutableRegistryHub() {\n        return RegistryHubSingleton::getMutable();\n    }\n    void cleanUp() {\n        cleanupSingletons();\n        cleanUpContext();\n    }\n    std::string translateActiveException() {\n        return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();\n    }\n\n} // end namespace Catch\n// end catch_registry_hub.cpp\n// start catch_reporter_registry.cpp\n\nnamespace Catch {\n\n    ReporterRegistry::~ReporterRegistry() = default;\n\n    IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const {\n        auto it =  m_factories.find( name );\n        if( it == m_factories.end() )\n            return nullptr;\n        return it->second->create( ReporterConfig( config ) );\n    }\n\n    void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) {\n        m_factories.emplace(name, factory);\n    }\n    void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) {\n        m_listeners.push_back( factory );\n    }\n\n    IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const {\n        return m_factories;\n    }\n    IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const {\n        return m_listeners;\n    }\n\n}\n// end catch_reporter_registry.cpp\n// start catch_result_type.cpp\n\nnamespace Catch {\n\n    bool isOk( ResultWas::OfType resultType ) {\n        return ( resultType & ResultWas::FailureBit ) == 0;\n    }\n    bool isJustInfo( int flags ) {\n        return flags == ResultWas::Info;\n    }\n\n    ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {\n        return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );\n    }\n\n    bool shouldContinueOnFailure( int flags )    { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }\n    bool shouldSuppressFailure( int flags )      { return ( flags & ResultDisposition::SuppressFail ) != 0; }\n\n} // end namespace Catch\n// end catch_result_type.cpp\n// start catch_run_context.cpp\n\n#include <cassert>\n#include <algorithm>\n#include <sstream>\n\nnamespace Catch {\n\n    namespace Generators {\n        struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {\n            GeneratorBasePtr m_generator;\n\n            GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )\n            :   TrackerBase( nameAndLocation, ctx, parent )\n            {}\n            ~GeneratorTracker();\n\n            static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {\n                std::shared_ptr<GeneratorTracker> tracker;\n\n                ITracker& currentTracker = ctx.currentTracker();\n                if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {\n                    assert( childTracker );\n                    assert( childTracker->isGeneratorTracker() );\n                    tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );\n                }\n                else {\n                    tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, &currentTracker );\n                    currentTracker.addChild( tracker );\n                }\n\n                if( !ctx.completedCycle() && !tracker->isComplete() ) {\n                    tracker->open();\n                }\n\n                return *tracker;\n            }\n\n            // TrackerBase interface\n            bool isGeneratorTracker() const override { return true; }\n            auto hasGenerator() const -> bool override {\n                return !!m_generator;\n            }\n            void close() override {\n                TrackerBase::close();\n                // Generator interface only finds out if it has another item on atual move\n                if (m_runState == CompletedSuccessfully && m_generator->next()) {\n                    m_children.clear();\n                    m_runState = Executing;\n                }\n            }\n\n            // IGeneratorTracker interface\n            auto getGenerator() const -> GeneratorBasePtr const& override {\n                return m_generator;\n            }\n            void setGenerator( GeneratorBasePtr&& generator ) override {\n                m_generator = std::move( generator );\n            }\n        };\n        GeneratorTracker::~GeneratorTracker() {}\n    }\n\n    RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)\n    :   m_runInfo(_config->name()),\n        m_context(getCurrentMutableContext()),\n        m_config(_config),\n        m_reporter(std::move(reporter)),\n        m_lastAssertionInfo{ StringRef(), SourceLineInfo(\"\",0), StringRef(), ResultDisposition::Normal },\n        m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )\n    {\n        m_context.setRunner(this);\n        m_context.setConfig(m_config);\n        m_context.setResultCapture(this);\n        m_reporter->testRunStarting(m_runInfo);\n    }\n\n    RunContext::~RunContext() {\n        m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));\n    }\n\n    void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {\n        m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));\n    }\n\n    void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) {\n        m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));\n    }\n\n    Totals RunContext::runTest(TestCase const& testCase) {\n        Totals prevTotals = m_totals;\n\n        std::string redirectedCout;\n        std::string redirectedCerr;\n\n        auto const& testInfo = testCase.getTestCaseInfo();\n\n        m_reporter->testCaseStarting(testInfo);\n\n        m_activeTestCase = &testCase;\n\n        ITracker& rootTracker = m_trackerContext.startRun();\n        assert(rootTracker.isSectionTracker());\n        static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());\n        do {\n            m_trackerContext.startCycle();\n            m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));\n            runCurrentTest(redirectedCout, redirectedCerr);\n        } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());\n\n        Totals deltaTotals = m_totals.delta(prevTotals);\n        if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {\n            deltaTotals.assertions.failed++;\n            deltaTotals.testCases.passed--;\n            deltaTotals.testCases.failed++;\n        }\n        m_totals.testCases += deltaTotals.testCases;\n        m_reporter->testCaseEnded(TestCaseStats(testInfo,\n                                  deltaTotals,\n                                  redirectedCout,\n                                  redirectedCerr,\n                                  aborting()));\n\n        m_activeTestCase = nullptr;\n        m_testCaseTracker = nullptr;\n\n        return deltaTotals;\n    }\n\n    IConfigPtr RunContext::config() const {\n        return m_config;\n    }\n\n    IStreamingReporter& RunContext::reporter() const {\n        return *m_reporter;\n    }\n\n    void RunContext::assertionEnded(AssertionResult const & result) {\n        if (result.getResultType() == ResultWas::Ok) {\n            m_totals.assertions.passed++;\n            m_lastAssertionPassed = true;\n        } else if (!result.isOk()) {\n            m_lastAssertionPassed = false;\n            if( m_activeTestCase->getTestCaseInfo().okToFail() )\n                m_totals.assertions.failedButOk++;\n            else\n                m_totals.assertions.failed++;\n        }\n        else {\n            m_lastAssertionPassed = true;\n        }\n\n        // We have no use for the return value (whether messages should be cleared), because messages were made scoped\n        // and should be let to clear themselves out.\n        static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));\n\n        if (result.getResultType() != ResultWas::Warning)\n            m_messageScopes.clear();\n\n        // Reset working state\n        resetAssertionInfo();\n        m_lastResult = result;\n    }\n    void RunContext::resetAssertionInfo() {\n        m_lastAssertionInfo.macroName = StringRef();\n        m_lastAssertionInfo.capturedExpression = \"{Unknown expression after the reported line}\"_sr;\n    }\n\n    bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) {\n        ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));\n        if (!sectionTracker.isOpen())\n            return false;\n        m_activeSections.push_back(&sectionTracker);\n\n        m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;\n\n        m_reporter->sectionStarting(sectionInfo);\n\n        assertions = m_totals.assertions;\n\n        return true;\n    }\n    auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {\n        using namespace Generators;\n        GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( \"generator\", lineInfo ) );\n        assert( tracker.isOpen() );\n        m_lastAssertionInfo.lineInfo = lineInfo;\n        return tracker;\n    }\n\n    bool RunContext::testForMissingAssertions(Counts& assertions) {\n        if (assertions.total() != 0)\n            return false;\n        if (!m_config->warnAboutMissingAssertions())\n            return false;\n        if (m_trackerContext.currentTracker().hasChildren())\n            return false;\n        m_totals.assertions.failed++;\n        assertions.failed++;\n        return true;\n    }\n\n    void RunContext::sectionEnded(SectionEndInfo const & endInfo) {\n        Counts assertions = m_totals.assertions - endInfo.prevAssertions;\n        bool missingAssertions = testForMissingAssertions(assertions);\n\n        if (!m_activeSections.empty()) {\n            m_activeSections.back()->close();\n            m_activeSections.pop_back();\n        }\n\n        m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));\n        m_messages.clear();\n        m_messageScopes.clear();\n    }\n\n    void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {\n        if (m_unfinishedSections.empty())\n            m_activeSections.back()->fail();\n        else\n            m_activeSections.back()->close();\n        m_activeSections.pop_back();\n\n        m_unfinishedSections.push_back(endInfo);\n    }\n    void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {\n        m_reporter->benchmarkStarting( info );\n    }\n    void RunContext::benchmarkEnded( BenchmarkStats const& stats ) {\n        m_reporter->benchmarkEnded( stats );\n    }\n\n    void RunContext::pushScopedMessage(MessageInfo const & message) {\n        m_messages.push_back(message);\n    }\n\n    void RunContext::popScopedMessage(MessageInfo const & message) {\n        m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());\n    }\n\n    void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {\n        m_messageScopes.emplace_back( builder );\n    }\n\n    std::string RunContext::getCurrentTestName() const {\n        return m_activeTestCase\n            ? m_activeTestCase->getTestCaseInfo().name\n            : std::string();\n    }\n\n    const AssertionResult * RunContext::getLastResult() const {\n        return &(*m_lastResult);\n    }\n\n    void RunContext::exceptionEarlyReported() {\n        m_shouldReportUnexpected = false;\n    }\n\n    void RunContext::handleFatalErrorCondition( StringRef message ) {\n        // First notify reporter that bad things happened\n        m_reporter->fatalErrorEncountered(message);\n\n        // Don't rebuild the result -- the stringification itself can cause more fatal errors\n        // Instead, fake a result data.\n        AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );\n        tempResult.message = message;\n        AssertionResult result(m_lastAssertionInfo, tempResult);\n\n        assertionEnded(result);\n\n        handleUnfinishedSections();\n\n        // Recreate section for test case (as we will lose the one that was in scope)\n        auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();\n        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);\n\n        Counts assertions;\n        assertions.failed = 1;\n        SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);\n        m_reporter->sectionEnded(testCaseSectionStats);\n\n        auto const& testInfo = m_activeTestCase->getTestCaseInfo();\n\n        Totals deltaTotals;\n        deltaTotals.testCases.failed = 1;\n        deltaTotals.assertions.failed = 1;\n        m_reporter->testCaseEnded(TestCaseStats(testInfo,\n                                  deltaTotals,\n                                  std::string(),\n                                  std::string(),\n                                  false));\n        m_totals.testCases.failed++;\n        testGroupEnded(std::string(), m_totals, 1, 1);\n        m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));\n    }\n\n    bool RunContext::lastAssertionPassed() {\n         return m_lastAssertionPassed;\n    }\n\n    void RunContext::assertionPassed() {\n        m_lastAssertionPassed = true;\n        ++m_totals.assertions.passed;\n        resetAssertionInfo();\n        m_messageScopes.clear();\n    }\n\n    bool RunContext::aborting() const {\n        return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter());\n    }\n\n    void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {\n        auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();\n        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);\n        m_reporter->sectionStarting(testCaseSection);\n        Counts prevAssertions = m_totals.assertions;\n        double duration = 0;\n        m_shouldReportUnexpected = true;\n        m_lastAssertionInfo = { \"TEST_CASE\"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };\n\n        seedRng(*m_config);\n\n        Timer timer;\n        CATCH_TRY {\n            if (m_reporter->getPreferences().shouldRedirectStdOut) {\n#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)\n                RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);\n\n                timer.start();\n                invokeActiveTestCase();\n#else\n                OutputRedirect r(redirectedCout, redirectedCerr);\n                timer.start();\n                invokeActiveTestCase();\n#endif\n            } else {\n                timer.start();\n                invokeActiveTestCase();\n            }\n            duration = timer.getElapsedSeconds();\n        } CATCH_CATCH_ANON (TestFailureException&) {\n            // This just means the test was aborted due to failure\n        } CATCH_CATCH_ALL {\n            // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions\n            // are reported without translation at the point of origin.\n            if( m_shouldReportUnexpected ) {\n                AssertionReaction dummyReaction;\n                handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );\n            }\n        }\n        Counts assertions = m_totals.assertions - prevAssertions;\n        bool missingAssertions = testForMissingAssertions(assertions);\n\n        m_testCaseTracker->close();\n        handleUnfinishedSections();\n        m_messages.clear();\n        m_messageScopes.clear();\n\n        SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);\n        m_reporter->sectionEnded(testCaseSectionStats);\n    }\n\n    void RunContext::invokeActiveTestCase() {\n        FatalConditionHandler fatalConditionHandler; // Handle signals\n        m_activeTestCase->invoke();\n        fatalConditionHandler.reset();\n    }\n\n    void RunContext::handleUnfinishedSections() {\n        // If sections ended prematurely due to an exception we stored their\n        // infos here so we can tear them down outside the unwind process.\n        for (auto it = m_unfinishedSections.rbegin(),\n             itEnd = m_unfinishedSections.rend();\n             it != itEnd;\n             ++it)\n            sectionEnded(*it);\n        m_unfinishedSections.clear();\n    }\n\n    void RunContext::handleExpr(\n        AssertionInfo const& info,\n        ITransientExpression const& expr,\n        AssertionReaction& reaction\n    ) {\n        m_reporter->assertionStarting( info );\n\n        bool negated = isFalseTest( info.resultDisposition );\n        bool result = expr.getResult() != negated;\n\n        if( result ) {\n            if (!m_includeSuccessfulResults) {\n                assertionPassed();\n            }\n            else {\n                reportExpr(info, ResultWas::Ok, &expr, negated);\n            }\n        }\n        else {\n            reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );\n            populateReaction( reaction );\n        }\n    }\n    void RunContext::reportExpr(\n            AssertionInfo const &info,\n            ResultWas::OfType resultType,\n            ITransientExpression const *expr,\n            bool negated ) {\n\n        m_lastAssertionInfo = info;\n        AssertionResultData data( resultType, LazyExpression( negated ) );\n\n        AssertionResult assertionResult{ info, data };\n        assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;\n\n        assertionEnded( assertionResult );\n    }\n\n    void RunContext::handleMessage(\n            AssertionInfo const& info,\n            ResultWas::OfType resultType,\n            StringRef const& message,\n            AssertionReaction& reaction\n    ) {\n        m_reporter->assertionStarting( info );\n\n        m_lastAssertionInfo = info;\n\n        AssertionResultData data( resultType, LazyExpression( false ) );\n        data.message = message;\n        AssertionResult assertionResult{ m_lastAssertionInfo, data };\n        assertionEnded( assertionResult );\n        if( !assertionResult.isOk() )\n            populateReaction( reaction );\n    }\n    void RunContext::handleUnexpectedExceptionNotThrown(\n            AssertionInfo const& info,\n            AssertionReaction& reaction\n    ) {\n        handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);\n    }\n\n    void RunContext::handleUnexpectedInflightException(\n            AssertionInfo const& info,\n            std::string const& message,\n            AssertionReaction& reaction\n    ) {\n        m_lastAssertionInfo = info;\n\n        AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );\n        data.message = message;\n        AssertionResult assertionResult{ info, data };\n        assertionEnded( assertionResult );\n        populateReaction( reaction );\n    }\n\n    void RunContext::populateReaction( AssertionReaction& reaction ) {\n        reaction.shouldDebugBreak = m_config->shouldDebugBreak();\n        reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);\n    }\n\n    void RunContext::handleIncomplete(\n            AssertionInfo const& info\n    ) {\n        m_lastAssertionInfo = info;\n\n        AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );\n        data.message = \"Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE\";\n        AssertionResult assertionResult{ info, data };\n        assertionEnded( assertionResult );\n    }\n    void RunContext::handleNonExpr(\n            AssertionInfo const &info,\n            ResultWas::OfType resultType,\n            AssertionReaction &reaction\n    ) {\n        m_lastAssertionInfo = info;\n\n        AssertionResultData data( resultType, LazyExpression( false ) );\n        AssertionResult assertionResult{ info, data };\n        assertionEnded( assertionResult );\n\n        if( !assertionResult.isOk() )\n            populateReaction( reaction );\n    }\n\n    IResultCapture& getResultCapture() {\n        if (auto* capture = getCurrentContext().getResultCapture())\n            return *capture;\n        else\n            CATCH_INTERNAL_ERROR(\"No result capture instance\");\n    }\n}\n// end catch_run_context.cpp\n// start catch_section.cpp\n\nnamespace Catch {\n\n    Section::Section( SectionInfo const& info )\n    :   m_info( info ),\n        m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )\n    {\n        m_timer.start();\n    }\n\n    Section::~Section() {\n        if( m_sectionIncluded ) {\n            SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };\n            if( uncaught_exceptions() )\n                getResultCapture().sectionEndedEarly( endInfo );\n            else\n                getResultCapture().sectionEnded( endInfo );\n        }\n    }\n\n    // This indicates whether the section should be executed or not\n    Section::operator bool() const {\n        return m_sectionIncluded;\n    }\n\n} // end namespace Catch\n// end catch_section.cpp\n// start catch_section_info.cpp\n\nnamespace Catch {\n\n    SectionInfo::SectionInfo\n        (   SourceLineInfo const& _lineInfo,\n            std::string const& _name )\n    :   name( _name ),\n        lineInfo( _lineInfo )\n    {}\n\n} // end namespace Catch\n// end catch_section_info.cpp\n// start catch_session.cpp\n\n// start catch_session.h\n\n#include <memory>\n\nnamespace Catch {\n\n    class Session : NonCopyable {\n    public:\n\n        Session();\n        ~Session() override;\n\n        void showHelp() const;\n        void libIdentify();\n\n        int applyCommandLine( int argc, char const * const * argv );\n    #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)\n        int applyCommandLine( int argc, wchar_t const * const * argv );\n    #endif\n\n        void useConfigData( ConfigData const& configData );\n\n        template<typename CharT>\n        int run(int argc, CharT const * const argv[]) {\n            if (m_startupExceptions)\n                return 1;\n            int returnCode = applyCommandLine(argc, argv);\n            if (returnCode == 0)\n                returnCode = run();\n            return returnCode;\n        }\n\n        int run();\n\n        clara::Parser const& cli() const;\n        void cli( clara::Parser const& newParser );\n        ConfigData& configData();\n        Config& config();\n    private:\n        int runInternal();\n\n        clara::Parser m_cli;\n        ConfigData m_configData;\n        std::shared_ptr<Config> m_config;\n        bool m_startupExceptions = false;\n    };\n\n} // end namespace Catch\n\n// end catch_session.h\n// start catch_version.h\n\n#include <iosfwd>\n\nnamespace Catch {\n\n    // Versioning information\n    struct Version {\n        Version( Version const& ) = delete;\n        Version& operator=( Version const& ) = delete;\n        Version(    unsigned int _majorVersion,\n                    unsigned int _minorVersion,\n                    unsigned int _patchNumber,\n                    char const * const _branchName,\n                    unsigned int _buildNumber );\n\n        unsigned int const majorVersion;\n        unsigned int const minorVersion;\n        unsigned int const patchNumber;\n\n        // buildNumber is only used if branchName is not null\n        char const * const branchName;\n        unsigned int const buildNumber;\n\n        friend std::ostream& operator << ( std::ostream& os, Version const& version );\n    };\n\n    Version const& libraryVersion();\n}\n\n// end catch_version.h\n#include <cstdlib>\n#include <iomanip>\n\nnamespace Catch {\n\n    namespace {\n        const int MaxExitCode = 255;\n\n        IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) {\n            auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config);\n            CATCH_ENFORCE(reporter, \"No reporter registered with name: '\" << reporterName << \"'\");\n\n            return reporter;\n        }\n\n        IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {\n            if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {\n                return createReporter(config->getReporterName(), config);\n            }\n\n            // On older platforms, returning std::unique_ptr<ListeningReporter>\n            // when the return type is std::unique_ptr<IStreamingReporter>\n            // doesn't compile without a std::move call. However, this causes\n            // a warning on newer platforms. Thus, we have to work around\n            // it a bit and downcast the pointer manually.\n            auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter);\n            auto& multi = static_cast<ListeningReporter&>(*ret);\n            auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();\n            for (auto const& listener : listeners) {\n                multi.addListener(listener->create(Catch::ReporterConfig(config)));\n            }\n            multi.addReporter(createReporter(config->getReporterName(), config));\n            return ret;\n        }\n\n        Catch::Totals runTests(std::shared_ptr<Config> const& config) {\n            auto reporter = makeReporter(config);\n\n            RunContext context(config, std::move(reporter));\n\n            Totals totals;\n\n            context.testGroupStarting(config->name(), 1, 1);\n\n            TestSpec testSpec = config->testSpec();\n\n            auto const& allTestCases = getAllTestCasesSorted(*config);\n            for (auto const& testCase : allTestCases) {\n                if (!context.aborting() && matchTest(testCase, testSpec, *config))\n                    totals += context.runTest(testCase);\n                else\n                    context.reporter().skipTest(testCase);\n            }\n\n            if (config->warnAboutNoTests() && totals.testCases.total() == 0) {\n                ReusableStringStream testConfig;\n\n                bool first = true;\n                for (const auto& input : config->getTestsOrTags()) {\n                    if (!first) { testConfig << ' '; }\n                    first = false;\n                    testConfig << input;\n                }\n\n                context.reporter().noMatchingTestCases(testConfig.str());\n                totals.error = -1;\n            }\n\n            context.testGroupEnded(config->name(), totals, 1, 1);\n            return totals;\n        }\n\n        void applyFilenamesAsTags(Catch::IConfig const& config) {\n            auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));\n            for (auto& testCase : tests) {\n                auto tags = testCase.tags;\n\n                std::string filename = testCase.lineInfo.file;\n                auto lastSlash = filename.find_last_of(\"\\\\/\");\n                if (lastSlash != std::string::npos) {\n                    filename.erase(0, lastSlash);\n                    filename[0] = '#';\n                }\n\n                auto lastDot = filename.find_last_of('.');\n                if (lastDot != std::string::npos) {\n                    filename.erase(lastDot);\n                }\n\n                tags.push_back(std::move(filename));\n                setTags(testCase, tags);\n            }\n        }\n\n    } // anon namespace\n\n    Session::Session() {\n        static bool alreadyInstantiated = false;\n        if( alreadyInstantiated ) {\n            CATCH_TRY { CATCH_INTERNAL_ERROR( \"Only one instance of Catch::Session can ever be used\" ); }\n            CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); }\n        }\n\n        // There cannot be exceptions at startup in no-exception mode.\n#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)\n        const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();\n        if ( !exceptions.empty() ) {\n            m_startupExceptions = true;\n            Colour colourGuard( Colour::Red );\n            Catch::cerr() << \"Errors occurred during startup!\" << '\\n';\n            // iterate over all exceptions and notify user\n            for ( const auto& ex_ptr : exceptions ) {\n                try {\n                    std::rethrow_exception(ex_ptr);\n                } catch ( std::exception const& ex ) {\n                    Catch::cerr() << Column( ex.what() ).indent(2) << '\\n';\n                }\n            }\n        }\n#endif\n\n        alreadyInstantiated = true;\n        m_cli = makeCommandLineParser( m_configData );\n    }\n    Session::~Session() {\n        Catch::cleanUp();\n    }\n\n    void Session::showHelp() const {\n        Catch::cout()\n                << \"\\nCatch v\" << libraryVersion() << \"\\n\"\n                << m_cli << std::endl\n                << \"For more detailed usage please see the project docs\\n\" << std::endl;\n    }\n    void Session::libIdentify() {\n        Catch::cout()\n                << std::left << std::setw(16) << \"description: \" << \"A Catch test executable\\n\"\n                << std::left << std::setw(16) << \"category: \" << \"testframework\\n\"\n                << std::left << std::setw(16) << \"framework: \" << \"Catch Test\\n\"\n                << std::left << std::setw(16) << \"version: \" << libraryVersion() << std::endl;\n    }\n\n    int Session::applyCommandLine( int argc, char const * const * argv ) {\n        if( m_startupExceptions )\n            return 1;\n\n        auto result = m_cli.parse( clara::Args( argc, argv ) );\n        if( !result ) {\n            config();\n            getCurrentMutableContext().setConfig(m_config);\n            Catch::cerr()\n                << Colour( Colour::Red )\n                << \"\\nError(s) in input:\\n\"\n                << Column( result.errorMessage() ).indent( 2 )\n                << \"\\n\\n\";\n            Catch::cerr() << \"Run with -? for usage\\n\" << std::endl;\n            return MaxExitCode;\n        }\n\n        if( m_configData.showHelp )\n            showHelp();\n        if( m_configData.libIdentify )\n            libIdentify();\n        m_config.reset();\n        return 0;\n    }\n\n#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)\n    int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {\n\n        char **utf8Argv = new char *[ argc ];\n\n        for ( int i = 0; i < argc; ++i ) {\n            int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );\n\n            utf8Argv[ i ] = new char[ bufSize ];\n\n            WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );\n        }\n\n        int returnCode = applyCommandLine( argc, utf8Argv );\n\n        for ( int i = 0; i < argc; ++i )\n            delete [] utf8Argv[ i ];\n\n        delete [] utf8Argv;\n\n        return returnCode;\n    }\n#endif\n\n    void Session::useConfigData( ConfigData const& configData ) {\n        m_configData = configData;\n        m_config.reset();\n    }\n\n    int Session::run() {\n        if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {\n            Catch::cout() << \"...waiting for enter/ return before starting\" << std::endl;\n            static_cast<void>(std::getchar());\n        }\n        int exitCode = runInternal();\n        if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {\n            Catch::cout() << \"...waiting for enter/ return before exiting, with code: \" << exitCode << std::endl;\n            static_cast<void>(std::getchar());\n        }\n        return exitCode;\n    }\n\n    clara::Parser const& Session::cli() const {\n        return m_cli;\n    }\n    void Session::cli( clara::Parser const& newParser ) {\n        m_cli = newParser;\n    }\n    ConfigData& Session::configData() {\n        return m_configData;\n    }\n    Config& Session::config() {\n        if( !m_config )\n            m_config = std::make_shared<Config>( m_configData );\n        return *m_config;\n    }\n\n    int Session::runInternal() {\n        if( m_startupExceptions )\n            return 1;\n\n        if (m_configData.showHelp || m_configData.libIdentify) {\n            return 0;\n        }\n\n        CATCH_TRY {\n            config(); // Force config to be constructed\n\n            seedRng( *m_config );\n\n            if( m_configData.filenamesAsTags )\n                applyFilenamesAsTags( *m_config );\n\n            // Handle list request\n            if( Option<std::size_t> listed = list( m_config ) )\n                return static_cast<int>( *listed );\n\n            auto totals = runTests( m_config );\n            // Note that on unices only the lower 8 bits are usually used, clamping\n            // the return value to 255 prevents false negative when some multiple\n            // of 256 tests has failed\n            return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));\n        }\n#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)\n        catch( std::exception& ex ) {\n            Catch::cerr() << ex.what() << std::endl;\n            return MaxExitCode;\n        }\n#endif\n    }\n\n} // end namespace Catch\n// end catch_session.cpp\n// start catch_singletons.cpp\n\n#include <vector>\n\nnamespace Catch {\n\n    namespace {\n        static auto getSingletons() -> std::vector<ISingleton*>*& {\n            static std::vector<ISingleton*>* g_singletons = nullptr;\n            if( !g_singletons )\n                g_singletons = new std::vector<ISingleton*>();\n            return g_singletons;\n        }\n    }\n\n    ISingleton::~ISingleton() {}\n\n    void addSingleton(ISingleton* singleton ) {\n        getSingletons()->push_back( singleton );\n    }\n    void cleanupSingletons() {\n        auto& singletons = getSingletons();\n        for( auto singleton : *singletons )\n            delete singleton;\n        delete singletons;\n        singletons = nullptr;\n    }\n\n} // namespace Catch\n// end catch_singletons.cpp\n// start catch_startup_exception_registry.cpp\n\nnamespace Catch {\nvoid StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {\n        CATCH_TRY {\n            m_exceptions.push_back(exception);\n        } CATCH_CATCH_ALL {\n            // If we run out of memory during start-up there's really not a lot more we can do about it\n            std::terminate();\n        }\n    }\n\n    std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept {\n        return m_exceptions;\n    }\n\n} // end namespace Catch\n// end catch_startup_exception_registry.cpp\n// start catch_stream.cpp\n\n#include <cstdio>\n#include <iostream>\n#include <fstream>\n#include <sstream>\n#include <vector>\n#include <memory>\n\nnamespace Catch {\n\n    Catch::IStream::~IStream() = default;\n\n    namespace detail { namespace {\n        template<typename WriterF, std::size_t bufferSize=256>\n        class StreamBufImpl : public std::streambuf {\n            char data[bufferSize];\n            WriterF m_writer;\n\n        public:\n            StreamBufImpl() {\n                setp( data, data + sizeof(data) );\n            }\n\n            ~StreamBufImpl() noexcept {\n                StreamBufImpl::sync();\n            }\n\n        private:\n            int overflow( int c ) override {\n                sync();\n\n                if( c != EOF ) {\n                    if( pbase() == epptr() )\n                        m_writer( std::string( 1, static_cast<char>( c ) ) );\n                    else\n                        sputc( static_cast<char>( c ) );\n                }\n                return 0;\n            }\n\n            int sync() override {\n                if( pbase() != pptr() ) {\n                    m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );\n                    setp( pbase(), epptr() );\n                }\n                return 0;\n            }\n        };\n\n        ///////////////////////////////////////////////////////////////////////////\n\n        struct OutputDebugWriter {\n\n            void operator()( std::string const&str ) {\n                writeToDebugConsole( str );\n            }\n        };\n\n        ///////////////////////////////////////////////////////////////////////////\n\n        class FileStream : public IStream {\n            mutable std::ofstream m_ofs;\n        public:\n            FileStream( StringRef filename ) {\n                m_ofs.open( filename.c_str() );\n                CATCH_ENFORCE( !m_ofs.fail(), \"Unable to open file: '\" << filename << \"'\" );\n            }\n            ~FileStream() override = default;\n        public: // IStream\n            std::ostream& stream() const override {\n                return m_ofs;\n            }\n        };\n\n        ///////////////////////////////////////////////////////////////////////////\n\n        class CoutStream : public IStream {\n            mutable std::ostream m_os;\n        public:\n            // Store the streambuf from cout up-front because\n            // cout may get redirected when running tests\n            CoutStream() : m_os( Catch::cout().rdbuf() ) {}\n            ~CoutStream() override = default;\n\n        public: // IStream\n            std::ostream& stream() const override { return m_os; }\n        };\n\n        ///////////////////////////////////////////////////////////////////////////\n\n        class DebugOutStream : public IStream {\n            std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;\n            mutable std::ostream m_os;\n        public:\n            DebugOutStream()\n            :   m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),\n                m_os( m_streamBuf.get() )\n            {}\n\n            ~DebugOutStream() override = default;\n\n        public: // IStream\n            std::ostream& stream() const override { return m_os; }\n        };\n\n    }} // namespace anon::detail\n\n    ///////////////////////////////////////////////////////////////////////////\n\n    auto makeStream( StringRef const &filename ) -> IStream const* {\n        if( filename.empty() )\n            return new detail::CoutStream();\n        else if( filename[0] == '%' ) {\n            if( filename == \"%debug\" )\n                return new detail::DebugOutStream();\n            else\n                CATCH_ERROR( \"Unrecognised stream: '\" << filename << \"'\" );\n        }\n        else\n            return new detail::FileStream( filename );\n    }\n\n    // This class encapsulates the idea of a pool of ostringstreams that can be reused.\n    struct StringStreams {\n        std::vector<std::unique_ptr<std::ostringstream>> m_streams;\n        std::vector<std::size_t> m_unused;\n        std::ostringstream m_referenceStream; // Used for copy state/ flags from\n\n        auto add() -> std::size_t {\n            if( m_unused.empty() ) {\n                m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) );\n                return m_streams.size()-1;\n            }\n            else {\n                auto index = m_unused.back();\n                m_unused.pop_back();\n                return index;\n            }\n        }\n\n        void release( std::size_t index ) {\n            m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state\n            m_unused.push_back(index);\n        }\n    };\n\n    ReusableStringStream::ReusableStringStream()\n    :   m_index( Singleton<StringStreams>::getMutable().add() ),\n        m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )\n    {}\n\n    ReusableStringStream::~ReusableStringStream() {\n        static_cast<std::ostringstream*>( m_oss )->str(\"\");\n        m_oss->clear();\n        Singleton<StringStreams>::getMutable().release( m_index );\n    }\n\n    auto ReusableStringStream::str() const -> std::string {\n        return static_cast<std::ostringstream*>( m_oss )->str();\n    }\n\n    ///////////////////////////////////////////////////////////////////////////\n\n#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions\n    std::ostream& cout() { return std::cout; }\n    std::ostream& cerr() { return std::cerr; }\n    std::ostream& clog() { return std::clog; }\n#endif\n}\n// end catch_stream.cpp\n// start catch_string_manip.cpp\n\n#include <algorithm>\n#include <ostream>\n#include <cstring>\n#include <cctype>\n\nnamespace Catch {\n\n    namespace {\n        char toLowerCh(char c) {\n            return static_cast<char>( std::tolower( c ) );\n        }\n    }\n\n    bool startsWith( std::string const& s, std::string const& prefix ) {\n        return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());\n    }\n    bool startsWith( std::string const& s, char prefix ) {\n        return !s.empty() && s[0] == prefix;\n    }\n    bool endsWith( std::string const& s, std::string const& suffix ) {\n        return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());\n    }\n    bool endsWith( std::string const& s, char suffix ) {\n        return !s.empty() && s[s.size()-1] == suffix;\n    }\n    bool contains( std::string const& s, std::string const& infix ) {\n        return s.find( infix ) != std::string::npos;\n    }\n    void toLowerInPlace( std::string& s ) {\n        std::transform( s.begin(), s.end(), s.begin(), toLowerCh );\n    }\n    std::string toLower( std::string const& s ) {\n        std::string lc = s;\n        toLowerInPlace( lc );\n        return lc;\n    }\n    std::string trim( std::string const& str ) {\n        static char const* whitespaceChars = \"\\n\\r\\t \";\n        std::string::size_type start = str.find_first_not_of( whitespaceChars );\n        std::string::size_type end = str.find_last_not_of( whitespaceChars );\n\n        return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();\n    }\n\n    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {\n        bool replaced = false;\n        std::size_t i = str.find( replaceThis );\n        while( i != std::string::npos ) {\n            replaced = true;\n            str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );\n            if( i < str.size()-withThis.size() )\n                i = str.find( replaceThis, i+withThis.size() );\n            else\n                i = std::string::npos;\n        }\n        return replaced;\n    }\n\n    pluralise::pluralise( std::size_t count, std::string const& label )\n    :   m_count( count ),\n        m_label( label )\n    {}\n\n    std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {\n        os << pluraliser.m_count << ' ' << pluraliser.m_label;\n        if( pluraliser.m_count != 1 )\n            os << 's';\n        return os;\n    }\n\n}\n// end catch_string_manip.cpp\n// start catch_stringref.cpp\n\n#if defined(__clang__)\n#    pragma clang diagnostic push\n#    pragma clang diagnostic ignored \"-Wexit-time-destructors\"\n#endif\n\n#include <ostream>\n#include <cstring>\n#include <cstdint>\n\nnamespace {\n    const uint32_t byte_2_lead = 0xC0;\n    const uint32_t byte_3_lead = 0xE0;\n    const uint32_t byte_4_lead = 0xF0;\n}\n\nnamespace Catch {\n    StringRef::StringRef( char const* rawChars ) noexcept\n    : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )\n    {}\n\n    StringRef::operator std::string() const {\n        return std::string( m_start, m_size );\n    }\n\n    void StringRef::swap( StringRef& other ) noexcept {\n        std::swap( m_start, other.m_start );\n        std::swap( m_size, other.m_size );\n        std::swap( m_data, other.m_data );\n    }\n\n    auto StringRef::c_str() const -> char const* {\n        if( isSubstring() )\n           const_cast<StringRef*>( this )->takeOwnership();\n        return m_start;\n    }\n    auto StringRef::currentData() const noexcept -> char const* {\n        return m_start;\n    }\n\n    auto StringRef::isOwned() const noexcept -> bool {\n        return m_data != nullptr;\n    }\n    auto StringRef::isSubstring() const noexcept -> bool {\n        return m_start[m_size] != '\\0';\n    }\n\n    void StringRef::takeOwnership() {\n        if( !isOwned() ) {\n            m_data = new char[m_size+1];\n            memcpy( m_data, m_start, m_size );\n            m_data[m_size] = '\\0';\n            m_start = m_data;\n        }\n    }\n    auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef {\n        if( start < m_size )\n            return StringRef( m_start+start, size );\n        else\n            return StringRef();\n    }\n    auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool {\n        return\n            size() == other.size() &&\n            (std::strncmp( m_start, other.m_start, size() ) == 0);\n    }\n    auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool {\n        return !operator==( other );\n    }\n\n    auto StringRef::operator[](size_type index) const noexcept -> char {\n        return m_start[index];\n    }\n\n    auto StringRef::numberOfCharacters() const noexcept -> size_type {\n        size_type noChars = m_size;\n        // Make adjustments for uft encodings\n        for( size_type i=0; i < m_size; ++i ) {\n            char c = m_start[i];\n            if( ( c & byte_2_lead ) == byte_2_lead ) {\n                noChars--;\n                if (( c & byte_3_lead ) == byte_3_lead )\n                    noChars--;\n                if( ( c & byte_4_lead ) == byte_4_lead )\n                    noChars--;\n            }\n        }\n        return noChars;\n    }\n\n    auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string {\n        std::string str;\n        str.reserve( lhs.size() + rhs.size() );\n        str += lhs;\n        str += rhs;\n        return str;\n    }\n    auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string {\n        return std::string( lhs ) + std::string( rhs );\n    }\n    auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string {\n        return std::string( lhs ) + std::string( rhs );\n    }\n\n    auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {\n        return os.write(str.currentData(), str.size());\n    }\n\n    auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {\n        lhs.append(rhs.currentData(), rhs.size());\n        return lhs;\n    }\n\n} // namespace Catch\n\n#if defined(__clang__)\n#    pragma clang diagnostic pop\n#endif\n// end catch_stringref.cpp\n// start catch_tag_alias.cpp\n\nnamespace Catch {\n    TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}\n}\n// end catch_tag_alias.cpp\n// start catch_tag_alias_autoregistrar.cpp\n\nnamespace Catch {\n\n    RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {\n        CATCH_TRY {\n            getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);\n        } CATCH_CATCH_ALL {\n            // Do not throw when constructing global objects, instead register the exception to be processed later\n            getMutableRegistryHub().registerStartupException();\n        }\n    }\n\n}\n// end catch_tag_alias_autoregistrar.cpp\n// start catch_tag_alias_registry.cpp\n\n#include <sstream>\n\nnamespace Catch {\n\n    TagAliasRegistry::~TagAliasRegistry() {}\n\n    TagAlias const* TagAliasRegistry::find( std::string const& alias ) const {\n        auto it = m_registry.find( alias );\n        if( it != m_registry.end() )\n            return &(it->second);\n        else\n            return nullptr;\n    }\n\n    std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {\n        std::string expandedTestSpec = unexpandedTestSpec;\n        for( auto const& registryKvp : m_registry ) {\n            std::size_t pos = expandedTestSpec.find( registryKvp.first );\n            if( pos != std::string::npos ) {\n                expandedTestSpec =  expandedTestSpec.substr( 0, pos ) +\n                                    registryKvp.second.tag +\n                                    expandedTestSpec.substr( pos + registryKvp.first.size() );\n            }\n        }\n        return expandedTestSpec;\n    }\n\n    void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {\n        CATCH_ENFORCE( startsWith(alias, \"[@\") && endsWith(alias, ']'),\n                      \"error: tag alias, '\" << alias << \"' is not of the form [@alias name].\\n\" << lineInfo );\n\n        CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,\n                      \"error: tag alias, '\" << alias << \"' already registered.\\n\"\n                      << \"\\tFirst seen at: \" << find(alias)->lineInfo << \"\\n\"\n                      << \"\\tRedefined at: \" << lineInfo );\n    }\n\n    ITagAliasRegistry::~ITagAliasRegistry() {}\n\n    ITagAliasRegistry const& ITagAliasRegistry::get() {\n        return getRegistryHub().getTagAliasRegistry();\n    }\n\n} // end namespace Catch\n// end catch_tag_alias_registry.cpp\n// start catch_test_case_info.cpp\n\n#include <cctype>\n#include <exception>\n#include <algorithm>\n#include <sstream>\n\nnamespace Catch {\n\n    namespace {\n        TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {\n            if( startsWith( tag, '.' ) ||\n                tag == \"!hide\" )\n                return TestCaseInfo::IsHidden;\n            else if( tag == \"!throws\" )\n                return TestCaseInfo::Throws;\n            else if( tag == \"!shouldfail\" )\n                return TestCaseInfo::ShouldFail;\n            else if( tag == \"!mayfail\" )\n                return TestCaseInfo::MayFail;\n            else if( tag == \"!nonportable\" )\n                return TestCaseInfo::NonPortable;\n            else if( tag == \"!benchmark\" )\n                return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );\n            else\n                return TestCaseInfo::None;\n        }\n        bool isReservedTag( std::string const& tag ) {\n            return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );\n        }\n        void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {\n            CATCH_ENFORCE( !isReservedTag(tag),\n                          \"Tag name: [\" << tag << \"] is not allowed.\\n\"\n                          << \"Tag names starting with non alpha-numeric characters are reserved\\n\"\n                          << _lineInfo );\n        }\n    }\n\n    TestCase makeTestCase(  ITestInvoker* _testCase,\n                            std::string const& _className,\n                            NameAndTags const& nameAndTags,\n                            SourceLineInfo const& _lineInfo )\n    {\n        bool isHidden = false;\n\n        // Parse out tags\n        std::vector<std::string> tags;\n        std::string desc, tag;\n        bool inTag = false;\n        std::string _descOrTags = nameAndTags.tags;\n        for (char c : _descOrTags) {\n            if( !inTag ) {\n                if( c == '[' )\n                    inTag = true;\n                else\n                    desc += c;\n            }\n            else {\n                if( c == ']' ) {\n                    TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );\n                    if( ( prop & TestCaseInfo::IsHidden ) != 0 )\n                        isHidden = true;\n                    else if( prop == TestCaseInfo::None )\n                        enforceNotReservedTag( tag, _lineInfo );\n\n                    tags.push_back( tag );\n                    tag.clear();\n                    inTag = false;\n                }\n                else\n                    tag += c;\n            }\n        }\n        if( isHidden ) {\n            tags.push_back( \".\" );\n        }\n\n        TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );\n        return TestCase( _testCase, std::move(info) );\n    }\n\n    void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {\n        std::sort(begin(tags), end(tags));\n        tags.erase(std::unique(begin(tags), end(tags)), end(tags));\n        testCaseInfo.lcaseTags.clear();\n\n        for( auto const& tag : tags ) {\n            std::string lcaseTag = toLower( tag );\n            testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );\n            testCaseInfo.lcaseTags.push_back( lcaseTag );\n        }\n        testCaseInfo.tags = std::move(tags);\n    }\n\n    TestCaseInfo::TestCaseInfo( std::string const& _name,\n                                std::string const& _className,\n                                std::string const& _description,\n                                std::vector<std::string> const& _tags,\n                                SourceLineInfo const& _lineInfo )\n    :   name( _name ),\n        className( _className ),\n        description( _description ),\n        lineInfo( _lineInfo ),\n        properties( None )\n    {\n        setTags( *this, _tags );\n    }\n\n    bool TestCaseInfo::isHidden() const {\n        return ( properties & IsHidden ) != 0;\n    }\n    bool TestCaseInfo::throws() const {\n        return ( properties & Throws ) != 0;\n    }\n    bool TestCaseInfo::okToFail() const {\n        return ( properties & (ShouldFail | MayFail ) ) != 0;\n    }\n    bool TestCaseInfo::expectedToFail() const {\n        return ( properties & (ShouldFail ) ) != 0;\n    }\n\n    std::string TestCaseInfo::tagsAsString() const {\n        std::string ret;\n        // '[' and ']' per tag\n        std::size_t full_size = 2 * tags.size();\n        for (const auto& tag : tags) {\n            full_size += tag.size();\n        }\n        ret.reserve(full_size);\n        for (const auto& tag : tags) {\n            ret.push_back('[');\n            ret.append(tag);\n            ret.push_back(']');\n        }\n\n        return ret;\n    }\n\n    TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {}\n\n    TestCase TestCase::withName( std::string const& _newName ) const {\n        TestCase other( *this );\n        other.name = _newName;\n        return other;\n    }\n\n    void TestCase::invoke() const {\n        test->invoke();\n    }\n\n    bool TestCase::operator == ( TestCase const& other ) const {\n        return  test.get() == other.test.get() &&\n                name == other.name &&\n                className == other.className;\n    }\n\n    bool TestCase::operator < ( TestCase const& other ) const {\n        return name < other.name;\n    }\n\n    TestCaseInfo const& TestCase::getTestCaseInfo() const\n    {\n        return *this;\n    }\n\n} // end namespace Catch\n// end catch_test_case_info.cpp\n// start catch_test_case_registry_impl.cpp\n\n#include <sstream>\n\nnamespace Catch {\n\n    std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {\n\n        std::vector<TestCase> sorted = unsortedTestCases;\n\n        switch( config.runOrder() ) {\n            case RunTests::InLexicographicalOrder:\n                std::sort( sorted.begin(), sorted.end() );\n                break;\n            case RunTests::InRandomOrder:\n                seedRng( config );\n                std::shuffle( sorted.begin(), sorted.end(), rng() );\n                break;\n            case RunTests::InDeclarationOrder:\n                // already in declaration order\n                break;\n        }\n        return sorted;\n    }\n    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {\n        return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );\n    }\n\n    void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {\n        std::set<TestCase> seenFunctions;\n        for( auto const& function : functions ) {\n            auto prev = seenFunctions.insert( function );\n            CATCH_ENFORCE( prev.second,\n                    \"error: TEST_CASE( \\\"\" << function.name << \"\\\" ) already defined.\\n\"\n                    << \"\\tFirst seen at \" << prev.first->getTestCaseInfo().lineInfo << \"\\n\"\n                    << \"\\tRedefined at \" << function.getTestCaseInfo().lineInfo );\n        }\n    }\n\n    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {\n        std::vector<TestCase> filtered;\n        filtered.reserve( testCases.size() );\n        for( auto const& testCase : testCases )\n            if( matchTest( testCase, testSpec, config ) )\n                filtered.push_back( testCase );\n        return filtered;\n    }\n    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {\n        return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );\n    }\n\n    void TestRegistry::registerTest( TestCase const& testCase ) {\n        std::string name = testCase.getTestCaseInfo().name;\n        if( name.empty() ) {\n            ReusableStringStream rss;\n            rss << \"Anonymous test case \" << ++m_unnamedCount;\n            return registerTest( testCase.withName( rss.str() ) );\n        }\n        m_functions.push_back( testCase );\n    }\n\n    std::vector<TestCase> const& TestRegistry::getAllTests() const {\n        return m_functions;\n    }\n    std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {\n        if( m_sortedFunctions.empty() )\n            enforceNoDuplicateTestCases( m_functions );\n\n        if(  m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {\n            m_sortedFunctions = sortTests( config, m_functions );\n            m_currentSortOrder = config.runOrder();\n        }\n        return m_sortedFunctions;\n    }\n\n    ///////////////////////////////////////////////////////////////////////////\n    TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}\n\n    void TestInvokerAsFunction::invoke() const {\n        m_testAsFunction();\n    }\n\n    std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {\n        std::string className = classOrQualifiedMethodName;\n        if( startsWith( className, '&' ) )\n        {\n            std::size_t lastColons = className.rfind( \"::\" );\n            std::size_t penultimateColons = className.rfind( \"::\", lastColons-1 );\n            if( penultimateColons == std::string::npos )\n                penultimateColons = 1;\n            className = className.substr( penultimateColons, lastColons-penultimateColons );\n        }\n        return className;\n    }\n\n} // end namespace Catch\n// end catch_test_case_registry_impl.cpp\n// start catch_test_case_tracker.cpp\n\n#include <algorithm>\n#include <cassert>\n#include <stdexcept>\n#include <memory>\n#include <sstream>\n\n#if defined(__clang__)\n#    pragma clang diagnostic push\n#    pragma clang diagnostic ignored \"-Wexit-time-destructors\"\n#endif\n\nnamespace Catch {\nnamespace TestCaseTracking {\n\n    NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location )\n    :   name( _name ),\n        location( _location )\n    {}\n\n    ITracker::~ITracker() = default;\n\n    TrackerContext& TrackerContext::instance() {\n        static TrackerContext s_instance;\n        return s_instance;\n    }\n\n    ITracker& TrackerContext::startRun() {\n        m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( \"{root}\", CATCH_INTERNAL_LINEINFO ), *this, nullptr );\n        m_currentTracker = nullptr;\n        m_runState = Executing;\n        return *m_rootTracker;\n    }\n\n    void TrackerContext::endRun() {\n        m_rootTracker.reset();\n        m_currentTracker = nullptr;\n        m_runState = NotStarted;\n    }\n\n    void TrackerContext::startCycle() {\n        m_currentTracker = m_rootTracker.get();\n        m_runState = Executing;\n    }\n    void TrackerContext::completeCycle() {\n        m_runState = CompletedCycle;\n    }\n\n    bool TrackerContext::completedCycle() const {\n        return m_runState == CompletedCycle;\n    }\n    ITracker& TrackerContext::currentTracker() {\n        return *m_currentTracker;\n    }\n    void TrackerContext::setCurrentTracker( ITracker* tracker ) {\n        m_currentTracker = tracker;\n    }\n\n    TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )\n    :   m_nameAndLocation( nameAndLocation ),\n        m_ctx( ctx ),\n        m_parent( parent )\n    {}\n\n    NameAndLocation const& TrackerBase::nameAndLocation() const {\n        return m_nameAndLocation;\n    }\n    bool TrackerBase::isComplete() const {\n        return m_runState == CompletedSuccessfully || m_runState == Failed;\n    }\n    bool TrackerBase::isSuccessfullyCompleted() const {\n        return m_runState == CompletedSuccessfully;\n    }\n    bool TrackerBase::isOpen() const {\n        return m_runState != NotStarted && !isComplete();\n    }\n    bool TrackerBase::hasChildren() const {\n        return !m_children.empty();\n    }\n\n    void TrackerBase::addChild( ITrackerPtr const& child ) {\n        m_children.push_back( child );\n    }\n\n    ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) {\n        auto it = std::find_if( m_children.begin(), m_children.end(),\n            [&nameAndLocation]( ITrackerPtr const& tracker ){\n                return\n                    tracker->nameAndLocation().location == nameAndLocation.location &&\n                    tracker->nameAndLocation().name == nameAndLocation.name;\n            } );\n        return( it != m_children.end() )\n            ? *it\n            : nullptr;\n    }\n    ITracker& TrackerBase::parent() {\n        assert( m_parent ); // Should always be non-null except for root\n        return *m_parent;\n    }\n\n    void TrackerBase::openChild() {\n        if( m_runState != ExecutingChildren ) {\n            m_runState = ExecutingChildren;\n            if( m_parent )\n                m_parent->openChild();\n        }\n    }\n\n    bool TrackerBase::isSectionTracker() const { return false; }\n    bool TrackerBase::isGeneratorTracker() const { return false; }\n\n    void TrackerBase::open() {\n        m_runState = Executing;\n        moveToThis();\n        if( m_parent )\n            m_parent->openChild();\n    }\n\n    void TrackerBase::close() {\n\n        // Close any still open children (e.g. generators)\n        while( &m_ctx.currentTracker() != this )\n            m_ctx.currentTracker().close();\n\n        switch( m_runState ) {\n            case NeedsAnotherRun:\n                break;\n\n            case Executing:\n                m_runState = CompletedSuccessfully;\n                break;\n            case ExecutingChildren:\n                if( m_children.empty() || m_children.back()->isComplete() )\n                    m_runState = CompletedSuccessfully;\n                break;\n\n            case NotStarted:\n            case CompletedSuccessfully:\n            case Failed:\n                CATCH_INTERNAL_ERROR( \"Illogical state: \" << m_runState );\n\n            default:\n                CATCH_INTERNAL_ERROR( \"Unknown state: \" << m_runState );\n        }\n        moveToParent();\n        m_ctx.completeCycle();\n    }\n    void TrackerBase::fail() {\n        m_runState = Failed;\n        if( m_parent )\n            m_parent->markAsNeedingAnotherRun();\n        moveToParent();\n        m_ctx.completeCycle();\n    }\n    void TrackerBase::markAsNeedingAnotherRun() {\n        m_runState = NeedsAnotherRun;\n    }\n\n    void TrackerBase::moveToParent() {\n        assert( m_parent );\n        m_ctx.setCurrentTracker( m_parent );\n    }\n    void TrackerBase::moveToThis() {\n        m_ctx.setCurrentTracker( this );\n    }\n\n    SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )\n    :   TrackerBase( nameAndLocation, ctx, parent )\n    {\n        if( parent ) {\n            while( !parent->isSectionTracker() )\n                parent = &parent->parent();\n\n            SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );\n            addNextFilters( parentSection.m_filters );\n        }\n    }\n\n    bool SectionTracker::isComplete() const {\n        bool complete = true;\n\n        if ((m_filters.empty() || m_filters[0] == \"\") ||\n             std::find(m_filters.begin(), m_filters.end(),\n                       m_nameAndLocation.name) != m_filters.end())\n            complete = TrackerBase::isComplete();\n        return complete;\n\n    }\n\n    bool SectionTracker::isSectionTracker() const { return true; }\n\n    SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {\n        std::shared_ptr<SectionTracker> section;\n\n        ITracker& currentTracker = ctx.currentTracker();\n        if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {\n            assert( childTracker );\n            assert( childTracker->isSectionTracker() );\n            section = std::static_pointer_cast<SectionTracker>( childTracker );\n        }\n        else {\n            section = std::make_shared<SectionTracker>( nameAndLocation, ctx, &currentTracker );\n            currentTracker.addChild( section );\n        }\n        if( !ctx.completedCycle() )\n            section->tryOpen();\n        return *section;\n    }\n\n    void SectionTracker::tryOpen() {\n        if( !isComplete() && (m_filters.empty() || m_filters[0].empty() ||  m_filters[0] == m_nameAndLocation.name ) )\n            open();\n    }\n\n    void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {\n        if( !filters.empty() ) {\n            m_filters.push_back(\"\"); // Root - should never be consulted\n            m_filters.push_back(\"\"); // Test Case - not a section filter\n            m_filters.insert( m_filters.end(), filters.begin(), filters.end() );\n        }\n    }\n    void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) {\n        if( filters.size() > 1 )\n            m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );\n    }\n\n} // namespace TestCaseTracking\n\nusing TestCaseTracking::ITracker;\nusing TestCaseTracking::TrackerContext;\nusing TestCaseTracking::SectionTracker;\n\n} // namespace Catch\n\n#if defined(__clang__)\n#    pragma clang diagnostic pop\n#endif\n// end catch_test_case_tracker.cpp\n// start catch_test_registry.cpp\n\nnamespace Catch {\n\n    auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* {\n        return new(std::nothrow) TestInvokerAsFunction( testAsFunction );\n    }\n\n    NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {}\n\n    AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {\n        CATCH_TRY {\n            getMutableRegistryHub()\n                    .registerTest(\n                        makeTestCase(\n                            invoker,\n                            extractClassName( classOrMethod ),\n                            nameAndTags,\n                            lineInfo));\n        } CATCH_CATCH_ALL {\n            // Do not throw when constructing global objects, instead register the exception to be processed later\n            getMutableRegistryHub().registerStartupException();\n        }\n    }\n\n    AutoReg::~AutoReg() = default;\n}\n// end catch_test_registry.cpp\n// start catch_test_spec.cpp\n\n#include <algorithm>\n#include <string>\n#include <vector>\n#include <memory>\n\nnamespace Catch {\n\n    TestSpec::Pattern::~Pattern() = default;\n    TestSpec::NamePattern::~NamePattern() = default;\n    TestSpec::TagPattern::~TagPattern() = default;\n    TestSpec::ExcludedPattern::~ExcludedPattern() = default;\n\n    TestSpec::NamePattern::NamePattern( std::string const& name )\n    : m_wildcardPattern( toLower( name ), CaseSensitive::No )\n    {}\n    bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {\n        return m_wildcardPattern.matches( toLower( testCase.name ) );\n    }\n\n    TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}\n    bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {\n        return std::find(begin(testCase.lcaseTags),\n                         end(testCase.lcaseTags),\n                         m_tag) != end(testCase.lcaseTags);\n    }\n\n    TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}\n    bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }\n\n    bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {\n        // All patterns in a filter must match for the filter to be a match\n        for( auto const& pattern : m_patterns ) {\n            if( !pattern->matches( testCase ) )\n                return false;\n        }\n        return true;\n    }\n\n    bool TestSpec::hasFilters() const {\n        return !m_filters.empty();\n    }\n    bool TestSpec::matches( TestCaseInfo const& testCase ) const {\n        // A TestSpec matches if any filter matches\n        for( auto const& filter : m_filters )\n            if( filter.matches( testCase ) )\n                return true;\n        return false;\n    }\n}\n// end catch_test_spec.cpp\n// start catch_test_spec_parser.cpp\n\nnamespace Catch {\n\n    TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}\n\n    TestSpecParser& TestSpecParser::parse( std::string const& arg ) {\n        m_mode = None;\n        m_exclusion = false;\n        m_start = std::string::npos;\n        m_arg = m_tagAliases->expandAliases( arg );\n        m_escapeChars.clear();\n        for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )\n            visitChar( m_arg[m_pos] );\n        if( m_mode == Name )\n            addPattern<TestSpec::NamePattern>();\n        return *this;\n    }\n    TestSpec TestSpecParser::testSpec() {\n        addFilter();\n        return m_testSpec;\n    }\n\n    void TestSpecParser::visitChar( char c ) {\n        if( m_mode == None ) {\n            switch( c ) {\n            case ' ': return;\n            case '~': m_exclusion = true; return;\n            case '[': return startNewMode( Tag, ++m_pos );\n            case '\"': return startNewMode( QuotedName, ++m_pos );\n            case '\\\\': return escape();\n            default: startNewMode( Name, m_pos ); break;\n            }\n        }\n        if( m_mode == Name ) {\n            if( c == ',' ) {\n                addPattern<TestSpec::NamePattern>();\n                addFilter();\n            }\n            else if( c == '[' ) {\n                if( subString() == \"exclude:\" )\n                    m_exclusion = true;\n                else\n                    addPattern<TestSpec::NamePattern>();\n                startNewMode( Tag, ++m_pos );\n            }\n            else if( c == '\\\\' )\n                escape();\n        }\n        else if( m_mode == EscapedName )\n            m_mode = Name;\n        else if( m_mode == QuotedName && c == '\"' )\n            addPattern<TestSpec::NamePattern>();\n        else if( m_mode == Tag && c == ']' )\n            addPattern<TestSpec::TagPattern>();\n    }\n    void TestSpecParser::startNewMode( Mode mode, std::size_t start ) {\n        m_mode = mode;\n        m_start = start;\n    }\n    void TestSpecParser::escape() {\n        if( m_mode == None )\n            m_start = m_pos;\n        m_mode = EscapedName;\n        m_escapeChars.push_back( m_pos );\n    }\n    std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); }\n\n    void TestSpecParser::addFilter() {\n        if( !m_currentFilter.m_patterns.empty() ) {\n            m_testSpec.m_filters.push_back( m_currentFilter );\n            m_currentFilter = TestSpec::Filter();\n        }\n    }\n\n    TestSpec parseTestSpec( std::string const& arg ) {\n        return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();\n    }\n\n} // namespace Catch\n// end catch_test_spec_parser.cpp\n// start catch_timer.cpp\n\n#include <chrono>\n\nstatic const uint64_t nanosecondsInSecond = 1000000000;\n\nnamespace Catch {\n\n    auto getCurrentNanosecondsSinceEpoch() -> uint64_t {\n        return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();\n    }\n\n    namespace {\n        auto estimateClockResolution() -> uint64_t {\n            uint64_t sum = 0;\n            static const uint64_t iterations = 1000000;\n\n            auto startTime = getCurrentNanosecondsSinceEpoch();\n\n            for( std::size_t i = 0; i < iterations; ++i ) {\n\n                uint64_t ticks;\n                uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();\n                do {\n                    ticks = getCurrentNanosecondsSinceEpoch();\n                } while( ticks == baseTicks );\n\n                auto delta = ticks - baseTicks;\n                sum += delta;\n\n                // If we have been calibrating for over 3 seconds -- the clock\n                // is terrible and we should move on.\n                // TBD: How to signal that the measured resolution is probably wrong?\n                if (ticks > startTime + 3 * nanosecondsInSecond) {\n                    return sum / ( i + 1u );\n                }\n            }\n\n            // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers\n            // - and potentially do more iterations if there's a high variance.\n            return sum/iterations;\n        }\n    }\n    auto getEstimatedClockResolution() -> uint64_t {\n        static auto s_resolution = estimateClockResolution();\n        return s_resolution;\n    }\n\n    void Timer::start() {\n       m_nanoseconds = getCurrentNanosecondsSinceEpoch();\n    }\n    auto Timer::getElapsedNanoseconds() const -> uint64_t {\n        return getCurrentNanosecondsSinceEpoch() - m_nanoseconds;\n    }\n    auto Timer::getElapsedMicroseconds() const -> uint64_t {\n        return getElapsedNanoseconds()/1000;\n    }\n    auto Timer::getElapsedMilliseconds() const -> unsigned int {\n        return static_cast<unsigned int>(getElapsedMicroseconds()/1000);\n    }\n    auto Timer::getElapsedSeconds() const -> double {\n        return getElapsedMicroseconds()/1000000.0;\n    }\n\n} // namespace Catch\n// end catch_timer.cpp\n// start catch_tostring.cpp\n\n#if defined(__clang__)\n#    pragma clang diagnostic push\n#    pragma clang diagnostic ignored \"-Wexit-time-destructors\"\n#    pragma clang diagnostic ignored \"-Wglobal-constructors\"\n#endif\n\n// Enable specific decls locally\n#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)\n#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER\n#endif\n\n#include <cmath>\n#include <iomanip>\n\nnamespace Catch {\n\nnamespace Detail {\n\n    const std::string unprintableString = \"{?}\";\n\n    namespace {\n        const int hexThreshold = 255;\n\n        struct Endianness {\n            enum Arch { Big, Little };\n\n            static Arch which() {\n                union _{\n                    int asInt;\n                    char asChar[sizeof (int)];\n                } u;\n\n                u.asInt = 1;\n                return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;\n            }\n        };\n    }\n\n    std::string rawMemoryToString( const void *object, std::size_t size ) {\n        // Reverse order for little endian architectures\n        int i = 0, end = static_cast<int>( size ), inc = 1;\n        if( Endianness::which() == Endianness::Little ) {\n            i = end-1;\n            end = inc = -1;\n        }\n\n        unsigned char const *bytes = static_cast<unsigned char const *>(object);\n        ReusableStringStream rss;\n        rss << \"0x\" << std::setfill('0') << std::hex;\n        for( ; i != end; i += inc )\n             rss << std::setw(2) << static_cast<unsigned>(bytes[i]);\n       return rss.str();\n    }\n}\n\ntemplate<typename T>\nstd::string fpToString( T value, int precision ) {\n    if (Catch::isnan(value)) {\n        return \"nan\";\n    }\n\n    ReusableStringStream rss;\n    rss << std::setprecision( precision )\n        << std::fixed\n        << value;\n    std::string d = rss.str();\n    std::size_t i = d.find_last_not_of( '0' );\n    if( i != std::string::npos && i != d.size()-1 ) {\n        if( d[i] == '.' )\n            i++;\n        d = d.substr( 0, i+1 );\n    }\n    return d;\n}\n\n//// ======================================================= ////\n//\n//   Out-of-line defs for full specialization of StringMaker\n//\n//// ======================================================= ////\n\nstd::string StringMaker<std::string>::convert(const std::string& str) {\n    if (!getCurrentContext().getConfig()->showInvisibles()) {\n        return '\"' + str + '\"';\n    }\n\n    std::string s(\"\\\"\");\n    for (char c : str) {\n        switch (c) {\n        case '\\n':\n            s.append(\"\\\\n\");\n            break;\n        case '\\t':\n            s.append(\"\\\\t\");\n            break;\n        default:\n            s.push_back(c);\n            break;\n        }\n    }\n    s.append(\"\\\"\");\n    return s;\n}\n\n#ifdef CATCH_CONFIG_CPP17_STRING_VIEW\nstd::string StringMaker<std::string_view>::convert(std::string_view str) {\n    return ::Catch::Detail::stringify(std::string{ str });\n}\n#endif\n\nstd::string StringMaker<char const*>::convert(char const* str) {\n    if (str) {\n        return ::Catch::Detail::stringify(std::string{ str });\n    } else {\n        return{ \"{null string}\" };\n    }\n}\nstd::string StringMaker<char*>::convert(char* str) {\n    if (str) {\n        return ::Catch::Detail::stringify(std::string{ str });\n    } else {\n        return{ \"{null string}\" };\n    }\n}\n\n#ifdef CATCH_CONFIG_WCHAR\nstd::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {\n    std::string s;\n    s.reserve(wstr.size());\n    for (auto c : wstr) {\n        s += (c <= 0xff) ? static_cast<char>(c) : '?';\n    }\n    return ::Catch::Detail::stringify(s);\n}\n\n# ifdef CATCH_CONFIG_CPP17_STRING_VIEW\nstd::string StringMaker<std::wstring_view>::convert(std::wstring_view str) {\n    return StringMaker<std::wstring>::convert(std::wstring(str));\n}\n# endif\n\nstd::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {\n    if (str) {\n        return ::Catch::Detail::stringify(std::wstring{ str });\n    } else {\n        return{ \"{null string}\" };\n    }\n}\nstd::string StringMaker<wchar_t *>::convert(wchar_t * str) {\n    if (str) {\n        return ::Catch::Detail::stringify(std::wstring{ str });\n    } else {\n        return{ \"{null string}\" };\n    }\n}\n#endif\n\nstd::string StringMaker<int>::convert(int value) {\n    return ::Catch::Detail::stringify(static_cast<long long>(value));\n}\nstd::string StringMaker<long>::convert(long value) {\n    return ::Catch::Detail::stringify(static_cast<long long>(value));\n}\nstd::string StringMaker<long long>::convert(long long value) {\n    ReusableStringStream rss;\n    rss << value;\n    if (value > Detail::hexThreshold) {\n        rss << \" (0x\" << std::hex << value << ')';\n    }\n    return rss.str();\n}\n\nstd::string StringMaker<unsigned int>::convert(unsigned int value) {\n    return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));\n}\nstd::string StringMaker<unsigned long>::convert(unsigned long value) {\n    return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));\n}\nstd::string StringMaker<unsigned long long>::convert(unsigned long long value) {\n    ReusableStringStream rss;\n    rss << value;\n    if (value > Detail::hexThreshold) {\n        rss << \" (0x\" << std::hex << value << ')';\n    }\n    return rss.str();\n}\n\nstd::string StringMaker<bool>::convert(bool b) {\n    return b ? \"true\" : \"false\";\n}\n\nstd::string StringMaker<signed char>::convert(signed char value) {\n    if (value == '\\r') {\n        return \"'\\\\r'\";\n    } else if (value == '\\f') {\n        return \"'\\\\f'\";\n    } else if (value == '\\n') {\n        return \"'\\\\n'\";\n    } else if (value == '\\t') {\n        return \"'\\\\t'\";\n    } else if ('\\0' <= value && value < ' ') {\n        return ::Catch::Detail::stringify(static_cast<unsigned int>(value));\n    } else {\n        char chstr[] = \"' '\";\n        chstr[1] = value;\n        return chstr;\n    }\n}\nstd::string StringMaker<char>::convert(char c) {\n    return ::Catch::Detail::stringify(static_cast<signed char>(c));\n}\nstd::string StringMaker<unsigned char>::convert(unsigned char c) {\n    return ::Catch::Detail::stringify(static_cast<char>(c));\n}\n\nstd::string StringMaker<std::nullptr_t>::convert(std::nullptr_t) {\n    return \"nullptr\";\n}\n\nstd::string StringMaker<float>::convert(float value) {\n    return fpToString(value, 5) + 'f';\n}\nstd::string StringMaker<double>::convert(double value) {\n    return fpToString(value, 10);\n}\n\nstd::string ratio_string<std::atto>::symbol() { return \"a\"; }\nstd::string ratio_string<std::femto>::symbol() { return \"f\"; }\nstd::string ratio_string<std::pico>::symbol() { return \"p\"; }\nstd::string ratio_string<std::nano>::symbol() { return \"n\"; }\nstd::string ratio_string<std::micro>::symbol() { return \"u\"; }\nstd::string ratio_string<std::milli>::symbol() { return \"m\"; }\n\n} // end namespace Catch\n\n#if defined(__clang__)\n#    pragma clang diagnostic pop\n#endif\n\n// end catch_tostring.cpp\n// start catch_totals.cpp\n\nnamespace Catch {\n\n    Counts Counts::operator - ( Counts const& other ) const {\n        Counts diff;\n        diff.passed = passed - other.passed;\n        diff.failed = failed - other.failed;\n        diff.failedButOk = failedButOk - other.failedButOk;\n        return diff;\n    }\n\n    Counts& Counts::operator += ( Counts const& other ) {\n        passed += other.passed;\n        failed += other.failed;\n        failedButOk += other.failedButOk;\n        return *this;\n    }\n\n    std::size_t Counts::total() const {\n        return passed + failed + failedButOk;\n    }\n    bool Counts::allPassed() const {\n        return failed == 0 && failedButOk == 0;\n    }\n    bool Counts::allOk() const {\n        return failed == 0;\n    }\n\n    Totals Totals::operator - ( Totals const& other ) const {\n        Totals diff;\n        diff.assertions = assertions - other.assertions;\n        diff.testCases = testCases - other.testCases;\n        return diff;\n    }\n\n    Totals& Totals::operator += ( Totals const& other ) {\n        assertions += other.assertions;\n        testCases += other.testCases;\n        return *this;\n    }\n\n    Totals Totals::delta( Totals const& prevTotals ) const {\n        Totals diff = *this - prevTotals;\n        if( diff.assertions.failed > 0 )\n            ++diff.testCases.failed;\n        else if( diff.assertions.failedButOk > 0 )\n            ++diff.testCases.failedButOk;\n        else\n            ++diff.testCases.passed;\n        return diff;\n    }\n\n}\n// end catch_totals.cpp\n// start catch_uncaught_exceptions.cpp\n\n#include <exception>\n\nnamespace Catch {\n    bool uncaught_exceptions() {\n#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)\n        return std::uncaught_exceptions() > 0;\n#else\n        return std::uncaught_exception();\n#endif\n  }\n} // end namespace Catch\n// end catch_uncaught_exceptions.cpp\n// start catch_version.cpp\n\n#include <ostream>\n\nnamespace Catch {\n\n    Version::Version\n        (   unsigned int _majorVersion,\n            unsigned int _minorVersion,\n            unsigned int _patchNumber,\n            char const * const _branchName,\n            unsigned int _buildNumber )\n    :   majorVersion( _majorVersion ),\n        minorVersion( _minorVersion ),\n        patchNumber( _patchNumber ),\n        branchName( _branchName ),\n        buildNumber( _buildNumber )\n    {}\n\n    std::ostream& operator << ( std::ostream& os, Version const& version ) {\n        os  << version.majorVersion << '.'\n            << version.minorVersion << '.'\n            << version.patchNumber;\n        // branchName is never null -> 0th char is \\0 if it is empty\n        if (version.branchName[0]) {\n            os << '-' << version.branchName\n               << '.' << version.buildNumber;\n        }\n        return os;\n    }\n\n    Version const& libraryVersion() {\n        static Version version( 2, 7, 0, \"\", 0 );\n        return version;\n    }\n\n}\n// end catch_version.cpp\n// start catch_wildcard_pattern.cpp\n\n#include <sstream>\n\nnamespace Catch {\n\n    WildcardPattern::WildcardPattern( std::string const& pattern,\n                                      CaseSensitive::Choice caseSensitivity )\n    :   m_caseSensitivity( caseSensitivity ),\n        m_pattern( adjustCase( pattern ) )\n    {\n        if( startsWith( m_pattern, '*' ) ) {\n            m_pattern = m_pattern.substr( 1 );\n            m_wildcard = WildcardAtStart;\n        }\n        if( endsWith( m_pattern, '*' ) ) {\n            m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );\n            m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );\n        }\n    }\n\n    bool WildcardPattern::matches( std::string const& str ) const {\n        switch( m_wildcard ) {\n            case NoWildcard:\n                return m_pattern == adjustCase( str );\n            case WildcardAtStart:\n                return endsWith( adjustCase( str ), m_pattern );\n            case WildcardAtEnd:\n                return startsWith( adjustCase( str ), m_pattern );\n            case WildcardAtBothEnds:\n                return contains( adjustCase( str ), m_pattern );\n            default:\n                CATCH_INTERNAL_ERROR( \"Unknown enum\" );\n        }\n    }\n\n    std::string WildcardPattern::adjustCase( std::string const& str ) const {\n        return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;\n    }\n}\n// end catch_wildcard_pattern.cpp\n// start catch_xmlwriter.cpp\n\n#include <iomanip>\n\nusing uchar = unsigned char;\n\nnamespace Catch {\n\nnamespace {\n\n    size_t trailingBytes(unsigned char c) {\n        if ((c & 0xE0) == 0xC0) {\n            return 2;\n        }\n        if ((c & 0xF0) == 0xE0) {\n            return 3;\n        }\n        if ((c & 0xF8) == 0xF0) {\n            return 4;\n        }\n        CATCH_INTERNAL_ERROR(\"Invalid multibyte utf-8 start byte encountered\");\n    }\n\n    uint32_t headerValue(unsigned char c) {\n        if ((c & 0xE0) == 0xC0) {\n            return c & 0x1F;\n        }\n        if ((c & 0xF0) == 0xE0) {\n            return c & 0x0F;\n        }\n        if ((c & 0xF8) == 0xF0) {\n            return c & 0x07;\n        }\n        CATCH_INTERNAL_ERROR(\"Invalid multibyte utf-8 start byte encountered\");\n    }\n\n    void hexEscapeChar(std::ostream& os, unsigned char c) {\n        std::ios_base::fmtflags f(os.flags());\n        os << \"\\\\x\"\n            << std::uppercase << std::hex << std::setfill('0') << std::setw(2)\n            << static_cast<int>(c);\n        os.flags(f);\n    }\n\n} // anonymous namespace\n\n    XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )\n    :   m_str( str ),\n        m_forWhat( forWhat )\n    {}\n\n    void XmlEncode::encodeTo( std::ostream& os ) const {\n        // Apostrophe escaping not necessary if we always use \" to write attributes\n        // (see: http://www.w3.org/TR/xml/#syntax)\n\n        for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {\n            uchar c = m_str[idx];\n            switch (c) {\n            case '<':   os << \"&lt;\"; break;\n            case '&':   os << \"&amp;\"; break;\n\n            case '>':\n                // See: http://www.w3.org/TR/xml/#syntax\n                if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')\n                    os << \"&gt;\";\n                else\n                    os << c;\n                break;\n\n            case '\\\"':\n                if (m_forWhat == ForAttributes)\n                    os << \"&quot;\";\n                else\n                    os << c;\n                break;\n\n            default:\n                // Check for control characters and invalid utf-8\n\n                // Escape control characters in standard ascii\n                // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0\n                if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {\n                    hexEscapeChar(os, c);\n                    break;\n                }\n\n                // Plain ASCII: Write it to stream\n                if (c < 0x7F) {\n                    os << c;\n                    break;\n                }\n\n                // UTF-8 territory\n                // Check if the encoding is valid and if it is not, hex escape bytes.\n                // Important: We do not check the exact decoded values for validity, only the encoding format\n                // First check that this bytes is a valid lead byte:\n                // This means that it is not encoded as 1111 1XXX\n                // Or as 10XX XXXX\n                if (c <  0xC0 ||\n                    c >= 0xF8) {\n                    hexEscapeChar(os, c);\n                    break;\n                }\n\n                auto encBytes = trailingBytes(c);\n                // Are there enough bytes left to avoid accessing out-of-bounds memory?\n                if (idx + encBytes - 1 >= m_str.size()) {\n                    hexEscapeChar(os, c);\n                    break;\n                }\n                // The header is valid, check data\n                // The next encBytes bytes must together be a valid utf-8\n                // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)\n                bool valid = true;\n                uint32_t value = headerValue(c);\n                for (std::size_t n = 1; n < encBytes; ++n) {\n                    uchar nc = m_str[idx + n];\n                    valid &= ((nc & 0xC0) == 0x80);\n                    value = (value << 6) | (nc & 0x3F);\n                }\n\n                if (\n                    // Wrong bit pattern of following bytes\n                    (!valid) ||\n                    // Overlong encodings\n                    (value < 0x80) ||\n                    (0x80 <= value && value < 0x800   && encBytes > 2) ||\n                    (0x800 < value && value < 0x10000 && encBytes > 3) ||\n                    // Encoded value out of range\n                    (value >= 0x110000)\n                    ) {\n                    hexEscapeChar(os, c);\n                    break;\n                }\n\n                // If we got here, this is in fact a valid(ish) utf-8 sequence\n                for (std::size_t n = 0; n < encBytes; ++n) {\n                    os << m_str[idx + n];\n                }\n                idx += encBytes - 1;\n                break;\n            }\n        }\n    }\n\n    std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {\n        xmlEncode.encodeTo( os );\n        return os;\n    }\n\n    XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )\n    :   m_writer( writer )\n    {}\n\n    XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept\n    :   m_writer( other.m_writer ){\n        other.m_writer = nullptr;\n    }\n    XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {\n        if ( m_writer ) {\n            m_writer->endElement();\n        }\n        m_writer = other.m_writer;\n        other.m_writer = nullptr;\n        return *this;\n    }\n\n    XmlWriter::ScopedElement::~ScopedElement() {\n        if( m_writer )\n            m_writer->endElement();\n    }\n\n    XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) {\n        m_writer->writeText( text, indent );\n        return *this;\n    }\n\n    XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )\n    {\n        writeDeclaration();\n    }\n\n    XmlWriter::~XmlWriter() {\n        while( !m_tags.empty() )\n            endElement();\n    }\n\n    XmlWriter& XmlWriter::startElement( std::string const& name ) {\n        ensureTagClosed();\n        newlineIfNecessary();\n        m_os << m_indent << '<' << name;\n        m_tags.push_back( name );\n        m_indent += \"  \";\n        m_tagIsOpen = true;\n        return *this;\n    }\n\n    XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) {\n        ScopedElement scoped( this );\n        startElement( name );\n        return scoped;\n    }\n\n    XmlWriter& XmlWriter::endElement() {\n        newlineIfNecessary();\n        m_indent = m_indent.substr( 0, m_indent.size()-2 );\n        if( m_tagIsOpen ) {\n            m_os << \"/>\";\n            m_tagIsOpen = false;\n        }\n        else {\n            m_os << m_indent << \"</\" << m_tags.back() << \">\";\n        }\n        m_os << std::endl;\n        m_tags.pop_back();\n        return *this;\n    }\n\n    XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) {\n        if( !name.empty() && !attribute.empty() )\n            m_os << ' ' << name << \"=\\\"\" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '\"';\n        return *this;\n    }\n\n    XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) {\n        m_os << ' ' << name << \"=\\\"\" << ( attribute ? \"true\" : \"false\" ) << '\"';\n        return *this;\n    }\n\n    XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) {\n        if( !text.empty() ){\n            bool tagWasOpen = m_tagIsOpen;\n            ensureTagClosed();\n            if( tagWasOpen && indent )\n                m_os << m_indent;\n            m_os << XmlEncode( text );\n            m_needsNewline = true;\n        }\n        return *this;\n    }\n\n    XmlWriter& XmlWriter::writeComment( std::string const& text ) {\n        ensureTagClosed();\n        m_os << m_indent << \"<!--\" << text << \"-->\";\n        m_needsNewline = true;\n        return *this;\n    }\n\n    void XmlWriter::writeStylesheetRef( std::string const& url ) {\n        m_os << \"<?xml-stylesheet type=\\\"text/xsl\\\" href=\\\"\" << url << \"\\\"?>\\n\";\n    }\n\n    XmlWriter& XmlWriter::writeBlankLine() {\n        ensureTagClosed();\n        m_os << '\\n';\n        return *this;\n    }\n\n    void XmlWriter::ensureTagClosed() {\n        if( m_tagIsOpen ) {\n            m_os << \">\" << std::endl;\n            m_tagIsOpen = false;\n        }\n    }\n\n    void XmlWriter::writeDeclaration() {\n        m_os << \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\\n\";\n    }\n\n    void XmlWriter::newlineIfNecessary() {\n        if( m_needsNewline ) {\n            m_os << std::endl;\n            m_needsNewline = false;\n        }\n    }\n}\n// end catch_xmlwriter.cpp\n// start catch_reporter_bases.cpp\n\n#include <cstring>\n#include <cfloat>\n#include <cstdio>\n#include <cassert>\n#include <memory>\n\nnamespace Catch {\n    void prepareExpandedExpression(AssertionResult& result) {\n        result.getExpandedExpression();\n    }\n\n    // Because formatting using c++ streams is stateful, drop down to C is required\n    // Alternatively we could use stringstream, but its performance is... not good.\n    std::string getFormattedDuration( double duration ) {\n        // Max exponent + 1 is required to represent the whole part\n        // + 1 for decimal point\n        // + 3 for the 3 decimal places\n        // + 1 for null terminator\n        const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;\n        char buffer[maxDoubleSize];\n\n        // Save previous errno, to prevent sprintf from overwriting it\n        ErrnoGuard guard;\n#ifdef _MSC_VER\n        sprintf_s(buffer, \"%.3f\", duration);\n#else\n        std::sprintf(buffer, \"%.3f\", duration);\n#endif\n        return std::string(buffer);\n    }\n\n    TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)\n        :StreamingReporterBase(_config) {}\n\n    std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() {\n        return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High };\n    }\n\n    void TestEventListenerBase::assertionStarting(AssertionInfo const &) {}\n\n    bool TestEventListenerBase::assertionEnded(AssertionStats const &) {\n        return false;\n    }\n\n} // end namespace Catch\n// end catch_reporter_bases.cpp\n// start catch_reporter_compact.cpp\n\nnamespace {\n\n#ifdef CATCH_PLATFORM_MAC\n    const char* failedString() { return \"FAILED\"; }\n    const char* passedString() { return \"PASSED\"; }\n#else\n    const char* failedString() { return \"failed\"; }\n    const char* passedString() { return \"passed\"; }\n#endif\n\n    // Colour::LightGrey\n    Catch::Colour::Code dimColour() { return Catch::Colour::FileName; }\n\n    std::string bothOrAll( std::size_t count ) {\n        return count == 1 ? std::string() :\n               count == 2 ? \"both \" : \"all \" ;\n    }\n\n} // anon namespace\n\nnamespace Catch {\nnamespace {\n// Colour, message variants:\n// - white: No tests ran.\n// -   red: Failed [both/all] N test cases, failed [both/all] M assertions.\n// - white: Passed [both/all] N test cases (no assertions).\n// -   red: Failed N tests cases, failed M assertions.\n// - green: Passed [both/all] N tests cases with M assertions.\nvoid printTotals(std::ostream& out, const Totals& totals) {\n    if (totals.testCases.total() == 0) {\n        out << \"No tests ran.\";\n    } else if (totals.testCases.failed == totals.testCases.total()) {\n        Colour colour(Colour::ResultError);\n        const std::string qualify_assertions_failed =\n            totals.assertions.failed == totals.assertions.total() ?\n            bothOrAll(totals.assertions.failed) : std::string();\n        out <<\n            \"Failed \" << bothOrAll(totals.testCases.failed)\n            << pluralise(totals.testCases.failed, \"test case\") << \", \"\n            \"failed \" << qualify_assertions_failed <<\n            pluralise(totals.assertions.failed, \"assertion\") << '.';\n    } else if (totals.assertions.total() == 0) {\n        out <<\n            \"Passed \" << bothOrAll(totals.testCases.total())\n            << pluralise(totals.testCases.total(), \"test case\")\n            << \" (no assertions).\";\n    } else if (totals.assertions.failed) {\n        Colour colour(Colour::ResultError);\n        out <<\n            \"Failed \" << pluralise(totals.testCases.failed, \"test case\") << \", \"\n            \"failed \" << pluralise(totals.assertions.failed, \"assertion\") << '.';\n    } else {\n        Colour colour(Colour::ResultSuccess);\n        out <<\n            \"Passed \" << bothOrAll(totals.testCases.passed)\n            << pluralise(totals.testCases.passed, \"test case\") <<\n            \" with \" << pluralise(totals.assertions.passed, \"assertion\") << '.';\n    }\n}\n\n// Implementation of CompactReporter formatting\nclass AssertionPrinter {\npublic:\n    AssertionPrinter& operator= (AssertionPrinter const&) = delete;\n    AssertionPrinter(AssertionPrinter const&) = delete;\n    AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)\n        : stream(_stream)\n        , result(_stats.assertionResult)\n        , messages(_stats.infoMessages)\n        , itMessage(_stats.infoMessages.begin())\n        , printInfoMessages(_printInfoMessages) {}\n\n    void print() {\n        printSourceInfo();\n\n        itMessage = messages.begin();\n\n        switch (result.getResultType()) {\n        case ResultWas::Ok:\n            printResultType(Colour::ResultSuccess, passedString());\n            printOriginalExpression();\n            printReconstructedExpression();\n            if (!result.hasExpression())\n                printRemainingMessages(Colour::None);\n            else\n                printRemainingMessages();\n            break;\n        case ResultWas::ExpressionFailed:\n            if (result.isOk())\n                printResultType(Colour::ResultSuccess, failedString() + std::string(\" - but was ok\"));\n            else\n                printResultType(Colour::Error, failedString());\n            printOriginalExpression();\n            printReconstructedExpression();\n            printRemainingMessages();\n            break;\n        case ResultWas::ThrewException:\n            printResultType(Colour::Error, failedString());\n            printIssue(\"unexpected exception with message:\");\n            printMessage();\n            printExpressionWas();\n            printRemainingMessages();\n            break;\n        case ResultWas::FatalErrorCondition:\n            printResultType(Colour::Error, failedString());\n            printIssue(\"fatal error condition with message:\");\n            printMessage();\n            printExpressionWas();\n            printRemainingMessages();\n            break;\n        case ResultWas::DidntThrowException:\n            printResultType(Colour::Error, failedString());\n            printIssue(\"expected exception, got none\");\n            printExpressionWas();\n            printRemainingMessages();\n            break;\n        case ResultWas::Info:\n            printResultType(Colour::None, \"info\");\n            printMessage();\n            printRemainingMessages();\n            break;\n        case ResultWas::Warning:\n            printResultType(Colour::None, \"warning\");\n            printMessage();\n            printRemainingMessages();\n            break;\n        case ResultWas::ExplicitFailure:\n            printResultType(Colour::Error, failedString());\n            printIssue(\"explicitly\");\n            printRemainingMessages(Colour::None);\n            break;\n            // These cases are here to prevent compiler warnings\n        case ResultWas::Unknown:\n        case ResultWas::FailureBit:\n        case ResultWas::Exception:\n            printResultType(Colour::Error, \"** internal error **\");\n            break;\n        }\n    }\n\nprivate:\n    void printSourceInfo() const {\n        Colour colourGuard(Colour::FileName);\n        stream << result.getSourceInfo() << ':';\n    }\n\n    void printResultType(Colour::Code colour, std::string const& passOrFail) const {\n        if (!passOrFail.empty()) {\n            {\n                Colour colourGuard(colour);\n                stream << ' ' << passOrFail;\n            }\n            stream << ':';\n        }\n    }\n\n    void printIssue(std::string const& issue) const {\n        stream << ' ' << issue;\n    }\n\n    void printExpressionWas() {\n        if (result.hasExpression()) {\n            stream << ';';\n            {\n                Colour colour(dimColour());\n                stream << \" expression was:\";\n            }\n            printOriginalExpression();\n        }\n    }\n\n    void printOriginalExpression() const {\n        if (result.hasExpression()) {\n            stream << ' ' << result.getExpression();\n        }\n    }\n\n    void printReconstructedExpression() const {\n        if (result.hasExpandedExpression()) {\n            {\n                Colour colour(dimColour());\n                stream << \" for: \";\n            }\n            stream << result.getExpandedExpression();\n        }\n    }\n\n    void printMessage() {\n        if (itMessage != messages.end()) {\n            stream << \" '\" << itMessage->message << '\\'';\n            ++itMessage;\n        }\n    }\n\n    void printRemainingMessages(Colour::Code colour = dimColour()) {\n        if (itMessage == messages.end())\n            return;\n\n        // using messages.end() directly yields (or auto) compilation error:\n        std::vector<MessageInfo>::const_iterator itEnd = messages.end();\n        const std::size_t N = static_cast<std::size_t>(std::distance(itMessage, itEnd));\n\n        {\n            Colour colourGuard(colour);\n            stream << \" with \" << pluralise(N, \"message\") << ':';\n        }\n\n        for (; itMessage != itEnd; ) {\n            // If this assertion is a warning ignore any INFO messages\n            if (printInfoMessages || itMessage->type != ResultWas::Info) {\n                stream << \" '\" << itMessage->message << '\\'';\n                if (++itMessage != itEnd) {\n                    Colour colourGuard(dimColour());\n                    stream << \" and\";\n                }\n            }\n        }\n    }\n\nprivate:\n    std::ostream& stream;\n    AssertionResult const& result;\n    std::vector<MessageInfo> messages;\n    std::vector<MessageInfo>::const_iterator itMessage;\n    bool printInfoMessages;\n};\n\n} // anon namespace\n\n        std::string CompactReporter::getDescription() {\n            return \"Reports test results on a single line, suitable for IDEs\";\n        }\n\n        ReporterPreferences CompactReporter::getPreferences() const {\n            return m_reporterPrefs;\n        }\n\n        void CompactReporter::noMatchingTestCases( std::string const& spec ) {\n            stream << \"No test cases matched '\" << spec << '\\'' << std::endl;\n        }\n\n        void CompactReporter::assertionStarting( AssertionInfo const& ) {}\n\n        bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) {\n            AssertionResult const& result = _assertionStats.assertionResult;\n\n            bool printInfoMessages = true;\n\n            // Drop out if result was successful and we're not printing those\n            if( !m_config->includeSuccessfulResults() && result.isOk() ) {\n                if( result.getResultType() != ResultWas::Warning )\n                    return false;\n                printInfoMessages = false;\n            }\n\n            AssertionPrinter printer( stream, _assertionStats, printInfoMessages );\n            printer.print();\n\n            stream << std::endl;\n            return true;\n        }\n\n        void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {\n            if (m_config->showDurations() == ShowDurations::Always) {\n                stream << getFormattedDuration(_sectionStats.durationInSeconds) << \" s: \" << _sectionStats.sectionInfo.name << std::endl;\n            }\n        }\n\n        void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) {\n            printTotals( stream, _testRunStats.totals );\n            stream << '\\n' << std::endl;\n            StreamingReporterBase::testRunEnded( _testRunStats );\n        }\n\n        CompactReporter::~CompactReporter() {}\n\n    CATCH_REGISTER_REPORTER( \"compact\", CompactReporter )\n\n} // end namespace Catch\n// end catch_reporter_compact.cpp\n// start catch_reporter_console.cpp\n\n#include <cfloat>\n#include <cstdio>\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch\n // Note that 4062 (not all labels are handled\n // and default is missing) is enabled\n#endif\n\nnamespace Catch {\n\nnamespace {\n\n// Formatter impl for ConsoleReporter\nclass ConsoleAssertionPrinter {\npublic:\n    ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete;\n    ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete;\n    ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)\n        : stream(_stream),\n        stats(_stats),\n        result(_stats.assertionResult),\n        colour(Colour::None),\n        message(result.getMessage()),\n        messages(_stats.infoMessages),\n        printInfoMessages(_printInfoMessages) {\n        switch (result.getResultType()) {\n        case ResultWas::Ok:\n            colour = Colour::Success;\n            passOrFail = \"PASSED\";\n            //if( result.hasMessage() )\n            if (_stats.infoMessages.size() == 1)\n                messageLabel = \"with message\";\n            if (_stats.infoMessages.size() > 1)\n                messageLabel = \"with messages\";\n            break;\n        case ResultWas::ExpressionFailed:\n            if (result.isOk()) {\n                colour = Colour::Success;\n                passOrFail = \"FAILED - but was ok\";\n            } else {\n                colour = Colour::Error;\n                passOrFail = \"FAILED\";\n            }\n            if (_stats.infoMessages.size() == 1)\n                messageLabel = \"with message\";\n            if (_stats.infoMessages.size() > 1)\n                messageLabel = \"with messages\";\n            break;\n        case ResultWas::ThrewException:\n            colour = Colour::Error;\n            passOrFail = \"FAILED\";\n            messageLabel = \"due to unexpected exception with \";\n            if (_stats.infoMessages.size() == 1)\n                messageLabel += \"message\";\n            if (_stats.infoMessages.size() > 1)\n                messageLabel += \"messages\";\n            break;\n        case ResultWas::FatalErrorCondition:\n            colour = Colour::Error;\n            passOrFail = \"FAILED\";\n            messageLabel = \"due to a fatal error condition\";\n            break;\n        case ResultWas::DidntThrowException:\n            colour = Colour::Error;\n            passOrFail = \"FAILED\";\n            messageLabel = \"because no exception was thrown where one was expected\";\n            break;\n        case ResultWas::Info:\n            messageLabel = \"info\";\n            break;\n        case ResultWas::Warning:\n            messageLabel = \"warning\";\n            break;\n        case ResultWas::ExplicitFailure:\n            passOrFail = \"FAILED\";\n            colour = Colour::Error;\n            if (_stats.infoMessages.size() == 1)\n                messageLabel = \"explicitly with message\";\n            if (_stats.infoMessages.size() > 1)\n                messageLabel = \"explicitly with messages\";\n            break;\n            // These cases are here to prevent compiler warnings\n        case ResultWas::Unknown:\n        case ResultWas::FailureBit:\n        case ResultWas::Exception:\n            passOrFail = \"** internal error **\";\n            colour = Colour::Error;\n            break;\n        }\n    }\n\n    void print() const {\n        printSourceInfo();\n        if (stats.totals.assertions.total() > 0) {\n            printResultType();\n            printOriginalExpression();\n            printReconstructedExpression();\n        } else {\n            stream << '\\n';\n        }\n        printMessage();\n    }\n\nprivate:\n    void printResultType() const {\n        if (!passOrFail.empty()) {\n            Colour colourGuard(colour);\n            stream << passOrFail << \":\\n\";\n        }\n    }\n    void printOriginalExpression() const {\n        if (result.hasExpression()) {\n            Colour colourGuard(Colour::OriginalExpression);\n            stream << \"  \";\n            stream << result.getExpressionInMacro();\n            stream << '\\n';\n        }\n    }\n    void printReconstructedExpression() const {\n        if (result.hasExpandedExpression()) {\n            stream << \"with expansion:\\n\";\n            Colour colourGuard(Colour::ReconstructedExpression);\n            stream << Column(result.getExpandedExpression()).indent(2) << '\\n';\n        }\n    }\n    void printMessage() const {\n        if (!messageLabel.empty())\n            stream << messageLabel << ':' << '\\n';\n        for (auto const& msg : messages) {\n            // If this assertion is a warning ignore any INFO messages\n            if (printInfoMessages || msg.type != ResultWas::Info)\n                stream << Column(msg.message).indent(2) << '\\n';\n        }\n    }\n    void printSourceInfo() const {\n        Colour colourGuard(Colour::FileName);\n        stream << result.getSourceInfo() << \": \";\n    }\n\n    std::ostream& stream;\n    AssertionStats const& stats;\n    AssertionResult const& result;\n    Colour::Code colour;\n    std::string passOrFail;\n    std::string messageLabel;\n    std::string message;\n    std::vector<MessageInfo> messages;\n    bool printInfoMessages;\n};\n\nstd::size_t makeRatio(std::size_t number, std::size_t total) {\n    std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;\n    return (ratio == 0 && number > 0) ? 1 : ratio;\n}\n\nstd::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) {\n    if (i > j && i > k)\n        return i;\n    else if (j > k)\n        return j;\n    else\n        return k;\n}\n\nstruct ColumnInfo {\n    enum Justification { Left, Right };\n    std::string name;\n    int width;\n    Justification justification;\n};\nstruct ColumnBreak {};\nstruct RowBreak {};\n\nclass Duration {\n    enum class Unit {\n        Auto,\n        Nanoseconds,\n        Microseconds,\n        Milliseconds,\n        Seconds,\n        Minutes\n    };\n    static const uint64_t s_nanosecondsInAMicrosecond = 1000;\n    static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;\n    static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;\n    static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;\n\n    uint64_t m_inNanoseconds;\n    Unit m_units;\n\npublic:\n    explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)\n        : m_inNanoseconds(inNanoseconds),\n        m_units(units) {\n        if (m_units == Unit::Auto) {\n            if (m_inNanoseconds < s_nanosecondsInAMicrosecond)\n                m_units = Unit::Nanoseconds;\n            else if (m_inNanoseconds < s_nanosecondsInAMillisecond)\n                m_units = Unit::Microseconds;\n            else if (m_inNanoseconds < s_nanosecondsInASecond)\n                m_units = Unit::Milliseconds;\n            else if (m_inNanoseconds < s_nanosecondsInAMinute)\n                m_units = Unit::Seconds;\n            else\n                m_units = Unit::Minutes;\n        }\n\n    }\n\n    auto value() const -> double {\n        switch (m_units) {\n        case Unit::Microseconds:\n            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond);\n        case Unit::Milliseconds:\n            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond);\n        case Unit::Seconds:\n            return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond);\n        case Unit::Minutes:\n            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);\n        default:\n            return static_cast<double>(m_inNanoseconds);\n        }\n    }\n    auto unitsAsString() const -> std::string {\n        switch (m_units) {\n        case Unit::Nanoseconds:\n            return \"ns\";\n        case Unit::Microseconds:\n            return \"us\";\n        case Unit::Milliseconds:\n            return \"ms\";\n        case Unit::Seconds:\n            return \"s\";\n        case Unit::Minutes:\n            return \"m\";\n        default:\n            return \"** internal error **\";\n        }\n\n    }\n    friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& {\n        return os << duration.value() << \" \" << duration.unitsAsString();\n    }\n};\n} // end anon namespace\n\nclass TablePrinter {\n    std::ostream& m_os;\n    std::vector<ColumnInfo> m_columnInfos;\n    std::ostringstream m_oss;\n    int m_currentColumn = -1;\n    bool m_isOpen = false;\n\npublic:\n    TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )\n    :   m_os( os ),\n        m_columnInfos( std::move( columnInfos ) ) {}\n\n    auto columnInfos() const -> std::vector<ColumnInfo> const& {\n        return m_columnInfos;\n    }\n\n    void open() {\n        if (!m_isOpen) {\n            m_isOpen = true;\n            *this << RowBreak();\n            for (auto const& info : m_columnInfos)\n                *this << info.name << ColumnBreak();\n            *this << RowBreak();\n            m_os << Catch::getLineOfChars<'-'>() << \"\\n\";\n        }\n    }\n    void close() {\n        if (m_isOpen) {\n            *this << RowBreak();\n            m_os << std::endl;\n            m_isOpen = false;\n        }\n    }\n\n    template<typename T>\n    friend TablePrinter& operator << (TablePrinter& tp, T const& value) {\n        tp.m_oss << value;\n        return tp;\n    }\n\n    friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) {\n        auto colStr = tp.m_oss.str();\n        // This takes account of utf8 encodings\n        auto strSize = Catch::StringRef(colStr).numberOfCharacters();\n        tp.m_oss.str(\"\");\n        tp.open();\n        if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {\n            tp.m_currentColumn = -1;\n            tp.m_os << \"\\n\";\n        }\n        tp.m_currentColumn++;\n\n        auto colInfo = tp.m_columnInfos[tp.m_currentColumn];\n        auto padding = (strSize + 2 < static_cast<std::size_t>(colInfo.width))\n            ? std::string(colInfo.width - (strSize + 2), ' ')\n            : std::string();\n        if (colInfo.justification == ColumnInfo::Left)\n            tp.m_os << colStr << padding << \" \";\n        else\n            tp.m_os << padding << colStr << \" \";\n        return tp;\n    }\n\n    friend TablePrinter& operator << (TablePrinter& tp, RowBreak) {\n        if (tp.m_currentColumn > 0) {\n            tp.m_os << \"\\n\";\n            tp.m_currentColumn = -1;\n        }\n        return tp;\n    }\n};\n\nConsoleReporter::ConsoleReporter(ReporterConfig const& config)\n    : StreamingReporterBase(config),\n    m_tablePrinter(new TablePrinter(config.stream(),\n    {\n        { \"benchmark name\", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },\n        { \"iters\", 8, ColumnInfo::Right },\n        { \"elapsed ns\", 14, ColumnInfo::Right },\n        { \"average\", 14, ColumnInfo::Right }\n    })) {}\nConsoleReporter::~ConsoleReporter() = default;\n\nstd::string ConsoleReporter::getDescription() {\n    return \"Reports test results as plain lines of text\";\n}\n\nvoid ConsoleReporter::noMatchingTestCases(std::string const& spec) {\n    stream << \"No test cases matched '\" << spec << '\\'' << std::endl;\n}\n\nvoid ConsoleReporter::assertionStarting(AssertionInfo const&) {}\n\nbool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {\n    AssertionResult const& result = _assertionStats.assertionResult;\n\n    bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();\n\n    // Drop out if result was successful but we're not printing them.\n    if (!includeResults && result.getResultType() != ResultWas::Warning)\n        return false;\n\n    lazyPrint();\n\n    ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);\n    printer.print();\n    stream << std::endl;\n    return true;\n}\n\nvoid ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) {\n    m_headerPrinted = false;\n    StreamingReporterBase::sectionStarting(_sectionInfo);\n}\nvoid ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {\n    m_tablePrinter->close();\n    if (_sectionStats.missingAssertions) {\n        lazyPrint();\n        Colour colour(Colour::ResultError);\n        if (m_sectionStack.size() > 1)\n            stream << \"\\nNo assertions in section\";\n        else\n            stream << \"\\nNo assertions in test case\";\n        stream << \" '\" << _sectionStats.sectionInfo.name << \"'\\n\" << std::endl;\n    }\n    if (m_config->showDurations() == ShowDurations::Always) {\n        stream << getFormattedDuration(_sectionStats.durationInSeconds) << \" s: \" << _sectionStats.sectionInfo.name << std::endl;\n    }\n    if (m_headerPrinted) {\n        m_headerPrinted = false;\n    }\n    StreamingReporterBase::sectionEnded(_sectionStats);\n}\n\nvoid ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {\n    lazyPrintWithoutClosingBenchmarkTable();\n\n    auto nameCol = Column( info.name ).width( static_cast<std::size_t>( m_tablePrinter->columnInfos()[0].width - 2 ) );\n\n    bool firstLine = true;\n    for (auto line : nameCol) {\n        if (!firstLine)\n            (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();\n        else\n            firstLine = false;\n\n        (*m_tablePrinter) << line << ColumnBreak();\n    }\n}\nvoid ConsoleReporter::benchmarkEnded(BenchmarkStats const& stats) {\n    Duration average(stats.elapsedTimeInNanoseconds / stats.iterations);\n    (*m_tablePrinter)\n        << stats.iterations << ColumnBreak()\n        << stats.elapsedTimeInNanoseconds << ColumnBreak()\n        << average << ColumnBreak();\n}\n\nvoid ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {\n    m_tablePrinter->close();\n    StreamingReporterBase::testCaseEnded(_testCaseStats);\n    m_headerPrinted = false;\n}\nvoid ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) {\n    if (currentGroupInfo.used) {\n        printSummaryDivider();\n        stream << \"Summary for group '\" << _testGroupStats.groupInfo.name << \"':\\n\";\n        printTotals(_testGroupStats.totals);\n        stream << '\\n' << std::endl;\n    }\n    StreamingReporterBase::testGroupEnded(_testGroupStats);\n}\nvoid ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {\n    printTotalsDivider(_testRunStats.totals);\n    printTotals(_testRunStats.totals);\n    stream << std::endl;\n    StreamingReporterBase::testRunEnded(_testRunStats);\n}\n\nvoid ConsoleReporter::lazyPrint() {\n\n    m_tablePrinter->close();\n    lazyPrintWithoutClosingBenchmarkTable();\n}\n\nvoid ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {\n\n    if (!currentTestRunInfo.used)\n        lazyPrintRunInfo();\n    if (!currentGroupInfo.used)\n        lazyPrintGroupInfo();\n\n    if (!m_headerPrinted) {\n        printTestCaseAndSectionHeader();\n        m_headerPrinted = true;\n    }\n}\nvoid ConsoleReporter::lazyPrintRunInfo() {\n    stream << '\\n' << getLineOfChars<'~'>() << '\\n';\n    Colour colour(Colour::SecondaryText);\n    stream << currentTestRunInfo->name\n        << \" is a Catch v\" << libraryVersion() << \" host application.\\n\"\n        << \"Run with -? for options\\n\\n\";\n\n    if (m_config->rngSeed() != 0)\n        stream << \"Randomness seeded to: \" << m_config->rngSeed() << \"\\n\\n\";\n\n    currentTestRunInfo.used = true;\n}\nvoid ConsoleReporter::lazyPrintGroupInfo() {\n    if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {\n        printClosedHeader(\"Group: \" + currentGroupInfo->name);\n        currentGroupInfo.used = true;\n    }\n}\nvoid ConsoleReporter::printTestCaseAndSectionHeader() {\n    assert(!m_sectionStack.empty());\n    printOpenHeader(currentTestCaseInfo->name);\n\n    if (m_sectionStack.size() > 1) {\n        Colour colourGuard(Colour::Headers);\n\n        auto\n            it = m_sectionStack.begin() + 1, // Skip first section (test case)\n            itEnd = m_sectionStack.end();\n        for (; it != itEnd; ++it)\n            printHeaderString(it->name, 2);\n    }\n\n    SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;\n\n    if (!lineInfo.empty()) {\n        stream << getLineOfChars<'-'>() << '\\n';\n        Colour colourGuard(Colour::FileName);\n        stream << lineInfo << '\\n';\n    }\n    stream << getLineOfChars<'.'>() << '\\n' << std::endl;\n}\n\nvoid ConsoleReporter::printClosedHeader(std::string const& _name) {\n    printOpenHeader(_name);\n    stream << getLineOfChars<'.'>() << '\\n';\n}\nvoid ConsoleReporter::printOpenHeader(std::string const& _name) {\n    stream << getLineOfChars<'-'>() << '\\n';\n    {\n        Colour colourGuard(Colour::Headers);\n        printHeaderString(_name);\n    }\n}\n\n// if string has a : in first line will set indent to follow it on\n// subsequent lines\nvoid ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) {\n    std::size_t i = _string.find(\": \");\n    if (i != std::string::npos)\n        i += 2;\n    else\n        i = 0;\n    stream << Column(_string).indent(indent + i).initialIndent(indent) << '\\n';\n}\n\nstruct SummaryColumn {\n\n    SummaryColumn( std::string _label, Colour::Code _colour )\n    :   label( std::move( _label ) ),\n        colour( _colour ) {}\n    SummaryColumn addRow( std::size_t count ) {\n        ReusableStringStream rss;\n        rss << count;\n        std::string row = rss.str();\n        for (auto& oldRow : rows) {\n            while (oldRow.size() < row.size())\n                oldRow = ' ' + oldRow;\n            while (oldRow.size() > row.size())\n                row = ' ' + row;\n        }\n        rows.push_back(row);\n        return *this;\n    }\n\n    std::string label;\n    Colour::Code colour;\n    std::vector<std::string> rows;\n\n};\n\nvoid ConsoleReporter::printTotals( Totals const& totals ) {\n    if (totals.testCases.total() == 0) {\n        stream << Colour(Colour::Warning) << \"No tests ran\\n\";\n    } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) {\n        stream << Colour(Colour::ResultSuccess) << \"All tests passed\";\n        stream << \" (\"\n            << pluralise(totals.assertions.passed, \"assertion\") << \" in \"\n            << pluralise(totals.testCases.passed, \"test case\") << ')'\n            << '\\n';\n    } else {\n\n        std::vector<SummaryColumn> columns;\n        columns.push_back(SummaryColumn(\"\", Colour::None)\n                          .addRow(totals.testCases.total())\n                          .addRow(totals.assertions.total()));\n        columns.push_back(SummaryColumn(\"passed\", Colour::Success)\n                          .addRow(totals.testCases.passed)\n                          .addRow(totals.assertions.passed));\n        columns.push_back(SummaryColumn(\"failed\", Colour::ResultError)\n                          .addRow(totals.testCases.failed)\n                          .addRow(totals.assertions.failed));\n        columns.push_back(SummaryColumn(\"failed as expected\", Colour::ResultExpectedFailure)\n                          .addRow(totals.testCases.failedButOk)\n                          .addRow(totals.assertions.failedButOk));\n\n        printSummaryRow(\"test cases\", columns, 0);\n        printSummaryRow(\"assertions\", columns, 1);\n    }\n}\nvoid ConsoleReporter::printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row) {\n    for (auto col : cols) {\n        std::string value = col.rows[row];\n        if (col.label.empty()) {\n            stream << label << \": \";\n            if (value != \"0\")\n                stream << value;\n            else\n                stream << Colour(Colour::Warning) << \"- none -\";\n        } else if (value != \"0\") {\n            stream << Colour(Colour::LightGrey) << \" | \";\n            stream << Colour(col.colour)\n                << value << ' ' << col.label;\n        }\n    }\n    stream << '\\n';\n}\n\nvoid ConsoleReporter::printTotalsDivider(Totals const& totals) {\n    if (totals.testCases.total() > 0) {\n        std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());\n        std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());\n        std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());\n        while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)\n            findMax(failedRatio, failedButOkRatio, passedRatio)++;\n        while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)\n            findMax(failedRatio, failedButOkRatio, passedRatio)--;\n\n        stream << Colour(Colour::Error) << std::string(failedRatio, '=');\n        stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '=');\n        if (totals.testCases.allPassed())\n            stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '=');\n        else\n            stream << Colour(Colour::Success) << std::string(passedRatio, '=');\n    } else {\n        stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '=');\n    }\n    stream << '\\n';\n}\nvoid ConsoleReporter::printSummaryDivider() {\n    stream << getLineOfChars<'-'>() << '\\n';\n}\n\nCATCH_REGISTER_REPORTER(\"console\", ConsoleReporter)\n\n} // end namespace Catch\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n// end catch_reporter_console.cpp\n// start catch_reporter_junit.cpp\n\n#include <cassert>\n#include <sstream>\n#include <ctime>\n#include <algorithm>\n\nnamespace Catch {\n\n    namespace {\n        std::string getCurrentTimestamp() {\n            // Beware, this is not reentrant because of backward compatibility issues\n            // Also, UTC only, again because of backward compatibility (%z is C++11)\n            time_t rawtime;\n            std::time(&rawtime);\n            auto const timeStampSize = sizeof(\"2017-01-16T17:06:45Z\");\n\n#ifdef _MSC_VER\n            std::tm timeInfo = {};\n            gmtime_s(&timeInfo, &rawtime);\n#else\n            std::tm* timeInfo;\n            timeInfo = std::gmtime(&rawtime);\n#endif\n\n            char timeStamp[timeStampSize];\n            const char * const fmt = \"%Y-%m-%dT%H:%M:%SZ\";\n\n#ifdef _MSC_VER\n            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);\n#else\n            std::strftime(timeStamp, timeStampSize, fmt, timeInfo);\n#endif\n            return std::string(timeStamp);\n        }\n\n        std::string fileNameTag(const std::vector<std::string> &tags) {\n            auto it = std::find_if(begin(tags),\n                                   end(tags),\n                                   [] (std::string const& tag) {return tag.front() == '#'; });\n            if (it != tags.end())\n                return it->substr(1);\n            return std::string();\n        }\n    } // anonymous namespace\n\n    JunitReporter::JunitReporter( ReporterConfig const& _config )\n        :   CumulativeReporterBase( _config ),\n            xml( _config.stream() )\n        {\n            m_reporterPrefs.shouldRedirectStdOut = true;\n            m_reporterPrefs.shouldReportAllAssertions = true;\n        }\n\n    JunitReporter::~JunitReporter() {}\n\n    std::string JunitReporter::getDescription() {\n        return \"Reports test results in an XML format that looks like Ant's junitreport target\";\n    }\n\n    void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {}\n\n    void JunitReporter::testRunStarting( TestRunInfo const& runInfo )  {\n        CumulativeReporterBase::testRunStarting( runInfo );\n        xml.startElement( \"testsuites\" );\n        if( m_config->rngSeed() != 0 ) {\n            xml.startElement( \"properties\" );\n            xml.scopedElement( \"property\" )\n                .writeAttribute( \"name\", \"random-seed\" )\n                .writeAttribute( \"value\", m_config->rngSeed() );\n            xml.endElement();\n        }\n    }\n\n    void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {\n        suiteTimer.start();\n        stdOutForSuite.clear();\n        stdErrForSuite.clear();\n        unexpectedExceptions = 0;\n        CumulativeReporterBase::testGroupStarting( groupInfo );\n    }\n\n    void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) {\n        m_okToFail = testCaseInfo.okToFail();\n    }\n\n    bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) {\n        if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )\n            unexpectedExceptions++;\n        return CumulativeReporterBase::assertionEnded( assertionStats );\n    }\n\n    void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {\n        stdOutForSuite += testCaseStats.stdOut;\n        stdErrForSuite += testCaseStats.stdErr;\n        CumulativeReporterBase::testCaseEnded( testCaseStats );\n    }\n\n    void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {\n        double suiteTime = suiteTimer.getElapsedSeconds();\n        CumulativeReporterBase::testGroupEnded( testGroupStats );\n        writeGroup( *m_testGroups.back(), suiteTime );\n    }\n\n    void JunitReporter::testRunEndedCumulative() {\n        xml.endElement();\n    }\n\n    void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) {\n        XmlWriter::ScopedElement e = xml.scopedElement( \"testsuite\" );\n        TestGroupStats const& stats = groupNode.value;\n        xml.writeAttribute( \"name\", stats.groupInfo.name );\n        xml.writeAttribute( \"errors\", unexpectedExceptions );\n        xml.writeAttribute( \"failures\", stats.totals.assertions.failed-unexpectedExceptions );\n        xml.writeAttribute( \"tests\", stats.totals.assertions.total() );\n        xml.writeAttribute( \"hostname\", \"tbd\" ); // !TBD\n        if( m_config->showDurations() == ShowDurations::Never )\n            xml.writeAttribute( \"time\", \"\" );\n        else\n            xml.writeAttribute( \"time\", suiteTime );\n        xml.writeAttribute( \"timestamp\", getCurrentTimestamp() );\n\n        // Write test cases\n        for( auto const& child : groupNode.children )\n            writeTestCase( *child );\n\n        xml.scopedElement( \"system-out\" ).writeText( trim( stdOutForSuite ), false );\n        xml.scopedElement( \"system-err\" ).writeText( trim( stdErrForSuite ), false );\n    }\n\n    void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {\n        TestCaseStats const& stats = testCaseNode.value;\n\n        // All test cases have exactly one section - which represents the\n        // test case itself. That section may have 0-n nested sections\n        assert( testCaseNode.children.size() == 1 );\n        SectionNode const& rootSection = *testCaseNode.children.front();\n\n        std::string className = stats.testInfo.className;\n\n        if( className.empty() ) {\n            className = fileNameTag(stats.testInfo.tags);\n            if ( className.empty() )\n                className = \"global\";\n        }\n\n        if ( !m_config->name().empty() )\n            className = m_config->name() + \".\" + className;\n\n        writeSection( className, \"\", rootSection );\n    }\n\n    void JunitReporter::writeSection(  std::string const& className,\n                        std::string const& rootName,\n                        SectionNode const& sectionNode ) {\n        std::string name = trim( sectionNode.stats.sectionInfo.name );\n        if( !rootName.empty() )\n            name = rootName + '/' + name;\n\n        if( !sectionNode.assertions.empty() ||\n            !sectionNode.stdOut.empty() ||\n            !sectionNode.stdErr.empty() ) {\n            XmlWriter::ScopedElement e = xml.scopedElement( \"testcase\" );\n            if( className.empty() ) {\n                xml.writeAttribute( \"classname\", name );\n                xml.writeAttribute( \"name\", \"root\" );\n            }\n            else {\n                xml.writeAttribute( \"classname\", className );\n                xml.writeAttribute( \"name\", name );\n            }\n            xml.writeAttribute( \"time\", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) );\n\n            writeAssertions( sectionNode );\n\n            if( !sectionNode.stdOut.empty() )\n                xml.scopedElement( \"system-out\" ).writeText( trim( sectionNode.stdOut ), false );\n            if( !sectionNode.stdErr.empty() )\n                xml.scopedElement( \"system-err\" ).writeText( trim( sectionNode.stdErr ), false );\n        }\n        for( auto const& childNode : sectionNode.childSections )\n            if( className.empty() )\n                writeSection( name, \"\", *childNode );\n            else\n                writeSection( className, name, *childNode );\n    }\n\n    void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {\n        for( auto const& assertion : sectionNode.assertions )\n            writeAssertion( assertion );\n    }\n\n    void JunitReporter::writeAssertion( AssertionStats const& stats ) {\n        AssertionResult const& result = stats.assertionResult;\n        if( !result.isOk() ) {\n            std::string elementName;\n            switch( result.getResultType() ) {\n                case ResultWas::ThrewException:\n                case ResultWas::FatalErrorCondition:\n                    elementName = \"error\";\n                    break;\n                case ResultWas::ExplicitFailure:\n                    elementName = \"failure\";\n                    break;\n                case ResultWas::ExpressionFailed:\n                    elementName = \"failure\";\n                    break;\n                case ResultWas::DidntThrowException:\n                    elementName = \"failure\";\n                    break;\n\n                // We should never see these here:\n                case ResultWas::Info:\n                case ResultWas::Warning:\n                case ResultWas::Ok:\n                case ResultWas::Unknown:\n                case ResultWas::FailureBit:\n                case ResultWas::Exception:\n                    elementName = \"internalError\";\n                    break;\n            }\n\n            XmlWriter::ScopedElement e = xml.scopedElement( elementName );\n\n            xml.writeAttribute( \"message\", result.getExpandedExpression() );\n            xml.writeAttribute( \"type\", result.getTestMacroName() );\n\n            ReusableStringStream rss;\n            if( !result.getMessage().empty() )\n                rss << result.getMessage() << '\\n';\n            for( auto const& msg : stats.infoMessages )\n                if( msg.type == ResultWas::Info )\n                    rss << msg.message << '\\n';\n\n            rss << \"at \" << result.getSourceInfo();\n            xml.writeText( rss.str(), false );\n        }\n    }\n\n    CATCH_REGISTER_REPORTER( \"junit\", JunitReporter )\n\n} // end namespace Catch\n// end catch_reporter_junit.cpp\n// start catch_reporter_listening.cpp\n\n#include <cassert>\n\nnamespace Catch {\n\n    ListeningReporter::ListeningReporter() {\n        // We will assume that listeners will always want all assertions\n        m_preferences.shouldReportAllAssertions = true;\n    }\n\n    void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {\n        m_listeners.push_back( std::move( listener ) );\n    }\n\n    void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {\n        assert(!m_reporter && \"Listening reporter can wrap only 1 real reporter\");\n        m_reporter = std::move( reporter );\n        m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut;\n    }\n\n    ReporterPreferences ListeningReporter::getPreferences() const {\n        return m_preferences;\n    }\n\n    std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {\n        return std::set<Verbosity>{ };\n    }\n\n    void ListeningReporter::noMatchingTestCases( std::string const& spec ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->noMatchingTestCases( spec );\n        }\n        m_reporter->noMatchingTestCases( spec );\n    }\n\n    void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->benchmarkStarting( benchmarkInfo );\n        }\n        m_reporter->benchmarkStarting( benchmarkInfo );\n    }\n    void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->benchmarkEnded( benchmarkStats );\n        }\n        m_reporter->benchmarkEnded( benchmarkStats );\n    }\n\n    void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->testRunStarting( testRunInfo );\n        }\n        m_reporter->testRunStarting( testRunInfo );\n    }\n\n    void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->testGroupStarting( groupInfo );\n        }\n        m_reporter->testGroupStarting( groupInfo );\n    }\n\n    void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->testCaseStarting( testInfo );\n        }\n        m_reporter->testCaseStarting( testInfo );\n    }\n\n    void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->sectionStarting( sectionInfo );\n        }\n        m_reporter->sectionStarting( sectionInfo );\n    }\n\n    void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->assertionStarting( assertionInfo );\n        }\n        m_reporter->assertionStarting( assertionInfo );\n    }\n\n    // The return value indicates if the messages buffer should be cleared:\n    bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) {\n        for( auto const& listener : m_listeners ) {\n            static_cast<void>( listener->assertionEnded( assertionStats ) );\n        }\n        return m_reporter->assertionEnded( assertionStats );\n    }\n\n    void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->sectionEnded( sectionStats );\n        }\n        m_reporter->sectionEnded( sectionStats );\n    }\n\n    void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->testCaseEnded( testCaseStats );\n        }\n        m_reporter->testCaseEnded( testCaseStats );\n    }\n\n    void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->testGroupEnded( testGroupStats );\n        }\n        m_reporter->testGroupEnded( testGroupStats );\n    }\n\n    void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->testRunEnded( testRunStats );\n        }\n        m_reporter->testRunEnded( testRunStats );\n    }\n\n    void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) {\n        for ( auto const& listener : m_listeners ) {\n            listener->skipTest( testInfo );\n        }\n        m_reporter->skipTest( testInfo );\n    }\n\n    bool ListeningReporter::isMulti() const {\n        return true;\n    }\n\n} // end namespace Catch\n// end catch_reporter_listening.cpp\n// start catch_reporter_xml.cpp\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch\n                              // Note that 4062 (not all labels are handled\n                              // and default is missing) is enabled\n#endif\n\nnamespace Catch {\n    XmlReporter::XmlReporter( ReporterConfig const& _config )\n    :   StreamingReporterBase( _config ),\n        m_xml(_config.stream())\n    {\n        m_reporterPrefs.shouldRedirectStdOut = true;\n        m_reporterPrefs.shouldReportAllAssertions = true;\n    }\n\n    XmlReporter::~XmlReporter() = default;\n\n    std::string XmlReporter::getDescription() {\n        return \"Reports test results as an XML document\";\n    }\n\n    std::string XmlReporter::getStylesheetRef() const {\n        return std::string();\n    }\n\n    void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) {\n        m_xml\n            .writeAttribute( \"filename\", sourceInfo.file )\n            .writeAttribute( \"line\", sourceInfo.line );\n    }\n\n    void XmlReporter::noMatchingTestCases( std::string const& s ) {\n        StreamingReporterBase::noMatchingTestCases( s );\n    }\n\n    void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) {\n        StreamingReporterBase::testRunStarting( testInfo );\n        std::string stylesheetRef = getStylesheetRef();\n        if( !stylesheetRef.empty() )\n            m_xml.writeStylesheetRef( stylesheetRef );\n        m_xml.startElement( \"Catch\" );\n        if( !m_config->name().empty() )\n            m_xml.writeAttribute( \"name\", m_config->name() );\n        if( m_config->rngSeed() != 0 )\n            m_xml.scopedElement( \"Randomness\" )\n                .writeAttribute( \"seed\", m_config->rngSeed() );\n    }\n\n    void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) {\n        StreamingReporterBase::testGroupStarting( groupInfo );\n        m_xml.startElement( \"Group\" )\n            .writeAttribute( \"name\", groupInfo.name );\n    }\n\n    void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) {\n        StreamingReporterBase::testCaseStarting(testInfo);\n        m_xml.startElement( \"TestCase\" )\n            .writeAttribute( \"name\", trim( testInfo.name ) )\n            .writeAttribute( \"description\", testInfo.description )\n            .writeAttribute( \"tags\", testInfo.tagsAsString() );\n\n        writeSourceInfo( testInfo.lineInfo );\n\n        if ( m_config->showDurations() == ShowDurations::Always )\n            m_testCaseTimer.start();\n        m_xml.ensureTagClosed();\n    }\n\n    void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) {\n        StreamingReporterBase::sectionStarting( sectionInfo );\n        if( m_sectionDepth++ > 0 ) {\n            m_xml.startElement( \"Section\" )\n                .writeAttribute( \"name\", trim( sectionInfo.name ) );\n            writeSourceInfo( sectionInfo.lineInfo );\n            m_xml.ensureTagClosed();\n        }\n    }\n\n    void XmlReporter::assertionStarting( AssertionInfo const& ) { }\n\n    bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) {\n\n        AssertionResult const& result = assertionStats.assertionResult;\n\n        bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();\n\n        if( includeResults || result.getResultType() == ResultWas::Warning ) {\n            // Print any info messages in <Info> tags.\n            for( auto const& msg : assertionStats.infoMessages ) {\n                if( msg.type == ResultWas::Info && includeResults ) {\n                    m_xml.scopedElement( \"Info\" )\n                            .writeText( msg.message );\n                } else if ( msg.type == ResultWas::Warning ) {\n                    m_xml.scopedElement( \"Warning\" )\n                            .writeText( msg.message );\n                }\n            }\n        }\n\n        // Drop out if result was successful but we're not printing them.\n        if( !includeResults && result.getResultType() != ResultWas::Warning )\n            return true;\n\n        // Print the expression if there is one.\n        if( result.hasExpression() ) {\n            m_xml.startElement( \"Expression\" )\n                .writeAttribute( \"success\", result.succeeded() )\n                .writeAttribute( \"type\", result.getTestMacroName() );\n\n            writeSourceInfo( result.getSourceInfo() );\n\n            m_xml.scopedElement( \"Original\" )\n                .writeText( result.getExpression() );\n            m_xml.scopedElement( \"Expanded\" )\n                .writeText( result.getExpandedExpression() );\n        }\n\n        // And... Print a result applicable to each result type.\n        switch( result.getResultType() ) {\n            case ResultWas::ThrewException:\n                m_xml.startElement( \"Exception\" );\n                writeSourceInfo( result.getSourceInfo() );\n                m_xml.writeText( result.getMessage() );\n                m_xml.endElement();\n                break;\n            case ResultWas::FatalErrorCondition:\n                m_xml.startElement( \"FatalErrorCondition\" );\n                writeSourceInfo( result.getSourceInfo() );\n                m_xml.writeText( result.getMessage() );\n                m_xml.endElement();\n                break;\n            case ResultWas::Info:\n                m_xml.scopedElement( \"Info\" )\n                    .writeText( result.getMessage() );\n                break;\n            case ResultWas::Warning:\n                // Warning will already have been written\n                break;\n            case ResultWas::ExplicitFailure:\n                m_xml.startElement( \"Failure\" );\n                writeSourceInfo( result.getSourceInfo() );\n                m_xml.writeText( result.getMessage() );\n                m_xml.endElement();\n                break;\n            default:\n                break;\n        }\n\n        if( result.hasExpression() )\n            m_xml.endElement();\n\n        return true;\n    }\n\n    void XmlReporter::sectionEnded( SectionStats const& sectionStats ) {\n        StreamingReporterBase::sectionEnded( sectionStats );\n        if( --m_sectionDepth > 0 ) {\n            XmlWriter::ScopedElement e = m_xml.scopedElement( \"OverallResults\" );\n            e.writeAttribute( \"successes\", sectionStats.assertions.passed );\n            e.writeAttribute( \"failures\", sectionStats.assertions.failed );\n            e.writeAttribute( \"expectedFailures\", sectionStats.assertions.failedButOk );\n\n            if ( m_config->showDurations() == ShowDurations::Always )\n                e.writeAttribute( \"durationInSeconds\", sectionStats.durationInSeconds );\n\n            m_xml.endElement();\n        }\n    }\n\n    void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {\n        StreamingReporterBase::testCaseEnded( testCaseStats );\n        XmlWriter::ScopedElement e = m_xml.scopedElement( \"OverallResult\" );\n        e.writeAttribute( \"success\", testCaseStats.totals.assertions.allOk() );\n\n        if ( m_config->showDurations() == ShowDurations::Always )\n            e.writeAttribute( \"durationInSeconds\", m_testCaseTimer.getElapsedSeconds() );\n\n        if( !testCaseStats.stdOut.empty() )\n            m_xml.scopedElement( \"StdOut\" ).writeText( trim( testCaseStats.stdOut ), false );\n        if( !testCaseStats.stdErr.empty() )\n            m_xml.scopedElement( \"StdErr\" ).writeText( trim( testCaseStats.stdErr ), false );\n\n        m_xml.endElement();\n    }\n\n    void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {\n        StreamingReporterBase::testGroupEnded( testGroupStats );\n        // TODO: Check testGroupStats.aborting and act accordingly.\n        m_xml.scopedElement( \"OverallResults\" )\n            .writeAttribute( \"successes\", testGroupStats.totals.assertions.passed )\n            .writeAttribute( \"failures\", testGroupStats.totals.assertions.failed )\n            .writeAttribute( \"expectedFailures\", testGroupStats.totals.assertions.failedButOk );\n        m_xml.endElement();\n    }\n\n    void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) {\n        StreamingReporterBase::testRunEnded( testRunStats );\n        m_xml.scopedElement( \"OverallResults\" )\n            .writeAttribute( \"successes\", testRunStats.totals.assertions.passed )\n            .writeAttribute( \"failures\", testRunStats.totals.assertions.failed )\n            .writeAttribute( \"expectedFailures\", testRunStats.totals.assertions.failedButOk );\n        m_xml.endElement();\n    }\n\n    CATCH_REGISTER_REPORTER( \"xml\", XmlReporter )\n\n} // end namespace Catch\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n// end catch_reporter_xml.cpp\n\nnamespace Catch {\n    LeakDetector leakDetector;\n}\n\n#ifdef __clang__\n#pragma clang diagnostic pop\n#endif\n\n// end catch_impl.hpp\n#endif\n\n#ifdef CATCH_CONFIG_MAIN\n// start catch_default_main.hpp\n\n#ifndef __OBJC__\n\n#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)\n// Standard C/C++ Win32 Unicode wmain entry point\nextern \"C\" int wmain (int argc, wchar_t * argv[], wchar_t * []) {\n#else\n// Standard C/C++ main entry point\nint main (int argc, char * argv[]) {\n#endif\n\n    return Catch::Session().run( argc, argv );\n}\n\n#else // __OBJC__\n\n// Objective-C entry point\nint main (int argc, char * const argv[]) {\n#if !CATCH_ARC_ENABLED\n    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];\n#endif\n\n    Catch::registerTestMethods();\n    int result = Catch::Session().run( argc, (char**)argv );\n\n#if !CATCH_ARC_ENABLED\n    [pool drain];\n#endif\n\n    return result;\n}\n\n#endif // __OBJC__\n\n// end catch_default_main.hpp\n#endif\n\n#if !defined(CATCH_CONFIG_IMPL_ONLY)\n\n#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED\n#  undef CLARA_CONFIG_MAIN\n#endif\n\n#if !defined(CATCH_CONFIG_DISABLE)\n//////\n// If this config identifier is defined then all CATCH macros are prefixed with CATCH_\n#ifdef CATCH_CONFIG_PREFIX_ALL\n\n#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( \"CATCH_REQUIRE\", Catch::ResultDisposition::Normal, __VA_ARGS__ )\n#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( \"CATCH_REQUIRE_FALSE\", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )\n\n#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( \"CATCH_REQUIRE_THROWS\", Catch::ResultDisposition::Normal, __VA_ARGS__ )\n#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( \"CATCH_REQUIRE_THROWS_AS\", exceptionType, Catch::ResultDisposition::Normal, expr )\n#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( \"CATCH_REQUIRE_THROWS_WITH\", Catch::ResultDisposition::Normal, matcher, expr )\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( \"CATCH_REQUIRE_THROWS_MATCHES\", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )\n#endif// CATCH_CONFIG_DISABLE_MATCHERS\n#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( \"CATCH_REQUIRE_NOTHROW\", Catch::ResultDisposition::Normal, __VA_ARGS__ )\n\n#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( \"CATCH_CHECK\", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( \"CATCH_CHECK_FALSE\", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )\n#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( \"CATCH_CHECKED_IF\", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( \"CATCH_CHECKED_ELSE\", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( \"CATCH_CHECK_NOFAIL\", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )\n\n#define CATCH_CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( \"CATCH_CHECK_THROWS\", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( \"CATCH_CHECK_THROWS_AS\", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )\n#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( \"CATCH_CHECK_THROWS_WITH\", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( \"CATCH_CHECK_THROWS_MATCHES\", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )\n#endif // CATCH_CONFIG_DISABLE_MATCHERS\n#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( \"CATCH_CHECK_NOTHROW\", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( \"CATCH_CHECK_THAT\", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )\n\n#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( \"CATCH_REQUIRE_THAT\", matcher, Catch::ResultDisposition::Normal, arg )\n#endif // CATCH_CONFIG_DISABLE_MATCHERS\n\n#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( \"CATCH_INFO\", msg )\n#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( \"CATCH_WARN\", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )\n#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), \"CATCH_CAPTURE\",__VA_ARGS__ )\n\n#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )\n#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )\n#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )\n#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )\n#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )\n#define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )\n#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( \"CATCH_FAIL\", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )\n#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( \"CATCH_FAIL_CHECK\", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( \"CATCH_SUCCEED\", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n\n#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()\n\n#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )\n#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )\n#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )\n#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )\n#else\n#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )\n#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )\n#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )\n#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )\n#endif\n\n#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)\n#define CATCH_STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__ ,      #__VA_ARGS__ );     CATCH_SUCCEED( #__VA_ARGS__ )\n#define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), \"!(\" #__VA_ARGS__ \")\" ); CATCH_SUCCEED( #__VA_ARGS__ )\n#else\n#define CATCH_STATIC_REQUIRE( ... )       CATCH_REQUIRE( __VA_ARGS__ )\n#define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )\n#endif\n\n// \"BDD-style\" convenience wrappers\n#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( \"Scenario: \" __VA_ARGS__ )\n#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, \"Scenario: \" __VA_ARGS__ )\n#define CATCH_GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( \"    Given: \" << desc )\n#define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( \"And given: \" << desc )\n#define CATCH_WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( \"     When: \" << desc )\n#define CATCH_AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( \" And when: \" << desc )\n#define CATCH_THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( \"     Then: \" << desc )\n#define CATCH_AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( \"      And: \" << desc )\n\n// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required\n#else\n\n#define REQUIRE( ... ) INTERNAL_CATCH_TEST( \"REQUIRE\", Catch::ResultDisposition::Normal, __VA_ARGS__  )\n#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( \"REQUIRE_FALSE\", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )\n\n#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( \"REQUIRE_THROWS\", Catch::ResultDisposition::Normal, __VA_ARGS__ )\n#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( \"REQUIRE_THROWS_AS\", exceptionType, Catch::ResultDisposition::Normal, expr )\n#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( \"REQUIRE_THROWS_WITH\", Catch::ResultDisposition::Normal, matcher, expr )\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( \"REQUIRE_THROWS_MATCHES\", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )\n#endif // CATCH_CONFIG_DISABLE_MATCHERS\n#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( \"REQUIRE_NOTHROW\", Catch::ResultDisposition::Normal, __VA_ARGS__ )\n\n#define CHECK( ... ) INTERNAL_CATCH_TEST( \"CHECK\", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( \"CHECK_FALSE\", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )\n#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( \"CHECKED_IF\", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( \"CHECKED_ELSE\", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( \"CHECK_NOFAIL\", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )\n\n#define CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( \"CHECK_THROWS\", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( \"CHECK_THROWS_AS\", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )\n#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( \"CHECK_THROWS_WITH\", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( \"CHECK_THROWS_MATCHES\", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )\n#endif // CATCH_CONFIG_DISABLE_MATCHERS\n#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( \"CHECK_NOTHROW\", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( \"CHECK_THAT\", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )\n\n#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( \"REQUIRE_THAT\", matcher, Catch::ResultDisposition::Normal, arg )\n#endif // CATCH_CONFIG_DISABLE_MATCHERS\n\n#define INFO( msg ) INTERNAL_CATCH_INFO( \"INFO\", msg )\n#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( \"UNSCOPED_INFO\", msg )\n#define WARN( msg ) INTERNAL_CATCH_MSG( \"WARN\", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )\n#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), \"CAPTURE\",__VA_ARGS__ )\n\n#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )\n#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )\n#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )\n#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )\n#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )\n#define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )\n#define FAIL( ... ) INTERNAL_CATCH_MSG( \"FAIL\", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )\n#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( \"FAIL_CHECK\", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n#define SUCCEED( ... ) INTERNAL_CATCH_MSG( \"SUCCEED\", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )\n#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()\n\n#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )\n#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )\n#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )\n#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )\n#else\n#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )\n#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )\n#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )\n#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )\n#endif\n\n#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)\n#define STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__,  #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )\n#define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), \"!(\" #__VA_ARGS__ \")\" ); SUCCEED( \"!(\" #__VA_ARGS__ \")\" )\n#else\n#define STATIC_REQUIRE( ... )       REQUIRE( __VA_ARGS__ )\n#define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )\n#endif\n\n#endif\n\n#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )\n\n// \"BDD-style\" convenience wrappers\n#define SCENARIO( ... ) TEST_CASE( \"Scenario: \" __VA_ARGS__ )\n#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, \"Scenario: \" __VA_ARGS__ )\n\n#define GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( \"    Given: \" << desc )\n#define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( \"And given: \" << desc )\n#define WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( \"     When: \" << desc )\n#define AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( \" And when: \" << desc )\n#define THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( \"     Then: \" << desc )\n#define AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( \"      And: \" << desc )\n\nusing Catch::Detail::Approx;\n\n#else // CATCH_CONFIG_DISABLE\n\n//////\n// If this config identifier is defined then all CATCH macros are prefixed with CATCH_\n#ifdef CATCH_CONFIG_PREFIX_ALL\n\n#define CATCH_REQUIRE( ... )        (void)(0)\n#define CATCH_REQUIRE_FALSE( ... )  (void)(0)\n\n#define CATCH_REQUIRE_THROWS( ... ) (void)(0)\n#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)\n#define CATCH_REQUIRE_THROWS_WITH( expr, matcher )     (void)(0)\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)\n#endif// CATCH_CONFIG_DISABLE_MATCHERS\n#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)\n\n#define CATCH_CHECK( ... )         (void)(0)\n#define CATCH_CHECK_FALSE( ... )   (void)(0)\n#define CATCH_CHECKED_IF( ... )    if (__VA_ARGS__)\n#define CATCH_CHECKED_ELSE( ... )  if (!(__VA_ARGS__))\n#define CATCH_CHECK_NOFAIL( ... )  (void)(0)\n\n#define CATCH_CHECK_THROWS( ... )  (void)(0)\n#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)\n#define CATCH_CHECK_THROWS_WITH( expr, matcher )     (void)(0)\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)\n#endif // CATCH_CONFIG_DISABLE_MATCHERS\n#define CATCH_CHECK_NOTHROW( ... ) (void)(0)\n\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#define CATCH_CHECK_THAT( arg, matcher )   (void)(0)\n\n#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)\n#endif // CATCH_CONFIG_DISABLE_MATCHERS\n\n#define CATCH_INFO( msg )    (void)(0)\n#define CATCH_WARN( msg )    (void)(0)\n#define CATCH_CAPTURE( msg ) (void)(0)\n\n#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))\n#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))\n#define CATCH_METHOD_AS_TEST_CASE( method, ... )\n#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)\n#define CATCH_SECTION( ... )\n#define CATCH_DYNAMIC_SECTION( ... )\n#define CATCH_FAIL( ... ) (void)(0)\n#define CATCH_FAIL_CHECK( ... ) (void)(0)\n#define CATCH_SUCCEED( ... ) (void)(0)\n\n#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))\n\n#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )\n#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )\n#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )\n#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )\n#else\n#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )\n#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )\n#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )\n#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )\n#endif\n\n// \"BDD-style\" convenience wrappers\n#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))\n#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )\n#define CATCH_GIVEN( desc )\n#define CATCH_AND_GIVEN( desc )\n#define CATCH_WHEN( desc )\n#define CATCH_AND_WHEN( desc )\n#define CATCH_THEN( desc )\n#define CATCH_AND_THEN( desc )\n\n#define CATCH_STATIC_REQUIRE( ... )       (void)(0)\n#define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)\n\n// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required\n#else\n\n#define REQUIRE( ... )       (void)(0)\n#define REQUIRE_FALSE( ... ) (void)(0)\n\n#define REQUIRE_THROWS( ... ) (void)(0)\n#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)\n#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)\n#endif // CATCH_CONFIG_DISABLE_MATCHERS\n#define REQUIRE_NOTHROW( ... ) (void)(0)\n\n#define CHECK( ... ) (void)(0)\n#define CHECK_FALSE( ... ) (void)(0)\n#define CHECKED_IF( ... ) if (__VA_ARGS__)\n#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))\n#define CHECK_NOFAIL( ... ) (void)(0)\n\n#define CHECK_THROWS( ... )  (void)(0)\n#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)\n#define CHECK_THROWS_WITH( expr, matcher ) (void)(0)\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)\n#endif // CATCH_CONFIG_DISABLE_MATCHERS\n#define CHECK_NOTHROW( ... ) (void)(0)\n\n#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)\n#define CHECK_THAT( arg, matcher ) (void)(0)\n\n#define REQUIRE_THAT( arg, matcher ) (void)(0)\n#endif // CATCH_CONFIG_DISABLE_MATCHERS\n\n#define INFO( msg ) (void)(0)\n#define WARN( msg ) (void)(0)\n#define CAPTURE( msg ) (void)(0)\n\n#define TEST_CASE( ... )  INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))\n#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))\n#define METHOD_AS_TEST_CASE( method, ... )\n#define REGISTER_TEST_CASE( Function, ... ) (void)(0)\n#define SECTION( ... )\n#define DYNAMIC_SECTION( ... )\n#define FAIL( ... ) (void)(0)\n#define FAIL_CHECK( ... ) (void)(0)\n#define SUCCEED( ... ) (void)(0)\n#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))\n\n#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR\n#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )\n#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )\n#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )\n#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )\n#else\n#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )\n#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )\n#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )\n#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )\n#endif\n\n#define STATIC_REQUIRE( ... )       (void)(0)\n#define STATIC_REQUIRE_FALSE( ... ) (void)(0)\n\n#endif\n\n#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )\n\n// \"BDD-style\" convenience wrappers\n#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) )\n#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )\n\n#define GIVEN( desc )\n#define AND_GIVEN( desc )\n#define WHEN( desc )\n#define AND_WHEN( desc )\n#define THEN( desc )\n#define AND_THEN( desc )\n\nusing Catch::Detail::Approx;\n\n#endif\n\n#endif // ! CATCH_CONFIG_IMPL_ONLY\n\n// start catch_reenable_warnings.h\n\n\n#ifdef __clang__\n#    ifdef __ICC // icpc defines the __clang__ macro\n#        pragma warning(pop)\n#    else\n#        pragma clang diagnostic pop\n#    endif\n#elif defined __GNUC__\n#    pragma GCC diagnostic pop\n#endif\n\n// end catch_reenable_warnings.h\n// end catch.hpp\n#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n"
  },
  {
    "path": "src/DRAMsim3/ext/headers/json.hpp",
    "content": "/*\n    __ _____ _____ _____\n __|  |   __|     |   | |  JSON for Modern C++\n|  |  |__   |  |  | | | |  version 3.5.0\n|_____|_____|_____|_|___|  https://github.com/nlohmann/json\n\nLicensed under the MIT License <http://opensource.org/licenses/MIT>.\nSPDX-License-Identifier: MIT\nCopyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.\n\nPermission is hereby  granted, free of charge, to any  person obtaining a copy\nof this software and associated  documentation files (the \"Software\"), to deal\nin the Software  without restriction, including without  limitation the rights\nto  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell\ncopies  of  the Software,  and  to  permit persons  to  whom  the Software  is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE  IS PROVIDED \"AS  IS\", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR\nIMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,\nFITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE\nAUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER\nLIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n#ifndef NLOHMANN_JSON_HPP\n#define NLOHMANN_JSON_HPP\n\n#define NLOHMANN_JSON_VERSION_MAJOR 3\n#define NLOHMANN_JSON_VERSION_MINOR 5\n#define NLOHMANN_JSON_VERSION_PATCH 0\n\n#include <algorithm> // all_of, find, for_each\n#include <cassert> // assert\n#include <ciso646> // and, not, or\n#include <cstddef> // nullptr_t, ptrdiff_t, size_t\n#include <functional> // hash, less\n#include <initializer_list> // initializer_list\n#include <iosfwd> // istream, ostream\n#include <iterator> // random_access_iterator_tag\n#include <numeric> // accumulate\n#include <string> // string, stoi, to_string\n#include <utility> // declval, forward, move, pair, swap\n\n// #include <nlohmann/json_fwd.hpp>\n#ifndef NLOHMANN_JSON_FWD_HPP\n#define NLOHMANN_JSON_FWD_HPP\n\n#include <cstdint> // int64_t, uint64_t\n#include <map> // map\n#include <memory> // allocator\n#include <string> // string\n#include <vector> // vector\n\n/*!\n@brief namespace for Niels Lohmann\n@see https://github.com/nlohmann\n@since version 1.0.0\n*/\nnamespace nlohmann\n{\n/*!\n@brief default JSONSerializer template argument\n\nThis serializer ignores the template arguments and uses ADL\n([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))\nfor serialization.\n*/\ntemplate<typename T = void, typename SFINAE = void>\nstruct adl_serializer;\n\ntemplate<template<typename U, typename V, typename... Args> class ObjectType =\n         std::map,\n         template<typename U, typename... Args> class ArrayType = std::vector,\n         class StringType = std::string, class BooleanType = bool,\n         class NumberIntegerType = std::int64_t,\n         class NumberUnsignedType = std::uint64_t,\n         class NumberFloatType = double,\n         template<typename U> class AllocatorType = std::allocator,\n         template<typename T, typename SFINAE = void> class JSONSerializer =\n         adl_serializer>\nclass basic_json;\n\n/*!\n@brief JSON Pointer\n\nA JSON pointer defines a string syntax for identifying a specific value\nwithin a JSON document. It can be used with functions `at` and\n`operator[]`. Furthermore, JSON pointers are the base for JSON patches.\n\n@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)\n\n@since version 2.0.0\n*/\ntemplate<typename BasicJsonType>\nclass json_pointer;\n\n/*!\n@brief default JSON class\n\nThis type is the default specialization of the @ref basic_json class which\nuses the standard template types.\n\n@since version 1.0.0\n*/\nusing json = basic_json<>;\n}  // namespace nlohmann\n\n#endif\n\n// #include <nlohmann/detail/macro_scope.hpp>\n\n\n// This file contains all internal macro definitions\n// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them\n\n// exclude unsupported compilers\n#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)\n    #if defined(__clang__)\n        #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400\n            #error \"unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers\"\n        #endif\n    #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))\n        #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800\n            #error \"unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers\"\n        #endif\n    #endif\n#endif\n\n// disable float-equal warnings on GCC/clang\n#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)\n    #pragma GCC diagnostic push\n    #pragma GCC diagnostic ignored \"-Wfloat-equal\"\n#endif\n\n// disable documentation warnings on clang\n#if defined(__clang__)\n    #pragma GCC diagnostic push\n    #pragma GCC diagnostic ignored \"-Wdocumentation\"\n#endif\n\n// allow for portable deprecation warnings\n#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)\n    #define JSON_DEPRECATED __attribute__((deprecated))\n#elif defined(_MSC_VER)\n    #define JSON_DEPRECATED __declspec(deprecated)\n#else\n    #define JSON_DEPRECATED\n#endif\n\n// allow for portable nodiscard warnings\n#if defined(__has_cpp_attribute)\n    #if __has_cpp_attribute(nodiscard)\n        #define JSON_NODISCARD [[nodiscard]]\n    #elif __has_cpp_attribute(gnu::warn_unused_result)\n        #define JSON_NODISCARD [[gnu::warn_unused_result]]\n    #else\n        #define JSON_NODISCARD\n    #endif\n#else\n    #define JSON_NODISCARD\n#endif\n\n// allow to disable exceptions\n#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)\n    #define JSON_THROW(exception) throw exception\n    #define JSON_TRY try\n    #define JSON_CATCH(exception) catch(exception)\n    #define JSON_INTERNAL_CATCH(exception) catch(exception)\n#else\n    #define JSON_THROW(exception) std::abort()\n    #define JSON_TRY if(true)\n    #define JSON_CATCH(exception) if(false)\n    #define JSON_INTERNAL_CATCH(exception) if(false)\n#endif\n\n// override exception macros\n#if defined(JSON_THROW_USER)\n    #undef JSON_THROW\n    #define JSON_THROW JSON_THROW_USER\n#endif\n#if defined(JSON_TRY_USER)\n    #undef JSON_TRY\n    #define JSON_TRY JSON_TRY_USER\n#endif\n#if defined(JSON_CATCH_USER)\n    #undef JSON_CATCH\n    #define JSON_CATCH JSON_CATCH_USER\n    #undef JSON_INTERNAL_CATCH\n    #define JSON_INTERNAL_CATCH JSON_CATCH_USER\n#endif\n#if defined(JSON_INTERNAL_CATCH_USER)\n    #undef JSON_INTERNAL_CATCH\n    #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER\n#endif\n\n// manual branch prediction\n#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)\n    #define JSON_LIKELY(x)      __builtin_expect(!!(x), 1)\n    #define JSON_UNLIKELY(x)    __builtin_expect(!!(x), 0)\n#else\n    #define JSON_LIKELY(x)      x\n    #define JSON_UNLIKELY(x)    x\n#endif\n\n// C++ language standard detection\n#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464\n    #define JSON_HAS_CPP_17\n    #define JSON_HAS_CPP_14\n#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)\n    #define JSON_HAS_CPP_14\n#endif\n\n/*!\n@brief macro to briefly define a mapping between an enum and JSON\n@def NLOHMANN_JSON_SERIALIZE_ENUM\n@since version 3.4.0\n*/\n#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...)                                           \\\n    template<typename BasicJsonType>                                                           \\\n    inline void to_json(BasicJsonType& j, const ENUM_TYPE& e)                                  \\\n    {                                                                                          \\\n        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE \" must be an enum!\");         \\\n        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                    \\\n        auto it = std::find_if(std::begin(m), std::end(m),                                     \\\n                               [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \\\n        {                                                                                      \\\n            return ej_pair.first == e;                                                         \\\n        });                                                                                    \\\n        j = ((it != std::end(m)) ? it : std::begin(m))->second;                                \\\n    }                                                                                          \\\n    template<typename BasicJsonType>                                                           \\\n    inline void from_json(const BasicJsonType& j, ENUM_TYPE& e)                                \\\n    {                                                                                          \\\n        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE \" must be an enum!\");         \\\n        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                    \\\n        auto it = std::find_if(std::begin(m), std::end(m),                                     \\\n                               [j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \\\n        {                                                                                      \\\n            return ej_pair.second == j;                                                        \\\n        });                                                                                    \\\n        e = ((it != std::end(m)) ? it : std::begin(m))->first;                                 \\\n    }\n\n// Ugly macros to avoid uglier copy-paste when specializing basic_json. They\n// may be removed in the future once the class is split.\n\n#define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \\\n    template<template<typename, typename, typename...> class ObjectType,   \\\n             template<typename, typename...> class ArrayType,              \\\n             class StringType, class BooleanType, class NumberIntegerType, \\\n             class NumberUnsignedType, class NumberFloatType,              \\\n             template<typename> class AllocatorType,                       \\\n             template<typename, typename = void> class JSONSerializer>\n\n#define NLOHMANN_BASIC_JSON_TPL                                            \\\n    basic_json<ObjectType, ArrayType, StringType, BooleanType,             \\\n    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \\\n    AllocatorType, JSONSerializer>\n\n// #include <nlohmann/detail/meta/cpp_future.hpp>\n\n\n#include <ciso646> // not\n#include <cstddef> // size_t\n#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type\n\nnamespace nlohmann\n{\nnamespace detail\n{\n// alias templates to reduce boilerplate\ntemplate<bool B, typename T = void>\nusing enable_if_t = typename std::enable_if<B, T>::type;\n\ntemplate<typename T>\nusing uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;\n\n// implementation of C++14 index_sequence and affiliates\n// source: https://stackoverflow.com/a/32223343\ntemplate<std::size_t... Ints>\nstruct index_sequence\n{\n    using type = index_sequence;\n    using value_type = std::size_t;\n    static constexpr std::size_t size() noexcept\n    {\n        return sizeof...(Ints);\n    }\n};\n\ntemplate<class Sequence1, class Sequence2>\nstruct merge_and_renumber;\n\ntemplate<std::size_t... I1, std::size_t... I2>\nstruct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>\n        : index_sequence < I1..., (sizeof...(I1) + I2)... > {};\n\ntemplate<std::size_t N>\nstruct make_index_sequence\n    : merge_and_renumber < typename make_index_sequence < N / 2 >::type,\n      typename make_index_sequence < N - N / 2 >::type > {};\n\ntemplate<> struct make_index_sequence<0> : index_sequence<> {};\ntemplate<> struct make_index_sequence<1> : index_sequence<0> {};\n\ntemplate<typename... Ts>\nusing index_sequence_for = make_index_sequence<sizeof...(Ts)>;\n\n// dispatch utility (taken from ranges-v3)\ntemplate<unsigned N> struct priority_tag : priority_tag < N - 1 > {};\ntemplate<> struct priority_tag<0> {};\n\n// taken from ranges-v3\ntemplate<typename T>\nstruct static_const\n{\n    static constexpr T value{};\n};\n\ntemplate<typename T>\nconstexpr T static_const<T>::value;\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/meta/type_traits.hpp>\n\n\n#include <ciso646> // not\n#include <limits> // numeric_limits\n#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type\n#include <utility> // declval\n\n// #include <nlohmann/json_fwd.hpp>\n\n// #include <nlohmann/detail/iterators/iterator_traits.hpp>\n\n\n#include <iterator> // random_access_iterator_tag\n\n// #include <nlohmann/detail/meta/void_t.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\ntemplate <typename ...Ts> struct make_void\n{\n    using type = void;\n};\ntemplate <typename ...Ts> using void_t = typename make_void<Ts...>::type;\n} // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/meta/cpp_future.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\ntemplate <typename It, typename = void>\nstruct iterator_types {};\n\ntemplate <typename It>\nstruct iterator_types <\n    It,\n    void_t<typename It::difference_type, typename It::value_type, typename It::pointer,\n    typename It::reference, typename It::iterator_category >>\n{\n    using difference_type = typename It::difference_type;\n    using value_type = typename It::value_type;\n    using pointer = typename It::pointer;\n    using reference = typename It::reference;\n    using iterator_category = typename It::iterator_category;\n};\n\n// This is required as some compilers implement std::iterator_traits in a way that\n// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.\ntemplate <typename T, typename = void>\nstruct iterator_traits\n{\n};\n\ntemplate <typename T>\nstruct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>\n            : iterator_types<T>\n{\n};\n\ntemplate <typename T>\nstruct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>\n{\n    using iterator_category = std::random_access_iterator_tag;\n    using value_type = T;\n    using difference_type = ptrdiff_t;\n    using pointer = T*;\n    using reference = T&;\n};\n}\n}\n\n// #include <nlohmann/detail/meta/cpp_future.hpp>\n\n// #include <nlohmann/detail/meta/detected.hpp>\n\n\n#include <type_traits>\n\n// #include <nlohmann/detail/meta/void_t.hpp>\n\n\n// http://en.cppreference.com/w/cpp/experimental/is_detected\nnamespace nlohmann\n{\nnamespace detail\n{\nstruct nonesuch\n{\n    nonesuch() = delete;\n    ~nonesuch() = delete;\n    nonesuch(nonesuch const&) = delete;\n    void operator=(nonesuch const&) = delete;\n};\n\ntemplate <class Default,\n          class AlwaysVoid,\n          template <class...> class Op,\n          class... Args>\nstruct detector\n{\n    using value_t = std::false_type;\n    using type = Default;\n};\n\ntemplate <class Default, template <class...> class Op, class... Args>\nstruct detector<Default, void_t<Op<Args...>>, Op, Args...>\n{\n    using value_t = std::true_type;\n    using type = Op<Args...>;\n};\n\ntemplate <template <class...> class Op, class... Args>\nusing is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;\n\ntemplate <template <class...> class Op, class... Args>\nusing detected_t = typename detector<nonesuch, void, Op, Args...>::type;\n\ntemplate <class Default, template <class...> class Op, class... Args>\nusing detected_or = detector<Default, void, Op, Args...>;\n\ntemplate <class Default, template <class...> class Op, class... Args>\nusing detected_or_t = typename detected_or<Default, Op, Args...>::type;\n\ntemplate <class Expected, template <class...> class Op, class... Args>\nusing is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;\n\ntemplate <class To, template <class...> class Op, class... Args>\nusing is_detected_convertible =\n    std::is_convertible<detected_t<Op, Args...>, To>;\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/macro_scope.hpp>\n\n\nnamespace nlohmann\n{\n/*!\n@brief detail namespace with internal helper functions\n\nThis namespace collects functions that should not be exposed,\nimplementations of some @ref basic_json methods, and meta-programming helpers.\n\n@since version 2.1.0\n*/\nnamespace detail\n{\n/////////////\n// helpers //\n/////////////\n\n// Note to maintainers:\n//\n// Every trait in this file expects a non CV-qualified type.\n// The only exceptions are in the 'aliases for detected' section\n// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))\n//\n// In this case, T has to be properly CV-qualified to constraint the function arguments\n// (e.g. to_json(BasicJsonType&, const T&))\n\ntemplate<typename> struct is_basic_json : std::false_type {};\n\nNLOHMANN_BASIC_JSON_TPL_DECLARATION\nstruct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};\n\n//////////////////////////\n// aliases for detected //\n//////////////////////////\n\ntemplate <typename T>\nusing mapped_type_t = typename T::mapped_type;\n\ntemplate <typename T>\nusing key_type_t = typename T::key_type;\n\ntemplate <typename T>\nusing value_type_t = typename T::value_type;\n\ntemplate <typename T>\nusing difference_type_t = typename T::difference_type;\n\ntemplate <typename T>\nusing pointer_t = typename T::pointer;\n\ntemplate <typename T>\nusing reference_t = typename T::reference;\n\ntemplate <typename T>\nusing iterator_category_t = typename T::iterator_category;\n\ntemplate <typename T>\nusing iterator_t = typename T::iterator;\n\ntemplate <typename T, typename... Args>\nusing to_json_function = decltype(T::to_json(std::declval<Args>()...));\n\ntemplate <typename T, typename... Args>\nusing from_json_function = decltype(T::from_json(std::declval<Args>()...));\n\ntemplate <typename T, typename U>\nusing get_template_function = decltype(std::declval<T>().template get<U>());\n\n// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists\ntemplate <typename BasicJsonType, typename T, typename = void>\nstruct has_from_json : std::false_type {};\n\ntemplate <typename BasicJsonType, typename T>\nstruct has_from_json<BasicJsonType, T,\n           enable_if_t<not is_basic_json<T>::value>>\n{\n    using serializer = typename BasicJsonType::template json_serializer<T, void>;\n\n    static constexpr bool value =\n        is_detected_exact<void, from_json_function, serializer,\n        const BasicJsonType&, T&>::value;\n};\n\n// This trait checks if JSONSerializer<T>::from_json(json const&) exists\n// this overload is used for non-default-constructible user-defined-types\ntemplate <typename BasicJsonType, typename T, typename = void>\nstruct has_non_default_from_json : std::false_type {};\n\ntemplate<typename BasicJsonType, typename T>\nstruct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>\n{\n    using serializer = typename BasicJsonType::template json_serializer<T, void>;\n\n    static constexpr bool value =\n        is_detected_exact<T, from_json_function, serializer,\n        const BasicJsonType&>::value;\n};\n\n// This trait checks if BasicJsonType::json_serializer<T>::to_json exists\n// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.\ntemplate <typename BasicJsonType, typename T, typename = void>\nstruct has_to_json : std::false_type {};\n\ntemplate <typename BasicJsonType, typename T>\nstruct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>\n{\n    using serializer = typename BasicJsonType::template json_serializer<T, void>;\n\n    static constexpr bool value =\n        is_detected_exact<void, to_json_function, serializer, BasicJsonType&,\n        T>::value;\n};\n\n\n///////////////////\n// is_ functions //\n///////////////////\n\ntemplate <typename T, typename = void>\nstruct is_iterator_traits : std::false_type {};\n\ntemplate <typename T>\nstruct is_iterator_traits<iterator_traits<T>>\n{\n  private:\n    using traits = iterator_traits<T>;\n\n  public:\n    static constexpr auto value =\n        is_detected<value_type_t, traits>::value &&\n        is_detected<difference_type_t, traits>::value &&\n        is_detected<pointer_t, traits>::value &&\n        is_detected<iterator_category_t, traits>::value &&\n        is_detected<reference_t, traits>::value;\n};\n\n// source: https://stackoverflow.com/a/37193089/4116453\n\ntemplate <typename T, typename = void>\nstruct is_complete_type : std::false_type {};\n\ntemplate <typename T>\nstruct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};\n\ntemplate <typename BasicJsonType, typename CompatibleObjectType,\n          typename = void>\nstruct is_compatible_object_type_impl : std::false_type {};\n\ntemplate <typename BasicJsonType, typename CompatibleObjectType>\nstruct is_compatible_object_type_impl <\n    BasicJsonType, CompatibleObjectType,\n    enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and\n    is_detected<key_type_t, CompatibleObjectType>::value >>\n{\n\n    using object_t = typename BasicJsonType::object_t;\n\n    // macOS's is_constructible does not play well with nonesuch...\n    static constexpr bool value =\n        std::is_constructible<typename object_t::key_type,\n        typename CompatibleObjectType::key_type>::value and\n        std::is_constructible<typename object_t::mapped_type,\n        typename CompatibleObjectType::mapped_type>::value;\n};\n\ntemplate <typename BasicJsonType, typename CompatibleObjectType>\nstruct is_compatible_object_type\n    : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};\n\ntemplate <typename BasicJsonType, typename ConstructibleObjectType,\n          typename = void>\nstruct is_constructible_object_type_impl : std::false_type {};\n\ntemplate <typename BasicJsonType, typename ConstructibleObjectType>\nstruct is_constructible_object_type_impl <\n    BasicJsonType, ConstructibleObjectType,\n    enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value and\n    is_detected<key_type_t, ConstructibleObjectType>::value >>\n{\n    using object_t = typename BasicJsonType::object_t;\n\n    static constexpr bool value =\n        (std::is_constructible<typename ConstructibleObjectType::key_type, typename object_t::key_type>::value and\n         std::is_same<typename object_t::mapped_type, typename ConstructibleObjectType::mapped_type>::value) or\n        (has_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type>::value or\n         has_non_default_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type >::value);\n};\n\ntemplate <typename BasicJsonType, typename ConstructibleObjectType>\nstruct is_constructible_object_type\n    : is_constructible_object_type_impl<BasicJsonType,\n      ConstructibleObjectType> {};\n\ntemplate <typename BasicJsonType, typename CompatibleStringType,\n          typename = void>\nstruct is_compatible_string_type_impl : std::false_type {};\n\ntemplate <typename BasicJsonType, typename CompatibleStringType>\nstruct is_compatible_string_type_impl <\n    BasicJsonType, CompatibleStringType,\n    enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,\n    value_type_t, CompatibleStringType>::value >>\n{\n    static constexpr auto value =\n        std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;\n};\n\ntemplate <typename BasicJsonType, typename ConstructibleStringType>\nstruct is_compatible_string_type\n    : is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};\n\ntemplate <typename BasicJsonType, typename ConstructibleStringType,\n          typename = void>\nstruct is_constructible_string_type_impl : std::false_type {};\n\ntemplate <typename BasicJsonType, typename ConstructibleStringType>\nstruct is_constructible_string_type_impl <\n    BasicJsonType, ConstructibleStringType,\n    enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,\n    value_type_t, ConstructibleStringType>::value >>\n{\n    static constexpr auto value =\n        std::is_constructible<ConstructibleStringType,\n        typename BasicJsonType::string_t>::value;\n};\n\ntemplate <typename BasicJsonType, typename ConstructibleStringType>\nstruct is_constructible_string_type\n    : is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};\n\ntemplate <typename BasicJsonType, typename CompatibleArrayType, typename = void>\nstruct is_compatible_array_type_impl : std::false_type {};\n\ntemplate <typename BasicJsonType, typename CompatibleArrayType>\nstruct is_compatible_array_type_impl <\n    BasicJsonType, CompatibleArrayType,\n    enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and\n    is_detected<iterator_t, CompatibleArrayType>::value and\n// This is needed because json_reverse_iterator has a ::iterator type...\n// Therefore it is detected as a CompatibleArrayType.\n// The real fix would be to have an Iterable concept.\n    not is_iterator_traits<\n    iterator_traits<CompatibleArrayType>>::value >>\n{\n    static constexpr bool value =\n        std::is_constructible<BasicJsonType,\n        typename CompatibleArrayType::value_type>::value;\n};\n\ntemplate <typename BasicJsonType, typename CompatibleArrayType>\nstruct is_compatible_array_type\n    : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};\n\ntemplate <typename BasicJsonType, typename ConstructibleArrayType, typename = void>\nstruct is_constructible_array_type_impl : std::false_type {};\n\ntemplate <typename BasicJsonType, typename ConstructibleArrayType>\nstruct is_constructible_array_type_impl <\n    BasicJsonType, ConstructibleArrayType,\n    enable_if_t<std::is_same<ConstructibleArrayType,\n    typename BasicJsonType::value_type>::value >>\n            : std::true_type {};\n\ntemplate <typename BasicJsonType, typename ConstructibleArrayType>\nstruct is_constructible_array_type_impl <\n    BasicJsonType, ConstructibleArrayType,\n    enable_if_t<not std::is_same<ConstructibleArrayType,\n    typename BasicJsonType::value_type>::value and\n    is_detected<value_type_t, ConstructibleArrayType>::value and\n    is_detected<iterator_t, ConstructibleArrayType>::value and\n    is_complete_type<\n    detected_t<value_type_t, ConstructibleArrayType>>::value >>\n{\n    static constexpr bool value =\n        // This is needed because json_reverse_iterator has a ::iterator type,\n        // furthermore, std::back_insert_iterator (and other iterators) have a base class `iterator`...\n        // Therefore it is detected as a ConstructibleArrayType.\n        // The real fix would be to have an Iterable concept.\n        not is_iterator_traits <\n        iterator_traits<ConstructibleArrayType >>::value and\n\n        (std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t::value_type>::value or\n         has_from_json<BasicJsonType,\n         typename ConstructibleArrayType::value_type>::value or\n         has_non_default_from_json <\n         BasicJsonType, typename ConstructibleArrayType::value_type >::value);\n};\n\ntemplate <typename BasicJsonType, typename ConstructibleArrayType>\nstruct is_constructible_array_type\n    : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};\n\ntemplate <typename RealIntegerType, typename CompatibleNumberIntegerType,\n          typename = void>\nstruct is_compatible_integer_type_impl : std::false_type {};\n\ntemplate <typename RealIntegerType, typename CompatibleNumberIntegerType>\nstruct is_compatible_integer_type_impl <\n    RealIntegerType, CompatibleNumberIntegerType,\n    enable_if_t<std::is_integral<RealIntegerType>::value and\n    std::is_integral<CompatibleNumberIntegerType>::value and\n    not std::is_same<bool, CompatibleNumberIntegerType>::value >>\n{\n    // is there an assert somewhere on overflows?\n    using RealLimits = std::numeric_limits<RealIntegerType>;\n    using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;\n\n    static constexpr auto value =\n        std::is_constructible<RealIntegerType,\n        CompatibleNumberIntegerType>::value and\n        CompatibleLimits::is_integer and\n        RealLimits::is_signed == CompatibleLimits::is_signed;\n};\n\ntemplate <typename RealIntegerType, typename CompatibleNumberIntegerType>\nstruct is_compatible_integer_type\n    : is_compatible_integer_type_impl<RealIntegerType,\n      CompatibleNumberIntegerType> {};\n\ntemplate <typename BasicJsonType, typename CompatibleType, typename = void>\nstruct is_compatible_type_impl: std::false_type {};\n\ntemplate <typename BasicJsonType, typename CompatibleType>\nstruct is_compatible_type_impl <\n    BasicJsonType, CompatibleType,\n    enable_if_t<is_complete_type<CompatibleType>::value >>\n{\n    static constexpr bool value =\n        has_to_json<BasicJsonType, CompatibleType>::value;\n};\n\ntemplate <typename BasicJsonType, typename CompatibleType>\nstruct is_compatible_type\n    : is_compatible_type_impl<BasicJsonType, CompatibleType> {};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/exceptions.hpp>\n\n\n#include <exception> // exception\n#include <stdexcept> // runtime_error\n#include <string> // to_string\n\n// #include <nlohmann/detail/input/position_t.hpp>\n\n\n#include <cstddef> // size_t\n\nnamespace nlohmann\n{\nnamespace detail\n{\n/// struct to capture the start position of the current token\nstruct position_t\n{\n    /// the total number of characters read\n    std::size_t chars_read_total = 0;\n    /// the number of characters read in the current line\n    std::size_t chars_read_current_line = 0;\n    /// the number of lines read\n    std::size_t lines_read = 0;\n\n    /// conversion to size_t to preserve SAX interface\n    constexpr operator size_t() const\n    {\n        return chars_read_total;\n    }\n};\n\n}\n}\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\n////////////////\n// exceptions //\n////////////////\n\n/*!\n@brief general exception of the @ref basic_json class\n\nThis class is an extension of `std::exception` objects with a member @a id for\nexception ids. It is used as the base class for all exceptions thrown by the\n@ref basic_json class. This class can hence be used as \"wildcard\" to catch\nexceptions.\n\nSubclasses:\n- @ref parse_error for exceptions indicating a parse error\n- @ref invalid_iterator for exceptions indicating errors with iterators\n- @ref type_error for exceptions indicating executing a member function with\n                  a wrong type\n- @ref out_of_range for exceptions indicating access out of the defined range\n- @ref other_error for exceptions indicating other library errors\n\n@internal\n@note To have nothrow-copy-constructible exceptions, we internally use\n      `std::runtime_error` which can cope with arbitrary-length error messages.\n      Intermediate strings are built with static functions and then passed to\n      the actual constructor.\n@endinternal\n\n@liveexample{The following code shows how arbitrary library exceptions can be\ncaught.,exception}\n\n@since version 3.0.0\n*/\nclass exception : public std::exception\n{\n  public:\n    /// returns the explanatory string\n    const char* what() const noexcept override\n    {\n        return m.what();\n    }\n\n    /// the id of the exception\n    const int id;\n\n  protected:\n    exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}\n\n    static std::string name(const std::string& ename, int id_)\n    {\n        return \"[json.exception.\" + ename + \".\" + std::to_string(id_) + \"] \";\n    }\n\n  private:\n    /// an exception object as storage for error messages\n    std::runtime_error m;\n};\n\n/*!\n@brief exception indicating a parse error\n\nThis exception is thrown by the library when a parse error occurs. Parse errors\ncan occur during the deserialization of JSON text, CBOR, MessagePack, as well\nas when using JSON Patch.\n\nMember @a byte holds the byte index of the last read character in the input\nfile.\n\nExceptions have ids 1xx.\n\nname / id                      | example message | description\n------------------------------ | --------------- | -------------------------\njson.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.\njson.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\\uxxxx` entries (\"surrogate pairs\"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.\njson.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.\njson.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.\njson.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one \"op\" member, whose value indicates the operation to perform. Its value must be one of \"add\", \"remove\", \"replace\", \"move\", \"copy\", or \"test\"; other values are errors.\njson.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.\njson.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.\njson.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.\njson.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.\njson.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.\njson.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.\njson.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.\njson.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).\n\n@note For an input with n bytes, 1 is the index of the first character and n+1\n      is the index of the terminating null byte or the end of file. This also\n      holds true when reading a byte vector (CBOR or MessagePack).\n\n@liveexample{The following code shows how a `parse_error` exception can be\ncaught.,parse_error}\n\n@sa @ref exception for the base class of the library exceptions\n@sa @ref invalid_iterator for exceptions indicating errors with iterators\n@sa @ref type_error for exceptions indicating executing a member function with\n                    a wrong type\n@sa @ref out_of_range for exceptions indicating access out of the defined range\n@sa @ref other_error for exceptions indicating other library errors\n\n@since version 3.0.0\n*/\nclass parse_error : public exception\n{\n  public:\n    /*!\n    @brief create a parse error exception\n    @param[in] id_       the id of the exception\n    @param[in] position  the position where the error occurred (or with\n                         chars_read_total=0 if the position cannot be\n                         determined)\n    @param[in] what_arg  the explanatory string\n    @return parse_error object\n    */\n    static parse_error create(int id_, const position_t& pos, const std::string& what_arg)\n    {\n        std::string w = exception::name(\"parse_error\", id_) + \"parse error\" +\n                        position_string(pos) + \": \" + what_arg;\n        return parse_error(id_, pos.chars_read_total, w.c_str());\n    }\n\n    static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)\n    {\n        std::string w = exception::name(\"parse_error\", id_) + \"parse error\" +\n                        (byte_ != 0 ? (\" at byte \" + std::to_string(byte_)) : \"\") +\n                        \": \" + what_arg;\n        return parse_error(id_, byte_, w.c_str());\n    }\n\n    /*!\n    @brief byte index of the parse error\n\n    The byte index of the last read character in the input file.\n\n    @note For an input with n bytes, 1 is the index of the first character and\n          n+1 is the index of the terminating null byte or the end of file.\n          This also holds true when reading a byte vector (CBOR or MessagePack).\n    */\n    const std::size_t byte;\n\n  private:\n    parse_error(int id_, std::size_t byte_, const char* what_arg)\n        : exception(id_, what_arg), byte(byte_) {}\n\n    static std::string position_string(const position_t& pos)\n    {\n        return \" at line \" + std::to_string(pos.lines_read + 1) +\n               \", column \" + std::to_string(pos.chars_read_current_line);\n    }\n};\n\n/*!\n@brief exception indicating errors with iterators\n\nThis exception is thrown if iterators passed to a library function do not match\nthe expected semantics.\n\nExceptions have ids 2xx.\n\nname / id                           | example message | description\n----------------------------------- | --------------- | -------------------------\njson.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.\njson.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.\njson.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.\njson.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.\njson.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.\njson.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.\njson.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.\njson.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.\njson.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.\njson.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.\njson.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.\njson.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.\njson.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.\njson.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().\n\n@liveexample{The following code shows how an `invalid_iterator` exception can be\ncaught.,invalid_iterator}\n\n@sa @ref exception for the base class of the library exceptions\n@sa @ref parse_error for exceptions indicating a parse error\n@sa @ref type_error for exceptions indicating executing a member function with\n                    a wrong type\n@sa @ref out_of_range for exceptions indicating access out of the defined range\n@sa @ref other_error for exceptions indicating other library errors\n\n@since version 3.0.0\n*/\nclass invalid_iterator : public exception\n{\n  public:\n    static invalid_iterator create(int id_, const std::string& what_arg)\n    {\n        std::string w = exception::name(\"invalid_iterator\", id_) + what_arg;\n        return invalid_iterator(id_, w.c_str());\n    }\n\n  private:\n    invalid_iterator(int id_, const char* what_arg)\n        : exception(id_, what_arg) {}\n};\n\n/*!\n@brief exception indicating executing a member function with a wrong type\n\nThis exception is thrown in case of a type error; that is, a library function is\nexecuted on a JSON value whose type does not match the expected semantics.\n\nExceptions have ids 3xx.\n\nname / id                     | example message | description\n----------------------------- | --------------- | -------------------------\njson.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.\njson.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.\njson.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.\njson.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.\njson.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.\njson.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.\njson.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.\njson.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.\njson.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.\njson.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.\njson.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.\njson.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.\njson.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.\njson.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.\njson.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.\njson.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |\njson.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) |\n\n@liveexample{The following code shows how a `type_error` exception can be\ncaught.,type_error}\n\n@sa @ref exception for the base class of the library exceptions\n@sa @ref parse_error for exceptions indicating a parse error\n@sa @ref invalid_iterator for exceptions indicating errors with iterators\n@sa @ref out_of_range for exceptions indicating access out of the defined range\n@sa @ref other_error for exceptions indicating other library errors\n\n@since version 3.0.0\n*/\nclass type_error : public exception\n{\n  public:\n    static type_error create(int id_, const std::string& what_arg)\n    {\n        std::string w = exception::name(\"type_error\", id_) + what_arg;\n        return type_error(id_, w.c_str());\n    }\n\n  private:\n    type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}\n};\n\n/*!\n@brief exception indicating access out of the defined range\n\nThis exception is thrown in case a library function is called on an input\nparameter that exceeds the expected range, for instance in case of array\nindices or nonexisting object keys.\n\nExceptions have ids 4xx.\n\nname / id                       | example message | description\n------------------------------- | --------------- | -------------------------\njson.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.\njson.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.\njson.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.\njson.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.\njson.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.\njson.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.\njson.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. |\njson.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |\njson.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |\n\n@liveexample{The following code shows how an `out_of_range` exception can be\ncaught.,out_of_range}\n\n@sa @ref exception for the base class of the library exceptions\n@sa @ref parse_error for exceptions indicating a parse error\n@sa @ref invalid_iterator for exceptions indicating errors with iterators\n@sa @ref type_error for exceptions indicating executing a member function with\n                    a wrong type\n@sa @ref other_error for exceptions indicating other library errors\n\n@since version 3.0.0\n*/\nclass out_of_range : public exception\n{\n  public:\n    static out_of_range create(int id_, const std::string& what_arg)\n    {\n        std::string w = exception::name(\"out_of_range\", id_) + what_arg;\n        return out_of_range(id_, w.c_str());\n    }\n\n  private:\n    out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}\n};\n\n/*!\n@brief exception indicating other library errors\n\nThis exception is thrown in case of errors that cannot be classified with the\nother exception types.\n\nExceptions have ids 5xx.\n\nname / id                      | example message | description\n------------------------------ | --------------- | -------------------------\njson.exception.other_error.501 | unsuccessful: {\"op\":\"test\",\"path\":\"/baz\", \"value\":\"bar\"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.\n\n@sa @ref exception for the base class of the library exceptions\n@sa @ref parse_error for exceptions indicating a parse error\n@sa @ref invalid_iterator for exceptions indicating errors with iterators\n@sa @ref type_error for exceptions indicating executing a member function with\n                    a wrong type\n@sa @ref out_of_range for exceptions indicating access out of the defined range\n\n@liveexample{The following code shows how an `other_error` exception can be\ncaught.,other_error}\n\n@since version 3.0.0\n*/\nclass other_error : public exception\n{\n  public:\n    static other_error create(int id_, const std::string& what_arg)\n    {\n        std::string w = exception::name(\"other_error\", id_) + what_arg;\n        return other_error(id_, w.c_str());\n    }\n\n  private:\n    other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/value_t.hpp>\n\n\n#include <array> // array\n#include <ciso646> // and\n#include <cstddef> // size_t\n#include <cstdint> // uint8_t\n\nnamespace nlohmann\n{\nnamespace detail\n{\n///////////////////////////\n// JSON type enumeration //\n///////////////////////////\n\n/*!\n@brief the JSON type enumeration\n\nThis enumeration collects the different JSON types. It is internally used to\ndistinguish the stored values, and the functions @ref basic_json::is_null(),\n@ref basic_json::is_object(), @ref basic_json::is_array(),\n@ref basic_json::is_string(), @ref basic_json::is_boolean(),\n@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),\n@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),\n@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and\n@ref basic_json::is_structured() rely on it.\n\n@note There are three enumeration entries (number_integer, number_unsigned, and\nnumber_float), because the library distinguishes these three types for numbers:\n@ref basic_json::number_unsigned_t is used for unsigned integers,\n@ref basic_json::number_integer_t is used for signed integers, and\n@ref basic_json::number_float_t is used for floating-point numbers or to\napproximate integers which do not fit in the limits of their respective type.\n\n@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON\nvalue with the default value for a given type\n\n@since version 1.0.0\n*/\nenum class value_t : std::uint8_t\n{\n    null,             ///< null value\n    object,           ///< object (unordered set of name/value pairs)\n    array,            ///< array (ordered collection of values)\n    string,           ///< string value\n    boolean,          ///< boolean value\n    number_integer,   ///< number value (signed integer)\n    number_unsigned,  ///< number value (unsigned integer)\n    number_float,     ///< number value (floating-point)\n    discarded         ///< discarded by the the parser callback function\n};\n\n/*!\n@brief comparison operator for JSON types\n\nReturns an ordering that is similar to Python:\n- order: null < boolean < number < object < array < string\n- furthermore, each type is not smaller than itself\n- discarded values are not comparable\n\n@since version 1.0.0\n*/\ninline bool operator<(const value_t lhs, const value_t rhs) noexcept\n{\n    static constexpr std::array<std::uint8_t, 8> order = {{\n            0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,\n            1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */\n        }\n    };\n\n    const auto l_index = static_cast<std::size_t>(lhs);\n    const auto r_index = static_cast<std::size_t>(rhs);\n    return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];\n}\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/conversions/from_json.hpp>\n\n\n#include <algorithm> // transform\n#include <array> // array\n#include <ciso646> // and, not\n#include <forward_list> // forward_list\n#include <iterator> // inserter, front_inserter, end\n#include <map> // map\n#include <string> // string\n#include <tuple> // tuple, make_tuple\n#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible\n#include <unordered_map> // unordered_map\n#include <utility> // pair, declval\n#include <valarray> // valarray\n\n// #include <nlohmann/detail/exceptions.hpp>\n\n// #include <nlohmann/detail/macro_scope.hpp>\n\n// #include <nlohmann/detail/meta/cpp_future.hpp>\n\n// #include <nlohmann/detail/meta/type_traits.hpp>\n\n// #include <nlohmann/detail/value_t.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\ntemplate<typename BasicJsonType>\nvoid from_json(const BasicJsonType& j, typename std::nullptr_t& n)\n{\n    if (JSON_UNLIKELY(not j.is_null()))\n    {\n        JSON_THROW(type_error::create(302, \"type must be null, but is \" + std::string(j.type_name())));\n    }\n    n = nullptr;\n}\n\n// overloads for basic_json template parameters\ntemplate<typename BasicJsonType, typename ArithmeticType,\n         enable_if_t<std::is_arithmetic<ArithmeticType>::value and\n                     not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,\n                     int> = 0>\nvoid get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)\n{\n    switch (static_cast<value_t>(j))\n    {\n        case value_t::number_unsigned:\n        {\n            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());\n            break;\n        }\n        case value_t::number_integer:\n        {\n            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());\n            break;\n        }\n        case value_t::number_float:\n        {\n            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());\n            break;\n        }\n\n        default:\n            JSON_THROW(type_error::create(302, \"type must be number, but is \" + std::string(j.type_name())));\n    }\n}\n\ntemplate<typename BasicJsonType>\nvoid from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)\n{\n    if (JSON_UNLIKELY(not j.is_boolean()))\n    {\n        JSON_THROW(type_error::create(302, \"type must be boolean, but is \" + std::string(j.type_name())));\n    }\n    b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();\n}\n\ntemplate<typename BasicJsonType>\nvoid from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)\n{\n    if (JSON_UNLIKELY(not j.is_string()))\n    {\n        JSON_THROW(type_error::create(302, \"type must be string, but is \" + std::string(j.type_name())));\n    }\n    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();\n}\n\ntemplate <\n    typename BasicJsonType, typename ConstructibleStringType,\n    enable_if_t <\n        is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value and\n        not std::is_same<typename BasicJsonType::string_t,\n                         ConstructibleStringType>::value,\n        int > = 0 >\nvoid from_json(const BasicJsonType& j, ConstructibleStringType& s)\n{\n    if (JSON_UNLIKELY(not j.is_string()))\n    {\n        JSON_THROW(type_error::create(302, \"type must be string, but is \" + std::string(j.type_name())));\n    }\n\n    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();\n}\n\ntemplate<typename BasicJsonType>\nvoid from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)\n{\n    get_arithmetic_value(j, val);\n}\n\ntemplate<typename BasicJsonType>\nvoid from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)\n{\n    get_arithmetic_value(j, val);\n}\n\ntemplate<typename BasicJsonType>\nvoid from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)\n{\n    get_arithmetic_value(j, val);\n}\n\ntemplate<typename BasicJsonType, typename EnumType,\n         enable_if_t<std::is_enum<EnumType>::value, int> = 0>\nvoid from_json(const BasicJsonType& j, EnumType& e)\n{\n    typename std::underlying_type<EnumType>::type val;\n    get_arithmetic_value(j, val);\n    e = static_cast<EnumType>(val);\n}\n\n// forward_list doesn't have an insert method\ntemplate<typename BasicJsonType, typename T, typename Allocator,\n         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>\nvoid from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)\n{\n    if (JSON_UNLIKELY(not j.is_array()))\n    {\n        JSON_THROW(type_error::create(302, \"type must be array, but is \" + std::string(j.type_name())));\n    }\n    std::transform(j.rbegin(), j.rend(),\n                   std::front_inserter(l), [](const BasicJsonType & i)\n    {\n        return i.template get<T>();\n    });\n}\n\n// valarray doesn't have an insert method\ntemplate<typename BasicJsonType, typename T,\n         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>\nvoid from_json(const BasicJsonType& j, std::valarray<T>& l)\n{\n    if (JSON_UNLIKELY(not j.is_array()))\n    {\n        JSON_THROW(type_error::create(302, \"type must be array, but is \" + std::string(j.type_name())));\n    }\n    l.resize(j.size());\n    std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));\n}\n\ntemplate<typename BasicJsonType>\nvoid from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)\n{\n    arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();\n}\n\ntemplate <typename BasicJsonType, typename T, std::size_t N>\nauto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,\n                          priority_tag<2> /*unused*/)\n-> decltype(j.template get<T>(), void())\n{\n    for (std::size_t i = 0; i < N; ++i)\n    {\n        arr[i] = j.at(i).template get<T>();\n    }\n}\n\ntemplate<typename BasicJsonType, typename ConstructibleArrayType>\nauto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)\n-> decltype(\n    arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),\n    j.template get<typename ConstructibleArrayType::value_type>(),\n    void())\n{\n    using std::end;\n\n    arr.reserve(j.size());\n    std::transform(j.begin(), j.end(),\n                   std::inserter(arr, end(arr)), [](const BasicJsonType & i)\n    {\n        // get<BasicJsonType>() returns *this, this won't call a from_json\n        // method when value_type is BasicJsonType\n        return i.template get<typename ConstructibleArrayType::value_type>();\n    });\n}\n\ntemplate <typename BasicJsonType, typename ConstructibleArrayType>\nvoid from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,\n                          priority_tag<0> /*unused*/)\n{\n    using std::end;\n\n    std::transform(\n        j.begin(), j.end(), std::inserter(arr, end(arr)),\n        [](const BasicJsonType & i)\n    {\n        // get<BasicJsonType>() returns *this, this won't call a from_json\n        // method when value_type is BasicJsonType\n        return i.template get<typename ConstructibleArrayType::value_type>();\n    });\n}\n\ntemplate <typename BasicJsonType, typename ConstructibleArrayType,\n          enable_if_t <\n              is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value and\n              not is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value and\n              not is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value and\n              not is_basic_json<ConstructibleArrayType>::value,\n              int > = 0 >\n\nauto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)\n-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),\nj.template get<typename ConstructibleArrayType::value_type>(),\nvoid())\n{\n    if (JSON_UNLIKELY(not j.is_array()))\n    {\n        JSON_THROW(type_error::create(302, \"type must be array, but is \" +\n                                      std::string(j.type_name())));\n    }\n\n    from_json_array_impl(j, arr, priority_tag<3> {});\n}\n\ntemplate<typename BasicJsonType, typename ConstructibleObjectType,\n         enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>\nvoid from_json(const BasicJsonType& j, ConstructibleObjectType& obj)\n{\n    if (JSON_UNLIKELY(not j.is_object()))\n    {\n        JSON_THROW(type_error::create(302, \"type must be object, but is \" + std::string(j.type_name())));\n    }\n\n    auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();\n    using value_type = typename ConstructibleObjectType::value_type;\n    std::transform(\n        inner_object->begin(), inner_object->end(),\n        std::inserter(obj, obj.begin()),\n        [](typename BasicJsonType::object_t::value_type const & p)\n    {\n        return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());\n    });\n}\n\n// overload for arithmetic types, not chosen for basic_json template arguments\n// (BooleanType, etc..); note: Is it really necessary to provide explicit\n// overloads for boolean_t etc. in case of a custom BooleanType which is not\n// an arithmetic type?\ntemplate<typename BasicJsonType, typename ArithmeticType,\n         enable_if_t <\n             std::is_arithmetic<ArithmeticType>::value and\n             not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and\n             not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and\n             not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and\n             not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,\n             int> = 0>\nvoid from_json(const BasicJsonType& j, ArithmeticType& val)\n{\n    switch (static_cast<value_t>(j))\n    {\n        case value_t::number_unsigned:\n        {\n            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());\n            break;\n        }\n        case value_t::number_integer:\n        {\n            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());\n            break;\n        }\n        case value_t::number_float:\n        {\n            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());\n            break;\n        }\n        case value_t::boolean:\n        {\n            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());\n            break;\n        }\n\n        default:\n            JSON_THROW(type_error::create(302, \"type must be number, but is \" + std::string(j.type_name())));\n    }\n}\n\ntemplate<typename BasicJsonType, typename A1, typename A2>\nvoid from_json(const BasicJsonType& j, std::pair<A1, A2>& p)\n{\n    p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};\n}\n\ntemplate<typename BasicJsonType, typename Tuple, std::size_t... Idx>\nvoid from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...> /*unused*/)\n{\n    t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);\n}\n\ntemplate<typename BasicJsonType, typename... Args>\nvoid from_json(const BasicJsonType& j, std::tuple<Args...>& t)\n{\n    from_json_tuple_impl(j, t, index_sequence_for<Args...> {});\n}\n\ntemplate <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,\n          typename = enable_if_t<not std::is_constructible<\n                                     typename BasicJsonType::string_t, Key>::value>>\nvoid from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)\n{\n    if (JSON_UNLIKELY(not j.is_array()))\n    {\n        JSON_THROW(type_error::create(302, \"type must be array, but is \" + std::string(j.type_name())));\n    }\n    for (const auto& p : j)\n    {\n        if (JSON_UNLIKELY(not p.is_array()))\n        {\n            JSON_THROW(type_error::create(302, \"type must be array, but is \" + std::string(p.type_name())));\n        }\n        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());\n    }\n}\n\ntemplate <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,\n          typename = enable_if_t<not std::is_constructible<\n                                     typename BasicJsonType::string_t, Key>::value>>\nvoid from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)\n{\n    if (JSON_UNLIKELY(not j.is_array()))\n    {\n        JSON_THROW(type_error::create(302, \"type must be array, but is \" + std::string(j.type_name())));\n    }\n    for (const auto& p : j)\n    {\n        if (JSON_UNLIKELY(not p.is_array()))\n        {\n            JSON_THROW(type_error::create(302, \"type must be array, but is \" + std::string(p.type_name())));\n        }\n        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());\n    }\n}\n\nstruct from_json_fn\n{\n    template<typename BasicJsonType, typename T>\n    auto operator()(const BasicJsonType& j, T& val) const\n    noexcept(noexcept(from_json(j, val)))\n    -> decltype(from_json(j, val), void())\n    {\n        return from_json(j, val);\n    }\n};\n}  // namespace detail\n\n/// namespace to hold default `from_json` function\n/// to see why this is required:\n/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html\nnamespace\n{\nconstexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;\n} // namespace\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/conversions/to_json.hpp>\n\n\n#include <ciso646> // or, and, not\n#include <iterator> // begin, end\n#include <tuple> // tuple, get\n#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type\n#include <utility> // move, forward, declval, pair\n#include <valarray> // valarray\n#include <vector> // vector\n\n// #include <nlohmann/detail/meta/cpp_future.hpp>\n\n// #include <nlohmann/detail/meta/type_traits.hpp>\n\n// #include <nlohmann/detail/value_t.hpp>\n\n// #include <nlohmann/detail/iterators/iteration_proxy.hpp>\n\n\n#include <cstddef> // size_t\n#include <string> // string, to_string\n#include <iterator> // input_iterator_tag\n#include <tuple> // tuple_size, get, tuple_element\n\n// #include <nlohmann/detail/value_t.hpp>\n\n// #include <nlohmann/detail/meta/type_traits.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\ntemplate <typename IteratorType> class iteration_proxy_value\n{\n  public:\n    using difference_type = std::ptrdiff_t;\n    using value_type = iteration_proxy_value;\n    using pointer = value_type * ;\n    using reference = value_type & ;\n    using iterator_category = std::input_iterator_tag;\n\n  private:\n    /// the iterator\n    IteratorType anchor;\n    /// an index for arrays (used to create key names)\n    std::size_t array_index = 0;\n    /// last stringified array index\n    mutable std::size_t array_index_last = 0;\n    /// a string representation of the array index\n    mutable std::string array_index_str = \"0\";\n    /// an empty string (to return a reference for primitive values)\n    const std::string empty_str = \"\";\n\n  public:\n    explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}\n\n    /// dereference operator (needed for range-based for)\n    iteration_proxy_value& operator*()\n    {\n        return *this;\n    }\n\n    /// increment operator (needed for range-based for)\n    iteration_proxy_value& operator++()\n    {\n        ++anchor;\n        ++array_index;\n\n        return *this;\n    }\n\n    /// equality operator (needed for InputIterator)\n    bool operator==(const iteration_proxy_value& o) const\n    {\n        return anchor == o.anchor;\n    }\n\n    /// inequality operator (needed for range-based for)\n    bool operator!=(const iteration_proxy_value& o) const\n    {\n        return anchor != o.anchor;\n    }\n\n    /// return key of the iterator\n    const std::string& key() const\n    {\n        assert(anchor.m_object != nullptr);\n\n        switch (anchor.m_object->type())\n        {\n            // use integer array index as key\n            case value_t::array:\n            {\n                if (array_index != array_index_last)\n                {\n                    array_index_str = std::to_string(array_index);\n                    array_index_last = array_index;\n                }\n                return array_index_str;\n            }\n\n            // use key from the object\n            case value_t::object:\n                return anchor.key();\n\n            // use an empty key for all primitive types\n            default:\n                return empty_str;\n        }\n    }\n\n    /// return value of the iterator\n    typename IteratorType::reference value() const\n    {\n        return anchor.value();\n    }\n};\n\n/// proxy class for the items() function\ntemplate<typename IteratorType> class iteration_proxy\n{\n  private:\n    /// the container to iterate\n    typename IteratorType::reference container;\n\n  public:\n    /// construct iteration proxy from a container\n    explicit iteration_proxy(typename IteratorType::reference cont) noexcept\n        : container(cont) {}\n\n    /// return iterator begin (needed for range-based for)\n    iteration_proxy_value<IteratorType> begin() noexcept\n    {\n        return iteration_proxy_value<IteratorType>(container.begin());\n    }\n\n    /// return iterator end (needed for range-based for)\n    iteration_proxy_value<IteratorType> end() noexcept\n    {\n        return iteration_proxy_value<IteratorType>(container.end());\n    }\n};\n// Structured Bindings Support\n// For further reference see https://blog.tartanllama.xyz/structured-bindings/\n// And see https://github.com/nlohmann/json/pull/1391\ntemplate <std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>\nauto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())\n{\n    return i.key();\n}\n// Structured Bindings Support\n// For further reference see https://blog.tartanllama.xyz/structured-bindings/\n// And see https://github.com/nlohmann/json/pull/1391\ntemplate <std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>\nauto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())\n{\n    return i.value();\n}\n}  // namespace detail\n}  // namespace nlohmann\n\n// The Addition to the STD Namespace is required to add\n// Structured Bindings Support to the iteration_proxy_value class\n// For further reference see https://blog.tartanllama.xyz/structured-bindings/\n// And see https://github.com/nlohmann/json/pull/1391\nnamespace std\n{\n#if defined(__clang__)\n    // Fix: https://github.com/nlohmann/json/issues/1401\n    #pragma clang diagnostic push\n    #pragma clang diagnostic ignored \"-Wmismatched-tags\"\n#endif\ntemplate <typename IteratorType>\nclass tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>\n            : public std::integral_constant<std::size_t, 2> {};\n\ntemplate <std::size_t N, typename IteratorType>\nclass tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>\n{\n  public:\n    using type = decltype(\n                     get<N>(std::declval <\n                            ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));\n};\n#if defined(__clang__)\n    #pragma clang diagnostic pop\n#endif\n}\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\n//////////////////\n// constructors //\n//////////////////\n\ntemplate<value_t> struct external_constructor;\n\ntemplate<>\nstruct external_constructor<value_t::boolean>\n{\n    template<typename BasicJsonType>\n    static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept\n    {\n        j.m_type = value_t::boolean;\n        j.m_value = b;\n        j.assert_invariant();\n    }\n};\n\ntemplate<>\nstruct external_constructor<value_t::string>\n{\n    template<typename BasicJsonType>\n    static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)\n    {\n        j.m_type = value_t::string;\n        j.m_value = s;\n        j.assert_invariant();\n    }\n\n    template<typename BasicJsonType>\n    static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)\n    {\n        j.m_type = value_t::string;\n        j.m_value = std::move(s);\n        j.assert_invariant();\n    }\n\n    template<typename BasicJsonType, typename CompatibleStringType,\n             enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,\n                         int> = 0>\n    static void construct(BasicJsonType& j, const CompatibleStringType& str)\n    {\n        j.m_type = value_t::string;\n        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);\n        j.assert_invariant();\n    }\n};\n\ntemplate<>\nstruct external_constructor<value_t::number_float>\n{\n    template<typename BasicJsonType>\n    static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept\n    {\n        j.m_type = value_t::number_float;\n        j.m_value = val;\n        j.assert_invariant();\n    }\n};\n\ntemplate<>\nstruct external_constructor<value_t::number_unsigned>\n{\n    template<typename BasicJsonType>\n    static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept\n    {\n        j.m_type = value_t::number_unsigned;\n        j.m_value = val;\n        j.assert_invariant();\n    }\n};\n\ntemplate<>\nstruct external_constructor<value_t::number_integer>\n{\n    template<typename BasicJsonType>\n    static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept\n    {\n        j.m_type = value_t::number_integer;\n        j.m_value = val;\n        j.assert_invariant();\n    }\n};\n\ntemplate<>\nstruct external_constructor<value_t::array>\n{\n    template<typename BasicJsonType>\n    static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)\n    {\n        j.m_type = value_t::array;\n        j.m_value = arr;\n        j.assert_invariant();\n    }\n\n    template<typename BasicJsonType>\n    static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)\n    {\n        j.m_type = value_t::array;\n        j.m_value = std::move(arr);\n        j.assert_invariant();\n    }\n\n    template<typename BasicJsonType, typename CompatibleArrayType,\n             enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,\n                         int> = 0>\n    static void construct(BasicJsonType& j, const CompatibleArrayType& arr)\n    {\n        using std::begin;\n        using std::end;\n        j.m_type = value_t::array;\n        j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));\n        j.assert_invariant();\n    }\n\n    template<typename BasicJsonType>\n    static void construct(BasicJsonType& j, const std::vector<bool>& arr)\n    {\n        j.m_type = value_t::array;\n        j.m_value = value_t::array;\n        j.m_value.array->reserve(arr.size());\n        for (const bool x : arr)\n        {\n            j.m_value.array->push_back(x);\n        }\n        j.assert_invariant();\n    }\n\n    template<typename BasicJsonType, typename T,\n             enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>\n    static void construct(BasicJsonType& j, const std::valarray<T>& arr)\n    {\n        j.m_type = value_t::array;\n        j.m_value = value_t::array;\n        j.m_value.array->resize(arr.size());\n        std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());\n        j.assert_invariant();\n    }\n};\n\ntemplate<>\nstruct external_constructor<value_t::object>\n{\n    template<typename BasicJsonType>\n    static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)\n    {\n        j.m_type = value_t::object;\n        j.m_value = obj;\n        j.assert_invariant();\n    }\n\n    template<typename BasicJsonType>\n    static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)\n    {\n        j.m_type = value_t::object;\n        j.m_value = std::move(obj);\n        j.assert_invariant();\n    }\n\n    template<typename BasicJsonType, typename CompatibleObjectType,\n             enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>\n    static void construct(BasicJsonType& j, const CompatibleObjectType& obj)\n    {\n        using std::begin;\n        using std::end;\n\n        j.m_type = value_t::object;\n        j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));\n        j.assert_invariant();\n    }\n};\n\n/////////////\n// to_json //\n/////////////\n\ntemplate<typename BasicJsonType, typename T,\n         enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>\nvoid to_json(BasicJsonType& j, T b) noexcept\n{\n    external_constructor<value_t::boolean>::construct(j, b);\n}\n\ntemplate<typename BasicJsonType, typename CompatibleString,\n         enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>\nvoid to_json(BasicJsonType& j, const CompatibleString& s)\n{\n    external_constructor<value_t::string>::construct(j, s);\n}\n\ntemplate<typename BasicJsonType>\nvoid to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)\n{\n    external_constructor<value_t::string>::construct(j, std::move(s));\n}\n\ntemplate<typename BasicJsonType, typename FloatType,\n         enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>\nvoid to_json(BasicJsonType& j, FloatType val) noexcept\n{\n    external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));\n}\n\ntemplate<typename BasicJsonType, typename CompatibleNumberUnsignedType,\n         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>\nvoid to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept\n{\n    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));\n}\n\ntemplate<typename BasicJsonType, typename CompatibleNumberIntegerType,\n         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>\nvoid to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept\n{\n    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));\n}\n\ntemplate<typename BasicJsonType, typename EnumType,\n         enable_if_t<std::is_enum<EnumType>::value, int> = 0>\nvoid to_json(BasicJsonType& j, EnumType e) noexcept\n{\n    using underlying_type = typename std::underlying_type<EnumType>::type;\n    external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));\n}\n\ntemplate<typename BasicJsonType>\nvoid to_json(BasicJsonType& j, const std::vector<bool>& e)\n{\n    external_constructor<value_t::array>::construct(j, e);\n}\n\ntemplate <typename BasicJsonType, typename CompatibleArrayType,\n          enable_if_t<is_compatible_array_type<BasicJsonType,\n                      CompatibleArrayType>::value and\n                      not is_compatible_object_type<\n                          BasicJsonType, CompatibleArrayType>::value and\n                      not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and\n                      not is_basic_json<CompatibleArrayType>::value,\n                      int> = 0>\nvoid to_json(BasicJsonType& j, const CompatibleArrayType& arr)\n{\n    external_constructor<value_t::array>::construct(j, arr);\n}\n\ntemplate<typename BasicJsonType, typename T,\n         enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>\nvoid to_json(BasicJsonType& j, const std::valarray<T>& arr)\n{\n    external_constructor<value_t::array>::construct(j, std::move(arr));\n}\n\ntemplate<typename BasicJsonType>\nvoid to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)\n{\n    external_constructor<value_t::array>::construct(j, std::move(arr));\n}\n\ntemplate<typename BasicJsonType, typename CompatibleObjectType,\n         enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>\nvoid to_json(BasicJsonType& j, const CompatibleObjectType& obj)\n{\n    external_constructor<value_t::object>::construct(j, obj);\n}\n\ntemplate<typename BasicJsonType>\nvoid to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)\n{\n    external_constructor<value_t::object>::construct(j, std::move(obj));\n}\n\ntemplate <\n    typename BasicJsonType, typename T, std::size_t N,\n    enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,\n                const T(&)[N]>::value,\n                int> = 0 >\nvoid to_json(BasicJsonType& j, const T(&arr)[N])\n{\n    external_constructor<value_t::array>::construct(j, arr);\n}\n\ntemplate<typename BasicJsonType, typename... Args>\nvoid to_json(BasicJsonType& j, const std::pair<Args...>& p)\n{\n    j = { p.first, p.second };\n}\n\n// for https://github.com/nlohmann/json/pull/1134\ntemplate < typename BasicJsonType, typename T,\n           enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>\nvoid to_json(BasicJsonType& j, const T& b)\n{\n    j = { {b.key(), b.value()} };\n}\n\ntemplate<typename BasicJsonType, typename Tuple, std::size_t... Idx>\nvoid to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)\n{\n    j = { std::get<Idx>(t)... };\n}\n\ntemplate<typename BasicJsonType, typename... Args>\nvoid to_json(BasicJsonType& j, const std::tuple<Args...>& t)\n{\n    to_json_tuple_impl(j, t, index_sequence_for<Args...> {});\n}\n\nstruct to_json_fn\n{\n    template<typename BasicJsonType, typename T>\n    auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))\n    -> decltype(to_json(j, std::forward<T>(val)), void())\n    {\n        return to_json(j, std::forward<T>(val));\n    }\n};\n}  // namespace detail\n\n/// namespace to hold default `to_json` function\nnamespace\n{\nconstexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;\n} // namespace\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/input/input_adapters.hpp>\n\n\n#include <cassert> // assert\n#include <cstddef> // size_t\n#include <cstring> // strlen\n#include <istream> // istream\n#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next\n#include <memory> // shared_ptr, make_shared, addressof\n#include <numeric> // accumulate\n#include <string> // string, char_traits\n#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer\n#include <utility> // pair, declval\n#include <cstdio> //FILE *\n\n// #include <nlohmann/detail/iterators/iterator_traits.hpp>\n\n// #include <nlohmann/detail/macro_scope.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\n/// the supported input formats\nenum class input_format_t { json, cbor, msgpack, ubjson, bson };\n\n////////////////////\n// input adapters //\n////////////////////\n\n/*!\n@brief abstract input adapter interface\n\nProduces a stream of std::char_traits<char>::int_type characters from a\nstd::istream, a buffer, or some other input type. Accepts the return of\nexactly one non-EOF character for future input. The int_type characters\nreturned consist of all valid char values as positive values (typically\nunsigned char), plus an EOF value outside that range, specified by the value\nof the function std::char_traits<char>::eof(). This value is typically -1, but\ncould be any arbitrary value which is not a valid char value.\n*/\nstruct input_adapter_protocol\n{\n    /// get a character [0,255] or std::char_traits<char>::eof().\n    virtual std::char_traits<char>::int_type get_character() = 0;\n    virtual ~input_adapter_protocol() = default;\n};\n\n/// a type to simplify interfaces\nusing input_adapter_t = std::shared_ptr<input_adapter_protocol>;\n\n/*!\nInput adapter for stdio file access. This adapter read only 1 byte and do not use any\n buffer. This adapter is a very low level adapter.\n*/\nclass file_input_adapter : public input_adapter_protocol\n{\n  public:\n    explicit file_input_adapter(std::FILE* f)  noexcept\n        : m_file(f)\n    {}\n\n    std::char_traits<char>::int_type get_character() noexcept override\n    {\n        return std::fgetc(m_file);\n    }\n  private:\n    /// the file pointer to read from\n    std::FILE* m_file;\n};\n\n\n/*!\nInput adapter for a (caching) istream. Ignores a UFT Byte Order Mark at\nbeginning of input. Does not support changing the underlying std::streambuf\nin mid-input. Maintains underlying std::istream and std::streambuf to support\nsubsequent use of standard std::istream operations to process any input\ncharacters following those used in parsing the JSON input.  Clears the\nstd::istream flags; any input errors (e.g., EOF) will be detected by the first\nsubsequent call for input from the std::istream.\n*/\nclass input_stream_adapter : public input_adapter_protocol\n{\n  public:\n    ~input_stream_adapter() override\n    {\n        // clear stream flags; we use underlying streambuf I/O, do not\n        // maintain ifstream flags, except eof\n        is.clear(is.rdstate() & std::ios::eofbit);\n    }\n\n    explicit input_stream_adapter(std::istream& i)\n        : is(i), sb(*i.rdbuf())\n    {}\n\n    // delete because of pointer members\n    input_stream_adapter(const input_stream_adapter&) = delete;\n    input_stream_adapter& operator=(input_stream_adapter&) = delete;\n    input_stream_adapter(input_stream_adapter&&) = delete;\n    input_stream_adapter& operator=(input_stream_adapter&&) = delete;\n\n    // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to\n    // ensure that std::char_traits<char>::eof() and the character 0xFF do not\n    // end up as the same value, eg. 0xFFFFFFFF.\n    std::char_traits<char>::int_type get_character() override\n    {\n        auto res = sb.sbumpc();\n        // set eof manually, as we don't use the istream interface.\n        if (res == EOF)\n        {\n            is.clear(is.rdstate() | std::ios::eofbit);\n        }\n        return res;\n    }\n\n  private:\n    /// the associated input stream\n    std::istream& is;\n    std::streambuf& sb;\n};\n\n/// input adapter for buffer input\nclass input_buffer_adapter : public input_adapter_protocol\n{\n  public:\n    input_buffer_adapter(const char* b, const std::size_t l) noexcept\n        : cursor(b), limit(b + l)\n    {}\n\n    // delete because of pointer members\n    input_buffer_adapter(const input_buffer_adapter&) = delete;\n    input_buffer_adapter& operator=(input_buffer_adapter&) = delete;\n    input_buffer_adapter(input_buffer_adapter&&) = delete;\n    input_buffer_adapter& operator=(input_buffer_adapter&&) = delete;\n    ~input_buffer_adapter() override = default;\n\n    std::char_traits<char>::int_type get_character() noexcept override\n    {\n        if (JSON_LIKELY(cursor < limit))\n        {\n            return std::char_traits<char>::to_int_type(*(cursor++));\n        }\n\n        return std::char_traits<char>::eof();\n    }\n\n  private:\n    /// pointer to the current character\n    const char* cursor;\n    /// pointer past the last character\n    const char* const limit;\n};\n\ntemplate<typename WideStringType, size_t T>\nstruct wide_string_input_helper\n{\n    // UTF-32\n    static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)\n    {\n        utf8_bytes_index = 0;\n\n        if (current_wchar == str.size())\n        {\n            utf8_bytes[0] = std::char_traits<char>::eof();\n            utf8_bytes_filled = 1;\n        }\n        else\n        {\n            // get the current character\n            const auto wc = static_cast<int>(str[current_wchar++]);\n\n            // UTF-32 to UTF-8 encoding\n            if (wc < 0x80)\n            {\n                utf8_bytes[0] = wc;\n                utf8_bytes_filled = 1;\n            }\n            else if (wc <= 0x7FF)\n            {\n                utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);\n                utf8_bytes[1] = 0x80 | (wc & 0x3F);\n                utf8_bytes_filled = 2;\n            }\n            else if (wc <= 0xFFFF)\n            {\n                utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);\n                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);\n                utf8_bytes[2] = 0x80 | (wc & 0x3F);\n                utf8_bytes_filled = 3;\n            }\n            else if (wc <= 0x10FFFF)\n            {\n                utf8_bytes[0] = 0xF0 | ((wc >> 18) & 0x07);\n                utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);\n                utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);\n                utf8_bytes[3] = 0x80 | (wc & 0x3F);\n                utf8_bytes_filled = 4;\n            }\n            else\n            {\n                // unknown character\n                utf8_bytes[0] = wc;\n                utf8_bytes_filled = 1;\n            }\n        }\n    }\n};\n\ntemplate<typename WideStringType>\nstruct wide_string_input_helper<WideStringType, 2>\n{\n    // UTF-16\n    static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)\n    {\n        utf8_bytes_index = 0;\n\n        if (current_wchar == str.size())\n        {\n            utf8_bytes[0] = std::char_traits<char>::eof();\n            utf8_bytes_filled = 1;\n        }\n        else\n        {\n            // get the current character\n            const auto wc = static_cast<int>(str[current_wchar++]);\n\n            // UTF-16 to UTF-8 encoding\n            if (wc < 0x80)\n            {\n                utf8_bytes[0] = wc;\n                utf8_bytes_filled = 1;\n            }\n            else if (wc <= 0x7FF)\n            {\n                utf8_bytes[0] = 0xC0 | ((wc >> 6));\n                utf8_bytes[1] = 0x80 | (wc & 0x3F);\n                utf8_bytes_filled = 2;\n            }\n            else if (0xD800 > wc or wc >= 0xE000)\n            {\n                utf8_bytes[0] = 0xE0 | ((wc >> 12));\n                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);\n                utf8_bytes[2] = 0x80 | (wc & 0x3F);\n                utf8_bytes_filled = 3;\n            }\n            else\n            {\n                if (current_wchar < str.size())\n                {\n                    const auto wc2 = static_cast<int>(str[current_wchar++]);\n                    const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));\n                    utf8_bytes[0] = 0xf0 | (charcode >> 18);\n                    utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);\n                    utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);\n                    utf8_bytes[3] = 0x80 | (charcode & 0x3F);\n                    utf8_bytes_filled = 4;\n                }\n                else\n                {\n                    // unknown character\n                    ++current_wchar;\n                    utf8_bytes[0] = wc;\n                    utf8_bytes_filled = 1;\n                }\n            }\n        }\n    }\n};\n\ntemplate<typename WideStringType>\nclass wide_string_input_adapter : public input_adapter_protocol\n{\n  public:\n    explicit wide_string_input_adapter(const WideStringType& w)  noexcept\n        : str(w)\n    {}\n\n    std::char_traits<char>::int_type get_character() noexcept override\n    {\n        // check if buffer needs to be filled\n        if (utf8_bytes_index == utf8_bytes_filled)\n        {\n            fill_buffer<sizeof(typename WideStringType::value_type)>();\n\n            assert(utf8_bytes_filled > 0);\n            assert(utf8_bytes_index == 0);\n        }\n\n        // use buffer\n        assert(utf8_bytes_filled > 0);\n        assert(utf8_bytes_index < utf8_bytes_filled);\n        return utf8_bytes[utf8_bytes_index++];\n    }\n\n  private:\n    template<size_t T>\n    void fill_buffer()\n    {\n        wide_string_input_helper<WideStringType, T>::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);\n    }\n\n    /// the wstring to process\n    const WideStringType& str;\n\n    /// index of the current wchar in str\n    std::size_t current_wchar = 0;\n\n    /// a buffer for UTF-8 bytes\n    std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};\n\n    /// index to the utf8_codes array for the next valid byte\n    std::size_t utf8_bytes_index = 0;\n    /// number of valid bytes in the utf8_codes array\n    std::size_t utf8_bytes_filled = 0;\n};\n\nclass input_adapter\n{\n  public:\n    // native support\n    input_adapter(std::FILE* file)\n        : ia(std::make_shared<file_input_adapter>(file)) {}\n    /// input adapter for input stream\n    input_adapter(std::istream& i)\n        : ia(std::make_shared<input_stream_adapter>(i)) {}\n\n    /// input adapter for input stream\n    input_adapter(std::istream&& i)\n        : ia(std::make_shared<input_stream_adapter>(i)) {}\n\n    input_adapter(const std::wstring& ws)\n        : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}\n\n    input_adapter(const std::u16string& ws)\n        : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}\n\n    input_adapter(const std::u32string& ws)\n        : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}\n\n    /// input adapter for buffer\n    template<typename CharT,\n             typename std::enable_if<\n                 std::is_pointer<CharT>::value and\n                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and\n                 sizeof(typename std::remove_pointer<CharT>::type) == 1,\n                 int>::type = 0>\n    input_adapter(CharT b, std::size_t l)\n        : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}\n\n    // derived support\n\n    /// input adapter for string literal\n    template<typename CharT,\n             typename std::enable_if<\n                 std::is_pointer<CharT>::value and\n                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and\n                 sizeof(typename std::remove_pointer<CharT>::type) == 1,\n                 int>::type = 0>\n    input_adapter(CharT b)\n        : input_adapter(reinterpret_cast<const char*>(b),\n                        std::strlen(reinterpret_cast<const char*>(b))) {}\n\n    /// input adapter for iterator range with contiguous storage\n    template<class IteratorType,\n             typename std::enable_if<\n                 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,\n                 int>::type = 0>\n    input_adapter(IteratorType first, IteratorType last)\n    {\n#ifndef NDEBUG\n        // assertion to check that the iterator range is indeed contiguous,\n        // see http://stackoverflow.com/a/35008842/266378 for more discussion\n        const auto is_contiguous = std::accumulate(\n                                       first, last, std::pair<bool, int>(true, 0),\n                                       [&first](std::pair<bool, int> res, decltype(*first) val)\n        {\n            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));\n            return res;\n        }).first;\n        assert(is_contiguous);\n#endif\n\n        // assertion to check that each element is 1 byte long\n        static_assert(\n            sizeof(typename iterator_traits<IteratorType>::value_type) == 1,\n            \"each element in the iterator range must have the size of 1 byte\");\n\n        const auto len = static_cast<size_t>(std::distance(first, last));\n        if (JSON_LIKELY(len > 0))\n        {\n            // there is at least one element: use the address of first\n            ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);\n        }\n        else\n        {\n            // the address of first cannot be used: use nullptr\n            ia = std::make_shared<input_buffer_adapter>(nullptr, len);\n        }\n    }\n\n    /// input adapter for array\n    template<class T, std::size_t N>\n    input_adapter(T (&array)[N])\n        : input_adapter(std::begin(array), std::end(array)) {}\n\n    /// input adapter for contiguous container\n    template<class ContiguousContainer, typename\n             std::enable_if<not std::is_pointer<ContiguousContainer>::value and\n                            std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,\n                            int>::type = 0>\n    input_adapter(const ContiguousContainer& c)\n        : input_adapter(std::begin(c), std::end(c)) {}\n\n    operator input_adapter_t()\n    {\n        return ia;\n    }\n\n  private:\n    /// the actual adapter\n    input_adapter_t ia = nullptr;\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/input/lexer.hpp>\n\n\n#include <clocale> // localeconv\n#include <cstddef> // size_t\n#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull\n#include <cstdio> // snprintf\n#include <initializer_list> // initializer_list\n#include <string> // char_traits, string\n#include <vector> // vector\n\n// #include <nlohmann/detail/macro_scope.hpp>\n\n// #include <nlohmann/detail/input/input_adapters.hpp>\n\n// #include <nlohmann/detail/input/position_t.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\n///////////\n// lexer //\n///////////\n\n/*!\n@brief lexical analysis\n\nThis class organizes the lexical analysis during JSON deserialization.\n*/\ntemplate<typename BasicJsonType>\nclass lexer\n{\n    using number_integer_t = typename BasicJsonType::number_integer_t;\n    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n    using number_float_t = typename BasicJsonType::number_float_t;\n    using string_t = typename BasicJsonType::string_t;\n\n  public:\n    /// token types for the parser\n    enum class token_type\n    {\n        uninitialized,    ///< indicating the scanner is uninitialized\n        literal_true,     ///< the `true` literal\n        literal_false,    ///< the `false` literal\n        literal_null,     ///< the `null` literal\n        value_string,     ///< a string -- use get_string() for actual value\n        value_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value\n        value_integer,    ///< a signed integer -- use get_number_integer() for actual value\n        value_float,      ///< an floating point number -- use get_number_float() for actual value\n        begin_array,      ///< the character for array begin `[`\n        begin_object,     ///< the character for object begin `{`\n        end_array,        ///< the character for array end `]`\n        end_object,       ///< the character for object end `}`\n        name_separator,   ///< the name separator `:`\n        value_separator,  ///< the value separator `,`\n        parse_error,      ///< indicating a parse error\n        end_of_input,     ///< indicating the end of the input buffer\n        literal_or_value  ///< a literal or the begin of a value (only for diagnostics)\n    };\n\n    /// return name of values of type token_type (only used for errors)\n    static const char* token_type_name(const token_type t) noexcept\n    {\n        switch (t)\n        {\n            case token_type::uninitialized:\n                return \"<uninitialized>\";\n            case token_type::literal_true:\n                return \"true literal\";\n            case token_type::literal_false:\n                return \"false literal\";\n            case token_type::literal_null:\n                return \"null literal\";\n            case token_type::value_string:\n                return \"string literal\";\n            case lexer::token_type::value_unsigned:\n            case lexer::token_type::value_integer:\n            case lexer::token_type::value_float:\n                return \"number literal\";\n            case token_type::begin_array:\n                return \"'['\";\n            case token_type::begin_object:\n                return \"'{'\";\n            case token_type::end_array:\n                return \"']'\";\n            case token_type::end_object:\n                return \"'}'\";\n            case token_type::name_separator:\n                return \"':'\";\n            case token_type::value_separator:\n                return \"','\";\n            case token_type::parse_error:\n                return \"<parse error>\";\n            case token_type::end_of_input:\n                return \"end of input\";\n            case token_type::literal_or_value:\n                return \"'[', '{', or a literal\";\n            // LCOV_EXCL_START\n            default: // catch non-enum values\n                return \"unknown token\";\n                // LCOV_EXCL_STOP\n        }\n    }\n\n    explicit lexer(detail::input_adapter_t&& adapter)\n        : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}\n\n    // delete because of pointer members\n    lexer(const lexer&) = delete;\n    lexer(lexer&&) = delete;\n    lexer& operator=(lexer&) = delete;\n    lexer& operator=(lexer&&) = delete;\n    ~lexer() = default;\n\n  private:\n    /////////////////////\n    // locales\n    /////////////////////\n\n    /// return the locale-dependent decimal point\n    static char get_decimal_point() noexcept\n    {\n        const auto loc = localeconv();\n        assert(loc != nullptr);\n        return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);\n    }\n\n    /////////////////////\n    // scan functions\n    /////////////////////\n\n    /*!\n    @brief get codepoint from 4 hex characters following `\\u`\n\n    For input \"\\u c1 c2 c3 c4\" the codepoint is:\n      (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4\n    = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)\n\n    Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'\n    must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The\n    conversion is done by subtracting the offset (0x30, 0x37, and 0x57)\n    between the ASCII value of the character and the desired integer value.\n\n    @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or\n            non-hex character)\n    */\n    int get_codepoint()\n    {\n        // this function only makes sense after reading `\\u`\n        assert(current == 'u');\n        int codepoint = 0;\n\n        const auto factors = { 12, 8, 4, 0 };\n        for (const auto factor : factors)\n        {\n            get();\n\n            if (current >= '0' and current <= '9')\n            {\n                codepoint += ((current - 0x30) << factor);\n            }\n            else if (current >= 'A' and current <= 'F')\n            {\n                codepoint += ((current - 0x37) << factor);\n            }\n            else if (current >= 'a' and current <= 'f')\n            {\n                codepoint += ((current - 0x57) << factor);\n            }\n            else\n            {\n                return -1;\n            }\n        }\n\n        assert(0x0000 <= codepoint and codepoint <= 0xFFFF);\n        return codepoint;\n    }\n\n    /*!\n    @brief check if the next byte(s) are inside a given range\n\n    Adds the current byte and, for each passed range, reads a new byte and\n    checks if it is inside the range. If a violation was detected, set up an\n    error message and return false. Otherwise, return true.\n\n    @param[in] ranges  list of integers; interpreted as list of pairs of\n                       inclusive lower and upper bound, respectively\n\n    @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,\n         1, 2, or 3 pairs. This precondition is enforced by an assertion.\n\n    @return true if and only if no range violation was detected\n    */\n    bool next_byte_in_range(std::initializer_list<int> ranges)\n    {\n        assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);\n        add(current);\n\n        for (auto range = ranges.begin(); range != ranges.end(); ++range)\n        {\n            get();\n            if (JSON_LIKELY(*range <= current and current <= *(++range)))\n            {\n                add(current);\n            }\n            else\n            {\n                error_message = \"invalid string: ill-formed UTF-8 byte\";\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /*!\n    @brief scan a string literal\n\n    This function scans a string according to Sect. 7 of RFC 7159. While\n    scanning, bytes are escaped and copied into buffer token_buffer. Then the\n    function returns successfully, token_buffer is *not* null-terminated (as it\n    may contain \\0 bytes), and token_buffer.size() is the number of bytes in the\n    string.\n\n    @return token_type::value_string if string could be successfully scanned,\n            token_type::parse_error otherwise\n\n    @note In case of errors, variable error_message contains a textual\n          description.\n    */\n    token_type scan_string()\n    {\n        // reset token_buffer (ignore opening quote)\n        reset();\n\n        // we entered the function by reading an open quote\n        assert(current == '\\\"');\n\n        while (true)\n        {\n            // get next character\n            switch (get())\n            {\n                // end of file while parsing string\n                case std::char_traits<char>::eof():\n                {\n                    error_message = \"invalid string: missing closing quote\";\n                    return token_type::parse_error;\n                }\n\n                // closing quote\n                case '\\\"':\n                {\n                    return token_type::value_string;\n                }\n\n                // escapes\n                case '\\\\':\n                {\n                    switch (get())\n                    {\n                        // quotation mark\n                        case '\\\"':\n                            add('\\\"');\n                            break;\n                        // reverse solidus\n                        case '\\\\':\n                            add('\\\\');\n                            break;\n                        // solidus\n                        case '/':\n                            add('/');\n                            break;\n                        // backspace\n                        case 'b':\n                            add('\\b');\n                            break;\n                        // form feed\n                        case 'f':\n                            add('\\f');\n                            break;\n                        // line feed\n                        case 'n':\n                            add('\\n');\n                            break;\n                        // carriage return\n                        case 'r':\n                            add('\\r');\n                            break;\n                        // tab\n                        case 't':\n                            add('\\t');\n                            break;\n\n                        // unicode escapes\n                        case 'u':\n                        {\n                            const int codepoint1 = get_codepoint();\n                            int codepoint = codepoint1; // start with codepoint1\n\n                            if (JSON_UNLIKELY(codepoint1 == -1))\n                            {\n                                error_message = \"invalid string: '\\\\u' must be followed by 4 hex digits\";\n                                return token_type::parse_error;\n                            }\n\n                            // check if code point is a high surrogate\n                            if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)\n                            {\n                                // expect next \\uxxxx entry\n                                if (JSON_LIKELY(get() == '\\\\' and get() == 'u'))\n                                {\n                                    const int codepoint2 = get_codepoint();\n\n                                    if (JSON_UNLIKELY(codepoint2 == -1))\n                                    {\n                                        error_message = \"invalid string: '\\\\u' must be followed by 4 hex digits\";\n                                        return token_type::parse_error;\n                                    }\n\n                                    // check if codepoint2 is a low surrogate\n                                    if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))\n                                    {\n                                        // overwrite codepoint\n                                        codepoint =\n                                            // high surrogate occupies the most significant 22 bits\n                                            (codepoint1 << 10)\n                                            // low surrogate occupies the least significant 15 bits\n                                            + codepoint2\n                                            // there is still the 0xD800, 0xDC00 and 0x10000 noise\n                                            // in the result so we have to subtract with:\n                                            // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00\n                                            - 0x35FDC00;\n                                    }\n                                    else\n                                    {\n                                        error_message = \"invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF\";\n                                        return token_type::parse_error;\n                                    }\n                                }\n                                else\n                                {\n                                    error_message = \"invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF\";\n                                    return token_type::parse_error;\n                                }\n                            }\n                            else\n                            {\n                                if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))\n                                {\n                                    error_message = \"invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF\";\n                                    return token_type::parse_error;\n                                }\n                            }\n\n                            // result of the above calculation yields a proper codepoint\n                            assert(0x00 <= codepoint and codepoint <= 0x10FFFF);\n\n                            // translate codepoint into bytes\n                            if (codepoint < 0x80)\n                            {\n                                // 1-byte characters: 0xxxxxxx (ASCII)\n                                add(codepoint);\n                            }\n                            else if (codepoint <= 0x7FF)\n                            {\n                                // 2-byte characters: 110xxxxx 10xxxxxx\n                                add(0xC0 | (codepoint >> 6));\n                                add(0x80 | (codepoint & 0x3F));\n                            }\n                            else if (codepoint <= 0xFFFF)\n                            {\n                                // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx\n                                add(0xE0 | (codepoint >> 12));\n                                add(0x80 | ((codepoint >> 6) & 0x3F));\n                                add(0x80 | (codepoint & 0x3F));\n                            }\n                            else\n                            {\n                                // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\n                                add(0xF0 | (codepoint >> 18));\n                                add(0x80 | ((codepoint >> 12) & 0x3F));\n                                add(0x80 | ((codepoint >> 6) & 0x3F));\n                                add(0x80 | (codepoint & 0x3F));\n                            }\n\n                            break;\n                        }\n\n                        // other characters after escape\n                        default:\n                            error_message = \"invalid string: forbidden character after backslash\";\n                            return token_type::parse_error;\n                    }\n\n                    break;\n                }\n\n                // invalid control characters\n                case 0x00:\n                {\n                    error_message = \"invalid string: control character U+0000 (NUL) must be escaped to \\\\u0000\";\n                    return token_type::parse_error;\n                }\n\n                case 0x01:\n                {\n                    error_message = \"invalid string: control character U+0001 (SOH) must be escaped to \\\\u0001\";\n                    return token_type::parse_error;\n                }\n\n                case 0x02:\n                {\n                    error_message = \"invalid string: control character U+0002 (STX) must be escaped to \\\\u0002\";\n                    return token_type::parse_error;\n                }\n\n                case 0x03:\n                {\n                    error_message = \"invalid string: control character U+0003 (ETX) must be escaped to \\\\u0003\";\n                    return token_type::parse_error;\n                }\n\n                case 0x04:\n                {\n                    error_message = \"invalid string: control character U+0004 (EOT) must be escaped to \\\\u0004\";\n                    return token_type::parse_error;\n                }\n\n                case 0x05:\n                {\n                    error_message = \"invalid string: control character U+0005 (ENQ) must be escaped to \\\\u0005\";\n                    return token_type::parse_error;\n                }\n\n                case 0x06:\n                {\n                    error_message = \"invalid string: control character U+0006 (ACK) must be escaped to \\\\u0006\";\n                    return token_type::parse_error;\n                }\n\n                case 0x07:\n                {\n                    error_message = \"invalid string: control character U+0007 (BEL) must be escaped to \\\\u0007\";\n                    return token_type::parse_error;\n                }\n\n                case 0x08:\n                {\n                    error_message = \"invalid string: control character U+0008 (BS) must be escaped to \\\\u0008 or \\\\b\";\n                    return token_type::parse_error;\n                }\n\n                case 0x09:\n                {\n                    error_message = \"invalid string: control character U+0009 (HT) must be escaped to \\\\u0009 or \\\\t\";\n                    return token_type::parse_error;\n                }\n\n                case 0x0A:\n                {\n                    error_message = \"invalid string: control character U+000A (LF) must be escaped to \\\\u000A or \\\\n\";\n                    return token_type::parse_error;\n                }\n\n                case 0x0B:\n                {\n                    error_message = \"invalid string: control character U+000B (VT) must be escaped to \\\\u000B\";\n                    return token_type::parse_error;\n                }\n\n                case 0x0C:\n                {\n                    error_message = \"invalid string: control character U+000C (FF) must be escaped to \\\\u000C or \\\\f\";\n                    return token_type::parse_error;\n                }\n\n                case 0x0D:\n                {\n                    error_message = \"invalid string: control character U+000D (CR) must be escaped to \\\\u000D or \\\\r\";\n                    return token_type::parse_error;\n                }\n\n                case 0x0E:\n                {\n                    error_message = \"invalid string: control character U+000E (SO) must be escaped to \\\\u000E\";\n                    return token_type::parse_error;\n                }\n\n                case 0x0F:\n                {\n                    error_message = \"invalid string: control character U+000F (SI) must be escaped to \\\\u000F\";\n                    return token_type::parse_error;\n                }\n\n                case 0x10:\n                {\n                    error_message = \"invalid string: control character U+0010 (DLE) must be escaped to \\\\u0010\";\n                    return token_type::parse_error;\n                }\n\n                case 0x11:\n                {\n                    error_message = \"invalid string: control character U+0011 (DC1) must be escaped to \\\\u0011\";\n                    return token_type::parse_error;\n                }\n\n                case 0x12:\n                {\n                    error_message = \"invalid string: control character U+0012 (DC2) must be escaped to \\\\u0012\";\n                    return token_type::parse_error;\n                }\n\n                case 0x13:\n                {\n                    error_message = \"invalid string: control character U+0013 (DC3) must be escaped to \\\\u0013\";\n                    return token_type::parse_error;\n                }\n\n                case 0x14:\n                {\n                    error_message = \"invalid string: control character U+0014 (DC4) must be escaped to \\\\u0014\";\n                    return token_type::parse_error;\n                }\n\n                case 0x15:\n                {\n                    error_message = \"invalid string: control character U+0015 (NAK) must be escaped to \\\\u0015\";\n                    return token_type::parse_error;\n                }\n\n                case 0x16:\n                {\n                    error_message = \"invalid string: control character U+0016 (SYN) must be escaped to \\\\u0016\";\n                    return token_type::parse_error;\n                }\n\n                case 0x17:\n                {\n                    error_message = \"invalid string: control character U+0017 (ETB) must be escaped to \\\\u0017\";\n                    return token_type::parse_error;\n                }\n\n                case 0x18:\n                {\n                    error_message = \"invalid string: control character U+0018 (CAN) must be escaped to \\\\u0018\";\n                    return token_type::parse_error;\n                }\n\n                case 0x19:\n                {\n                    error_message = \"invalid string: control character U+0019 (EM) must be escaped to \\\\u0019\";\n                    return token_type::parse_error;\n                }\n\n                case 0x1A:\n                {\n                    error_message = \"invalid string: control character U+001A (SUB) must be escaped to \\\\u001A\";\n                    return token_type::parse_error;\n                }\n\n                case 0x1B:\n                {\n                    error_message = \"invalid string: control character U+001B (ESC) must be escaped to \\\\u001B\";\n                    return token_type::parse_error;\n                }\n\n                case 0x1C:\n                {\n                    error_message = \"invalid string: control character U+001C (FS) must be escaped to \\\\u001C\";\n                    return token_type::parse_error;\n                }\n\n                case 0x1D:\n                {\n                    error_message = \"invalid string: control character U+001D (GS) must be escaped to \\\\u001D\";\n                    return token_type::parse_error;\n                }\n\n                case 0x1E:\n                {\n                    error_message = \"invalid string: control character U+001E (RS) must be escaped to \\\\u001E\";\n                    return token_type::parse_error;\n                }\n\n                case 0x1F:\n                {\n                    error_message = \"invalid string: control character U+001F (US) must be escaped to \\\\u001F\";\n                    return token_type::parse_error;\n                }\n\n                // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))\n                case 0x20:\n                case 0x21:\n                case 0x23:\n                case 0x24:\n                case 0x25:\n                case 0x26:\n                case 0x27:\n                case 0x28:\n                case 0x29:\n                case 0x2A:\n                case 0x2B:\n                case 0x2C:\n                case 0x2D:\n                case 0x2E:\n                case 0x2F:\n                case 0x30:\n                case 0x31:\n                case 0x32:\n                case 0x33:\n                case 0x34:\n                case 0x35:\n                case 0x36:\n                case 0x37:\n                case 0x38:\n                case 0x39:\n                case 0x3A:\n                case 0x3B:\n                case 0x3C:\n                case 0x3D:\n                case 0x3E:\n                case 0x3F:\n                case 0x40:\n                case 0x41:\n                case 0x42:\n                case 0x43:\n                case 0x44:\n                case 0x45:\n                case 0x46:\n                case 0x47:\n                case 0x48:\n                case 0x49:\n                case 0x4A:\n                case 0x4B:\n                case 0x4C:\n                case 0x4D:\n                case 0x4E:\n                case 0x4F:\n                case 0x50:\n                case 0x51:\n                case 0x52:\n                case 0x53:\n                case 0x54:\n                case 0x55:\n                case 0x56:\n                case 0x57:\n                case 0x58:\n                case 0x59:\n                case 0x5A:\n                case 0x5B:\n                case 0x5D:\n                case 0x5E:\n                case 0x5F:\n                case 0x60:\n                case 0x61:\n                case 0x62:\n                case 0x63:\n                case 0x64:\n                case 0x65:\n                case 0x66:\n                case 0x67:\n                case 0x68:\n                case 0x69:\n                case 0x6A:\n                case 0x6B:\n                case 0x6C:\n                case 0x6D:\n                case 0x6E:\n                case 0x6F:\n                case 0x70:\n                case 0x71:\n                case 0x72:\n                case 0x73:\n                case 0x74:\n                case 0x75:\n                case 0x76:\n                case 0x77:\n                case 0x78:\n                case 0x79:\n                case 0x7A:\n                case 0x7B:\n                case 0x7C:\n                case 0x7D:\n                case 0x7E:\n                case 0x7F:\n                {\n                    add(current);\n                    break;\n                }\n\n                // U+0080..U+07FF: bytes C2..DF 80..BF\n                case 0xC2:\n                case 0xC3:\n                case 0xC4:\n                case 0xC5:\n                case 0xC6:\n                case 0xC7:\n                case 0xC8:\n                case 0xC9:\n                case 0xCA:\n                case 0xCB:\n                case 0xCC:\n                case 0xCD:\n                case 0xCE:\n                case 0xCF:\n                case 0xD0:\n                case 0xD1:\n                case 0xD2:\n                case 0xD3:\n                case 0xD4:\n                case 0xD5:\n                case 0xD6:\n                case 0xD7:\n                case 0xD8:\n                case 0xD9:\n                case 0xDA:\n                case 0xDB:\n                case 0xDC:\n                case 0xDD:\n                case 0xDE:\n                case 0xDF:\n                {\n                    if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))\n                    {\n                        return token_type::parse_error;\n                    }\n                    break;\n                }\n\n                // U+0800..U+0FFF: bytes E0 A0..BF 80..BF\n                case 0xE0:\n                {\n                    if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))\n                    {\n                        return token_type::parse_error;\n                    }\n                    break;\n                }\n\n                // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF\n                // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF\n                case 0xE1:\n                case 0xE2:\n                case 0xE3:\n                case 0xE4:\n                case 0xE5:\n                case 0xE6:\n                case 0xE7:\n                case 0xE8:\n                case 0xE9:\n                case 0xEA:\n                case 0xEB:\n                case 0xEC:\n                case 0xEE:\n                case 0xEF:\n                {\n                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))\n                    {\n                        return token_type::parse_error;\n                    }\n                    break;\n                }\n\n                // U+D000..U+D7FF: bytes ED 80..9F 80..BF\n                case 0xED:\n                {\n                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))\n                    {\n                        return token_type::parse_error;\n                    }\n                    break;\n                }\n\n                // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF\n                case 0xF0:\n                {\n                    if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))\n                    {\n                        return token_type::parse_error;\n                    }\n                    break;\n                }\n\n                // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF\n                case 0xF1:\n                case 0xF2:\n                case 0xF3:\n                {\n                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))\n                    {\n                        return token_type::parse_error;\n                    }\n                    break;\n                }\n\n                // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF\n                case 0xF4:\n                {\n                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))\n                    {\n                        return token_type::parse_error;\n                    }\n                    break;\n                }\n\n                // remaining bytes (80..C1 and F5..FF) are ill-formed\n                default:\n                {\n                    error_message = \"invalid string: ill-formed UTF-8 byte\";\n                    return token_type::parse_error;\n                }\n            }\n        }\n    }\n\n    static void strtof(float& f, const char* str, char** endptr) noexcept\n    {\n        f = std::strtof(str, endptr);\n    }\n\n    static void strtof(double& f, const char* str, char** endptr) noexcept\n    {\n        f = std::strtod(str, endptr);\n    }\n\n    static void strtof(long double& f, const char* str, char** endptr) noexcept\n    {\n        f = std::strtold(str, endptr);\n    }\n\n    /*!\n    @brief scan a number literal\n\n    This function scans a string according to Sect. 6 of RFC 7159.\n\n    The function is realized with a deterministic finite state machine derived\n    from the grammar described in RFC 7159. Starting in state \"init\", the\n    input is read and used to determined the next state. Only state \"done\"\n    accepts the number. State \"error\" is a trap state to model errors. In the\n    table below, \"anything\" means any character but the ones listed before.\n\n    state    | 0        | 1-9      | e E      | +       | -       | .        | anything\n    ---------|----------|----------|----------|---------|---------|----------|-----------\n    init     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error]\n    minus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error]\n    zero     | done     | done     | exponent | done    | done    | decimal1 | done\n    any1     | any1     | any1     | exponent | done    | done    | decimal1 | done\n    decimal1 | decimal2 | [error]  | [error]  | [error] | [error] | [error]  | [error]\n    decimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done\n    exponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error]\n    sign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error]\n    any2     | any2     | any2     | done     | done    | done    | done     | done\n\n    The state machine is realized with one label per state (prefixed with\n    \"scan_number_\") and `goto` statements between them. The state machine\n    contains cycles, but any cycle can be left when EOF is read. Therefore,\n    the function is guaranteed to terminate.\n\n    During scanning, the read bytes are stored in token_buffer. This string is\n    then converted to a signed integer, an unsigned integer, or a\n    floating-point number.\n\n    @return token_type::value_unsigned, token_type::value_integer, or\n            token_type::value_float if number could be successfully scanned,\n            token_type::parse_error otherwise\n\n    @note The scanner is independent of the current locale. Internally, the\n          locale's decimal point is used instead of `.` to work with the\n          locale-dependent converters.\n    */\n    token_type scan_number()  // lgtm [cpp/use-of-goto]\n    {\n        // reset token_buffer to store the number's bytes\n        reset();\n\n        // the type of the parsed number; initially set to unsigned; will be\n        // changed if minus sign, decimal point or exponent is read\n        token_type number_type = token_type::value_unsigned;\n\n        // state (init): we just found out we need to scan a number\n        switch (current)\n        {\n            case '-':\n            {\n                add(current);\n                goto scan_number_minus;\n            }\n\n            case '0':\n            {\n                add(current);\n                goto scan_number_zero;\n            }\n\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7':\n            case '8':\n            case '9':\n            {\n                add(current);\n                goto scan_number_any1;\n            }\n\n            // LCOV_EXCL_START\n            default:\n            {\n                // all other characters are rejected outside scan_number()\n                assert(false);\n            }\n                // LCOV_EXCL_STOP\n        }\n\nscan_number_minus:\n        // state: we just parsed a leading minus sign\n        number_type = token_type::value_integer;\n        switch (get())\n        {\n            case '0':\n            {\n                add(current);\n                goto scan_number_zero;\n            }\n\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7':\n            case '8':\n            case '9':\n            {\n                add(current);\n                goto scan_number_any1;\n            }\n\n            default:\n            {\n                error_message = \"invalid number; expected digit after '-'\";\n                return token_type::parse_error;\n            }\n        }\n\nscan_number_zero:\n        // state: we just parse a zero (maybe with a leading minus sign)\n        switch (get())\n        {\n            case '.':\n            {\n                add(decimal_point_char);\n                goto scan_number_decimal1;\n            }\n\n            case 'e':\n            case 'E':\n            {\n                add(current);\n                goto scan_number_exponent;\n            }\n\n            default:\n                goto scan_number_done;\n        }\n\nscan_number_any1:\n        // state: we just parsed a number 0-9 (maybe with a leading minus sign)\n        switch (get())\n        {\n            case '0':\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7':\n            case '8':\n            case '9':\n            {\n                add(current);\n                goto scan_number_any1;\n            }\n\n            case '.':\n            {\n                add(decimal_point_char);\n                goto scan_number_decimal1;\n            }\n\n            case 'e':\n            case 'E':\n            {\n                add(current);\n                goto scan_number_exponent;\n            }\n\n            default:\n                goto scan_number_done;\n        }\n\nscan_number_decimal1:\n        // state: we just parsed a decimal point\n        number_type = token_type::value_float;\n        switch (get())\n        {\n            case '0':\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7':\n            case '8':\n            case '9':\n            {\n                add(current);\n                goto scan_number_decimal2;\n            }\n\n            default:\n            {\n                error_message = \"invalid number; expected digit after '.'\";\n                return token_type::parse_error;\n            }\n        }\n\nscan_number_decimal2:\n        // we just parsed at least one number after a decimal point\n        switch (get())\n        {\n            case '0':\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7':\n            case '8':\n            case '9':\n            {\n                add(current);\n                goto scan_number_decimal2;\n            }\n\n            case 'e':\n            case 'E':\n            {\n                add(current);\n                goto scan_number_exponent;\n            }\n\n            default:\n                goto scan_number_done;\n        }\n\nscan_number_exponent:\n        // we just parsed an exponent\n        number_type = token_type::value_float;\n        switch (get())\n        {\n            case '+':\n            case '-':\n            {\n                add(current);\n                goto scan_number_sign;\n            }\n\n            case '0':\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7':\n            case '8':\n            case '9':\n            {\n                add(current);\n                goto scan_number_any2;\n            }\n\n            default:\n            {\n                error_message =\n                    \"invalid number; expected '+', '-', or digit after exponent\";\n                return token_type::parse_error;\n            }\n        }\n\nscan_number_sign:\n        // we just parsed an exponent sign\n        switch (get())\n        {\n            case '0':\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7':\n            case '8':\n            case '9':\n            {\n                add(current);\n                goto scan_number_any2;\n            }\n\n            default:\n            {\n                error_message = \"invalid number; expected digit after exponent sign\";\n                return token_type::parse_error;\n            }\n        }\n\nscan_number_any2:\n        // we just parsed a number after the exponent or exponent sign\n        switch (get())\n        {\n            case '0':\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7':\n            case '8':\n            case '9':\n            {\n                add(current);\n                goto scan_number_any2;\n            }\n\n            default:\n                goto scan_number_done;\n        }\n\nscan_number_done:\n        // unget the character after the number (we only read it to know that\n        // we are done scanning a number)\n        unget();\n\n        char* endptr = nullptr;\n        errno = 0;\n\n        // try to parse integers first and fall back to floats\n        if (number_type == token_type::value_unsigned)\n        {\n            const auto x = std::strtoull(token_buffer.data(), &endptr, 10);\n\n            // we checked the number format before\n            assert(endptr == token_buffer.data() + token_buffer.size());\n\n            if (errno == 0)\n            {\n                value_unsigned = static_cast<number_unsigned_t>(x);\n                if (value_unsigned == x)\n                {\n                    return token_type::value_unsigned;\n                }\n            }\n        }\n        else if (number_type == token_type::value_integer)\n        {\n            const auto x = std::strtoll(token_buffer.data(), &endptr, 10);\n\n            // we checked the number format before\n            assert(endptr == token_buffer.data() + token_buffer.size());\n\n            if (errno == 0)\n            {\n                value_integer = static_cast<number_integer_t>(x);\n                if (value_integer == x)\n                {\n                    return token_type::value_integer;\n                }\n            }\n        }\n\n        // this code is reached if we parse a floating-point number or if an\n        // integer conversion above failed\n        strtof(value_float, token_buffer.data(), &endptr);\n\n        // we checked the number format before\n        assert(endptr == token_buffer.data() + token_buffer.size());\n\n        return token_type::value_float;\n    }\n\n    /*!\n    @param[in] literal_text  the literal text to expect\n    @param[in] length        the length of the passed literal text\n    @param[in] return_type   the token type to return on success\n    */\n    token_type scan_literal(const char* literal_text, const std::size_t length,\n                            token_type return_type)\n    {\n        assert(current == literal_text[0]);\n        for (std::size_t i = 1; i < length; ++i)\n        {\n            if (JSON_UNLIKELY(get() != literal_text[i]))\n            {\n                error_message = \"invalid literal\";\n                return token_type::parse_error;\n            }\n        }\n        return return_type;\n    }\n\n    /////////////////////\n    // input management\n    /////////////////////\n\n    /// reset token_buffer; current character is beginning of token\n    void reset() noexcept\n    {\n        token_buffer.clear();\n        token_string.clear();\n        token_string.push_back(std::char_traits<char>::to_char_type(current));\n    }\n\n    /*\n    @brief get next character from the input\n\n    This function provides the interface to the used input adapter. It does\n    not throw in case the input reached EOF, but returns a\n    `std::char_traits<char>::eof()` in that case.  Stores the scanned characters\n    for use in error messages.\n\n    @return character read from the input\n    */\n    std::char_traits<char>::int_type get()\n    {\n        ++position.chars_read_total;\n        ++position.chars_read_current_line;\n\n        if (next_unget)\n        {\n            // just reset the next_unget variable and work with current\n            next_unget = false;\n        }\n        else\n        {\n            current = ia->get_character();\n        }\n\n        if (JSON_LIKELY(current != std::char_traits<char>::eof()))\n        {\n            token_string.push_back(std::char_traits<char>::to_char_type(current));\n        }\n\n        if (current == '\\n')\n        {\n            ++position.lines_read;\n            position.chars_read_current_line = 0;\n        }\n\n        return current;\n    }\n\n    /*!\n    @brief unget current character (read it again on next get)\n\n    We implement unget by setting variable next_unget to true. The input is not\n    changed - we just simulate ungetting by modifying chars_read_total,\n    chars_read_current_line, and token_string. The next call to get() will\n    behave as if the unget character is read again.\n    */\n    void unget()\n    {\n        next_unget = true;\n\n        --position.chars_read_total;\n\n        // in case we \"unget\" a newline, we have to also decrement the lines_read\n        if (position.chars_read_current_line == 0)\n        {\n            if (position.lines_read > 0)\n            {\n                --position.lines_read;\n            }\n        }\n        else\n        {\n            --position.chars_read_current_line;\n        }\n\n        if (JSON_LIKELY(current != std::char_traits<char>::eof()))\n        {\n            assert(token_string.size() != 0);\n            token_string.pop_back();\n        }\n    }\n\n    /// add a character to token_buffer\n    void add(int c)\n    {\n        token_buffer.push_back(std::char_traits<char>::to_char_type(c));\n    }\n\n  public:\n    /////////////////////\n    // value getters\n    /////////////////////\n\n    /// return integer value\n    constexpr number_integer_t get_number_integer() const noexcept\n    {\n        return value_integer;\n    }\n\n    /// return unsigned integer value\n    constexpr number_unsigned_t get_number_unsigned() const noexcept\n    {\n        return value_unsigned;\n    }\n\n    /// return floating-point value\n    constexpr number_float_t get_number_float() const noexcept\n    {\n        return value_float;\n    }\n\n    /// return current string value (implicitly resets the token; useful only once)\n    string_t& get_string()\n    {\n        return token_buffer;\n    }\n\n    /////////////////////\n    // diagnostics\n    /////////////////////\n\n    /// return position of last read token\n    constexpr position_t get_position() const noexcept\n    {\n        return position;\n    }\n\n    /// return the last read token (for errors only).  Will never contain EOF\n    /// (an arbitrary value that is not a valid char value, often -1), because\n    /// 255 may legitimately occur.  May contain NUL, which should be escaped.\n    std::string get_token_string() const\n    {\n        // escape control characters\n        std::string result;\n        for (const auto c : token_string)\n        {\n            if ('\\x00' <= c and c <= '\\x1F')\n            {\n                // escape control characters\n                char cs[9];\n                (std::snprintf)(cs, 9, \"<U+%.4X>\", static_cast<unsigned char>(c));\n                result += cs;\n            }\n            else\n            {\n                // add character as is\n                result.push_back(c);\n            }\n        }\n\n        return result;\n    }\n\n    /// return syntax error message\n    constexpr const char* get_error_message() const noexcept\n    {\n        return error_message;\n    }\n\n    /////////////////////\n    // actual scanner\n    /////////////////////\n\n    /*!\n    @brief skip the UTF-8 byte order mark\n    @return true iff there is no BOM or the correct BOM has been skipped\n    */\n    bool skip_bom()\n    {\n        if (get() == 0xEF)\n        {\n            // check if we completely parse the BOM\n            return get() == 0xBB and get() == 0xBF;\n        }\n\n        // the first character is not the beginning of the BOM; unget it to\n        // process is later\n        unget();\n        return true;\n    }\n\n    token_type scan()\n    {\n        // initially, skip the BOM\n        if (position.chars_read_total == 0 and not skip_bom())\n        {\n            error_message = \"invalid BOM; must be 0xEF 0xBB 0xBF if given\";\n            return token_type::parse_error;\n        }\n\n        // read next character and ignore whitespace\n        do\n        {\n            get();\n        }\n        while (current == ' ' or current == '\\t' or current == '\\n' or current == '\\r');\n\n        switch (current)\n        {\n            // structural characters\n            case '[':\n                return token_type::begin_array;\n            case ']':\n                return token_type::end_array;\n            case '{':\n                return token_type::begin_object;\n            case '}':\n                return token_type::end_object;\n            case ':':\n                return token_type::name_separator;\n            case ',':\n                return token_type::value_separator;\n\n            // literals\n            case 't':\n                return scan_literal(\"true\", 4, token_type::literal_true);\n            case 'f':\n                return scan_literal(\"false\", 5, token_type::literal_false);\n            case 'n':\n                return scan_literal(\"null\", 4, token_type::literal_null);\n\n            // string\n            case '\\\"':\n                return scan_string();\n\n            // number\n            case '-':\n            case '0':\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7':\n            case '8':\n            case '9':\n                return scan_number();\n\n            // end of input (the null byte is needed when parsing from\n            // string literals)\n            case '\\0':\n            case std::char_traits<char>::eof():\n                return token_type::end_of_input;\n\n            // error\n            default:\n                error_message = \"invalid literal\";\n                return token_type::parse_error;\n        }\n    }\n\n  private:\n    /// input adapter\n    detail::input_adapter_t ia = nullptr;\n\n    /// the current character\n    std::char_traits<char>::int_type current = std::char_traits<char>::eof();\n\n    /// whether the next get() call should just return current\n    bool next_unget = false;\n\n    /// the start position of the current token\n    position_t position;\n\n    /// raw input token string (for error messages)\n    std::vector<char> token_string {};\n\n    /// buffer for variable-length tokens (numbers, strings)\n    string_t token_buffer {};\n\n    /// a description of occurred lexer errors\n    const char* error_message = \"\";\n\n    // number values\n    number_integer_t value_integer = 0;\n    number_unsigned_t value_unsigned = 0;\n    number_float_t value_float = 0;\n\n    /// the decimal point\n    const char decimal_point_char = '.';\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/input/parser.hpp>\n\n\n#include <cassert> // assert\n#include <cmath> // isfinite\n#include <cstdint> // uint8_t\n#include <functional> // function\n#include <string> // string\n#include <utility> // move\n\n// #include <nlohmann/detail/exceptions.hpp>\n\n// #include <nlohmann/detail/macro_scope.hpp>\n\n// #include <nlohmann/detail/meta/is_sax.hpp>\n\n\n#include <cstdint> // size_t\n#include <utility> // declval\n\n// #include <nlohmann/detail/meta/detected.hpp>\n\n// #include <nlohmann/detail/meta/type_traits.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\ntemplate <typename T>\nusing null_function_t = decltype(std::declval<T&>().null());\n\ntemplate <typename T>\nusing boolean_function_t =\n    decltype(std::declval<T&>().boolean(std::declval<bool>()));\n\ntemplate <typename T, typename Integer>\nusing number_integer_function_t =\n    decltype(std::declval<T&>().number_integer(std::declval<Integer>()));\n\ntemplate <typename T, typename Unsigned>\nusing number_unsigned_function_t =\n    decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));\n\ntemplate <typename T, typename Float, typename String>\nusing number_float_function_t = decltype(std::declval<T&>().number_float(\n                                    std::declval<Float>(), std::declval<const String&>()));\n\ntemplate <typename T, typename String>\nusing string_function_t =\n    decltype(std::declval<T&>().string(std::declval<String&>()));\n\ntemplate <typename T>\nusing start_object_function_t =\n    decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));\n\ntemplate <typename T, typename String>\nusing key_function_t =\n    decltype(std::declval<T&>().key(std::declval<String&>()));\n\ntemplate <typename T>\nusing end_object_function_t = decltype(std::declval<T&>().end_object());\n\ntemplate <typename T>\nusing start_array_function_t =\n    decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));\n\ntemplate <typename T>\nusing end_array_function_t = decltype(std::declval<T&>().end_array());\n\ntemplate <typename T, typename Exception>\nusing parse_error_function_t = decltype(std::declval<T&>().parse_error(\n        std::declval<std::size_t>(), std::declval<const std::string&>(),\n        std::declval<const Exception&>()));\n\ntemplate <typename SAX, typename BasicJsonType>\nstruct is_sax\n{\n  private:\n    static_assert(is_basic_json<BasicJsonType>::value,\n                  \"BasicJsonType must be of type basic_json<...>\");\n\n    using number_integer_t = typename BasicJsonType::number_integer_t;\n    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n    using number_float_t = typename BasicJsonType::number_float_t;\n    using string_t = typename BasicJsonType::string_t;\n    using exception_t = typename BasicJsonType::exception;\n\n  public:\n    static constexpr bool value =\n        is_detected_exact<bool, null_function_t, SAX>::value &&\n        is_detected_exact<bool, boolean_function_t, SAX>::value &&\n        is_detected_exact<bool, number_integer_function_t, SAX,\n        number_integer_t>::value &&\n        is_detected_exact<bool, number_unsigned_function_t, SAX,\n        number_unsigned_t>::value &&\n        is_detected_exact<bool, number_float_function_t, SAX, number_float_t,\n        string_t>::value &&\n        is_detected_exact<bool, string_function_t, SAX, string_t>::value &&\n        is_detected_exact<bool, start_object_function_t, SAX>::value &&\n        is_detected_exact<bool, key_function_t, SAX, string_t>::value &&\n        is_detected_exact<bool, end_object_function_t, SAX>::value &&\n        is_detected_exact<bool, start_array_function_t, SAX>::value &&\n        is_detected_exact<bool, end_array_function_t, SAX>::value &&\n        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;\n};\n\ntemplate <typename SAX, typename BasicJsonType>\nstruct is_sax_static_asserts\n{\n  private:\n    static_assert(is_basic_json<BasicJsonType>::value,\n                  \"BasicJsonType must be of type basic_json<...>\");\n\n    using number_integer_t = typename BasicJsonType::number_integer_t;\n    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n    using number_float_t = typename BasicJsonType::number_float_t;\n    using string_t = typename BasicJsonType::string_t;\n    using exception_t = typename BasicJsonType::exception;\n\n  public:\n    static_assert(is_detected_exact<bool, null_function_t, SAX>::value,\n                  \"Missing/invalid function: bool null()\");\n    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,\n                  \"Missing/invalid function: bool boolean(bool)\");\n    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,\n                  \"Missing/invalid function: bool boolean(bool)\");\n    static_assert(\n        is_detected_exact<bool, number_integer_function_t, SAX,\n        number_integer_t>::value,\n        \"Missing/invalid function: bool number_integer(number_integer_t)\");\n    static_assert(\n        is_detected_exact<bool, number_unsigned_function_t, SAX,\n        number_unsigned_t>::value,\n        \"Missing/invalid function: bool number_unsigned(number_unsigned_t)\");\n    static_assert(is_detected_exact<bool, number_float_function_t, SAX,\n                  number_float_t, string_t>::value,\n                  \"Missing/invalid function: bool number_float(number_float_t, const string_t&)\");\n    static_assert(\n        is_detected_exact<bool, string_function_t, SAX, string_t>::value,\n        \"Missing/invalid function: bool string(string_t&)\");\n    static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,\n                  \"Missing/invalid function: bool start_object(std::size_t)\");\n    static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,\n                  \"Missing/invalid function: bool key(string_t&)\");\n    static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,\n                  \"Missing/invalid function: bool end_object()\");\n    static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,\n                  \"Missing/invalid function: bool start_array(std::size_t)\");\n    static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,\n                  \"Missing/invalid function: bool end_array()\");\n    static_assert(\n        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,\n        \"Missing/invalid function: bool parse_error(std::size_t, const \"\n        \"std::string&, const exception&)\");\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/input/input_adapters.hpp>\n\n// #include <nlohmann/detail/input/json_sax.hpp>\n\n\n#include <cassert>\n#include <cstddef>\n#include <string>\n#include <vector>\n\n// #include <nlohmann/detail/exceptions.hpp>\n\n// #include <nlohmann/detail/macro_scope.hpp>\n\n\nnamespace nlohmann\n{\n\n/*!\n@brief SAX interface\n\nThis class describes the SAX interface used by @ref nlohmann::json::sax_parse.\nEach function is called in different situations while the input is parsed. The\nboolean return value informs the parser whether to continue processing the\ninput.\n*/\ntemplate<typename BasicJsonType>\nstruct json_sax\n{\n    /// type for (signed) integers\n    using number_integer_t = typename BasicJsonType::number_integer_t;\n    /// type for unsigned integers\n    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n    /// type for floating-point numbers\n    using number_float_t = typename BasicJsonType::number_float_t;\n    /// type for strings\n    using string_t = typename BasicJsonType::string_t;\n\n    /*!\n    @brief a null value was read\n    @return whether parsing should proceed\n    */\n    virtual bool null() = 0;\n\n    /*!\n    @brief a boolean value was read\n    @param[in] val  boolean value\n    @return whether parsing should proceed\n    */\n    virtual bool boolean(bool val) = 0;\n\n    /*!\n    @brief an integer number was read\n    @param[in] val  integer value\n    @return whether parsing should proceed\n    */\n    virtual bool number_integer(number_integer_t val) = 0;\n\n    /*!\n    @brief an unsigned integer number was read\n    @param[in] val  unsigned integer value\n    @return whether parsing should proceed\n    */\n    virtual bool number_unsigned(number_unsigned_t val) = 0;\n\n    /*!\n    @brief an floating-point number was read\n    @param[in] val  floating-point value\n    @param[in] s    raw token value\n    @return whether parsing should proceed\n    */\n    virtual bool number_float(number_float_t val, const string_t& s) = 0;\n\n    /*!\n    @brief a string was read\n    @param[in] val  string value\n    @return whether parsing should proceed\n    @note It is safe to move the passed string.\n    */\n    virtual bool string(string_t& val) = 0;\n\n    /*!\n    @brief the beginning of an object was read\n    @param[in] elements  number of object elements or -1 if unknown\n    @return whether parsing should proceed\n    @note binary formats may report the number of elements\n    */\n    virtual bool start_object(std::size_t elements) = 0;\n\n    /*!\n    @brief an object key was read\n    @param[in] val  object key\n    @return whether parsing should proceed\n    @note It is safe to move the passed string.\n    */\n    virtual bool key(string_t& val) = 0;\n\n    /*!\n    @brief the end of an object was read\n    @return whether parsing should proceed\n    */\n    virtual bool end_object() = 0;\n\n    /*!\n    @brief the beginning of an array was read\n    @param[in] elements  number of array elements or -1 if unknown\n    @return whether parsing should proceed\n    @note binary formats may report the number of elements\n    */\n    virtual bool start_array(std::size_t elements) = 0;\n\n    /*!\n    @brief the end of an array was read\n    @return whether parsing should proceed\n    */\n    virtual bool end_array() = 0;\n\n    /*!\n    @brief a parse error occurred\n    @param[in] position    the position in the input where the error occurs\n    @param[in] last_token  the last read token\n    @param[in] ex          an exception object describing the error\n    @return whether parsing should proceed (must return false)\n    */\n    virtual bool parse_error(std::size_t position,\n                             const std::string& last_token,\n                             const detail::exception& ex) = 0;\n\n    virtual ~json_sax() = default;\n};\n\n\nnamespace detail\n{\n/*!\n@brief SAX implementation to create a JSON value from SAX events\n\nThis class implements the @ref json_sax interface and processes the SAX events\nto create a JSON value which makes it basically a DOM parser. The structure or\nhierarchy of the JSON value is managed by the stack `ref_stack` which contains\na pointer to the respective array or object for each recursion depth.\n\nAfter successful parsing, the value that is passed by reference to the\nconstructor contains the parsed value.\n\n@tparam BasicJsonType  the JSON type\n*/\ntemplate<typename BasicJsonType>\nclass json_sax_dom_parser\n{\n  public:\n    using number_integer_t = typename BasicJsonType::number_integer_t;\n    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n    using number_float_t = typename BasicJsonType::number_float_t;\n    using string_t = typename BasicJsonType::string_t;\n\n    /*!\n    @param[in, out] r  reference to a JSON value that is manipulated while\n                       parsing\n    @param[in] allow_exceptions_  whether parse errors yield exceptions\n    */\n    explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)\n        : root(r), allow_exceptions(allow_exceptions_)\n    {}\n\n    bool null()\n    {\n        handle_value(nullptr);\n        return true;\n    }\n\n    bool boolean(bool val)\n    {\n        handle_value(val);\n        return true;\n    }\n\n    bool number_integer(number_integer_t val)\n    {\n        handle_value(val);\n        return true;\n    }\n\n    bool number_unsigned(number_unsigned_t val)\n    {\n        handle_value(val);\n        return true;\n    }\n\n    bool number_float(number_float_t val, const string_t& /*unused*/)\n    {\n        handle_value(val);\n        return true;\n    }\n\n    bool string(string_t& val)\n    {\n        handle_value(val);\n        return true;\n    }\n\n    bool start_object(std::size_t len)\n    {\n        ref_stack.push_back(handle_value(BasicJsonType::value_t::object));\n\n        if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))\n        {\n            JSON_THROW(out_of_range::create(408,\n                                            \"excessive object size: \" + std::to_string(len)));\n        }\n\n        return true;\n    }\n\n    bool key(string_t& val)\n    {\n        // add null at given key and store the reference for later\n        object_element = &(ref_stack.back()->m_value.object->operator[](val));\n        return true;\n    }\n\n    bool end_object()\n    {\n        ref_stack.pop_back();\n        return true;\n    }\n\n    bool start_array(std::size_t len)\n    {\n        ref_stack.push_back(handle_value(BasicJsonType::value_t::array));\n\n        if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))\n        {\n            JSON_THROW(out_of_range::create(408,\n                                            \"excessive array size: \" + std::to_string(len)));\n        }\n\n        return true;\n    }\n\n    bool end_array()\n    {\n        ref_stack.pop_back();\n        return true;\n    }\n\n    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,\n                     const detail::exception& ex)\n    {\n        errored = true;\n        if (allow_exceptions)\n        {\n            // determine the proper exception type from the id\n            switch ((ex.id / 100) % 100)\n            {\n                case 1:\n                    JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));\n                case 4:\n                    JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));\n                // LCOV_EXCL_START\n                case 2:\n                    JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));\n                case 3:\n                    JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));\n                case 5:\n                    JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));\n                default:\n                    assert(false);\n                    // LCOV_EXCL_STOP\n            }\n        }\n        return false;\n    }\n\n    constexpr bool is_errored() const\n    {\n        return errored;\n    }\n\n  private:\n    /*!\n    @invariant If the ref stack is empty, then the passed value will be the new\n               root.\n    @invariant If the ref stack contains a value, then it is an array or an\n               object to which we can add elements\n    */\n    template<typename Value>\n    BasicJsonType* handle_value(Value&& v)\n    {\n        if (ref_stack.empty())\n        {\n            root = BasicJsonType(std::forward<Value>(v));\n            return &root;\n        }\n\n        assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());\n\n        if (ref_stack.back()->is_array())\n        {\n            ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));\n            return &(ref_stack.back()->m_value.array->back());\n        }\n        else\n        {\n            assert(object_element);\n            *object_element = BasicJsonType(std::forward<Value>(v));\n            return object_element;\n        }\n    }\n\n    /// the parsed JSON value\n    BasicJsonType& root;\n    /// stack to model hierarchy of values\n    std::vector<BasicJsonType*> ref_stack;\n    /// helper to hold the reference for the next object element\n    BasicJsonType* object_element = nullptr;\n    /// whether a syntax error occurred\n    bool errored = false;\n    /// whether to throw exceptions in case of errors\n    const bool allow_exceptions = true;\n};\n\ntemplate<typename BasicJsonType>\nclass json_sax_dom_callback_parser\n{\n  public:\n    using number_integer_t = typename BasicJsonType::number_integer_t;\n    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n    using number_float_t = typename BasicJsonType::number_float_t;\n    using string_t = typename BasicJsonType::string_t;\n    using parser_callback_t = typename BasicJsonType::parser_callback_t;\n    using parse_event_t = typename BasicJsonType::parse_event_t;\n\n    json_sax_dom_callback_parser(BasicJsonType& r,\n                                 const parser_callback_t cb,\n                                 const bool allow_exceptions_ = true)\n        : root(r), callback(cb), allow_exceptions(allow_exceptions_)\n    {\n        keep_stack.push_back(true);\n    }\n\n    bool null()\n    {\n        handle_value(nullptr);\n        return true;\n    }\n\n    bool boolean(bool val)\n    {\n        handle_value(val);\n        return true;\n    }\n\n    bool number_integer(number_integer_t val)\n    {\n        handle_value(val);\n        return true;\n    }\n\n    bool number_unsigned(number_unsigned_t val)\n    {\n        handle_value(val);\n        return true;\n    }\n\n    bool number_float(number_float_t val, const string_t& /*unused*/)\n    {\n        handle_value(val);\n        return true;\n    }\n\n    bool string(string_t& val)\n    {\n        handle_value(val);\n        return true;\n    }\n\n    bool start_object(std::size_t len)\n    {\n        // check callback for object start\n        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);\n        keep_stack.push_back(keep);\n\n        auto val = handle_value(BasicJsonType::value_t::object, true);\n        ref_stack.push_back(val.second);\n\n        // check object limit\n        if (ref_stack.back())\n        {\n            if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))\n            {\n                JSON_THROW(out_of_range::create(408,\n                                                \"excessive object size: \" + std::to_string(len)));\n            }\n        }\n\n        return true;\n    }\n\n    bool key(string_t& val)\n    {\n        BasicJsonType k = BasicJsonType(val);\n\n        // check callback for key\n        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);\n        key_keep_stack.push_back(keep);\n\n        // add discarded value at given key and store the reference for later\n        if (keep and ref_stack.back())\n        {\n            object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);\n        }\n\n        return true;\n    }\n\n    bool end_object()\n    {\n        if (ref_stack.back())\n        {\n            if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))\n            {\n                // discard object\n                *ref_stack.back() = discarded;\n            }\n        }\n\n        assert(not ref_stack.empty());\n        assert(not keep_stack.empty());\n        ref_stack.pop_back();\n        keep_stack.pop_back();\n\n        if (not ref_stack.empty() and ref_stack.back())\n        {\n            // remove discarded value\n            if (ref_stack.back()->is_object())\n            {\n                for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)\n                {\n                    if (it->is_discarded())\n                    {\n                        ref_stack.back()->erase(it);\n                        break;\n                    }\n                }\n            }\n        }\n\n        return true;\n    }\n\n    bool start_array(std::size_t len)\n    {\n        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);\n        keep_stack.push_back(keep);\n\n        auto val = handle_value(BasicJsonType::value_t::array, true);\n        ref_stack.push_back(val.second);\n\n        // check array limit\n        if (ref_stack.back())\n        {\n            if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))\n            {\n                JSON_THROW(out_of_range::create(408,\n                                                \"excessive array size: \" + std::to_string(len)));\n            }\n        }\n\n        return true;\n    }\n\n    bool end_array()\n    {\n        bool keep = true;\n\n        if (ref_stack.back())\n        {\n            keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());\n            if (not keep)\n            {\n                // discard array\n                *ref_stack.back() = discarded;\n            }\n        }\n\n        assert(not ref_stack.empty());\n        assert(not keep_stack.empty());\n        ref_stack.pop_back();\n        keep_stack.pop_back();\n\n        // remove discarded value\n        if (not keep and not ref_stack.empty())\n        {\n            if (ref_stack.back()->is_array())\n            {\n                ref_stack.back()->m_value.array->pop_back();\n            }\n        }\n\n        return true;\n    }\n\n    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,\n                     const detail::exception& ex)\n    {\n        errored = true;\n        if (allow_exceptions)\n        {\n            // determine the proper exception type from the id\n            switch ((ex.id / 100) % 100)\n            {\n                case 1:\n                    JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));\n                case 4:\n                    JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));\n                // LCOV_EXCL_START\n                case 2:\n                    JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));\n                case 3:\n                    JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));\n                case 5:\n                    JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));\n                default:\n                    assert(false);\n                    // LCOV_EXCL_STOP\n            }\n        }\n        return false;\n    }\n\n    constexpr bool is_errored() const\n    {\n        return errored;\n    }\n\n  private:\n    /*!\n    @param[in] v  value to add to the JSON value we build during parsing\n    @param[in] skip_callback  whether we should skip calling the callback\n               function; this is required after start_array() and\n               start_object() SAX events, because otherwise we would call the\n               callback function with an empty array or object, respectively.\n\n    @invariant If the ref stack is empty, then the passed value will be the new\n               root.\n    @invariant If the ref stack contains a value, then it is an array or an\n               object to which we can add elements\n\n    @return pair of boolean (whether value should be kept) and pointer (to the\n            passed value in the ref_stack hierarchy; nullptr if not kept)\n    */\n    template<typename Value>\n    std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)\n    {\n        assert(not keep_stack.empty());\n\n        // do not handle this value if we know it would be added to a discarded\n        // container\n        if (not keep_stack.back())\n        {\n            return {false, nullptr};\n        }\n\n        // create value\n        auto value = BasicJsonType(std::forward<Value>(v));\n\n        // check callback\n        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);\n\n        // do not handle this value if we just learnt it shall be discarded\n        if (not keep)\n        {\n            return {false, nullptr};\n        }\n\n        if (ref_stack.empty())\n        {\n            root = std::move(value);\n            return {true, &root};\n        }\n\n        // skip this value if we already decided to skip the parent\n        // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)\n        if (not ref_stack.back())\n        {\n            return {false, nullptr};\n        }\n\n        // we now only expect arrays and objects\n        assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());\n\n        if (ref_stack.back()->is_array())\n        {\n            ref_stack.back()->m_value.array->push_back(std::move(value));\n            return {true, &(ref_stack.back()->m_value.array->back())};\n        }\n        else\n        {\n            // check if we should store an element for the current key\n            assert(not key_keep_stack.empty());\n            const bool store_element = key_keep_stack.back();\n            key_keep_stack.pop_back();\n\n            if (not store_element)\n            {\n                return {false, nullptr};\n            }\n\n            assert(object_element);\n            *object_element = std::move(value);\n            return {true, object_element};\n        }\n    }\n\n    /// the parsed JSON value\n    BasicJsonType& root;\n    /// stack to model hierarchy of values\n    std::vector<BasicJsonType*> ref_stack;\n    /// stack to manage which values to keep\n    std::vector<bool> keep_stack;\n    /// stack to manage which object keys to keep\n    std::vector<bool> key_keep_stack;\n    /// helper to hold the reference for the next object element\n    BasicJsonType* object_element = nullptr;\n    /// whether a syntax error occurred\n    bool errored = false;\n    /// callback function\n    const parser_callback_t callback = nullptr;\n    /// whether to throw exceptions in case of errors\n    const bool allow_exceptions = true;\n    /// a discarded value for the callback\n    BasicJsonType discarded = BasicJsonType::value_t::discarded;\n};\n\ntemplate<typename BasicJsonType>\nclass json_sax_acceptor\n{\n  public:\n    using number_integer_t = typename BasicJsonType::number_integer_t;\n    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n    using number_float_t = typename BasicJsonType::number_float_t;\n    using string_t = typename BasicJsonType::string_t;\n\n    bool null()\n    {\n        return true;\n    }\n\n    bool boolean(bool /*unused*/)\n    {\n        return true;\n    }\n\n    bool number_integer(number_integer_t /*unused*/)\n    {\n        return true;\n    }\n\n    bool number_unsigned(number_unsigned_t /*unused*/)\n    {\n        return true;\n    }\n\n    bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)\n    {\n        return true;\n    }\n\n    bool string(string_t& /*unused*/)\n    {\n        return true;\n    }\n\n    bool start_object(std::size_t  /*unused*/ = std::size_t(-1))\n    {\n        return true;\n    }\n\n    bool key(string_t& /*unused*/)\n    {\n        return true;\n    }\n\n    bool end_object()\n    {\n        return true;\n    }\n\n    bool start_array(std::size_t  /*unused*/ = std::size_t(-1))\n    {\n        return true;\n    }\n\n    bool end_array()\n    {\n        return true;\n    }\n\n    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)\n    {\n        return false;\n    }\n};\n}  // namespace detail\n\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/input/lexer.hpp>\n\n// #include <nlohmann/detail/value_t.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\n////////////\n// parser //\n////////////\n\n/*!\n@brief syntax analysis\n\nThis class implements a recursive decent parser.\n*/\ntemplate<typename BasicJsonType>\nclass parser\n{\n    using number_integer_t = typename BasicJsonType::number_integer_t;\n    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n    using number_float_t = typename BasicJsonType::number_float_t;\n    using string_t = typename BasicJsonType::string_t;\n    using lexer_t = lexer<BasicJsonType>;\n    using token_type = typename lexer_t::token_type;\n\n  public:\n    enum class parse_event_t : uint8_t\n    {\n        /// the parser read `{` and started to process a JSON object\n        object_start,\n        /// the parser read `}` and finished processing a JSON object\n        object_end,\n        /// the parser read `[` and started to process a JSON array\n        array_start,\n        /// the parser read `]` and finished processing a JSON array\n        array_end,\n        /// the parser read a key of a value in an object\n        key,\n        /// the parser finished reading a JSON value\n        value\n    };\n\n    using parser_callback_t =\n        std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;\n\n    /// a parser reading from an input adapter\n    explicit parser(detail::input_adapter_t&& adapter,\n                    const parser_callback_t cb = nullptr,\n                    const bool allow_exceptions_ = true)\n        : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)\n    {\n        // read first token\n        get_token();\n    }\n\n    /*!\n    @brief public parser interface\n\n    @param[in] strict      whether to expect the last token to be EOF\n    @param[in,out] result  parsed JSON value\n\n    @throw parse_error.101 in case of an unexpected token\n    @throw parse_error.102 if to_unicode fails or surrogate error\n    @throw parse_error.103 if to_unicode fails\n    */\n    void parse(const bool strict, BasicJsonType& result)\n    {\n        if (callback)\n        {\n            json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);\n            sax_parse_internal(&sdp);\n            result.assert_invariant();\n\n            // in strict mode, input must be completely read\n            if (strict and (get_token() != token_type::end_of_input))\n            {\n                sdp.parse_error(m_lexer.get_position(),\n                                m_lexer.get_token_string(),\n                                parse_error::create(101, m_lexer.get_position(),\n                                                    exception_message(token_type::end_of_input, \"value\")));\n            }\n\n            // in case of an error, return discarded value\n            if (sdp.is_errored())\n            {\n                result = value_t::discarded;\n                return;\n            }\n\n            // set top-level value to null if it was discarded by the callback\n            // function\n            if (result.is_discarded())\n            {\n                result = nullptr;\n            }\n        }\n        else\n        {\n            json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);\n            sax_parse_internal(&sdp);\n            result.assert_invariant();\n\n            // in strict mode, input must be completely read\n            if (strict and (get_token() != token_type::end_of_input))\n            {\n                sdp.parse_error(m_lexer.get_position(),\n                                m_lexer.get_token_string(),\n                                parse_error::create(101, m_lexer.get_position(),\n                                                    exception_message(token_type::end_of_input, \"value\")));\n            }\n\n            // in case of an error, return discarded value\n            if (sdp.is_errored())\n            {\n                result = value_t::discarded;\n                return;\n            }\n        }\n    }\n\n    /*!\n    @brief public accept interface\n\n    @param[in] strict  whether to expect the last token to be EOF\n    @return whether the input is a proper JSON text\n    */\n    bool accept(const bool strict = true)\n    {\n        json_sax_acceptor<BasicJsonType> sax_acceptor;\n        return sax_parse(&sax_acceptor, strict);\n    }\n\n    template <typename SAX>\n    bool sax_parse(SAX* sax, const bool strict = true)\n    {\n        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};\n        const bool result = sax_parse_internal(sax);\n\n        // strict mode: next byte must be EOF\n        if (result and strict and (get_token() != token_type::end_of_input))\n        {\n            return sax->parse_error(m_lexer.get_position(),\n                                    m_lexer.get_token_string(),\n                                    parse_error::create(101, m_lexer.get_position(),\n                                            exception_message(token_type::end_of_input, \"value\")));\n        }\n\n        return result;\n    }\n\n  private:\n    template <typename SAX>\n    bool sax_parse_internal(SAX* sax)\n    {\n        // stack to remember the hierarchy of structured values we are parsing\n        // true = array; false = object\n        std::vector<bool> states;\n        // value to avoid a goto (see comment where set to true)\n        bool skip_to_state_evaluation = false;\n\n        while (true)\n        {\n            if (not skip_to_state_evaluation)\n            {\n                // invariant: get_token() was called before each iteration\n                switch (last_token)\n                {\n                    case token_type::begin_object:\n                    {\n                        if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))\n                        {\n                            return false;\n                        }\n\n                        // closing } -> we are done\n                        if (get_token() == token_type::end_object)\n                        {\n                            if (JSON_UNLIKELY(not sax->end_object()))\n                            {\n                                return false;\n                            }\n                            break;\n                        }\n\n                        // parse key\n                        if (JSON_UNLIKELY(last_token != token_type::value_string))\n                        {\n                            return sax->parse_error(m_lexer.get_position(),\n                                                    m_lexer.get_token_string(),\n                                                    parse_error::create(101, m_lexer.get_position(),\n                                                            exception_message(token_type::value_string, \"object key\")));\n                        }\n                        if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))\n                        {\n                            return false;\n                        }\n\n                        // parse separator (:)\n                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))\n                        {\n                            return sax->parse_error(m_lexer.get_position(),\n                                                    m_lexer.get_token_string(),\n                                                    parse_error::create(101, m_lexer.get_position(),\n                                                            exception_message(token_type::name_separator, \"object separator\")));\n                        }\n\n                        // remember we are now inside an object\n                        states.push_back(false);\n\n                        // parse values\n                        get_token();\n                        continue;\n                    }\n\n                    case token_type::begin_array:\n                    {\n                        if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))\n                        {\n                            return false;\n                        }\n\n                        // closing ] -> we are done\n                        if (get_token() == token_type::end_array)\n                        {\n                            if (JSON_UNLIKELY(not sax->end_array()))\n                            {\n                                return false;\n                            }\n                            break;\n                        }\n\n                        // remember we are now inside an array\n                        states.push_back(true);\n\n                        // parse values (no need to call get_token)\n                        continue;\n                    }\n\n                    case token_type::value_float:\n                    {\n                        const auto res = m_lexer.get_number_float();\n\n                        if (JSON_UNLIKELY(not std::isfinite(res)))\n                        {\n                            return sax->parse_error(m_lexer.get_position(),\n                                                    m_lexer.get_token_string(),\n                                                    out_of_range::create(406, \"number overflow parsing '\" + m_lexer.get_token_string() + \"'\"));\n                        }\n                        else\n                        {\n                            if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))\n                            {\n                                return false;\n                            }\n                            break;\n                        }\n                    }\n\n                    case token_type::literal_false:\n                    {\n                        if (JSON_UNLIKELY(not sax->boolean(false)))\n                        {\n                            return false;\n                        }\n                        break;\n                    }\n\n                    case token_type::literal_null:\n                    {\n                        if (JSON_UNLIKELY(not sax->null()))\n                        {\n                            return false;\n                        }\n                        break;\n                    }\n\n                    case token_type::literal_true:\n                    {\n                        if (JSON_UNLIKELY(not sax->boolean(true)))\n                        {\n                            return false;\n                        }\n                        break;\n                    }\n\n                    case token_type::value_integer:\n                    {\n                        if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))\n                        {\n                            return false;\n                        }\n                        break;\n                    }\n\n                    case token_type::value_string:\n                    {\n                        if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))\n                        {\n                            return false;\n                        }\n                        break;\n                    }\n\n                    case token_type::value_unsigned:\n                    {\n                        if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))\n                        {\n                            return false;\n                        }\n                        break;\n                    }\n\n                    case token_type::parse_error:\n                    {\n                        // using \"uninitialized\" to avoid \"expected\" message\n                        return sax->parse_error(m_lexer.get_position(),\n                                                m_lexer.get_token_string(),\n                                                parse_error::create(101, m_lexer.get_position(),\n                                                        exception_message(token_type::uninitialized, \"value\")));\n                    }\n\n                    default: // the last token was unexpected\n                    {\n                        return sax->parse_error(m_lexer.get_position(),\n                                                m_lexer.get_token_string(),\n                                                parse_error::create(101, m_lexer.get_position(),\n                                                        exception_message(token_type::literal_or_value, \"value\")));\n                    }\n                }\n            }\n            else\n            {\n                skip_to_state_evaluation = false;\n            }\n\n            // we reached this line after we successfully parsed a value\n            if (states.empty())\n            {\n                // empty stack: we reached the end of the hierarchy: done\n                return true;\n            }\n            else\n            {\n                if (states.back())  // array\n                {\n                    // comma -> next value\n                    if (get_token() == token_type::value_separator)\n                    {\n                        // parse a new value\n                        get_token();\n                        continue;\n                    }\n\n                    // closing ]\n                    if (JSON_LIKELY(last_token == token_type::end_array))\n                    {\n                        if (JSON_UNLIKELY(not sax->end_array()))\n                        {\n                            return false;\n                        }\n\n                        // We are done with this array. Before we can parse a\n                        // new value, we need to evaluate the new state first.\n                        // By setting skip_to_state_evaluation to false, we\n                        // are effectively jumping to the beginning of this if.\n                        assert(not states.empty());\n                        states.pop_back();\n                        skip_to_state_evaluation = true;\n                        continue;\n                    }\n                    else\n                    {\n                        return sax->parse_error(m_lexer.get_position(),\n                                                m_lexer.get_token_string(),\n                                                parse_error::create(101, m_lexer.get_position(),\n                                                        exception_message(token_type::end_array, \"array\")));\n                    }\n                }\n                else  // object\n                {\n                    // comma -> next value\n                    if (get_token() == token_type::value_separator)\n                    {\n                        // parse key\n                        if (JSON_UNLIKELY(get_token() != token_type::value_string))\n                        {\n                            return sax->parse_error(m_lexer.get_position(),\n                                                    m_lexer.get_token_string(),\n                                                    parse_error::create(101, m_lexer.get_position(),\n                                                            exception_message(token_type::value_string, \"object key\")));\n                        }\n                        else\n                        {\n                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))\n                            {\n                                return false;\n                            }\n                        }\n\n                        // parse separator (:)\n                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))\n                        {\n                            return sax->parse_error(m_lexer.get_position(),\n                                                    m_lexer.get_token_string(),\n                                                    parse_error::create(101, m_lexer.get_position(),\n                                                            exception_message(token_type::name_separator, \"object separator\")));\n                        }\n\n                        // parse values\n                        get_token();\n                        continue;\n                    }\n\n                    // closing }\n                    if (JSON_LIKELY(last_token == token_type::end_object))\n                    {\n                        if (JSON_UNLIKELY(not sax->end_object()))\n                        {\n                            return false;\n                        }\n\n                        // We are done with this object. Before we can parse a\n                        // new value, we need to evaluate the new state first.\n                        // By setting skip_to_state_evaluation to false, we\n                        // are effectively jumping to the beginning of this if.\n                        assert(not states.empty());\n                        states.pop_back();\n                        skip_to_state_evaluation = true;\n                        continue;\n                    }\n                    else\n                    {\n                        return sax->parse_error(m_lexer.get_position(),\n                                                m_lexer.get_token_string(),\n                                                parse_error::create(101, m_lexer.get_position(),\n                                                        exception_message(token_type::end_object, \"object\")));\n                    }\n                }\n            }\n        }\n    }\n\n    /// get next token from lexer\n    token_type get_token()\n    {\n        return (last_token = m_lexer.scan());\n    }\n\n    std::string exception_message(const token_type expected, const std::string& context)\n    {\n        std::string error_msg = \"syntax error \";\n\n        if (not context.empty())\n        {\n            error_msg += \"while parsing \" + context + \" \";\n        }\n\n        error_msg += \"- \";\n\n        if (last_token == token_type::parse_error)\n        {\n            error_msg += std::string(m_lexer.get_error_message()) + \"; last read: '\" +\n                         m_lexer.get_token_string() + \"'\";\n        }\n        else\n        {\n            error_msg += \"unexpected \" + std::string(lexer_t::token_type_name(last_token));\n        }\n\n        if (expected != token_type::uninitialized)\n        {\n            error_msg += \"; expected \" + std::string(lexer_t::token_type_name(expected));\n        }\n\n        return error_msg;\n    }\n\n  private:\n    /// callback function\n    const parser_callback_t callback = nullptr;\n    /// the type of the last read token\n    token_type last_token = token_type::uninitialized;\n    /// the lexer\n    lexer_t m_lexer;\n    /// whether to throw exceptions in case of errors\n    const bool allow_exceptions = true;\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/iterators/primitive_iterator.hpp>\n\n\n#include <cstddef> // ptrdiff_t\n#include <limits>  // numeric_limits\n\nnamespace nlohmann\n{\nnamespace detail\n{\n/*\n@brief an iterator for primitive JSON types\n\nThis class models an iterator for primitive JSON types (boolean, number,\nstring). It's only purpose is to allow the iterator/const_iterator classes\nto \"iterate\" over primitive values. Internally, the iterator is modeled by\na `difference_type` variable. Value begin_value (`0`) models the begin,\nend_value (`1`) models past the end.\n*/\nclass primitive_iterator_t\n{\n  private:\n    using difference_type = std::ptrdiff_t;\n    static constexpr difference_type begin_value = 0;\n    static constexpr difference_type end_value = begin_value + 1;\n\n    /// iterator as signed integer type\n    difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();\n\n  public:\n    constexpr difference_type get_value() const noexcept\n    {\n        return m_it;\n    }\n\n    /// set iterator to a defined beginning\n    void set_begin() noexcept\n    {\n        m_it = begin_value;\n    }\n\n    /// set iterator to a defined past the end\n    void set_end() noexcept\n    {\n        m_it = end_value;\n    }\n\n    /// return whether the iterator can be dereferenced\n    constexpr bool is_begin() const noexcept\n    {\n        return m_it == begin_value;\n    }\n\n    /// return whether the iterator is at end\n    constexpr bool is_end() const noexcept\n    {\n        return m_it == end_value;\n    }\n\n    friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\n    {\n        return lhs.m_it == rhs.m_it;\n    }\n\n    friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\n    {\n        return lhs.m_it < rhs.m_it;\n    }\n\n    primitive_iterator_t operator+(difference_type n) noexcept\n    {\n        auto result = *this;\n        result += n;\n        return result;\n    }\n\n    friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept\n    {\n        return lhs.m_it - rhs.m_it;\n    }\n\n    primitive_iterator_t& operator++() noexcept\n    {\n        ++m_it;\n        return *this;\n    }\n\n    primitive_iterator_t const operator++(int) noexcept\n    {\n        auto result = *this;\n        ++m_it;\n        return result;\n    }\n\n    primitive_iterator_t& operator--() noexcept\n    {\n        --m_it;\n        return *this;\n    }\n\n    primitive_iterator_t const operator--(int) noexcept\n    {\n        auto result = *this;\n        --m_it;\n        return result;\n    }\n\n    primitive_iterator_t& operator+=(difference_type n) noexcept\n    {\n        m_it += n;\n        return *this;\n    }\n\n    primitive_iterator_t& operator-=(difference_type n) noexcept\n    {\n        m_it -= n;\n        return *this;\n    }\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/iterators/internal_iterator.hpp>\n\n\n// #include <nlohmann/detail/iterators/primitive_iterator.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\n/*!\n@brief an iterator value\n\n@note This structure could easily be a union, but MSVC currently does not allow\nunions members with complex constructors, see https://github.com/nlohmann/json/pull/105.\n*/\ntemplate<typename BasicJsonType> struct internal_iterator\n{\n    /// iterator for JSON objects\n    typename BasicJsonType::object_t::iterator object_iterator {};\n    /// iterator for JSON arrays\n    typename BasicJsonType::array_t::iterator array_iterator {};\n    /// generic iterator for all other types\n    primitive_iterator_t primitive_iterator {};\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/iterators/iter_impl.hpp>\n\n\n#include <ciso646> // not\n#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next\n#include <type_traits> // conditional, is_const, remove_const\n\n// #include <nlohmann/detail/exceptions.hpp>\n\n// #include <nlohmann/detail/iterators/internal_iterator.hpp>\n\n// #include <nlohmann/detail/iterators/primitive_iterator.hpp>\n\n// #include <nlohmann/detail/macro_scope.hpp>\n\n// #include <nlohmann/detail/meta/cpp_future.hpp>\n\n// #include <nlohmann/detail/meta/type_traits.hpp>\n\n// #include <nlohmann/detail/value_t.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\n// forward declare, to be able to friend it later on\ntemplate<typename IteratorType> class iteration_proxy;\ntemplate<typename IteratorType> class iteration_proxy_value;\n\n/*!\n@brief a template for a bidirectional iterator for the @ref basic_json class\nThis class implements a both iterators (iterator and const_iterator) for the\n@ref basic_json class.\n@note An iterator is called *initialized* when a pointer to a JSON value has\n      been set (e.g., by a constructor or a copy assignment). If the iterator is\n      default-constructed, it is *uninitialized* and most methods are undefined.\n      **The library uses assertions to detect calls on uninitialized iterators.**\n@requirement The class satisfies the following concept requirements:\n-\n[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):\n  The iterator that can be moved can be moved in both directions (i.e.\n  incremented and decremented).\n@since version 1.0.0, simplified in version 2.0.9, change to bidirectional\n       iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)\n*/\ntemplate<typename BasicJsonType>\nclass iter_impl\n{\n    /// allow basic_json to access private members\n    friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;\n    friend BasicJsonType;\n    friend iteration_proxy<iter_impl>;\n    friend iteration_proxy_value<iter_impl>;\n\n    using object_t = typename BasicJsonType::object_t;\n    using array_t = typename BasicJsonType::array_t;\n    // make sure BasicJsonType is basic_json or const basic_json\n    static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,\n                  \"iter_impl only accepts (const) basic_json\");\n\n  public:\n\n    /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.\n    /// The C++ Standard has never required user-defined iterators to derive from std::iterator.\n    /// A user-defined iterator should provide publicly accessible typedefs named\n    /// iterator_category, value_type, difference_type, pointer, and reference.\n    /// Note that value_type is required to be non-const, even for constant iterators.\n    using iterator_category = std::bidirectional_iterator_tag;\n\n    /// the type of the values when the iterator is dereferenced\n    using value_type = typename BasicJsonType::value_type;\n    /// a type to represent differences between iterators\n    using difference_type = typename BasicJsonType::difference_type;\n    /// defines a pointer to the type iterated over (value_type)\n    using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,\n          typename BasicJsonType::const_pointer,\n          typename BasicJsonType::pointer>::type;\n    /// defines a reference to the type iterated over (value_type)\n    using reference =\n        typename std::conditional<std::is_const<BasicJsonType>::value,\n        typename BasicJsonType::const_reference,\n        typename BasicJsonType::reference>::type;\n\n    /// default constructor\n    iter_impl() = default;\n\n    /*!\n    @brief constructor for a given JSON instance\n    @param[in] object  pointer to a JSON object for this iterator\n    @pre object != nullptr\n    @post The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    explicit iter_impl(pointer object) noexcept : m_object(object)\n    {\n        assert(m_object != nullptr);\n\n        switch (m_object->m_type)\n        {\n            case value_t::object:\n            {\n                m_it.object_iterator = typename object_t::iterator();\n                break;\n            }\n\n            case value_t::array:\n            {\n                m_it.array_iterator = typename array_t::iterator();\n                break;\n            }\n\n            default:\n            {\n                m_it.primitive_iterator = primitive_iterator_t();\n                break;\n            }\n        }\n    }\n\n    /*!\n    @note The conventional copy constructor and copy assignment are implicitly\n          defined. Combined with the following converting constructor and\n          assignment, they support: (1) copy from iterator to iterator, (2)\n          copy from const iterator to const iterator, and (3) conversion from\n          iterator to const iterator. However conversion from const iterator\n          to iterator is not defined.\n    */\n\n    /*!\n    @brief converting constructor\n    @param[in] other  non-const iterator to copy from\n    @note It is not checked whether @a other is initialized.\n    */\n    iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept\n        : m_object(other.m_object), m_it(other.m_it) {}\n\n    /*!\n    @brief converting assignment\n    @param[in,out] other  non-const iterator to copy from\n    @return const/non-const iterator\n    @note It is not checked whether @a other is initialized.\n    */\n    iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept\n    {\n        m_object = other.m_object;\n        m_it = other.m_it;\n        return *this;\n    }\n\n  private:\n    /*!\n    @brief set the iterator to the first value\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    void set_begin() noexcept\n    {\n        assert(m_object != nullptr);\n\n        switch (m_object->m_type)\n        {\n            case value_t::object:\n            {\n                m_it.object_iterator = m_object->m_value.object->begin();\n                break;\n            }\n\n            case value_t::array:\n            {\n                m_it.array_iterator = m_object->m_value.array->begin();\n                break;\n            }\n\n            case value_t::null:\n            {\n                // set to end so begin()==end() is true: null is empty\n                m_it.primitive_iterator.set_end();\n                break;\n            }\n\n            default:\n            {\n                m_it.primitive_iterator.set_begin();\n                break;\n            }\n        }\n    }\n\n    /*!\n    @brief set the iterator past the last value\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    void set_end() noexcept\n    {\n        assert(m_object != nullptr);\n\n        switch (m_object->m_type)\n        {\n            case value_t::object:\n            {\n                m_it.object_iterator = m_object->m_value.object->end();\n                break;\n            }\n\n            case value_t::array:\n            {\n                m_it.array_iterator = m_object->m_value.array->end();\n                break;\n            }\n\n            default:\n            {\n                m_it.primitive_iterator.set_end();\n                break;\n            }\n        }\n    }\n\n  public:\n    /*!\n    @brief return a reference to the value pointed to by the iterator\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    reference operator*() const\n    {\n        assert(m_object != nullptr);\n\n        switch (m_object->m_type)\n        {\n            case value_t::object:\n            {\n                assert(m_it.object_iterator != m_object->m_value.object->end());\n                return m_it.object_iterator->second;\n            }\n\n            case value_t::array:\n            {\n                assert(m_it.array_iterator != m_object->m_value.array->end());\n                return *m_it.array_iterator;\n            }\n\n            case value_t::null:\n                JSON_THROW(invalid_iterator::create(214, \"cannot get value\"));\n\n            default:\n            {\n                if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))\n                {\n                    return *m_object;\n                }\n\n                JSON_THROW(invalid_iterator::create(214, \"cannot get value\"));\n            }\n        }\n    }\n\n    /*!\n    @brief dereference the iterator\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    pointer operator->() const\n    {\n        assert(m_object != nullptr);\n\n        switch (m_object->m_type)\n        {\n            case value_t::object:\n            {\n                assert(m_it.object_iterator != m_object->m_value.object->end());\n                return &(m_it.object_iterator->second);\n            }\n\n            case value_t::array:\n            {\n                assert(m_it.array_iterator != m_object->m_value.array->end());\n                return &*m_it.array_iterator;\n            }\n\n            default:\n            {\n                if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))\n                {\n                    return m_object;\n                }\n\n                JSON_THROW(invalid_iterator::create(214, \"cannot get value\"));\n            }\n        }\n    }\n\n    /*!\n    @brief post-increment (it++)\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    iter_impl const operator++(int)\n    {\n        auto result = *this;\n        ++(*this);\n        return result;\n    }\n\n    /*!\n    @brief pre-increment (++it)\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    iter_impl& operator++()\n    {\n        assert(m_object != nullptr);\n\n        switch (m_object->m_type)\n        {\n            case value_t::object:\n            {\n                std::advance(m_it.object_iterator, 1);\n                break;\n            }\n\n            case value_t::array:\n            {\n                std::advance(m_it.array_iterator, 1);\n                break;\n            }\n\n            default:\n            {\n                ++m_it.primitive_iterator;\n                break;\n            }\n        }\n\n        return *this;\n    }\n\n    /*!\n    @brief post-decrement (it--)\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    iter_impl const operator--(int)\n    {\n        auto result = *this;\n        --(*this);\n        return result;\n    }\n\n    /*!\n    @brief pre-decrement (--it)\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    iter_impl& operator--()\n    {\n        assert(m_object != nullptr);\n\n        switch (m_object->m_type)\n        {\n            case value_t::object:\n            {\n                std::advance(m_it.object_iterator, -1);\n                break;\n            }\n\n            case value_t::array:\n            {\n                std::advance(m_it.array_iterator, -1);\n                break;\n            }\n\n            default:\n            {\n                --m_it.primitive_iterator;\n                break;\n            }\n        }\n\n        return *this;\n    }\n\n    /*!\n    @brief  comparison: equal\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    bool operator==(const iter_impl& other) const\n    {\n        // if objects are not the same, the comparison is undefined\n        if (JSON_UNLIKELY(m_object != other.m_object))\n        {\n            JSON_THROW(invalid_iterator::create(212, \"cannot compare iterators of different containers\"));\n        }\n\n        assert(m_object != nullptr);\n\n        switch (m_object->m_type)\n        {\n            case value_t::object:\n                return (m_it.object_iterator == other.m_it.object_iterator);\n\n            case value_t::array:\n                return (m_it.array_iterator == other.m_it.array_iterator);\n\n            default:\n                return (m_it.primitive_iterator == other.m_it.primitive_iterator);\n        }\n    }\n\n    /*!\n    @brief  comparison: not equal\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    bool operator!=(const iter_impl& other) const\n    {\n        return not operator==(other);\n    }\n\n    /*!\n    @brief  comparison: smaller\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    bool operator<(const iter_impl& other) const\n    {\n        // if objects are not the same, the comparison is undefined\n        if (JSON_UNLIKELY(m_object != other.m_object))\n        {\n            JSON_THROW(invalid_iterator::create(212, \"cannot compare iterators of different containers\"));\n        }\n\n        assert(m_object != nullptr);\n\n        switch (m_object->m_type)\n        {\n            case value_t::object:\n                JSON_THROW(invalid_iterator::create(213, \"cannot compare order of object iterators\"));\n\n            case value_t::array:\n                return (m_it.array_iterator < other.m_it.array_iterator);\n\n            default:\n                return (m_it.primitive_iterator < other.m_it.primitive_iterator);\n        }\n    }\n\n    /*!\n    @brief  comparison: less than or equal\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    bool operator<=(const iter_impl& other) const\n    {\n        return not other.operator < (*this);\n    }\n\n    /*!\n    @brief  comparison: greater than\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    bool operator>(const iter_impl& other) const\n    {\n        return not operator<=(other);\n    }\n\n    /*!\n    @brief  comparison: greater than or equal\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    bool operator>=(const iter_impl& other) const\n    {\n        return not operator<(other);\n    }\n\n    /*!\n    @brief  add to iterator\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    iter_impl& operator+=(difference_type i)\n    {\n        assert(m_object != nullptr);\n\n        switch (m_object->m_type)\n        {\n            case value_t::object:\n                JSON_THROW(invalid_iterator::create(209, \"cannot use offsets with object iterators\"));\n\n            case value_t::array:\n            {\n                std::advance(m_it.array_iterator, i);\n                break;\n            }\n\n            default:\n            {\n                m_it.primitive_iterator += i;\n                break;\n            }\n        }\n\n        return *this;\n    }\n\n    /*!\n    @brief  subtract from iterator\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    iter_impl& operator-=(difference_type i)\n    {\n        return operator+=(-i);\n    }\n\n    /*!\n    @brief  add to iterator\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    iter_impl operator+(difference_type i) const\n    {\n        auto result = *this;\n        result += i;\n        return result;\n    }\n\n    /*!\n    @brief  addition of distance and iterator\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    friend iter_impl operator+(difference_type i, const iter_impl& it)\n    {\n        auto result = it;\n        result += i;\n        return result;\n    }\n\n    /*!\n    @brief  subtract from iterator\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    iter_impl operator-(difference_type i) const\n    {\n        auto result = *this;\n        result -= i;\n        return result;\n    }\n\n    /*!\n    @brief  return difference\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    difference_type operator-(const iter_impl& other) const\n    {\n        assert(m_object != nullptr);\n\n        switch (m_object->m_type)\n        {\n            case value_t::object:\n                JSON_THROW(invalid_iterator::create(209, \"cannot use offsets with object iterators\"));\n\n            case value_t::array:\n                return m_it.array_iterator - other.m_it.array_iterator;\n\n            default:\n                return m_it.primitive_iterator - other.m_it.primitive_iterator;\n        }\n    }\n\n    /*!\n    @brief  access to successor\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    reference operator[](difference_type n) const\n    {\n        assert(m_object != nullptr);\n\n        switch (m_object->m_type)\n        {\n            case value_t::object:\n                JSON_THROW(invalid_iterator::create(208, \"cannot use operator[] for object iterators\"));\n\n            case value_t::array:\n                return *std::next(m_it.array_iterator, n);\n\n            case value_t::null:\n                JSON_THROW(invalid_iterator::create(214, \"cannot get value\"));\n\n            default:\n            {\n                if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))\n                {\n                    return *m_object;\n                }\n\n                JSON_THROW(invalid_iterator::create(214, \"cannot get value\"));\n            }\n        }\n    }\n\n    /*!\n    @brief  return the key of an object iterator\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    const typename object_t::key_type& key() const\n    {\n        assert(m_object != nullptr);\n\n        if (JSON_LIKELY(m_object->is_object()))\n        {\n            return m_it.object_iterator->first;\n        }\n\n        JSON_THROW(invalid_iterator::create(207, \"cannot use key() for non-object iterators\"));\n    }\n\n    /*!\n    @brief  return the value of an iterator\n    @pre The iterator is initialized; i.e. `m_object != nullptr`.\n    */\n    reference value() const\n    {\n        return operator*();\n    }\n\n  private:\n    /// associated JSON instance\n    pointer m_object = nullptr;\n    /// the actual iterator of the associated instance\n    internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it;\n};\n}  // namespace detail\n} // namespace nlohmann\n// #include <nlohmann/detail/iterators/iteration_proxy.hpp>\n\n// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>\n\n\n#include <cstddef> // ptrdiff_t\n#include <iterator> // reverse_iterator\n#include <utility> // declval\n\nnamespace nlohmann\n{\nnamespace detail\n{\n//////////////////////\n// reverse_iterator //\n//////////////////////\n\n/*!\n@brief a template for a reverse iterator class\n\n@tparam Base the base iterator type to reverse. Valid types are @ref\niterator (to create @ref reverse_iterator) and @ref const_iterator (to\ncreate @ref const_reverse_iterator).\n\n@requirement The class satisfies the following concept requirements:\n-\n[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):\n  The iterator that can be moved can be moved in both directions (i.e.\n  incremented and decremented).\n- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):\n  It is possible to write to the pointed-to element (only if @a Base is\n  @ref iterator).\n\n@since version 1.0.0\n*/\ntemplate<typename Base>\nclass json_reverse_iterator : public std::reverse_iterator<Base>\n{\n  public:\n    using difference_type = std::ptrdiff_t;\n    /// shortcut to the reverse iterator adapter\n    using base_iterator = std::reverse_iterator<Base>;\n    /// the reference type for the pointed-to element\n    using reference = typename Base::reference;\n\n    /// create reverse iterator from iterator\n    explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept\n        : base_iterator(it) {}\n\n    /// create reverse iterator from base class\n    explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}\n\n    /// post-increment (it++)\n    json_reverse_iterator const operator++(int)\n    {\n        return static_cast<json_reverse_iterator>(base_iterator::operator++(1));\n    }\n\n    /// pre-increment (++it)\n    json_reverse_iterator& operator++()\n    {\n        return static_cast<json_reverse_iterator&>(base_iterator::operator++());\n    }\n\n    /// post-decrement (it--)\n    json_reverse_iterator const operator--(int)\n    {\n        return static_cast<json_reverse_iterator>(base_iterator::operator--(1));\n    }\n\n    /// pre-decrement (--it)\n    json_reverse_iterator& operator--()\n    {\n        return static_cast<json_reverse_iterator&>(base_iterator::operator--());\n    }\n\n    /// add to iterator\n    json_reverse_iterator& operator+=(difference_type i)\n    {\n        return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));\n    }\n\n    /// add to iterator\n    json_reverse_iterator operator+(difference_type i) const\n    {\n        return static_cast<json_reverse_iterator>(base_iterator::operator+(i));\n    }\n\n    /// subtract from iterator\n    json_reverse_iterator operator-(difference_type i) const\n    {\n        return static_cast<json_reverse_iterator>(base_iterator::operator-(i));\n    }\n\n    /// return difference\n    difference_type operator-(const json_reverse_iterator& other) const\n    {\n        return base_iterator(*this) - base_iterator(other);\n    }\n\n    /// access to successor\n    reference operator[](difference_type n) const\n    {\n        return *(this->operator+(n));\n    }\n\n    /// return the key of an object iterator\n    auto key() const -> decltype(std::declval<Base>().key())\n    {\n        auto it = --this->base();\n        return it.key();\n    }\n\n    /// return the value of an iterator\n    reference value() const\n    {\n        auto it = --this->base();\n        return it.operator * ();\n    }\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/output/output_adapters.hpp>\n\n\n#include <algorithm> // copy\n#include <cstddef> // size_t\n#include <ios> // streamsize\n#include <iterator> // back_inserter\n#include <memory> // shared_ptr, make_shared\n#include <ostream> // basic_ostream\n#include <string> // basic_string\n#include <vector> // vector\n\nnamespace nlohmann\n{\nnamespace detail\n{\n/// abstract output adapter interface\ntemplate<typename CharType> struct output_adapter_protocol\n{\n    virtual void write_character(CharType c) = 0;\n    virtual void write_characters(const CharType* s, std::size_t length) = 0;\n    virtual ~output_adapter_protocol() = default;\n};\n\n/// a type to simplify interfaces\ntemplate<typename CharType>\nusing output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;\n\n/// output adapter for byte vectors\ntemplate<typename CharType>\nclass output_vector_adapter : public output_adapter_protocol<CharType>\n{\n  public:\n    explicit output_vector_adapter(std::vector<CharType>& vec) noexcept\n        : v(vec)\n    {}\n\n    void write_character(CharType c) override\n    {\n        v.push_back(c);\n    }\n\n    void write_characters(const CharType* s, std::size_t length) override\n    {\n        std::copy(s, s + length, std::back_inserter(v));\n    }\n\n  private:\n    std::vector<CharType>& v;\n};\n\n/// output adapter for output streams\ntemplate<typename CharType>\nclass output_stream_adapter : public output_adapter_protocol<CharType>\n{\n  public:\n    explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept\n        : stream(s)\n    {}\n\n    void write_character(CharType c) override\n    {\n        stream.put(c);\n    }\n\n    void write_characters(const CharType* s, std::size_t length) override\n    {\n        stream.write(s, static_cast<std::streamsize>(length));\n    }\n\n  private:\n    std::basic_ostream<CharType>& stream;\n};\n\n/// output adapter for basic_string\ntemplate<typename CharType, typename StringType = std::basic_string<CharType>>\nclass output_string_adapter : public output_adapter_protocol<CharType>\n{\n  public:\n    explicit output_string_adapter(StringType& s) noexcept\n        : str(s)\n    {}\n\n    void write_character(CharType c) override\n    {\n        str.push_back(c);\n    }\n\n    void write_characters(const CharType* s, std::size_t length) override\n    {\n        str.append(s, length);\n    }\n\n  private:\n    StringType& str;\n};\n\ntemplate<typename CharType, typename StringType = std::basic_string<CharType>>\nclass output_adapter\n{\n  public:\n    output_adapter(std::vector<CharType>& vec)\n        : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}\n\n    output_adapter(std::basic_ostream<CharType>& s)\n        : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}\n\n    output_adapter(StringType& s)\n        : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}\n\n    operator output_adapter_t<CharType>()\n    {\n        return oa;\n    }\n\n  private:\n    output_adapter_t<CharType> oa = nullptr;\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/input/binary_reader.hpp>\n\n\n#include <algorithm> // generate_n\n#include <array> // array\n#include <cassert> // assert\n#include <cmath> // ldexp\n#include <cstddef> // size_t\n#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t\n#include <cstdio> // snprintf\n#include <cstring> // memcpy\n#include <iterator> // back_inserter\n#include <limits> // numeric_limits\n#include <string> // char_traits, string\n#include <utility> // make_pair, move\n\n// #include <nlohmann/detail/input/input_adapters.hpp>\n\n// #include <nlohmann/detail/input/json_sax.hpp>\n\n// #include <nlohmann/detail/exceptions.hpp>\n\n// #include <nlohmann/detail/macro_scope.hpp>\n\n// #include <nlohmann/detail/meta/is_sax.hpp>\n\n// #include <nlohmann/detail/value_t.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\n///////////////////\n// binary reader //\n///////////////////\n\n/*!\n@brief deserialization of CBOR, MessagePack, and UBJSON values\n*/\ntemplate<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>\nclass binary_reader\n{\n    using number_integer_t = typename BasicJsonType::number_integer_t;\n    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n    using number_float_t = typename BasicJsonType::number_float_t;\n    using string_t = typename BasicJsonType::string_t;\n    using json_sax_t = SAX;\n\n  public:\n    /*!\n    @brief create a binary reader\n\n    @param[in] adapter  input adapter to read from\n    */\n    explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))\n    {\n        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};\n        assert(ia);\n    }\n\n    /*!\n    @param[in] format  the binary format to parse\n    @param[in] sax_    a SAX event processor\n    @param[in] strict  whether to expect the input to be consumed completed\n\n    @return\n    */\n    bool sax_parse(const input_format_t format,\n                   json_sax_t* sax_,\n                   const bool strict = true)\n    {\n        sax = sax_;\n        bool result = false;\n\n        switch (format)\n        {\n            case input_format_t::bson:\n                result = parse_bson_internal();\n                break;\n\n            case input_format_t::cbor:\n                result = parse_cbor_internal();\n                break;\n\n            case input_format_t::msgpack:\n                result = parse_msgpack_internal();\n                break;\n\n            case input_format_t::ubjson:\n                result = parse_ubjson_internal();\n                break;\n\n            // LCOV_EXCL_START\n            default:\n                assert(false);\n                // LCOV_EXCL_STOP\n        }\n\n        // strict mode: next byte must be EOF\n        if (result and strict)\n        {\n            if (format == input_format_t::ubjson)\n            {\n                get_ignore_noop();\n            }\n            else\n            {\n                get();\n            }\n\n            if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))\n            {\n                return sax->parse_error(chars_read, get_token_string(),\n                                        parse_error::create(110, chars_read, exception_message(format, \"expected end of input; last byte: 0x\" + get_token_string(), \"value\")));\n            }\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief determine system byte order\n\n    @return true if and only if system's byte order is little endian\n\n    @note from http://stackoverflow.com/a/1001328/266378\n    */\n    static constexpr bool little_endianess(int num = 1) noexcept\n    {\n        return (*reinterpret_cast<char*>(&num) == 1);\n    }\n\n  private:\n    //////////\n    // BSON //\n    //////////\n\n    /*!\n    @brief Reads in a BSON-object and passes it to the SAX-parser.\n    @return whether a valid BSON-value was passed to the SAX parser\n    */\n    bool parse_bson_internal()\n    {\n        std::int32_t document_size;\n        get_number<std::int32_t, true>(input_format_t::bson, document_size);\n\n        if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))\n        {\n            return false;\n        }\n\n        if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/false)))\n        {\n            return false;\n        }\n\n        return sax->end_object();\n    }\n\n    /*!\n    @brief Parses a C-style string from the BSON input.\n    @param[in, out] result  A reference to the string variable where the read\n                            string is to be stored.\n    @return `true` if the \\x00-byte indicating the end of the string was\n             encountered before the EOF; false` indicates an unexpected EOF.\n    */\n    bool get_bson_cstr(string_t& result)\n    {\n        auto out = std::back_inserter(result);\n        while (true)\n        {\n            get();\n            if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, \"cstring\")))\n            {\n                return false;\n            }\n            if (current == 0x00)\n            {\n                return true;\n            }\n            *out++ = static_cast<char>(current);\n        }\n\n        return true;\n    }\n\n    /*!\n    @brief Parses a zero-terminated string of length @a len from the BSON\n           input.\n    @param[in] len  The length (including the zero-byte at the end) of the\n                    string to be read.\n    @param[in, out] result  A reference to the string variable where the read\n                            string is to be stored.\n    @tparam NumberType The type of the length @a len\n    @pre len >= 1\n    @return `true` if the string was successfully parsed\n    */\n    template<typename NumberType>\n    bool get_bson_string(const NumberType len, string_t& result)\n    {\n        if (JSON_UNLIKELY(len < 1))\n        {\n            auto last_token = get_token_string();\n            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, \"string length must be at least 1, is \" + std::to_string(len), \"string\")));\n        }\n\n        return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) and get() != std::char_traits<char>::eof();\n    }\n\n    /*!\n    @brief Read a BSON document element of the given @a element_type.\n    @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html\n    @param[in] element_type_parse_position The position in the input stream,\n               where the `element_type` was read.\n    @warning Not all BSON element types are supported yet. An unsupported\n             @a element_type will give rise to a parse_error.114:\n             Unsupported BSON record type 0x...\n    @return whether a valid BSON-object/array was passed to the SAX parser\n    */\n    bool parse_bson_element_internal(const int element_type,\n                                     const std::size_t element_type_parse_position)\n    {\n        switch (element_type)\n        {\n            case 0x01: // double\n            {\n                double number;\n                return get_number<double, true>(input_format_t::bson, number) and sax->number_float(static_cast<number_float_t>(number), \"\");\n            }\n\n            case 0x02: // string\n            {\n                std::int32_t len;\n                string_t value;\n                return get_number<std::int32_t, true>(input_format_t::bson, len) and get_bson_string(len, value) and sax->string(value);\n            }\n\n            case 0x03: // object\n            {\n                return parse_bson_internal();\n            }\n\n            case 0x04: // array\n            {\n                return parse_bson_array();\n            }\n\n            case 0x08: // boolean\n            {\n                return sax->boolean(get() != 0);\n            }\n\n            case 0x0A: // null\n            {\n                return sax->null();\n            }\n\n            case 0x10: // int32\n            {\n                std::int32_t value;\n                return get_number<std::int32_t, true>(input_format_t::bson, value) and sax->number_integer(value);\n            }\n\n            case 0x12: // int64\n            {\n                std::int64_t value;\n                return get_number<std::int64_t, true>(input_format_t::bson, value) and sax->number_integer(value);\n            }\n\n            default: // anything else not supported (yet)\n            {\n                char cr[3];\n                (std::snprintf)(cr, sizeof(cr), \"%.2hhX\", static_cast<unsigned char>(element_type));\n                return sax->parse_error(element_type_parse_position, std::string(cr), parse_error::create(114, element_type_parse_position, \"Unsupported BSON record type 0x\" + std::string(cr)));\n            }\n        }\n    }\n\n    /*!\n    @brief Read a BSON element list (as specified in the BSON-spec)\n\n    The same binary layout is used for objects and arrays, hence it must be\n    indicated with the argument @a is_array which one is expected\n    (true --> array, false --> object).\n\n    @param[in] is_array Determines if the element list being read is to be\n                        treated as an object (@a is_array == false), or as an\n                        array (@a is_array == true).\n    @return whether a valid BSON-object/array was passed to the SAX parser\n    */\n    bool parse_bson_element_list(const bool is_array)\n    {\n        string_t key;\n        while (int element_type = get())\n        {\n            if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, \"element list\")))\n            {\n                return false;\n            }\n\n            const std::size_t element_type_parse_position = chars_read;\n            if (JSON_UNLIKELY(not get_bson_cstr(key)))\n            {\n                return false;\n            }\n\n            if (not is_array)\n            {\n                if (not sax->key(key))\n                {\n                    return false;\n                }\n            }\n\n            if (JSON_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position)))\n            {\n                return false;\n            }\n\n            // get_bson_cstr only appends\n            key.clear();\n        }\n\n        return true;\n    }\n\n    /*!\n    @brief Reads an array from the BSON input and passes it to the SAX-parser.\n    @return whether a valid BSON-array was passed to the SAX parser\n    */\n    bool parse_bson_array()\n    {\n        std::int32_t document_size;\n        get_number<std::int32_t, true>(input_format_t::bson, document_size);\n\n        if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))\n        {\n            return false;\n        }\n\n        if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/true)))\n        {\n            return false;\n        }\n\n        return sax->end_array();\n    }\n\n    //////////\n    // CBOR //\n    //////////\n\n    /*!\n    @param[in] get_char  whether a new character should be retrieved from the\n                         input (true, default) or whether the last read\n                         character should be considered instead\n\n    @return whether a valid CBOR value was passed to the SAX parser\n    */\n    bool parse_cbor_internal(const bool get_char = true)\n    {\n        switch (get_char ? get() : current)\n        {\n            // EOF\n            case std::char_traits<char>::eof():\n                return unexpect_eof(input_format_t::cbor, \"value\");\n\n            // Integer 0x00..0x17 (0..23)\n            case 0x00:\n            case 0x01:\n            case 0x02:\n            case 0x03:\n            case 0x04:\n            case 0x05:\n            case 0x06:\n            case 0x07:\n            case 0x08:\n            case 0x09:\n            case 0x0A:\n            case 0x0B:\n            case 0x0C:\n            case 0x0D:\n            case 0x0E:\n            case 0x0F:\n            case 0x10:\n            case 0x11:\n            case 0x12:\n            case 0x13:\n            case 0x14:\n            case 0x15:\n            case 0x16:\n            case 0x17:\n                return sax->number_unsigned(static_cast<number_unsigned_t>(current));\n\n            case 0x18: // Unsigned integer (one-byte uint8_t follows)\n            {\n                uint8_t number;\n                return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);\n            }\n\n            case 0x19: // Unsigned integer (two-byte uint16_t follows)\n            {\n                uint16_t number;\n                return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);\n            }\n\n            case 0x1A: // Unsigned integer (four-byte uint32_t follows)\n            {\n                uint32_t number;\n                return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);\n            }\n\n            case 0x1B: // Unsigned integer (eight-byte uint64_t follows)\n            {\n                uint64_t number;\n                return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);\n            }\n\n            // Negative integer -1-0x00..-1-0x17 (-1..-24)\n            case 0x20:\n            case 0x21:\n            case 0x22:\n            case 0x23:\n            case 0x24:\n            case 0x25:\n            case 0x26:\n            case 0x27:\n            case 0x28:\n            case 0x29:\n            case 0x2A:\n            case 0x2B:\n            case 0x2C:\n            case 0x2D:\n            case 0x2E:\n            case 0x2F:\n            case 0x30:\n            case 0x31:\n            case 0x32:\n            case 0x33:\n            case 0x34:\n            case 0x35:\n            case 0x36:\n            case 0x37:\n                return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current));\n\n            case 0x38: // Negative integer (one-byte uint8_t follows)\n            {\n                uint8_t number;\n                return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);\n            }\n\n            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)\n            {\n                uint16_t number;\n                return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);\n            }\n\n            case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)\n            {\n                uint32_t number;\n                return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);\n            }\n\n            case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)\n            {\n                uint64_t number;\n                return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1)\n                        - static_cast<number_integer_t>(number));\n            }\n\n            // UTF-8 string (0x00..0x17 bytes follow)\n            case 0x60:\n            case 0x61:\n            case 0x62:\n            case 0x63:\n            case 0x64:\n            case 0x65:\n            case 0x66:\n            case 0x67:\n            case 0x68:\n            case 0x69:\n            case 0x6A:\n            case 0x6B:\n            case 0x6C:\n            case 0x6D:\n            case 0x6E:\n            case 0x6F:\n            case 0x70:\n            case 0x71:\n            case 0x72:\n            case 0x73:\n            case 0x74:\n            case 0x75:\n            case 0x76:\n            case 0x77:\n            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)\n            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)\n            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)\n            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)\n            case 0x7F: // UTF-8 string (indefinite length)\n            {\n                string_t s;\n                return get_cbor_string(s) and sax->string(s);\n            }\n\n            // array (0x00..0x17 data items follow)\n            case 0x80:\n            case 0x81:\n            case 0x82:\n            case 0x83:\n            case 0x84:\n            case 0x85:\n            case 0x86:\n            case 0x87:\n            case 0x88:\n            case 0x89:\n            case 0x8A:\n            case 0x8B:\n            case 0x8C:\n            case 0x8D:\n            case 0x8E:\n            case 0x8F:\n            case 0x90:\n            case 0x91:\n            case 0x92:\n            case 0x93:\n            case 0x94:\n            case 0x95:\n            case 0x96:\n            case 0x97:\n                return get_cbor_array(static_cast<std::size_t>(current & 0x1F));\n\n            case 0x98: // array (one-byte uint8_t for n follows)\n            {\n                uint8_t len;\n                return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));\n            }\n\n            case 0x99: // array (two-byte uint16_t for n follow)\n            {\n                uint16_t len;\n                return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));\n            }\n\n            case 0x9A: // array (four-byte uint32_t for n follow)\n            {\n                uint32_t len;\n                return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));\n            }\n\n            case 0x9B: // array (eight-byte uint64_t for n follow)\n            {\n                uint64_t len;\n                return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));\n            }\n\n            case 0x9F: // array (indefinite length)\n                return get_cbor_array(std::size_t(-1));\n\n            // map (0x00..0x17 pairs of data items follow)\n            case 0xA0:\n            case 0xA1:\n            case 0xA2:\n            case 0xA3:\n            case 0xA4:\n            case 0xA5:\n            case 0xA6:\n            case 0xA7:\n            case 0xA8:\n            case 0xA9:\n            case 0xAA:\n            case 0xAB:\n            case 0xAC:\n            case 0xAD:\n            case 0xAE:\n            case 0xAF:\n            case 0xB0:\n            case 0xB1:\n            case 0xB2:\n            case 0xB3:\n            case 0xB4:\n            case 0xB5:\n            case 0xB6:\n            case 0xB7:\n                return get_cbor_object(static_cast<std::size_t>(current & 0x1F));\n\n            case 0xB8: // map (one-byte uint8_t for n follows)\n            {\n                uint8_t len;\n                return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));\n            }\n\n            case 0xB9: // map (two-byte uint16_t for n follow)\n            {\n                uint16_t len;\n                return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));\n            }\n\n            case 0xBA: // map (four-byte uint32_t for n follow)\n            {\n                uint32_t len;\n                return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));\n            }\n\n            case 0xBB: // map (eight-byte uint64_t for n follow)\n            {\n                uint64_t len;\n                return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));\n            }\n\n            case 0xBF: // map (indefinite length)\n                return get_cbor_object(std::size_t(-1));\n\n            case 0xF4: // false\n                return sax->boolean(false);\n\n            case 0xF5: // true\n                return sax->boolean(true);\n\n            case 0xF6: // null\n                return sax->null();\n\n            case 0xF9: // Half-Precision Float (two-byte IEEE 754)\n            {\n                const int byte1_raw = get();\n                if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, \"number\")))\n                {\n                    return false;\n                }\n                const int byte2_raw = get();\n                if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, \"number\")))\n                {\n                    return false;\n                }\n\n                const auto byte1 = static_cast<unsigned char>(byte1_raw);\n                const auto byte2 = static_cast<unsigned char>(byte2_raw);\n\n                // code from RFC 7049, Appendix D, Figure 3:\n                // As half-precision floating-point numbers were only added\n                // to IEEE 754 in 2008, today's programming platforms often\n                // still only have limited support for them. It is very\n                // easy to include at least decoding support for them even\n                // without such support. An example of a small decoder for\n                // half-precision floating-point numbers in the C language\n                // is shown in Fig. 3.\n                const int half = (byte1 << 8) + byte2;\n                const double val = [&half]\n                {\n                    const int exp = (half >> 10) & 0x1F;\n                    const int mant = half & 0x3FF;\n                    assert(0 <= exp and exp <= 32);\n                    assert(0 <= mant and mant <= 1024);\n                    switch (exp)\n                    {\n                        case 0:\n                            return std::ldexp(mant, -24);\n                        case 31:\n                            return (mant == 0)\n                            ? std::numeric_limits<double>::infinity()\n                            : std::numeric_limits<double>::quiet_NaN();\n                        default:\n                            return std::ldexp(mant + 1024, exp - 25);\n                    }\n                }();\n                return sax->number_float((half & 0x8000) != 0\n                                         ? static_cast<number_float_t>(-val)\n                                         : static_cast<number_float_t>(val), \"\");\n            }\n\n            case 0xFA: // Single-Precision Float (four-byte IEEE 754)\n            {\n                float number;\n                return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), \"\");\n            }\n\n            case 0xFB: // Double-Precision Float (eight-byte IEEE 754)\n            {\n                double number;\n                return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), \"\");\n            }\n\n            default: // anything else (0xFF is handled inside the other types)\n            {\n                auto last_token = get_token_string();\n                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, \"invalid byte: 0x\" + last_token, \"value\")));\n            }\n        }\n    }\n\n    /*!\n    @brief reads a CBOR string\n\n    This function first reads starting bytes to determine the expected\n    string length and then copies this number of bytes into a string.\n    Additionally, CBOR's strings with indefinite lengths are supported.\n\n    @param[out] result  created string\n\n    @return whether string creation completed\n    */\n    bool get_cbor_string(string_t& result)\n    {\n        if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, \"string\")))\n        {\n            return false;\n        }\n\n        switch (current)\n        {\n            // UTF-8 string (0x00..0x17 bytes follow)\n            case 0x60:\n            case 0x61:\n            case 0x62:\n            case 0x63:\n            case 0x64:\n            case 0x65:\n            case 0x66:\n            case 0x67:\n            case 0x68:\n            case 0x69:\n            case 0x6A:\n            case 0x6B:\n            case 0x6C:\n            case 0x6D:\n            case 0x6E:\n            case 0x6F:\n            case 0x70:\n            case 0x71:\n            case 0x72:\n            case 0x73:\n            case 0x74:\n            case 0x75:\n            case 0x76:\n            case 0x77:\n            {\n                return get_string(input_format_t::cbor, current & 0x1F, result);\n            }\n\n            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)\n            {\n                uint8_t len;\n                return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);\n            }\n\n            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)\n            {\n                uint16_t len;\n                return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);\n            }\n\n            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)\n            {\n                uint32_t len;\n                return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);\n            }\n\n            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)\n            {\n                uint64_t len;\n                return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);\n            }\n\n            case 0x7F: // UTF-8 string (indefinite length)\n            {\n                while (get() != 0xFF)\n                {\n                    string_t chunk;\n                    if (not get_cbor_string(chunk))\n                    {\n                        return false;\n                    }\n                    result.append(chunk);\n                }\n                return true;\n            }\n\n            default:\n            {\n                auto last_token = get_token_string();\n                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, \"expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x\" + last_token, \"string\")));\n            }\n        }\n    }\n\n    /*!\n    @param[in] len  the length of the array or std::size_t(-1) for an\n                    array of indefinite size\n    @return whether array creation completed\n    */\n    bool get_cbor_array(const std::size_t len)\n    {\n        if (JSON_UNLIKELY(not sax->start_array(len)))\n        {\n            return false;\n        }\n\n        if (len != std::size_t(-1))\n        {\n            for (std::size_t i = 0; i < len; ++i)\n            {\n                if (JSON_UNLIKELY(not parse_cbor_internal()))\n                {\n                    return false;\n                }\n            }\n        }\n        else\n        {\n            while (get() != 0xFF)\n            {\n                if (JSON_UNLIKELY(not parse_cbor_internal(false)))\n                {\n                    return false;\n                }\n            }\n        }\n\n        return sax->end_array();\n    }\n\n    /*!\n    @param[in] len  the length of the object or std::size_t(-1) for an\n                    object of indefinite size\n    @return whether object creation completed\n    */\n    bool get_cbor_object(const std::size_t len)\n    {\n        if (JSON_UNLIKELY(not sax->start_object(len)))\n        {\n            return false;\n        }\n\n        string_t key;\n        if (len != std::size_t(-1))\n        {\n            for (std::size_t i = 0; i < len; ++i)\n            {\n                get();\n                if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))\n                {\n                    return false;\n                }\n\n                if (JSON_UNLIKELY(not parse_cbor_internal()))\n                {\n                    return false;\n                }\n                key.clear();\n            }\n        }\n        else\n        {\n            while (get() != 0xFF)\n            {\n                if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))\n                {\n                    return false;\n                }\n\n                if (JSON_UNLIKELY(not parse_cbor_internal()))\n                {\n                    return false;\n                }\n                key.clear();\n            }\n        }\n\n        return sax->end_object();\n    }\n\n    /////////////\n    // MsgPack //\n    /////////////\n\n    /*!\n    @return whether a valid MessagePack value was passed to the SAX parser\n    */\n    bool parse_msgpack_internal()\n    {\n        switch (get())\n        {\n            // EOF\n            case std::char_traits<char>::eof():\n                return unexpect_eof(input_format_t::msgpack, \"value\");\n\n            // positive fixint\n            case 0x00:\n            case 0x01:\n            case 0x02:\n            case 0x03:\n            case 0x04:\n            case 0x05:\n            case 0x06:\n            case 0x07:\n            case 0x08:\n            case 0x09:\n            case 0x0A:\n            case 0x0B:\n            case 0x0C:\n            case 0x0D:\n            case 0x0E:\n            case 0x0F:\n            case 0x10:\n            case 0x11:\n            case 0x12:\n            case 0x13:\n            case 0x14:\n            case 0x15:\n            case 0x16:\n            case 0x17:\n            case 0x18:\n            case 0x19:\n            case 0x1A:\n            case 0x1B:\n            case 0x1C:\n            case 0x1D:\n            case 0x1E:\n            case 0x1F:\n            case 0x20:\n            case 0x21:\n            case 0x22:\n            case 0x23:\n            case 0x24:\n            case 0x25:\n            case 0x26:\n            case 0x27:\n            case 0x28:\n            case 0x29:\n            case 0x2A:\n            case 0x2B:\n            case 0x2C:\n            case 0x2D:\n            case 0x2E:\n            case 0x2F:\n            case 0x30:\n            case 0x31:\n            case 0x32:\n            case 0x33:\n            case 0x34:\n            case 0x35:\n            case 0x36:\n            case 0x37:\n            case 0x38:\n            case 0x39:\n            case 0x3A:\n            case 0x3B:\n            case 0x3C:\n            case 0x3D:\n            case 0x3E:\n            case 0x3F:\n            case 0x40:\n            case 0x41:\n            case 0x42:\n            case 0x43:\n            case 0x44:\n            case 0x45:\n            case 0x46:\n            case 0x47:\n            case 0x48:\n            case 0x49:\n            case 0x4A:\n            case 0x4B:\n            case 0x4C:\n            case 0x4D:\n            case 0x4E:\n            case 0x4F:\n            case 0x50:\n            case 0x51:\n            case 0x52:\n            case 0x53:\n            case 0x54:\n            case 0x55:\n            case 0x56:\n            case 0x57:\n            case 0x58:\n            case 0x59:\n            case 0x5A:\n            case 0x5B:\n            case 0x5C:\n            case 0x5D:\n            case 0x5E:\n            case 0x5F:\n            case 0x60:\n            case 0x61:\n            case 0x62:\n            case 0x63:\n            case 0x64:\n            case 0x65:\n            case 0x66:\n            case 0x67:\n            case 0x68:\n            case 0x69:\n            case 0x6A:\n            case 0x6B:\n            case 0x6C:\n            case 0x6D:\n            case 0x6E:\n            case 0x6F:\n            case 0x70:\n            case 0x71:\n            case 0x72:\n            case 0x73:\n            case 0x74:\n            case 0x75:\n            case 0x76:\n            case 0x77:\n            case 0x78:\n            case 0x79:\n            case 0x7A:\n            case 0x7B:\n            case 0x7C:\n            case 0x7D:\n            case 0x7E:\n            case 0x7F:\n                return sax->number_unsigned(static_cast<number_unsigned_t>(current));\n\n            // fixmap\n            case 0x80:\n            case 0x81:\n            case 0x82:\n            case 0x83:\n            case 0x84:\n            case 0x85:\n            case 0x86:\n            case 0x87:\n            case 0x88:\n            case 0x89:\n            case 0x8A:\n            case 0x8B:\n            case 0x8C:\n            case 0x8D:\n            case 0x8E:\n            case 0x8F:\n                return get_msgpack_object(static_cast<std::size_t>(current & 0x0F));\n\n            // fixarray\n            case 0x90:\n            case 0x91:\n            case 0x92:\n            case 0x93:\n            case 0x94:\n            case 0x95:\n            case 0x96:\n            case 0x97:\n            case 0x98:\n            case 0x99:\n            case 0x9A:\n            case 0x9B:\n            case 0x9C:\n            case 0x9D:\n            case 0x9E:\n            case 0x9F:\n                return get_msgpack_array(static_cast<std::size_t>(current & 0x0F));\n\n            // fixstr\n            case 0xA0:\n            case 0xA1:\n            case 0xA2:\n            case 0xA3:\n            case 0xA4:\n            case 0xA5:\n            case 0xA6:\n            case 0xA7:\n            case 0xA8:\n            case 0xA9:\n            case 0xAA:\n            case 0xAB:\n            case 0xAC:\n            case 0xAD:\n            case 0xAE:\n            case 0xAF:\n            case 0xB0:\n            case 0xB1:\n            case 0xB2:\n            case 0xB3:\n            case 0xB4:\n            case 0xB5:\n            case 0xB6:\n            case 0xB7:\n            case 0xB8:\n            case 0xB9:\n            case 0xBA:\n            case 0xBB:\n            case 0xBC:\n            case 0xBD:\n            case 0xBE:\n            case 0xBF:\n            {\n                string_t s;\n                return get_msgpack_string(s) and sax->string(s);\n            }\n\n            case 0xC0: // nil\n                return sax->null();\n\n            case 0xC2: // false\n                return sax->boolean(false);\n\n            case 0xC3: // true\n                return sax->boolean(true);\n\n            case 0xCA: // float 32\n            {\n                float number;\n                return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), \"\");\n            }\n\n            case 0xCB: // float 64\n            {\n                double number;\n                return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), \"\");\n            }\n\n            case 0xCC: // uint 8\n            {\n                uint8_t number;\n                return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);\n            }\n\n            case 0xCD: // uint 16\n            {\n                uint16_t number;\n                return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);\n            }\n\n            case 0xCE: // uint 32\n            {\n                uint32_t number;\n                return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);\n            }\n\n            case 0xCF: // uint 64\n            {\n                uint64_t number;\n                return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);\n            }\n\n            case 0xD0: // int 8\n            {\n                int8_t number;\n                return get_number(input_format_t::msgpack, number) and sax->number_integer(number);\n            }\n\n            case 0xD1: // int 16\n            {\n                int16_t number;\n                return get_number(input_format_t::msgpack, number) and sax->number_integer(number);\n            }\n\n            case 0xD2: // int 32\n            {\n                int32_t number;\n                return get_number(input_format_t::msgpack, number) and sax->number_integer(number);\n            }\n\n            case 0xD3: // int 64\n            {\n                int64_t number;\n                return get_number(input_format_t::msgpack, number) and sax->number_integer(number);\n            }\n\n            case 0xD9: // str 8\n            case 0xDA: // str 16\n            case 0xDB: // str 32\n            {\n                string_t s;\n                return get_msgpack_string(s) and sax->string(s);\n            }\n\n            case 0xDC: // array 16\n            {\n                uint16_t len;\n                return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));\n            }\n\n            case 0xDD: // array 32\n            {\n                uint32_t len;\n                return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));\n            }\n\n            case 0xDE: // map 16\n            {\n                uint16_t len;\n                return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));\n            }\n\n            case 0xDF: // map 32\n            {\n                uint32_t len;\n                return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));\n            }\n\n            // negative fixint\n            case 0xE0:\n            case 0xE1:\n            case 0xE2:\n            case 0xE3:\n            case 0xE4:\n            case 0xE5:\n            case 0xE6:\n            case 0xE7:\n            case 0xE8:\n            case 0xE9:\n            case 0xEA:\n            case 0xEB:\n            case 0xEC:\n            case 0xED:\n            case 0xEE:\n            case 0xEF:\n            case 0xF0:\n            case 0xF1:\n            case 0xF2:\n            case 0xF3:\n            case 0xF4:\n            case 0xF5:\n            case 0xF6:\n            case 0xF7:\n            case 0xF8:\n            case 0xF9:\n            case 0xFA:\n            case 0xFB:\n            case 0xFC:\n            case 0xFD:\n            case 0xFE:\n            case 0xFF:\n                return sax->number_integer(static_cast<int8_t>(current));\n\n            default: // anything else\n            {\n                auto last_token = get_token_string();\n                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, \"invalid byte: 0x\" + last_token, \"value\")));\n            }\n        }\n    }\n\n    /*!\n    @brief reads a MessagePack string\n\n    This function first reads starting bytes to determine the expected\n    string length and then copies this number of bytes into a string.\n\n    @param[out] result  created string\n\n    @return whether string creation completed\n    */\n    bool get_msgpack_string(string_t& result)\n    {\n        if (JSON_UNLIKELY(not unexpect_eof(input_format_t::msgpack, \"string\")))\n        {\n            return false;\n        }\n\n        switch (current)\n        {\n            // fixstr\n            case 0xA0:\n            case 0xA1:\n            case 0xA2:\n            case 0xA3:\n            case 0xA4:\n            case 0xA5:\n            case 0xA6:\n            case 0xA7:\n            case 0xA8:\n            case 0xA9:\n            case 0xAA:\n            case 0xAB:\n            case 0xAC:\n            case 0xAD:\n            case 0xAE:\n            case 0xAF:\n            case 0xB0:\n            case 0xB1:\n            case 0xB2:\n            case 0xB3:\n            case 0xB4:\n            case 0xB5:\n            case 0xB6:\n            case 0xB7:\n            case 0xB8:\n            case 0xB9:\n            case 0xBA:\n            case 0xBB:\n            case 0xBC:\n            case 0xBD:\n            case 0xBE:\n            case 0xBF:\n            {\n                return get_string(input_format_t::msgpack, current & 0x1F, result);\n            }\n\n            case 0xD9: // str 8\n            {\n                uint8_t len;\n                return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);\n            }\n\n            case 0xDA: // str 16\n            {\n                uint16_t len;\n                return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);\n            }\n\n            case 0xDB: // str 32\n            {\n                uint32_t len;\n                return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);\n            }\n\n            default:\n            {\n                auto last_token = get_token_string();\n                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, \"expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x\" + last_token, \"string\")));\n            }\n        }\n    }\n\n    /*!\n    @param[in] len  the length of the array\n    @return whether array creation completed\n    */\n    bool get_msgpack_array(const std::size_t len)\n    {\n        if (JSON_UNLIKELY(not sax->start_array(len)))\n        {\n            return false;\n        }\n\n        for (std::size_t i = 0; i < len; ++i)\n        {\n            if (JSON_UNLIKELY(not parse_msgpack_internal()))\n            {\n                return false;\n            }\n        }\n\n        return sax->end_array();\n    }\n\n    /*!\n    @param[in] len  the length of the object\n    @return whether object creation completed\n    */\n    bool get_msgpack_object(const std::size_t len)\n    {\n        if (JSON_UNLIKELY(not sax->start_object(len)))\n        {\n            return false;\n        }\n\n        string_t key;\n        for (std::size_t i = 0; i < len; ++i)\n        {\n            get();\n            if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))\n            {\n                return false;\n            }\n\n            if (JSON_UNLIKELY(not parse_msgpack_internal()))\n            {\n                return false;\n            }\n            key.clear();\n        }\n\n        return sax->end_object();\n    }\n\n    ////////////\n    // UBJSON //\n    ////////////\n\n    /*!\n    @param[in] get_char  whether a new character should be retrieved from the\n                         input (true, default) or whether the last read\n                         character should be considered instead\n\n    @return whether a valid UBJSON value was passed to the SAX parser\n    */\n    bool parse_ubjson_internal(const bool get_char = true)\n    {\n        return get_ubjson_value(get_char ? get_ignore_noop() : current);\n    }\n\n    /*!\n    @brief reads a UBJSON string\n\n    This function is either called after reading the 'S' byte explicitly\n    indicating a string, or in case of an object key where the 'S' byte can be\n    left out.\n\n    @param[out] result   created string\n    @param[in] get_char  whether a new character should be retrieved from the\n                         input (true, default) or whether the last read\n                         character should be considered instead\n\n    @return whether string creation completed\n    */\n    bool get_ubjson_string(string_t& result, const bool get_char = true)\n    {\n        if (get_char)\n        {\n            get();  // TODO: may we ignore N here?\n        }\n\n        if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, \"value\")))\n        {\n            return false;\n        }\n\n        switch (current)\n        {\n            case 'U':\n            {\n                uint8_t len;\n                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);\n            }\n\n            case 'i':\n            {\n                int8_t len;\n                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);\n            }\n\n            case 'I':\n            {\n                int16_t len;\n                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);\n            }\n\n            case 'l':\n            {\n                int32_t len;\n                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);\n            }\n\n            case 'L':\n            {\n                int64_t len;\n                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);\n            }\n\n            default:\n                auto last_token = get_token_string();\n                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, \"expected length type specification (U, i, I, l, L); last byte: 0x\" + last_token, \"string\")));\n        }\n    }\n\n    /*!\n    @param[out] result  determined size\n    @return whether size determination completed\n    */\n    bool get_ubjson_size_value(std::size_t& result)\n    {\n        switch (get_ignore_noop())\n        {\n            case 'U':\n            {\n                uint8_t number;\n                if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))\n                {\n                    return false;\n                }\n                result = static_cast<std::size_t>(number);\n                return true;\n            }\n\n            case 'i':\n            {\n                int8_t number;\n                if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))\n                {\n                    return false;\n                }\n                result = static_cast<std::size_t>(number);\n                return true;\n            }\n\n            case 'I':\n            {\n                int16_t number;\n                if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))\n                {\n                    return false;\n                }\n                result = static_cast<std::size_t>(number);\n                return true;\n            }\n\n            case 'l':\n            {\n                int32_t number;\n                if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))\n                {\n                    return false;\n                }\n                result = static_cast<std::size_t>(number);\n                return true;\n            }\n\n            case 'L':\n            {\n                int64_t number;\n                if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))\n                {\n                    return false;\n                }\n                result = static_cast<std::size_t>(number);\n                return true;\n            }\n\n            default:\n            {\n                auto last_token = get_token_string();\n                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, \"expected length type specification (U, i, I, l, L) after '#'; last byte: 0x\" + last_token, \"size\")));\n            }\n        }\n    }\n\n    /*!\n    @brief determine the type and size for a container\n\n    In the optimized UBJSON format, a type and a size can be provided to allow\n    for a more compact representation.\n\n    @param[out] result  pair of the size and the type\n\n    @return whether pair creation completed\n    */\n    bool get_ubjson_size_type(std::pair<std::size_t, int>& result)\n    {\n        result.first = string_t::npos; // size\n        result.second = 0; // type\n\n        get_ignore_noop();\n\n        if (current == '$')\n        {\n            result.second = get();  // must not ignore 'N', because 'N' maybe the type\n            if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, \"type\")))\n            {\n                return false;\n            }\n\n            get_ignore_noop();\n            if (JSON_UNLIKELY(current != '#'))\n            {\n                if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, \"value\")))\n                {\n                    return false;\n                }\n                auto last_token = get_token_string();\n                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, \"expected '#' after type information; last byte: 0x\" + last_token, \"size\")));\n            }\n\n            return get_ubjson_size_value(result.first);\n        }\n        else if (current == '#')\n        {\n            return get_ubjson_size_value(result.first);\n        }\n        return true;\n    }\n\n    /*!\n    @param prefix  the previously read or set type prefix\n    @return whether value creation completed\n    */\n    bool get_ubjson_value(const int prefix)\n    {\n        switch (prefix)\n        {\n            case std::char_traits<char>::eof():  // EOF\n                return unexpect_eof(input_format_t::ubjson, \"value\");\n\n            case 'T':  // true\n                return sax->boolean(true);\n            case 'F':  // false\n                return sax->boolean(false);\n\n            case 'Z':  // null\n                return sax->null();\n\n            case 'U':\n            {\n                uint8_t number;\n                return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);\n            }\n\n            case 'i':\n            {\n                int8_t number;\n                return get_number(input_format_t::ubjson, number) and sax->number_integer(number);\n            }\n\n            case 'I':\n            {\n                int16_t number;\n                return get_number(input_format_t::ubjson, number) and sax->number_integer(number);\n            }\n\n            case 'l':\n            {\n                int32_t number;\n                return get_number(input_format_t::ubjson, number) and sax->number_integer(number);\n            }\n\n            case 'L':\n            {\n                int64_t number;\n                return get_number(input_format_t::ubjson, number) and sax->number_integer(number);\n            }\n\n            case 'd':\n            {\n                float number;\n                return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), \"\");\n            }\n\n            case 'D':\n            {\n                double number;\n                return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), \"\");\n            }\n\n            case 'C':  // char\n            {\n                get();\n                if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, \"char\")))\n                {\n                    return false;\n                }\n                if (JSON_UNLIKELY(current > 127))\n                {\n                    auto last_token = get_token_string();\n                    return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, \"byte after 'C' must be in range 0x00..0x7F; last byte: 0x\" + last_token, \"char\")));\n                }\n                string_t s(1, static_cast<char>(current));\n                return sax->string(s);\n            }\n\n            case 'S':  // string\n            {\n                string_t s;\n                return get_ubjson_string(s) and sax->string(s);\n            }\n\n            case '[':  // array\n                return get_ubjson_array();\n\n            case '{':  // object\n                return get_ubjson_object();\n\n            default: // anything else\n            {\n                auto last_token = get_token_string();\n                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, \"invalid byte: 0x\" + last_token, \"value\")));\n            }\n        }\n    }\n\n    /*!\n    @return whether array creation completed\n    */\n    bool get_ubjson_array()\n    {\n        std::pair<std::size_t, int> size_and_type;\n        if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))\n        {\n            return false;\n        }\n\n        if (size_and_type.first != string_t::npos)\n        {\n            if (JSON_UNLIKELY(not sax->start_array(size_and_type.first)))\n            {\n                return false;\n            }\n\n            if (size_and_type.second != 0)\n            {\n                if (size_and_type.second != 'N')\n                {\n                    for (std::size_t i = 0; i < size_and_type.first; ++i)\n                    {\n                        if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))\n                        {\n                            return false;\n                        }\n                    }\n                }\n            }\n            else\n            {\n                for (std::size_t i = 0; i < size_and_type.first; ++i)\n                {\n                    if (JSON_UNLIKELY(not parse_ubjson_internal()))\n                    {\n                        return false;\n                    }\n                }\n            }\n        }\n        else\n        {\n            if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))\n            {\n                return false;\n            }\n\n            while (current != ']')\n            {\n                if (JSON_UNLIKELY(not parse_ubjson_internal(false)))\n                {\n                    return false;\n                }\n                get_ignore_noop();\n            }\n        }\n\n        return sax->end_array();\n    }\n\n    /*!\n    @return whether object creation completed\n    */\n    bool get_ubjson_object()\n    {\n        std::pair<std::size_t, int> size_and_type;\n        if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))\n        {\n            return false;\n        }\n\n        string_t key;\n        if (size_and_type.first != string_t::npos)\n        {\n            if (JSON_UNLIKELY(not sax->start_object(size_and_type.first)))\n            {\n                return false;\n            }\n\n            if (size_and_type.second != 0)\n            {\n                for (std::size_t i = 0; i < size_and_type.first; ++i)\n                {\n                    if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))\n                    {\n                        return false;\n                    }\n                    if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))\n                    {\n                        return false;\n                    }\n                    key.clear();\n                }\n            }\n            else\n            {\n                for (std::size_t i = 0; i < size_and_type.first; ++i)\n                {\n                    if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))\n                    {\n                        return false;\n                    }\n                    if (JSON_UNLIKELY(not parse_ubjson_internal()))\n                    {\n                        return false;\n                    }\n                    key.clear();\n                }\n            }\n        }\n        else\n        {\n            if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))\n            {\n                return false;\n            }\n\n            while (current != '}')\n            {\n                if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))\n                {\n                    return false;\n                }\n                if (JSON_UNLIKELY(not parse_ubjson_internal()))\n                {\n                    return false;\n                }\n                get_ignore_noop();\n                key.clear();\n            }\n        }\n\n        return sax->end_object();\n    }\n\n    ///////////////////////\n    // Utility functions //\n    ///////////////////////\n\n    /*!\n    @brief get next character from the input\n\n    This function provides the interface to the used input adapter. It does\n    not throw in case the input reached EOF, but returns a -'ve valued\n    `std::char_traits<char>::eof()` in that case.\n\n    @return character read from the input\n    */\n    int get()\n    {\n        ++chars_read;\n        return (current = ia->get_character());\n    }\n\n    /*!\n    @return character read from the input after ignoring all 'N' entries\n    */\n    int get_ignore_noop()\n    {\n        do\n        {\n            get();\n        }\n        while (current == 'N');\n\n        return current;\n    }\n\n    /*\n    @brief read a number from the input\n\n    @tparam NumberType the type of the number\n    @param[in] format   the current format (for diagnostics)\n    @param[out] result  number of type @a NumberType\n\n    @return whether conversion completed\n\n    @note This function needs to respect the system's endianess, because\n          bytes in CBOR, MessagePack, and UBJSON are stored in network order\n          (big endian) and therefore need reordering on little endian systems.\n    */\n    template<typename NumberType, bool InputIsLittleEndian = false>\n    bool get_number(const input_format_t format, NumberType& result)\n    {\n        // step 1: read input into array with system's byte order\n        std::array<uint8_t, sizeof(NumberType)> vec;\n        for (std::size_t i = 0; i < sizeof(NumberType); ++i)\n        {\n            get();\n            if (JSON_UNLIKELY(not unexpect_eof(format, \"number\")))\n            {\n                return false;\n            }\n\n            // reverse byte order prior to conversion if necessary\n            if (is_little_endian && !InputIsLittleEndian)\n            {\n                vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);\n            }\n            else\n            {\n                vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE\n            }\n        }\n\n        // step 2: convert array into number of type T and return\n        std::memcpy(&result, vec.data(), sizeof(NumberType));\n        return true;\n    }\n\n    /*!\n    @brief create a string by reading characters from the input\n\n    @tparam NumberType the type of the number\n    @param[in] format the current format (for diagnostics)\n    @param[in] len number of characters to read\n    @param[out] result string created by reading @a len bytes\n\n    @return whether string creation completed\n\n    @note We can not reserve @a len bytes for the result, because @a len\n          may be too large. Usually, @ref unexpect_eof() detects the end of\n          the input before we run out of string memory.\n    */\n    template<typename NumberType>\n    bool get_string(const input_format_t format,\n                    const NumberType len,\n                    string_t& result)\n    {\n        bool success = true;\n        std::generate_n(std::back_inserter(result), len, [this, &success, &format]()\n        {\n            get();\n            if (JSON_UNLIKELY(not unexpect_eof(format, \"string\")))\n            {\n                success = false;\n            }\n            return static_cast<char>(current);\n        });\n        return success;\n    }\n\n    /*!\n    @param[in] format   the current format (for diagnostics)\n    @param[in] context  further context information (for diagnostics)\n    @return whether the last read character is not EOF\n    */\n    bool unexpect_eof(const input_format_t format, const char* context) const\n    {\n        if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))\n        {\n            return sax->parse_error(chars_read, \"<end of file>\",\n                                    parse_error::create(110, chars_read, exception_message(format, \"unexpected end of input\", context)));\n        }\n        return true;\n    }\n\n    /*!\n    @return a string representation of the last read byte\n    */\n    std::string get_token_string() const\n    {\n        char cr[3];\n        (std::snprintf)(cr, 3, \"%.2hhX\", static_cast<unsigned char>(current));\n        return std::string{cr};\n    }\n\n    /*!\n    @param[in] format   the current format\n    @param[in] detail   a detailed error message\n    @param[in] context  further contect information\n    @return a message string to use in the parse_error exceptions\n    */\n    std::string exception_message(const input_format_t format,\n                                  const std::string& detail,\n                                  const std::string& context) const\n    {\n        std::string error_msg = \"syntax error while parsing \";\n\n        switch (format)\n        {\n            case input_format_t::cbor:\n                error_msg += \"CBOR\";\n                break;\n\n            case input_format_t::msgpack:\n                error_msg += \"MessagePack\";\n                break;\n\n            case input_format_t::ubjson:\n                error_msg += \"UBJSON\";\n                break;\n\n            case input_format_t::bson:\n                error_msg += \"BSON\";\n                break;\n\n            // LCOV_EXCL_START\n            default:\n                assert(false);\n                // LCOV_EXCL_STOP\n        }\n\n        return error_msg + \" \" + context + \": \" + detail;\n    }\n\n  private:\n    /// input adapter\n    input_adapter_t ia = nullptr;\n\n    /// the current character\n    int current = std::char_traits<char>::eof();\n\n    /// the number of characters read\n    std::size_t chars_read = 0;\n\n    /// whether we can assume little endianess\n    const bool is_little_endian = little_endianess();\n\n    /// the SAX parser\n    json_sax_t* sax = nullptr;\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/output/binary_writer.hpp>\n\n\n#include <algorithm> // reverse\n#include <array> // array\n#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t\n#include <cstring> // memcpy\n#include <limits> // numeric_limits\n\n// #include <nlohmann/detail/input/binary_reader.hpp>\n\n// #include <nlohmann/detail/output/output_adapters.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\n///////////////////\n// binary writer //\n///////////////////\n\n/*!\n@brief serialization to CBOR and MessagePack values\n*/\ntemplate<typename BasicJsonType, typename CharType>\nclass binary_writer\n{\n    using string_t = typename BasicJsonType::string_t;\n\n  public:\n    /*!\n    @brief create a binary writer\n\n    @param[in] adapter  output adapter to write to\n    */\n    explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)\n    {\n        assert(oa);\n    }\n\n    /*!\n    @param[in] j  JSON value to serialize\n    @pre       j.type() == value_t::object\n    */\n    void write_bson(const BasicJsonType& j)\n    {\n        switch (j.type())\n        {\n            case value_t::object:\n            {\n                write_bson_object(*j.m_value.object);\n                break;\n            }\n\n            default:\n            {\n                JSON_THROW(type_error::create(317, \"to serialize to BSON, top-level type must be object, but is \" + std::string(j.type_name())));\n            }\n        }\n    }\n\n    /*!\n    @param[in] j  JSON value to serialize\n    */\n    void write_cbor(const BasicJsonType& j)\n    {\n        switch (j.type())\n        {\n            case value_t::null:\n            {\n                oa->write_character(to_char_type(0xF6));\n                break;\n            }\n\n            case value_t::boolean:\n            {\n                oa->write_character(j.m_value.boolean\n                                    ? to_char_type(0xF5)\n                                    : to_char_type(0xF4));\n                break;\n            }\n\n            case value_t::number_integer:\n            {\n                if (j.m_value.number_integer >= 0)\n                {\n                    // CBOR does not differentiate between positive signed\n                    // integers and unsigned integers. Therefore, we used the\n                    // code from the value_t::number_unsigned case here.\n                    if (j.m_value.number_integer <= 0x17)\n                    {\n                        write_number(static_cast<uint8_t>(j.m_value.number_integer));\n                    }\n                    else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())\n                    {\n                        oa->write_character(to_char_type(0x18));\n                        write_number(static_cast<uint8_t>(j.m_value.number_integer));\n                    }\n                    else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())\n                    {\n                        oa->write_character(to_char_type(0x19));\n                        write_number(static_cast<uint16_t>(j.m_value.number_integer));\n                    }\n                    else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())\n                    {\n                        oa->write_character(to_char_type(0x1A));\n                        write_number(static_cast<uint32_t>(j.m_value.number_integer));\n                    }\n                    else\n                    {\n                        oa->write_character(to_char_type(0x1B));\n                        write_number(static_cast<uint64_t>(j.m_value.number_integer));\n                    }\n                }\n                else\n                {\n                    // The conversions below encode the sign in the first\n                    // byte, and the value is converted to a positive number.\n                    const auto positive_number = -1 - j.m_value.number_integer;\n                    if (j.m_value.number_integer >= -24)\n                    {\n                        write_number(static_cast<uint8_t>(0x20 + positive_number));\n                    }\n                    else if (positive_number <= (std::numeric_limits<uint8_t>::max)())\n                    {\n                        oa->write_character(to_char_type(0x38));\n                        write_number(static_cast<uint8_t>(positive_number));\n                    }\n                    else if (positive_number <= (std::numeric_limits<uint16_t>::max)())\n                    {\n                        oa->write_character(to_char_type(0x39));\n                        write_number(static_cast<uint16_t>(positive_number));\n                    }\n                    else if (positive_number <= (std::numeric_limits<uint32_t>::max)())\n                    {\n                        oa->write_character(to_char_type(0x3A));\n                        write_number(static_cast<uint32_t>(positive_number));\n                    }\n                    else\n                    {\n                        oa->write_character(to_char_type(0x3B));\n                        write_number(static_cast<uint64_t>(positive_number));\n                    }\n                }\n                break;\n            }\n\n            case value_t::number_unsigned:\n            {\n                if (j.m_value.number_unsigned <= 0x17)\n                {\n                    write_number(static_cast<uint8_t>(j.m_value.number_unsigned));\n                }\n                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())\n                {\n                    oa->write_character(to_char_type(0x18));\n                    write_number(static_cast<uint8_t>(j.m_value.number_unsigned));\n                }\n                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())\n                {\n                    oa->write_character(to_char_type(0x19));\n                    write_number(static_cast<uint16_t>(j.m_value.number_unsigned));\n                }\n                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())\n                {\n                    oa->write_character(to_char_type(0x1A));\n                    write_number(static_cast<uint32_t>(j.m_value.number_unsigned));\n                }\n                else\n                {\n                    oa->write_character(to_char_type(0x1B));\n                    write_number(static_cast<uint64_t>(j.m_value.number_unsigned));\n                }\n                break;\n            }\n\n            case value_t::number_float:\n            {\n                oa->write_character(get_cbor_float_prefix(j.m_value.number_float));\n                write_number(j.m_value.number_float);\n                break;\n            }\n\n            case value_t::string:\n            {\n                // step 1: write control byte and the string length\n                const auto N = j.m_value.string->size();\n                if (N <= 0x17)\n                {\n                    write_number(static_cast<uint8_t>(0x60 + N));\n                }\n                else if (N <= (std::numeric_limits<uint8_t>::max)())\n                {\n                    oa->write_character(to_char_type(0x78));\n                    write_number(static_cast<uint8_t>(N));\n                }\n                else if (N <= (std::numeric_limits<uint16_t>::max)())\n                {\n                    oa->write_character(to_char_type(0x79));\n                    write_number(static_cast<uint16_t>(N));\n                }\n                else if (N <= (std::numeric_limits<uint32_t>::max)())\n                {\n                    oa->write_character(to_char_type(0x7A));\n                    write_number(static_cast<uint32_t>(N));\n                }\n                // LCOV_EXCL_START\n                else if (N <= (std::numeric_limits<uint64_t>::max)())\n                {\n                    oa->write_character(to_char_type(0x7B));\n                    write_number(static_cast<uint64_t>(N));\n                }\n                // LCOV_EXCL_STOP\n\n                // step 2: write the string\n                oa->write_characters(\n                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),\n                    j.m_value.string->size());\n                break;\n            }\n\n            case value_t::array:\n            {\n                // step 1: write control byte and the array size\n                const auto N = j.m_value.array->size();\n                if (N <= 0x17)\n                {\n                    write_number(static_cast<uint8_t>(0x80 + N));\n                }\n                else if (N <= (std::numeric_limits<uint8_t>::max)())\n                {\n                    oa->write_character(to_char_type(0x98));\n                    write_number(static_cast<uint8_t>(N));\n                }\n                else if (N <= (std::numeric_limits<uint16_t>::max)())\n                {\n                    oa->write_character(to_char_type(0x99));\n                    write_number(static_cast<uint16_t>(N));\n                }\n                else if (N <= (std::numeric_limits<uint32_t>::max)())\n                {\n                    oa->write_character(to_char_type(0x9A));\n                    write_number(static_cast<uint32_t>(N));\n                }\n                // LCOV_EXCL_START\n                else if (N <= (std::numeric_limits<uint64_t>::max)())\n                {\n                    oa->write_character(to_char_type(0x9B));\n                    write_number(static_cast<uint64_t>(N));\n                }\n                // LCOV_EXCL_STOP\n\n                // step 2: write each element\n                for (const auto& el : *j.m_value.array)\n                {\n                    write_cbor(el);\n                }\n                break;\n            }\n\n            case value_t::object:\n            {\n                // step 1: write control byte and the object size\n                const auto N = j.m_value.object->size();\n                if (N <= 0x17)\n                {\n                    write_number(static_cast<uint8_t>(0xA0 + N));\n                }\n                else if (N <= (std::numeric_limits<uint8_t>::max)())\n                {\n                    oa->write_character(to_char_type(0xB8));\n                    write_number(static_cast<uint8_t>(N));\n                }\n                else if (N <= (std::numeric_limits<uint16_t>::max)())\n                {\n                    oa->write_character(to_char_type(0xB9));\n                    write_number(static_cast<uint16_t>(N));\n                }\n                else if (N <= (std::numeric_limits<uint32_t>::max)())\n                {\n                    oa->write_character(to_char_type(0xBA));\n                    write_number(static_cast<uint32_t>(N));\n                }\n                // LCOV_EXCL_START\n                else if (N <= (std::numeric_limits<uint64_t>::max)())\n                {\n                    oa->write_character(to_char_type(0xBB));\n                    write_number(static_cast<uint64_t>(N));\n                }\n                // LCOV_EXCL_STOP\n\n                // step 2: write each element\n                for (const auto& el : *j.m_value.object)\n                {\n                    write_cbor(el.first);\n                    write_cbor(el.second);\n                }\n                break;\n            }\n\n            default:\n                break;\n        }\n    }\n\n    /*!\n    @param[in] j  JSON value to serialize\n    */\n    void write_msgpack(const BasicJsonType& j)\n    {\n        switch (j.type())\n        {\n            case value_t::null: // nil\n            {\n                oa->write_character(to_char_type(0xC0));\n                break;\n            }\n\n            case value_t::boolean: // true and false\n            {\n                oa->write_character(j.m_value.boolean\n                                    ? to_char_type(0xC3)\n                                    : to_char_type(0xC2));\n                break;\n            }\n\n            case value_t::number_integer:\n            {\n                if (j.m_value.number_integer >= 0)\n                {\n                    // MessagePack does not differentiate between positive\n                    // signed integers and unsigned integers. Therefore, we used\n                    // the code from the value_t::number_unsigned case here.\n                    if (j.m_value.number_unsigned < 128)\n                    {\n                        // positive fixnum\n                        write_number(static_cast<uint8_t>(j.m_value.number_integer));\n                    }\n                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())\n                    {\n                        // uint 8\n                        oa->write_character(to_char_type(0xCC));\n                        write_number(static_cast<uint8_t>(j.m_value.number_integer));\n                    }\n                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())\n                    {\n                        // uint 16\n                        oa->write_character(to_char_type(0xCD));\n                        write_number(static_cast<uint16_t>(j.m_value.number_integer));\n                    }\n                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())\n                    {\n                        // uint 32\n                        oa->write_character(to_char_type(0xCE));\n                        write_number(static_cast<uint32_t>(j.m_value.number_integer));\n                    }\n                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())\n                    {\n                        // uint 64\n                        oa->write_character(to_char_type(0xCF));\n                        write_number(static_cast<uint64_t>(j.m_value.number_integer));\n                    }\n                }\n                else\n                {\n                    if (j.m_value.number_integer >= -32)\n                    {\n                        // negative fixnum\n                        write_number(static_cast<int8_t>(j.m_value.number_integer));\n                    }\n                    else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and\n                             j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())\n                    {\n                        // int 8\n                        oa->write_character(to_char_type(0xD0));\n                        write_number(static_cast<int8_t>(j.m_value.number_integer));\n                    }\n                    else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and\n                             j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())\n                    {\n                        // int 16\n                        oa->write_character(to_char_type(0xD1));\n                        write_number(static_cast<int16_t>(j.m_value.number_integer));\n                    }\n                    else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and\n                             j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())\n                    {\n                        // int 32\n                        oa->write_character(to_char_type(0xD2));\n                        write_number(static_cast<int32_t>(j.m_value.number_integer));\n                    }\n                    else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and\n                             j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())\n                    {\n                        // int 64\n                        oa->write_character(to_char_type(0xD3));\n                        write_number(static_cast<int64_t>(j.m_value.number_integer));\n                    }\n                }\n                break;\n            }\n\n            case value_t::number_unsigned:\n            {\n                if (j.m_value.number_unsigned < 128)\n                {\n                    // positive fixnum\n                    write_number(static_cast<uint8_t>(j.m_value.number_integer));\n                }\n                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())\n                {\n                    // uint 8\n                    oa->write_character(to_char_type(0xCC));\n                    write_number(static_cast<uint8_t>(j.m_value.number_integer));\n                }\n                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())\n                {\n                    // uint 16\n                    oa->write_character(to_char_type(0xCD));\n                    write_number(static_cast<uint16_t>(j.m_value.number_integer));\n                }\n                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())\n                {\n                    // uint 32\n                    oa->write_character(to_char_type(0xCE));\n                    write_number(static_cast<uint32_t>(j.m_value.number_integer));\n                }\n                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())\n                {\n                    // uint 64\n                    oa->write_character(to_char_type(0xCF));\n                    write_number(static_cast<uint64_t>(j.m_value.number_integer));\n                }\n                break;\n            }\n\n            case value_t::number_float:\n            {\n                oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));\n                write_number(j.m_value.number_float);\n                break;\n            }\n\n            case value_t::string:\n            {\n                // step 1: write control byte and the string length\n                const auto N = j.m_value.string->size();\n                if (N <= 31)\n                {\n                    // fixstr\n                    write_number(static_cast<uint8_t>(0xA0 | N));\n                }\n                else if (N <= (std::numeric_limits<uint8_t>::max)())\n                {\n                    // str 8\n                    oa->write_character(to_char_type(0xD9));\n                    write_number(static_cast<uint8_t>(N));\n                }\n                else if (N <= (std::numeric_limits<uint16_t>::max)())\n                {\n                    // str 16\n                    oa->write_character(to_char_type(0xDA));\n                    write_number(static_cast<uint16_t>(N));\n                }\n                else if (N <= (std::numeric_limits<uint32_t>::max)())\n                {\n                    // str 32\n                    oa->write_character(to_char_type(0xDB));\n                    write_number(static_cast<uint32_t>(N));\n                }\n\n                // step 2: write the string\n                oa->write_characters(\n                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),\n                    j.m_value.string->size());\n                break;\n            }\n\n            case value_t::array:\n            {\n                // step 1: write control byte and the array size\n                const auto N = j.m_value.array->size();\n                if (N <= 15)\n                {\n                    // fixarray\n                    write_number(static_cast<uint8_t>(0x90 | N));\n                }\n                else if (N <= (std::numeric_limits<uint16_t>::max)())\n                {\n                    // array 16\n                    oa->write_character(to_char_type(0xDC));\n                    write_number(static_cast<uint16_t>(N));\n                }\n                else if (N <= (std::numeric_limits<uint32_t>::max)())\n                {\n                    // array 32\n                    oa->write_character(to_char_type(0xDD));\n                    write_number(static_cast<uint32_t>(N));\n                }\n\n                // step 2: write each element\n                for (const auto& el : *j.m_value.array)\n                {\n                    write_msgpack(el);\n                }\n                break;\n            }\n\n            case value_t::object:\n            {\n                // step 1: write control byte and the object size\n                const auto N = j.m_value.object->size();\n                if (N <= 15)\n                {\n                    // fixmap\n                    write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));\n                }\n                else if (N <= (std::numeric_limits<uint16_t>::max)())\n                {\n                    // map 16\n                    oa->write_character(to_char_type(0xDE));\n                    write_number(static_cast<uint16_t>(N));\n                }\n                else if (N <= (std::numeric_limits<uint32_t>::max)())\n                {\n                    // map 32\n                    oa->write_character(to_char_type(0xDF));\n                    write_number(static_cast<uint32_t>(N));\n                }\n\n                // step 2: write each element\n                for (const auto& el : *j.m_value.object)\n                {\n                    write_msgpack(el.first);\n                    write_msgpack(el.second);\n                }\n                break;\n            }\n\n            default:\n                break;\n        }\n    }\n\n    /*!\n    @param[in] j  JSON value to serialize\n    @param[in] use_count   whether to use '#' prefixes (optimized format)\n    @param[in] use_type    whether to use '$' prefixes (optimized format)\n    @param[in] add_prefix  whether prefixes need to be used for this value\n    */\n    void write_ubjson(const BasicJsonType& j, const bool use_count,\n                      const bool use_type, const bool add_prefix = true)\n    {\n        switch (j.type())\n        {\n            case value_t::null:\n            {\n                if (add_prefix)\n                {\n                    oa->write_character(to_char_type('Z'));\n                }\n                break;\n            }\n\n            case value_t::boolean:\n            {\n                if (add_prefix)\n                {\n                    oa->write_character(j.m_value.boolean\n                                        ? to_char_type('T')\n                                        : to_char_type('F'));\n                }\n                break;\n            }\n\n            case value_t::number_integer:\n            {\n                write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);\n                break;\n            }\n\n            case value_t::number_unsigned:\n            {\n                write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);\n                break;\n            }\n\n            case value_t::number_float:\n            {\n                write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);\n                break;\n            }\n\n            case value_t::string:\n            {\n                if (add_prefix)\n                {\n                    oa->write_character(to_char_type('S'));\n                }\n                write_number_with_ubjson_prefix(j.m_value.string->size(), true);\n                oa->write_characters(\n                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),\n                    j.m_value.string->size());\n                break;\n            }\n\n            case value_t::array:\n            {\n                if (add_prefix)\n                {\n                    oa->write_character(to_char_type('['));\n                }\n\n                bool prefix_required = true;\n                if (use_type and not j.m_value.array->empty())\n                {\n                    assert(use_count);\n                    const CharType first_prefix = ubjson_prefix(j.front());\n                    const bool same_prefix = std::all_of(j.begin() + 1, j.end(),\n                                                         [this, first_prefix](const BasicJsonType & v)\n                    {\n                        return ubjson_prefix(v) == first_prefix;\n                    });\n\n                    if (same_prefix)\n                    {\n                        prefix_required = false;\n                        oa->write_character(to_char_type('$'));\n                        oa->write_character(first_prefix);\n                    }\n                }\n\n                if (use_count)\n                {\n                    oa->write_character(to_char_type('#'));\n                    write_number_with_ubjson_prefix(j.m_value.array->size(), true);\n                }\n\n                for (const auto& el : *j.m_value.array)\n                {\n                    write_ubjson(el, use_count, use_type, prefix_required);\n                }\n\n                if (not use_count)\n                {\n                    oa->write_character(to_char_type(']'));\n                }\n\n                break;\n            }\n\n            case value_t::object:\n            {\n                if (add_prefix)\n                {\n                    oa->write_character(to_char_type('{'));\n                }\n\n                bool prefix_required = true;\n                if (use_type and not j.m_value.object->empty())\n                {\n                    assert(use_count);\n                    const CharType first_prefix = ubjson_prefix(j.front());\n                    const bool same_prefix = std::all_of(j.begin(), j.end(),\n                                                         [this, first_prefix](const BasicJsonType & v)\n                    {\n                        return ubjson_prefix(v) == first_prefix;\n                    });\n\n                    if (same_prefix)\n                    {\n                        prefix_required = false;\n                        oa->write_character(to_char_type('$'));\n                        oa->write_character(first_prefix);\n                    }\n                }\n\n                if (use_count)\n                {\n                    oa->write_character(to_char_type('#'));\n                    write_number_with_ubjson_prefix(j.m_value.object->size(), true);\n                }\n\n                for (const auto& el : *j.m_value.object)\n                {\n                    write_number_with_ubjson_prefix(el.first.size(), true);\n                    oa->write_characters(\n                        reinterpret_cast<const CharType*>(el.first.c_str()),\n                        el.first.size());\n                    write_ubjson(el.second, use_count, use_type, prefix_required);\n                }\n\n                if (not use_count)\n                {\n                    oa->write_character(to_char_type('}'));\n                }\n\n                break;\n            }\n\n            default:\n                break;\n        }\n    }\n\n  private:\n    //////////\n    // BSON //\n    //////////\n\n    /*!\n    @return The size of a BSON document entry header, including the id marker\n            and the entry name size (and its null-terminator).\n    */\n    static std::size_t calc_bson_entry_header_size(const string_t& name)\n    {\n        const auto it = name.find(static_cast<typename string_t::value_type>(0));\n        if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos))\n        {\n            JSON_THROW(out_of_range::create(409,\n                                            \"BSON key cannot contain code point U+0000 (at byte \" + std::to_string(it) + \")\"));\n        }\n\n        return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;\n    }\n\n    /*!\n    @brief Writes the given @a element_type and @a name to the output adapter\n    */\n    void write_bson_entry_header(const string_t& name,\n                                 const std::uint8_t element_type)\n    {\n        oa->write_character(to_char_type(element_type)); // boolean\n        oa->write_characters(\n            reinterpret_cast<const CharType*>(name.c_str()),\n            name.size() + 1u);\n    }\n\n    /*!\n    @brief Writes a BSON element with key @a name and boolean value @a value\n    */\n    void write_bson_boolean(const string_t& name,\n                            const bool value)\n    {\n        write_bson_entry_header(name, 0x08);\n        oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));\n    }\n\n    /*!\n    @brief Writes a BSON element with key @a name and double value @a value\n    */\n    void write_bson_double(const string_t& name,\n                           const double value)\n    {\n        write_bson_entry_header(name, 0x01);\n        write_number<double, true>(value);\n    }\n\n    /*!\n    @return The size of the BSON-encoded string in @a value\n    */\n    static std::size_t calc_bson_string_size(const string_t& value)\n    {\n        return sizeof(std::int32_t) + value.size() + 1ul;\n    }\n\n    /*!\n    @brief Writes a BSON element with key @a name and string value @a value\n    */\n    void write_bson_string(const string_t& name,\n                           const string_t& value)\n    {\n        write_bson_entry_header(name, 0x02);\n\n        write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));\n        oa->write_characters(\n            reinterpret_cast<const CharType*>(value.c_str()),\n            value.size() + 1);\n    }\n\n    /*!\n    @brief Writes a BSON element with key @a name and null value\n    */\n    void write_bson_null(const string_t& name)\n    {\n        write_bson_entry_header(name, 0x0A);\n    }\n\n    /*!\n    @return The size of the BSON-encoded integer @a value\n    */\n    static std::size_t calc_bson_integer_size(const std::int64_t value)\n    {\n        if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())\n        {\n            return sizeof(std::int32_t);\n        }\n        else\n        {\n            return sizeof(std::int64_t);\n        }\n    }\n\n    /*!\n    @brief Writes a BSON element with key @a name and integer @a value\n    */\n    void write_bson_integer(const string_t& name,\n                            const std::int64_t value)\n    {\n        if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())\n        {\n            write_bson_entry_header(name, 0x10); // int32\n            write_number<std::int32_t, true>(static_cast<std::int32_t>(value));\n        }\n        else\n        {\n            write_bson_entry_header(name, 0x12); // int64\n            write_number<std::int64_t, true>(static_cast<std::int64_t>(value));\n        }\n    }\n\n    /*!\n    @return The size of the BSON-encoded unsigned integer in @a j\n    */\n    static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept\n    {\n        return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))\n               ? sizeof(std::int32_t)\n               : sizeof(std::int64_t);\n    }\n\n    /*!\n    @brief Writes a BSON element with key @a name and unsigned @a value\n    */\n    void write_bson_unsigned(const string_t& name,\n                             const std::uint64_t value)\n    {\n        if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))\n        {\n            write_bson_entry_header(name, 0x10 /* int32 */);\n            write_number<std::int32_t, true>(static_cast<std::int32_t>(value));\n        }\n        else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))\n        {\n            write_bson_entry_header(name, 0x12 /* int64 */);\n            write_number<std::int64_t, true>(static_cast<std::int64_t>(value));\n        }\n        else\n        {\n            JSON_THROW(out_of_range::create(407, \"integer number \" + std::to_string(value) + \" cannot be represented by BSON as it does not fit int64\"));\n        }\n    }\n\n    /*!\n    @brief Writes a BSON element with key @a name and object @a value\n    */\n    void write_bson_object_entry(const string_t& name,\n                                 const typename BasicJsonType::object_t& value)\n    {\n        write_bson_entry_header(name, 0x03); // object\n        write_bson_object(value);\n    }\n\n    /*!\n    @return The size of the BSON-encoded array @a value\n    */\n    static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)\n    {\n        std::size_t embedded_document_size = 0ul;\n        std::size_t array_index = 0ul;\n\n        for (const auto& el : value)\n        {\n            embedded_document_size += calc_bson_element_size(std::to_string(array_index++), el);\n        }\n\n        return sizeof(std::int32_t) + embedded_document_size + 1ul;\n    }\n\n    /*!\n    @brief Writes a BSON element with key @a name and array @a value\n    */\n    void write_bson_array(const string_t& name,\n                          const typename BasicJsonType::array_t& value)\n    {\n        write_bson_entry_header(name, 0x04); // array\n        write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));\n\n        std::size_t array_index = 0ul;\n\n        for (const auto& el : value)\n        {\n            write_bson_element(std::to_string(array_index++), el);\n        }\n\n        oa->write_character(to_char_type(0x00));\n    }\n\n    /*!\n    @brief Calculates the size necessary to serialize the JSON value @a j with its @a name\n    @return The calculated size for the BSON document entry for @a j with the given @a name.\n    */\n    static std::size_t calc_bson_element_size(const string_t& name,\n            const BasicJsonType& j)\n    {\n        const auto header_size = calc_bson_entry_header_size(name);\n        switch (j.type())\n        {\n            case value_t::object:\n                return header_size + calc_bson_object_size(*j.m_value.object);\n\n            case value_t::array:\n                return header_size + calc_bson_array_size(*j.m_value.array);\n\n            case value_t::boolean:\n                return header_size + 1ul;\n\n            case value_t::number_float:\n                return header_size + 8ul;\n\n            case value_t::number_integer:\n                return header_size + calc_bson_integer_size(j.m_value.number_integer);\n\n            case value_t::number_unsigned:\n                return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);\n\n            case value_t::string:\n                return header_size + calc_bson_string_size(*j.m_value.string);\n\n            case value_t::null:\n                return header_size + 0ul;\n\n            // LCOV_EXCL_START\n            default:\n                assert(false);\n                return 0ul;\n                // LCOV_EXCL_STOP\n        }\n    }\n\n    /*!\n    @brief Serializes the JSON value @a j to BSON and associates it with the\n           key @a name.\n    @param name The name to associate with the JSON entity @a j within the\n                current BSON document\n    @return The size of the BSON entry\n    */\n    void write_bson_element(const string_t& name,\n                            const BasicJsonType& j)\n    {\n        switch (j.type())\n        {\n            case value_t::object:\n                return write_bson_object_entry(name, *j.m_value.object);\n\n            case value_t::array:\n                return write_bson_array(name, *j.m_value.array);\n\n            case value_t::boolean:\n                return write_bson_boolean(name, j.m_value.boolean);\n\n            case value_t::number_float:\n                return write_bson_double(name, j.m_value.number_float);\n\n            case value_t::number_integer:\n                return write_bson_integer(name, j.m_value.number_integer);\n\n            case value_t::number_unsigned:\n                return write_bson_unsigned(name, j.m_value.number_unsigned);\n\n            case value_t::string:\n                return write_bson_string(name, *j.m_value.string);\n\n            case value_t::null:\n                return write_bson_null(name);\n\n            // LCOV_EXCL_START\n            default:\n                assert(false);\n                return;\n                // LCOV_EXCL_STOP\n        }\n    }\n\n    /*!\n    @brief Calculates the size of the BSON serialization of the given\n           JSON-object @a j.\n    @param[in] j  JSON value to serialize\n    @pre       j.type() == value_t::object\n    */\n    static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)\n    {\n        std::size_t document_size = std::accumulate(value.begin(), value.end(), 0ul,\n                                    [](size_t result, const typename BasicJsonType::object_t::value_type & el)\n        {\n            return result += calc_bson_element_size(el.first, el.second);\n        });\n\n        return sizeof(std::int32_t) + document_size + 1ul;\n    }\n\n    /*!\n    @param[in] j  JSON value to serialize\n    @pre       j.type() == value_t::object\n    */\n    void write_bson_object(const typename BasicJsonType::object_t& value)\n    {\n        write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));\n\n        for (const auto& el : value)\n        {\n            write_bson_element(el.first, el.second);\n        }\n\n        oa->write_character(to_char_type(0x00));\n    }\n\n    //////////\n    // CBOR //\n    //////////\n\n    static constexpr CharType get_cbor_float_prefix(float /*unused*/)\n    {\n        return to_char_type(0xFA);  // Single-Precision Float\n    }\n\n    static constexpr CharType get_cbor_float_prefix(double /*unused*/)\n    {\n        return to_char_type(0xFB);  // Double-Precision Float\n    }\n\n    /////////////\n    // MsgPack //\n    /////////////\n\n    static constexpr CharType get_msgpack_float_prefix(float /*unused*/)\n    {\n        return to_char_type(0xCA);  // float 32\n    }\n\n    static constexpr CharType get_msgpack_float_prefix(double /*unused*/)\n    {\n        return to_char_type(0xCB);  // float 64\n    }\n\n    ////////////\n    // UBJSON //\n    ////////////\n\n    // UBJSON: write number (floating point)\n    template<typename NumberType, typename std::enable_if<\n                 std::is_floating_point<NumberType>::value, int>::type = 0>\n    void write_number_with_ubjson_prefix(const NumberType n,\n                                         const bool add_prefix)\n    {\n        if (add_prefix)\n        {\n            oa->write_character(get_ubjson_float_prefix(n));\n        }\n        write_number(n);\n    }\n\n    // UBJSON: write number (unsigned integer)\n    template<typename NumberType, typename std::enable_if<\n                 std::is_unsigned<NumberType>::value, int>::type = 0>\n    void write_number_with_ubjson_prefix(const NumberType n,\n                                         const bool add_prefix)\n    {\n        if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))\n        {\n            if (add_prefix)\n            {\n                oa->write_character(to_char_type('i'));  // int8\n            }\n            write_number(static_cast<uint8_t>(n));\n        }\n        else if (n <= (std::numeric_limits<uint8_t>::max)())\n        {\n            if (add_prefix)\n            {\n                oa->write_character(to_char_type('U'));  // uint8\n            }\n            write_number(static_cast<uint8_t>(n));\n        }\n        else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)()))\n        {\n            if (add_prefix)\n            {\n                oa->write_character(to_char_type('I'));  // int16\n            }\n            write_number(static_cast<int16_t>(n));\n        }\n        else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))\n        {\n            if (add_prefix)\n            {\n                oa->write_character(to_char_type('l'));  // int32\n            }\n            write_number(static_cast<int32_t>(n));\n        }\n        else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))\n        {\n            if (add_prefix)\n            {\n                oa->write_character(to_char_type('L'));  // int64\n            }\n            write_number(static_cast<int64_t>(n));\n        }\n        else\n        {\n            JSON_THROW(out_of_range::create(407, \"integer number \" + std::to_string(n) + \" cannot be represented by UBJSON as it does not fit int64\"));\n        }\n    }\n\n    // UBJSON: write number (signed integer)\n    template<typename NumberType, typename std::enable_if<\n                 std::is_signed<NumberType>::value and\n                 not std::is_floating_point<NumberType>::value, int>::type = 0>\n    void write_number_with_ubjson_prefix(const NumberType n,\n                                         const bool add_prefix)\n    {\n        if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())\n        {\n            if (add_prefix)\n            {\n                oa->write_character(to_char_type('i'));  // int8\n            }\n            write_number(static_cast<int8_t>(n));\n        }\n        else if (static_cast<int64_t>((std::numeric_limits<uint8_t>::min)()) <= n and n <= static_cast<int64_t>((std::numeric_limits<uint8_t>::max)()))\n        {\n            if (add_prefix)\n            {\n                oa->write_character(to_char_type('U'));  // uint8\n            }\n            write_number(static_cast<uint8_t>(n));\n        }\n        else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())\n        {\n            if (add_prefix)\n            {\n                oa->write_character(to_char_type('I'));  // int16\n            }\n            write_number(static_cast<int16_t>(n));\n        }\n        else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())\n        {\n            if (add_prefix)\n            {\n                oa->write_character(to_char_type('l'));  // int32\n            }\n            write_number(static_cast<int32_t>(n));\n        }\n        else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())\n        {\n            if (add_prefix)\n            {\n                oa->write_character(to_char_type('L'));  // int64\n            }\n            write_number(static_cast<int64_t>(n));\n        }\n        // LCOV_EXCL_START\n        else\n        {\n            JSON_THROW(out_of_range::create(407, \"integer number \" + std::to_string(n) + \" cannot be represented by UBJSON as it does not fit int64\"));\n        }\n        // LCOV_EXCL_STOP\n    }\n\n    /*!\n    @brief determine the type prefix of container values\n\n    @note This function does not need to be 100% accurate when it comes to\n          integer limits. In case a number exceeds the limits of int64_t,\n          this will be detected by a later call to function\n          write_number_with_ubjson_prefix. Therefore, we return 'L' for any\n          value that does not fit the previous limits.\n    */\n    CharType ubjson_prefix(const BasicJsonType& j) const noexcept\n    {\n        switch (j.type())\n        {\n            case value_t::null:\n                return 'Z';\n\n            case value_t::boolean:\n                return j.m_value.boolean ? 'T' : 'F';\n\n            case value_t::number_integer:\n            {\n                if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())\n                {\n                    return 'i';\n                }\n                if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())\n                {\n                    return 'U';\n                }\n                if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())\n                {\n                    return 'I';\n                }\n                if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())\n                {\n                    return 'l';\n                }\n                // no check and assume int64_t (see note above)\n                return 'L';\n            }\n\n            case value_t::number_unsigned:\n            {\n                if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)())\n                {\n                    return 'i';\n                }\n                if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())\n                {\n                    return 'U';\n                }\n                if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)())\n                {\n                    return 'I';\n                }\n                if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)())\n                {\n                    return 'l';\n                }\n                // no check and assume int64_t (see note above)\n                return 'L';\n            }\n\n            case value_t::number_float:\n                return get_ubjson_float_prefix(j.m_value.number_float);\n\n            case value_t::string:\n                return 'S';\n\n            case value_t::array:\n                return '[';\n\n            case value_t::object:\n                return '{';\n\n            default:  // discarded values\n                return 'N';\n        }\n    }\n\n    static constexpr CharType get_ubjson_float_prefix(float /*unused*/)\n    {\n        return 'd';  // float 32\n    }\n\n    static constexpr CharType get_ubjson_float_prefix(double /*unused*/)\n    {\n        return 'D';  // float 64\n    }\n\n    ///////////////////////\n    // Utility functions //\n    ///////////////////////\n\n    /*\n    @brief write a number to output input\n    @param[in] n number of type @a NumberType\n    @tparam NumberType the type of the number\n    @tparam OutputIsLittleEndian Set to true if output data is\n                                 required to be little endian\n\n    @note This function needs to respect the system's endianess, because bytes\n          in CBOR, MessagePack, and UBJSON are stored in network order (big\n          endian) and therefore need reordering on little endian systems.\n    */\n    template<typename NumberType, bool OutputIsLittleEndian = false>\n    void write_number(const NumberType n)\n    {\n        // step 1: write number to array of length NumberType\n        std::array<CharType, sizeof(NumberType)> vec;\n        std::memcpy(vec.data(), &n, sizeof(NumberType));\n\n        // step 2: write array to output (with possible reordering)\n        if (is_little_endian and not OutputIsLittleEndian)\n        {\n            // reverse byte order prior to conversion if necessary\n            std::reverse(vec.begin(), vec.end());\n        }\n\n        oa->write_characters(vec.data(), sizeof(NumberType));\n    }\n\n  public:\n    // The following to_char_type functions are implement the conversion\n    // between uint8_t and CharType. In case CharType is not unsigned,\n    // such a conversion is required to allow values greater than 128.\n    // See <https://github.com/nlohmann/json/issues/1286> for a discussion.\n    template < typename C = CharType,\n               enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >\n    static constexpr CharType to_char_type(std::uint8_t x) noexcept\n    {\n        return *reinterpret_cast<char*>(&x);\n    }\n\n    template < typename C = CharType,\n               enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >\n    static CharType to_char_type(std::uint8_t x) noexcept\n    {\n        static_assert(sizeof(std::uint8_t) == sizeof(CharType), \"size of CharType must be equal to std::uint8_t\");\n        static_assert(std::is_pod<CharType>::value, \"CharType must be POD\");\n        CharType result;\n        std::memcpy(&result, &x, sizeof(x));\n        return result;\n    }\n\n    template<typename C = CharType,\n             enable_if_t<std::is_unsigned<C>::value>* = nullptr>\n    static constexpr CharType to_char_type(std::uint8_t x) noexcept\n    {\n        return x;\n    }\n\n    template < typename InputCharType, typename C = CharType,\n               enable_if_t <\n                   std::is_signed<C>::value and\n                   std::is_signed<char>::value and\n                   std::is_same<char, typename std::remove_cv<InputCharType>::type>::value\n                   > * = nullptr >\n    static constexpr CharType to_char_type(InputCharType x) noexcept\n    {\n        return x;\n    }\n\n  private:\n    /// whether we can assume little endianess\n    const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();\n\n    /// the output\n    output_adapter_t<CharType> oa = nullptr;\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/output/serializer.hpp>\n\n\n#include <algorithm> // reverse, remove, fill, find, none_of\n#include <array> // array\n#include <cassert> // assert\n#include <ciso646> // and, or\n#include <clocale> // localeconv, lconv\n#include <cmath> // labs, isfinite, isnan, signbit\n#include <cstddef> // size_t, ptrdiff_t\n#include <cstdint> // uint8_t\n#include <cstdio> // snprintf\n#include <limits> // numeric_limits\n#include <string> // string\n#include <type_traits> // is_same\n\n// #include <nlohmann/detail/exceptions.hpp>\n\n// #include <nlohmann/detail/conversions/to_chars.hpp>\n\n\n#include <cassert> // assert\n#include <ciso646> // or, and, not\n#include <cmath>   // signbit, isfinite\n#include <cstdint> // intN_t, uintN_t\n#include <cstring> // memcpy, memmove\n#include <limits> // numeric_limits\n#include <type_traits> // conditional\n\nnamespace nlohmann\n{\nnamespace detail\n{\n\n/*!\n@brief implements the Grisu2 algorithm for binary to decimal floating-point\nconversion.\n\nThis implementation is a slightly modified version of the reference\nimplementation which may be obtained from\nhttp://florian.loitsch.com/publications (bench.tar.gz).\n\nThe code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.\n\nFor a detailed description of the algorithm see:\n\n[1] Loitsch, \"Printing Floating-Point Numbers Quickly and Accurately with\n    Integers\", Proceedings of the ACM SIGPLAN 2010 Conference on Programming\n    Language Design and Implementation, PLDI 2010\n[2] Burger, Dybvig, \"Printing Floating-Point Numbers Quickly and Accurately\",\n    Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language\n    Design and Implementation, PLDI 1996\n*/\nnamespace dtoa_impl\n{\n\ntemplate <typename Target, typename Source>\nTarget reinterpret_bits(const Source source)\n{\n    static_assert(sizeof(Target) == sizeof(Source), \"size mismatch\");\n\n    Target target;\n    std::memcpy(&target, &source, sizeof(Source));\n    return target;\n}\n\nstruct diyfp // f * 2^e\n{\n    static constexpr int kPrecision = 64; // = q\n\n    uint64_t f = 0;\n    int e = 0;\n\n    constexpr diyfp(uint64_t f_, int e_) noexcept : f(f_), e(e_) {}\n\n    /*!\n    @brief returns x - y\n    @pre x.e == y.e and x.f >= y.f\n    */\n    static diyfp sub(const diyfp& x, const diyfp& y) noexcept\n    {\n        assert(x.e == y.e);\n        assert(x.f >= y.f);\n\n        return {x.f - y.f, x.e};\n    }\n\n    /*!\n    @brief returns x * y\n    @note The result is rounded. (Only the upper q bits are returned.)\n    */\n    static diyfp mul(const diyfp& x, const diyfp& y) noexcept\n    {\n        static_assert(kPrecision == 64, \"internal error\");\n\n        // Computes:\n        //  f = round((x.f * y.f) / 2^q)\n        //  e = x.e + y.e + q\n\n        // Emulate the 64-bit * 64-bit multiplication:\n        //\n        // p = u * v\n        //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)\n        //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )\n        //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )\n        //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )\n        //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)\n        //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )\n        //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )\n        //\n        // (Since Q might be larger than 2^32 - 1)\n        //\n        //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)\n        //\n        // (Q_hi + H does not overflow a 64-bit int)\n        //\n        //   = p_lo + 2^64 p_hi\n\n        const uint64_t u_lo = x.f & 0xFFFFFFFF;\n        const uint64_t u_hi = x.f >> 32;\n        const uint64_t v_lo = y.f & 0xFFFFFFFF;\n        const uint64_t v_hi = y.f >> 32;\n\n        const uint64_t p0 = u_lo * v_lo;\n        const uint64_t p1 = u_lo * v_hi;\n        const uint64_t p2 = u_hi * v_lo;\n        const uint64_t p3 = u_hi * v_hi;\n\n        const uint64_t p0_hi = p0 >> 32;\n        const uint64_t p1_lo = p1 & 0xFFFFFFFF;\n        const uint64_t p1_hi = p1 >> 32;\n        const uint64_t p2_lo = p2 & 0xFFFFFFFF;\n        const uint64_t p2_hi = p2 >> 32;\n\n        uint64_t Q = p0_hi + p1_lo + p2_lo;\n\n        // The full product might now be computed as\n        //\n        // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)\n        // p_lo = p0_lo + (Q << 32)\n        //\n        // But in this particular case here, the full p_lo is not required.\n        // Effectively we only need to add the highest bit in p_lo to p_hi (and\n        // Q_hi + 1 does not overflow).\n\n        Q += uint64_t{1} << (64 - 32 - 1); // round, ties up\n\n        const uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32);\n\n        return {h, x.e + y.e + 64};\n    }\n\n    /*!\n    @brief normalize x such that the significand is >= 2^(q-1)\n    @pre x.f != 0\n    */\n    static diyfp normalize(diyfp x) noexcept\n    {\n        assert(x.f != 0);\n\n        while ((x.f >> 63) == 0)\n        {\n            x.f <<= 1;\n            x.e--;\n        }\n\n        return x;\n    }\n\n    /*!\n    @brief normalize x such that the result has the exponent E\n    @pre e >= x.e and the upper e - x.e bits of x.f must be zero.\n    */\n    static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept\n    {\n        const int delta = x.e - target_exponent;\n\n        assert(delta >= 0);\n        assert(((x.f << delta) >> delta) == x.f);\n\n        return {x.f << delta, target_exponent};\n    }\n};\n\nstruct boundaries\n{\n    diyfp w;\n    diyfp minus;\n    diyfp plus;\n};\n\n/*!\nCompute the (normalized) diyfp representing the input number 'value' and its\nboundaries.\n\n@pre value must be finite and positive\n*/\ntemplate <typename FloatType>\nboundaries compute_boundaries(FloatType value)\n{\n    assert(std::isfinite(value));\n    assert(value > 0);\n\n    // Convert the IEEE representation into a diyfp.\n    //\n    // If v is denormal:\n    //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))\n    // If v is normalized:\n    //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))\n\n    static_assert(std::numeric_limits<FloatType>::is_iec559,\n                  \"internal error: dtoa_short requires an IEEE-754 floating-point implementation\");\n\n    constexpr int      kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)\n    constexpr int      kBias      = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);\n    constexpr int      kMinExp    = 1 - kBias;\n    constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1)\n\n    using bits_type = typename std::conditional< kPrecision == 24, uint32_t, uint64_t >::type;\n\n    const uint64_t bits = reinterpret_bits<bits_type>(value);\n    const uint64_t E = bits >> (kPrecision - 1);\n    const uint64_t F = bits & (kHiddenBit - 1);\n\n    const bool is_denormal = (E == 0);\n    const diyfp v = is_denormal\n                    ? diyfp(F, kMinExp)\n                    : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);\n\n    // Compute the boundaries m- and m+ of the floating-point value\n    // v = f * 2^e.\n    //\n    // Determine v- and v+, the floating-point predecessor and successor if v,\n    // respectively.\n    //\n    //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)\n    //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)\n    //\n    //      v+ = v + 2^e\n    //\n    // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_\n    // between m- and m+ round to v, regardless of how the input rounding\n    // algorithm breaks ties.\n    //\n    //      ---+-------------+-------------+-------------+-------------+---  (A)\n    //         v-            m-            v             m+            v+\n    //\n    //      -----------------+------+------+-------------+-------------+---  (B)\n    //                       v-     m-     v             m+            v+\n\n    const bool lower_boundary_is_closer = (F == 0 and E > 1);\n    const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);\n    const diyfp m_minus = lower_boundary_is_closer\n                          ? diyfp(4 * v.f - 1, v.e - 2)  // (B)\n                          : diyfp(2 * v.f - 1, v.e - 1); // (A)\n\n    // Determine the normalized w+ = m+.\n    const diyfp w_plus = diyfp::normalize(m_plus);\n\n    // Determine w- = m- such that e_(w-) = e_(w+).\n    const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);\n\n    return {diyfp::normalize(v), w_minus, w_plus};\n}\n\n// Given normalized diyfp w, Grisu needs to find a (normalized) cached\n// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies\n// within a certain range [alpha, gamma] (Definition 3.2 from [1])\n//\n//      alpha <= e = e_c + e_w + q <= gamma\n//\n// or\n//\n//      f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q\n//                          <= f_c * f_w * 2^gamma\n//\n// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies\n//\n//      2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma\n//\n// or\n//\n//      2^(q - 2 + alpha) <= c * w < 2^(q + gamma)\n//\n// The choice of (alpha,gamma) determines the size of the table and the form of\n// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well\n// in practice:\n//\n// The idea is to cut the number c * w = f * 2^e into two parts, which can be\n// processed independently: An integral part p1, and a fractional part p2:\n//\n//      f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e\n//              = (f div 2^-e) + (f mod 2^-e) * 2^e\n//              = p1 + p2 * 2^e\n//\n// The conversion of p1 into decimal form requires a series of divisions and\n// modulos by (a power of) 10. These operations are faster for 32-bit than for\n// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be\n// achieved by choosing\n//\n//      -e >= 32   or   e <= -32 := gamma\n//\n// In order to convert the fractional part\n//\n//      p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...\n//\n// into decimal form, the fraction is repeatedly multiplied by 10 and the digits\n// d[-i] are extracted in order:\n//\n//      (10 * p2) div 2^-e = d[-1]\n//      (10 * p2) mod 2^-e = d[-2] / 10^1 + ...\n//\n// The multiplication by 10 must not overflow. It is sufficient to choose\n//\n//      10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.\n//\n// Since p2 = f mod 2^-e < 2^-e,\n//\n//      -e <= 60   or   e >= -60 := alpha\n\nconstexpr int kAlpha = -60;\nconstexpr int kGamma = -32;\n\nstruct cached_power // c = f * 2^e ~= 10^k\n{\n    uint64_t f;\n    int e;\n    int k;\n};\n\n/*!\nFor a normalized diyfp w = f * 2^e, this function returns a (normalized) cached\npower-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c\nsatisfies (Definition 3.2 from [1])\n\n     alpha <= e_c + e + q <= gamma.\n*/\ninline cached_power get_cached_power_for_binary_exponent(int e)\n{\n    // Now\n    //\n    //      alpha <= e_c + e + q <= gamma                                    (1)\n    //      ==> f_c * 2^alpha <= c * 2^e * 2^q\n    //\n    // and since the c's are normalized, 2^(q-1) <= f_c,\n    //\n    //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)\n    //      ==> 2^(alpha - e - 1) <= c\n    //\n    // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as\n    //\n    //      k = ceil( log_10( 2^(alpha - e - 1) ) )\n    //        = ceil( (alpha - e - 1) * log_10(2) )\n    //\n    // From the paper:\n    // \"In theory the result of the procedure could be wrong since c is rounded,\n    //  and the computation itself is approximated [...]. In practice, however,\n    //  this simple function is sufficient.\"\n    //\n    // For IEEE double precision floating-point numbers converted into\n    // normalized diyfp's w = f * 2^e, with q = 64,\n    //\n    //      e >= -1022      (min IEEE exponent)\n    //           -52        (p - 1)\n    //           -52        (p - 1, possibly normalize denormal IEEE numbers)\n    //           -11        (normalize the diyfp)\n    //         = -1137\n    //\n    // and\n    //\n    //      e <= +1023      (max IEEE exponent)\n    //           -52        (p - 1)\n    //           -11        (normalize the diyfp)\n    //         = 960\n    //\n    // This binary exponent range [-1137,960] results in a decimal exponent\n    // range [-307,324]. One does not need to store a cached power for each\n    // k in this range. For each such k it suffices to find a cached power\n    // such that the exponent of the product lies in [alpha,gamma].\n    // This implies that the difference of the decimal exponents of adjacent\n    // table entries must be less than or equal to\n    //\n    //      floor( (gamma - alpha) * log_10(2) ) = 8.\n    //\n    // (A smaller distance gamma-alpha would require a larger table.)\n\n    // NB:\n    // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.\n\n    constexpr int kCachedPowersSize = 79;\n    constexpr int kCachedPowersMinDecExp = -300;\n    constexpr int kCachedPowersDecStep = 8;\n\n    static constexpr cached_power kCachedPowers[] =\n    {\n        { 0xAB70FE17C79AC6CA, -1060, -300 },\n        { 0xFF77B1FCBEBCDC4F, -1034, -292 },\n        { 0xBE5691EF416BD60C, -1007, -284 },\n        { 0x8DD01FAD907FFC3C,  -980, -276 },\n        { 0xD3515C2831559A83,  -954, -268 },\n        { 0x9D71AC8FADA6C9B5,  -927, -260 },\n        { 0xEA9C227723EE8BCB,  -901, -252 },\n        { 0xAECC49914078536D,  -874, -244 },\n        { 0x823C12795DB6CE57,  -847, -236 },\n        { 0xC21094364DFB5637,  -821, -228 },\n        { 0x9096EA6F3848984F,  -794, -220 },\n        { 0xD77485CB25823AC7,  -768, -212 },\n        { 0xA086CFCD97BF97F4,  -741, -204 },\n        { 0xEF340A98172AACE5,  -715, -196 },\n        { 0xB23867FB2A35B28E,  -688, -188 },\n        { 0x84C8D4DFD2C63F3B,  -661, -180 },\n        { 0xC5DD44271AD3CDBA,  -635, -172 },\n        { 0x936B9FCEBB25C996,  -608, -164 },\n        { 0xDBAC6C247D62A584,  -582, -156 },\n        { 0xA3AB66580D5FDAF6,  -555, -148 },\n        { 0xF3E2F893DEC3F126,  -529, -140 },\n        { 0xB5B5ADA8AAFF80B8,  -502, -132 },\n        { 0x87625F056C7C4A8B,  -475, -124 },\n        { 0xC9BCFF6034C13053,  -449, -116 },\n        { 0x964E858C91BA2655,  -422, -108 },\n        { 0xDFF9772470297EBD,  -396, -100 },\n        { 0xA6DFBD9FB8E5B88F,  -369,  -92 },\n        { 0xF8A95FCF88747D94,  -343,  -84 },\n        { 0xB94470938FA89BCF,  -316,  -76 },\n        { 0x8A08F0F8BF0F156B,  -289,  -68 },\n        { 0xCDB02555653131B6,  -263,  -60 },\n        { 0x993FE2C6D07B7FAC,  -236,  -52 },\n        { 0xE45C10C42A2B3B06,  -210,  -44 },\n        { 0xAA242499697392D3,  -183,  -36 },\n        { 0xFD87B5F28300CA0E,  -157,  -28 },\n        { 0xBCE5086492111AEB,  -130,  -20 },\n        { 0x8CBCCC096F5088CC,  -103,  -12 },\n        { 0xD1B71758E219652C,   -77,   -4 },\n        { 0x9C40000000000000,   -50,    4 },\n        { 0xE8D4A51000000000,   -24,   12 },\n        { 0xAD78EBC5AC620000,     3,   20 },\n        { 0x813F3978F8940984,    30,   28 },\n        { 0xC097CE7BC90715B3,    56,   36 },\n        { 0x8F7E32CE7BEA5C70,    83,   44 },\n        { 0xD5D238A4ABE98068,   109,   52 },\n        { 0x9F4F2726179A2245,   136,   60 },\n        { 0xED63A231D4C4FB27,   162,   68 },\n        { 0xB0DE65388CC8ADA8,   189,   76 },\n        { 0x83C7088E1AAB65DB,   216,   84 },\n        { 0xC45D1DF942711D9A,   242,   92 },\n        { 0x924D692CA61BE758,   269,  100 },\n        { 0xDA01EE641A708DEA,   295,  108 },\n        { 0xA26DA3999AEF774A,   322,  116 },\n        { 0xF209787BB47D6B85,   348,  124 },\n        { 0xB454E4A179DD1877,   375,  132 },\n        { 0x865B86925B9BC5C2,   402,  140 },\n        { 0xC83553C5C8965D3D,   428,  148 },\n        { 0x952AB45CFA97A0B3,   455,  156 },\n        { 0xDE469FBD99A05FE3,   481,  164 },\n        { 0xA59BC234DB398C25,   508,  172 },\n        { 0xF6C69A72A3989F5C,   534,  180 },\n        { 0xB7DCBF5354E9BECE,   561,  188 },\n        { 0x88FCF317F22241E2,   588,  196 },\n        { 0xCC20CE9BD35C78A5,   614,  204 },\n        { 0x98165AF37B2153DF,   641,  212 },\n        { 0xE2A0B5DC971F303A,   667,  220 },\n        { 0xA8D9D1535CE3B396,   694,  228 },\n        { 0xFB9B7CD9A4A7443C,   720,  236 },\n        { 0xBB764C4CA7A44410,   747,  244 },\n        { 0x8BAB8EEFB6409C1A,   774,  252 },\n        { 0xD01FEF10A657842C,   800,  260 },\n        { 0x9B10A4E5E9913129,   827,  268 },\n        { 0xE7109BFBA19C0C9D,   853,  276 },\n        { 0xAC2820D9623BF429,   880,  284 },\n        { 0x80444B5E7AA7CF85,   907,  292 },\n        { 0xBF21E44003ACDD2D,   933,  300 },\n        { 0x8E679C2F5E44FF8F,   960,  308 },\n        { 0xD433179D9C8CB841,   986,  316 },\n        { 0x9E19DB92B4E31BA9,  1013,  324 },\n    };\n\n    // This computation gives exactly the same results for k as\n    //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)\n    // for |e| <= 1500, but doesn't require floating-point operations.\n    // NB: log_10(2) ~= 78913 / 2^18\n    assert(e >= -1500);\n    assert(e <=  1500);\n    const int f = kAlpha - e - 1;\n    const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);\n\n    const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;\n    assert(index >= 0);\n    assert(index < kCachedPowersSize);\n    static_cast<void>(kCachedPowersSize); // Fix warning.\n\n    const cached_power cached = kCachedPowers[index];\n    assert(kAlpha <= cached.e + e + 64);\n    assert(kGamma >= cached.e + e + 64);\n\n    return cached;\n}\n\n/*!\nFor n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.\nFor n == 0, returns 1 and sets pow10 := 1.\n*/\ninline int find_largest_pow10(const uint32_t n, uint32_t& pow10)\n{\n    // LCOV_EXCL_START\n    if (n >= 1000000000)\n    {\n        pow10 = 1000000000;\n        return 10;\n    }\n    // LCOV_EXCL_STOP\n    else if (n >= 100000000)\n    {\n        pow10 = 100000000;\n        return  9;\n    }\n    else if (n >= 10000000)\n    {\n        pow10 = 10000000;\n        return  8;\n    }\n    else if (n >= 1000000)\n    {\n        pow10 = 1000000;\n        return  7;\n    }\n    else if (n >= 100000)\n    {\n        pow10 = 100000;\n        return  6;\n    }\n    else if (n >= 10000)\n    {\n        pow10 = 10000;\n        return  5;\n    }\n    else if (n >= 1000)\n    {\n        pow10 = 1000;\n        return  4;\n    }\n    else if (n >= 100)\n    {\n        pow10 = 100;\n        return  3;\n    }\n    else if (n >= 10)\n    {\n        pow10 = 10;\n        return  2;\n    }\n    else\n    {\n        pow10 = 1;\n        return 1;\n    }\n}\n\ninline void grisu2_round(char* buf, int len, uint64_t dist, uint64_t delta,\n                         uint64_t rest, uint64_t ten_k)\n{\n    assert(len >= 1);\n    assert(dist <= delta);\n    assert(rest <= delta);\n    assert(ten_k > 0);\n\n    //               <--------------------------- delta ---->\n    //                                  <---- dist --------->\n    // --------------[------------------+-------------------]--------------\n    //               M-                 w                   M+\n    //\n    //                                  ten_k\n    //                                <------>\n    //                                       <---- rest ---->\n    // --------------[------------------+----+--------------]--------------\n    //                                  w    V\n    //                                       = buf * 10^k\n    //\n    // ten_k represents a unit-in-the-last-place in the decimal representation\n    // stored in buf.\n    // Decrement buf by ten_k while this takes buf closer to w.\n\n    // The tests are written in this order to avoid overflow in unsigned\n    // integer arithmetic.\n\n    while (rest < dist\n            and delta - rest >= ten_k\n            and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))\n    {\n        assert(buf[len - 1] != '0');\n        buf[len - 1]--;\n        rest += ten_k;\n    }\n}\n\n/*!\nGenerates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.\nM- and M+ must be normalized and share the same exponent -60 <= e <= -32.\n*/\ninline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,\n                             diyfp M_minus, diyfp w, diyfp M_plus)\n{\n    static_assert(kAlpha >= -60, \"internal error\");\n    static_assert(kGamma <= -32, \"internal error\");\n\n    // Generates the digits (and the exponent) of a decimal floating-point\n    // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's\n    // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.\n    //\n    //               <--------------------------- delta ---->\n    //                                  <---- dist --------->\n    // --------------[------------------+-------------------]--------------\n    //               M-                 w                   M+\n    //\n    // Grisu2 generates the digits of M+ from left to right and stops as soon as\n    // V is in [M-,M+].\n\n    assert(M_plus.e >= kAlpha);\n    assert(M_plus.e <= kGamma);\n\n    uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)\n    uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)\n\n    // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):\n    //\n    //      M+ = f * 2^e\n    //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e\n    //         = ((p1        ) * 2^-e + (p2        )) * 2^e\n    //         = p1 + p2 * 2^e\n\n    const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e);\n\n    auto p1 = static_cast<uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)\n    uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e\n\n    // 1)\n    //\n    // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]\n\n    assert(p1 > 0);\n\n    uint32_t pow10;\n    const int k = find_largest_pow10(p1, pow10);\n\n    //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)\n    //\n    //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))\n    //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))\n    //\n    //      M+ = p1                                             + p2 * 2^e\n    //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e\n    //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e\n    //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e\n    //\n    // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)\n    //\n    //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]\n    //\n    // but stop as soon as\n    //\n    //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e\n\n    int n = k;\n    while (n > 0)\n    {\n        // Invariants:\n        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)\n        //      pow10 = 10^(n-1) <= p1 < 10^n\n        //\n        const uint32_t d = p1 / pow10;  // d = p1 div 10^(n-1)\n        const uint32_t r = p1 % pow10;  // r = p1 mod 10^(n-1)\n        //\n        //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e\n        //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)\n        //\n        assert(d <= 9);\n        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d\n        //\n        //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)\n        //\n        p1 = r;\n        n--;\n        //\n        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)\n        //      pow10 = 10^n\n        //\n\n        // Now check if enough digits have been generated.\n        // Compute\n        //\n        //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e\n        //\n        // Note:\n        // Since rest and delta share the same exponent e, it suffices to\n        // compare the significands.\n        const uint64_t rest = (uint64_t{p1} << -one.e) + p2;\n        if (rest <= delta)\n        {\n            // V = buffer * 10^n, with M- <= V <= M+.\n\n            decimal_exponent += n;\n\n            // We may now just stop. But instead look if the buffer could be\n            // decremented to bring V closer to w.\n            //\n            // pow10 = 10^n is now 1 ulp in the decimal representation V.\n            // The rounding procedure works with diyfp's with an implicit\n            // exponent of e.\n            //\n            //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e\n            //\n            const uint64_t ten_n = uint64_t{pow10} << -one.e;\n            grisu2_round(buffer, length, dist, delta, rest, ten_n);\n\n            return;\n        }\n\n        pow10 /= 10;\n        //\n        //      pow10 = 10^(n-1) <= p1 < 10^n\n        // Invariants restored.\n    }\n\n    // 2)\n    //\n    // The digits of the integral part have been generated:\n    //\n    //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e\n    //         = buffer            + p2 * 2^e\n    //\n    // Now generate the digits of the fractional part p2 * 2^e.\n    //\n    // Note:\n    // No decimal point is generated: the exponent is adjusted instead.\n    //\n    // p2 actually represents the fraction\n    //\n    //      p2 * 2^e\n    //          = p2 / 2^-e\n    //          = d[-1] / 10^1 + d[-2] / 10^2 + ...\n    //\n    // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)\n    //\n    //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m\n    //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)\n    //\n    // using\n    //\n    //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)\n    //                = (                   d) * 2^-e + (                   r)\n    //\n    // or\n    //      10^m * p2 * 2^e = d + r * 2^e\n    //\n    // i.e.\n    //\n    //      M+ = buffer + p2 * 2^e\n    //         = buffer + 10^-m * (d + r * 2^e)\n    //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e\n    //\n    // and stop as soon as 10^-m * r * 2^e <= delta * 2^e\n\n    assert(p2 > delta);\n\n    int m = 0;\n    for (;;)\n    {\n        // Invariant:\n        //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e\n        //         = buffer * 10^-m + 10^-m * (p2                                 ) * 2^e\n        //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e\n        //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e\n        //\n        assert(p2 <= UINT64_MAX / 10);\n        p2 *= 10;\n        const uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e\n        const uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e\n        //\n        //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e\n        //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))\n        //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e\n        //\n        assert(d <= 9);\n        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d\n        //\n        //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e\n        //\n        p2 = r;\n        m++;\n        //\n        //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e\n        // Invariant restored.\n\n        // Check if enough digits have been generated.\n        //\n        //      10^-m * p2 * 2^e <= delta * 2^e\n        //              p2 * 2^e <= 10^m * delta * 2^e\n        //                    p2 <= 10^m * delta\n        delta *= 10;\n        dist  *= 10;\n        if (p2 <= delta)\n        {\n            break;\n        }\n    }\n\n    // V = buffer * 10^-m, with M- <= V <= M+.\n\n    decimal_exponent -= m;\n\n    // 1 ulp in the decimal representation is now 10^-m.\n    // Since delta and dist are now scaled by 10^m, we need to do the\n    // same with ulp in order to keep the units in sync.\n    //\n    //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e\n    //\n    const uint64_t ten_m = one.f;\n    grisu2_round(buffer, length, dist, delta, p2, ten_m);\n\n    // By construction this algorithm generates the shortest possible decimal\n    // number (Loitsch, Theorem 6.2) which rounds back to w.\n    // For an input number of precision p, at least\n    //\n    //      N = 1 + ceil(p * log_10(2))\n    //\n    // decimal digits are sufficient to identify all binary floating-point\n    // numbers (Matula, \"In-and-Out conversions\").\n    // This implies that the algorithm does not produce more than N decimal\n    // digits.\n    //\n    //      N = 17 for p = 53 (IEEE double precision)\n    //      N = 9  for p = 24 (IEEE single precision)\n}\n\n/*!\nv = buf * 10^decimal_exponent\nlen is the length of the buffer (number of decimal digits)\nThe buffer must be large enough, i.e. >= max_digits10.\n*/\ninline void grisu2(char* buf, int& len, int& decimal_exponent,\n                   diyfp m_minus, diyfp v, diyfp m_plus)\n{\n    assert(m_plus.e == m_minus.e);\n    assert(m_plus.e == v.e);\n\n    //  --------(-----------------------+-----------------------)--------    (A)\n    //          m-                      v                       m+\n    //\n    //  --------------------(-----------+-----------------------)--------    (B)\n    //                      m-          v                       m+\n    //\n    // First scale v (and m- and m+) such that the exponent is in the range\n    // [alpha, gamma].\n\n    const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);\n\n    const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k\n\n    // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]\n    const diyfp w       = diyfp::mul(v,       c_minus_k);\n    const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);\n    const diyfp w_plus  = diyfp::mul(m_plus,  c_minus_k);\n\n    //  ----(---+---)---------------(---+---)---------------(---+---)----\n    //          w-                      w                       w+\n    //          = c*m-                  = c*v                   = c*m+\n    //\n    // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and\n    // w+ are now off by a small amount.\n    // In fact:\n    //\n    //      w - v * 10^k < 1 ulp\n    //\n    // To account for this inaccuracy, add resp. subtract 1 ulp.\n    //\n    //  --------+---[---------------(---+---)---------------]---+--------\n    //          w-  M-                  w                   M+  w+\n    //\n    // Now any number in [M-, M+] (bounds included) will round to w when input,\n    // regardless of how the input rounding algorithm breaks ties.\n    //\n    // And digit_gen generates the shortest possible such number in [M-, M+].\n    // Note that this does not mean that Grisu2 always generates the shortest\n    // possible number in the interval (m-, m+).\n    const diyfp M_minus(w_minus.f + 1, w_minus.e);\n    const diyfp M_plus (w_plus.f  - 1, w_plus.e );\n\n    decimal_exponent = -cached.k; // = -(-k) = k\n\n    grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);\n}\n\n/*!\nv = buf * 10^decimal_exponent\nlen is the length of the buffer (number of decimal digits)\nThe buffer must be large enough, i.e. >= max_digits10.\n*/\ntemplate <typename FloatType>\nvoid grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)\n{\n    static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,\n                  \"internal error: not enough precision\");\n\n    assert(std::isfinite(value));\n    assert(value > 0);\n\n    // If the neighbors (and boundaries) of 'value' are always computed for double-precision\n    // numbers, all float's can be recovered using strtod (and strtof). However, the resulting\n    // decimal representations are not exactly \"short\".\n    //\n    // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)\n    // says \"value is converted to a string as if by std::sprintf in the default (\"C\") locale\"\n    // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'\n    // does.\n    // On the other hand, the documentation for 'std::to_chars' requires that \"parsing the\n    // representation using the corresponding std::from_chars function recovers value exactly\". That\n    // indicates that single precision floating-point numbers should be recovered using\n    // 'std::strtof'.\n    //\n    // NB: If the neighbors are computed for single-precision numbers, there is a single float\n    //     (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision\n    //     value is off by 1 ulp.\n#if 0\n    const boundaries w = compute_boundaries(static_cast<double>(value));\n#else\n    const boundaries w = compute_boundaries(value);\n#endif\n\n    grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);\n}\n\n/*!\n@brief appends a decimal representation of e to buf\n@return a pointer to the element following the exponent.\n@pre -1000 < e < 1000\n*/\ninline char* append_exponent(char* buf, int e)\n{\n    assert(e > -1000);\n    assert(e <  1000);\n\n    if (e < 0)\n    {\n        e = -e;\n        *buf++ = '-';\n    }\n    else\n    {\n        *buf++ = '+';\n    }\n\n    auto k = static_cast<uint32_t>(e);\n    if (k < 10)\n    {\n        // Always print at least two digits in the exponent.\n        // This is for compatibility with printf(\"%g\").\n        *buf++ = '0';\n        *buf++ = static_cast<char>('0' + k);\n    }\n    else if (k < 100)\n    {\n        *buf++ = static_cast<char>('0' + k / 10);\n        k %= 10;\n        *buf++ = static_cast<char>('0' + k);\n    }\n    else\n    {\n        *buf++ = static_cast<char>('0' + k / 100);\n        k %= 100;\n        *buf++ = static_cast<char>('0' + k / 10);\n        k %= 10;\n        *buf++ = static_cast<char>('0' + k);\n    }\n\n    return buf;\n}\n\n/*!\n@brief prettify v = buf * 10^decimal_exponent\n\nIf v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point\nnotation. Otherwise it will be printed in exponential notation.\n\n@pre min_exp < 0\n@pre max_exp > 0\n*/\ninline char* format_buffer(char* buf, int len, int decimal_exponent,\n                           int min_exp, int max_exp)\n{\n    assert(min_exp < 0);\n    assert(max_exp > 0);\n\n    const int k = len;\n    const int n = len + decimal_exponent;\n\n    // v = buf * 10^(n-k)\n    // k is the length of the buffer (number of decimal digits)\n    // n is the position of the decimal point relative to the start of the buffer.\n\n    if (k <= n and n <= max_exp)\n    {\n        // digits[000]\n        // len <= max_exp + 2\n\n        std::memset(buf + k, '0', static_cast<size_t>(n - k));\n        // Make it look like a floating-point number (#362, #378)\n        buf[n + 0] = '.';\n        buf[n + 1] = '0';\n        return buf + (n + 2);\n    }\n\n    if (0 < n and n <= max_exp)\n    {\n        // dig.its\n        // len <= max_digits10 + 1\n\n        assert(k > n);\n\n        std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n));\n        buf[n] = '.';\n        return buf + (k + 1);\n    }\n\n    if (min_exp < n and n <= 0)\n    {\n        // 0.[000]digits\n        // len <= 2 + (-min_exp - 1) + max_digits10\n\n        std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k));\n        buf[0] = '0';\n        buf[1] = '.';\n        std::memset(buf + 2, '0', static_cast<size_t>(-n));\n        return buf + (2 + (-n) + k);\n    }\n\n    if (k == 1)\n    {\n        // dE+123\n        // len <= 1 + 5\n\n        buf += 1;\n    }\n    else\n    {\n        // d.igitsE+123\n        // len <= max_digits10 + 1 + 5\n\n        std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1));\n        buf[1] = '.';\n        buf += 1 + k;\n    }\n\n    *buf++ = 'e';\n    return append_exponent(buf, n - 1);\n}\n\n} // namespace dtoa_impl\n\n/*!\n@brief generates a decimal representation of the floating-point number value in [first, last).\n\nThe format of the resulting decimal representation is similar to printf's %g\nformat. Returns an iterator pointing past-the-end of the decimal representation.\n\n@note The input number must be finite, i.e. NaN's and Inf's are not supported.\n@note The buffer must be large enough.\n@note The result is NOT null-terminated.\n*/\ntemplate <typename FloatType>\nchar* to_chars(char* first, const char* last, FloatType value)\n{\n    static_cast<void>(last); // maybe unused - fix warning\n    assert(std::isfinite(value));\n\n    // Use signbit(value) instead of (value < 0) since signbit works for -0.\n    if (std::signbit(value))\n    {\n        value = -value;\n        *first++ = '-';\n    }\n\n    if (value == 0) // +-0\n    {\n        *first++ = '0';\n        // Make it look like a floating-point number (#362, #378)\n        *first++ = '.';\n        *first++ = '0';\n        return first;\n    }\n\n    assert(last - first >= std::numeric_limits<FloatType>::max_digits10);\n\n    // Compute v = buffer * 10^decimal_exponent.\n    // The decimal digits are stored in the buffer, which needs to be interpreted\n    // as an unsigned decimal integer.\n    // len is the length of the buffer, i.e. the number of decimal digits.\n    int len = 0;\n    int decimal_exponent = 0;\n    dtoa_impl::grisu2(first, len, decimal_exponent, value);\n\n    assert(len <= std::numeric_limits<FloatType>::max_digits10);\n\n    // Format the buffer like printf(\"%.*g\", prec, value)\n    constexpr int kMinExp = -4;\n    // Use digits10 here to increase compatibility with version 2.\n    constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;\n\n    assert(last - first >= kMaxExp + 2);\n    assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);\n    assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);\n\n    return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);\n}\n\n} // namespace detail\n} // namespace nlohmann\n\n// #include <nlohmann/detail/macro_scope.hpp>\n\n// #include <nlohmann/detail/meta/cpp_future.hpp>\n\n// #include <nlohmann/detail/output/binary_writer.hpp>\n\n// #include <nlohmann/detail/output/output_adapters.hpp>\n\n// #include <nlohmann/detail/value_t.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\n///////////////////\n// serialization //\n///////////////////\n\n/// how to treat decoding errors\nenum class error_handler_t\n{\n    strict,  ///< throw a type_error exception in case of invalid UTF-8\n    replace, ///< replace invalid UTF-8 sequences with U+FFFD\n    ignore   ///< ignore invalid UTF-8 sequences\n};\n\ntemplate<typename BasicJsonType>\nclass serializer\n{\n    using string_t = typename BasicJsonType::string_t;\n    using number_float_t = typename BasicJsonType::number_float_t;\n    using number_integer_t = typename BasicJsonType::number_integer_t;\n    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n    static constexpr uint8_t UTF8_ACCEPT = 0;\n    static constexpr uint8_t UTF8_REJECT = 1;\n\n  public:\n    /*!\n    @param[in] s  output stream to serialize to\n    @param[in] ichar  indentation character to use\n    @param[in] error_handler_  how to react on decoding errors\n    */\n    serializer(output_adapter_t<char> s, const char ichar,\n               error_handler_t error_handler_ = error_handler_t::strict)\n        : o(std::move(s))\n        , loc(std::localeconv())\n        , thousands_sep(loc->thousands_sep == nullptr ? '\\0' : * (loc->thousands_sep))\n        , decimal_point(loc->decimal_point == nullptr ? '\\0' : * (loc->decimal_point))\n        , indent_char(ichar)\n        , indent_string(512, indent_char)\n        , error_handler(error_handler_)\n    {}\n\n    // delete because of pointer members\n    serializer(const serializer&) = delete;\n    serializer& operator=(const serializer&) = delete;\n    serializer(serializer&&) = delete;\n    serializer& operator=(serializer&&) = delete;\n    ~serializer() = default;\n\n    /*!\n    @brief internal implementation of the serialization function\n\n    This function is called by the public member function dump and organizes\n    the serialization internally. The indentation level is propagated as\n    additional parameter. In case of arrays and objects, the function is\n    called recursively.\n\n    - strings and object keys are escaped using `escape_string()`\n    - integer numbers are converted implicitly via `operator<<`\n    - floating-point numbers are converted to a string using `\"%g\"` format\n\n    @param[in] val             value to serialize\n    @param[in] pretty_print    whether the output shall be pretty-printed\n    @param[in] indent_step     the indent level\n    @param[in] current_indent  the current indent level (only used internally)\n    */\n    void dump(const BasicJsonType& val, const bool pretty_print,\n              const bool ensure_ascii,\n              const unsigned int indent_step,\n              const unsigned int current_indent = 0)\n    {\n        switch (val.m_type)\n        {\n            case value_t::object:\n            {\n                if (val.m_value.object->empty())\n                {\n                    o->write_characters(\"{}\", 2);\n                    return;\n                }\n\n                if (pretty_print)\n                {\n                    o->write_characters(\"{\\n\", 2);\n\n                    // variable to hold indentation for recursive calls\n                    const auto new_indent = current_indent + indent_step;\n                    if (JSON_UNLIKELY(indent_string.size() < new_indent))\n                    {\n                        indent_string.resize(indent_string.size() * 2, ' ');\n                    }\n\n                    // first n-1 elements\n                    auto i = val.m_value.object->cbegin();\n                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)\n                    {\n                        o->write_characters(indent_string.c_str(), new_indent);\n                        o->write_character('\\\"');\n                        dump_escaped(i->first, ensure_ascii);\n                        o->write_characters(\"\\\": \", 3);\n                        dump(i->second, true, ensure_ascii, indent_step, new_indent);\n                        o->write_characters(\",\\n\", 2);\n                    }\n\n                    // last element\n                    assert(i != val.m_value.object->cend());\n                    assert(std::next(i) == val.m_value.object->cend());\n                    o->write_characters(indent_string.c_str(), new_indent);\n                    o->write_character('\\\"');\n                    dump_escaped(i->first, ensure_ascii);\n                    o->write_characters(\"\\\": \", 3);\n                    dump(i->second, true, ensure_ascii, indent_step, new_indent);\n\n                    o->write_character('\\n');\n                    o->write_characters(indent_string.c_str(), current_indent);\n                    o->write_character('}');\n                }\n                else\n                {\n                    o->write_character('{');\n\n                    // first n-1 elements\n                    auto i = val.m_value.object->cbegin();\n                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)\n                    {\n                        o->write_character('\\\"');\n                        dump_escaped(i->first, ensure_ascii);\n                        o->write_characters(\"\\\":\", 2);\n                        dump(i->second, false, ensure_ascii, indent_step, current_indent);\n                        o->write_character(',');\n                    }\n\n                    // last element\n                    assert(i != val.m_value.object->cend());\n                    assert(std::next(i) == val.m_value.object->cend());\n                    o->write_character('\\\"');\n                    dump_escaped(i->first, ensure_ascii);\n                    o->write_characters(\"\\\":\", 2);\n                    dump(i->second, false, ensure_ascii, indent_step, current_indent);\n\n                    o->write_character('}');\n                }\n\n                return;\n            }\n\n            case value_t::array:\n            {\n                if (val.m_value.array->empty())\n                {\n                    o->write_characters(\"[]\", 2);\n                    return;\n                }\n\n                if (pretty_print)\n                {\n                    o->write_characters(\"[\\n\", 2);\n\n                    // variable to hold indentation for recursive calls\n                    const auto new_indent = current_indent + indent_step;\n                    if (JSON_UNLIKELY(indent_string.size() < new_indent))\n                    {\n                        indent_string.resize(indent_string.size() * 2, ' ');\n                    }\n\n                    // first n-1 elements\n                    for (auto i = val.m_value.array->cbegin();\n                            i != val.m_value.array->cend() - 1; ++i)\n                    {\n                        o->write_characters(indent_string.c_str(), new_indent);\n                        dump(*i, true, ensure_ascii, indent_step, new_indent);\n                        o->write_characters(\",\\n\", 2);\n                    }\n\n                    // last element\n                    assert(not val.m_value.array->empty());\n                    o->write_characters(indent_string.c_str(), new_indent);\n                    dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);\n\n                    o->write_character('\\n');\n                    o->write_characters(indent_string.c_str(), current_indent);\n                    o->write_character(']');\n                }\n                else\n                {\n                    o->write_character('[');\n\n                    // first n-1 elements\n                    for (auto i = val.m_value.array->cbegin();\n                            i != val.m_value.array->cend() - 1; ++i)\n                    {\n                        dump(*i, false, ensure_ascii, indent_step, current_indent);\n                        o->write_character(',');\n                    }\n\n                    // last element\n                    assert(not val.m_value.array->empty());\n                    dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);\n\n                    o->write_character(']');\n                }\n\n                return;\n            }\n\n            case value_t::string:\n            {\n                o->write_character('\\\"');\n                dump_escaped(*val.m_value.string, ensure_ascii);\n                o->write_character('\\\"');\n                return;\n            }\n\n            case value_t::boolean:\n            {\n                if (val.m_value.boolean)\n                {\n                    o->write_characters(\"true\", 4);\n                }\n                else\n                {\n                    o->write_characters(\"false\", 5);\n                }\n                return;\n            }\n\n            case value_t::number_integer:\n            {\n                dump_integer(val.m_value.number_integer);\n                return;\n            }\n\n            case value_t::number_unsigned:\n            {\n                dump_integer(val.m_value.number_unsigned);\n                return;\n            }\n\n            case value_t::number_float:\n            {\n                dump_float(val.m_value.number_float);\n                return;\n            }\n\n            case value_t::discarded:\n            {\n                o->write_characters(\"<discarded>\", 11);\n                return;\n            }\n\n            case value_t::null:\n            {\n                o->write_characters(\"null\", 4);\n                return;\n            }\n        }\n    }\n\n  private:\n    /*!\n    @brief dump escaped string\n\n    Escape a string by replacing certain special characters by a sequence of an\n    escape character (backslash) and another character and other control\n    characters by a sequence of \"\\u\" followed by a four-digit hex\n    representation. The escaped string is written to output stream @a o.\n\n    @param[in] s  the string to escape\n    @param[in] ensure_ascii  whether to escape non-ASCII characters with\n                             \\uXXXX sequences\n\n    @complexity Linear in the length of string @a s.\n    */\n    void dump_escaped(const string_t& s, const bool ensure_ascii)\n    {\n        uint32_t codepoint;\n        uint8_t state = UTF8_ACCEPT;\n        std::size_t bytes = 0;  // number of bytes written to string_buffer\n\n        // number of bytes written at the point of the last valid byte\n        std::size_t bytes_after_last_accept = 0;\n        std::size_t undumped_chars = 0;\n\n        for (std::size_t i = 0; i < s.size(); ++i)\n        {\n            const auto byte = static_cast<uint8_t>(s[i]);\n\n            switch (decode(state, codepoint, byte))\n            {\n                case UTF8_ACCEPT:  // decode found a new code point\n                {\n                    switch (codepoint)\n                    {\n                        case 0x08: // backspace\n                        {\n                            string_buffer[bytes++] = '\\\\';\n                            string_buffer[bytes++] = 'b';\n                            break;\n                        }\n\n                        case 0x09: // horizontal tab\n                        {\n                            string_buffer[bytes++] = '\\\\';\n                            string_buffer[bytes++] = 't';\n                            break;\n                        }\n\n                        case 0x0A: // newline\n                        {\n                            string_buffer[bytes++] = '\\\\';\n                            string_buffer[bytes++] = 'n';\n                            break;\n                        }\n\n                        case 0x0C: // formfeed\n                        {\n                            string_buffer[bytes++] = '\\\\';\n                            string_buffer[bytes++] = 'f';\n                            break;\n                        }\n\n                        case 0x0D: // carriage return\n                        {\n                            string_buffer[bytes++] = '\\\\';\n                            string_buffer[bytes++] = 'r';\n                            break;\n                        }\n\n                        case 0x22: // quotation mark\n                        {\n                            string_buffer[bytes++] = '\\\\';\n                            string_buffer[bytes++] = '\\\"';\n                            break;\n                        }\n\n                        case 0x5C: // reverse solidus\n                        {\n                            string_buffer[bytes++] = '\\\\';\n                            string_buffer[bytes++] = '\\\\';\n                            break;\n                        }\n\n                        default:\n                        {\n                            // escape control characters (0x00..0x1F) or, if\n                            // ensure_ascii parameter is used, non-ASCII characters\n                            if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))\n                            {\n                                if (codepoint <= 0xFFFF)\n                                {\n                                    (std::snprintf)(string_buffer.data() + bytes, 7, \"\\\\u%04x\",\n                                                    static_cast<uint16_t>(codepoint));\n                                    bytes += 6;\n                                }\n                                else\n                                {\n                                    (std::snprintf)(string_buffer.data() + bytes, 13, \"\\\\u%04x\\\\u%04x\",\n                                                    static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)),\n                                                    static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF)));\n                                    bytes += 12;\n                                }\n                            }\n                            else\n                            {\n                                // copy byte to buffer (all previous bytes\n                                // been copied have in default case above)\n                                string_buffer[bytes++] = s[i];\n                            }\n                            break;\n                        }\n                    }\n\n                    // write buffer and reset index; there must be 13 bytes\n                    // left, as this is the maximal number of bytes to be\n                    // written (\"\\uxxxx\\uxxxx\\0\") for one code point\n                    if (string_buffer.size() - bytes < 13)\n                    {\n                        o->write_characters(string_buffer.data(), bytes);\n                        bytes = 0;\n                    }\n\n                    // remember the byte position of this accept\n                    bytes_after_last_accept = bytes;\n                    undumped_chars = 0;\n                    break;\n                }\n\n                case UTF8_REJECT:  // decode found invalid UTF-8 byte\n                {\n                    switch (error_handler)\n                    {\n                        case error_handler_t::strict:\n                        {\n                            std::string sn(3, '\\0');\n                            (std::snprintf)(&sn[0], sn.size(), \"%.2X\", byte);\n                            JSON_THROW(type_error::create(316, \"invalid UTF-8 byte at index \" + std::to_string(i) + \": 0x\" + sn));\n                        }\n\n                        case error_handler_t::ignore:\n                        case error_handler_t::replace:\n                        {\n                            // in case we saw this character the first time, we\n                            // would like to read it again, because the byte\n                            // may be OK for itself, but just not OK for the\n                            // previous sequence\n                            if (undumped_chars > 0)\n                            {\n                                --i;\n                            }\n\n                            // reset length buffer to the last accepted index;\n                            // thus removing/ignoring the invalid characters\n                            bytes = bytes_after_last_accept;\n\n                            if (error_handler == error_handler_t::replace)\n                            {\n                                // add a replacement character\n                                if (ensure_ascii)\n                                {\n                                    string_buffer[bytes++] = '\\\\';\n                                    string_buffer[bytes++] = 'u';\n                                    string_buffer[bytes++] = 'f';\n                                    string_buffer[bytes++] = 'f';\n                                    string_buffer[bytes++] = 'f';\n                                    string_buffer[bytes++] = 'd';\n                                }\n                                else\n                                {\n                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\\xEF');\n                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\\xBF');\n                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\\xBD');\n                                }\n\n                                // write buffer and reset index; there must be 13 bytes\n                                // left, as this is the maximal number of bytes to be\n                                // written (\"\\uxxxx\\uxxxx\\0\") for one code point\n                                if (string_buffer.size() - bytes < 13)\n                                {\n                                    o->write_characters(string_buffer.data(), bytes);\n                                    bytes = 0;\n                                }\n\n                                bytes_after_last_accept = bytes;\n                            }\n\n                            undumped_chars = 0;\n\n                            // continue processing the string\n                            state = UTF8_ACCEPT;\n                            break;\n                        }\n                    }\n                    break;\n                }\n\n                default:  // decode found yet incomplete multi-byte code point\n                {\n                    if (not ensure_ascii)\n                    {\n                        // code point will not be escaped - copy byte to buffer\n                        string_buffer[bytes++] = s[i];\n                    }\n                    ++undumped_chars;\n                    break;\n                }\n            }\n        }\n\n        // we finished processing the string\n        if (JSON_LIKELY(state == UTF8_ACCEPT))\n        {\n            // write buffer\n            if (bytes > 0)\n            {\n                o->write_characters(string_buffer.data(), bytes);\n            }\n        }\n        else\n        {\n            // we finish reading, but do not accept: string was incomplete\n            switch (error_handler)\n            {\n                case error_handler_t::strict:\n                {\n                    std::string sn(3, '\\0');\n                    (std::snprintf)(&sn[0], sn.size(), \"%.2X\", static_cast<uint8_t>(s.back()));\n                    JSON_THROW(type_error::create(316, \"incomplete UTF-8 string; last byte: 0x\" + sn));\n                }\n\n                case error_handler_t::ignore:\n                {\n                    // write all accepted bytes\n                    o->write_characters(string_buffer.data(), bytes_after_last_accept);\n                    break;\n                }\n\n                case error_handler_t::replace:\n                {\n                    // write all accepted bytes\n                    o->write_characters(string_buffer.data(), bytes_after_last_accept);\n                    // add a replacement character\n                    if (ensure_ascii)\n                    {\n                        o->write_characters(\"\\\\ufffd\", 6);\n                    }\n                    else\n                    {\n                        o->write_characters(\"\\xEF\\xBF\\xBD\", 3);\n                    }\n                    break;\n                }\n            }\n        }\n    }\n\n    /*!\n    @brief count digits\n\n    Count the number of decimal (base 10) digits for an input unsigned integer.\n\n    @param[in] x  unsigned integer number to count its digits\n    @return    number of decimal digits\n    */\n    inline unsigned int count_digits(number_unsigned_t x) noexcept\n    {\n        unsigned int n_digits = 1;\n        for (;;)\n        {\n            if (x < 10)\n            {\n                return n_digits;\n            }\n            if (x < 100)\n            {\n                return n_digits + 1;\n            }\n            if (x < 1000)\n            {\n                return n_digits + 2;\n            }\n            if (x < 10000)\n            {\n                return n_digits + 3;\n            }\n            x = x / 10000u;\n            n_digits += 4;\n        }\n    }\n\n    /*!\n    @brief dump an integer\n\n    Dump a given integer to output stream @a o. Works internally with\n    @a number_buffer.\n\n    @param[in] x  integer number (signed or unsigned) to dump\n    @tparam NumberType either @a number_integer_t or @a number_unsigned_t\n    */\n    template<typename NumberType, detail::enable_if_t<\n                 std::is_same<NumberType, number_unsigned_t>::value or\n                 std::is_same<NumberType, number_integer_t>::value,\n                 int> = 0>\n    void dump_integer(NumberType x)\n    {\n        static constexpr std::array<std::array<char, 2>, 100> digits_to_99\n        {\n            {\n                {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'}, {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'},\n                {'1', '0'}, {'1', '1'}, {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'}, {'1', '8'}, {'1', '9'},\n                {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},\n                {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'}, {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'},\n                {'4', '0'}, {'4', '1'}, {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'}, {'4', '8'}, {'4', '9'},\n                {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},\n                {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'}, {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'},\n                {'7', '0'}, {'7', '1'}, {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'}, {'7', '8'}, {'7', '9'},\n                {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'}, {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},\n                {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'}, {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'},\n            }\n        };\n\n        // special case for \"0\"\n        if (x == 0)\n        {\n            o->write_character('0');\n            return;\n        }\n\n        // use a pointer to fill the buffer\n        auto buffer_ptr = begin(number_buffer);\n\n        const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not(x >= 0); // see issue #755\n        number_unsigned_t abs_value;\n\n        unsigned int n_chars;\n\n        if (is_negative)\n        {\n            *buffer_ptr = '-';\n            abs_value = static_cast<number_unsigned_t>(-1 - x) + 1;\n\n            // account one more byte for the minus sign\n            n_chars = 1 + count_digits(abs_value);\n        }\n        else\n        {\n            abs_value = static_cast<number_unsigned_t>(x);\n            n_chars = count_digits(abs_value);\n        }\n\n        // spare 1 byte for '\\0'\n        assert(n_chars < number_buffer.size() - 1);\n\n        // jump to the end to generate the string from backward\n        // so we later avoid reversing the result\n        buffer_ptr += n_chars;\n\n        // Fast int2ascii implementation inspired by \"Fastware\" talk by Andrei Alexandrescu\n        // See: https://www.youtube.com/watch?v=o4-CwDo2zpg\n        while (abs_value >= 100)\n        {\n            const auto digits_index = static_cast<unsigned>((abs_value % 100));\n            abs_value /= 100;\n            *(--buffer_ptr) = digits_to_99[digits_index][1];\n            *(--buffer_ptr) = digits_to_99[digits_index][0];\n        }\n\n        if (abs_value >= 10)\n        {\n            const auto digits_index = static_cast<unsigned>(abs_value);\n            *(--buffer_ptr) = digits_to_99[digits_index][1];\n            *(--buffer_ptr) = digits_to_99[digits_index][0];\n        }\n        else\n        {\n            *(--buffer_ptr) = static_cast<char>('0' + abs_value);\n        }\n\n        o->write_characters(number_buffer.data(), n_chars);\n    }\n\n    /*!\n    @brief dump a floating-point number\n\n    Dump a given floating-point number to output stream @a o. Works internally\n    with @a number_buffer.\n\n    @param[in] x  floating-point number to dump\n    */\n    void dump_float(number_float_t x)\n    {\n        // NaN / inf\n        if (not std::isfinite(x))\n        {\n            o->write_characters(\"null\", 4);\n            return;\n        }\n\n        // If number_float_t is an IEEE-754 single or double precision number,\n        // use the Grisu2 algorithm to produce short numbers which are\n        // guaranteed to round-trip, using strtof and strtod, resp.\n        //\n        // NB: The test below works if <long double> == <double>.\n        static constexpr bool is_ieee_single_or_double\n            = (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or\n              (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);\n\n        dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());\n    }\n\n    void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)\n    {\n        char* begin = number_buffer.data();\n        char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);\n\n        o->write_characters(begin, static_cast<size_t>(end - begin));\n    }\n\n    void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)\n    {\n        // get number of digits for a float -> text -> float round-trip\n        static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;\n\n        // the actual conversion\n        std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), \"%.*g\", d, x);\n\n        // negative value indicates an error\n        assert(len > 0);\n        // check if buffer was large enough\n        assert(static_cast<std::size_t>(len) < number_buffer.size());\n\n        // erase thousands separator\n        if (thousands_sep != '\\0')\n        {\n            const auto end = std::remove(number_buffer.begin(),\n                                         number_buffer.begin() + len, thousands_sep);\n            std::fill(end, number_buffer.end(), '\\0');\n            assert((end - number_buffer.begin()) <= len);\n            len = (end - number_buffer.begin());\n        }\n\n        // convert decimal point to '.'\n        if (decimal_point != '\\0' and decimal_point != '.')\n        {\n            const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);\n            if (dec_pos != number_buffer.end())\n            {\n                *dec_pos = '.';\n            }\n        }\n\n        o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));\n\n        // determine if need to append \".0\"\n        const bool value_is_int_like =\n            std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,\n                         [](char c)\n        {\n            return (c == '.' or c == 'e');\n        });\n\n        if (value_is_int_like)\n        {\n            o->write_characters(\".0\", 2);\n        }\n    }\n\n    /*!\n    @brief check whether a string is UTF-8 encoded\n\n    The function checks each byte of a string whether it is UTF-8 encoded. The\n    result of the check is stored in the @a state parameter. The function must\n    be called initially with state 0 (accept). State 1 means the string must\n    be rejected, because the current byte is not allowed. If the string is\n    completely processed, but the state is non-zero, the string ended\n    prematurely; that is, the last byte indicated more bytes should have\n    followed.\n\n    @param[in,out] state  the state of the decoding\n    @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT)\n    @param[in] byte       next byte to decode\n    @return               new state\n\n    @note The function has been edited: a std::array is used.\n\n    @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>\n    @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/\n    */\n    static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept\n    {\n        static const std::array<uint8_t, 400> utf8d =\n        {\n            {\n                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F\n                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F\n                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F\n                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F\n                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F\n                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF\n                8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF\n                0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF\n                0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF\n                0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0\n                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2\n                1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4\n                1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6\n                1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8\n            }\n        };\n\n        const uint8_t type = utf8d[byte];\n\n        codep = (state != UTF8_ACCEPT)\n                ? (byte & 0x3fu) | (codep << 6)\n                : static_cast<uint32_t>(0xff >> type) & (byte);\n\n        state = utf8d[256u + state * 16u + type];\n        return state;\n    }\n\n  private:\n    /// the output of the serializer\n    output_adapter_t<char> o = nullptr;\n\n    /// a (hopefully) large enough character buffer\n    std::array<char, 64> number_buffer{{}};\n\n    /// the locale\n    const std::lconv* loc = nullptr;\n    /// the locale's thousand separator character\n    const char thousands_sep = '\\0';\n    /// the locale's decimal point character\n    const char decimal_point = '\\0';\n\n    /// string buffer\n    std::array<char, 512> string_buffer{{}};\n\n    /// the indentation character\n    const char indent_char;\n    /// the indentation string\n    string_t indent_string;\n\n    /// error_handler how to react on decoding errors\n    const error_handler_t error_handler;\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/json_ref.hpp>\n\n\n#include <initializer_list>\n#include <utility>\n\n// #include <nlohmann/detail/meta/type_traits.hpp>\n\n\nnamespace nlohmann\n{\nnamespace detail\n{\ntemplate<typename BasicJsonType>\nclass json_ref\n{\n  public:\n    using value_type = BasicJsonType;\n\n    json_ref(value_type&& value)\n        : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)\n    {}\n\n    json_ref(const value_type& value)\n        : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)\n    {}\n\n    json_ref(std::initializer_list<json_ref> init)\n        : owned_value(init), value_ref(&owned_value), is_rvalue(true)\n    {}\n\n    template <\n        class... Args,\n        enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >\n    json_ref(Args && ... args)\n        : owned_value(std::forward<Args>(args)...), value_ref(&owned_value),\n          is_rvalue(true) {}\n\n    // class should be movable only\n    json_ref(json_ref&&) = default;\n    json_ref(const json_ref&) = delete;\n    json_ref& operator=(const json_ref&) = delete;\n    json_ref& operator=(json_ref&&) = delete;\n    ~json_ref() = default;\n\n    value_type moved_or_copied() const\n    {\n        if (is_rvalue)\n        {\n            return std::move(*value_ref);\n        }\n        return *value_ref;\n    }\n\n    value_type const& operator*() const\n    {\n        return *static_cast<value_type const*>(value_ref);\n    }\n\n    value_type const* operator->() const\n    {\n        return static_cast<value_type const*>(value_ref);\n    }\n\n  private:\n    mutable value_type owned_value = nullptr;\n    value_type* value_ref = nullptr;\n    const bool is_rvalue;\n};\n}  // namespace detail\n}  // namespace nlohmann\n\n// #include <nlohmann/detail/json_pointer.hpp>\n\n\n#include <algorithm> // all_of\n#include <cassert> // assert\n#include <numeric> // accumulate\n#include <string> // string\n#include <vector> // vector\n\n// #include <nlohmann/detail/macro_scope.hpp>\n\n// #include <nlohmann/detail/exceptions.hpp>\n\n// #include <nlohmann/detail/value_t.hpp>\n\n\nnamespace nlohmann\n{\ntemplate<typename BasicJsonType>\nclass json_pointer\n{\n    // allow basic_json to access private members\n    NLOHMANN_BASIC_JSON_TPL_DECLARATION\n    friend class basic_json;\n\n  public:\n    /*!\n    @brief create JSON pointer\n\n    Create a JSON pointer according to the syntax described in\n    [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).\n\n    @param[in] s  string representing the JSON pointer; if omitted, the empty\n                  string is assumed which references the whole JSON value\n\n    @throw parse_error.107 if the given JSON pointer @a s is nonempty and does\n                           not begin with a slash (`/`); see example below\n\n    @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is\n    not followed by `0` (representing `~`) or `1` (representing `/`); see\n    example below\n\n    @liveexample{The example shows the construction several valid JSON pointers\n    as well as the exceptional behavior.,json_pointer}\n\n    @since version 2.0.0\n    */\n    explicit json_pointer(const std::string& s = \"\")\n        : reference_tokens(split(s))\n    {}\n\n    /*!\n    @brief return a string representation of the JSON pointer\n\n    @invariant For each JSON pointer `ptr`, it holds:\n    @code {.cpp}\n    ptr == json_pointer(ptr.to_string());\n    @endcode\n\n    @return a string representation of the JSON pointer\n\n    @liveexample{The example shows the result of `to_string`.,\n    json_pointer__to_string}\n\n    @since version 2.0.0\n    */\n    std::string to_string() const\n    {\n        return std::accumulate(reference_tokens.begin(), reference_tokens.end(),\n                               std::string{},\n                               [](const std::string & a, const std::string & b)\n        {\n            return a + \"/\" + escape(b);\n        });\n    }\n\n    /// @copydoc to_string()\n    operator std::string() const\n    {\n        return to_string();\n    }\n\n    /*!\n    @param[in] s  reference token to be converted into an array index\n\n    @return integer representation of @a s\n\n    @throw out_of_range.404 if string @a s could not be converted to an integer\n    */\n    static int array_index(const std::string& s)\n    {\n        std::size_t processed_chars = 0;\n        const int res = std::stoi(s, &processed_chars);\n\n        // check if the string was completely read\n        if (JSON_UNLIKELY(processed_chars != s.size()))\n        {\n            JSON_THROW(detail::out_of_range::create(404, \"unresolved reference token '\" + s + \"'\"));\n        }\n\n        return res;\n    }\n\n    /*!\n    @brief remove and return last reference pointer\n    @throw out_of_range.405 if JSON pointer has no parent\n    */\n    std::string pop_back()\n    {\n        if (JSON_UNLIKELY(is_root()))\n        {\n            JSON_THROW(detail::out_of_range::create(405, \"JSON pointer has no parent\"));\n        }\n\n        auto last = reference_tokens.back();\n        reference_tokens.pop_back();\n        return last;\n    }\n\n    /*!\n    @brief remove and return last reference pointer\n    @throw out_of_range.405 if JSON pointer has no parent\n    */\n    void push_back(const std::string& tok)\n    {\n        reference_tokens.push_back(tok);\n    }\n\n  private:\n    /// return whether pointer points to the root document\n    bool is_root() const noexcept\n    {\n        return reference_tokens.empty();\n    }\n\n    json_pointer top() const\n    {\n        if (JSON_UNLIKELY(is_root()))\n        {\n            JSON_THROW(detail::out_of_range::create(405, \"JSON pointer has no parent\"));\n        }\n\n        json_pointer result = *this;\n        result.reference_tokens = {reference_tokens[0]};\n        return result;\n    }\n\n    /*!\n    @brief create and return a reference to the pointed to value\n\n    @complexity Linear in the number of reference tokens.\n\n    @throw parse_error.109 if array index is not a number\n    @throw type_error.313 if value cannot be unflattened\n    */\n    BasicJsonType& get_and_create(BasicJsonType& j) const\n    {\n        using size_type = typename BasicJsonType::size_type;\n        auto result = &j;\n\n        // in case no reference tokens exist, return a reference to the JSON value\n        // j which will be overwritten by a primitive value\n        for (const auto& reference_token : reference_tokens)\n        {\n            switch (result->m_type)\n            {\n                case detail::value_t::null:\n                {\n                    if (reference_token == \"0\")\n                    {\n                        // start a new array if reference token is 0\n                        result = &result->operator[](0);\n                    }\n                    else\n                    {\n                        // start a new object otherwise\n                        result = &result->operator[](reference_token);\n                    }\n                    break;\n                }\n\n                case detail::value_t::object:\n                {\n                    // create an entry in the object\n                    result = &result->operator[](reference_token);\n                    break;\n                }\n\n                case detail::value_t::array:\n                {\n                    // create an entry in the array\n                    JSON_TRY\n                    {\n                        result = &result->operator[](static_cast<size_type>(array_index(reference_token)));\n                    }\n                    JSON_CATCH(std::invalid_argument&)\n                    {\n                        JSON_THROW(detail::parse_error::create(109, 0, \"array index '\" + reference_token + \"' is not a number\"));\n                    }\n                    break;\n                }\n\n                /*\n                The following code is only reached if there exists a reference\n                token _and_ the current value is primitive. In this case, we have\n                an error situation, because primitive values may only occur as\n                single value; that is, with an empty list of reference tokens.\n                */\n                default:\n                    JSON_THROW(detail::type_error::create(313, \"invalid value to unflatten\"));\n            }\n        }\n\n        return *result;\n    }\n\n    /*!\n    @brief return a reference to the pointed to value\n\n    @note This version does not throw if a value is not present, but tries to\n          create nested values instead. For instance, calling this function\n          with pointer `\"/this/that\"` on a null value is equivalent to calling\n          `operator[](\"this\").operator[](\"that\")` on that value, effectively\n          changing the null value to an object.\n\n    @param[in] ptr  a JSON value\n\n    @return reference to the JSON value pointed to by the JSON pointer\n\n    @complexity Linear in the length of the JSON pointer.\n\n    @throw parse_error.106   if an array index begins with '0'\n    @throw parse_error.109   if an array index was not a number\n    @throw out_of_range.404  if the JSON pointer can not be resolved\n    */\n    BasicJsonType& get_unchecked(BasicJsonType* ptr) const\n    {\n        using size_type = typename BasicJsonType::size_type;\n        for (const auto& reference_token : reference_tokens)\n        {\n            // convert null values to arrays or objects before continuing\n            if (ptr->m_type == detail::value_t::null)\n            {\n                // check if reference token is a number\n                const bool nums =\n                    std::all_of(reference_token.begin(), reference_token.end(),\n                                [](const char x)\n                {\n                    return (x >= '0' and x <= '9');\n                });\n\n                // change value to array for numbers or \"-\" or to object otherwise\n                *ptr = (nums or reference_token == \"-\")\n                       ? detail::value_t::array\n                       : detail::value_t::object;\n            }\n\n            switch (ptr->m_type)\n            {\n                case detail::value_t::object:\n                {\n                    // use unchecked object access\n                    ptr = &ptr->operator[](reference_token);\n                    break;\n                }\n\n                case detail::value_t::array:\n                {\n                    // error condition (cf. RFC 6901, Sect. 4)\n                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))\n                    {\n                        JSON_THROW(detail::parse_error::create(106, 0,\n                                                               \"array index '\" + reference_token +\n                                                               \"' must not begin with '0'\"));\n                    }\n\n                    if (reference_token == \"-\")\n                    {\n                        // explicitly treat \"-\" as index beyond the end\n                        ptr = &ptr->operator[](ptr->m_value.array->size());\n                    }\n                    else\n                    {\n                        // convert array index to number; unchecked access\n                        JSON_TRY\n                        {\n                            ptr = &ptr->operator[](\n                                static_cast<size_type>(array_index(reference_token)));\n                        }\n                        JSON_CATCH(std::invalid_argument&)\n                        {\n                            JSON_THROW(detail::parse_error::create(109, 0, \"array index '\" + reference_token + \"' is not a number\"));\n                        }\n                    }\n                    break;\n                }\n\n                default:\n                    JSON_THROW(detail::out_of_range::create(404, \"unresolved reference token '\" + reference_token + \"'\"));\n            }\n        }\n\n        return *ptr;\n    }\n\n    /*!\n    @throw parse_error.106   if an array index begins with '0'\n    @throw parse_error.109   if an array index was not a number\n    @throw out_of_range.402  if the array index '-' is used\n    @throw out_of_range.404  if the JSON pointer can not be resolved\n    */\n    BasicJsonType& get_checked(BasicJsonType* ptr) const\n    {\n        using size_type = typename BasicJsonType::size_type;\n        for (const auto& reference_token : reference_tokens)\n        {\n            switch (ptr->m_type)\n            {\n                case detail::value_t::object:\n                {\n                    // note: at performs range check\n                    ptr = &ptr->at(reference_token);\n                    break;\n                }\n\n                case detail::value_t::array:\n                {\n                    if (JSON_UNLIKELY(reference_token == \"-\"))\n                    {\n                        // \"-\" always fails the range check\n                        JSON_THROW(detail::out_of_range::create(402,\n                                                                \"array index '-' (\" + std::to_string(ptr->m_value.array->size()) +\n                                                                \") is out of range\"));\n                    }\n\n                    // error condition (cf. RFC 6901, Sect. 4)\n                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))\n                    {\n                        JSON_THROW(detail::parse_error::create(106, 0,\n                                                               \"array index '\" + reference_token +\n                                                               \"' must not begin with '0'\"));\n                    }\n\n                    // note: at performs range check\n                    JSON_TRY\n                    {\n                        ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));\n                    }\n                    JSON_CATCH(std::invalid_argument&)\n                    {\n                        JSON_THROW(detail::parse_error::create(109, 0, \"array index '\" + reference_token + \"' is not a number\"));\n                    }\n                    break;\n                }\n\n                default:\n                    JSON_THROW(detail::out_of_range::create(404, \"unresolved reference token '\" + reference_token + \"'\"));\n            }\n        }\n\n        return *ptr;\n    }\n\n    /*!\n    @brief return a const reference to the pointed to value\n\n    @param[in] ptr  a JSON value\n\n    @return const reference to the JSON value pointed to by the JSON\n    pointer\n\n    @throw parse_error.106   if an array index begins with '0'\n    @throw parse_error.109   if an array index was not a number\n    @throw out_of_range.402  if the array index '-' is used\n    @throw out_of_range.404  if the JSON pointer can not be resolved\n    */\n    const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const\n    {\n        using size_type = typename BasicJsonType::size_type;\n        for (const auto& reference_token : reference_tokens)\n        {\n            switch (ptr->m_type)\n            {\n                case detail::value_t::object:\n                {\n                    // use unchecked object access\n                    ptr = &ptr->operator[](reference_token);\n                    break;\n                }\n\n                case detail::value_t::array:\n                {\n                    if (JSON_UNLIKELY(reference_token == \"-\"))\n                    {\n                        // \"-\" cannot be used for const access\n                        JSON_THROW(detail::out_of_range::create(402,\n                                                                \"array index '-' (\" + std::to_string(ptr->m_value.array->size()) +\n                                                                \") is out of range\"));\n                    }\n\n                    // error condition (cf. RFC 6901, Sect. 4)\n                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))\n                    {\n                        JSON_THROW(detail::parse_error::create(106, 0,\n                                                               \"array index '\" + reference_token +\n                                                               \"' must not begin with '0'\"));\n                    }\n\n                    // use unchecked array access\n                    JSON_TRY\n                    {\n                        ptr = &ptr->operator[](\n                            static_cast<size_type>(array_index(reference_token)));\n                    }\n                    JSON_CATCH(std::invalid_argument&)\n                    {\n                        JSON_THROW(detail::parse_error::create(109, 0, \"array index '\" + reference_token + \"' is not a number\"));\n                    }\n                    break;\n                }\n\n                default:\n                    JSON_THROW(detail::out_of_range::create(404, \"unresolved reference token '\" + reference_token + \"'\"));\n            }\n        }\n\n        return *ptr;\n    }\n\n    /*!\n    @throw parse_error.106   if an array index begins with '0'\n    @throw parse_error.109   if an array index was not a number\n    @throw out_of_range.402  if the array index '-' is used\n    @throw out_of_range.404  if the JSON pointer can not be resolved\n    */\n    const BasicJsonType& get_checked(const BasicJsonType* ptr) const\n    {\n        using size_type = typename BasicJsonType::size_type;\n        for (const auto& reference_token : reference_tokens)\n        {\n            switch (ptr->m_type)\n            {\n                case detail::value_t::object:\n                {\n                    // note: at performs range check\n                    ptr = &ptr->at(reference_token);\n                    break;\n                }\n\n                case detail::value_t::array:\n                {\n                    if (JSON_UNLIKELY(reference_token == \"-\"))\n                    {\n                        // \"-\" always fails the range check\n                        JSON_THROW(detail::out_of_range::create(402,\n                                                                \"array index '-' (\" + std::to_string(ptr->m_value.array->size()) +\n                                                                \") is out of range\"));\n                    }\n\n                    // error condition (cf. RFC 6901, Sect. 4)\n                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))\n                    {\n                        JSON_THROW(detail::parse_error::create(106, 0,\n                                                               \"array index '\" + reference_token +\n                                                               \"' must not begin with '0'\"));\n                    }\n\n                    // note: at performs range check\n                    JSON_TRY\n                    {\n                        ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));\n                    }\n                    JSON_CATCH(std::invalid_argument&)\n                    {\n                        JSON_THROW(detail::parse_error::create(109, 0, \"array index '\" + reference_token + \"' is not a number\"));\n                    }\n                    break;\n                }\n\n                default:\n                    JSON_THROW(detail::out_of_range::create(404, \"unresolved reference token '\" + reference_token + \"'\"));\n            }\n        }\n\n        return *ptr;\n    }\n\n    /*!\n    @brief split the string input to reference tokens\n\n    @note This function is only called by the json_pointer constructor.\n          All exceptions below are documented there.\n\n    @throw parse_error.107  if the pointer is not empty or begins with '/'\n    @throw parse_error.108  if character '~' is not followed by '0' or '1'\n    */\n    static std::vector<std::string> split(const std::string& reference_string)\n    {\n        std::vector<std::string> result;\n\n        // special case: empty reference string -> no reference tokens\n        if (reference_string.empty())\n        {\n            return result;\n        }\n\n        // check if nonempty reference string begins with slash\n        if (JSON_UNLIKELY(reference_string[0] != '/'))\n        {\n            JSON_THROW(detail::parse_error::create(107, 1,\n                                                   \"JSON pointer must be empty or begin with '/' - was: '\" +\n                                                   reference_string + \"'\"));\n        }\n\n        // extract the reference tokens:\n        // - slash: position of the last read slash (or end of string)\n        // - start: position after the previous slash\n        for (\n            // search for the first slash after the first character\n            std::size_t slash = reference_string.find_first_of('/', 1),\n            // set the beginning of the first reference token\n            start = 1;\n            // we can stop if start == 0 (if slash == std::string::npos)\n            start != 0;\n            // set the beginning of the next reference token\n            // (will eventually be 0 if slash == std::string::npos)\n            start = (slash == std::string::npos) ? 0 : slash + 1,\n            // find next slash\n            slash = reference_string.find_first_of('/', start))\n        {\n            // use the text between the beginning of the reference token\n            // (start) and the last slash (slash).\n            auto reference_token = reference_string.substr(start, slash - start);\n\n            // check reference tokens are properly escaped\n            for (std::size_t pos = reference_token.find_first_of('~');\n                    pos != std::string::npos;\n                    pos = reference_token.find_first_of('~', pos + 1))\n            {\n                assert(reference_token[pos] == '~');\n\n                // ~ must be followed by 0 or 1\n                if (JSON_UNLIKELY(pos == reference_token.size() - 1 or\n                                  (reference_token[pos + 1] != '0' and\n                                   reference_token[pos + 1] != '1')))\n                {\n                    JSON_THROW(detail::parse_error::create(108, 0, \"escape character '~' must be followed with '0' or '1'\"));\n                }\n            }\n\n            // finally, store the reference token\n            unescape(reference_token);\n            result.push_back(reference_token);\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief replace all occurrences of a substring by another string\n\n    @param[in,out] s  the string to manipulate; changed so that all\n                   occurrences of @a f are replaced with @a t\n    @param[in]     f  the substring to replace with @a t\n    @param[in]     t  the string to replace @a f\n\n    @pre The search string @a f must not be empty. **This precondition is\n    enforced with an assertion.**\n\n    @since version 2.0.0\n    */\n    static void replace_substring(std::string& s, const std::string& f,\n                                  const std::string& t)\n    {\n        assert(not f.empty());\n        for (auto pos = s.find(f);                // find first occurrence of f\n                pos != std::string::npos;         // make sure f was found\n                s.replace(pos, f.size(), t),      // replace with t, and\n                pos = s.find(f, pos + t.size()))  // find next occurrence of f\n        {}\n    }\n\n    /// escape \"~\" to \"~0\" and \"/\" to \"~1\"\n    static std::string escape(std::string s)\n    {\n        replace_substring(s, \"~\", \"~0\");\n        replace_substring(s, \"/\", \"~1\");\n        return s;\n    }\n\n    /// unescape \"~1\" to tilde and \"~0\" to slash (order is important!)\n    static void unescape(std::string& s)\n    {\n        replace_substring(s, \"~1\", \"/\");\n        replace_substring(s, \"~0\", \"~\");\n    }\n\n    /*!\n    @param[in] reference_string  the reference string to the current value\n    @param[in] value             the value to consider\n    @param[in,out] result        the result object to insert values to\n\n    @note Empty objects or arrays are flattened to `null`.\n    */\n    static void flatten(const std::string& reference_string,\n                        const BasicJsonType& value,\n                        BasicJsonType& result)\n    {\n        switch (value.m_type)\n        {\n            case detail::value_t::array:\n            {\n                if (value.m_value.array->empty())\n                {\n                    // flatten empty array as null\n                    result[reference_string] = nullptr;\n                }\n                else\n                {\n                    // iterate array and use index as reference string\n                    for (std::size_t i = 0; i < value.m_value.array->size(); ++i)\n                    {\n                        flatten(reference_string + \"/\" + std::to_string(i),\n                                value.m_value.array->operator[](i), result);\n                    }\n                }\n                break;\n            }\n\n            case detail::value_t::object:\n            {\n                if (value.m_value.object->empty())\n                {\n                    // flatten empty object as null\n                    result[reference_string] = nullptr;\n                }\n                else\n                {\n                    // iterate object and use keys as reference string\n                    for (const auto& element : *value.m_value.object)\n                    {\n                        flatten(reference_string + \"/\" + escape(element.first), element.second, result);\n                    }\n                }\n                break;\n            }\n\n            default:\n            {\n                // add primitive value with its reference string\n                result[reference_string] = value;\n                break;\n            }\n        }\n    }\n\n    /*!\n    @param[in] value  flattened JSON\n\n    @return unflattened JSON\n\n    @throw parse_error.109 if array index is not a number\n    @throw type_error.314  if value is not an object\n    @throw type_error.315  if object values are not primitive\n    @throw type_error.313  if value cannot be unflattened\n    */\n    static BasicJsonType\n    unflatten(const BasicJsonType& value)\n    {\n        if (JSON_UNLIKELY(not value.is_object()))\n        {\n            JSON_THROW(detail::type_error::create(314, \"only objects can be unflattened\"));\n        }\n\n        BasicJsonType result;\n\n        // iterate the JSON object values\n        for (const auto& element : *value.m_value.object)\n        {\n            if (JSON_UNLIKELY(not element.second.is_primitive()))\n            {\n                JSON_THROW(detail::type_error::create(315, \"values in object must be primitive\"));\n            }\n\n            // assign value to reference pointed to by JSON pointer; Note that if\n            // the JSON pointer is \"\" (i.e., points to the whole value), function\n            // get_and_create returns a reference to result itself. An assignment\n            // will then create a primitive value.\n            json_pointer(element.first).get_and_create(result) = element.second;\n        }\n\n        return result;\n    }\n\n    friend bool operator==(json_pointer const& lhs,\n                           json_pointer const& rhs) noexcept\n    {\n        return (lhs.reference_tokens == rhs.reference_tokens);\n    }\n\n    friend bool operator!=(json_pointer const& lhs,\n                           json_pointer const& rhs) noexcept\n    {\n        return not (lhs == rhs);\n    }\n\n    /// the reference tokens\n    std::vector<std::string> reference_tokens;\n};\n}  // namespace nlohmann\n\n// #include <nlohmann/adl_serializer.hpp>\n\n\n#include <utility>\n\n// #include <nlohmann/detail/conversions/from_json.hpp>\n\n// #include <nlohmann/detail/conversions/to_json.hpp>\n\n\nnamespace nlohmann\n{\n\ntemplate<typename, typename>\nstruct adl_serializer\n{\n    /*!\n    @brief convert a JSON value to any value type\n\n    This function is usually called by the `get()` function of the\n    @ref basic_json class (either explicit or via conversion operators).\n\n    @param[in] j        JSON value to read from\n    @param[in,out] val  value to write to\n    */\n    template<typename BasicJsonType, typename ValueType>\n    static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(\n        noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))\n    -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())\n    {\n        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);\n    }\n\n    /*!\n    @brief convert any value type to a JSON value\n\n    This function is usually called by the constructors of the @ref basic_json\n    class.\n\n    @param[in,out] j  JSON value to write to\n    @param[in] val    value to read from\n    */\n    template <typename BasicJsonType, typename ValueType>\n    static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(\n        noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))\n    -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)), void())\n    {\n        ::nlohmann::to_json(j, std::forward<ValueType>(val));\n    }\n};\n\n}  // namespace nlohmann\n\n\n/*!\n@brief namespace for Niels Lohmann\n@see https://github.com/nlohmann\n@since version 1.0.0\n*/\nnamespace nlohmann\n{\n\n/*!\n@brief a class to store JSON values\n\n@tparam ObjectType type for JSON objects (`std::map` by default; will be used\nin @ref object_t)\n@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used\nin @ref array_t)\n@tparam StringType type for JSON strings and object keys (`std::string` by\ndefault; will be used in @ref string_t)\n@tparam BooleanType type for JSON booleans (`bool` by default; will be used\nin @ref boolean_t)\n@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by\ndefault; will be used in @ref number_integer_t)\n@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c\n`uint64_t` by default; will be used in @ref number_unsigned_t)\n@tparam NumberFloatType type for JSON floating-point numbers (`double` by\ndefault; will be used in @ref number_float_t)\n@tparam AllocatorType type of the allocator to use (`std::allocator` by\ndefault)\n@tparam JSONSerializer the serializer to resolve internal calls to `to_json()`\nand `from_json()` (@ref adl_serializer by default)\n\n@requirement The class satisfies the following concept requirements:\n- Basic\n - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):\n   JSON values can be default constructed. The result will be a JSON null\n   value.\n - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):\n   A JSON value can be constructed from an rvalue argument.\n - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):\n   A JSON value can be copy-constructed from an lvalue expression.\n - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):\n   A JSON value van be assigned from an rvalue argument.\n - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):\n   A JSON value can be copy-assigned from an lvalue expression.\n - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):\n   JSON values can be destructed.\n- Layout\n - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):\n   JSON values have\n   [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):\n   All non-static data members are private and standard layout types, the\n   class has no virtual functions or (virtual) base classes.\n- Library-wide\n - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):\n   JSON values can be compared with `==`, see @ref\n   operator==(const_reference,const_reference).\n - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):\n   JSON values can be compared with `<`, see @ref\n   operator<(const_reference,const_reference).\n - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):\n   Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of\n   other compatible types, using unqualified function call @ref swap().\n - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):\n   JSON values can be compared against `std::nullptr_t` objects which are used\n   to model the `null` value.\n- Container\n - [Container](https://en.cppreference.com/w/cpp/named_req/Container):\n   JSON values can be used like STL containers and provide iterator access.\n - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);\n   JSON values can be used like STL containers and provide reverse iterator\n   access.\n\n@invariant The member variables @a m_value and @a m_type have the following\nrelationship:\n- If `m_type == value_t::object`, then `m_value.object != nullptr`.\n- If `m_type == value_t::array`, then `m_value.array != nullptr`.\n- If `m_type == value_t::string`, then `m_value.string != nullptr`.\nThe invariants are checked by member function assert_invariant().\n\n@internal\n@note ObjectType trick from http://stackoverflow.com/a/9860911\n@endinternal\n\n@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange\nFormat](http://rfc7159.net/rfc7159)\n\n@since version 1.0.0\n\n@nosubgrouping\n*/\nNLOHMANN_BASIC_JSON_TPL_DECLARATION\nclass basic_json\n{\n  private:\n    template<detail::value_t> friend struct detail::external_constructor;\n    friend ::nlohmann::json_pointer<basic_json>;\n    friend ::nlohmann::detail::parser<basic_json>;\n    friend ::nlohmann::detail::serializer<basic_json>;\n    template<typename BasicJsonType>\n    friend class ::nlohmann::detail::iter_impl;\n    template<typename BasicJsonType, typename CharType>\n    friend class ::nlohmann::detail::binary_writer;\n    template<typename BasicJsonType, typename SAX>\n    friend class ::nlohmann::detail::binary_reader;\n    template<typename BasicJsonType>\n    friend class ::nlohmann::detail::json_sax_dom_parser;\n    template<typename BasicJsonType>\n    friend class ::nlohmann::detail::json_sax_dom_callback_parser;\n\n    /// workaround type for MSVC\n    using basic_json_t = NLOHMANN_BASIC_JSON_TPL;\n\n    // convenience aliases for types residing in namespace detail;\n    using lexer = ::nlohmann::detail::lexer<basic_json>;\n    using parser = ::nlohmann::detail::parser<basic_json>;\n\n    using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;\n    template<typename BasicJsonType>\n    using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;\n    template<typename BasicJsonType>\n    using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;\n    template<typename Iterator>\n    using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;\n    template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;\n\n    template<typename CharType>\n    using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;\n\n    using binary_reader = ::nlohmann::detail::binary_reader<basic_json>;\n    template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;\n\n    using serializer = ::nlohmann::detail::serializer<basic_json>;\n\n  public:\n    using value_t = detail::value_t;\n    /// JSON Pointer, see @ref nlohmann::json_pointer\n    using json_pointer = ::nlohmann::json_pointer<basic_json>;\n    template<typename T, typename SFINAE>\n    using json_serializer = JSONSerializer<T, SFINAE>;\n    /// how to treat decoding errors\n    using error_handler_t = detail::error_handler_t;\n    /// helper type for initializer lists of basic_json values\n    using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;\n\n    using input_format_t = detail::input_format_t;\n    /// SAX interface type, see @ref nlohmann::json_sax\n    using json_sax_t = json_sax<basic_json>;\n\n    ////////////////\n    // exceptions //\n    ////////////////\n\n    /// @name exceptions\n    /// Classes to implement user-defined exceptions.\n    /// @{\n\n    /// @copydoc detail::exception\n    using exception = detail::exception;\n    /// @copydoc detail::parse_error\n    using parse_error = detail::parse_error;\n    /// @copydoc detail::invalid_iterator\n    using invalid_iterator = detail::invalid_iterator;\n    /// @copydoc detail::type_error\n    using type_error = detail::type_error;\n    /// @copydoc detail::out_of_range\n    using out_of_range = detail::out_of_range;\n    /// @copydoc detail::other_error\n    using other_error = detail::other_error;\n\n    /// @}\n\n\n    /////////////////////\n    // container types //\n    /////////////////////\n\n    /// @name container types\n    /// The canonic container types to use @ref basic_json like any other STL\n    /// container.\n    /// @{\n\n    /// the type of elements in a basic_json container\n    using value_type = basic_json;\n\n    /// the type of an element reference\n    using reference = value_type&;\n    /// the type of an element const reference\n    using const_reference = const value_type&;\n\n    /// a type to represent differences between iterators\n    using difference_type = std::ptrdiff_t;\n    /// a type to represent container sizes\n    using size_type = std::size_t;\n\n    /// the allocator type\n    using allocator_type = AllocatorType<basic_json>;\n\n    /// the type of an element pointer\n    using pointer = typename std::allocator_traits<allocator_type>::pointer;\n    /// the type of an element const pointer\n    using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;\n\n    /// an iterator for a basic_json container\n    using iterator = iter_impl<basic_json>;\n    /// a const iterator for a basic_json container\n    using const_iterator = iter_impl<const basic_json>;\n    /// a reverse iterator for a basic_json container\n    using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;\n    /// a const reverse iterator for a basic_json container\n    using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;\n\n    /// @}\n\n\n    /*!\n    @brief returns the allocator associated with the container\n    */\n    static allocator_type get_allocator()\n    {\n        return allocator_type();\n    }\n\n    /*!\n    @brief returns version information on the library\n\n    This function returns a JSON object with information about the library,\n    including the version number and information on the platform and compiler.\n\n    @return JSON object holding version information\n    key         | description\n    ----------- | ---------------\n    `compiler`  | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).\n    `copyright` | The copyright line for the library as string.\n    `name`      | The name of the library as string.\n    `platform`  | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.\n    `url`       | The URL of the project as string.\n    `version`   | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).\n\n    @liveexample{The following code shows an example output of the `meta()`\n    function.,meta}\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes to any JSON value.\n\n    @complexity Constant.\n\n    @since 2.1.0\n    */\n    JSON_NODISCARD\n    static basic_json meta()\n    {\n        basic_json result;\n\n        result[\"copyright\"] = \"(C) 2013-2017 Niels Lohmann\";\n        result[\"name\"] = \"JSON for Modern C++\";\n        result[\"url\"] = \"https://github.com/nlohmann/json\";\n        result[\"version\"][\"string\"] =\n            std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + \".\" +\n            std::to_string(NLOHMANN_JSON_VERSION_MINOR) + \".\" +\n            std::to_string(NLOHMANN_JSON_VERSION_PATCH);\n        result[\"version\"][\"major\"] = NLOHMANN_JSON_VERSION_MAJOR;\n        result[\"version\"][\"minor\"] = NLOHMANN_JSON_VERSION_MINOR;\n        result[\"version\"][\"patch\"] = NLOHMANN_JSON_VERSION_PATCH;\n\n#ifdef _WIN32\n        result[\"platform\"] = \"win32\";\n#elif defined __linux__\n        result[\"platform\"] = \"linux\";\n#elif defined __APPLE__\n        result[\"platform\"] = \"apple\";\n#elif defined __unix__\n        result[\"platform\"] = \"unix\";\n#else\n        result[\"platform\"] = \"unknown\";\n#endif\n\n#if defined(__ICC) || defined(__INTEL_COMPILER)\n        result[\"compiler\"] = {{\"family\", \"icc\"}, {\"version\", __INTEL_COMPILER}};\n#elif defined(__clang__)\n        result[\"compiler\"] = {{\"family\", \"clang\"}, {\"version\", __clang_version__}};\n#elif defined(__GNUC__) || defined(__GNUG__)\n        result[\"compiler\"] = {{\"family\", \"gcc\"}, {\"version\", std::to_string(__GNUC__) + \".\" + std::to_string(__GNUC_MINOR__) + \".\" + std::to_string(__GNUC_PATCHLEVEL__)}};\n#elif defined(__HP_cc) || defined(__HP_aCC)\n        result[\"compiler\"] = \"hp\"\n#elif defined(__IBMCPP__)\n        result[\"compiler\"] = {{\"family\", \"ilecpp\"}, {\"version\", __IBMCPP__}};\n#elif defined(_MSC_VER)\n        result[\"compiler\"] = {{\"family\", \"msvc\"}, {\"version\", _MSC_VER}};\n#elif defined(__PGI)\n        result[\"compiler\"] = {{\"family\", \"pgcpp\"}, {\"version\", __PGI}};\n#elif defined(__SUNPRO_CC)\n        result[\"compiler\"] = {{\"family\", \"sunpro\"}, {\"version\", __SUNPRO_CC}};\n#else\n        result[\"compiler\"] = {{\"family\", \"unknown\"}, {\"version\", \"unknown\"}};\n#endif\n\n#ifdef __cplusplus\n        result[\"compiler\"][\"c++\"] = std::to_string(__cplusplus);\n#else\n        result[\"compiler\"][\"c++\"] = \"unknown\";\n#endif\n        return result;\n    }\n\n\n    ///////////////////////////\n    // JSON value data types //\n    ///////////////////////////\n\n    /// @name JSON value data types\n    /// The data types to store a JSON value. These types are derived from\n    /// the template arguments passed to class @ref basic_json.\n    /// @{\n\n#if defined(JSON_HAS_CPP_14)\n    // Use transparent comparator if possible, combined with perfect forwarding\n    // on find() and count() calls prevents unnecessary string construction.\n    using object_comparator_t = std::less<>;\n#else\n    using object_comparator_t = std::less<StringType>;\n#endif\n\n    /*!\n    @brief a type for an object\n\n    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:\n    > An object is an unordered collection of zero or more name/value pairs,\n    > where a name is a string and a value is a string, number, boolean, null,\n    > object, or array.\n\n    To store objects in C++, a type is defined by the template parameters\n    described below.\n\n    @tparam ObjectType  the container to store objects (e.g., `std::map` or\n    `std::unordered_map`)\n    @tparam StringType the type of the keys or names (e.g., `std::string`).\n    The comparison function `std::less<StringType>` is used to order elements\n    inside the container.\n    @tparam AllocatorType the allocator to use for objects (e.g.,\n    `std::allocator`)\n\n    #### Default type\n\n    With the default values for @a ObjectType (`std::map`), @a StringType\n    (`std::string`), and @a AllocatorType (`std::allocator`), the default\n    value for @a object_t is:\n\n    @code {.cpp}\n    std::map<\n      std::string, // key_type\n      basic_json, // value_type\n      std::less<std::string>, // key_compare\n      std::allocator<std::pair<const std::string, basic_json>> // allocator_type\n    >\n    @endcode\n\n    #### Behavior\n\n    The choice of @a object_t influences the behavior of the JSON class. With\n    the default type, objects have the following behavior:\n\n    - When all names are unique, objects will be interoperable in the sense\n      that all software implementations receiving that object will agree on\n      the name-value mappings.\n    - When the names within an object are not unique, it is unspecified which\n      one of the values for a given key will be chosen. For instance,\n      `{\"key\": 2, \"key\": 1}` could be equal to either `{\"key\": 1}` or\n      `{\"key\": 2}`.\n    - Internally, name/value pairs are stored in lexicographical order of the\n      names. Objects will also be serialized (see @ref dump) in this order.\n      For instance, `{\"b\": 1, \"a\": 2}` and `{\"a\": 2, \"b\": 1}` will be stored\n      and serialized as `{\"a\": 2, \"b\": 1}`.\n    - When comparing objects, the order of the name/value pairs is irrelevant.\n      This makes objects interoperable in the sense that they will not be\n      affected by these differences. For instance, `{\"b\": 1, \"a\": 2}` and\n      `{\"a\": 2, \"b\": 1}` will be treated as equal.\n\n    #### Limits\n\n    [RFC 7159](http://rfc7159.net/rfc7159) specifies:\n    > An implementation may set limits on the maximum depth of nesting.\n\n    In this class, the object's limit of nesting is not explicitly constrained.\n    However, a maximum depth of nesting may be introduced by the compiler or\n    runtime environment. A theoretical limit can be queried by calling the\n    @ref max_size function of a JSON object.\n\n    #### Storage\n\n    Objects are stored as pointers in a @ref basic_json type. That is, for any\n    access to object values, a pointer of type `object_t*` must be\n    dereferenced.\n\n    @sa @ref array_t -- type for an array value\n\n    @since version 1.0.0\n\n    @note The order name/value pairs are added to the object is *not*\n    preserved by the library. Therefore, iterating an object may return\n    name/value pairs in a different order than they were originally stored. In\n    fact, keys will be traversed in alphabetical order as `std::map` with\n    `std::less` is used by default. Please note this behavior conforms to [RFC\n    7159](http://rfc7159.net/rfc7159), because any order implements the\n    specified \"unordered\" nature of JSON objects.\n    */\n    using object_t = ObjectType<StringType,\n          basic_json,\n          object_comparator_t,\n          AllocatorType<std::pair<const StringType,\n          basic_json>>>;\n\n    /*!\n    @brief a type for an array\n\n    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:\n    > An array is an ordered sequence of zero or more values.\n\n    To store objects in C++, a type is defined by the template parameters\n    explained below.\n\n    @tparam ArrayType  container type to store arrays (e.g., `std::vector` or\n    `std::list`)\n    @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)\n\n    #### Default type\n\n    With the default values for @a ArrayType (`std::vector`) and @a\n    AllocatorType (`std::allocator`), the default value for @a array_t is:\n\n    @code {.cpp}\n    std::vector<\n      basic_json, // value_type\n      std::allocator<basic_json> // allocator_type\n    >\n    @endcode\n\n    #### Limits\n\n    [RFC 7159](http://rfc7159.net/rfc7159) specifies:\n    > An implementation may set limits on the maximum depth of nesting.\n\n    In this class, the array's limit of nesting is not explicitly constrained.\n    However, a maximum depth of nesting may be introduced by the compiler or\n    runtime environment. A theoretical limit can be queried by calling the\n    @ref max_size function of a JSON array.\n\n    #### Storage\n\n    Arrays are stored as pointers in a @ref basic_json type. That is, for any\n    access to array values, a pointer of type `array_t*` must be dereferenced.\n\n    @sa @ref object_t -- type for an object value\n\n    @since version 1.0.0\n    */\n    using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;\n\n    /*!\n    @brief a type for a string\n\n    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:\n    > A string is a sequence of zero or more Unicode characters.\n\n    To store objects in C++, a type is defined by the template parameter\n    described below. Unicode values are split by the JSON class into\n    byte-sized characters during deserialization.\n\n    @tparam StringType  the container to store strings (e.g., `std::string`).\n    Note this container is used for keys/names in objects, see @ref object_t.\n\n    #### Default type\n\n    With the default values for @a StringType (`std::string`), the default\n    value for @a string_t is:\n\n    @code {.cpp}\n    std::string\n    @endcode\n\n    #### Encoding\n\n    Strings are stored in UTF-8 encoding. Therefore, functions like\n    `std::string::size()` or `std::string::length()` return the number of\n    bytes in the string rather than the number of characters or glyphs.\n\n    #### String comparison\n\n    [RFC 7159](http://rfc7159.net/rfc7159) states:\n    > Software implementations are typically required to test names of object\n    > members for equality. Implementations that transform the textual\n    > representation into sequences of Unicode code units and then perform the\n    > comparison numerically, code unit by code unit, are interoperable in the\n    > sense that implementations will agree in all cases on equality or\n    > inequality of two strings. For example, implementations that compare\n    > strings with escaped characters unconverted may incorrectly find that\n    > `\"a\\\\b\"` and `\"a\\u005Cb\"` are not equal.\n\n    This implementation is interoperable as it does compare strings code unit\n    by code unit.\n\n    #### Storage\n\n    String values are stored as pointers in a @ref basic_json type. That is,\n    for any access to string values, a pointer of type `string_t*` must be\n    dereferenced.\n\n    @since version 1.0.0\n    */\n    using string_t = StringType;\n\n    /*!\n    @brief a type for a boolean\n\n    [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a\n    type which differentiates the two literals `true` and `false`.\n\n    To store objects in C++, a type is defined by the template parameter @a\n    BooleanType which chooses the type to use.\n\n    #### Default type\n\n    With the default values for @a BooleanType (`bool`), the default value for\n    @a boolean_t is:\n\n    @code {.cpp}\n    bool\n    @endcode\n\n    #### Storage\n\n    Boolean values are stored directly inside a @ref basic_json type.\n\n    @since version 1.0.0\n    */\n    using boolean_t = BooleanType;\n\n    /*!\n    @brief a type for a number (integer)\n\n    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:\n    > The representation of numbers is similar to that used in most\n    > programming languages. A number is represented in base 10 using decimal\n    > digits. It contains an integer component that may be prefixed with an\n    > optional minus sign, which may be followed by a fraction part and/or an\n    > exponent part. Leading zeros are not allowed. (...) Numeric values that\n    > cannot be represented in the grammar below (such as Infinity and NaN)\n    > are not permitted.\n\n    This description includes both integer and floating-point numbers.\n    However, C++ allows more precise storage if it is known whether the number\n    is a signed integer, an unsigned integer or a floating-point number.\n    Therefore, three different types, @ref number_integer_t, @ref\n    number_unsigned_t and @ref number_float_t are used.\n\n    To store integer numbers in C++, a type is defined by the template\n    parameter @a NumberIntegerType which chooses the type to use.\n\n    #### Default type\n\n    With the default values for @a NumberIntegerType (`int64_t`), the default\n    value for @a number_integer_t is:\n\n    @code {.cpp}\n    int64_t\n    @endcode\n\n    #### Default behavior\n\n    - The restrictions about leading zeros is not enforced in C++. Instead,\n      leading zeros in integer literals lead to an interpretation as octal\n      number. Internally, the value will be stored as decimal number. For\n      instance, the C++ integer literal `010` will be serialized to `8`.\n      During deserialization, leading zeros yield an error.\n    - Not-a-number (NaN) values will be serialized to `null`.\n\n    #### Limits\n\n    [RFC 7159](http://rfc7159.net/rfc7159) specifies:\n    > An implementation may set limits on the range and precision of numbers.\n\n    When the default type is used, the maximal integer number that can be\n    stored is `9223372036854775807` (INT64_MAX) and the minimal integer number\n    that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers\n    that are out of range will yield over/underflow when used in a\n    constructor. During deserialization, too large or small integer numbers\n    will be automatically be stored as @ref number_unsigned_t or @ref\n    number_float_t.\n\n    [RFC 7159](http://rfc7159.net/rfc7159) further states:\n    > Note that when such software is used, numbers that are integers and are\n    > in the range \\f$[-2^{53}+1, 2^{53}-1]\\f$ are interoperable in the sense\n    > that implementations will agree exactly on their numeric values.\n\n    As this range is a subrange of the exactly supported range [INT64_MIN,\n    INT64_MAX], this class's integer type is interoperable.\n\n    #### Storage\n\n    Integer number values are stored directly inside a @ref basic_json type.\n\n    @sa @ref number_float_t -- type for number values (floating-point)\n\n    @sa @ref number_unsigned_t -- type for number values (unsigned integer)\n\n    @since version 1.0.0\n    */\n    using number_integer_t = NumberIntegerType;\n\n    /*!\n    @brief a type for a number (unsigned)\n\n    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:\n    > The representation of numbers is similar to that used in most\n    > programming languages. A number is represented in base 10 using decimal\n    > digits. It contains an integer component that may be prefixed with an\n    > optional minus sign, which may be followed by a fraction part and/or an\n    > exponent part. Leading zeros are not allowed. (...) Numeric values that\n    > cannot be represented in the grammar below (such as Infinity and NaN)\n    > are not permitted.\n\n    This description includes both integer and floating-point numbers.\n    However, C++ allows more precise storage if it is known whether the number\n    is a signed integer, an unsigned integer or a floating-point number.\n    Therefore, three different types, @ref number_integer_t, @ref\n    number_unsigned_t and @ref number_float_t are used.\n\n    To store unsigned integer numbers in C++, a type is defined by the\n    template parameter @a NumberUnsignedType which chooses the type to use.\n\n    #### Default type\n\n    With the default values for @a NumberUnsignedType (`uint64_t`), the\n    default value for @a number_unsigned_t is:\n\n    @code {.cpp}\n    uint64_t\n    @endcode\n\n    #### Default behavior\n\n    - The restrictions about leading zeros is not enforced in C++. Instead,\n      leading zeros in integer literals lead to an interpretation as octal\n      number. Internally, the value will be stored as decimal number. For\n      instance, the C++ integer literal `010` will be serialized to `8`.\n      During deserialization, leading zeros yield an error.\n    - Not-a-number (NaN) values will be serialized to `null`.\n\n    #### Limits\n\n    [RFC 7159](http://rfc7159.net/rfc7159) specifies:\n    > An implementation may set limits on the range and precision of numbers.\n\n    When the default type is used, the maximal integer number that can be\n    stored is `18446744073709551615` (UINT64_MAX) and the minimal integer\n    number that can be stored is `0`. Integer numbers that are out of range\n    will yield over/underflow when used in a constructor. During\n    deserialization, too large or small integer numbers will be automatically\n    be stored as @ref number_integer_t or @ref number_float_t.\n\n    [RFC 7159](http://rfc7159.net/rfc7159) further states:\n    > Note that when such software is used, numbers that are integers and are\n    > in the range \\f$[-2^{53}+1, 2^{53}-1]\\f$ are interoperable in the sense\n    > that implementations will agree exactly on their numeric values.\n\n    As this range is a subrange (when considered in conjunction with the\n    number_integer_t type) of the exactly supported range [0, UINT64_MAX],\n    this class's integer type is interoperable.\n\n    #### Storage\n\n    Integer number values are stored directly inside a @ref basic_json type.\n\n    @sa @ref number_float_t -- type for number values (floating-point)\n    @sa @ref number_integer_t -- type for number values (integer)\n\n    @since version 2.0.0\n    */\n    using number_unsigned_t = NumberUnsignedType;\n\n    /*!\n    @brief a type for a number (floating-point)\n\n    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:\n    > The representation of numbers is similar to that used in most\n    > programming languages. A number is represented in base 10 using decimal\n    > digits. It contains an integer component that may be prefixed with an\n    > optional minus sign, which may be followed by a fraction part and/or an\n    > exponent part. Leading zeros are not allowed. (...) Numeric values that\n    > cannot be represented in the grammar below (such as Infinity and NaN)\n    > are not permitted.\n\n    This description includes both integer and floating-point numbers.\n    However, C++ allows more precise storage if it is known whether the number\n    is a signed integer, an unsigned integer or a floating-point number.\n    Therefore, three different types, @ref number_integer_t, @ref\n    number_unsigned_t and @ref number_float_t are used.\n\n    To store floating-point numbers in C++, a type is defined by the template\n    parameter @a NumberFloatType which chooses the type to use.\n\n    #### Default type\n\n    With the default values for @a NumberFloatType (`double`), the default\n    value for @a number_float_t is:\n\n    @code {.cpp}\n    double\n    @endcode\n\n    #### Default behavior\n\n    - The restrictions about leading zeros is not enforced in C++. Instead,\n      leading zeros in floating-point literals will be ignored. Internally,\n      the value will be stored as decimal number. For instance, the C++\n      floating-point literal `01.2` will be serialized to `1.2`. During\n      deserialization, leading zeros yield an error.\n    - Not-a-number (NaN) values will be serialized to `null`.\n\n    #### Limits\n\n    [RFC 7159](http://rfc7159.net/rfc7159) states:\n    > This specification allows implementations to set limits on the range and\n    > precision of numbers accepted. Since software that implements IEEE\n    > 754-2008 binary64 (double precision) numbers is generally available and\n    > widely used, good interoperability can be achieved by implementations\n    > that expect no more precision or range than these provide, in the sense\n    > that implementations will approximate JSON numbers within the expected\n    > precision.\n\n    This implementation does exactly follow this approach, as it uses double\n    precision floating-point numbers. Note values smaller than\n    `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`\n    will be stored as NaN internally and be serialized to `null`.\n\n    #### Storage\n\n    Floating-point number values are stored directly inside a @ref basic_json\n    type.\n\n    @sa @ref number_integer_t -- type for number values (integer)\n\n    @sa @ref number_unsigned_t -- type for number values (unsigned integer)\n\n    @since version 1.0.0\n    */\n    using number_float_t = NumberFloatType;\n\n    /// @}\n\n  private:\n\n    /// helper for exception-safe object creation\n    template<typename T, typename... Args>\n    static T* create(Args&& ... args)\n    {\n        AllocatorType<T> alloc;\n        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;\n\n        auto deleter = [&](T * object)\n        {\n            AllocatorTraits::deallocate(alloc, object, 1);\n        };\n        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);\n        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);\n        assert(object != nullptr);\n        return object.release();\n    }\n\n    ////////////////////////\n    // JSON value storage //\n    ////////////////////////\n\n    /*!\n    @brief a JSON value\n\n    The actual storage for a JSON value of the @ref basic_json class. This\n    union combines the different storage types for the JSON value types\n    defined in @ref value_t.\n\n    JSON type | value_t type    | used type\n    --------- | --------------- | ------------------------\n    object    | object          | pointer to @ref object_t\n    array     | array           | pointer to @ref array_t\n    string    | string          | pointer to @ref string_t\n    boolean   | boolean         | @ref boolean_t\n    number    | number_integer  | @ref number_integer_t\n    number    | number_unsigned | @ref number_unsigned_t\n    number    | number_float    | @ref number_float_t\n    null      | null            | *no value is stored*\n\n    @note Variable-length types (objects, arrays, and strings) are stored as\n    pointers. The size of the union should not exceed 64 bits if the default\n    value types are used.\n\n    @since version 1.0.0\n    */\n    union json_value\n    {\n        /// object (stored with pointer to save storage)\n        object_t* object;\n        /// array (stored with pointer to save storage)\n        array_t* array;\n        /// string (stored with pointer to save storage)\n        string_t* string;\n        /// boolean\n        boolean_t boolean;\n        /// number (integer)\n        number_integer_t number_integer;\n        /// number (unsigned integer)\n        number_unsigned_t number_unsigned;\n        /// number (floating-point)\n        number_float_t number_float;\n\n        /// default constructor (for null values)\n        json_value() = default;\n        /// constructor for booleans\n        json_value(boolean_t v) noexcept : boolean(v) {}\n        /// constructor for numbers (integer)\n        json_value(number_integer_t v) noexcept : number_integer(v) {}\n        /// constructor for numbers (unsigned)\n        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}\n        /// constructor for numbers (floating-point)\n        json_value(number_float_t v) noexcept : number_float(v) {}\n        /// constructor for empty values of a given type\n        json_value(value_t t)\n        {\n            switch (t)\n            {\n                case value_t::object:\n                {\n                    object = create<object_t>();\n                    break;\n                }\n\n                case value_t::array:\n                {\n                    array = create<array_t>();\n                    break;\n                }\n\n                case value_t::string:\n                {\n                    string = create<string_t>(\"\");\n                    break;\n                }\n\n                case value_t::boolean:\n                {\n                    boolean = boolean_t(false);\n                    break;\n                }\n\n                case value_t::number_integer:\n                {\n                    number_integer = number_integer_t(0);\n                    break;\n                }\n\n                case value_t::number_unsigned:\n                {\n                    number_unsigned = number_unsigned_t(0);\n                    break;\n                }\n\n                case value_t::number_float:\n                {\n                    number_float = number_float_t(0.0);\n                    break;\n                }\n\n                case value_t::null:\n                {\n                    object = nullptr;  // silence warning, see #821\n                    break;\n                }\n\n                default:\n                {\n                    object = nullptr;  // silence warning, see #821\n                    if (JSON_UNLIKELY(t == value_t::null))\n                    {\n                        JSON_THROW(other_error::create(500, \"961c151d2e87f2686a955a9be24d316f1362bf21 3.5.0\")); // LCOV_EXCL_LINE\n                    }\n                    break;\n                }\n            }\n        }\n\n        /// constructor for strings\n        json_value(const string_t& value)\n        {\n            string = create<string_t>(value);\n        }\n\n        /// constructor for rvalue strings\n        json_value(string_t&& value)\n        {\n            string = create<string_t>(std::move(value));\n        }\n\n        /// constructor for objects\n        json_value(const object_t& value)\n        {\n            object = create<object_t>(value);\n        }\n\n        /// constructor for rvalue objects\n        json_value(object_t&& value)\n        {\n            object = create<object_t>(std::move(value));\n        }\n\n        /// constructor for arrays\n        json_value(const array_t& value)\n        {\n            array = create<array_t>(value);\n        }\n\n        /// constructor for rvalue arrays\n        json_value(array_t&& value)\n        {\n            array = create<array_t>(std::move(value));\n        }\n\n        void destroy(value_t t) noexcept\n        {\n            switch (t)\n            {\n                case value_t::object:\n                {\n                    AllocatorType<object_t> alloc;\n                    std::allocator_traits<decltype(alloc)>::destroy(alloc, object);\n                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);\n                    break;\n                }\n\n                case value_t::array:\n                {\n                    AllocatorType<array_t> alloc;\n                    std::allocator_traits<decltype(alloc)>::destroy(alloc, array);\n                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);\n                    break;\n                }\n\n                case value_t::string:\n                {\n                    AllocatorType<string_t> alloc;\n                    std::allocator_traits<decltype(alloc)>::destroy(alloc, string);\n                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);\n                    break;\n                }\n\n                default:\n                {\n                    break;\n                }\n            }\n        }\n    };\n\n    /*!\n    @brief checks the class invariants\n\n    This function asserts the class invariants. It needs to be called at the\n    end of every constructor to make sure that created objects respect the\n    invariant. Furthermore, it has to be called each time the type of a JSON\n    value is changed, because the invariant expresses a relationship between\n    @a m_type and @a m_value.\n    */\n    void assert_invariant() const noexcept\n    {\n        assert(m_type != value_t::object or m_value.object != nullptr);\n        assert(m_type != value_t::array or m_value.array != nullptr);\n        assert(m_type != value_t::string or m_value.string != nullptr);\n    }\n\n  public:\n    //////////////////////////\n    // JSON parser callback //\n    //////////////////////////\n\n    /*!\n    @brief parser event types\n\n    The parser callback distinguishes the following events:\n    - `object_start`: the parser read `{` and started to process a JSON object\n    - `key`: the parser read a key of a value in an object\n    - `object_end`: the parser read `}` and finished processing a JSON object\n    - `array_start`: the parser read `[` and started to process a JSON array\n    - `array_end`: the parser read `]` and finished processing a JSON array\n    - `value`: the parser finished reading a JSON value\n\n    @image html callback_events.png \"Example when certain parse events are triggered\"\n\n    @sa @ref parser_callback_t for more information and examples\n    */\n    using parse_event_t = typename parser::parse_event_t;\n\n    /*!\n    @brief per-element parser callback type\n\n    With a parser callback function, the result of parsing a JSON text can be\n    influenced. When passed to @ref parse, it is called on certain events\n    (passed as @ref parse_event_t via parameter @a event) with a set recursion\n    depth @a depth and context JSON value @a parsed. The return value of the\n    callback function is a boolean indicating whether the element that emitted\n    the callback shall be kept or not.\n\n    We distinguish six scenarios (determined by the event type) in which the\n    callback function can be called. The following table describes the values\n    of the parameters @a depth, @a event, and @a parsed.\n\n    parameter @a event | description | parameter @a depth | parameter @a parsed\n    ------------------ | ----------- | ------------------ | -------------------\n    parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded\n    parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key\n    parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object\n    parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded\n    parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array\n    parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value\n\n    @image html callback_events.png \"Example when certain parse events are triggered\"\n\n    Discarding a value (i.e., returning `false`) has different effects\n    depending on the context in which function was called:\n\n    - Discarded values in structured types are skipped. That is, the parser\n      will behave as if the discarded value was never read.\n    - In case a value outside a structured type is skipped, it is replaced\n      with `null`. This case happens if the top-level element is skipped.\n\n    @param[in] depth  the depth of the recursion during parsing\n\n    @param[in] event  an event of type parse_event_t indicating the context in\n    the callback function has been called\n\n    @param[in,out] parsed  the current intermediate parse result; note that\n    writing to this value has no effect for parse_event_t::key events\n\n    @return Whether the JSON value which called the function during parsing\n    should be kept (`true`) or not (`false`). In the latter case, it is either\n    skipped completely or replaced by an empty discarded object.\n\n    @sa @ref parse for examples\n\n    @since version 1.0.0\n    */\n    using parser_callback_t = typename parser::parser_callback_t;\n\n    //////////////////\n    // constructors //\n    //////////////////\n\n    /// @name constructors and destructors\n    /// Constructors of class @ref basic_json, copy/move constructor, copy\n    /// assignment, static functions creating objects, and the destructor.\n    /// @{\n\n    /*!\n    @brief create an empty value with a given type\n\n    Create an empty JSON value with a given type. The value will be default\n    initialized with an empty value which depends on the type:\n\n    Value type  | initial value\n    ----------- | -------------\n    null        | `null`\n    boolean     | `false`\n    string      | `\"\"`\n    number      | `0`\n    object      | `{}`\n    array       | `[]`\n\n    @param[in] v  the type of the value to create\n\n    @complexity Constant.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes to any JSON value.\n\n    @liveexample{The following code shows the constructor for different @ref\n    value_t values,basic_json__value_t}\n\n    @sa @ref clear() -- restores the postcondition of this constructor\n\n    @since version 1.0.0\n    */\n    basic_json(const value_t v)\n        : m_type(v), m_value(v)\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create a null object\n\n    Create a `null` JSON value. It either takes a null pointer as parameter\n    (explicitly creating `null`) or no parameter (implicitly creating `null`).\n    The passed null pointer itself is not read -- it is only used to choose\n    the right constructor.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this constructor never throws\n    exceptions.\n\n    @liveexample{The following code shows the constructor with and without a\n    null pointer parameter.,basic_json__nullptr_t}\n\n    @since version 1.0.0\n    */\n    basic_json(std::nullptr_t = nullptr) noexcept\n        : basic_json(value_t::null)\n    {\n        assert_invariant();\n    }\n\n    /*!\n    @brief create a JSON value\n\n    This is a \"catch all\" constructor for all compatible JSON types; that is,\n    types for which a `to_json()` method exists. The constructor forwards the\n    parameter @a val to that method (to `json_serializer<U>::to_json` method\n    with `U = uncvref_t<CompatibleType>`, to be exact).\n\n    Template type @a CompatibleType includes, but is not limited to, the\n    following types:\n    - **arrays**: @ref array_t and all kinds of compatible containers such as\n      `std::vector`, `std::deque`, `std::list`, `std::forward_list`,\n      `std::array`, `std::valarray`, `std::set`, `std::unordered_set`,\n      `std::multiset`, and `std::unordered_multiset` with a `value_type` from\n      which a @ref basic_json value can be constructed.\n    - **objects**: @ref object_t and all kinds of compatible associative\n      containers such as `std::map`, `std::unordered_map`, `std::multimap`,\n      and `std::unordered_multimap` with a `key_type` compatible to\n      @ref string_t and a `value_type` from which a @ref basic_json value can\n      be constructed.\n    - **strings**: @ref string_t, string literals, and all compatible string\n      containers can be used.\n    - **numbers**: @ref number_integer_t, @ref number_unsigned_t,\n      @ref number_float_t, and all convertible number types such as `int`,\n      `size_t`, `int64_t`, `float` or `double` can be used.\n    - **boolean**: @ref boolean_t / `bool` can be used.\n\n    See the examples below.\n\n    @tparam CompatibleType a type such that:\n    - @a CompatibleType is not derived from `std::istream`,\n    - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move\n         constructors),\n    - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments)\n    - @a CompatibleType is not a @ref basic_json nested type (e.g.,\n         @ref json_pointer, @ref iterator, etc ...)\n    - @ref @ref json_serializer<U> has a\n         `to_json(basic_json_t&, CompatibleType&&)` method\n\n    @tparam U = `uncvref_t<CompatibleType>`\n\n    @param[in] val the value to be forwarded to the respective constructor\n\n    @complexity Usually linear in the size of the passed @a val, also\n                depending on the implementation of the called `to_json()`\n                method.\n\n    @exceptionsafety Depends on the called constructor. For types directly\n    supported by the library (i.e., all types for which no `to_json()` function\n    was provided), strong guarantee holds: if an exception is thrown, there are\n    no changes to any JSON value.\n\n    @liveexample{The following code shows the constructor with several\n    compatible types.,basic_json__CompatibleType}\n\n    @since version 2.1.0\n    */\n    template <typename CompatibleType,\n              typename U = detail::uncvref_t<CompatibleType>,\n              detail::enable_if_t<\n                  not detail::is_basic_json<U>::value and detail::is_compatible_type<basic_json_t, U>::value, int> = 0>\n    basic_json(CompatibleType && val) noexcept(noexcept(\n                JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),\n                                           std::forward<CompatibleType>(val))))\n    {\n        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));\n        assert_invariant();\n    }\n\n    /*!\n    @brief create a JSON value from an existing one\n\n    This is a constructor for existing @ref basic_json types.\n    It does not hijack copy/move constructors, since the parameter has different\n    template arguments than the current ones.\n\n    The constructor tries to convert the internal @ref m_value of the parameter.\n\n    @tparam BasicJsonType a type such that:\n    - @a BasicJsonType is a @ref basic_json type.\n    - @a BasicJsonType has different template arguments than @ref basic_json_t.\n\n    @param[in] val the @ref basic_json value to be converted.\n\n    @complexity Usually linear in the size of the passed @a val, also\n                depending on the implementation of the called `to_json()`\n                method.\n\n    @exceptionsafety Depends on the called constructor. For types directly\n    supported by the library (i.e., all types for which no `to_json()` function\n    was provided), strong guarantee holds: if an exception is thrown, there are\n    no changes to any JSON value.\n\n    @since version 3.2.0\n    */\n    template <typename BasicJsonType,\n              detail::enable_if_t<\n                  detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0>\n    basic_json(const BasicJsonType& val)\n    {\n        using other_boolean_t = typename BasicJsonType::boolean_t;\n        using other_number_float_t = typename BasicJsonType::number_float_t;\n        using other_number_integer_t = typename BasicJsonType::number_integer_t;\n        using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;\n        using other_string_t = typename BasicJsonType::string_t;\n        using other_object_t = typename BasicJsonType::object_t;\n        using other_array_t = typename BasicJsonType::array_t;\n\n        switch (val.type())\n        {\n            case value_t::boolean:\n                JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());\n                break;\n            case value_t::number_float:\n                JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());\n                break;\n            case value_t::number_integer:\n                JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());\n                break;\n            case value_t::number_unsigned:\n                JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());\n                break;\n            case value_t::string:\n                JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());\n                break;\n            case value_t::object:\n                JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());\n                break;\n            case value_t::array:\n                JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());\n                break;\n            case value_t::null:\n                *this = nullptr;\n                break;\n            case value_t::discarded:\n                m_type = value_t::discarded;\n                break;\n        }\n        assert_invariant();\n    }\n\n    /*!\n    @brief create a container (array or object) from an initializer list\n\n    Creates a JSON value of type array or object from the passed initializer\n    list @a init. In case @a type_deduction is `true` (default), the type of\n    the JSON value to be created is deducted from the initializer list @a init\n    according to the following rules:\n\n    1. If the list is empty, an empty JSON object value `{}` is created.\n    2. If the list consists of pairs whose first element is a string, a JSON\n       object value is created where the first elements of the pairs are\n       treated as keys and the second elements are as values.\n    3. In all other cases, an array is created.\n\n    The rules aim to create the best fit between a C++ initializer list and\n    JSON values. The rationale is as follows:\n\n    1. The empty initializer list is written as `{}` which is exactly an empty\n       JSON object.\n    2. C++ has no way of describing mapped types other than to list a list of\n       pairs. As JSON requires that keys must be of type string, rule 2 is the\n       weakest constraint one can pose on initializer lists to interpret them\n       as an object.\n    3. In all other cases, the initializer list could not be interpreted as\n       JSON object type, so interpreting it as JSON array type is safe.\n\n    With the rules described above, the following JSON values cannot be\n    expressed by an initializer list:\n\n    - the empty array (`[]`): use @ref array(initializer_list_t)\n      with an empty initializer list in this case\n    - arrays whose elements satisfy rule 2: use @ref\n      array(initializer_list_t) with the same initializer list\n      in this case\n\n    @note When used without parentheses around an empty initializer list, @ref\n    basic_json() is called instead of this function, yielding the JSON null\n    value.\n\n    @param[in] init  initializer list with JSON values\n\n    @param[in] type_deduction internal parameter; when set to `true`, the type\n    of the JSON value is deducted from the initializer list @a init; when set\n    to `false`, the type provided via @a manual_type is forced. This mode is\n    used by the functions @ref array(initializer_list_t) and\n    @ref object(initializer_list_t).\n\n    @param[in] manual_type internal parameter; when @a type_deduction is set\n    to `false`, the created JSON value will use the provided type (only @ref\n    value_t::array and @ref value_t::object are valid); when @a type_deduction\n    is set to `true`, this parameter has no effect\n\n    @throw type_error.301 if @a type_deduction is `false`, @a manual_type is\n    `value_t::object`, but @a init contains an element which is not a pair\n    whose first element is a string. In this case, the constructor could not\n    create an object. If @a type_deduction would have be `true`, an array\n    would have been created. See @ref object(initializer_list_t)\n    for an example.\n\n    @complexity Linear in the size of the initializer list @a init.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes to any JSON value.\n\n    @liveexample{The example below shows how JSON values are created from\n    initializer lists.,basic_json__list_init_t}\n\n    @sa @ref array(initializer_list_t) -- create a JSON array\n    value from an initializer list\n    @sa @ref object(initializer_list_t) -- create a JSON object\n    value from an initializer list\n\n    @since version 1.0.0\n    */\n    basic_json(initializer_list_t init,\n               bool type_deduction = true,\n               value_t manual_type = value_t::array)\n    {\n        // check if each element is an array with two elements whose first\n        // element is a string\n        bool is_an_object = std::all_of(init.begin(), init.end(),\n                                        [](const detail::json_ref<basic_json>& element_ref)\n        {\n            return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());\n        });\n\n        // adjust type if type deduction is not wanted\n        if (not type_deduction)\n        {\n            // if array is wanted, do not create an object though possible\n            if (manual_type == value_t::array)\n            {\n                is_an_object = false;\n            }\n\n            // if object is wanted but impossible, throw an exception\n            if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))\n            {\n                JSON_THROW(type_error::create(301, \"cannot create object from initializer list\"));\n            }\n        }\n\n        if (is_an_object)\n        {\n            // the initializer list is a list of pairs -> create object\n            m_type = value_t::object;\n            m_value = value_t::object;\n\n            std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)\n            {\n                auto element = element_ref.moved_or_copied();\n                m_value.object->emplace(\n                    std::move(*((*element.m_value.array)[0].m_value.string)),\n                    std::move((*element.m_value.array)[1]));\n            });\n        }\n        else\n        {\n            // the initializer list describes an array -> create array\n            m_type = value_t::array;\n            m_value.array = create<array_t>(init.begin(), init.end());\n        }\n\n        assert_invariant();\n    }\n\n    /*!\n    @brief explicitly create an array from an initializer list\n\n    Creates a JSON array value from a given initializer list. That is, given a\n    list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the\n    initializer list is empty, the empty array `[]` is created.\n\n    @note This function is only needed to express two edge cases that cannot\n    be realized with the initializer list constructor (@ref\n    basic_json(initializer_list_t, bool, value_t)). These cases\n    are:\n    1. creating an array whose elements are all pairs whose first element is a\n    string -- in this case, the initializer list constructor would create an\n    object, taking the first elements as keys\n    2. creating an empty array -- passing the empty initializer list to the\n    initializer list constructor yields an empty object\n\n    @param[in] init  initializer list with JSON values to create an array from\n    (optional)\n\n    @return JSON array value\n\n    @complexity Linear in the size of @a init.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes to any JSON value.\n\n    @liveexample{The following code shows an example for the `array`\n    function.,array}\n\n    @sa @ref basic_json(initializer_list_t, bool, value_t) --\n    create a JSON value from an initializer list\n    @sa @ref object(initializer_list_t) -- create a JSON object\n    value from an initializer list\n\n    @since version 1.0.0\n    */\n    JSON_NODISCARD\n    static basic_json array(initializer_list_t init = {})\n    {\n        return basic_json(init, false, value_t::array);\n    }\n\n    /*!\n    @brief explicitly create an object from an initializer list\n\n    Creates a JSON object value from a given initializer list. The initializer\n    lists elements must be pairs, and their first elements must be strings. If\n    the initializer list is empty, the empty object `{}` is created.\n\n    @note This function is only added for symmetry reasons. In contrast to the\n    related function @ref array(initializer_list_t), there are\n    no cases which can only be expressed by this function. That is, any\n    initializer list @a init can also be passed to the initializer list\n    constructor @ref basic_json(initializer_list_t, bool, value_t).\n\n    @param[in] init  initializer list to create an object from (optional)\n\n    @return JSON object value\n\n    @throw type_error.301 if @a init is not a list of pairs whose first\n    elements are strings. In this case, no object can be created. When such a\n    value is passed to @ref basic_json(initializer_list_t, bool, value_t),\n    an array would have been created from the passed initializer list @a init.\n    See example below.\n\n    @complexity Linear in the size of @a init.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes to any JSON value.\n\n    @liveexample{The following code shows an example for the `object`\n    function.,object}\n\n    @sa @ref basic_json(initializer_list_t, bool, value_t) --\n    create a JSON value from an initializer list\n    @sa @ref array(initializer_list_t) -- create a JSON array\n    value from an initializer list\n\n    @since version 1.0.0\n    */\n    JSON_NODISCARD\n    static basic_json object(initializer_list_t init = {})\n    {\n        return basic_json(init, false, value_t::object);\n    }\n\n    /*!\n    @brief construct an array with count copies of given value\n\n    Constructs a JSON array value by creating @a cnt copies of a passed value.\n    In case @a cnt is `0`, an empty array is created.\n\n    @param[in] cnt  the number of JSON copies of @a val to create\n    @param[in] val  the JSON value to copy\n\n    @post `std::distance(begin(),end()) == cnt` holds.\n\n    @complexity Linear in @a cnt.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes to any JSON value.\n\n    @liveexample{The following code shows examples for the @ref\n    basic_json(size_type\\, const basic_json&)\n    constructor.,basic_json__size_type_basic_json}\n\n    @since version 1.0.0\n    */\n    basic_json(size_type cnt, const basic_json& val)\n        : m_type(value_t::array)\n    {\n        m_value.array = create<array_t>(cnt, val);\n        assert_invariant();\n    }\n\n    /*!\n    @brief construct a JSON container given an iterator range\n\n    Constructs the JSON value with the contents of the range `[first, last)`.\n    The semantics depends on the different types a JSON value can have:\n    - In case of a null type, invalid_iterator.206 is thrown.\n    - In case of other primitive types (number, boolean, or string), @a first\n      must be `begin()` and @a last must be `end()`. In this case, the value is\n      copied. Otherwise, invalid_iterator.204 is thrown.\n    - In case of structured types (array, object), the constructor behaves as\n      similar versions for `std::vector` or `std::map`; that is, a JSON array\n      or object is constructed from the values in the range.\n\n    @tparam InputIT an input iterator type (@ref iterator or @ref\n    const_iterator)\n\n    @param[in] first begin of the range to copy from (included)\n    @param[in] last end of the range to copy from (excluded)\n\n    @pre Iterators @a first and @a last must be initialized. **This\n         precondition is enforced with an assertion (see warning).** If\n         assertions are switched off, a violation of this precondition yields\n         undefined behavior.\n\n    @pre Range `[first, last)` is valid. Usually, this precondition cannot be\n         checked efficiently. Only certain edge cases are detected; see the\n         description of the exceptions below. A violation of this precondition\n         yields undefined behavior.\n\n    @warning A precondition is enforced with a runtime assertion that will\n             result in calling `std::abort` if this precondition is not met.\n             Assertions can be disabled by defining `NDEBUG` at compile time.\n             See https://en.cppreference.com/w/cpp/error/assert for more\n             information.\n\n    @throw invalid_iterator.201 if iterators @a first and @a last are not\n    compatible (i.e., do not belong to the same JSON value). In this case,\n    the range `[first, last)` is undefined.\n    @throw invalid_iterator.204 if iterators @a first and @a last belong to a\n    primitive type (number, boolean, or string), but @a first does not point\n    to the first element any more. In this case, the range `[first, last)` is\n    undefined. See example code below.\n    @throw invalid_iterator.206 if iterators @a first and @a last belong to a\n    null value. In this case, the range `[first, last)` is undefined.\n\n    @complexity Linear in distance between @a first and @a last.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes to any JSON value.\n\n    @liveexample{The example below shows several ways to create JSON values by\n    specifying a subrange with iterators.,basic_json__InputIt_InputIt}\n\n    @since version 1.0.0\n    */\n    template<class InputIT, typename std::enable_if<\n                 std::is_same<InputIT, typename basic_json_t::iterator>::value or\n                 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>\n    basic_json(InputIT first, InputIT last)\n    {\n        assert(first.m_object != nullptr);\n        assert(last.m_object != nullptr);\n\n        // make sure iterator fits the current value\n        if (JSON_UNLIKELY(first.m_object != last.m_object))\n        {\n            JSON_THROW(invalid_iterator::create(201, \"iterators are not compatible\"));\n        }\n\n        // copy type from first iterator\n        m_type = first.m_object->m_type;\n\n        // check if iterator range is complete for primitive values\n        switch (m_type)\n        {\n            case value_t::boolean:\n            case value_t::number_float:\n            case value_t::number_integer:\n            case value_t::number_unsigned:\n            case value_t::string:\n            {\n                if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()\n                                  or not last.m_it.primitive_iterator.is_end()))\n                {\n                    JSON_THROW(invalid_iterator::create(204, \"iterators out of range\"));\n                }\n                break;\n            }\n\n            default:\n                break;\n        }\n\n        switch (m_type)\n        {\n            case value_t::number_integer:\n            {\n                m_value.number_integer = first.m_object->m_value.number_integer;\n                break;\n            }\n\n            case value_t::number_unsigned:\n            {\n                m_value.number_unsigned = first.m_object->m_value.number_unsigned;\n                break;\n            }\n\n            case value_t::number_float:\n            {\n                m_value.number_float = first.m_object->m_value.number_float;\n                break;\n            }\n\n            case value_t::boolean:\n            {\n                m_value.boolean = first.m_object->m_value.boolean;\n                break;\n            }\n\n            case value_t::string:\n            {\n                m_value = *first.m_object->m_value.string;\n                break;\n            }\n\n            case value_t::object:\n            {\n                m_value.object = create<object_t>(first.m_it.object_iterator,\n                                                  last.m_it.object_iterator);\n                break;\n            }\n\n            case value_t::array:\n            {\n                m_value.array = create<array_t>(first.m_it.array_iterator,\n                                                last.m_it.array_iterator);\n                break;\n            }\n\n            default:\n                JSON_THROW(invalid_iterator::create(206, \"cannot construct with iterators from \" +\n                                                    std::string(first.m_object->type_name())));\n        }\n\n        assert_invariant();\n    }\n\n\n    ///////////////////////////////////////\n    // other constructors and destructor //\n    ///////////////////////////////////////\n\n    /// @private\n    basic_json(const detail::json_ref<basic_json>& ref)\n        : basic_json(ref.moved_or_copied())\n    {}\n\n    /*!\n    @brief copy constructor\n\n    Creates a copy of a given JSON value.\n\n    @param[in] other  the JSON value to copy\n\n    @post `*this == other`\n\n    @complexity Linear in the size of @a other.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes to any JSON value.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](https://en.cppreference.com/w/cpp/named_req/Container)\n    requirements:\n    - The complexity is linear.\n    - As postcondition, it holds: `other == basic_json(other)`.\n\n    @liveexample{The following code shows an example for the copy\n    constructor.,basic_json__basic_json}\n\n    @since version 1.0.0\n    */\n    basic_json(const basic_json& other)\n        : m_type(other.m_type)\n    {\n        // check of passed value is valid\n        other.assert_invariant();\n\n        switch (m_type)\n        {\n            case value_t::object:\n            {\n                m_value = *other.m_value.object;\n                break;\n            }\n\n            case value_t::array:\n            {\n                m_value = *other.m_value.array;\n                break;\n            }\n\n            case value_t::string:\n            {\n                m_value = *other.m_value.string;\n                break;\n            }\n\n            case value_t::boolean:\n            {\n                m_value = other.m_value.boolean;\n                break;\n            }\n\n            case value_t::number_integer:\n            {\n                m_value = other.m_value.number_integer;\n                break;\n            }\n\n            case value_t::number_unsigned:\n            {\n                m_value = other.m_value.number_unsigned;\n                break;\n            }\n\n            case value_t::number_float:\n            {\n                m_value = other.m_value.number_float;\n                break;\n            }\n\n            default:\n                break;\n        }\n\n        assert_invariant();\n    }\n\n    /*!\n    @brief move constructor\n\n    Move constructor. Constructs a JSON value with the contents of the given\n    value @a other using move semantics. It \"steals\" the resources from @a\n    other and leaves it as JSON null value.\n\n    @param[in,out] other  value to move to this object\n\n    @post `*this` has the same value as @a other before the call.\n    @post @a other is a JSON null value.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this constructor never throws\n    exceptions.\n\n    @requirement This function helps `basic_json` satisfying the\n    [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)\n    requirements.\n\n    @liveexample{The code below shows the move constructor explicitly called\n    via std::move.,basic_json__moveconstructor}\n\n    @since version 1.0.0\n    */\n    basic_json(basic_json&& other) noexcept\n        : m_type(std::move(other.m_type)),\n          m_value(std::move(other.m_value))\n    {\n        // check that passed value is valid\n        other.assert_invariant();\n\n        // invalidate payload\n        other.m_type = value_t::null;\n        other.m_value = {};\n\n        assert_invariant();\n    }\n\n    /*!\n    @brief copy assignment\n\n    Copy assignment operator. Copies a JSON value via the \"copy and swap\"\n    strategy: It is expressed in terms of the copy constructor, destructor,\n    and the `swap()` member function.\n\n    @param[in] other  value to copy from\n\n    @complexity Linear.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](https://en.cppreference.com/w/cpp/named_req/Container)\n    requirements:\n    - The complexity is linear.\n\n    @liveexample{The code below shows and example for the copy assignment. It\n    creates a copy of value `a` which is then swapped with `b`. Finally\\, the\n    copy of `a` (which is the null value after the swap) is\n    destroyed.,basic_json__copyassignment}\n\n    @since version 1.0.0\n    */\n    basic_json& operator=(basic_json other) noexcept (\n        std::is_nothrow_move_constructible<value_t>::value and\n        std::is_nothrow_move_assignable<value_t>::value and\n        std::is_nothrow_move_constructible<json_value>::value and\n        std::is_nothrow_move_assignable<json_value>::value\n    )\n    {\n        // check that passed value is valid\n        other.assert_invariant();\n\n        using std::swap;\n        swap(m_type, other.m_type);\n        swap(m_value, other.m_value);\n\n        assert_invariant();\n        return *this;\n    }\n\n    /*!\n    @brief destructor\n\n    Destroys the JSON value and frees all allocated memory.\n\n    @complexity Linear.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](https://en.cppreference.com/w/cpp/named_req/Container)\n    requirements:\n    - The complexity is linear.\n    - All stored elements are destroyed and all memory is freed.\n\n    @since version 1.0.0\n    */\n    ~basic_json() noexcept\n    {\n        assert_invariant();\n        m_value.destroy(m_type);\n    }\n\n    /// @}\n\n  public:\n    ///////////////////////\n    // object inspection //\n    ///////////////////////\n\n    /// @name object inspection\n    /// Functions to inspect the type of a JSON value.\n    /// @{\n\n    /*!\n    @brief serialization\n\n    Serialization function for JSON values. The function tries to mimic\n    Python's `json.dumps()` function, and currently supports its @a indent\n    and @a ensure_ascii parameters.\n\n    @param[in] indent If indent is nonnegative, then array elements and object\n    members will be pretty-printed with that indent level. An indent level of\n    `0` will only insert newlines. `-1` (the default) selects the most compact\n    representation.\n    @param[in] indent_char The character to use for indentation if @a indent is\n    greater than `0`. The default is ` ` (space).\n    @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters\n    in the output are escaped with `\\uXXXX` sequences, and the result consists\n    of ASCII characters only.\n    @param[in] error_handler  how to react on decoding errors; there are three\n    possible values: `strict` (throws and exception in case a decoding error\n    occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD),\n    and `ignore` (ignore invalid UTF-8 sequences during serialization).\n\n    @return string containing the serialization of the JSON value\n\n    @throw type_error.316 if a string stored inside the JSON value is not\n                          UTF-8 encoded\n\n    @complexity Linear.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes in the JSON value.\n\n    @liveexample{The following example shows the effect of different @a indent\\,\n    @a indent_char\\, and @a ensure_ascii parameters to the result of the\n    serialization.,dump}\n\n    @see https://docs.python.org/2/library/json.html#json.dump\n\n    @since version 1.0.0; indentation character @a indent_char, option\n           @a ensure_ascii and exceptions added in version 3.0.0; error\n           handlers added in version 3.4.0.\n    */\n    string_t dump(const int indent = -1,\n                  const char indent_char = ' ',\n                  const bool ensure_ascii = false,\n                  const error_handler_t error_handler = error_handler_t::strict) const\n    {\n        string_t result;\n        serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);\n\n        if (indent >= 0)\n        {\n            s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));\n        }\n        else\n        {\n            s.dump(*this, false, ensure_ascii, 0);\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief return the type of the JSON value (explicit)\n\n    Return the type of the JSON value as a value from the @ref value_t\n    enumeration.\n\n    @return the type of the JSON value\n            Value type                | return value\n            ------------------------- | -------------------------\n            null                      | value_t::null\n            boolean                   | value_t::boolean\n            string                    | value_t::string\n            number (integer)          | value_t::number_integer\n            number (unsigned integer) | value_t::number_unsigned\n            number (floating-point)   | value_t::number_float\n            object                    | value_t::object\n            array                     | value_t::array\n            discarded                 | value_t::discarded\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `type()` for all JSON\n    types.,type}\n\n    @sa @ref operator value_t() -- return the type of the JSON value (implicit)\n    @sa @ref type_name() -- return the type as string\n\n    @since version 1.0.0\n    */\n    constexpr value_t type() const noexcept\n    {\n        return m_type;\n    }\n\n    /*!\n    @brief return whether type is primitive\n\n    This function returns true if and only if the JSON type is primitive\n    (string, number, boolean, or null).\n\n    @return `true` if type is primitive (string, number, boolean, or null),\n    `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_primitive()` for all JSON\n    types.,is_primitive}\n\n    @sa @ref is_structured() -- returns whether JSON value is structured\n    @sa @ref is_null() -- returns whether JSON value is `null`\n    @sa @ref is_string() -- returns whether JSON value is a string\n    @sa @ref is_boolean() -- returns whether JSON value is a boolean\n    @sa @ref is_number() -- returns whether JSON value is a number\n\n    @since version 1.0.0\n    */\n    constexpr bool is_primitive() const noexcept\n    {\n        return is_null() or is_string() or is_boolean() or is_number();\n    }\n\n    /*!\n    @brief return whether type is structured\n\n    This function returns true if and only if the JSON type is structured\n    (array or object).\n\n    @return `true` if type is structured (array or object), `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_structured()` for all JSON\n    types.,is_structured}\n\n    @sa @ref is_primitive() -- returns whether value is primitive\n    @sa @ref is_array() -- returns whether value is an array\n    @sa @ref is_object() -- returns whether value is an object\n\n    @since version 1.0.0\n    */\n    constexpr bool is_structured() const noexcept\n    {\n        return is_array() or is_object();\n    }\n\n    /*!\n    @brief return whether value is null\n\n    This function returns true if and only if the JSON value is null.\n\n    @return `true` if type is null, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_null()` for all JSON\n    types.,is_null}\n\n    @since version 1.0.0\n    */\n    constexpr bool is_null() const noexcept\n    {\n        return (m_type == value_t::null);\n    }\n\n    /*!\n    @brief return whether value is a boolean\n\n    This function returns true if and only if the JSON value is a boolean.\n\n    @return `true` if type is boolean, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_boolean()` for all JSON\n    types.,is_boolean}\n\n    @since version 1.0.0\n    */\n    constexpr bool is_boolean() const noexcept\n    {\n        return (m_type == value_t::boolean);\n    }\n\n    /*!\n    @brief return whether value is a number\n\n    This function returns true if and only if the JSON value is a number. This\n    includes both integer (signed and unsigned) and floating-point values.\n\n    @return `true` if type is number (regardless whether integer, unsigned\n    integer or floating-type), `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_number()` for all JSON\n    types.,is_number}\n\n    @sa @ref is_number_integer() -- check if value is an integer or unsigned\n    integer number\n    @sa @ref is_number_unsigned() -- check if value is an unsigned integer\n    number\n    @sa @ref is_number_float() -- check if value is a floating-point number\n\n    @since version 1.0.0\n    */\n    constexpr bool is_number() const noexcept\n    {\n        return is_number_integer() or is_number_float();\n    }\n\n    /*!\n    @brief return whether value is an integer number\n\n    This function returns true if and only if the JSON value is a signed or\n    unsigned integer number. This excludes floating-point values.\n\n    @return `true` if type is an integer or unsigned integer number, `false`\n    otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_number_integer()` for all\n    JSON types.,is_number_integer}\n\n    @sa @ref is_number() -- check if value is a number\n    @sa @ref is_number_unsigned() -- check if value is an unsigned integer\n    number\n    @sa @ref is_number_float() -- check if value is a floating-point number\n\n    @since version 1.0.0\n    */\n    constexpr bool is_number_integer() const noexcept\n    {\n        return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);\n    }\n\n    /*!\n    @brief return whether value is an unsigned integer number\n\n    This function returns true if and only if the JSON value is an unsigned\n    integer number. This excludes floating-point and signed integer values.\n\n    @return `true` if type is an unsigned integer number, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_number_unsigned()` for all\n    JSON types.,is_number_unsigned}\n\n    @sa @ref is_number() -- check if value is a number\n    @sa @ref is_number_integer() -- check if value is an integer or unsigned\n    integer number\n    @sa @ref is_number_float() -- check if value is a floating-point number\n\n    @since version 2.0.0\n    */\n    constexpr bool is_number_unsigned() const noexcept\n    {\n        return (m_type == value_t::number_unsigned);\n    }\n\n    /*!\n    @brief return whether value is a floating-point number\n\n    This function returns true if and only if the JSON value is a\n    floating-point number. This excludes signed and unsigned integer values.\n\n    @return `true` if type is a floating-point number, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_number_float()` for all\n    JSON types.,is_number_float}\n\n    @sa @ref is_number() -- check if value is number\n    @sa @ref is_number_integer() -- check if value is an integer number\n    @sa @ref is_number_unsigned() -- check if value is an unsigned integer\n    number\n\n    @since version 1.0.0\n    */\n    constexpr bool is_number_float() const noexcept\n    {\n        return (m_type == value_t::number_float);\n    }\n\n    /*!\n    @brief return whether value is an object\n\n    This function returns true if and only if the JSON value is an object.\n\n    @return `true` if type is object, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_object()` for all JSON\n    types.,is_object}\n\n    @since version 1.0.0\n    */\n    constexpr bool is_object() const noexcept\n    {\n        return (m_type == value_t::object);\n    }\n\n    /*!\n    @brief return whether value is an array\n\n    This function returns true if and only if the JSON value is an array.\n\n    @return `true` if type is array, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_array()` for all JSON\n    types.,is_array}\n\n    @since version 1.0.0\n    */\n    constexpr bool is_array() const noexcept\n    {\n        return (m_type == value_t::array);\n    }\n\n    /*!\n    @brief return whether value is a string\n\n    This function returns true if and only if the JSON value is a string.\n\n    @return `true` if type is string, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_string()` for all JSON\n    types.,is_string}\n\n    @since version 1.0.0\n    */\n    constexpr bool is_string() const noexcept\n    {\n        return (m_type == value_t::string);\n    }\n\n    /*!\n    @brief return whether value is discarded\n\n    This function returns true if and only if the JSON value was discarded\n    during parsing with a callback function (see @ref parser_callback_t).\n\n    @note This function will always be `false` for JSON values after parsing.\n    That is, discarded values can only occur during parsing, but will be\n    removed when inside a structured value or replaced by null in other cases.\n\n    @return `true` if type is discarded, `false` otherwise.\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies `is_discarded()` for all JSON\n    types.,is_discarded}\n\n    @since version 1.0.0\n    */\n    constexpr bool is_discarded() const noexcept\n    {\n        return (m_type == value_t::discarded);\n    }\n\n    /*!\n    @brief return the type of the JSON value (implicit)\n\n    Implicitly return the type of the JSON value as a value from the @ref\n    value_t enumeration.\n\n    @return the type of the JSON value\n\n    @complexity Constant.\n\n    @exceptionsafety No-throw guarantee: this member function never throws\n    exceptions.\n\n    @liveexample{The following code exemplifies the @ref value_t operator for\n    all JSON types.,operator__value_t}\n\n    @sa @ref type() -- return the type of the JSON value (explicit)\n    @sa @ref type_name() -- return the type as string\n\n    @since version 1.0.0\n    */\n    constexpr operator value_t() const noexcept\n    {\n        return m_type;\n    }\n\n    /// @}\n\n  private:\n    //////////////////\n    // value access //\n    //////////////////\n\n    /// get a boolean (explicit)\n    boolean_t get_impl(boolean_t* /*unused*/) const\n    {\n        if (JSON_LIKELY(is_boolean()))\n        {\n            return m_value.boolean;\n        }\n\n        JSON_THROW(type_error::create(302, \"type must be boolean, but is \" + std::string(type_name())));\n    }\n\n    /// get a pointer to the value (object)\n    object_t* get_impl_ptr(object_t* /*unused*/) noexcept\n    {\n        return is_object() ? m_value.object : nullptr;\n    }\n\n    /// get a pointer to the value (object)\n    constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept\n    {\n        return is_object() ? m_value.object : nullptr;\n    }\n\n    /// get a pointer to the value (array)\n    array_t* get_impl_ptr(array_t* /*unused*/) noexcept\n    {\n        return is_array() ? m_value.array : nullptr;\n    }\n\n    /// get a pointer to the value (array)\n    constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept\n    {\n        return is_array() ? m_value.array : nullptr;\n    }\n\n    /// get a pointer to the value (string)\n    string_t* get_impl_ptr(string_t* /*unused*/) noexcept\n    {\n        return is_string() ? m_value.string : nullptr;\n    }\n\n    /// get a pointer to the value (string)\n    constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept\n    {\n        return is_string() ? m_value.string : nullptr;\n    }\n\n    /// get a pointer to the value (boolean)\n    boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept\n    {\n        return is_boolean() ? &m_value.boolean : nullptr;\n    }\n\n    /// get a pointer to the value (boolean)\n    constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept\n    {\n        return is_boolean() ? &m_value.boolean : nullptr;\n    }\n\n    /// get a pointer to the value (integer number)\n    number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept\n    {\n        return is_number_integer() ? &m_value.number_integer : nullptr;\n    }\n\n    /// get a pointer to the value (integer number)\n    constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept\n    {\n        return is_number_integer() ? &m_value.number_integer : nullptr;\n    }\n\n    /// get a pointer to the value (unsigned number)\n    number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept\n    {\n        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;\n    }\n\n    /// get a pointer to the value (unsigned number)\n    constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept\n    {\n        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;\n    }\n\n    /// get a pointer to the value (floating-point number)\n    number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept\n    {\n        return is_number_float() ? &m_value.number_float : nullptr;\n    }\n\n    /// get a pointer to the value (floating-point number)\n    constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept\n    {\n        return is_number_float() ? &m_value.number_float : nullptr;\n    }\n\n    /*!\n    @brief helper function to implement get_ref()\n\n    This function helps to implement get_ref() without code duplication for\n    const and non-const overloads\n\n    @tparam ThisType will be deduced as `basic_json` or `const basic_json`\n\n    @throw type_error.303 if ReferenceType does not match underlying value\n    type of the current JSON\n    */\n    template<typename ReferenceType, typename ThisType>\n    static ReferenceType get_ref_impl(ThisType& obj)\n    {\n        // delegate the call to get_ptr<>()\n        auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();\n\n        if (JSON_LIKELY(ptr != nullptr))\n        {\n            return *ptr;\n        }\n\n        JSON_THROW(type_error::create(303, \"incompatible ReferenceType for get_ref, actual type is \" + std::string(obj.type_name())));\n    }\n\n  public:\n    /// @name value access\n    /// Direct access to the stored value of a JSON value.\n    /// @{\n\n    /*!\n    @brief get special-case overload\n\n    This overloads avoids a lot of template boilerplate, it can be seen as the\n    identity method\n\n    @tparam BasicJsonType == @ref basic_json\n\n    @return a copy of *this\n\n    @complexity Constant.\n\n    @since version 2.1.0\n    */\n    template<typename BasicJsonType, detail::enable_if_t<\n                 std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,\n                 int> = 0>\n    basic_json get() const\n    {\n        return *this;\n    }\n\n    /*!\n    @brief get special-case overload\n\n    This overloads converts the current @ref basic_json in a different\n    @ref basic_json type\n\n    @tparam BasicJsonType == @ref basic_json\n\n    @return a copy of *this, converted into @tparam BasicJsonType\n\n    @complexity Depending on the implementation of the called `from_json()`\n                method.\n\n    @since version 3.2.0\n    */\n    template<typename BasicJsonType, detail::enable_if_t<\n                 not std::is_same<BasicJsonType, basic_json>::value and\n                 detail::is_basic_json<BasicJsonType>::value, int> = 0>\n    BasicJsonType get() const\n    {\n        return *this;\n    }\n\n    /*!\n    @brief get a value (explicit)\n\n    Explicit type conversion between the JSON value and a compatible value\n    which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)\n    and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).\n    The value is converted by calling the @ref json_serializer<ValueType>\n    `from_json()` method.\n\n    The function is equivalent to executing\n    @code {.cpp}\n    ValueType ret;\n    JSONSerializer<ValueType>::from_json(*this, ret);\n    return ret;\n    @endcode\n\n    This overloads is chosen if:\n    - @a ValueType is not @ref basic_json,\n    - @ref json_serializer<ValueType> has a `from_json()` method of the form\n      `void from_json(const basic_json&, ValueType&)`, and\n    - @ref json_serializer<ValueType> does not have a `from_json()` method of\n      the form `ValueType from_json(const basic_json&)`\n\n    @tparam ValueTypeCV the provided value type\n    @tparam ValueType the returned value type\n\n    @return copy of the JSON value, converted to @a ValueType\n\n    @throw what @ref json_serializer<ValueType> `from_json()` method throws\n\n    @liveexample{The example below shows several conversions from JSON values\n    to other types. There a few things to note: (1) Floating-point numbers can\n    be converted to integers\\, (2) A JSON array can be converted to a standard\n    `std::vector<short>`\\, (3) A JSON object can be converted to C++\n    associative containers such as `std::unordered_map<std::string\\,\n    json>`.,get__ValueType_const}\n\n    @since version 2.1.0\n    */\n    template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,\n             detail::enable_if_t <\n                 not detail::is_basic_json<ValueType>::value and\n                 detail::has_from_json<basic_json_t, ValueType>::value and\n                 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,\n                 int> = 0>\n    ValueType get() const noexcept(noexcept(\n                                       JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))\n    {\n        // we cannot static_assert on ValueTypeCV being non-const, because\n        // there is support for get<const basic_json_t>(), which is why we\n        // still need the uncvref\n        static_assert(not std::is_reference<ValueTypeCV>::value,\n                      \"get() cannot be used with reference types, you might want to use get_ref()\");\n        static_assert(std::is_default_constructible<ValueType>::value,\n                      \"types must be DefaultConstructible when used with get()\");\n\n        ValueType ret;\n        JSONSerializer<ValueType>::from_json(*this, ret);\n        return ret;\n    }\n\n    /*!\n    @brief get a value (explicit); special case\n\n    Explicit type conversion between the JSON value and a compatible value\n    which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)\n    and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).\n    The value is converted by calling the @ref json_serializer<ValueType>\n    `from_json()` method.\n\n    The function is equivalent to executing\n    @code {.cpp}\n    return JSONSerializer<ValueTypeCV>::from_json(*this);\n    @endcode\n\n    This overloads is chosen if:\n    - @a ValueType is not @ref basic_json and\n    - @ref json_serializer<ValueType> has a `from_json()` method of the form\n      `ValueType from_json(const basic_json&)`\n\n    @note If @ref json_serializer<ValueType> has both overloads of\n    `from_json()`, this one is chosen.\n\n    @tparam ValueTypeCV the provided value type\n    @tparam ValueType the returned value type\n\n    @return copy of the JSON value, converted to @a ValueType\n\n    @throw what @ref json_serializer<ValueType> `from_json()` method throws\n\n    @since version 2.1.0\n    */\n    template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,\n             detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and\n                                 detail::has_non_default_from_json<basic_json_t, ValueType>::value,\n                                 int> = 0>\n    ValueType get() const noexcept(noexcept(\n                                       JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))\n    {\n        static_assert(not std::is_reference<ValueTypeCV>::value,\n                      \"get() cannot be used with reference types, you might want to use get_ref()\");\n        return JSONSerializer<ValueTypeCV>::from_json(*this);\n    }\n\n    /*!\n    @brief get a value (explicit)\n\n    Explicit type conversion between the JSON value and a compatible value.\n    The value is filled into the input parameter by calling the @ref json_serializer<ValueType>\n    `from_json()` method.\n\n    The function is equivalent to executing\n    @code {.cpp}\n    ValueType v;\n    JSONSerializer<ValueType>::from_json(*this, v);\n    @endcode\n\n    This overloads is chosen if:\n    - @a ValueType is not @ref basic_json,\n    - @ref json_serializer<ValueType> has a `from_json()` method of the form\n      `void from_json(const basic_json&, ValueType&)`, and\n\n    @tparam ValueType the input parameter type.\n\n    @return the input parameter, allowing chaining calls.\n\n    @throw what @ref json_serializer<ValueType> `from_json()` method throws\n\n    @liveexample{The example below shows several conversions from JSON values\n    to other types. There a few things to note: (1) Floating-point numbers can\n    be converted to integers\\, (2) A JSON array can be converted to a standard\n    `std::vector<short>`\\, (3) A JSON object can be converted to C++\n    associative containers such as `std::unordered_map<std::string\\,\n    json>`.,get_to}\n\n    @since version 3.3.0\n    */\n    template<typename ValueType,\n             detail::enable_if_t <\n                 not detail::is_basic_json<ValueType>::value and\n                 detail::has_from_json<basic_json_t, ValueType>::value,\n                 int> = 0>\n    ValueType & get_to(ValueType& v) const noexcept(noexcept(\n                JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))\n    {\n        JSONSerializer<ValueType>::from_json(*this, v);\n        return v;\n    }\n\n\n    /*!\n    @brief get a pointer value (implicit)\n\n    Implicit pointer access to the internally stored JSON value. No copies are\n    made.\n\n    @warning Writing data to the pointee of the result yields an undefined\n    state.\n\n    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref\n    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,\n    @ref number_unsigned_t, or @ref number_float_t. Enforced by a static\n    assertion.\n\n    @return pointer to the internally stored JSON value if the requested\n    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how pointers to internal values of a\n    JSON value can be requested. Note that no type conversions are made and a\n    `nullptr` is returned if the value and the requested pointer type does not\n    match.,get_ptr}\n\n    @since version 1.0.0\n    */\n    template<typename PointerType, typename std::enable_if<\n                 std::is_pointer<PointerType>::value, int>::type = 0>\n    auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))\n    {\n        // delegate the call to get_impl_ptr<>()\n        return get_impl_ptr(static_cast<PointerType>(nullptr));\n    }\n\n    /*!\n    @brief get a pointer value (implicit)\n    @copydoc get_ptr()\n    */\n    template<typename PointerType, typename std::enable_if<\n                 std::is_pointer<PointerType>::value and\n                 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>\n    constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))\n    {\n        // delegate the call to get_impl_ptr<>() const\n        return get_impl_ptr(static_cast<PointerType>(nullptr));\n    }\n\n    /*!\n    @brief get a pointer value (explicit)\n\n    Explicit pointer access to the internally stored JSON value. No copies are\n    made.\n\n    @warning The pointer becomes invalid if the underlying JSON object\n    changes.\n\n    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref\n    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,\n    @ref number_unsigned_t, or @ref number_float_t.\n\n    @return pointer to the internally stored JSON value if the requested\n    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how pointers to internal values of a\n    JSON value can be requested. Note that no type conversions are made and a\n    `nullptr` is returned if the value and the requested pointer type does not\n    match.,get__PointerType}\n\n    @sa @ref get_ptr() for explicit pointer-member access\n\n    @since version 1.0.0\n    */\n    template<typename PointerType, typename std::enable_if<\n                 std::is_pointer<PointerType>::value, int>::type = 0>\n    auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())\n    {\n        // delegate the call to get_ptr\n        return get_ptr<PointerType>();\n    }\n\n    /*!\n    @brief get a pointer value (explicit)\n    @copydoc get()\n    */\n    template<typename PointerType, typename std::enable_if<\n                 std::is_pointer<PointerType>::value, int>::type = 0>\n    constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())\n    {\n        // delegate the call to get_ptr\n        return get_ptr<PointerType>();\n    }\n\n    /*!\n    @brief get a reference value (implicit)\n\n    Implicit reference access to the internally stored JSON value. No copies\n    are made.\n\n    @warning Writing data to the referee of the result yields an undefined\n    state.\n\n    @tparam ReferenceType reference type; must be a reference to @ref array_t,\n    @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or\n    @ref number_float_t. Enforced by static assertion.\n\n    @return reference to the internally stored JSON value if the requested\n    reference type @a ReferenceType fits to the JSON value; throws\n    type_error.303 otherwise\n\n    @throw type_error.303 in case passed type @a ReferenceType is incompatible\n    with the stored JSON value; see example below\n\n    @complexity Constant.\n\n    @liveexample{The example shows several calls to `get_ref()`.,get_ref}\n\n    @since version 1.1.0\n    */\n    template<typename ReferenceType, typename std::enable_if<\n                 std::is_reference<ReferenceType>::value, int>::type = 0>\n    ReferenceType get_ref()\n    {\n        // delegate call to get_ref_impl\n        return get_ref_impl<ReferenceType>(*this);\n    }\n\n    /*!\n    @brief get a reference value (implicit)\n    @copydoc get_ref()\n    */\n    template<typename ReferenceType, typename std::enable_if<\n                 std::is_reference<ReferenceType>::value and\n                 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>\n    ReferenceType get_ref() const\n    {\n        // delegate call to get_ref_impl\n        return get_ref_impl<ReferenceType>(*this);\n    }\n\n    /*!\n    @brief get a value (implicit)\n\n    Implicit type conversion between the JSON value and a compatible value.\n    The call is realized by calling @ref get() const.\n\n    @tparam ValueType non-pointer type compatible to the JSON value, for\n    instance `int` for JSON integer numbers, `bool` for JSON booleans, or\n    `std::vector` types for JSON arrays. The character type of @ref string_t\n    as well as an initializer list of this type is excluded to avoid\n    ambiguities as these types implicitly convert to `std::string`.\n\n    @return copy of the JSON value, converted to type @a ValueType\n\n    @throw type_error.302 in case passed type @a ValueType is incompatible\n    to the JSON value type (e.g., the JSON value is of type boolean, but a\n    string is requested); see example below\n\n    @complexity Linear in the size of the JSON value.\n\n    @liveexample{The example below shows several conversions from JSON values\n    to other types. There a few things to note: (1) Floating-point numbers can\n    be converted to integers\\, (2) A JSON array can be converted to a standard\n    `std::vector<short>`\\, (3) A JSON object can be converted to C++\n    associative containers such as `std::unordered_map<std::string\\,\n    json>`.,operator__ValueType}\n\n    @since version 1.0.0\n    */\n    template < typename ValueType, typename std::enable_if <\n                   not std::is_pointer<ValueType>::value and\n                   not std::is_same<ValueType, detail::json_ref<basic_json>>::value and\n                   not std::is_same<ValueType, typename string_t::value_type>::value and\n                   not detail::is_basic_json<ValueType>::value\n\n#ifndef _MSC_VER  // fix for issue #167 operator<< ambiguity under VS2015\n                   and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value\n#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914\n                   and not std::is_same<ValueType, typename std::string_view>::value\n#endif\n#endif\n                   and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value\n                   , int >::type = 0 >\n    operator ValueType() const\n    {\n        // delegate the call to get<>() const\n        return get<ValueType>();\n    }\n\n    /// @}\n\n\n    ////////////////////\n    // element access //\n    ////////////////////\n\n    /// @name element access\n    /// Access to the JSON value.\n    /// @{\n\n    /*!\n    @brief access specified array element with bounds checking\n\n    Returns a reference to the element at specified location @a idx, with\n    bounds checking.\n\n    @param[in] idx  index of the element to access\n\n    @return reference to the element at index @a idx\n\n    @throw type_error.304 if the JSON value is not an array; in this case,\n    calling `at` with an index makes no sense. See example below.\n    @throw out_of_range.401 if the index @a idx is out of range of the array;\n    that is, `idx >= size()`. See example below.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes in the JSON value.\n\n    @complexity Constant.\n\n    @since version 1.0.0\n\n    @liveexample{The example below shows how array elements can be read and\n    written using `at()`. It also demonstrates the different exceptions that\n    can be thrown.,at__size_type}\n    */\n    reference at(size_type idx)\n    {\n        // at only works for arrays\n        if (JSON_LIKELY(is_array()))\n        {\n            JSON_TRY\n            {\n                return m_value.array->at(idx);\n            }\n            JSON_CATCH (std::out_of_range&)\n            {\n                // create better exception explanation\n                JSON_THROW(out_of_range::create(401, \"array index \" + std::to_string(idx) + \" is out of range\"));\n            }\n        }\n        else\n        {\n            JSON_THROW(type_error::create(304, \"cannot use at() with \" + std::string(type_name())));\n        }\n    }\n\n    /*!\n    @brief access specified array element with bounds checking\n\n    Returns a const reference to the element at specified location @a idx,\n    with bounds checking.\n\n    @param[in] idx  index of the element to access\n\n    @return const reference to the element at index @a idx\n\n    @throw type_error.304 if the JSON value is not an array; in this case,\n    calling `at` with an index makes no sense. See example below.\n    @throw out_of_range.401 if the index @a idx is out of range of the array;\n    that is, `idx >= size()`. See example below.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes in the JSON value.\n\n    @complexity Constant.\n\n    @since version 1.0.0\n\n    @liveexample{The example below shows how array elements can be read using\n    `at()`. It also demonstrates the different exceptions that can be thrown.,\n    at__size_type_const}\n    */\n    const_reference at(size_type idx) const\n    {\n        // at only works for arrays\n        if (JSON_LIKELY(is_array()))\n        {\n            JSON_TRY\n            {\n                return m_value.array->at(idx);\n            }\n            JSON_CATCH (std::out_of_range&)\n            {\n                // create better exception explanation\n                JSON_THROW(out_of_range::create(401, \"array index \" + std::to_string(idx) + \" is out of range\"));\n            }\n        }\n        else\n        {\n            JSON_THROW(type_error::create(304, \"cannot use at() with \" + std::string(type_name())));\n        }\n    }\n\n    /*!\n    @brief access specified object element with bounds checking\n\n    Returns a reference to the element at with specified key @a key, with\n    bounds checking.\n\n    @param[in] key  key of the element to access\n\n    @return reference to the element at key @a key\n\n    @throw type_error.304 if the JSON value is not an object; in this case,\n    calling `at` with a key makes no sense. See example below.\n    @throw out_of_range.403 if the key @a key is is not stored in the object;\n    that is, `find(key) == end()`. See example below.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes in the JSON value.\n\n    @complexity Logarithmic in the size of the container.\n\n    @sa @ref operator[](const typename object_t::key_type&) for unchecked\n    access by reference\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.0.0\n\n    @liveexample{The example below shows how object elements can be read and\n    written using `at()`. It also demonstrates the different exceptions that\n    can be thrown.,at__object_t_key_type}\n    */\n    reference at(const typename object_t::key_type& key)\n    {\n        // at only works for objects\n        if (JSON_LIKELY(is_object()))\n        {\n            JSON_TRY\n            {\n                return m_value.object->at(key);\n            }\n            JSON_CATCH (std::out_of_range&)\n            {\n                // create better exception explanation\n                JSON_THROW(out_of_range::create(403, \"key '\" + key + \"' not found\"));\n            }\n        }\n        else\n        {\n            JSON_THROW(type_error::create(304, \"cannot use at() with \" + std::string(type_name())));\n        }\n    }\n\n    /*!\n    @brief access specified object element with bounds checking\n\n    Returns a const reference to the element at with specified key @a key,\n    with bounds checking.\n\n    @param[in] key  key of the element to access\n\n    @return const reference to the element at key @a key\n\n    @throw type_error.304 if the JSON value is not an object; in this case,\n    calling `at` with a key makes no sense. See example below.\n    @throw out_of_range.403 if the key @a key is is not stored in the object;\n    that is, `find(key) == end()`. See example below.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes in the JSON value.\n\n    @complexity Logarithmic in the size of the container.\n\n    @sa @ref operator[](const typename object_t::key_type&) for unchecked\n    access by reference\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.0.0\n\n    @liveexample{The example below shows how object elements can be read using\n    `at()`. It also demonstrates the different exceptions that can be thrown.,\n    at__object_t_key_type_const}\n    */\n    const_reference at(const typename object_t::key_type& key) const\n    {\n        // at only works for objects\n        if (JSON_LIKELY(is_object()))\n        {\n            JSON_TRY\n            {\n                return m_value.object->at(key);\n            }\n            JSON_CATCH (std::out_of_range&)\n            {\n                // create better exception explanation\n                JSON_THROW(out_of_range::create(403, \"key '\" + key + \"' not found\"));\n            }\n        }\n        else\n        {\n            JSON_THROW(type_error::create(304, \"cannot use at() with \" + std::string(type_name())));\n        }\n    }\n\n    /*!\n    @brief access specified array element\n\n    Returns a reference to the element at specified location @a idx.\n\n    @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),\n    then the array is silently filled up with `null` values to make `idx` a\n    valid reference to the last stored element.\n\n    @param[in] idx  index of the element to access\n\n    @return reference to the element at index @a idx\n\n    @throw type_error.305 if the JSON value is not an array or null; in that\n    cases, using the [] operator with an index makes no sense.\n\n    @complexity Constant if @a idx is in the range of the array. Otherwise\n    linear in `idx - size()`.\n\n    @liveexample{The example below shows how array elements can be read and\n    written using `[]` operator. Note the addition of `null`\n    values.,operatorarray__size_type}\n\n    @since version 1.0.0\n    */\n    reference operator[](size_type idx)\n    {\n        // implicitly convert null value to an empty array\n        if (is_null())\n        {\n            m_type = value_t::array;\n            m_value.array = create<array_t>();\n            assert_invariant();\n        }\n\n        // operator[] only works for arrays\n        if (JSON_LIKELY(is_array()))\n        {\n            // fill up array with null values if given idx is outside range\n            if (idx >= m_value.array->size())\n            {\n                m_value.array->insert(m_value.array->end(),\n                                      idx - m_value.array->size() + 1,\n                                      basic_json());\n            }\n\n            return m_value.array->operator[](idx);\n        }\n\n        JSON_THROW(type_error::create(305, \"cannot use operator[] with a numeric argument with \" + std::string(type_name())));\n    }\n\n    /*!\n    @brief access specified array element\n\n    Returns a const reference to the element at specified location @a idx.\n\n    @param[in] idx  index of the element to access\n\n    @return const reference to the element at index @a idx\n\n    @throw type_error.305 if the JSON value is not an array; in that case,\n    using the [] operator with an index makes no sense.\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how array elements can be read using\n    the `[]` operator.,operatorarray__size_type_const}\n\n    @since version 1.0.0\n    */\n    const_reference operator[](size_type idx) const\n    {\n        // const operator[] only works for arrays\n        if (JSON_LIKELY(is_array()))\n        {\n            return m_value.array->operator[](idx);\n        }\n\n        JSON_THROW(type_error::create(305, \"cannot use operator[] with a numeric argument with \" + std::string(type_name())));\n    }\n\n    /*!\n    @brief access specified object element\n\n    Returns a reference to the element at with specified key @a key.\n\n    @note If @a key is not found in the object, then it is silently added to\n    the object and filled with a `null` value to make `key` a valid reference.\n    In case the value was `null` before, it is converted to an object.\n\n    @param[in] key  key of the element to access\n\n    @return reference to the element at key @a key\n\n    @throw type_error.305 if the JSON value is not an object or null; in that\n    cases, using the [] operator with a key makes no sense.\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be read and\n    written using the `[]` operator.,operatorarray__key_type}\n\n    @sa @ref at(const typename object_t::key_type&) for access by reference\n    with range checking\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.0.0\n    */\n    reference operator[](const typename object_t::key_type& key)\n    {\n        // implicitly convert null value to an empty object\n        if (is_null())\n        {\n            m_type = value_t::object;\n            m_value.object = create<object_t>();\n            assert_invariant();\n        }\n\n        // operator[] only works for objects\n        if (JSON_LIKELY(is_object()))\n        {\n            return m_value.object->operator[](key);\n        }\n\n        JSON_THROW(type_error::create(305, \"cannot use operator[] with a string argument with \" + std::string(type_name())));\n    }\n\n    /*!\n    @brief read-only access specified object element\n\n    Returns a const reference to the element at with specified key @a key. No\n    bounds checking is performed.\n\n    @warning If the element with key @a key does not exist, the behavior is\n    undefined.\n\n    @param[in] key  key of the element to access\n\n    @return const reference to the element at key @a key\n\n    @pre The element with key @a key must exist. **This precondition is\n         enforced with an assertion.**\n\n    @throw type_error.305 if the JSON value is not an object; in that case,\n    using the [] operator with a key makes no sense.\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be read using\n    the `[]` operator.,operatorarray__key_type_const}\n\n    @sa @ref at(const typename object_t::key_type&) for access by reference\n    with range checking\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.0.0\n    */\n    const_reference operator[](const typename object_t::key_type& key) const\n    {\n        // const operator[] only works for objects\n        if (JSON_LIKELY(is_object()))\n        {\n            assert(m_value.object->find(key) != m_value.object->end());\n            return m_value.object->find(key)->second;\n        }\n\n        JSON_THROW(type_error::create(305, \"cannot use operator[] with a string argument with \" + std::string(type_name())));\n    }\n\n    /*!\n    @brief access specified object element\n\n    Returns a reference to the element at with specified key @a key.\n\n    @note If @a key is not found in the object, then it is silently added to\n    the object and filled with a `null` value to make `key` a valid reference.\n    In case the value was `null` before, it is converted to an object.\n\n    @param[in] key  key of the element to access\n\n    @return reference to the element at key @a key\n\n    @throw type_error.305 if the JSON value is not an object or null; in that\n    cases, using the [] operator with a key makes no sense.\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be read and\n    written using the `[]` operator.,operatorarray__key_type}\n\n    @sa @ref at(const typename object_t::key_type&) for access by reference\n    with range checking\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.1.0\n    */\n    template<typename T>\n    reference operator[](T* key)\n    {\n        // implicitly convert null to object\n        if (is_null())\n        {\n            m_type = value_t::object;\n            m_value = value_t::object;\n            assert_invariant();\n        }\n\n        // at only works for objects\n        if (JSON_LIKELY(is_object()))\n        {\n            return m_value.object->operator[](key);\n        }\n\n        JSON_THROW(type_error::create(305, \"cannot use operator[] with a string argument with \" + std::string(type_name())));\n    }\n\n    /*!\n    @brief read-only access specified object element\n\n    Returns a const reference to the element at with specified key @a key. No\n    bounds checking is performed.\n\n    @warning If the element with key @a key does not exist, the behavior is\n    undefined.\n\n    @param[in] key  key of the element to access\n\n    @return const reference to the element at key @a key\n\n    @pre The element with key @a key must exist. **This precondition is\n         enforced with an assertion.**\n\n    @throw type_error.305 if the JSON value is not an object; in that case,\n    using the [] operator with a key makes no sense.\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be read using\n    the `[]` operator.,operatorarray__key_type_const}\n\n    @sa @ref at(const typename object_t::key_type&) for access by reference\n    with range checking\n    @sa @ref value() for access by value with a default value\n\n    @since version 1.1.0\n    */\n    template<typename T>\n    const_reference operator[](T* key) const\n    {\n        // at only works for objects\n        if (JSON_LIKELY(is_object()))\n        {\n            assert(m_value.object->find(key) != m_value.object->end());\n            return m_value.object->find(key)->second;\n        }\n\n        JSON_THROW(type_error::create(305, \"cannot use operator[] with a string argument with \" + std::string(type_name())));\n    }\n\n    /*!\n    @brief access specified object element with default value\n\n    Returns either a copy of an object's element at the specified key @a key\n    or a given default value if no element with key @a key exists.\n\n    The function is basically equivalent to executing\n    @code {.cpp}\n    try {\n        return at(key);\n    } catch(out_of_range) {\n        return default_value;\n    }\n    @endcode\n\n    @note Unlike @ref at(const typename object_t::key_type&), this function\n    does not throw if the given key @a key was not found.\n\n    @note Unlike @ref operator[](const typename object_t::key_type& key), this\n    function does not implicitly add an element to the position defined by @a\n    key. This function is furthermore also applicable to const objects.\n\n    @param[in] key  key of the element to access\n    @param[in] default_value  the value to return if @a key is not found\n\n    @tparam ValueType type compatible to JSON values, for instance `int` for\n    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for\n    JSON arrays. Note the type of the expected value at @a key and the default\n    value @a default_value must be compatible.\n\n    @return copy of the element at key @a key or @a default_value if @a key\n    is not found\n\n    @throw type_error.306 if the JSON value is not an object; in that case,\n    using `value()` with a key makes no sense.\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be queried\n    with a default value.,basic_json__value}\n\n    @sa @ref at(const typename object_t::key_type&) for access by reference\n    with range checking\n    @sa @ref operator[](const typename object_t::key_type&) for unchecked\n    access by reference\n\n    @since version 1.0.0\n    */\n    template<class ValueType, typename std::enable_if<\n                 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>\n    ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const\n    {\n        // at only works for objects\n        if (JSON_LIKELY(is_object()))\n        {\n            // if key is found, return value and given default value otherwise\n            const auto it = find(key);\n            if (it != end())\n            {\n                return *it;\n            }\n\n            return default_value;\n        }\n\n        JSON_THROW(type_error::create(306, \"cannot use value() with \" + std::string(type_name())));\n    }\n\n    /*!\n    @brief overload for a default value of type const char*\n    @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const\n    */\n    string_t value(const typename object_t::key_type& key, const char* default_value) const\n    {\n        return value(key, string_t(default_value));\n    }\n\n    /*!\n    @brief access specified object element via JSON Pointer with default value\n\n    Returns either a copy of an object's element at the specified key @a key\n    or a given default value if no element with key @a key exists.\n\n    The function is basically equivalent to executing\n    @code {.cpp}\n    try {\n        return at(ptr);\n    } catch(out_of_range) {\n        return default_value;\n    }\n    @endcode\n\n    @note Unlike @ref at(const json_pointer&), this function does not throw\n    if the given key @a key was not found.\n\n    @param[in] ptr  a JSON pointer to the element to access\n    @param[in] default_value  the value to return if @a ptr found no value\n\n    @tparam ValueType type compatible to JSON values, for instance `int` for\n    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for\n    JSON arrays. Note the type of the expected value at @a key and the default\n    value @a default_value must be compatible.\n\n    @return copy of the element at key @a key or @a default_value if @a key\n    is not found\n\n    @throw type_error.306 if the JSON value is not an object; in that case,\n    using `value()` with a key makes no sense.\n\n    @complexity Logarithmic in the size of the container.\n\n    @liveexample{The example below shows how object elements can be queried\n    with a default value.,basic_json__value_ptr}\n\n    @sa @ref operator[](const json_pointer&) for unchecked access by reference\n\n    @since version 2.0.2\n    */\n    template<class ValueType, typename std::enable_if<\n                 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>\n    ValueType value(const json_pointer& ptr, const ValueType& default_value) const\n    {\n        // at only works for objects\n        if (JSON_LIKELY(is_object()))\n        {\n            // if pointer resolves a value, return it or use default value\n            JSON_TRY\n            {\n                return ptr.get_checked(this);\n            }\n            JSON_INTERNAL_CATCH (out_of_range&)\n            {\n                return default_value;\n            }\n        }\n\n        JSON_THROW(type_error::create(306, \"cannot use value() with \" + std::string(type_name())));\n    }\n\n    /*!\n    @brief overload for a default value of type const char*\n    @copydoc basic_json::value(const json_pointer&, ValueType) const\n    */\n    string_t value(const json_pointer& ptr, const char* default_value) const\n    {\n        return value(ptr, string_t(default_value));\n    }\n\n    /*!\n    @brief access the first element\n\n    Returns a reference to the first element in the container. For a JSON\n    container `c`, the expression `c.front()` is equivalent to `*c.begin()`.\n\n    @return In case of a structured type (array or object), a reference to the\n    first element is returned. In case of number, string, or boolean values, a\n    reference to the value is returned.\n\n    @complexity Constant.\n\n    @pre The JSON value must not be `null` (would throw `std::out_of_range`)\n    or an empty array or object (undefined behavior, **guarded by\n    assertions**).\n    @post The JSON value remains unchanged.\n\n    @throw invalid_iterator.214 when called on `null` value\n\n    @liveexample{The following code shows an example for `front()`.,front}\n\n    @sa @ref back() -- access the last element\n\n    @since version 1.0.0\n    */\n    reference front()\n    {\n        return *begin();\n    }\n\n    /*!\n    @copydoc basic_json::front()\n    */\n    const_reference front() const\n    {\n        return *cbegin();\n    }\n\n    /*!\n    @brief access the last element\n\n    Returns a reference to the last element in the container. For a JSON\n    container `c`, the expression `c.back()` is equivalent to\n    @code {.cpp}\n    auto tmp = c.end();\n    --tmp;\n    return *tmp;\n    @endcode\n\n    @return In case of a structured type (array or object), a reference to the\n    last element is returned. In case of number, string, or boolean values, a\n    reference to the value is returned.\n\n    @complexity Constant.\n\n    @pre The JSON value must not be `null` (would throw `std::out_of_range`)\n    or an empty array or object (undefined behavior, **guarded by\n    assertions**).\n    @post The JSON value remains unchanged.\n\n    @throw invalid_iterator.214 when called on a `null` value. See example\n    below.\n\n    @liveexample{The following code shows an example for `back()`.,back}\n\n    @sa @ref front() -- access the first element\n\n    @since version 1.0.0\n    */\n    reference back()\n    {\n        auto tmp = end();\n        --tmp;\n        return *tmp;\n    }\n\n    /*!\n    @copydoc basic_json::back()\n    */\n    const_reference back() const\n    {\n        auto tmp = cend();\n        --tmp;\n        return *tmp;\n    }\n\n    /*!\n    @brief remove element given an iterator\n\n    Removes the element specified by iterator @a pos. The iterator @a pos must\n    be valid and dereferenceable. Thus the `end()` iterator (which is valid,\n    but is not dereferenceable) cannot be used as a value for @a pos.\n\n    If called on a primitive type other than `null`, the resulting JSON value\n    will be `null`.\n\n    @param[in] pos iterator to the element to remove\n    @return Iterator following the last removed element. If the iterator @a\n    pos refers to the last element, the `end()` iterator is returned.\n\n    @tparam IteratorType an @ref iterator or @ref const_iterator\n\n    @post Invalidates iterators and references at or after the point of the\n    erase, including the `end()` iterator.\n\n    @throw type_error.307 if called on a `null` value; example: `\"cannot use\n    erase() with null\"`\n    @throw invalid_iterator.202 if called on an iterator which does not belong\n    to the current JSON value; example: `\"iterator does not fit current\n    value\"`\n    @throw invalid_iterator.205 if called on a primitive type with invalid\n    iterator (i.e., any iterator which is not `begin()`); example: `\"iterator\n    out of range\"`\n\n    @complexity The complexity depends on the type:\n    - objects: amortized constant\n    - arrays: linear in distance between @a pos and the end of the container\n    - strings: linear in the length of the string\n    - other types: constant\n\n    @liveexample{The example shows the result of `erase()` for different JSON\n    types.,erase__IteratorType}\n\n    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in\n    the given range\n    @sa @ref erase(const typename object_t::key_type&) -- removes the element\n    from an object at the given key\n    @sa @ref erase(const size_type) -- removes the element from an array at\n    the given index\n\n    @since version 1.0.0\n    */\n    template<class IteratorType, typename std::enable_if<\n                 std::is_same<IteratorType, typename basic_json_t::iterator>::value or\n                 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type\n             = 0>\n    IteratorType erase(IteratorType pos)\n    {\n        // make sure iterator fits the current value\n        if (JSON_UNLIKELY(this != pos.m_object))\n        {\n            JSON_THROW(invalid_iterator::create(202, \"iterator does not fit current value\"));\n        }\n\n        IteratorType result = end();\n\n        switch (m_type)\n        {\n            case value_t::boolean:\n            case value_t::number_float:\n            case value_t::number_integer:\n            case value_t::number_unsigned:\n            case value_t::string:\n            {\n                if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))\n                {\n                    JSON_THROW(invalid_iterator::create(205, \"iterator out of range\"));\n                }\n\n                if (is_string())\n                {\n                    AllocatorType<string_t> alloc;\n                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);\n                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);\n                    m_value.string = nullptr;\n                }\n\n                m_type = value_t::null;\n                assert_invariant();\n                break;\n            }\n\n            case value_t::object:\n            {\n                result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);\n                break;\n            }\n\n            case value_t::array:\n            {\n                result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);\n                break;\n            }\n\n            default:\n                JSON_THROW(type_error::create(307, \"cannot use erase() with \" + std::string(type_name())));\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief remove elements given an iterator range\n\n    Removes the element specified by the range `[first; last)`. The iterator\n    @a first does not need to be dereferenceable if `first == last`: erasing\n    an empty range is a no-op.\n\n    If called on a primitive type other than `null`, the resulting JSON value\n    will be `null`.\n\n    @param[in] first iterator to the beginning of the range to remove\n    @param[in] last iterator past the end of the range to remove\n    @return Iterator following the last removed element. If the iterator @a\n    second refers to the last element, the `end()` iterator is returned.\n\n    @tparam IteratorType an @ref iterator or @ref const_iterator\n\n    @post Invalidates iterators and references at or after the point of the\n    erase, including the `end()` iterator.\n\n    @throw type_error.307 if called on a `null` value; example: `\"cannot use\n    erase() with null\"`\n    @throw invalid_iterator.203 if called on iterators which does not belong\n    to the current JSON value; example: `\"iterators do not fit current value\"`\n    @throw invalid_iterator.204 if called on a primitive type with invalid\n    iterators (i.e., if `first != begin()` and `last != end()`); example:\n    `\"iterators out of range\"`\n\n    @complexity The complexity depends on the type:\n    - objects: `log(size()) + std::distance(first, last)`\n    - arrays: linear in the distance between @a first and @a last, plus linear\n      in the distance between @a last and end of the container\n    - strings: linear in the length of the string\n    - other types: constant\n\n    @liveexample{The example shows the result of `erase()` for different JSON\n    types.,erase__IteratorType_IteratorType}\n\n    @sa @ref erase(IteratorType) -- removes the element at a given position\n    @sa @ref erase(const typename object_t::key_type&) -- removes the element\n    from an object at the given key\n    @sa @ref erase(const size_type) -- removes the element from an array at\n    the given index\n\n    @since version 1.0.0\n    */\n    template<class IteratorType, typename std::enable_if<\n                 std::is_same<IteratorType, typename basic_json_t::iterator>::value or\n                 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type\n             = 0>\n    IteratorType erase(IteratorType first, IteratorType last)\n    {\n        // make sure iterator fits the current value\n        if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))\n        {\n            JSON_THROW(invalid_iterator::create(203, \"iterators do not fit current value\"));\n        }\n\n        IteratorType result = end();\n\n        switch (m_type)\n        {\n            case value_t::boolean:\n            case value_t::number_float:\n            case value_t::number_integer:\n            case value_t::number_unsigned:\n            case value_t::string:\n            {\n                if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()\n                                or not last.m_it.primitive_iterator.is_end()))\n                {\n                    JSON_THROW(invalid_iterator::create(204, \"iterators out of range\"));\n                }\n\n                if (is_string())\n                {\n                    AllocatorType<string_t> alloc;\n                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);\n                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);\n                    m_value.string = nullptr;\n                }\n\n                m_type = value_t::null;\n                assert_invariant();\n                break;\n            }\n\n            case value_t::object:\n            {\n                result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,\n                                              last.m_it.object_iterator);\n                break;\n            }\n\n            case value_t::array:\n            {\n                result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,\n                                             last.m_it.array_iterator);\n                break;\n            }\n\n            default:\n                JSON_THROW(type_error::create(307, \"cannot use erase() with \" + std::string(type_name())));\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief remove element from a JSON object given a key\n\n    Removes elements from a JSON object with the key value @a key.\n\n    @param[in] key value of the elements to remove\n\n    @return Number of elements removed. If @a ObjectType is the default\n    `std::map` type, the return value will always be `0` (@a key was not\n    found) or `1` (@a key was found).\n\n    @post References and iterators to the erased elements are invalidated.\n    Other references and iterators are not affected.\n\n    @throw type_error.307 when called on a type other than JSON object;\n    example: `\"cannot use erase() with null\"`\n\n    @complexity `log(size()) + count(key)`\n\n    @liveexample{The example shows the effect of `erase()`.,erase__key_type}\n\n    @sa @ref erase(IteratorType) -- removes the element at a given position\n    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in\n    the given range\n    @sa @ref erase(const size_type) -- removes the element from an array at\n    the given index\n\n    @since version 1.0.0\n    */\n    size_type erase(const typename object_t::key_type& key)\n    {\n        // this erase only works for objects\n        if (JSON_LIKELY(is_object()))\n        {\n            return m_value.object->erase(key);\n        }\n\n        JSON_THROW(type_error::create(307, \"cannot use erase() with \" + std::string(type_name())));\n    }\n\n    /*!\n    @brief remove element from a JSON array given an index\n\n    Removes element from a JSON array at the index @a idx.\n\n    @param[in] idx index of the element to remove\n\n    @throw type_error.307 when called on a type other than JSON object;\n    example: `\"cannot use erase() with null\"`\n    @throw out_of_range.401 when `idx >= size()`; example: `\"array index 17\n    is out of range\"`\n\n    @complexity Linear in distance between @a idx and the end of the container.\n\n    @liveexample{The example shows the effect of `erase()`.,erase__size_type}\n\n    @sa @ref erase(IteratorType) -- removes the element at a given position\n    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in\n    the given range\n    @sa @ref erase(const typename object_t::key_type&) -- removes the element\n    from an object at the given key\n\n    @since version 1.0.0\n    */\n    void erase(const size_type idx)\n    {\n        // this erase only works for arrays\n        if (JSON_LIKELY(is_array()))\n        {\n            if (JSON_UNLIKELY(idx >= size()))\n            {\n                JSON_THROW(out_of_range::create(401, \"array index \" + std::to_string(idx) + \" is out of range\"));\n            }\n\n            m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));\n        }\n        else\n        {\n            JSON_THROW(type_error::create(307, \"cannot use erase() with \" + std::string(type_name())));\n        }\n    }\n\n    /// @}\n\n\n    ////////////\n    // lookup //\n    ////////////\n\n    /// @name lookup\n    /// @{\n\n    /*!\n    @brief find an element in a JSON object\n\n    Finds an element in a JSON object with key equivalent to @a key. If the\n    element is not found or the JSON value is not an object, end() is\n    returned.\n\n    @note This method always returns @ref end() when executed on a JSON type\n          that is not an object.\n\n    @param[in] key key value of the element to search for.\n\n    @return Iterator to an element with key equivalent to @a key. If no such\n    element is found or the JSON value is not an object, past-the-end (see\n    @ref end()) iterator is returned.\n\n    @complexity Logarithmic in the size of the JSON object.\n\n    @liveexample{The example shows how `find()` is used.,find__key_type}\n\n    @since version 1.0.0\n    */\n    template<typename KeyT>\n    iterator find(KeyT&& key)\n    {\n        auto result = end();\n\n        if (is_object())\n        {\n            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief find an element in a JSON object\n    @copydoc find(KeyT&&)\n    */\n    template<typename KeyT>\n    const_iterator find(KeyT&& key) const\n    {\n        auto result = cend();\n\n        if (is_object())\n        {\n            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief returns the number of occurrences of a key in a JSON object\n\n    Returns the number of elements with key @a key. If ObjectType is the\n    default `std::map` type, the return value will always be `0` (@a key was\n    not found) or `1` (@a key was found).\n\n    @note This method always returns `0` when executed on a JSON type that is\n          not an object.\n\n    @param[in] key key value of the element to count\n\n    @return Number of elements with key @a key. If the JSON value is not an\n    object, the return value will be `0`.\n\n    @complexity Logarithmic in the size of the JSON object.\n\n    @liveexample{The example shows how `count()` is used.,count}\n\n    @since version 1.0.0\n    */\n    template<typename KeyT>\n    size_type count(KeyT&& key) const\n    {\n        // return 0 for all nonobject types\n        return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;\n    }\n\n    /*!\n    @brief check the existence of an element in a JSON object\n\n    Check whether an element exists in a JSON object with key equivalent to\n    @a key. If the element is not found or the JSON value is not an object,\n    false is returned.\n\n    @note This method always returns false when executed on a JSON type\n          that is not an object.\n\n    @param[in] key key value to check its existence.\n\n    @return true if an element with specified @a key exists. If no such\n    element with such key is found or the JSON value is not an object,\n    false is returned.\n\n    @complexity Logarithmic in the size of the JSON object.\n\n    @since version 3.6.0\n    */\n    template<typename KeyT>\n    bool contains(KeyT&& key) const\n    {\n        if (is_object())\n        {\n            return (m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end());\n        }\n        else\n        {\n            return false;\n        }\n    }\n\n    /// @}\n\n\n    ///////////////\n    // iterators //\n    ///////////////\n\n    /// @name iterators\n    /// @{\n\n    /*!\n    @brief returns an iterator to the first element\n\n    Returns an iterator to the first element.\n\n    @image html range-begin-end.svg \"Illustration from cppreference.com\"\n\n    @return iterator to the first element\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](https://en.cppreference.com/w/cpp/named_req/Container)\n    requirements:\n    - The complexity is constant.\n\n    @liveexample{The following code shows an example for `begin()`.,begin}\n\n    @sa @ref cbegin() -- returns a const iterator to the beginning\n    @sa @ref end() -- returns an iterator to the end\n    @sa @ref cend() -- returns a const iterator to the end\n\n    @since version 1.0.0\n    */\n    iterator begin() noexcept\n    {\n        iterator result(this);\n        result.set_begin();\n        return result;\n    }\n\n    /*!\n    @copydoc basic_json::cbegin()\n    */\n    const_iterator begin() const noexcept\n    {\n        return cbegin();\n    }\n\n    /*!\n    @brief returns a const iterator to the first element\n\n    Returns a const iterator to the first element.\n\n    @image html range-begin-end.svg \"Illustration from cppreference.com\"\n\n    @return const iterator to the first element\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](https://en.cppreference.com/w/cpp/named_req/Container)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.\n\n    @liveexample{The following code shows an example for `cbegin()`.,cbegin}\n\n    @sa @ref begin() -- returns an iterator to the beginning\n    @sa @ref end() -- returns an iterator to the end\n    @sa @ref cend() -- returns a const iterator to the end\n\n    @since version 1.0.0\n    */\n    const_iterator cbegin() const noexcept\n    {\n        const_iterator result(this);\n        result.set_begin();\n        return result;\n    }\n\n    /*!\n    @brief returns an iterator to one past the last element\n\n    Returns an iterator to one past the last element.\n\n    @image html range-begin-end.svg \"Illustration from cppreference.com\"\n\n    @return iterator one past the last element\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](https://en.cppreference.com/w/cpp/named_req/Container)\n    requirements:\n    - The complexity is constant.\n\n    @liveexample{The following code shows an example for `end()`.,end}\n\n    @sa @ref cend() -- returns a const iterator to the end\n    @sa @ref begin() -- returns an iterator to the beginning\n    @sa @ref cbegin() -- returns a const iterator to the beginning\n\n    @since version 1.0.0\n    */\n    iterator end() noexcept\n    {\n        iterator result(this);\n        result.set_end();\n        return result;\n    }\n\n    /*!\n    @copydoc basic_json::cend()\n    */\n    const_iterator end() const noexcept\n    {\n        return cend();\n    }\n\n    /*!\n    @brief returns a const iterator to one past the last element\n\n    Returns a const iterator to one past the last element.\n\n    @image html range-begin-end.svg \"Illustration from cppreference.com\"\n\n    @return const iterator one past the last element\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](https://en.cppreference.com/w/cpp/named_req/Container)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `const_cast<const basic_json&>(*this).end()`.\n\n    @liveexample{The following code shows an example for `cend()`.,cend}\n\n    @sa @ref end() -- returns an iterator to the end\n    @sa @ref begin() -- returns an iterator to the beginning\n    @sa @ref cbegin() -- returns a const iterator to the beginning\n\n    @since version 1.0.0\n    */\n    const_iterator cend() const noexcept\n    {\n        const_iterator result(this);\n        result.set_end();\n        return result;\n    }\n\n    /*!\n    @brief returns an iterator to the reverse-beginning\n\n    Returns an iterator to the reverse-beginning; that is, the last element.\n\n    @image html range-rbegin-rend.svg \"Illustration from cppreference.com\"\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `reverse_iterator(end())`.\n\n    @liveexample{The following code shows an example for `rbegin()`.,rbegin}\n\n    @sa @ref crbegin() -- returns a const reverse iterator to the beginning\n    @sa @ref rend() -- returns a reverse iterator to the end\n    @sa @ref crend() -- returns a const reverse iterator to the end\n\n    @since version 1.0.0\n    */\n    reverse_iterator rbegin() noexcept\n    {\n        return reverse_iterator(end());\n    }\n\n    /*!\n    @copydoc basic_json::crbegin()\n    */\n    const_reverse_iterator rbegin() const noexcept\n    {\n        return crbegin();\n    }\n\n    /*!\n    @brief returns an iterator to the reverse-end\n\n    Returns an iterator to the reverse-end; that is, one before the first\n    element.\n\n    @image html range-rbegin-rend.svg \"Illustration from cppreference.com\"\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `reverse_iterator(begin())`.\n\n    @liveexample{The following code shows an example for `rend()`.,rend}\n\n    @sa @ref crend() -- returns a const reverse iterator to the end\n    @sa @ref rbegin() -- returns a reverse iterator to the beginning\n    @sa @ref crbegin() -- returns a const reverse iterator to the beginning\n\n    @since version 1.0.0\n    */\n    reverse_iterator rend() noexcept\n    {\n        return reverse_iterator(begin());\n    }\n\n    /*!\n    @copydoc basic_json::crend()\n    */\n    const_reverse_iterator rend() const noexcept\n    {\n        return crend();\n    }\n\n    /*!\n    @brief returns a const reverse iterator to the last element\n\n    Returns a const iterator to the reverse-beginning; that is, the last\n    element.\n\n    @image html range-rbegin-rend.svg \"Illustration from cppreference.com\"\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.\n\n    @liveexample{The following code shows an example for `crbegin()`.,crbegin}\n\n    @sa @ref rbegin() -- returns a reverse iterator to the beginning\n    @sa @ref rend() -- returns a reverse iterator to the end\n    @sa @ref crend() -- returns a const reverse iterator to the end\n\n    @since version 1.0.0\n    */\n    const_reverse_iterator crbegin() const noexcept\n    {\n        return const_reverse_iterator(cend());\n    }\n\n    /*!\n    @brief returns a const reverse iterator to one before the first\n\n    Returns a const reverse iterator to the reverse-end; that is, one before\n    the first element.\n\n    @image html range-rbegin-rend.svg \"Illustration from cppreference.com\"\n\n    @complexity Constant.\n\n    @requirement This function helps `basic_json` satisfying the\n    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.\n\n    @liveexample{The following code shows an example for `crend()`.,crend}\n\n    @sa @ref rend() -- returns a reverse iterator to the end\n    @sa @ref rbegin() -- returns a reverse iterator to the beginning\n    @sa @ref crbegin() -- returns a const reverse iterator to the beginning\n\n    @since version 1.0.0\n    */\n    const_reverse_iterator crend() const noexcept\n    {\n        return const_reverse_iterator(cbegin());\n    }\n\n  public:\n    /*!\n    @brief wrapper to access iterator member functions in range-based for\n\n    This function allows to access @ref iterator::key() and @ref\n    iterator::value() during range-based for loops. In these loops, a\n    reference to the JSON values is returned, so there is no access to the\n    underlying iterator.\n\n    For loop without iterator_wrapper:\n\n    @code{cpp}\n    for (auto it = j_object.begin(); it != j_object.end(); ++it)\n    {\n        std::cout << \"key: \" << it.key() << \", value:\" << it.value() << '\\n';\n    }\n    @endcode\n\n    Range-based for loop without iterator proxy:\n\n    @code{cpp}\n    for (auto it : j_object)\n    {\n        // \"it\" is of type json::reference and has no key() member\n        std::cout << \"value: \" << it << '\\n';\n    }\n    @endcode\n\n    Range-based for loop with iterator proxy:\n\n    @code{cpp}\n    for (auto it : json::iterator_wrapper(j_object))\n    {\n        std::cout << \"key: \" << it.key() << \", value:\" << it.value() << '\\n';\n    }\n    @endcode\n\n    @note When iterating over an array, `key()` will return the index of the\n          element as string (see example).\n\n    @param[in] ref  reference to a JSON value\n    @return iteration proxy object wrapping @a ref with an interface to use in\n            range-based for loops\n\n    @liveexample{The following code shows how the wrapper is used,iterator_wrapper}\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes in the JSON value.\n\n    @complexity Constant.\n\n    @note The name of this function is not yet final and may change in the\n    future.\n\n    @deprecated This stream operator is deprecated and will be removed in\n                future 4.0.0 of the library. Please use @ref items() instead;\n                that is, replace `json::iterator_wrapper(j)` with `j.items()`.\n    */\n    JSON_DEPRECATED\n    static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept\n    {\n        return ref.items();\n    }\n\n    /*!\n    @copydoc iterator_wrapper(reference)\n    */\n    JSON_DEPRECATED\n    static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept\n    {\n        return ref.items();\n    }\n\n    /*!\n    @brief helper to access iterator member functions in range-based for\n\n    This function allows to access @ref iterator::key() and @ref\n    iterator::value() during range-based for loops. In these loops, a\n    reference to the JSON values is returned, so there is no access to the\n    underlying iterator.\n\n    For loop without `items()` function:\n\n    @code{cpp}\n    for (auto it = j_object.begin(); it != j_object.end(); ++it)\n    {\n        std::cout << \"key: \" << it.key() << \", value:\" << it.value() << '\\n';\n    }\n    @endcode\n\n    Range-based for loop without `items()` function:\n\n    @code{cpp}\n    for (auto it : j_object)\n    {\n        // \"it\" is of type json::reference and has no key() member\n        std::cout << \"value: \" << it << '\\n';\n    }\n    @endcode\n\n    Range-based for loop with `items()` function:\n\n    @code{cpp}\n    for (auto& el : j_object.items())\n    {\n        std::cout << \"key: \" << el.key() << \", value:\" << el.value() << '\\n';\n    }\n    @endcode\n\n    The `items()` function also allows to use\n    [structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding)\n    (C++17):\n\n    @code{cpp}\n    for (auto& [key, val] : j_object.items())\n    {\n        std::cout << \"key: \" << key << \", value:\" << val << '\\n';\n    }\n    @endcode\n\n    @note When iterating over an array, `key()` will return the index of the\n          element as string (see example). For primitive types (e.g., numbers),\n          `key()` returns an empty string.\n\n    @return iteration proxy object wrapping @a ref with an interface to use in\n            range-based for loops\n\n    @liveexample{The following code shows how the function is used.,items}\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes in the JSON value.\n\n    @complexity Constant.\n\n    @since version 3.1.0, structured bindings support since 3.5.0.\n    */\n    iteration_proxy<iterator> items() noexcept\n    {\n        return iteration_proxy<iterator>(*this);\n    }\n\n    /*!\n    @copydoc items()\n    */\n    iteration_proxy<const_iterator> items() const noexcept\n    {\n        return iteration_proxy<const_iterator>(*this);\n    }\n\n    /// @}\n\n\n    //////////////\n    // capacity //\n    //////////////\n\n    /// @name capacity\n    /// @{\n\n    /*!\n    @brief checks whether the container is empty.\n\n    Checks if a JSON value has no elements (i.e. whether its @ref size is `0`).\n\n    @return The return value depends on the different types and is\n            defined as follows:\n            Value type  | return value\n            ----------- | -------------\n            null        | `true`\n            boolean     | `false`\n            string      | `false`\n            number      | `false`\n            object      | result of function `object_t::empty()`\n            array       | result of function `array_t::empty()`\n\n    @liveexample{The following code uses `empty()` to check if a JSON\n    object contains any elements.,empty}\n\n    @complexity Constant, as long as @ref array_t and @ref object_t satisfy\n    the Container concept; that is, their `empty()` functions have constant\n    complexity.\n\n    @iterators No changes.\n\n    @exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n    @note This function does not return whether a string stored as JSON value\n    is empty - it returns whether the JSON container itself is empty which is\n    false in the case of a string.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](https://en.cppreference.com/w/cpp/named_req/Container)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `begin() == end()`.\n\n    @sa @ref size() -- returns the number of elements\n\n    @since version 1.0.0\n    */\n    bool empty() const noexcept\n    {\n        switch (m_type)\n        {\n            case value_t::null:\n            {\n                // null values are empty\n                return true;\n            }\n\n            case value_t::array:\n            {\n                // delegate call to array_t::empty()\n                return m_value.array->empty();\n            }\n\n            case value_t::object:\n            {\n                // delegate call to object_t::empty()\n                return m_value.object->empty();\n            }\n\n            default:\n            {\n                // all other types are nonempty\n                return false;\n            }\n        }\n    }\n\n    /*!\n    @brief returns the number of elements\n\n    Returns the number of elements in a JSON value.\n\n    @return The return value depends on the different types and is\n            defined as follows:\n            Value type  | return value\n            ----------- | -------------\n            null        | `0`\n            boolean     | `1`\n            string      | `1`\n            number      | `1`\n            object      | result of function object_t::size()\n            array       | result of function array_t::size()\n\n    @liveexample{The following code calls `size()` on the different value\n    types.,size}\n\n    @complexity Constant, as long as @ref array_t and @ref object_t satisfy\n    the Container concept; that is, their size() functions have constant\n    complexity.\n\n    @iterators No changes.\n\n    @exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n    @note This function does not return the length of a string stored as JSON\n    value - it returns the number of elements in the JSON value which is 1 in\n    the case of a string.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](https://en.cppreference.com/w/cpp/named_req/Container)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of `std::distance(begin(), end())`.\n\n    @sa @ref empty() -- checks whether the container is empty\n    @sa @ref max_size() -- returns the maximal number of elements\n\n    @since version 1.0.0\n    */\n    size_type size() const noexcept\n    {\n        switch (m_type)\n        {\n            case value_t::null:\n            {\n                // null values are empty\n                return 0;\n            }\n\n            case value_t::array:\n            {\n                // delegate call to array_t::size()\n                return m_value.array->size();\n            }\n\n            case value_t::object:\n            {\n                // delegate call to object_t::size()\n                return m_value.object->size();\n            }\n\n            default:\n            {\n                // all other types have size 1\n                return 1;\n            }\n        }\n    }\n\n    /*!\n    @brief returns the maximum possible number of elements\n\n    Returns the maximum number of elements a JSON value is able to hold due to\n    system or library implementation limitations, i.e. `std::distance(begin(),\n    end())` for the JSON value.\n\n    @return The return value depends on the different types and is\n            defined as follows:\n            Value type  | return value\n            ----------- | -------------\n            null        | `0` (same as `size()`)\n            boolean     | `1` (same as `size()`)\n            string      | `1` (same as `size()`)\n            number      | `1` (same as `size()`)\n            object      | result of function `object_t::max_size()`\n            array       | result of function `array_t::max_size()`\n\n    @liveexample{The following code calls `max_size()` on the different value\n    types. Note the output is implementation specific.,max_size}\n\n    @complexity Constant, as long as @ref array_t and @ref object_t satisfy\n    the Container concept; that is, their `max_size()` functions have constant\n    complexity.\n\n    @iterators No changes.\n\n    @exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n    @requirement This function helps `basic_json` satisfying the\n    [Container](https://en.cppreference.com/w/cpp/named_req/Container)\n    requirements:\n    - The complexity is constant.\n    - Has the semantics of returning `b.size()` where `b` is the largest\n      possible JSON value.\n\n    @sa @ref size() -- returns the number of elements\n\n    @since version 1.0.0\n    */\n    size_type max_size() const noexcept\n    {\n        switch (m_type)\n        {\n            case value_t::array:\n            {\n                // delegate call to array_t::max_size()\n                return m_value.array->max_size();\n            }\n\n            case value_t::object:\n            {\n                // delegate call to object_t::max_size()\n                return m_value.object->max_size();\n            }\n\n            default:\n            {\n                // all other types have max_size() == size()\n                return size();\n            }\n        }\n    }\n\n    /// @}\n\n\n    ///////////////\n    // modifiers //\n    ///////////////\n\n    /// @name modifiers\n    /// @{\n\n    /*!\n    @brief clears the contents\n\n    Clears the content of a JSON value and resets it to the default value as\n    if @ref basic_json(value_t) would have been called with the current value\n    type from @ref type():\n\n    Value type  | initial value\n    ----------- | -------------\n    null        | `null`\n    boolean     | `false`\n    string      | `\"\"`\n    number      | `0`\n    object      | `{}`\n    array       | `[]`\n\n    @post Has the same effect as calling\n    @code {.cpp}\n    *this = basic_json(type());\n    @endcode\n\n    @liveexample{The example below shows the effect of `clear()` to different\n    JSON types.,clear}\n\n    @complexity Linear in the size of the JSON value.\n\n    @iterators All iterators, pointers and references related to this container\n               are invalidated.\n\n    @exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n    @sa @ref basic_json(value_t) -- constructor that creates an object with the\n        same value than calling `clear()`\n\n    @since version 1.0.0\n    */\n    void clear() noexcept\n    {\n        switch (m_type)\n        {\n            case value_t::number_integer:\n            {\n                m_value.number_integer = 0;\n                break;\n            }\n\n            case value_t::number_unsigned:\n            {\n                m_value.number_unsigned = 0;\n                break;\n            }\n\n            case value_t::number_float:\n            {\n                m_value.number_float = 0.0;\n                break;\n            }\n\n            case value_t::boolean:\n            {\n                m_value.boolean = false;\n                break;\n            }\n\n            case value_t::string:\n            {\n                m_value.string->clear();\n                break;\n            }\n\n            case value_t::array:\n            {\n                m_value.array->clear();\n                break;\n            }\n\n            case value_t::object:\n            {\n                m_value.object->clear();\n                break;\n            }\n\n            default:\n                break;\n        }\n    }\n\n    /*!\n    @brief add an object to an array\n\n    Appends the given element @a val to the end of the JSON value. If the\n    function is called on a JSON null value, an empty array is created before\n    appending @a val.\n\n    @param[in] val the value to add to the JSON array\n\n    @throw type_error.308 when called on a type other than JSON array or\n    null; example: `\"cannot use push_back() with number\"`\n\n    @complexity Amortized constant.\n\n    @liveexample{The example shows how `push_back()` and `+=` can be used to\n    add elements to a JSON array. Note how the `null` value was silently\n    converted to a JSON array.,push_back}\n\n    @since version 1.0.0\n    */\n    void push_back(basic_json&& val)\n    {\n        // push_back only works for null objects or arrays\n        if (JSON_UNLIKELY(not(is_null() or is_array())))\n        {\n            JSON_THROW(type_error::create(308, \"cannot use push_back() with \" + std::string(type_name())));\n        }\n\n        // transform null object into an array\n        if (is_null())\n        {\n            m_type = value_t::array;\n            m_value = value_t::array;\n            assert_invariant();\n        }\n\n        // add element to array (move semantics)\n        m_value.array->push_back(std::move(val));\n        // invalidate object\n        val.m_type = value_t::null;\n    }\n\n    /*!\n    @brief add an object to an array\n    @copydoc push_back(basic_json&&)\n    */\n    reference operator+=(basic_json&& val)\n    {\n        push_back(std::move(val));\n        return *this;\n    }\n\n    /*!\n    @brief add an object to an array\n    @copydoc push_back(basic_json&&)\n    */\n    void push_back(const basic_json& val)\n    {\n        // push_back only works for null objects or arrays\n        if (JSON_UNLIKELY(not(is_null() or is_array())))\n        {\n            JSON_THROW(type_error::create(308, \"cannot use push_back() with \" + std::string(type_name())));\n        }\n\n        // transform null object into an array\n        if (is_null())\n        {\n            m_type = value_t::array;\n            m_value = value_t::array;\n            assert_invariant();\n        }\n\n        // add element to array\n        m_value.array->push_back(val);\n    }\n\n    /*!\n    @brief add an object to an array\n    @copydoc push_back(basic_json&&)\n    */\n    reference operator+=(const basic_json& val)\n    {\n        push_back(val);\n        return *this;\n    }\n\n    /*!\n    @brief add an object to an object\n\n    Inserts the given element @a val to the JSON object. If the function is\n    called on a JSON null value, an empty object is created before inserting\n    @a val.\n\n    @param[in] val the value to add to the JSON object\n\n    @throw type_error.308 when called on a type other than JSON object or\n    null; example: `\"cannot use push_back() with number\"`\n\n    @complexity Logarithmic in the size of the container, O(log(`size()`)).\n\n    @liveexample{The example shows how `push_back()` and `+=` can be used to\n    add elements to a JSON object. Note how the `null` value was silently\n    converted to a JSON object.,push_back__object_t__value}\n\n    @since version 1.0.0\n    */\n    void push_back(const typename object_t::value_type& val)\n    {\n        // push_back only works for null objects or objects\n        if (JSON_UNLIKELY(not(is_null() or is_object())))\n        {\n            JSON_THROW(type_error::create(308, \"cannot use push_back() with \" + std::string(type_name())));\n        }\n\n        // transform null object into an object\n        if (is_null())\n        {\n            m_type = value_t::object;\n            m_value = value_t::object;\n            assert_invariant();\n        }\n\n        // add element to array\n        m_value.object->insert(val);\n    }\n\n    /*!\n    @brief add an object to an object\n    @copydoc push_back(const typename object_t::value_type&)\n    */\n    reference operator+=(const typename object_t::value_type& val)\n    {\n        push_back(val);\n        return *this;\n    }\n\n    /*!\n    @brief add an object to an object\n\n    This function allows to use `push_back` with an initializer list. In case\n\n    1. the current value is an object,\n    2. the initializer list @a init contains only two elements, and\n    3. the first element of @a init is a string,\n\n    @a init is converted into an object element and added using\n    @ref push_back(const typename object_t::value_type&). Otherwise, @a init\n    is converted to a JSON value and added using @ref push_back(basic_json&&).\n\n    @param[in] init  an initializer list\n\n    @complexity Linear in the size of the initializer list @a init.\n\n    @note This function is required to resolve an ambiguous overload error,\n          because pairs like `{\"key\", \"value\"}` can be both interpreted as\n          `object_t::value_type` or `std::initializer_list<basic_json>`, see\n          https://github.com/nlohmann/json/issues/235 for more information.\n\n    @liveexample{The example shows how initializer lists are treated as\n    objects when possible.,push_back__initializer_list}\n    */\n    void push_back(initializer_list_t init)\n    {\n        if (is_object() and init.size() == 2 and (*init.begin())->is_string())\n        {\n            basic_json&& key = init.begin()->moved_or_copied();\n            push_back(typename object_t::value_type(\n                          std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));\n        }\n        else\n        {\n            push_back(basic_json(init));\n        }\n    }\n\n    /*!\n    @brief add an object to an object\n    @copydoc push_back(initializer_list_t)\n    */\n    reference operator+=(initializer_list_t init)\n    {\n        push_back(init);\n        return *this;\n    }\n\n    /*!\n    @brief add an object to an array\n\n    Creates a JSON value from the passed parameters @a args to the end of the\n    JSON value. If the function is called on a JSON null value, an empty array\n    is created before appending the value created from @a args.\n\n    @param[in] args arguments to forward to a constructor of @ref basic_json\n    @tparam Args compatible types to create a @ref basic_json object\n\n    @throw type_error.311 when called on a type other than JSON array or\n    null; example: `\"cannot use emplace_back() with number\"`\n\n    @complexity Amortized constant.\n\n    @liveexample{The example shows how `push_back()` can be used to add\n    elements to a JSON array. Note how the `null` value was silently converted\n    to a JSON array.,emplace_back}\n\n    @since version 2.0.8\n    */\n    template<class... Args>\n    void emplace_back(Args&& ... args)\n    {\n        // emplace_back only works for null objects or arrays\n        if (JSON_UNLIKELY(not(is_null() or is_array())))\n        {\n            JSON_THROW(type_error::create(311, \"cannot use emplace_back() with \" + std::string(type_name())));\n        }\n\n        // transform null object into an array\n        if (is_null())\n        {\n            m_type = value_t::array;\n            m_value = value_t::array;\n            assert_invariant();\n        }\n\n        // add element to array (perfect forwarding)\n        m_value.array->emplace_back(std::forward<Args>(args)...);\n    }\n\n    /*!\n    @brief add an object to an object if key does not exist\n\n    Inserts a new element into a JSON object constructed in-place with the\n    given @a args if there is no element with the key in the container. If the\n    function is called on a JSON null value, an empty object is created before\n    appending the value created from @a args.\n\n    @param[in] args arguments to forward to a constructor of @ref basic_json\n    @tparam Args compatible types to create a @ref basic_json object\n\n    @return a pair consisting of an iterator to the inserted element, or the\n            already-existing element if no insertion happened, and a bool\n            denoting whether the insertion took place.\n\n    @throw type_error.311 when called on a type other than JSON object or\n    null; example: `\"cannot use emplace() with number\"`\n\n    @complexity Logarithmic in the size of the container, O(log(`size()`)).\n\n    @liveexample{The example shows how `emplace()` can be used to add elements\n    to a JSON object. Note how the `null` value was silently converted to a\n    JSON object. Further note how no value is added if there was already one\n    value stored with the same key.,emplace}\n\n    @since version 2.0.8\n    */\n    template<class... Args>\n    std::pair<iterator, bool> emplace(Args&& ... args)\n    {\n        // emplace only works for null objects or arrays\n        if (JSON_UNLIKELY(not(is_null() or is_object())))\n        {\n            JSON_THROW(type_error::create(311, \"cannot use emplace() with \" + std::string(type_name())));\n        }\n\n        // transform null object into an object\n        if (is_null())\n        {\n            m_type = value_t::object;\n            m_value = value_t::object;\n            assert_invariant();\n        }\n\n        // add element to array (perfect forwarding)\n        auto res = m_value.object->emplace(std::forward<Args>(args)...);\n        // create result iterator and set iterator to the result of emplace\n        auto it = begin();\n        it.m_it.object_iterator = res.first;\n\n        // return pair of iterator and boolean\n        return {it, res.second};\n    }\n\n    /// Helper for insertion of an iterator\n    /// @note: This uses std::distance to support GCC 4.8,\n    ///        see https://github.com/nlohmann/json/pull/1257\n    template<typename... Args>\n    iterator insert_iterator(const_iterator pos, Args&& ... args)\n    {\n        iterator result(this);\n        assert(m_value.array != nullptr);\n\n        auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);\n        m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);\n        result.m_it.array_iterator = m_value.array->begin() + insert_pos;\n\n        // This could have been written as:\n        // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);\n        // but the return value of insert is missing in GCC 4.8, so it is written this way instead.\n\n        return result;\n    }\n\n    /*!\n    @brief inserts element\n\n    Inserts element @a val before iterator @a pos.\n\n    @param[in] pos iterator before which the content will be inserted; may be\n    the end() iterator\n    @param[in] val element to insert\n    @return iterator pointing to the inserted @a val.\n\n    @throw type_error.309 if called on JSON values other than arrays;\n    example: `\"cannot use insert() with string\"`\n    @throw invalid_iterator.202 if @a pos is not an iterator of *this;\n    example: `\"iterator does not fit current value\"`\n\n    @complexity Constant plus linear in the distance between @a pos and end of\n    the container.\n\n    @liveexample{The example shows how `insert()` is used.,insert}\n\n    @since version 1.0.0\n    */\n    iterator insert(const_iterator pos, const basic_json& val)\n    {\n        // insert only works for arrays\n        if (JSON_LIKELY(is_array()))\n        {\n            // check if iterator pos fits to this JSON value\n            if (JSON_UNLIKELY(pos.m_object != this))\n            {\n                JSON_THROW(invalid_iterator::create(202, \"iterator does not fit current value\"));\n            }\n\n            // insert to array and return iterator\n            return insert_iterator(pos, val);\n        }\n\n        JSON_THROW(type_error::create(309, \"cannot use insert() with \" + std::string(type_name())));\n    }\n\n    /*!\n    @brief inserts element\n    @copydoc insert(const_iterator, const basic_json&)\n    */\n    iterator insert(const_iterator pos, basic_json&& val)\n    {\n        return insert(pos, val);\n    }\n\n    /*!\n    @brief inserts elements\n\n    Inserts @a cnt copies of @a val before iterator @a pos.\n\n    @param[in] pos iterator before which the content will be inserted; may be\n    the end() iterator\n    @param[in] cnt number of copies of @a val to insert\n    @param[in] val element to insert\n    @return iterator pointing to the first element inserted, or @a pos if\n    `cnt==0`\n\n    @throw type_error.309 if called on JSON values other than arrays; example:\n    `\"cannot use insert() with string\"`\n    @throw invalid_iterator.202 if @a pos is not an iterator of *this;\n    example: `\"iterator does not fit current value\"`\n\n    @complexity Linear in @a cnt plus linear in the distance between @a pos\n    and end of the container.\n\n    @liveexample{The example shows how `insert()` is used.,insert__count}\n\n    @since version 1.0.0\n    */\n    iterator insert(const_iterator pos, size_type cnt, const basic_json& val)\n    {\n        // insert only works for arrays\n        if (JSON_LIKELY(is_array()))\n        {\n            // check if iterator pos fits to this JSON value\n            if (JSON_UNLIKELY(pos.m_object != this))\n            {\n                JSON_THROW(invalid_iterator::create(202, \"iterator does not fit current value\"));\n            }\n\n            // insert to array and return iterator\n            return insert_iterator(pos, cnt, val);\n        }\n\n        JSON_THROW(type_error::create(309, \"cannot use insert() with \" + std::string(type_name())));\n    }\n\n    /*!\n    @brief inserts elements\n\n    Inserts elements from range `[first, last)` before iterator @a pos.\n\n    @param[in] pos iterator before which the content will be inserted; may be\n    the end() iterator\n    @param[in] first begin of the range of elements to insert\n    @param[in] last end of the range of elements to insert\n\n    @throw type_error.309 if called on JSON values other than arrays; example:\n    `\"cannot use insert() with string\"`\n    @throw invalid_iterator.202 if @a pos is not an iterator of *this;\n    example: `\"iterator does not fit current value\"`\n    @throw invalid_iterator.210 if @a first and @a last do not belong to the\n    same JSON value; example: `\"iterators do not fit\"`\n    @throw invalid_iterator.211 if @a first or @a last are iterators into\n    container for which insert is called; example: `\"passed iterators may not\n    belong to container\"`\n\n    @return iterator pointing to the first element inserted, or @a pos if\n    `first==last`\n\n    @complexity Linear in `std::distance(first, last)` plus linear in the\n    distance between @a pos and end of the container.\n\n    @liveexample{The example shows how `insert()` is used.,insert__range}\n\n    @since version 1.0.0\n    */\n    iterator insert(const_iterator pos, const_iterator first, const_iterator last)\n    {\n        // insert only works for arrays\n        if (JSON_UNLIKELY(not is_array()))\n        {\n            JSON_THROW(type_error::create(309, \"cannot use insert() with \" + std::string(type_name())));\n        }\n\n        // check if iterator pos fits to this JSON value\n        if (JSON_UNLIKELY(pos.m_object != this))\n        {\n            JSON_THROW(invalid_iterator::create(202, \"iterator does not fit current value\"));\n        }\n\n        // check if range iterators belong to the same JSON object\n        if (JSON_UNLIKELY(first.m_object != last.m_object))\n        {\n            JSON_THROW(invalid_iterator::create(210, \"iterators do not fit\"));\n        }\n\n        if (JSON_UNLIKELY(first.m_object == this))\n        {\n            JSON_THROW(invalid_iterator::create(211, \"passed iterators may not belong to container\"));\n        }\n\n        // insert to array and return iterator\n        return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);\n    }\n\n    /*!\n    @brief inserts elements\n\n    Inserts elements from initializer list @a ilist before iterator @a pos.\n\n    @param[in] pos iterator before which the content will be inserted; may be\n    the end() iterator\n    @param[in] ilist initializer list to insert the values from\n\n    @throw type_error.309 if called on JSON values other than arrays; example:\n    `\"cannot use insert() with string\"`\n    @throw invalid_iterator.202 if @a pos is not an iterator of *this;\n    example: `\"iterator does not fit current value\"`\n\n    @return iterator pointing to the first element inserted, or @a pos if\n    `ilist` is empty\n\n    @complexity Linear in `ilist.size()` plus linear in the distance between\n    @a pos and end of the container.\n\n    @liveexample{The example shows how `insert()` is used.,insert__ilist}\n\n    @since version 1.0.0\n    */\n    iterator insert(const_iterator pos, initializer_list_t ilist)\n    {\n        // insert only works for arrays\n        if (JSON_UNLIKELY(not is_array()))\n        {\n            JSON_THROW(type_error::create(309, \"cannot use insert() with \" + std::string(type_name())));\n        }\n\n        // check if iterator pos fits to this JSON value\n        if (JSON_UNLIKELY(pos.m_object != this))\n        {\n            JSON_THROW(invalid_iterator::create(202, \"iterator does not fit current value\"));\n        }\n\n        // insert to array and return iterator\n        return insert_iterator(pos, ilist.begin(), ilist.end());\n    }\n\n    /*!\n    @brief inserts elements\n\n    Inserts elements from range `[first, last)`.\n\n    @param[in] first begin of the range of elements to insert\n    @param[in] last end of the range of elements to insert\n\n    @throw type_error.309 if called on JSON values other than objects; example:\n    `\"cannot use insert() with string\"`\n    @throw invalid_iterator.202 if iterator @a first or @a last does does not\n    point to an object; example: `\"iterators first and last must point to\n    objects\"`\n    @throw invalid_iterator.210 if @a first and @a last do not belong to the\n    same JSON value; example: `\"iterators do not fit\"`\n\n    @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number\n    of elements to insert.\n\n    @liveexample{The example shows how `insert()` is used.,insert__range_object}\n\n    @since version 3.0.0\n    */\n    void insert(const_iterator first, const_iterator last)\n    {\n        // insert only works for objects\n        if (JSON_UNLIKELY(not is_object()))\n        {\n            JSON_THROW(type_error::create(309, \"cannot use insert() with \" + std::string(type_name())));\n        }\n\n        // check if range iterators belong to the same JSON object\n        if (JSON_UNLIKELY(first.m_object != last.m_object))\n        {\n            JSON_THROW(invalid_iterator::create(210, \"iterators do not fit\"));\n        }\n\n        // passed iterators must belong to objects\n        if (JSON_UNLIKELY(not first.m_object->is_object()))\n        {\n            JSON_THROW(invalid_iterator::create(202, \"iterators first and last must point to objects\"));\n        }\n\n        m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);\n    }\n\n    /*!\n    @brief updates a JSON object from another object, overwriting existing keys\n\n    Inserts all values from JSON object @a j and overwrites existing keys.\n\n    @param[in] j  JSON object to read values from\n\n    @throw type_error.312 if called on JSON values other than objects; example:\n    `\"cannot use update() with string\"`\n\n    @complexity O(N*log(size() + N)), where N is the number of elements to\n                insert.\n\n    @liveexample{The example shows how `update()` is used.,update}\n\n    @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update\n\n    @since version 3.0.0\n    */\n    void update(const_reference j)\n    {\n        // implicitly convert null value to an empty object\n        if (is_null())\n        {\n            m_type = value_t::object;\n            m_value.object = create<object_t>();\n            assert_invariant();\n        }\n\n        if (JSON_UNLIKELY(not is_object()))\n        {\n            JSON_THROW(type_error::create(312, \"cannot use update() with \" + std::string(type_name())));\n        }\n        if (JSON_UNLIKELY(not j.is_object()))\n        {\n            JSON_THROW(type_error::create(312, \"cannot use update() with \" + std::string(j.type_name())));\n        }\n\n        for (auto it = j.cbegin(); it != j.cend(); ++it)\n        {\n            m_value.object->operator[](it.key()) = it.value();\n        }\n    }\n\n    /*!\n    @brief updates a JSON object from another object, overwriting existing keys\n\n    Inserts all values from from range `[first, last)` and overwrites existing\n    keys.\n\n    @param[in] first begin of the range of elements to insert\n    @param[in] last end of the range of elements to insert\n\n    @throw type_error.312 if called on JSON values other than objects; example:\n    `\"cannot use update() with string\"`\n    @throw invalid_iterator.202 if iterator @a first or @a last does does not\n    point to an object; example: `\"iterators first and last must point to\n    objects\"`\n    @throw invalid_iterator.210 if @a first and @a last do not belong to the\n    same JSON value; example: `\"iterators do not fit\"`\n\n    @complexity O(N*log(size() + N)), where N is the number of elements to\n                insert.\n\n    @liveexample{The example shows how `update()` is used__range.,update}\n\n    @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update\n\n    @since version 3.0.0\n    */\n    void update(const_iterator first, const_iterator last)\n    {\n        // implicitly convert null value to an empty object\n        if (is_null())\n        {\n            m_type = value_t::object;\n            m_value.object = create<object_t>();\n            assert_invariant();\n        }\n\n        if (JSON_UNLIKELY(not is_object()))\n        {\n            JSON_THROW(type_error::create(312, \"cannot use update() with \" + std::string(type_name())));\n        }\n\n        // check if range iterators belong to the same JSON object\n        if (JSON_UNLIKELY(first.m_object != last.m_object))\n        {\n            JSON_THROW(invalid_iterator::create(210, \"iterators do not fit\"));\n        }\n\n        // passed iterators must belong to objects\n        if (JSON_UNLIKELY(not first.m_object->is_object()\n                          or not last.m_object->is_object()))\n        {\n            JSON_THROW(invalid_iterator::create(202, \"iterators first and last must point to objects\"));\n        }\n\n        for (auto it = first; it != last; ++it)\n        {\n            m_value.object->operator[](it.key()) = it.value();\n        }\n    }\n\n    /*!\n    @brief exchanges the values\n\n    Exchanges the contents of the JSON value with those of @a other. Does not\n    invoke any move, copy, or swap operations on individual elements. All\n    iterators and references remain valid. The past-the-end iterator is\n    invalidated.\n\n    @param[in,out] other JSON value to exchange the contents with\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how JSON values can be swapped with\n    `swap()`.,swap__reference}\n\n    @since version 1.0.0\n    */\n    void swap(reference other) noexcept (\n        std::is_nothrow_move_constructible<value_t>::value and\n        std::is_nothrow_move_assignable<value_t>::value and\n        std::is_nothrow_move_constructible<json_value>::value and\n        std::is_nothrow_move_assignable<json_value>::value\n    )\n    {\n        std::swap(m_type, other.m_type);\n        std::swap(m_value, other.m_value);\n        assert_invariant();\n    }\n\n    /*!\n    @brief exchanges the values\n\n    Exchanges the contents of a JSON array with those of @a other. Does not\n    invoke any move, copy, or swap operations on individual elements. All\n    iterators and references remain valid. The past-the-end iterator is\n    invalidated.\n\n    @param[in,out] other array to exchange the contents with\n\n    @throw type_error.310 when JSON value is not an array; example: `\"cannot\n    use swap() with string\"`\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how arrays can be swapped with\n    `swap()`.,swap__array_t}\n\n    @since version 1.0.0\n    */\n    void swap(array_t& other)\n    {\n        // swap only works for arrays\n        if (JSON_LIKELY(is_array()))\n        {\n            std::swap(*(m_value.array), other);\n        }\n        else\n        {\n            JSON_THROW(type_error::create(310, \"cannot use swap() with \" + std::string(type_name())));\n        }\n    }\n\n    /*!\n    @brief exchanges the values\n\n    Exchanges the contents of a JSON object with those of @a other. Does not\n    invoke any move, copy, or swap operations on individual elements. All\n    iterators and references remain valid. The past-the-end iterator is\n    invalidated.\n\n    @param[in,out] other object to exchange the contents with\n\n    @throw type_error.310 when JSON value is not an object; example:\n    `\"cannot use swap() with string\"`\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how objects can be swapped with\n    `swap()`.,swap__object_t}\n\n    @since version 1.0.0\n    */\n    void swap(object_t& other)\n    {\n        // swap only works for objects\n        if (JSON_LIKELY(is_object()))\n        {\n            std::swap(*(m_value.object), other);\n        }\n        else\n        {\n            JSON_THROW(type_error::create(310, \"cannot use swap() with \" + std::string(type_name())));\n        }\n    }\n\n    /*!\n    @brief exchanges the values\n\n    Exchanges the contents of a JSON string with those of @a other. Does not\n    invoke any move, copy, or swap operations on individual elements. All\n    iterators and references remain valid. The past-the-end iterator is\n    invalidated.\n\n    @param[in,out] other string to exchange the contents with\n\n    @throw type_error.310 when JSON value is not a string; example: `\"cannot\n    use swap() with boolean\"`\n\n    @complexity Constant.\n\n    @liveexample{The example below shows how strings can be swapped with\n    `swap()`.,swap__string_t}\n\n    @since version 1.0.0\n    */\n    void swap(string_t& other)\n    {\n        // swap only works for strings\n        if (JSON_LIKELY(is_string()))\n        {\n            std::swap(*(m_value.string), other);\n        }\n        else\n        {\n            JSON_THROW(type_error::create(310, \"cannot use swap() with \" + std::string(type_name())));\n        }\n    }\n\n    /// @}\n\n  public:\n    //////////////////////////////////////////\n    // lexicographical comparison operators //\n    //////////////////////////////////////////\n\n    /// @name lexicographical comparison operators\n    /// @{\n\n    /*!\n    @brief comparison: equal\n\n    Compares two JSON values for equality according to the following rules:\n    - Two JSON values are equal if (1) they are from the same type and (2)\n      their stored values are the same according to their respective\n      `operator==`.\n    - Integer and floating-point numbers are automatically converted before\n      comparison. Note than two NaN values are always treated as unequal.\n    - Two JSON null values are equal.\n\n    @note Floating-point inside JSON values numbers are compared with\n    `json::number_float_t::operator==` which is `double::operator==` by\n    default. To compare floating-point while respecting an epsilon, an alternative\n    [comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39)\n    could be used, for instance\n    @code {.cpp}\n    template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>\n    inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept\n    {\n        return std::abs(a - b) <= epsilon;\n    }\n    @endcode\n\n    @note NaN values never compare equal to themselves or to other NaN values.\n\n    @param[in] lhs  first JSON value to consider\n    @param[in] rhs  second JSON value to consider\n    @return whether the values @a lhs and @a rhs are equal\n\n    @exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n    @complexity Linear.\n\n    @liveexample{The example demonstrates comparing several JSON\n    types.,operator__equal}\n\n    @since version 1.0.0\n    */\n    friend bool operator==(const_reference lhs, const_reference rhs) noexcept\n    {\n        const auto lhs_type = lhs.type();\n        const auto rhs_type = rhs.type();\n\n        if (lhs_type == rhs_type)\n        {\n            switch (lhs_type)\n            {\n                case value_t::array:\n                    return (*lhs.m_value.array == *rhs.m_value.array);\n\n                case value_t::object:\n                    return (*lhs.m_value.object == *rhs.m_value.object);\n\n                case value_t::null:\n                    return true;\n\n                case value_t::string:\n                    return (*lhs.m_value.string == *rhs.m_value.string);\n\n                case value_t::boolean:\n                    return (lhs.m_value.boolean == rhs.m_value.boolean);\n\n                case value_t::number_integer:\n                    return (lhs.m_value.number_integer == rhs.m_value.number_integer);\n\n                case value_t::number_unsigned:\n                    return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);\n\n                case value_t::number_float:\n                    return (lhs.m_value.number_float == rhs.m_value.number_float);\n\n                default:\n                    return false;\n            }\n        }\n        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)\n        {\n            return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);\n        }\n        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)\n        {\n            return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));\n        }\n        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)\n        {\n            return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);\n        }\n        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)\n        {\n            return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));\n        }\n        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)\n        {\n            return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);\n        }\n        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)\n        {\n            return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));\n        }\n\n        return false;\n    }\n\n    /*!\n    @brief comparison: equal\n    @copydoc operator==(const_reference, const_reference)\n    */\n    template<typename ScalarType, typename std::enable_if<\n                 std::is_scalar<ScalarType>::value, int>::type = 0>\n    friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept\n    {\n        return (lhs == basic_json(rhs));\n    }\n\n    /*!\n    @brief comparison: equal\n    @copydoc operator==(const_reference, const_reference)\n    */\n    template<typename ScalarType, typename std::enable_if<\n                 std::is_scalar<ScalarType>::value, int>::type = 0>\n    friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept\n    {\n        return (basic_json(lhs) == rhs);\n    }\n\n    /*!\n    @brief comparison: not equal\n\n    Compares two JSON values for inequality by calculating `not (lhs == rhs)`.\n\n    @param[in] lhs  first JSON value to consider\n    @param[in] rhs  second JSON value to consider\n    @return whether the values @a lhs and @a rhs are not equal\n\n    @complexity Linear.\n\n    @exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n    @liveexample{The example demonstrates comparing several JSON\n    types.,operator__notequal}\n\n    @since version 1.0.0\n    */\n    friend bool operator!=(const_reference lhs, const_reference rhs) noexcept\n    {\n        return not (lhs == rhs);\n    }\n\n    /*!\n    @brief comparison: not equal\n    @copydoc operator!=(const_reference, const_reference)\n    */\n    template<typename ScalarType, typename std::enable_if<\n                 std::is_scalar<ScalarType>::value, int>::type = 0>\n    friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept\n    {\n        return (lhs != basic_json(rhs));\n    }\n\n    /*!\n    @brief comparison: not equal\n    @copydoc operator!=(const_reference, const_reference)\n    */\n    template<typename ScalarType, typename std::enable_if<\n                 std::is_scalar<ScalarType>::value, int>::type = 0>\n    friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept\n    {\n        return (basic_json(lhs) != rhs);\n    }\n\n    /*!\n    @brief comparison: less than\n\n    Compares whether one JSON value @a lhs is less than another JSON value @a\n    rhs according to the following rules:\n    - If @a lhs and @a rhs have the same type, the values are compared using\n      the default `<` operator.\n    - Integer and floating-point numbers are automatically converted before\n      comparison\n    - In case @a lhs and @a rhs have different types, the values are ignored\n      and the order of the types is considered, see\n      @ref operator<(const value_t, const value_t).\n\n    @param[in] lhs  first JSON value to consider\n    @param[in] rhs  second JSON value to consider\n    @return whether @a lhs is less than @a rhs\n\n    @complexity Linear.\n\n    @exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n    @liveexample{The example demonstrates comparing several JSON\n    types.,operator__less}\n\n    @since version 1.0.0\n    */\n    friend bool operator<(const_reference lhs, const_reference rhs) noexcept\n    {\n        const auto lhs_type = lhs.type();\n        const auto rhs_type = rhs.type();\n\n        if (lhs_type == rhs_type)\n        {\n            switch (lhs_type)\n            {\n                case value_t::array:\n                    return (*lhs.m_value.array) < (*rhs.m_value.array);\n\n                case value_t::object:\n                    return *lhs.m_value.object < *rhs.m_value.object;\n\n                case value_t::null:\n                    return false;\n\n                case value_t::string:\n                    return *lhs.m_value.string < *rhs.m_value.string;\n\n                case value_t::boolean:\n                    return lhs.m_value.boolean < rhs.m_value.boolean;\n\n                case value_t::number_integer:\n                    return lhs.m_value.number_integer < rhs.m_value.number_integer;\n\n                case value_t::number_unsigned:\n                    return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;\n\n                case value_t::number_float:\n                    return lhs.m_value.number_float < rhs.m_value.number_float;\n\n                default:\n                    return false;\n            }\n        }\n        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)\n        {\n            return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;\n        }\n        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)\n        {\n            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);\n        }\n        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)\n        {\n            return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;\n        }\n        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)\n        {\n            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);\n        }\n        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)\n        {\n            return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);\n        }\n        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)\n        {\n            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;\n        }\n\n        // We only reach this line if we cannot compare values. In that case,\n        // we compare types. Note we have to call the operator explicitly,\n        // because MSVC has problems otherwise.\n        return operator<(lhs_type, rhs_type);\n    }\n\n    /*!\n    @brief comparison: less than\n    @copydoc operator<(const_reference, const_reference)\n    */\n    template<typename ScalarType, typename std::enable_if<\n                 std::is_scalar<ScalarType>::value, int>::type = 0>\n    friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept\n    {\n        return (lhs < basic_json(rhs));\n    }\n\n    /*!\n    @brief comparison: less than\n    @copydoc operator<(const_reference, const_reference)\n    */\n    template<typename ScalarType, typename std::enable_if<\n                 std::is_scalar<ScalarType>::value, int>::type = 0>\n    friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept\n    {\n        return (basic_json(lhs) < rhs);\n    }\n\n    /*!\n    @brief comparison: less than or equal\n\n    Compares whether one JSON value @a lhs is less than or equal to another\n    JSON value by calculating `not (rhs < lhs)`.\n\n    @param[in] lhs  first JSON value to consider\n    @param[in] rhs  second JSON value to consider\n    @return whether @a lhs is less than or equal to @a rhs\n\n    @complexity Linear.\n\n    @exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n    @liveexample{The example demonstrates comparing several JSON\n    types.,operator__greater}\n\n    @since version 1.0.0\n    */\n    friend bool operator<=(const_reference lhs, const_reference rhs) noexcept\n    {\n        return not (rhs < lhs);\n    }\n\n    /*!\n    @brief comparison: less than or equal\n    @copydoc operator<=(const_reference, const_reference)\n    */\n    template<typename ScalarType, typename std::enable_if<\n                 std::is_scalar<ScalarType>::value, int>::type = 0>\n    friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept\n    {\n        return (lhs <= basic_json(rhs));\n    }\n\n    /*!\n    @brief comparison: less than or equal\n    @copydoc operator<=(const_reference, const_reference)\n    */\n    template<typename ScalarType, typename std::enable_if<\n                 std::is_scalar<ScalarType>::value, int>::type = 0>\n    friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept\n    {\n        return (basic_json(lhs) <= rhs);\n    }\n\n    /*!\n    @brief comparison: greater than\n\n    Compares whether one JSON value @a lhs is greater than another\n    JSON value by calculating `not (lhs <= rhs)`.\n\n    @param[in] lhs  first JSON value to consider\n    @param[in] rhs  second JSON value to consider\n    @return whether @a lhs is greater than to @a rhs\n\n    @complexity Linear.\n\n    @exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n    @liveexample{The example demonstrates comparing several JSON\n    types.,operator__lessequal}\n\n    @since version 1.0.0\n    */\n    friend bool operator>(const_reference lhs, const_reference rhs) noexcept\n    {\n        return not (lhs <= rhs);\n    }\n\n    /*!\n    @brief comparison: greater than\n    @copydoc operator>(const_reference, const_reference)\n    */\n    template<typename ScalarType, typename std::enable_if<\n                 std::is_scalar<ScalarType>::value, int>::type = 0>\n    friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept\n    {\n        return (lhs > basic_json(rhs));\n    }\n\n    /*!\n    @brief comparison: greater than\n    @copydoc operator>(const_reference, const_reference)\n    */\n    template<typename ScalarType, typename std::enable_if<\n                 std::is_scalar<ScalarType>::value, int>::type = 0>\n    friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept\n    {\n        return (basic_json(lhs) > rhs);\n    }\n\n    /*!\n    @brief comparison: greater than or equal\n\n    Compares whether one JSON value @a lhs is greater than or equal to another\n    JSON value by calculating `not (lhs < rhs)`.\n\n    @param[in] lhs  first JSON value to consider\n    @param[in] rhs  second JSON value to consider\n    @return whether @a lhs is greater than or equal to @a rhs\n\n    @complexity Linear.\n\n    @exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n    @liveexample{The example demonstrates comparing several JSON\n    types.,operator__greaterequal}\n\n    @since version 1.0.0\n    */\n    friend bool operator>=(const_reference lhs, const_reference rhs) noexcept\n    {\n        return not (lhs < rhs);\n    }\n\n    /*!\n    @brief comparison: greater than or equal\n    @copydoc operator>=(const_reference, const_reference)\n    */\n    template<typename ScalarType, typename std::enable_if<\n                 std::is_scalar<ScalarType>::value, int>::type = 0>\n    friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept\n    {\n        return (lhs >= basic_json(rhs));\n    }\n\n    /*!\n    @brief comparison: greater than or equal\n    @copydoc operator>=(const_reference, const_reference)\n    */\n    template<typename ScalarType, typename std::enable_if<\n                 std::is_scalar<ScalarType>::value, int>::type = 0>\n    friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept\n    {\n        return (basic_json(lhs) >= rhs);\n    }\n\n    /// @}\n\n    ///////////////////\n    // serialization //\n    ///////////////////\n\n    /// @name serialization\n    /// @{\n\n    /*!\n    @brief serialize to stream\n\n    Serialize the given JSON value @a j to the output stream @a o. The JSON\n    value will be serialized using the @ref dump member function.\n\n    - The indentation of the output can be controlled with the member variable\n      `width` of the output stream @a o. For instance, using the manipulator\n      `std::setw(4)` on @a o sets the indentation level to `4` and the\n      serialization result is the same as calling `dump(4)`.\n\n    - The indentation character can be controlled with the member variable\n      `fill` of the output stream @a o. For instance, the manipulator\n      `std::setfill('\\\\t')` sets indentation to use a tab character rather than\n      the default space character.\n\n    @param[in,out] o  stream to serialize to\n    @param[in] j  JSON value to serialize\n\n    @return the stream @a o\n\n    @throw type_error.316 if a string stored inside the JSON value is not\n                          UTF-8 encoded\n\n    @complexity Linear.\n\n    @liveexample{The example below shows the serialization with different\n    parameters to `width` to adjust the indentation level.,operator_serialize}\n\n    @since version 1.0.0; indentation character added in version 3.0.0\n    */\n    friend std::ostream& operator<<(std::ostream& o, const basic_json& j)\n    {\n        // read width member and use it as indentation parameter if nonzero\n        const bool pretty_print = (o.width() > 0);\n        const auto indentation = (pretty_print ? o.width() : 0);\n\n        // reset width to 0 for subsequent calls to this stream\n        o.width(0);\n\n        // do the actual serialization\n        serializer s(detail::output_adapter<char>(o), o.fill());\n        s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));\n        return o;\n    }\n\n    /*!\n    @brief serialize to stream\n    @deprecated This stream operator is deprecated and will be removed in\n                future 4.0.0 of the library. Please use\n                @ref operator<<(std::ostream&, const basic_json&)\n                instead; that is, replace calls like `j >> o;` with `o << j;`.\n    @since version 1.0.0; deprecated since version 3.0.0\n    */\n    JSON_DEPRECATED\n    friend std::ostream& operator>>(const basic_json& j, std::ostream& o)\n    {\n        return o << j;\n    }\n\n    /// @}\n\n\n    /////////////////////\n    // deserialization //\n    /////////////////////\n\n    /// @name deserialization\n    /// @{\n\n    /*!\n    @brief deserialize from a compatible input\n\n    This function reads from a compatible input. Examples are:\n    - an array of 1-byte values\n    - strings with character/literal type with size of 1 byte\n    - input streams\n    - container with contiguous storage of 1-byte values. Compatible container\n      types include `std::vector`, `std::string`, `std::array`,\n      `std::valarray`, and `std::initializer_list`. Furthermore, C-style\n      arrays can be used with `std::begin()`/`std::end()`. User-defined\n      containers can be used as long as they implement random-access iterators\n      and a contiguous storage.\n\n    @pre Each element of the container has a size of 1 byte. Violating this\n    precondition yields undefined behavior. **This precondition is enforced\n    with a static assertion.**\n\n    @pre The container storage is contiguous. Violating this precondition\n    yields undefined behavior. **This precondition is enforced with an\n    assertion.**\n\n    @warning There is no way to enforce all preconditions at compile-time. If\n             the function is called with a noncompliant container and with\n             assertions switched off, the behavior is undefined and will most\n             likely yield segmentation violation.\n\n    @param[in] i  input to read from\n    @param[in] cb  a parser callback function of type @ref parser_callback_t\n    which is used to control the deserialization by filtering unwanted values\n    (optional)\n    @param[in] allow_exceptions  whether to throw exceptions in case of a\n    parse error (optional, true by default)\n\n    @return deserialized JSON value; in case of a parse error and\n            @a allow_exceptions set to `false`, the return value will be\n            value_t::discarded.\n\n    @throw parse_error.101 if a parse error occurs; example: `\"\"unexpected end\n    of input; expected string literal\"\"`\n    @throw parse_error.102 if to_unicode fails or surrogate error\n    @throw parse_error.103 if to_unicode fails\n\n    @complexity Linear in the length of the input. The parser is a predictive\n    LL(1) parser. The complexity can be higher if the parser callback function\n    @a cb has a super-linear complexity.\n\n    @note A UTF-8 byte order mark is silently ignored.\n\n    @liveexample{The example below demonstrates the `parse()` function reading\n    from an array.,parse__array__parser_callback_t}\n\n    @liveexample{The example below demonstrates the `parse()` function with\n    and without callback function.,parse__string__parser_callback_t}\n\n    @liveexample{The example below demonstrates the `parse()` function with\n    and without callback function.,parse__istream__parser_callback_t}\n\n    @liveexample{The example below demonstrates the `parse()` function reading\n    from a contiguous container.,parse__contiguouscontainer__parser_callback_t}\n\n    @since version 2.0.3 (contiguous containers)\n    */\n    JSON_NODISCARD\n    static basic_json parse(detail::input_adapter&& i,\n                            const parser_callback_t cb = nullptr,\n                            const bool allow_exceptions = true)\n    {\n        basic_json result;\n        parser(i, cb, allow_exceptions).parse(true, result);\n        return result;\n    }\n\n    static bool accept(detail::input_adapter&& i)\n    {\n        return parser(i).accept(true);\n    }\n\n    /*!\n    @brief generate SAX events\n\n    The SAX event lister must follow the interface of @ref json_sax.\n\n    This function reads from a compatible input. Examples are:\n    - an array of 1-byte values\n    - strings with character/literal type with size of 1 byte\n    - input streams\n    - container with contiguous storage of 1-byte values. Compatible container\n      types include `std::vector`, `std::string`, `std::array`,\n      `std::valarray`, and `std::initializer_list`. Furthermore, C-style\n      arrays can be used with `std::begin()`/`std::end()`. User-defined\n      containers can be used as long as they implement random-access iterators\n      and a contiguous storage.\n\n    @pre Each element of the container has a size of 1 byte. Violating this\n    precondition yields undefined behavior. **This precondition is enforced\n    with a static assertion.**\n\n    @pre The container storage is contiguous. Violating this precondition\n    yields undefined behavior. **This precondition is enforced with an\n    assertion.**\n\n    @warning There is no way to enforce all preconditions at compile-time. If\n             the function is called with a noncompliant container and with\n             assertions switched off, the behavior is undefined and will most\n             likely yield segmentation violation.\n\n    @param[in] i  input to read from\n    @param[in,out] sax  SAX event listener\n    @param[in] format  the format to parse (JSON, CBOR, MessagePack, or UBJSON)\n    @param[in] strict  whether the input has to be consumed completely\n\n    @return return value of the last processed SAX event\n\n    @throw parse_error.101 if a parse error occurs; example: `\"\"unexpected end\n    of input; expected string literal\"\"`\n    @throw parse_error.102 if to_unicode fails or surrogate error\n    @throw parse_error.103 if to_unicode fails\n\n    @complexity Linear in the length of the input. The parser is a predictive\n    LL(1) parser. The complexity can be higher if the SAX consumer @a sax has\n    a super-linear complexity.\n\n    @note A UTF-8 byte order mark is silently ignored.\n\n    @liveexample{The example below demonstrates the `sax_parse()` function\n    reading from string and processing the events with a user-defined SAX\n    event consumer.,sax_parse}\n\n    @since version 3.2.0\n    */\n    template <typename SAX>\n    static bool sax_parse(detail::input_adapter&& i, SAX* sax,\n                          input_format_t format = input_format_t::json,\n                          const bool strict = true)\n    {\n        assert(sax);\n        switch (format)\n        {\n            case input_format_t::json:\n                return parser(std::move(i)).sax_parse(sax, strict);\n            default:\n                return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);\n        }\n    }\n\n    /*!\n    @brief deserialize from an iterator range with contiguous storage\n\n    This function reads from an iterator range of a container with contiguous\n    storage of 1-byte values. Compatible container types include\n    `std::vector`, `std::string`, `std::array`, `std::valarray`, and\n    `std::initializer_list`. Furthermore, C-style arrays can be used with\n    `std::begin()`/`std::end()`. User-defined containers can be used as long\n    as they implement random-access iterators and a contiguous storage.\n\n    @pre The iterator range is contiguous. Violating this precondition yields\n    undefined behavior. **This precondition is enforced with an assertion.**\n    @pre Each element in the range has a size of 1 byte. Violating this\n    precondition yields undefined behavior. **This precondition is enforced\n    with a static assertion.**\n\n    @warning There is no way to enforce all preconditions at compile-time. If\n             the function is called with noncompliant iterators and with\n             assertions switched off, the behavior is undefined and will most\n             likely yield segmentation violation.\n\n    @tparam IteratorType iterator of container with contiguous storage\n    @param[in] first  begin of the range to parse (included)\n    @param[in] last  end of the range to parse (excluded)\n    @param[in] cb  a parser callback function of type @ref parser_callback_t\n    which is used to control the deserialization by filtering unwanted values\n    (optional)\n    @param[in] allow_exceptions  whether to throw exceptions in case of a\n    parse error (optional, true by default)\n\n    @return deserialized JSON value; in case of a parse error and\n            @a allow_exceptions set to `false`, the return value will be\n            value_t::discarded.\n\n    @throw parse_error.101 in case of an unexpected token\n    @throw parse_error.102 if to_unicode fails or surrogate error\n    @throw parse_error.103 if to_unicode fails\n\n    @complexity Linear in the length of the input. The parser is a predictive\n    LL(1) parser. The complexity can be higher if the parser callback function\n    @a cb has a super-linear complexity.\n\n    @note A UTF-8 byte order mark is silently ignored.\n\n    @liveexample{The example below demonstrates the `parse()` function reading\n    from an iterator range.,parse__iteratortype__parser_callback_t}\n\n    @since version 2.0.3\n    */\n    template<class IteratorType, typename std::enable_if<\n                 std::is_base_of<\n                     std::random_access_iterator_tag,\n                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>\n    static basic_json parse(IteratorType first, IteratorType last,\n                            const parser_callback_t cb = nullptr,\n                            const bool allow_exceptions = true)\n    {\n        basic_json result;\n        parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);\n        return result;\n    }\n\n    template<class IteratorType, typename std::enable_if<\n                 std::is_base_of<\n                     std::random_access_iterator_tag,\n                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>\n    static bool accept(IteratorType first, IteratorType last)\n    {\n        return parser(detail::input_adapter(first, last)).accept(true);\n    }\n\n    template<class IteratorType, class SAX, typename std::enable_if<\n                 std::is_base_of<\n                     std::random_access_iterator_tag,\n                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>\n    static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)\n    {\n        return parser(detail::input_adapter(first, last)).sax_parse(sax);\n    }\n\n    /*!\n    @brief deserialize from stream\n    @deprecated This stream operator is deprecated and will be removed in\n                version 4.0.0 of the library. Please use\n                @ref operator>>(std::istream&, basic_json&)\n                instead; that is, replace calls like `j << i;` with `i >> j;`.\n    @since version 1.0.0; deprecated since version 3.0.0\n    */\n    JSON_DEPRECATED\n    friend std::istream& operator<<(basic_json& j, std::istream& i)\n    {\n        return operator>>(i, j);\n    }\n\n    /*!\n    @brief deserialize from stream\n\n    Deserializes an input stream to a JSON value.\n\n    @param[in,out] i  input stream to read a serialized JSON value from\n    @param[in,out] j  JSON value to write the deserialized input to\n\n    @throw parse_error.101 in case of an unexpected token\n    @throw parse_error.102 if to_unicode fails or surrogate error\n    @throw parse_error.103 if to_unicode fails\n\n    @complexity Linear in the length of the input. The parser is a predictive\n    LL(1) parser.\n\n    @note A UTF-8 byte order mark is silently ignored.\n\n    @liveexample{The example below shows how a JSON value is constructed by\n    reading a serialization from a stream.,operator_deserialize}\n\n    @sa parse(std::istream&, const parser_callback_t) for a variant with a\n    parser callback function to filter values while parsing\n\n    @since version 1.0.0\n    */\n    friend std::istream& operator>>(std::istream& i, basic_json& j)\n    {\n        parser(detail::input_adapter(i)).parse(false, j);\n        return i;\n    }\n\n    /// @}\n\n    ///////////////////////////\n    // convenience functions //\n    ///////////////////////////\n\n    /*!\n    @brief return the type as string\n\n    Returns the type name as string to be used in error messages - usually to\n    indicate that a function was called on a wrong JSON type.\n\n    @return a string representation of a the @a m_type member:\n            Value type  | return value\n            ----------- | -------------\n            null        | `\"null\"`\n            boolean     | `\"boolean\"`\n            string      | `\"string\"`\n            number      | `\"number\"` (for all number types)\n            object      | `\"object\"`\n            array       | `\"array\"`\n            discarded   | `\"discarded\"`\n\n    @exceptionsafety No-throw guarantee: this function never throws exceptions.\n\n    @complexity Constant.\n\n    @liveexample{The following code exemplifies `type_name()` for all JSON\n    types.,type_name}\n\n    @sa @ref type() -- return the type of the JSON value\n    @sa @ref operator value_t() -- return the type of the JSON value (implicit)\n\n    @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`\n    since 3.0.0\n    */\n    const char* type_name() const noexcept\n    {\n        {\n            switch (m_type)\n            {\n                case value_t::null:\n                    return \"null\";\n                case value_t::object:\n                    return \"object\";\n                case value_t::array:\n                    return \"array\";\n                case value_t::string:\n                    return \"string\";\n                case value_t::boolean:\n                    return \"boolean\";\n                case value_t::discarded:\n                    return \"discarded\";\n                default:\n                    return \"number\";\n            }\n        }\n    }\n\n\n  private:\n    //////////////////////\n    // member variables //\n    //////////////////////\n\n    /// the type of the current element\n    value_t m_type = value_t::null;\n\n    /// the value of the current element\n    json_value m_value = {};\n\n    //////////////////////////////////////////\n    // binary serialization/deserialization //\n    //////////////////////////////////////////\n\n    /// @name binary serialization/deserialization support\n    /// @{\n\n  public:\n    /*!\n    @brief create a CBOR serialization of a given JSON value\n\n    Serializes a given JSON value @a j to a byte vector using the CBOR (Concise\n    Binary Object Representation) serialization format. CBOR is a binary\n    serialization format which aims to be more compact than JSON itself, yet\n    more efficient to parse.\n\n    The library uses the following mapping from JSON values types to\n    CBOR types according to the CBOR specification (RFC 7049):\n\n    JSON value type | value/range                                | CBOR type                          | first byte\n    --------------- | ------------------------------------------ | ---------------------------------- | ---------------\n    null            | `null`                                     | Null                               | 0xF6\n    boolean         | `true`                                     | True                               | 0xF5\n    boolean         | `false`                                    | False                              | 0xF4\n    number_integer  | -9223372036854775808..-2147483649          | Negative integer (8 bytes follow)  | 0x3B\n    number_integer  | -2147483648..-32769                        | Negative integer (4 bytes follow)  | 0x3A\n    number_integer  | -32768..-129                               | Negative integer (2 bytes follow)  | 0x39\n    number_integer  | -128..-25                                  | Negative integer (1 byte follow)   | 0x38\n    number_integer  | -24..-1                                    | Negative integer                   | 0x20..0x37\n    number_integer  | 0..23                                      | Integer                            | 0x00..0x17\n    number_integer  | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18\n    number_integer  | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19\n    number_integer  | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1A\n    number_integer  | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1B\n    number_unsigned | 0..23                                      | Integer                            | 0x00..0x17\n    number_unsigned | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18\n    number_unsigned | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19\n    number_unsigned | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1A\n    number_unsigned | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1B\n    number_float    | *any value*                                | Double-Precision Float             | 0xFB\n    string          | *length*: 0..23                            | UTF-8 string                       | 0x60..0x77\n    string          | *length*: 23..255                          | UTF-8 string (1 byte follow)       | 0x78\n    string          | *length*: 256..65535                       | UTF-8 string (2 bytes follow)      | 0x79\n    string          | *length*: 65536..4294967295                | UTF-8 string (4 bytes follow)      | 0x7A\n    string          | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow)      | 0x7B\n    array           | *size*: 0..23                              | array                              | 0x80..0x97\n    array           | *size*: 23..255                            | array (1 byte follow)              | 0x98\n    array           | *size*: 256..65535                         | array (2 bytes follow)             | 0x99\n    array           | *size*: 65536..4294967295                  | array (4 bytes follow)             | 0x9A\n    array           | *size*: 4294967296..18446744073709551615   | array (8 bytes follow)             | 0x9B\n    object          | *size*: 0..23                              | map                                | 0xA0..0xB7\n    object          | *size*: 23..255                            | map (1 byte follow)                | 0xB8\n    object          | *size*: 256..65535                         | map (2 bytes follow)               | 0xB9\n    object          | *size*: 65536..4294967295                  | map (4 bytes follow)               | 0xBA\n    object          | *size*: 4294967296..18446744073709551615   | map (8 bytes follow)               | 0xBB\n\n    @note The mapping is **complete** in the sense that any JSON value type\n          can be converted to a CBOR value.\n\n    @note If NaN or Infinity are stored inside a JSON number, they are\n          serialized properly. This behavior differs from the @ref dump()\n          function which serializes NaN or Infinity to `null`.\n\n    @note The following CBOR types are not used in the conversion:\n          - byte strings (0x40..0x5F)\n          - UTF-8 strings terminated by \"break\" (0x7F)\n          - arrays terminated by \"break\" (0x9F)\n          - maps terminated by \"break\" (0xBF)\n          - date/time (0xC0..0xC1)\n          - bignum (0xC2..0xC3)\n          - decimal fraction (0xC4)\n          - bigfloat (0xC5)\n          - tagged items (0xC6..0xD4, 0xD8..0xDB)\n          - expected conversions (0xD5..0xD7)\n          - simple values (0xE0..0xF3, 0xF8)\n          - undefined (0xF7)\n          - half and single-precision floats (0xF9-0xFA)\n          - break (0xFF)\n\n    @param[in] j  JSON value to serialize\n    @return MessagePack serialization as byte vector\n\n    @complexity Linear in the size of the JSON value @a j.\n\n    @liveexample{The example shows the serialization of a JSON value to a byte\n    vector in CBOR format.,to_cbor}\n\n    @sa http://cbor.io\n    @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the\n        analogous deserialization\n    @sa @ref to_msgpack(const basic_json&) for the related MessagePack format\n    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the\n             related UBJSON format\n\n    @since version 2.0.9\n    */\n    static std::vector<uint8_t> to_cbor(const basic_json& j)\n    {\n        std::vector<uint8_t> result;\n        to_cbor(j, result);\n        return result;\n    }\n\n    static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)\n    {\n        binary_writer<uint8_t>(o).write_cbor(j);\n    }\n\n    static void to_cbor(const basic_json& j, detail::output_adapter<char> o)\n    {\n        binary_writer<char>(o).write_cbor(j);\n    }\n\n    /*!\n    @brief create a MessagePack serialization of a given JSON value\n\n    Serializes a given JSON value @a j to a byte vector using the MessagePack\n    serialization format. MessagePack is a binary serialization format which\n    aims to be more compact than JSON itself, yet more efficient to parse.\n\n    The library uses the following mapping from JSON values types to\n    MessagePack types according to the MessagePack specification:\n\n    JSON value type | value/range                       | MessagePack type | first byte\n    --------------- | --------------------------------- | ---------------- | ----------\n    null            | `null`                            | nil              | 0xC0\n    boolean         | `true`                            | true             | 0xC3\n    boolean         | `false`                           | false            | 0xC2\n    number_integer  | -9223372036854775808..-2147483649 | int64            | 0xD3\n    number_integer  | -2147483648..-32769               | int32            | 0xD2\n    number_integer  | -32768..-129                      | int16            | 0xD1\n    number_integer  | -128..-33                         | int8             | 0xD0\n    number_integer  | -32..-1                           | negative fixint  | 0xE0..0xFF\n    number_integer  | 0..127                            | positive fixint  | 0x00..0x7F\n    number_integer  | 128..255                          | uint 8           | 0xCC\n    number_integer  | 256..65535                        | uint 16          | 0xCD\n    number_integer  | 65536..4294967295                 | uint 32          | 0xCE\n    number_integer  | 4294967296..18446744073709551615  | uint 64          | 0xCF\n    number_unsigned | 0..127                            | positive fixint  | 0x00..0x7F\n    number_unsigned | 128..255                          | uint 8           | 0xCC\n    number_unsigned | 256..65535                        | uint 16          | 0xCD\n    number_unsigned | 65536..4294967295                 | uint 32          | 0xCE\n    number_unsigned | 4294967296..18446744073709551615  | uint 64          | 0xCF\n    number_float    | *any value*                       | float 64         | 0xCB\n    string          | *length*: 0..31                   | fixstr           | 0xA0..0xBF\n    string          | *length*: 32..255                 | str 8            | 0xD9\n    string          | *length*: 256..65535              | str 16           | 0xDA\n    string          | *length*: 65536..4294967295       | str 32           | 0xDB\n    array           | *size*: 0..15                     | fixarray         | 0x90..0x9F\n    array           | *size*: 16..65535                 | array 16         | 0xDC\n    array           | *size*: 65536..4294967295         | array 32         | 0xDD\n    object          | *size*: 0..15                     | fix map          | 0x80..0x8F\n    object          | *size*: 16..65535                 | map 16           | 0xDE\n    object          | *size*: 65536..4294967295         | map 32           | 0xDF\n\n    @note The mapping is **complete** in the sense that any JSON value type\n          can be converted to a MessagePack value.\n\n    @note The following values can **not** be converted to a MessagePack value:\n          - strings with more than 4294967295 bytes\n          - arrays with more than 4294967295 elements\n          - objects with more than 4294967295 elements\n\n    @note The following MessagePack types are not used in the conversion:\n          - bin 8 - bin 32 (0xC4..0xC6)\n          - ext 8 - ext 32 (0xC7..0xC9)\n          - float 32 (0xCA)\n          - fixext 1 - fixext 16 (0xD4..0xD8)\n\n    @note Any MessagePack output created @ref to_msgpack can be successfully\n          parsed by @ref from_msgpack.\n\n    @note If NaN or Infinity are stored inside a JSON number, they are\n          serialized properly. This behavior differs from the @ref dump()\n          function which serializes NaN or Infinity to `null`.\n\n    @param[in] j  JSON value to serialize\n    @return MessagePack serialization as byte vector\n\n    @complexity Linear in the size of the JSON value @a j.\n\n    @liveexample{The example shows the serialization of a JSON value to a byte\n    vector in MessagePack format.,to_msgpack}\n\n    @sa http://msgpack.org\n    @sa @ref from_msgpack for the analogous deserialization\n    @sa @ref to_cbor(const basic_json& for the related CBOR format\n    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the\n             related UBJSON format\n\n    @since version 2.0.9\n    */\n    static std::vector<uint8_t> to_msgpack(const basic_json& j)\n    {\n        std::vector<uint8_t> result;\n        to_msgpack(j, result);\n        return result;\n    }\n\n    static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)\n    {\n        binary_writer<uint8_t>(o).write_msgpack(j);\n    }\n\n    static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)\n    {\n        binary_writer<char>(o).write_msgpack(j);\n    }\n\n    /*!\n    @brief create a UBJSON serialization of a given JSON value\n\n    Serializes a given JSON value @a j to a byte vector using the UBJSON\n    (Universal Binary JSON) serialization format. UBJSON aims to be more compact\n    than JSON itself, yet more efficient to parse.\n\n    The library uses the following mapping from JSON values types to\n    UBJSON types according to the UBJSON specification:\n\n    JSON value type | value/range                       | UBJSON type | marker\n    --------------- | --------------------------------- | ----------- | ------\n    null            | `null`                            | null        | `Z`\n    boolean         | `true`                            | true        | `T`\n    boolean         | `false`                           | false       | `F`\n    number_integer  | -9223372036854775808..-2147483649 | int64       | `L`\n    number_integer  | -2147483648..-32769               | int32       | `l`\n    number_integer  | -32768..-129                      | int16       | `I`\n    number_integer  | -128..127                         | int8        | `i`\n    number_integer  | 128..255                          | uint8       | `U`\n    number_integer  | 256..32767                        | int16       | `I`\n    number_integer  | 32768..2147483647                 | int32       | `l`\n    number_integer  | 2147483648..9223372036854775807   | int64       | `L`\n    number_unsigned | 0..127                            | int8        | `i`\n    number_unsigned | 128..255                          | uint8       | `U`\n    number_unsigned | 256..32767                        | int16       | `I`\n    number_unsigned | 32768..2147483647                 | int32       | `l`\n    number_unsigned | 2147483648..9223372036854775807   | int64       | `L`\n    number_float    | *any value*                       | float64     | `D`\n    string          | *with shortest length indicator*  | string      | `S`\n    array           | *see notes on optimized format*   | array       | `[`\n    object          | *see notes on optimized format*   | map         | `{`\n\n    @note The mapping is **complete** in the sense that any JSON value type\n          can be converted to a UBJSON value.\n\n    @note The following values can **not** be converted to a UBJSON value:\n          - strings with more than 9223372036854775807 bytes (theoretical)\n          - unsigned integer numbers above 9223372036854775807\n\n    @note The following markers are not used in the conversion:\n          - `Z`: no-op values are not created.\n          - `C`: single-byte strings are serialized with `S` markers.\n\n    @note Any UBJSON output created @ref to_ubjson can be successfully parsed\n          by @ref from_ubjson.\n\n    @note If NaN or Infinity are stored inside a JSON number, they are\n          serialized properly. This behavior differs from the @ref dump()\n          function which serializes NaN or Infinity to `null`.\n\n    @note The optimized formats for containers are supported: Parameter\n          @a use_size adds size information to the beginning of a container and\n          removes the closing marker. Parameter @a use_type further checks\n          whether all elements of a container have the same type and adds the\n          type marker to the beginning of the container. The @a use_type\n          parameter must only be used together with @a use_size = true. Note\n          that @a use_size = true alone may result in larger representations -\n          the benefit of this parameter is that the receiving side is\n          immediately informed on the number of elements of the container.\n\n    @param[in] j  JSON value to serialize\n    @param[in] use_size  whether to add size annotations to container types\n    @param[in] use_type  whether to add type annotations to container types\n                         (must be combined with @a use_size = true)\n    @return UBJSON serialization as byte vector\n\n    @complexity Linear in the size of the JSON value @a j.\n\n    @liveexample{The example shows the serialization of a JSON value to a byte\n    vector in UBJSON format.,to_ubjson}\n\n    @sa http://ubjson.org\n    @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the\n        analogous deserialization\n    @sa @ref to_cbor(const basic_json& for the related CBOR format\n    @sa @ref to_msgpack(const basic_json&) for the related MessagePack format\n\n    @since version 3.1.0\n    */\n    static std::vector<uint8_t> to_ubjson(const basic_json& j,\n                                          const bool use_size = false,\n                                          const bool use_type = false)\n    {\n        std::vector<uint8_t> result;\n        to_ubjson(j, result, use_size, use_type);\n        return result;\n    }\n\n    static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,\n                          const bool use_size = false, const bool use_type = false)\n    {\n        binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);\n    }\n\n    static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,\n                          const bool use_size = false, const bool use_type = false)\n    {\n        binary_writer<char>(o).write_ubjson(j, use_size, use_type);\n    }\n\n\n    /*!\n    @brief Serializes the given JSON object `j` to BSON and returns a vector\n           containing the corresponding BSON-representation.\n\n    BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are\n    stored as a single entity (a so-called document).\n\n    The library uses the following mapping from JSON values types to BSON types:\n\n    JSON value type | value/range                       | BSON type   | marker\n    --------------- | --------------------------------- | ----------- | ------\n    null            | `null`                            | null        | 0x0A\n    boolean         | `true`, `false`                   | boolean     | 0x08\n    number_integer  | -9223372036854775808..-2147483649 | int64       | 0x12\n    number_integer  | -2147483648..2147483647           | int32       | 0x10\n    number_integer  | 2147483648..9223372036854775807   | int64       | 0x12\n    number_unsigned | 0..2147483647                     | int32       | 0x10\n    number_unsigned | 2147483648..9223372036854775807   | int64       | 0x12\n    number_unsigned | 9223372036854775808..18446744073709551615| --   | --\n    number_float    | *any value*                       | double      | 0x01\n    string          | *any value*                       | string      | 0x02\n    array           | *any value*                       | document    | 0x04\n    object          | *any value*                       | document    | 0x03\n\n    @warning The mapping is **incomplete**, since only JSON-objects (and things\n    contained therein) can be serialized to BSON.\n    Also, integers larger than 9223372036854775807 cannot be serialized to BSON,\n    and the keys may not contain U+0000, since they are serialized a\n    zero-terminated c-strings.\n\n    @throw out_of_range.407  if `j.is_number_unsigned() && j.get<std::uint64_t>() > 9223372036854775807`\n    @throw out_of_range.409  if a key in `j` contains a NULL (U+0000)\n    @throw type_error.317    if `!j.is_object()`\n\n    @pre The input `j` is required to be an object: `j.is_object() == true`.\n\n    @note Any BSON output created via @ref to_bson can be successfully parsed\n          by @ref from_bson.\n\n    @param[in] j  JSON value to serialize\n    @return BSON serialization as byte vector\n\n    @complexity Linear in the size of the JSON value @a j.\n\n    @liveexample{The example shows the serialization of a JSON value to a byte\n    vector in BSON format.,to_bson}\n\n    @sa http://bsonspec.org/spec.html\n    @sa @ref from_bson(detail::input_adapter&&, const bool strict) for the\n        analogous deserialization\n    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the\n             related UBJSON format\n    @sa @ref to_cbor(const basic_json&) for the related CBOR format\n    @sa @ref to_msgpack(const basic_json&) for the related MessagePack format\n    */\n    static std::vector<uint8_t> to_bson(const basic_json& j)\n    {\n        std::vector<uint8_t> result;\n        to_bson(j, result);\n        return result;\n    }\n\n    /*!\n    @brief Serializes the given JSON object `j` to BSON and forwards the\n           corresponding BSON-representation to the given output_adapter `o`.\n    @param j The JSON object to convert to BSON.\n    @param o The output adapter that receives the binary BSON representation.\n    @pre The input `j` shall be an object: `j.is_object() == true`\n    @sa @ref to_bson(const basic_json&)\n    */\n    static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o)\n    {\n        binary_writer<uint8_t>(o).write_bson(j);\n    }\n\n    /*!\n    @copydoc to_bson(const basic_json&, detail::output_adapter<uint8_t>)\n    */\n    static void to_bson(const basic_json& j, detail::output_adapter<char> o)\n    {\n        binary_writer<char>(o).write_bson(j);\n    }\n\n\n    /*!\n    @brief create a JSON value from an input in CBOR format\n\n    Deserializes a given input @a i to a JSON value using the CBOR (Concise\n    Binary Object Representation) serialization format.\n\n    The library maps CBOR types to JSON value types as follows:\n\n    CBOR type              | JSON value type | first byte\n    ---------------------- | --------------- | ----------\n    Integer                | number_unsigned | 0x00..0x17\n    Unsigned integer       | number_unsigned | 0x18\n    Unsigned integer       | number_unsigned | 0x19\n    Unsigned integer       | number_unsigned | 0x1A\n    Unsigned integer       | number_unsigned | 0x1B\n    Negative integer       | number_integer  | 0x20..0x37\n    Negative integer       | number_integer  | 0x38\n    Negative integer       | number_integer  | 0x39\n    Negative integer       | number_integer  | 0x3A\n    Negative integer       | number_integer  | 0x3B\n    Negative integer       | number_integer  | 0x40..0x57\n    UTF-8 string           | string          | 0x60..0x77\n    UTF-8 string           | string          | 0x78\n    UTF-8 string           | string          | 0x79\n    UTF-8 string           | string          | 0x7A\n    UTF-8 string           | string          | 0x7B\n    UTF-8 string           | string          | 0x7F\n    array                  | array           | 0x80..0x97\n    array                  | array           | 0x98\n    array                  | array           | 0x99\n    array                  | array           | 0x9A\n    array                  | array           | 0x9B\n    array                  | array           | 0x9F\n    map                    | object          | 0xA0..0xB7\n    map                    | object          | 0xB8\n    map                    | object          | 0xB9\n    map                    | object          | 0xBA\n    map                    | object          | 0xBB\n    map                    | object          | 0xBF\n    False                  | `false`         | 0xF4\n    True                   | `true`          | 0xF5\n    Null                   | `null`          | 0xF6\n    Half-Precision Float   | number_float    | 0xF9\n    Single-Precision Float | number_float    | 0xFA\n    Double-Precision Float | number_float    | 0xFB\n\n    @warning The mapping is **incomplete** in the sense that not all CBOR\n             types can be converted to a JSON value. The following CBOR types\n             are not supported and will yield parse errors (parse_error.112):\n             - byte strings (0x40..0x5F)\n             - date/time (0xC0..0xC1)\n             - bignum (0xC2..0xC3)\n             - decimal fraction (0xC4)\n             - bigfloat (0xC5)\n             - tagged items (0xC6..0xD4, 0xD8..0xDB)\n             - expected conversions (0xD5..0xD7)\n             - simple values (0xE0..0xF3, 0xF8)\n             - undefined (0xF7)\n\n    @warning CBOR allows map keys of any type, whereas JSON only allows\n             strings as keys in object values. Therefore, CBOR maps with keys\n             other than UTF-8 strings are rejected (parse_error.113).\n\n    @note Any CBOR output created @ref to_cbor can be successfully parsed by\n          @ref from_cbor.\n\n    @param[in] i  an input in CBOR format convertible to an input adapter\n    @param[in] strict  whether to expect the input to be consumed until EOF\n                       (true by default)\n    @param[in] allow_exceptions  whether to throw exceptions in case of a\n    parse error (optional, true by default)\n\n    @return deserialized JSON value; in case of a parse error and\n            @a allow_exceptions set to `false`, the return value will be\n            value_t::discarded.\n\n    @throw parse_error.110 if the given input ends prematurely or the end of\n    file was not reached when @a strict was set to true\n    @throw parse_error.112 if unsupported features from CBOR were\n    used in the given input @a v or if the input is not valid CBOR\n    @throw parse_error.113 if a string was expected as map key, but not found\n\n    @complexity Linear in the size of the input @a i.\n\n    @liveexample{The example shows the deserialization of a byte vector in CBOR\n    format to a JSON value.,from_cbor}\n\n    @sa http://cbor.io\n    @sa @ref to_cbor(const basic_json&) for the analogous serialization\n    @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the\n        related MessagePack format\n    @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the\n        related UBJSON format\n\n    @since version 2.0.9; parameter @a start_index since 2.1.1; changed to\n           consume input adapters, removed start_index parameter, and added\n           @a strict parameter since 3.0.0; added @a allow_exceptions parameter\n           since 3.2.0\n    */\n    JSON_NODISCARD\n    static basic_json from_cbor(detail::input_adapter&& i,\n                                const bool strict = true,\n                                const bool allow_exceptions = true)\n    {\n        basic_json result;\n        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);\n        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);\n        return res ? result : basic_json(value_t::discarded);\n    }\n\n    /*!\n    @copydoc from_cbor(detail::input_adapter&&, const bool, const bool)\n    */\n    template<typename A1, typename A2,\n             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>\n    JSON_NODISCARD\n    static basic_json from_cbor(A1 && a1, A2 && a2,\n                                const bool strict = true,\n                                const bool allow_exceptions = true)\n    {\n        basic_json result;\n        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);\n        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);\n        return res ? result : basic_json(value_t::discarded);\n    }\n\n    /*!\n    @brief create a JSON value from an input in MessagePack format\n\n    Deserializes a given input @a i to a JSON value using the MessagePack\n    serialization format.\n\n    The library maps MessagePack types to JSON value types as follows:\n\n    MessagePack type | JSON value type | first byte\n    ---------------- | --------------- | ----------\n    positive fixint  | number_unsigned | 0x00..0x7F\n    fixmap           | object          | 0x80..0x8F\n    fixarray         | array           | 0x90..0x9F\n    fixstr           | string          | 0xA0..0xBF\n    nil              | `null`          | 0xC0\n    false            | `false`         | 0xC2\n    true             | `true`          | 0xC3\n    float 32         | number_float    | 0xCA\n    float 64         | number_float    | 0xCB\n    uint 8           | number_unsigned | 0xCC\n    uint 16          | number_unsigned | 0xCD\n    uint 32          | number_unsigned | 0xCE\n    uint 64          | number_unsigned | 0xCF\n    int 8            | number_integer  | 0xD0\n    int 16           | number_integer  | 0xD1\n    int 32           | number_integer  | 0xD2\n    int 64           | number_integer  | 0xD3\n    str 8            | string          | 0xD9\n    str 16           | string          | 0xDA\n    str 32           | string          | 0xDB\n    array 16         | array           | 0xDC\n    array 32         | array           | 0xDD\n    map 16           | object          | 0xDE\n    map 32           | object          | 0xDF\n    negative fixint  | number_integer  | 0xE0-0xFF\n\n    @warning The mapping is **incomplete** in the sense that not all\n             MessagePack types can be converted to a JSON value. The following\n             MessagePack types are not supported and will yield parse errors:\n              - bin 8 - bin 32 (0xC4..0xC6)\n              - ext 8 - ext 32 (0xC7..0xC9)\n              - fixext 1 - fixext 16 (0xD4..0xD8)\n\n    @note Any MessagePack output created @ref to_msgpack can be successfully\n          parsed by @ref from_msgpack.\n\n    @param[in] i  an input in MessagePack format convertible to an input\n                  adapter\n    @param[in] strict  whether to expect the input to be consumed until EOF\n                       (true by default)\n    @param[in] allow_exceptions  whether to throw exceptions in case of a\n    parse error (optional, true by default)\n\n    @return deserialized JSON value; in case of a parse error and\n            @a allow_exceptions set to `false`, the return value will be\n            value_t::discarded.\n\n    @throw parse_error.110 if the given input ends prematurely or the end of\n    file was not reached when @a strict was set to true\n    @throw parse_error.112 if unsupported features from MessagePack were\n    used in the given input @a i or if the input is not valid MessagePack\n    @throw parse_error.113 if a string was expected as map key, but not found\n\n    @complexity Linear in the size of the input @a i.\n\n    @liveexample{The example shows the deserialization of a byte vector in\n    MessagePack format to a JSON value.,from_msgpack}\n\n    @sa http://msgpack.org\n    @sa @ref to_msgpack(const basic_json&) for the analogous serialization\n    @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the\n        related CBOR format\n    @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for\n        the related UBJSON format\n    @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for\n        the related BSON format\n\n    @since version 2.0.9; parameter @a start_index since 2.1.1; changed to\n           consume input adapters, removed start_index parameter, and added\n           @a strict parameter since 3.0.0; added @a allow_exceptions parameter\n           since 3.2.0\n    */\n    JSON_NODISCARD\n    static basic_json from_msgpack(detail::input_adapter&& i,\n                                   const bool strict = true,\n                                   const bool allow_exceptions = true)\n    {\n        basic_json result;\n        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);\n        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);\n        return res ? result : basic_json(value_t::discarded);\n    }\n\n    /*!\n    @copydoc from_msgpack(detail::input_adapter&&, const bool, const bool)\n    */\n    template<typename A1, typename A2,\n             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>\n    JSON_NODISCARD\n    static basic_json from_msgpack(A1 && a1, A2 && a2,\n                                   const bool strict = true,\n                                   const bool allow_exceptions = true)\n    {\n        basic_json result;\n        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);\n        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);\n        return res ? result : basic_json(value_t::discarded);\n    }\n\n    /*!\n    @brief create a JSON value from an input in UBJSON format\n\n    Deserializes a given input @a i to a JSON value using the UBJSON (Universal\n    Binary JSON) serialization format.\n\n    The library maps UBJSON types to JSON value types as follows:\n\n    UBJSON type | JSON value type                         | marker\n    ----------- | --------------------------------------- | ------\n    no-op       | *no value, next value is read*          | `N`\n    null        | `null`                                  | `Z`\n    false       | `false`                                 | `F`\n    true        | `true`                                  | `T`\n    float32     | number_float                            | `d`\n    float64     | number_float                            | `D`\n    uint8       | number_unsigned                         | `U`\n    int8        | number_integer                          | `i`\n    int16       | number_integer                          | `I`\n    int32       | number_integer                          | `l`\n    int64       | number_integer                          | `L`\n    string      | string                                  | `S`\n    char        | string                                  | `C`\n    array       | array (optimized values are supported)  | `[`\n    object      | object (optimized values are supported) | `{`\n\n    @note The mapping is **complete** in the sense that any UBJSON value can\n          be converted to a JSON value.\n\n    @param[in] i  an input in UBJSON format convertible to an input adapter\n    @param[in] strict  whether to expect the input to be consumed until EOF\n                       (true by default)\n    @param[in] allow_exceptions  whether to throw exceptions in case of a\n    parse error (optional, true by default)\n\n    @return deserialized JSON value; in case of a parse error and\n            @a allow_exceptions set to `false`, the return value will be\n            value_t::discarded.\n\n    @throw parse_error.110 if the given input ends prematurely or the end of\n    file was not reached when @a strict was set to true\n    @throw parse_error.112 if a parse error occurs\n    @throw parse_error.113 if a string could not be parsed successfully\n\n    @complexity Linear in the size of the input @a i.\n\n    @liveexample{The example shows the deserialization of a byte vector in\n    UBJSON format to a JSON value.,from_ubjson}\n\n    @sa http://ubjson.org\n    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the\n             analogous serialization\n    @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the\n        related CBOR format\n    @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for\n        the related MessagePack format\n    @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for\n        the related BSON format\n\n    @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0\n    */\n    JSON_NODISCARD\n    static basic_json from_ubjson(detail::input_adapter&& i,\n                                  const bool strict = true,\n                                  const bool allow_exceptions = true)\n    {\n        basic_json result;\n        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);\n        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);\n        return res ? result : basic_json(value_t::discarded);\n    }\n\n    /*!\n    @copydoc from_ubjson(detail::input_adapter&&, const bool, const bool)\n    */\n    template<typename A1, typename A2,\n             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>\n    JSON_NODISCARD\n    static basic_json from_ubjson(A1 && a1, A2 && a2,\n                                  const bool strict = true,\n                                  const bool allow_exceptions = true)\n    {\n        basic_json result;\n        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);\n        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);\n        return res ? result : basic_json(value_t::discarded);\n    }\n\n    /*!\n    @brief Create a JSON value from an input in BSON format\n\n    Deserializes a given input @a i to a JSON value using the BSON (Binary JSON)\n    serialization format.\n\n    The library maps BSON record types to JSON value types as follows:\n\n    BSON type       | BSON marker byte | JSON value type\n    --------------- | ---------------- | ---------------------------\n    double          | 0x01             | number_float\n    string          | 0x02             | string\n    document        | 0x03             | object\n    array           | 0x04             | array\n    binary          | 0x05             | still unsupported\n    undefined       | 0x06             | still unsupported\n    ObjectId        | 0x07             | still unsupported\n    boolean         | 0x08             | boolean\n    UTC Date-Time   | 0x09             | still unsupported\n    null            | 0x0A             | null\n    Regular Expr.   | 0x0B             | still unsupported\n    DB Pointer      | 0x0C             | still unsupported\n    JavaScript Code | 0x0D             | still unsupported\n    Symbol          | 0x0E             | still unsupported\n    JavaScript Code | 0x0F             | still unsupported\n    int32           | 0x10             | number_integer\n    Timestamp       | 0x11             | still unsupported\n    128-bit decimal float | 0x13       | still unsupported\n    Max Key         | 0x7F             | still unsupported\n    Min Key         | 0xFF             | still unsupported\n\n    @warning The mapping is **incomplete**. The unsupported mappings\n             are indicated in the table above.\n\n    @param[in] i  an input in BSON format convertible to an input adapter\n    @param[in] strict  whether to expect the input to be consumed until EOF\n                       (true by default)\n    @param[in] allow_exceptions  whether to throw exceptions in case of a\n    parse error (optional, true by default)\n\n    @return deserialized JSON value; in case of a parse error and\n            @a allow_exceptions set to `false`, the return value will be\n            value_t::discarded.\n\n    @throw parse_error.114 if an unsupported BSON record type is encountered\n\n    @complexity Linear in the size of the input @a i.\n\n    @liveexample{The example shows the deserialization of a byte vector in\n    BSON format to a JSON value.,from_bson}\n\n    @sa http://bsonspec.org/spec.html\n    @sa @ref to_bson(const basic_json&) for the analogous serialization\n    @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the\n        related CBOR format\n    @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for\n        the related MessagePack format\n    @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the\n        related UBJSON format\n    */\n    JSON_NODISCARD\n    static basic_json from_bson(detail::input_adapter&& i,\n                                const bool strict = true,\n                                const bool allow_exceptions = true)\n    {\n        basic_json result;\n        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);\n        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::bson, &sdp, strict);\n        return res ? result : basic_json(value_t::discarded);\n    }\n\n    /*!\n    @copydoc from_bson(detail::input_adapter&&, const bool, const bool)\n    */\n    template<typename A1, typename A2,\n             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>\n    JSON_NODISCARD\n    static basic_json from_bson(A1 && a1, A2 && a2,\n                                const bool strict = true,\n                                const bool allow_exceptions = true)\n    {\n        basic_json result;\n        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);\n        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::bson, &sdp, strict);\n        return res ? result : basic_json(value_t::discarded);\n    }\n\n\n\n    /// @}\n\n    //////////////////////////\n    // JSON Pointer support //\n    //////////////////////////\n\n    /// @name JSON Pointer functions\n    /// @{\n\n    /*!\n    @brief access specified element via JSON Pointer\n\n    Uses a JSON pointer to retrieve a reference to the respective JSON value.\n    No bound checking is performed. Similar to @ref operator[](const typename\n    object_t::key_type&), `null` values are created in arrays and objects if\n    necessary.\n\n    In particular:\n    - If the JSON pointer points to an object key that does not exist, it\n      is created an filled with a `null` value before a reference to it\n      is returned.\n    - If the JSON pointer points to an array index that does not exist, it\n      is created an filled with a `null` value before a reference to it\n      is returned. All indices between the current maximum and the given\n      index are also filled with `null`.\n    - The special value `-` is treated as a synonym for the index past the\n      end.\n\n    @param[in] ptr  a JSON pointer\n\n    @return reference to the element pointed to by @a ptr\n\n    @complexity Constant.\n\n    @throw parse_error.106   if an array index begins with '0'\n    @throw parse_error.109   if an array index was not a number\n    @throw out_of_range.404  if the JSON pointer can not be resolved\n\n    @liveexample{The behavior is shown in the example.,operatorjson_pointer}\n\n    @since version 2.0.0\n    */\n    reference operator[](const json_pointer& ptr)\n    {\n        return ptr.get_unchecked(this);\n    }\n\n    /*!\n    @brief access specified element via JSON Pointer\n\n    Uses a JSON pointer to retrieve a reference to the respective JSON value.\n    No bound checking is performed. The function does not change the JSON\n    value; no `null` values are created. In particular, the the special value\n    `-` yields an exception.\n\n    @param[in] ptr  JSON pointer to the desired element\n\n    @return const reference to the element pointed to by @a ptr\n\n    @complexity Constant.\n\n    @throw parse_error.106   if an array index begins with '0'\n    @throw parse_error.109   if an array index was not a number\n    @throw out_of_range.402  if the array index '-' is used\n    @throw out_of_range.404  if the JSON pointer can not be resolved\n\n    @liveexample{The behavior is shown in the example.,operatorjson_pointer_const}\n\n    @since version 2.0.0\n    */\n    const_reference operator[](const json_pointer& ptr) const\n    {\n        return ptr.get_unchecked(this);\n    }\n\n    /*!\n    @brief access specified element via JSON Pointer\n\n    Returns a reference to the element at with specified JSON pointer @a ptr,\n    with bounds checking.\n\n    @param[in] ptr  JSON pointer to the desired element\n\n    @return reference to the element pointed to by @a ptr\n\n    @throw parse_error.106 if an array index in the passed JSON pointer @a ptr\n    begins with '0'. See example below.\n\n    @throw parse_error.109 if an array index in the passed JSON pointer @a ptr\n    is not a number. See example below.\n\n    @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr\n    is out of range. See example below.\n\n    @throw out_of_range.402 if the array index '-' is used in the passed JSON\n    pointer @a ptr. As `at` provides checked access (and no elements are\n    implicitly inserted), the index '-' is always invalid. See example below.\n\n    @throw out_of_range.403 if the JSON pointer describes a key of an object\n    which cannot be found. See example below.\n\n    @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.\n    See example below.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes in the JSON value.\n\n    @complexity Constant.\n\n    @since version 2.0.0\n\n    @liveexample{The behavior is shown in the example.,at_json_pointer}\n    */\n    reference at(const json_pointer& ptr)\n    {\n        return ptr.get_checked(this);\n    }\n\n    /*!\n    @brief access specified element via JSON Pointer\n\n    Returns a const reference to the element at with specified JSON pointer @a\n    ptr, with bounds checking.\n\n    @param[in] ptr  JSON pointer to the desired element\n\n    @return reference to the element pointed to by @a ptr\n\n    @throw parse_error.106 if an array index in the passed JSON pointer @a ptr\n    begins with '0'. See example below.\n\n    @throw parse_error.109 if an array index in the passed JSON pointer @a ptr\n    is not a number. See example below.\n\n    @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr\n    is out of range. See example below.\n\n    @throw out_of_range.402 if the array index '-' is used in the passed JSON\n    pointer @a ptr. As `at` provides checked access (and no elements are\n    implicitly inserted), the index '-' is always invalid. See example below.\n\n    @throw out_of_range.403 if the JSON pointer describes a key of an object\n    which cannot be found. See example below.\n\n    @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.\n    See example below.\n\n    @exceptionsafety Strong guarantee: if an exception is thrown, there are no\n    changes in the JSON value.\n\n    @complexity Constant.\n\n    @since version 2.0.0\n\n    @liveexample{The behavior is shown in the example.,at_json_pointer_const}\n    */\n    const_reference at(const json_pointer& ptr) const\n    {\n        return ptr.get_checked(this);\n    }\n\n    /*!\n    @brief return flattened JSON value\n\n    The function creates a JSON object whose keys are JSON pointers (see [RFC\n    6901](https://tools.ietf.org/html/rfc6901)) and whose values are all\n    primitive. The original JSON value can be restored using the @ref\n    unflatten() function.\n\n    @return an object that maps JSON pointers to primitive values\n\n    @note Empty objects and arrays are flattened to `null` and will not be\n          reconstructed correctly by the @ref unflatten() function.\n\n    @complexity Linear in the size the JSON value.\n\n    @liveexample{The following code shows how a JSON object is flattened to an\n    object whose keys consist of JSON pointers.,flatten}\n\n    @sa @ref unflatten() for the reverse function\n\n    @since version 2.0.0\n    */\n    basic_json flatten() const\n    {\n        basic_json result(value_t::object);\n        json_pointer::flatten(\"\", *this, result);\n        return result;\n    }\n\n    /*!\n    @brief unflatten a previously flattened JSON value\n\n    The function restores the arbitrary nesting of a JSON value that has been\n    flattened before using the @ref flatten() function. The JSON value must\n    meet certain constraints:\n    1. The value must be an object.\n    2. The keys must be JSON pointers (see\n       [RFC 6901](https://tools.ietf.org/html/rfc6901))\n    3. The mapped values must be primitive JSON types.\n\n    @return the original JSON from a flattened version\n\n    @note Empty objects and arrays are flattened by @ref flatten() to `null`\n          values and can not unflattened to their original type. Apart from\n          this example, for a JSON value `j`, the following is always true:\n          `j == j.flatten().unflatten()`.\n\n    @complexity Linear in the size the JSON value.\n\n    @throw type_error.314  if value is not an object\n    @throw type_error.315  if object values are not primitive\n\n    @liveexample{The following code shows how a flattened JSON object is\n    unflattened into the original nested JSON object.,unflatten}\n\n    @sa @ref flatten() for the reverse function\n\n    @since version 2.0.0\n    */\n    basic_json unflatten() const\n    {\n        return json_pointer::unflatten(*this);\n    }\n\n    /// @}\n\n    //////////////////////////\n    // JSON Patch functions //\n    //////////////////////////\n\n    /// @name JSON Patch functions\n    /// @{\n\n    /*!\n    @brief applies a JSON patch\n\n    [JSON Patch](http://jsonpatch.com) defines a JSON document structure for\n    expressing a sequence of operations to apply to a JSON) document. With\n    this function, a JSON Patch is applied to the current JSON value by\n    executing all operations from the patch.\n\n    @param[in] json_patch  JSON patch document\n    @return patched document\n\n    @note The application of a patch is atomic: Either all operations succeed\n          and the patched document is returned or an exception is thrown. In\n          any case, the original value is not changed: the patch is applied\n          to a copy of the value.\n\n    @throw parse_error.104 if the JSON patch does not consist of an array of\n    objects\n\n    @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory\n    attributes are missing); example: `\"operation add must have member path\"`\n\n    @throw out_of_range.401 if an array index is out of range.\n\n    @throw out_of_range.403 if a JSON pointer inside the patch could not be\n    resolved successfully in the current JSON value; example: `\"key baz not\n    found\"`\n\n    @throw out_of_range.405 if JSON pointer has no parent (\"add\", \"remove\",\n    \"move\")\n\n    @throw other_error.501 if \"test\" operation was unsuccessful\n\n    @complexity Linear in the size of the JSON value and the length of the\n    JSON patch. As usually only a fraction of the JSON value is affected by\n    the patch, the complexity can usually be neglected.\n\n    @liveexample{The following code shows how a JSON patch is applied to a\n    value.,patch}\n\n    @sa @ref diff -- create a JSON patch by comparing two JSON values\n\n    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)\n    @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)\n\n    @since version 2.0.0\n    */\n    basic_json patch(const basic_json& json_patch) const\n    {\n        // make a working copy to apply the patch to\n        basic_json result = *this;\n\n        // the valid JSON Patch operations\n        enum class patch_operations {add, remove, replace, move, copy, test, invalid};\n\n        const auto get_op = [](const std::string & op)\n        {\n            if (op == \"add\")\n            {\n                return patch_operations::add;\n            }\n            if (op == \"remove\")\n            {\n                return patch_operations::remove;\n            }\n            if (op == \"replace\")\n            {\n                return patch_operations::replace;\n            }\n            if (op == \"move\")\n            {\n                return patch_operations::move;\n            }\n            if (op == \"copy\")\n            {\n                return patch_operations::copy;\n            }\n            if (op == \"test\")\n            {\n                return patch_operations::test;\n            }\n\n            return patch_operations::invalid;\n        };\n\n        // wrapper for \"add\" operation; add value at ptr\n        const auto operation_add = [&result](json_pointer & ptr, basic_json val)\n        {\n            // adding to the root of the target document means replacing it\n            if (ptr.is_root())\n            {\n                result = val;\n            }\n            else\n            {\n                // make sure the top element of the pointer exists\n                json_pointer top_pointer = ptr.top();\n                if (top_pointer != ptr)\n                {\n                    result.at(top_pointer);\n                }\n\n                // get reference to parent of JSON pointer ptr\n                const auto last_path = ptr.pop_back();\n                basic_json& parent = result[ptr];\n\n                switch (parent.m_type)\n                {\n                    case value_t::null:\n                    case value_t::object:\n                    {\n                        // use operator[] to add value\n                        parent[last_path] = val;\n                        break;\n                    }\n\n                    case value_t::array:\n                    {\n                        if (last_path == \"-\")\n                        {\n                            // special case: append to back\n                            parent.push_back(val);\n                        }\n                        else\n                        {\n                            const auto idx = json_pointer::array_index(last_path);\n                            if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))\n                            {\n                                // avoid undefined behavior\n                                JSON_THROW(out_of_range::create(401, \"array index \" + std::to_string(idx) + \" is out of range\"));\n                            }\n\n                            // default case: insert add offset\n                            parent.insert(parent.begin() + static_cast<difference_type>(idx), val);\n                        }\n                        break;\n                    }\n\n                    // LCOV_EXCL_START\n                    default:\n                    {\n                        // if there exists a parent it cannot be primitive\n                        assert(false);\n                    }\n                        // LCOV_EXCL_STOP\n                }\n            }\n        };\n\n        // wrapper for \"remove\" operation; remove value at ptr\n        const auto operation_remove = [&result](json_pointer & ptr)\n        {\n            // get reference to parent of JSON pointer ptr\n            const auto last_path = ptr.pop_back();\n            basic_json& parent = result.at(ptr);\n\n            // remove child\n            if (parent.is_object())\n            {\n                // perform range check\n                auto it = parent.find(last_path);\n                if (JSON_LIKELY(it != parent.end()))\n                {\n                    parent.erase(it);\n                }\n                else\n                {\n                    JSON_THROW(out_of_range::create(403, \"key '\" + last_path + \"' not found\"));\n                }\n            }\n            else if (parent.is_array())\n            {\n                // note erase performs range check\n                parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));\n            }\n        };\n\n        // type check: top level value must be an array\n        if (JSON_UNLIKELY(not json_patch.is_array()))\n        {\n            JSON_THROW(parse_error::create(104, 0, \"JSON patch must be an array of objects\"));\n        }\n\n        // iterate and apply the operations\n        for (const auto& val : json_patch)\n        {\n            // wrapper to get a value for an operation\n            const auto get_value = [&val](const std::string & op,\n                                          const std::string & member,\n                                          bool string_type) -> basic_json &\n            {\n                // find value\n                auto it = val.m_value.object->find(member);\n\n                // context-sensitive error message\n                const auto error_msg = (op == \"op\") ? \"operation\" : \"operation '\" + op + \"'\";\n\n                // check if desired value is present\n                if (JSON_UNLIKELY(it == val.m_value.object->end()))\n                {\n                    JSON_THROW(parse_error::create(105, 0, error_msg + \" must have member '\" + member + \"'\"));\n                }\n\n                // check if result is of type string\n                if (JSON_UNLIKELY(string_type and not it->second.is_string()))\n                {\n                    JSON_THROW(parse_error::create(105, 0, error_msg + \" must have string member '\" + member + \"'\"));\n                }\n\n                // no error: return value\n                return it->second;\n            };\n\n            // type check: every element of the array must be an object\n            if (JSON_UNLIKELY(not val.is_object()))\n            {\n                JSON_THROW(parse_error::create(104, 0, \"JSON patch must be an array of objects\"));\n            }\n\n            // collect mandatory members\n            const std::string op = get_value(\"op\", \"op\", true);\n            const std::string path = get_value(op, \"path\", true);\n            json_pointer ptr(path);\n\n            switch (get_op(op))\n            {\n                case patch_operations::add:\n                {\n                    operation_add(ptr, get_value(\"add\", \"value\", false));\n                    break;\n                }\n\n                case patch_operations::remove:\n                {\n                    operation_remove(ptr);\n                    break;\n                }\n\n                case patch_operations::replace:\n                {\n                    // the \"path\" location must exist - use at()\n                    result.at(ptr) = get_value(\"replace\", \"value\", false);\n                    break;\n                }\n\n                case patch_operations::move:\n                {\n                    const std::string from_path = get_value(\"move\", \"from\", true);\n                    json_pointer from_ptr(from_path);\n\n                    // the \"from\" location must exist - use at()\n                    basic_json v = result.at(from_ptr);\n\n                    // The move operation is functionally identical to a\n                    // \"remove\" operation on the \"from\" location, followed\n                    // immediately by an \"add\" operation at the target\n                    // location with the value that was just removed.\n                    operation_remove(from_ptr);\n                    operation_add(ptr, v);\n                    break;\n                }\n\n                case patch_operations::copy:\n                {\n                    const std::string from_path = get_value(\"copy\", \"from\", true);\n                    const json_pointer from_ptr(from_path);\n\n                    // the \"from\" location must exist - use at()\n                    basic_json v = result.at(from_ptr);\n\n                    // The copy is functionally identical to an \"add\"\n                    // operation at the target location using the value\n                    // specified in the \"from\" member.\n                    operation_add(ptr, v);\n                    break;\n                }\n\n                case patch_operations::test:\n                {\n                    bool success = false;\n                    JSON_TRY\n                    {\n                        // check if \"value\" matches the one at \"path\"\n                        // the \"path\" location must exist - use at()\n                        success = (result.at(ptr) == get_value(\"test\", \"value\", false));\n                    }\n                    JSON_INTERNAL_CATCH (out_of_range&)\n                    {\n                        // ignore out of range errors: success remains false\n                    }\n\n                    // throw an exception if test fails\n                    if (JSON_UNLIKELY(not success))\n                    {\n                        JSON_THROW(other_error::create(501, \"unsuccessful: \" + val.dump()));\n                    }\n\n                    break;\n                }\n\n                case patch_operations::invalid:\n                {\n                    // op must be \"add\", \"remove\", \"replace\", \"move\", \"copy\", or\n                    // \"test\"\n                    JSON_THROW(parse_error::create(105, 0, \"operation value '\" + op + \"' is invalid\"));\n                }\n            }\n        }\n\n        return result;\n    }\n\n    /*!\n    @brief creates a diff as a JSON patch\n\n    Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can\n    be changed into the value @a target by calling @ref patch function.\n\n    @invariant For two JSON values @a source and @a target, the following code\n    yields always `true`:\n    @code {.cpp}\n    source.patch(diff(source, target)) == target;\n    @endcode\n\n    @note Currently, only `remove`, `add`, and `replace` operations are\n          generated.\n\n    @param[in] source  JSON value to compare from\n    @param[in] target  JSON value to compare against\n    @param[in] path    helper value to create JSON pointers\n\n    @return a JSON patch to convert the @a source to @a target\n\n    @complexity Linear in the lengths of @a source and @a target.\n\n    @liveexample{The following code shows how a JSON patch is created as a\n    diff for two JSON values.,diff}\n\n    @sa @ref patch -- apply a JSON patch\n    @sa @ref merge_patch -- apply a JSON Merge Patch\n\n    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)\n\n    @since version 2.0.0\n    */\n    JSON_NODISCARD\n    static basic_json diff(const basic_json& source, const basic_json& target,\n                           const std::string& path = \"\")\n    {\n        // the patch\n        basic_json result(value_t::array);\n\n        // if the values are the same, return empty patch\n        if (source == target)\n        {\n            return result;\n        }\n\n        if (source.type() != target.type())\n        {\n            // different types: replace value\n            result.push_back(\n            {\n                {\"op\", \"replace\"}, {\"path\", path}, {\"value\", target}\n            });\n        }\n        else\n        {\n            switch (source.type())\n            {\n                case value_t::array:\n                {\n                    // first pass: traverse common elements\n                    std::size_t i = 0;\n                    while (i < source.size() and i < target.size())\n                    {\n                        // recursive call to compare array values at index i\n                        auto temp_diff = diff(source[i], target[i], path + \"/\" + std::to_string(i));\n                        result.insert(result.end(), temp_diff.begin(), temp_diff.end());\n                        ++i;\n                    }\n\n                    // i now reached the end of at least one array\n                    // in a second pass, traverse the remaining elements\n\n                    // remove my remaining elements\n                    const auto end_index = static_cast<difference_type>(result.size());\n                    while (i < source.size())\n                    {\n                        // add operations in reverse order to avoid invalid\n                        // indices\n                        result.insert(result.begin() + end_index, object(\n                        {\n                            {\"op\", \"remove\"},\n                            {\"path\", path + \"/\" + std::to_string(i)}\n                        }));\n                        ++i;\n                    }\n\n                    // add other remaining elements\n                    while (i < target.size())\n                    {\n                        result.push_back(\n                        {\n                            {\"op\", \"add\"},\n                            {\"path\", path + \"/\" + std::to_string(i)},\n                            {\"value\", target[i]}\n                        });\n                        ++i;\n                    }\n\n                    break;\n                }\n\n                case value_t::object:\n                {\n                    // first pass: traverse this object's elements\n                    for (auto it = source.cbegin(); it != source.cend(); ++it)\n                    {\n                        // escape the key name to be used in a JSON patch\n                        const auto key = json_pointer::escape(it.key());\n\n                        if (target.find(it.key()) != target.end())\n                        {\n                            // recursive call to compare object values at key it\n                            auto temp_diff = diff(it.value(), target[it.key()], path + \"/\" + key);\n                            result.insert(result.end(), temp_diff.begin(), temp_diff.end());\n                        }\n                        else\n                        {\n                            // found a key that is not in o -> remove it\n                            result.push_back(object(\n                            {\n                                {\"op\", \"remove\"}, {\"path\", path + \"/\" + key}\n                            }));\n                        }\n                    }\n\n                    // second pass: traverse other object's elements\n                    for (auto it = target.cbegin(); it != target.cend(); ++it)\n                    {\n                        if (source.find(it.key()) == source.end())\n                        {\n                            // found a key that is not in this -> add it\n                            const auto key = json_pointer::escape(it.key());\n                            result.push_back(\n                            {\n                                {\"op\", \"add\"}, {\"path\", path + \"/\" + key},\n                                {\"value\", it.value()}\n                            });\n                        }\n                    }\n\n                    break;\n                }\n\n                default:\n                {\n                    // both primitive type: replace value\n                    result.push_back(\n                    {\n                        {\"op\", \"replace\"}, {\"path\", path}, {\"value\", target}\n                    });\n                    break;\n                }\n            }\n        }\n\n        return result;\n    }\n\n    /// @}\n\n    ////////////////////////////////\n    // JSON Merge Patch functions //\n    ////////////////////////////////\n\n    /// @name JSON Merge Patch functions\n    /// @{\n\n    /*!\n    @brief applies a JSON Merge Patch\n\n    The merge patch format is primarily intended for use with the HTTP PATCH\n    method as a means of describing a set of modifications to a target\n    resource's content. This function applies a merge patch to the current\n    JSON value.\n\n    The function implements the following algorithm from Section 2 of\n    [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396):\n\n    ```\n    define MergePatch(Target, Patch):\n      if Patch is an Object:\n        if Target is not an Object:\n          Target = {} // Ignore the contents and set it to an empty Object\n        for each Name/Value pair in Patch:\n          if Value is null:\n            if Name exists in Target:\n              remove the Name/Value pair from Target\n          else:\n            Target[Name] = MergePatch(Target[Name], Value)\n        return Target\n      else:\n        return Patch\n    ```\n\n    Thereby, `Target` is the current object; that is, the patch is applied to\n    the current value.\n\n    @param[in] apply_patch  the patch to apply\n\n    @complexity Linear in the lengths of @a patch.\n\n    @liveexample{The following code shows how a JSON Merge Patch is applied to\n    a JSON document.,merge_patch}\n\n    @sa @ref patch -- apply a JSON patch\n    @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)\n\n    @since version 3.0.0\n    */\n    void merge_patch(const basic_json& apply_patch)\n    {\n        if (apply_patch.is_object())\n        {\n            if (not is_object())\n            {\n                *this = object();\n            }\n            for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)\n            {\n                if (it.value().is_null())\n                {\n                    erase(it.key());\n                }\n                else\n                {\n                    operator[](it.key()).merge_patch(it.value());\n                }\n            }\n        }\n        else\n        {\n            *this = apply_patch;\n        }\n    }\n\n    /// @}\n};\n} // namespace nlohmann\n\n///////////////////////\n// nonmember support //\n///////////////////////\n\n// specialization of std::swap, and std::hash\nnamespace std\n{\n\n/// hash value for JSON objects\ntemplate<>\nstruct hash<nlohmann::json>\n{\n    /*!\n    @brief return a hash value for a JSON object\n\n    @since version 1.0.0\n    */\n    std::size_t operator()(const nlohmann::json& j) const\n    {\n        // a naive hashing via the string representation\n        const auto& h = hash<nlohmann::json::string_t>();\n        return h(j.dump());\n    }\n};\n\n/// specialization for std::less<value_t>\n/// @note: do not remove the space after '<',\n///        see https://github.com/nlohmann/json/pull/679\ntemplate<>\nstruct less< ::nlohmann::detail::value_t>\n{\n    /*!\n    @brief compare two value_t enum values\n    @since version 3.0.0\n    */\n    bool operator()(nlohmann::detail::value_t lhs,\n                    nlohmann::detail::value_t rhs) const noexcept\n    {\n        return nlohmann::detail::operator<(lhs, rhs);\n    }\n};\n\n/*!\n@brief exchanges the values of two JSON objects\n\n@since version 1.0.0\n*/\ntemplate<>\ninline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(\n    is_nothrow_move_constructible<nlohmann::json>::value and\n    is_nothrow_move_assignable<nlohmann::json>::value\n)\n{\n    j1.swap(j2);\n}\n\n} // namespace std\n\n/*!\n@brief user-defined string literal for JSON values\n\nThis operator implements a user-defined string literal for JSON objects. It\ncan be used by adding `\"_json\"` to a string literal and returns a JSON object\nif no parse error occurred.\n\n@param[in] s  a string representation of a JSON object\n@param[in] n  the length of string @a s\n@return a JSON object\n\n@since version 1.0.0\n*/\ninline nlohmann::json operator \"\" _json(const char* s, std::size_t n)\n{\n    return nlohmann::json::parse(s, s + n);\n}\n\n/*!\n@brief user-defined string literal for JSON pointer\n\nThis operator implements a user-defined string literal for JSON Pointers. It\ncan be used by adding `\"_json_pointer\"` to a string literal and returns a JSON pointer\nobject if no parse error occurred.\n\n@param[in] s  a string representation of a JSON Pointer\n@param[in] n  the length of string @a s\n@return a JSON pointer object\n\n@since version 2.0.0\n*/\ninline nlohmann::json::json_pointer operator \"\" _json_pointer(const char* s, std::size_t n)\n{\n    return nlohmann::json::json_pointer(std::string(s, n));\n}\n\n// #include <nlohmann/detail/macro_unscope.hpp>\n\n\n// restore GCC/clang diagnostic settings\n#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)\n    #pragma GCC diagnostic pop\n#endif\n#if defined(__clang__)\n    #pragma GCC diagnostic pop\n#endif\n\n// clean up\n#undef JSON_INTERNAL_CATCH\n#undef JSON_CATCH\n#undef JSON_THROW\n#undef JSON_TRY\n#undef JSON_LIKELY\n#undef JSON_UNLIKELY\n#undef JSON_DEPRECATED\n#undef JSON_NODISCARD\n#undef JSON_HAS_CPP_14\n#undef JSON_HAS_CPP_17\n#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION\n#undef NLOHMANN_BASIC_JSON_TPL\n\n\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/scripts/batch_run.py",
    "content": "#!/usr/bin/python\n\n\"\"\"\nRun a batch of configs\n\"\"\"\n\nimport argparse\nimport os\nimport shlex\nimport subprocess\nimport sys\nimport tempfile\n# project modules\nimport analysis\nimport parse_config\n\ndef process_configs(args):\n    \"\"\"given parsed args, return the config files in a list\"\"\"\n    configs = []\n    config_dirs = []\n    if not args.input:\n        print \"please specify at least one input from -i option\"\n        exit(1)\n        \n    for item in args.input:\n        if not os.path.exists(item):\n            print \"Input \", item, \" not exists!\"\n            exit(1)\n\n        if os.path.isfile(item):\n            if item[-4:] != \".ini\":\n                print \"INFO: ignoring non-ini file:\", item\n            else:\n                configs.append(item)\n        elif os.path.isdir(item):\n            for f in os.listdir(item):\n                if f[-4:] != \".ini\":\n                    print \"INFO: ignoring non-ini file:\", f\n                else:\n                    configs.append(os.path.join(item, f))\n        else:\n            print \"???\"\n            exit(1)\n    return configs\n\n\ndef build_summary(config_files, stats_csvs, summary_name):\n    # get some info from configs\n    protocols = []\n    for c in config_files:\n        protocols.append(parse_config.get_protocol(c))\n    \n    density = []\n    for c in config_files:\n        density.append(parse_config.get_density(c))\n\n    page_sizes = []\n    for c in config_files:\n        page_sizes.append(parse_config.get_page_size(c))\n\n    pure_config_names = []\n    for f in config_files:\n        pure_config_names.append(os.path.basename(f)[:-4])\n\n    summary_df = analysis.get_summary_df(stats_csvs)\n    summary_df = summary_df.assign(config=pure_config_names,\n                                   protocol=protocols,\n                                   density=density,\n                                   page_size=page_sizes)\n    summary_df.set_index(\"config\", inplace=True)\n    summary_df.to_csv(summary_name)\n   \n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(description=\"Run a batch of simulation\"\n                                     \"with a given set of config files \"\n                                     \"and possibliy redirect output, -h for help\")\n    parser.add_argument(\"executable\", help=\"executable location\")\n    parser.add_argument(\"-o\", \"--output-dir\", nargs=\"?\", default=\"\", help=\"override the 'output-prefix'\"\n                        \"and the outputs will be 'output-dir/config-name-post-fix'\"\n                        \"this won't mess the original file by using tempfiles\")\n    parser.add_argument(\"-i\", \"--input\", nargs=\"+\", help=\"configs input, could be a dir or list of files\"\n                        \"non-ini files will be ignored\")\n    parser.add_argument(\"-n\", default=100000, type=int, help=\"num of cycles, applied to all configs\")\n    parser.add_argument(\"--cpu-type\", default=\"random\", choices=[\"random\", \"trace\", \"stream\"],\n                        help=\"cpu type\")\n    parser.add_argument(\"-t\", \"--trace-file\", help=\"trace file, only for trace cpu\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"Silent output from simulation (not this script)\" )\n    parser.add_argument(\"-s\", \"--summary\", default=\"summary.csv\", help=\"Summary sheet name\")\n    args = parser.parse_args()\n\n    # some input sanity check\n    if not os.path.exists(args.executable):\n        print \"Exicutable: \", args.executable, \" not exits!\"\n        exit(1)\n\n    configs = process_configs(args)   \n\n    if args.output_dir:\n        if not os.path.exists(args.output_dir):\n            try:\n                os.mkdir(args.output_dir)\n                print \"WARNING: output dir not exists, creating one...\"\n            except OSError:\n                print \"cannot make directory: \", args.output_dir\n                exit(1)\n        print \"INFO: Overriding the output directory to: \", args.output_dir\n    \n    if args.cpu_type == \"trace\":\n        if not os.path.exists(args.trace_file):\n            print \"trace file not found for trace cpu\"\n    \n    output_prefixs = []\n    pure_config_names = []\n    for c in configs:\n        mem_type = \"default\"\n        if \"hmc\" in c.lower():\n            mem_type = \"hmc\"\n\n        config_file = c\n        pure_config_name = os.path.basename(c)[:-4]\n        pure_config_names.append(pure_config_name)\n\n        prefix = parse_config.get_val_from_file(c, \"other\", \"output_prefix\")\n        if args.output_dir:\n            prefix = os.path.join(args.output_dir, prefix)\n        output_prefixs.append(prefix)\n\n        cmd_str = \"%s --memory-type=%s --cpu-type=%s -c %s -n %d --output-dir %s\" % \\\n                  (args.executable, mem_type, args.cpu_type, config_file, args.n, args.output_dir)\n        \n        if args.cpu_type == \"trace\":\n            cmd_str += \" --trace-file=%s\" % args.trace_file\n\n        print \"EXECUTING:\", cmd_str\n        temp_stdout = None\n        if args.quiet:\n            temp_stdout = tempfile.TemporaryFile()\n        else:\n            temp_stdout = sys.stdout\n        try:\n            subprocess.call(shlex.split(cmd_str), stdout=temp_stdout)\n        except KeyboardInterrupt:\n            print \"skipping this one...\"\n\n    print \"INFO: Finished execution phase, generating results summary...\"\n\n    # prepare building summary csv\n    if args.output_dir:\n        summary_dir = args.output_dir\n    else:\n        summary_dir = \".\"\n    stats_csvs = []\n    for output_pre in output_prefixs:\n        stats_csvs.append(output_pre+\"stats.csv\")\n\n    build_summary(configs, stats_csvs, os.path.join(args.output_dir, args.summary))\n\n    "
  },
  {
    "path": "src/DRAMsim3/scripts/final_PowerTemperature_map.py",
    "content": "import argparse\nfrom numpy import genfromtxt\nfrom numpy import amax\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom matplotlib.patches import Rectangle\nimport sys\n\n\nparser = argparse.ArgumentParser()\nparser.add_argument(\"-m\", \"--mem_name\", help=\"type of memory\")\nparser.add_argument(\"-l\", \"--layer_str\", help=\"specified layer\")\nparser.add_argument(\"-f\", \"--save_root\", help=\"figure saved file\")\nargs = parser.parse_args()\n\nif len(sys.argv) != 7:\n\tparser.print_help()\n\tsys.exit(0)\n\n\nPT_file = \"../build/\" + args.mem_name + \"-output-final_power_temperature.csv\"\npos_file = \"../build/\" + args.mem_name + \"-output-bank_position.csv\"\n\nprint \"data file: \" + PT_file \nprint \"bank position file: \" + pos_file\n\n\nPT_data = genfromtxt(PT_file, delimiter=',')\nPT_data = PT_data[1:, :]\n\nBpos = genfromtxt(pos_file, delimiter=',')\nBpos = Bpos[1:, :]\n\nX = int(amax(PT_data[:, 1]))\nY = int(amax(PT_data[:, 2]))\nZ = int(amax(PT_data[:, 3]))\n\nprint \"Dimension: (\" + str(X) + \", \" + str(Y) + \", \" + str(Z) + \")\"\n\npower = np.empty((X+1, Y+1, Z+1))\ntemperature = np.empty((X+1, Y+1, Z+1))\n\nfor i in range(0, len(PT_data)):\n\tx_ = int(PT_data[i,1])\n\ty_ = int(PT_data[i,2])\n\tz_ = int(PT_data[i,3])\n\tpower[x_, y_, z_] = PT_data[i,4]\n\ttemperature[x_, y_, z_] = PT_data[i,5]\n\nlayer = int(args.layer_str)\n\nif layer >= 0 and layer <= Z:\n\tplt.figure()\n\tplt.imshow(power[:,:,layer], aspect='auto')\n\tca = plt.gca()\n\tfor i in range(0, len(Bpos)):\n\t\tif Bpos[i,6] == layer:\n\t\t\tx_ = Bpos[i,2] \n\t\t\ty_ = Bpos[i,4]\n\t\t\tw_ = Bpos[i,3] - Bpos[i,2] + 1\n\t\t\tl_ = Bpos[i,5] - Bpos[i,4] + 1\n\t\t\tca.add_patch(Rectangle((y_-0.5, x_-0.5), l_, w_, fill=None, edgecolor='r'))\n\t\t\tif l_ > w_:\n\t\t\t\trot = 0\n\t\t\telse:\n\t\t\t\trot = 0\n\n\t\t\tca.text(y_-0.5+l_/4, x_-0.5+w_/2, 'R'+str(int(Bpos[i,0]))+'B'+str(int(Bpos[i,1])), color='r', rotation=rot)\n\n\n\tca.set_xlabel('Y (Column)')\n\tca.set_ylabel('X (Row)')\n\ttitle_str = 'Power (layer' + str(layer) + ')'\n\tca.set_title(title_str)\n\tplt.colorbar()\n\tplt.savefig(args.save_root + args.mem_name + '_final_power_layer' + str(layer) + '.png')\n\n\tplt.figure()\n\tplt.imshow(temperature[:,:,layer], aspect='auto')\n\tca = plt.gca()\n\tfor i in range(0, len(Bpos)):\n\t\tif Bpos[i,6] == layer:\n\t\t\tx_ = Bpos[i,2] \n\t\t\ty_ = Bpos[i,4]\n\t\t\tw_ = Bpos[i,3] - Bpos[i,2] + 1\n\t\t\tl_ = Bpos[i,5] - Bpos[i,4] + 1\n\t\t\tca.add_patch(Rectangle((y_-0.5, x_-0.5), l_, w_, fill=None, edgecolor='r'))\n\t\t\tif l_ > w_:\n\t\t\t\trot = 0\n\t\t\telse:\n\t\t\t\trot = 0\n\n\t\t\tca.text(y_-0.5+l_/4, x_-0.5+w_/2, 'R'+str(int(Bpos[i,0]))+'B'+str(int(Bpos[i,1])), color='r', rotation=rot)\n\n\n\tca.set_xlabel('Y (Column)')\n\tca.set_ylabel('X (Row)')\n\ttitle_str = 'Power (layer' + str(layer) + ')'\n\tca.set_title(title_str)\n\tplt.colorbar()\n\tplt.savefig(args.save_root + args.mem_name + '_final_temperature_layer' + str(layer) + '.png')\n\nelse:\n\tprint \"You should name a correct layer index\"\n\tprint \"Layer index should be in the range of [\" + str(0) + \", \" + str(Z) + \"]\"\n\n"
  },
  {
    "path": "src/DRAMsim3/scripts/heatmap.py",
    "content": "#!/usr/bin/env python3\nimport argparse\nimport os\nimport sys\nfrom collections import OrderedDict\n\ntry:\n    import numpy as np\n    import pandas as pd\n    import matplotlib\nexcept:\n    print(\"please install numpy, matplotlib and pandas\")\n    raise\n\nmatplotlib.use(\"Agg\")\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\n\n\n\ndef construct_mesh(df, val_key, xkey=\"x\", ykey=\"y\"):\n    \"\"\"\n    to construct mesh data structure to be used for plotting later\n    this should be as generic as possible\n    the 3 keys in the args are used to locate data in the dataframe\n    return a dict that can be used by pcolor/pcolormesh functions\n    \"\"\"\n    x = df[xkey]\n    y = df[ykey]\n    t = df[val_key]\n    xx, yy = np.meshgrid(x.unique(), y.unique())\n    zz = []\n    y_groups = df.groupby(ykey)\n    for i in y.unique():\n        group = y_groups.get_group(i)\n        z = group[val_key]\n        zz.append(z)\n    zz = np.array(zz)\n    res = {\"x\":xx, \"y\":yy, \"val\":zz}\n    return res\n\n\ndef plot_heatmap(x, y, t, title, save_to=\"\"):\n    \"\"\"\n    quick access to single heatmap\n    \"\"\"\n    fig = plt.figure()\n    ax = fig.add_subplot(111)\n    pcm = ax.pcolormesh(x, y, t, cmap=\"coolwarm\")\n    fig.colorbar(pcm, ax=ax, extend=\"max\")\n    fig.savefig(\"heatmap.png\")\n\n\ndef plot_sub_heatmap(fig, ax, x, y, t, title):\n    pcm = ax.pcolormesh(x, y, t, cmap=\"coolwarm\")\n    ax.set_title(title)\n    # no offset used since temperature should be straightforward\n    c_bar_formatter = matplotlib.ticker.ScalarFormatter(useOffset=False)\n    cbar = fig.colorbar(pcm, ax=ax, extend=\"max\", format=c_bar_formatter)\n    return fig, ax\n\ndef prep_fig_axes(num_plots):\n    \"\"\"\n    so for each z dimension we plot 1 fig and if\n    there are multiple channels plot them as subplots\n    returns a dict with fig as keys and axes list as values\n    \"\"\"\n    fig = plt.figure(tight_layout=True)\n    if num_plots == 1:\n        n_rows = 1\n        n_cols = 1\n    elif num_plots == 2:\n        n_rows = 1\n        n_cols = 2\n    elif num_plots == 4:\n        n_rows = 2\n        n_cols = 2\n    elif num_plots ==8:\n        n_rows = 2\n        n_cols = 4\n    elif num_plots == 16:\n        n_rows = 4\n        n_cols = 4\n    elif num_plots == 32:\n        n_rows = 4\n        n_cols = 8\n    elif num_plots == 64:\n        n_rows = 8\n        n_cols = 8\n    else:\n        n_rows = 1\n        n_cols = 1\n    # create axes in subplot\n    plot_num = 1\n    for i in range(num_plots):\n        # args in add_subplot start from 1\n        ax = fig.add_subplot(n_rows, n_cols, plot_num)\n        plot_num += 1\n    return fig, fig.get_axes()\n\n\ndef plot_multi_rank_heatmap(multi_rank_data, save_to=\"\"):\n    \"\"\"\n    this should also be a generic plot function \n    return figs and axes so that we can process it later\n    \"\"\"\n    num_plots = len(multi_rank_data)\n    fig, axes = prep_fig_axes(num_plots)\n    plot_num = 0\n    for ax in axes:\n        data = multi_rank_data[plot_num]\n        plot_sub_heatmap(fig, ax, data[\"x\"], data[\"y\"], data[\"val\"], data[\"title\"])\n        plot_num += 1\n    return fig, axes\n\n\ndef plot_bank_patch(bank_line_data, fig_axes, show_num=True):\n    z = bank_line_data[\"z\"]\n    fig = fig_axes[z][\"fig\"]\n    axes = fig_axes[z][\"axes\"]\n    x_len = bank_line_data[\"end_x\"] - bank_line_data[\"start_x\"]\n    y_len = bank_line_data[\"end_y\"] - bank_line_data[\"start_y\"]\n    starting_coord = (bank_line_data[\"start_x\"], bank_line_data[\"start_y\"])\n    for ax in axes:\n        ax.add_patch(\n            patches.Rectangle(\n                starting_coord,\n                x_len,\n                y_len,\n                fill=False,\n                edgecolor=None,  # default\n                linewidth=None  # default\n            )\n        )\n        if show_num:\n            ax.text(\n                starting_coord[0] + 2, \n                starting_coord[1] + 2,\n                \"B\" + str(bank_line_data[\"bank_id\"]),\n                fontsize=8,\n                color=\"white\"\n            )\n\n    return\n\n\ndef save_figs(figs, prefix, img_format=\"png\"):\n    for i, fig_axes in enumerate(figs):\n        fig = fig_axes[\"fig\"]\n        fig_name = prefix + str(i) + \".\" + img_format\n        print(\"generating \",fig_name)\n        fig.savefig(fig_name)\n\n\ndef plot_simulation(stats_csv_file, bank_pos_file):\n    \"\"\"\n    so for each z dimension we plot 1 fig and if\n    there are multiple channels plot them as subplots\n    \"\"\"\n    frame = pd.read_csv(stats_csv_file)\n    die_frames = frame.groupby(\"z\")\n    power_data = []\n    temp_data = []\n    for z, z_frame in die_frames:\n        rank_frames = z_frame.groupby(\"rank_channel_index\")\n        z_power_data = []\n        z_temp_data = []\n        for rank, rank_frame in rank_frames:\n            rank_power_data = construct_mesh(rank_frame, \"power\", \"x\", \"y\")\n            rank_power_data[\"title\"] = \"die_\" + str(z) + \"_channel_rank_\" + str(rank) + \"_power\"\n            rank_temp_data = construct_mesh(rank_frame, \"temperature\", \"x\", \"y\")\n            rank_temp_data[\"title\"] = \"die_\" + str(z) + \"_channel_rank_\" + str(rank) + \"_temperature\"\n            z_power_data.append(rank_power_data)\n            z_temp_data.append(rank_temp_data)\n        power_data.append(z_power_data)\n        temp_data.append(z_temp_data)\n    \n    num_figs = len(power_data)\n    power_figs = []\n    temp_figs = []\n    for i in range(num_figs):\n        fig, axes = plot_multi_rank_heatmap(power_data[i])\n        power_figs.append({\"fig\":fig, \"axes\":axes})\n        fig, axes = plot_multi_rank_heatmap(temp_data[i])\n        temp_figs.append({\"fig\":fig, \"axes\":axes})\n\n    bank_pos_frame = pd.read_csv(bank_pos_file)\n\n    bank_pos = []\n    for index, row in bank_pos_frame.iterrows():\n        plot_bank_patch(row, power_figs)\n        plot_bank_patch(row, temp_figs)\n    return power_figs, temp_figs\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(description=\"Plot power and temperature heatmap\")\n    parser.add_argument(\"-p\", \"--prefix\", help=\"prefix of the simulation,\"\n                        \"if this is provided then no need for other arguments\",\n                        default = \"\")\n    parser.add_argument(\"-s\", \"--stats-csv\", help=\"temp and power stats csv file\")\n    parser.add_argument(\"-b\", \"--bank-csv\", help=\"bank postion csv file\")\n    args = parser.parse_args()\n    prefix = args.prefix\n    if prefix:\n        csv_file = prefix + \"final_power_temperature.csv\"\n        bank_pos_file = prefix + \"bank_position.csv\"\n    else:\n        if  args.stats_csv:\n            print(args.stats_csv)\n            csv_file = args.stats_csv\n        else:\n            print(\"need stats csv file for temp and power!\")\n            exit(1)\n        if args.bank_csv:\n            print(args.bank_csv)\n            bank_pos_file = args.bank_csv\n        else:\n            print(\"need bank position file!\")\n            exit(1)\n    p_figs, t_figs = plot_simulation(csv_file, bank_pos_file)\n    save_figs(p_figs, prefix + \"fig_power_\")\n    save_figs(t_figs, prefix + \"fig_temp_\")\n"
  },
  {
    "path": "src/DRAMsim3/scripts/parse_config.py",
    "content": "#!/usr/bin/env python3\nimport sys\nimport tempfile\nimport configparser\n\ndef get_val(config, sec, opt):\n    \"\"\"\n    get value from a ini file given the section and option\n    the priority here is int, float, boolean and finally string\n    \"\"\"\n    try:\n        val = config.getint(sec, opt)\n    except ValueError:\n        try:\n            val = config.getfloat(sec, opt)\n        except ValueError:\n            try:\n                val = config.getboolean(sec, opt)\n            except ValueError:\n                val = config.get(sec, opt)  # shouldn't have any exceptions here..\n    return val\n\ndef get_val_from_file(config_file, sec, opt):\n    \"\"\"\n        a quick way to obtain an option from a config file\n    \"\"\"\n    config = configparser.ConfigParser()\n    config.read(config_file)\n    return get_val(config, sec, opt)\n\n\n# a few quick access functions using get_val_from_file\ndef get_protocol(config_file):\n    return get_val_from_file(config_file, \"dram_structure\", \"protocol\")\n\n\ndef get_ddr_speed(config_file):\n    t_ck = get_val_from_file(config_file, \"timing\", \"tCK\")\n    freq = int(1/t_ck * 2 * 1000.)  # to get to MHz\n    freq_lookup = [800, 1333, 1600, 1866, 2133, 2400, 2666, 2933, 3200]\n    actual_freq = sys.maxsize\n    for f in freq_lookup:\n        freq_diff = abs(actual_freq - f)\n        if abs(f - freq) < freq_diff:\n            actual_freq = f\n    return actual_freq\n\n\ndef get_page_size(config_file):\n    \"\"\" \n        get page size in bytes\n    \"\"\"\n    cols = get_val_from_file(config_file, \"dram_structure\", \"columns\")\n    width = get_val_from_file(config_file, \"dram_structure\", \"device_width\")\n    page_size = cols * width / 8\n    return page_size\n\n\ndef get_density(config_file):\n    \"\"\"\n        get device density in mega bytes\n    \"\"\"\n    bankgroups = get_val_from_file(config_file, \"dram_structure\", \"bankgroups\")\n    banks = get_val_from_file(config_file, \"dram_structure\", \"banks_per_group\")\n    rows = get_val_from_file(config_file, \"dram_structure\", \"rows\")\n    page_size = get_page_size(config_file)\n    density = bankgroups * banks * rows * page_size\n    return density / 1024 / 1024\n\ndef get_rank_size_mb(config_file):\n    dens = get_density(config_file)\n    dev_width = get_val_from_file(config_file, \"dram_structure\", \"device_width\")\n    bus_width = get_val_from_file(config_file, \"system\", \"bus_width\")\n    num_dev = bus_width / dev_width\n    rank_size = dens * num_dev\n    return int(rank_size)\n\n\ndef get_dict(config_file):\n    \"\"\"\n    read a ini file specified by config_file and\n    return a dict of configs with [section][option] : value structure\n    \"\"\"\n    _config_dict = {}\n    config = configparser.ConfigParser()\n    config.read(config_file)\n    for sec in config.sections():\n        _config_dict[sec] = {}\n        for opt in config.options(sec):\n            _config_dict[sec][opt] = get_val(config, sec, opt)\n    return _config_dict\n\n\ndef sub_options(config_file, sec, opt, new_value, inplace=False):\n    \"\"\"\n        given a config file, replace the specified section, option\n        with a new value, and the inplace flag decides whether the \n        config_file will be written or a tempfile handler will be \n        returned, NOTE if inplace is true all the comments in the\n        original file will be gone..\n    \"\"\"\n    config = configparser.ConfigParser()\n    config.read(config_file)\n    if not config.has_section(sec):\n        config.add_section(sec)\n    \n    try:\n        config.set(sec, opt, str(new_value))\n    except configparser.Error:\n        raise\n    if not inplace:\n        temp_fp = tempfile.NamedTemporaryFile()\n        config.write(temp_fp)\n        temp_fp.seek(0)\n        return temp_fp \n    else:\n        with open(config_file, \"wb\") as fp:\n            config.write(fp)\n\n"
  },
  {
    "path": "src/DRAMsim3/scripts/plot_stats.py",
    "content": "#!/usr/bin/env python3\n\"\"\"\nGenerate time series graphs of power/bandwidth/energy...\n\"\"\"\n\nimport argparse\nimport json\nimport os\nimport sys\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n\ndef extract_epoch_data(json_data, label, merge_channel=True):\n    \"\"\"\n    TODO enable merge_channel=False option later\n    \"\"\"\n    if merge_channel:\n        merged_data = {}\n        for line in json_data:\n            epoch_num = line[\"epoch_num\"]\n            if epoch_num in merged_data:\n                merged_data[epoch_num] += line[label]\n            else:\n                merged_data[epoch_num] = line[label]\n        return [v for (k, v) in sorted(merged_data.items(),\n                                       key=lambda t: t[0])]\n\n\ndef plot_epochs(json_data, label, unit=\"\", output=None):\n    \"\"\"\n    plot the time series of a specified stat serie (e.g. bw, power, etc)\n    \"\"\"\n    print('ploting {}'.format(label))\n    cycles_per_epoch = json_data[0]['num_cycles']\n    y_data = extract_epoch_data(json_data, label)\n    x_ticks = [i * cycles_per_epoch for i in range(len(y_data))]\n\n    plt.plot(x_ticks, y_data)\n\n    plt.title(label)\n    plt.ticklabel_format(style='sci', axis='x', scilimits=(0, 0))\n    plt.xlabel('Cycles')\n    plt.ylabel('{} ({})'.format(label, unit))\n    plt.ylim(bottom=0, top=1.1*max(y_data))\n    if output:\n        plt.savefig(output+'_epochs_{}.pdf'.format(label))\n        plt.clf()\n    else:\n        plt.show()\n    return\n\n\ndef extract_histo_data(data, label):\n    array = []\n    for chan, channel_data in data.items():\n        for key, count in channel_data[label].items():\n            val = int(key)\n            array.extend([val for _ in range(count)])\n    return array\n\n\ndef plot_histogram(json_data, label, unit='', output=None):\n    histo_data = extract_histo_data(json_data, label)\n    histo_data = sorted(histo_data)\n    total_cnt = len(histo_data)\n    existing_nums = set()\n    unique_vals = 0\n    for i in range(int(0.90 * total_cnt)):\n        if histo_data[i] in existing_nums:\n            continue\n        else:\n            existing_nums.add(histo_data[i])\n            unique_vals += 1\n    print('90-Percentile unique {} values: {}'.format(label, unique_vals))\n    x_min = min(histo_data)\n    x_max = max(histo_data)\n    x_99 = int(0.99 * len(histo_data))\n    mark_99 = histo_data[x_99]\n    avg = np.average(histo_data)\n    histo_data = histo_data[0:x_99]\n    \n    # doane seems to provide better esitmates for bins\n    plt.hist(histo_data, bins='doane', density=True)\n\n    line_avg = plt.axvline(x=avg, linestyle='--', c='g',\n                           label='Average:{0:.1f}'.format(avg))\n    line_99 = plt.axvline(x=mark_99, linestyle='-.', c='r',\n                          label='99 Percentile:{0:.1f}'.format(mark_99))\n    plt.title(label)\n    plt.xlabel(label + ' [max: ' + str(x_max) + '](' + unit + ')')\n    plt.ylabel('Density')\n    plt.legend(handles=[line_avg, line_99])\n    if output:\n        plt.savefig(output+'_histo_{}.pdf'.format(label))\n        plt.clf()\n    else:\n        plt.show()\n    return\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(description='Plot time serie graphs from '\n                                     'stats outputs, type -h for more options')\n    parser.add_argument('json', help='stats json file')\n    parser.add_argument('-d', '--dir', help='output dir', default='.')\n    parser.add_argument('-o', '--output',\n                        help='output name (withouth extension name)',\n                        default='dramsim')\n    parser.add_argument('-k', '--key',\n                        help='plot a specific key name in epoch stats, '\n                        'use the name in JSON')\n    args = parser.parse_args()\n\n    with open(args.json, 'r') as j_file:\n        is_epoch = False\n        try:\n            j_data = json.load(j_file)\n        except:\n            print('cannot load file ' + args.json)\n            exit(1)\n        if isinstance(j_data, list):\n            is_epoch = True\n        else:\n            is_epoch = False\n\n    prefix = os.path.join(args.dir, args.output)\n    if is_epoch:\n        data_units = {'average_bandwidth': 'GB/s',\n                      'average_power': 'mW',\n                      'average_read_latency': 'cycles'}\n        if args.key:\n            data_units[args.key] = ''\n        for label, unit in data_units.items():\n            plot_epochs(j_data, label, unit, prefix)\n    else:\n        data_units = {'read_latency': 'cycles',\n                      'write_latency': 'cycles',\n                      'interarrival_latency': 'cycles'}\n        for label, unit in data_units.items():\n            plot_histogram(j_data, label, unit, prefix)\n"
  },
  {
    "path": "src/DRAMsim3/scripts/trace_gen.py",
    "content": "#!/usr/bin/env python3\n\nimport argparse\nimport os\nimport random\n\n\nclass Generator():\n    \"\"\"\n    Format agnostic address stream generator\n    \"\"\"\n\n    def __init__(self, stream_type, interarrival, ratio, gb):\n        # convert to 0 ~ 1 for easier random generation\n        self._interval = interarrival\n        self._ratio = ratio / (ratio + 1.0)\n\n        self._gen = None\n\n        self._range = gb * (2 ** 30)\n        self._last_clk = 0\n        self._last_rd_addr = random.randrange(self._range)\n        self._last_wr_addr = random.randrange(self._range)\n        if stream_type == 'random':\n            self._gen = self._rand_gen\n        elif stream_type == 'stream':\n            self._gen = self._stream_gen\n        else:\n            self._gen = self._mix_gen\n\n    def _get_op(self):\n        if random.random() > self._ratio:\n            return 'w'\n        else:\n            return 'r'\n\n    def _rand_gen(self):\n        addr = random.randrange(self._range)\n        op = self._get_op()\n        return (op, addr)\n\n    def _stream_gen(self):\n        op = self._get_op()\n        if op == 'r':\n            self._last_rd_addr += 64\n            return (op, self._last_rd_addr)\n        else:\n            self._last_wr_addr += 64\n            return (op, self._last_wr_addr)\n\n    def _mix_gen(self):\n        if random.random() > 0.5:\n            return self._rand_gen()\n        else:\n            return self._stream_gen()\n\n    def gen(self):\n        op, addr = self._gen()\n        self._last_clk += self._interval\n        return (op, addr, self._last_clk)\n\n\ndef get_string(op, addr, clk, trace_format, interarrival):\n    op_map = {\n        'r': {\n            'dramsim2': 'READ',\n            'dramsim3': 'READ',\n            'ramulator': 'R',\n            'usimm': 'R',\n            'drsim': 'READ'\n        },\n        'w': {\n            'dramsim2': 'WRITE',\n            'dramsim3': 'WRITE',\n            'ramulator': 'W',\n            'usimm': 'W',\n            'drsim': 'WRITE'\n        }\n    }\n    actual_op = op_map[op][trace_format]\n    if 'dramsim' in trace_format:\n        return '{} {} {}\\n'.format(hex(addr), actual_op, clk)\n    elif 'ramulator' == trace_format:\n        return '{} {}\\n'.format(hex(addr), actual_op)\n    elif 'usimm' == trace_format:\n        # USIMM assumes a 3.2GHz CPU by default, we hard code it here...\n        # also use clk for pc for convinience\n        if actual_op == 'R':\n            return '{} {} {} 0x0\\n'.format(interarrival, actual_op, hex(addr))\n        else:\n            return '{} {} {}\\n'.format(interarrival, actual_op, hex(addr))\n    elif 'drsim' == trace_format:\n        return '{} {} {} 64B\\n'.format(hex(addr), actual_op, clk)\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(\n        description=\"Trace Generator for Various DRAM Simulators\",\n        formatter_class=argparse.ArgumentDefaultsHelpFormatter)\n    parser.add_argument('-s', '--stream-type', default='random',\n                        help='Address stream type, (r)andom, (s)tream, (m)ix')\n    parser.add_argument('-i', '--interarrival',\n                        help='Inter-arrival time in cycles',\n                        type=int, default=10)\n    parser.add_argument('-f', '--format', default='all',\n                        help='Trace format, dramsim2, dramsim3,'\n                        'ramulator, usimm, drsim, or all')\n    parser.add_argument(\"-o\", \"--output-dir\",\n                        help=\"output directory\", default=\".\")\n    parser.add_argument('-r', '--ratio', type=float, default=2,\n                        help='Read to write(1) ratio')\n    parser.add_argument('-n', '--num-reqs', type=int, default=100,\n                        help='Total number of requests.')\n    parser.add_argument('-g', '--gb', type=int, default=4,\n                        help='GBs of address space')\n\n    args = parser.parse_args()\n\n    if not os.path.exists(args.output_dir):\n        try:\n            os.mkdir(args.output_dir)\n        except (OSError, ValueError) as e:\n            print('Cannot use output path:' + args.output_dir)\n            print(e)\n            exit(1)\n    print(\"Output directory: \", args.output_dir)\n\n    stream_types = {'r': 'random', 'random': 'random',\n                    's': 'stream', 'stream': 'stream',\n                    'm': 'mix', 'mix': 'mix'}\n    stream_type = stream_types.get(args.stream_type, 'random')\n    print(\"Address stream type: \", stream_type)\n\n    formats = ['dramsim2', 'dramsim3', 'ramulator', 'usimm', 'drsim']\n    if args.format != 'all':\n        formats = [args.format]\n    print(\"Trace format(s):\", formats)\n\n    files = {}\n    for f in formats:\n        file_name = '{}_{}_i{}_n{}_rw{}.trace'.format(\n            f, stream_type, args.interarrival, args.num_reqs, int(args.ratio))\n        if f == 'dramsim2':\n            file_name = 'mase_' + file_name\n        print(\"Write to file: \", file_name)\n        files[f] = os.path.join(args.output_dir, file_name)\n\n    # open files\n    for f, name in files.items():\n        fp = open(name, 'w')\n        files[f] = fp\n\n    g = Generator(stream_type, args.interarrival, args.ratio, args.gb)\n    for i in range(args.num_reqs):\n        op, addr, clk = g.gen()\n        for f in formats:\n            line = get_string(op, addr, clk, f, args.interarrival)\n            files[f].write(line)\n"
  },
  {
    "path": "src/DRAMsim3/scripts/validation.py",
    "content": "#!/usr/bin/env python3\nimport os\nimport sys\nimport parse_config\n\nclass Command(object):\n    \"\"\"\n    providing a data structure to\n    conveniently convert the format from simulator output to the verilog format\n    \"\"\"\n    def __init__(self, line):\n        elements = line.split()\n        assert len(elements) == 8, \"each line has to be in the format of \"\\\n                                   \"clk cmd chan rank bankgroup bank row col\"\n        self.clk = int(elements[0])\n        self.cmd = elements[1]\n        self.chan = int(elements[2])\n        self.rank = int(elements[3])\n        self.bankgroup = int(elements[4])\n        self.bank = int(elements[5])\n        self.row = int(elements[6], 16)\n        self.col = int(elements[7], 16)\n\n    def get_ddr4_str(self):\n        \"\"\"\n        get a command line for verilog model workbench\n        \"\"\"\n        if self.cmd == \"activate\":\n            return \"activate(.bg(%d), .ba(%d), .row(%d));\\n\" % (self.bankgroup, self.bank, self.row)\n        elif self.cmd == \"read\":  # ap=0 no auto precharge, bc=1 NO burst chop, weird...\n            return \"read(.bg(%d), .ba(%d), .col(%d), .ap(0), .bc(1));\\n\" % \\\n                   (self.bankgroup, self.bank, self.col)\n        elif self.cmd == \"read_p\":\n            return \"read(.bg(%d), .ba(%d), .col(%d), .ap(1), .bc(1));\\n\" % \\\n                   (self.bankgroup, self.bank, self.col)\n        elif self.cmd == \"write\":\n            return \"write(.bg(%d), .ba(%d), .col(%d), .ap(0), .bc(1));\\n\" % \\\n                   (self.bankgroup, self.bank, self.col)\n        elif self.cmd == \"write_p\":\n            return \"write(.bg(%d), .ba(%d), .col(%d), .ap(1), .bc(1));\\n\" % \\\n                   (self.bankgroup, self.bank, self.col)\n        elif self.cmd == \"precharge\":\n            return \"precharge(.bg(%d), .ba(%d), .ap(0));\\n\" % \\\n                   (self.bankgroup, self.bank)\n        elif self.cmd == \"refresh\" or self.cmd == \"refresh_bank\":\n            return \"refresh();\\n\"  # currently the verilog model doesnt do bank refresh\n        return\n\n    def get_ddr3_str(self):\n        \"\"\"\n        get a command line for verilog model workbench\n        \"\"\"\n        if self.cmd == \"activate\":\n            return \"activate(%d, %d);\\n\" % (self.bank, self.row)\n        elif self.cmd == \"read\":\n            return \"read(%d, %d, %d, %d);\\n\" % (self.bank, self.col, 0, 1)\n        elif self.cmd == \"read_p\":\n            return \"read(%d, %d, %d, %d);\\n\" % (self.bank, self.col, 1, 1)\n        elif self.cmd == \"write\":\n            return \"write(%d, %d, %d, %d, %d, %d);\\n\" % (self.bank, self.col, 0, 1, 0, 0xdeadbeaf)\n        elif self.cmd == \"write_p\":\n            return \"write(%d, %d, %d, %d, %d, %d);\\n\" % (self.bank, self.col, 1, 1, 0, 0xdeadbeaf)\n        elif self.cmd == \"refresh\":\n            return \"refresh;\\n\"\n        elif self.cmd == \"precharge\":\n            return \"precharge(%d, %d);\\n\" % (self.bank, 0)\n\n    def get_drampower_str(self, config):\n        \"\"\"\n        translate to generate command trace that DRAMPower can take as input\n        to validate power calculation, but\n        we need to know the config in order to calculate bank number\n        \"\"\"\n        str_map = {\n            \"activate\": \"ACT\",\n            \"read\": \"RD\",\n            \"read_p\": \"RDA\",\n            \"write\": \"WR\",\n            \"write_p\": \"WRA\",\n            \"precharge\": \"PRE\",\n            \"refresh\": \"REF\"\n        }\n        cmd_str = str_map[self.cmd]\n        bank_num = self.bankgroup * config[\"dram_structure\"][\"banks_per_group\"] + self.bank\n        return \"%d,%s,%d\\n\" % (self.clk, cmd_str, bank_num)\n\ndef calculate_megs_per_device(config):\n    \"\"\"\n    given config dict, calculate device density in Mbits\n    \"\"\"\n    rows = config[\"dram_structure\"][\"rows\"]\n    cols = config[\"dram_structure\"][\"columns\"]\n    width = config[\"dram_structure\"][\"device_width\"]\n    bgs = config[\"dram_structure\"][\"bankgroups\"]\n    banks_per_group = config[\"dram_structure\"][\"banks_per_group\"]\n    banks = bgs * banks_per_group\n    bytes_per_bank = rows * cols * width\n    mega_bytes_per_device = bytes_per_bank * banks / 1024 /1024\n    return mega_bytes_per_device\n\n\nclass DRAMValidation(object):\n    \"\"\"\n    Base class for validation\n    \"\"\"\n    def __init__(self, config_file_name, trace_file_name, script_name=\"\", verilog_output=\"\"):\n        \"\"\"\n        Need to specify config ini file and trace file upon creation\n        \"\"\"\n        if (not os.path.exists(config_file_name)) or \\\n           (not os.path.exists(trace_file_name)):\n            print(\"config file or path file does not exist!\")\n            exit(1)\n\n        if verilog_output:\n            self.verilog_out = verilog_output\n        else:\n            self.verilog_out = trace_file_name + \".vh\"\n\n        if script_name:\n            self.script_out = script_name\n        else:\n            self.script_out = \"\"\n\n        self.drampower_out = self.verilog_out[:-3] + \".power.trc\"\n\n        self.configs = parse_config.get_dict(config_file_name)\n\n        trace_in = open(trace_file_name, \"r\")\n\n        self.commands = trace_in.readlines()\n\n    def get_prefix_str(self):\n        pass\n\n    def get_postfix_str(self):\n        postfix_str = \"\"\"\n            test_done;\n        end\n        \"\"\"\n        return postfix_str\n\n    def generate_modelsim_script(self, script_name=\"\"):\n        pass\n\n    def generate_verilog_bench(self, bench_name=\"\"):\n        pass\n\n    def generate_drampower_trace(self):\n        with open(self.drampower_out, \"w\") as fp:\n            for cmd_str in self.commands:\n                cmd = Command(cmd_str)\n                fp.write(cmd.get_drampower_str(self.configs))\n        return\n\n\n    def validation(self):\n        self.generate_modelsim_script(self.script_out)\n        self.generate_verilog_bench(self.verilog_out)\n        self.generate_drampower_trace()\n\n\nclass DDR3Validation(DRAMValidation):\n\n    def get_prefix_str(self):\n        \"\"\"\n        setting up the workbench initialization\n        \"\"\"\n        al = self.configs[\"timing\"][\"al\"]\n        cl = self.configs[\"timing\"][\"cl\"]\n\n        if al == 0:\n            mod_1_str = \"b0000000110\"\n        elif al == (cl - 1):\n            mod_1_str = \"b0000001110\"\n        elif al == (cl - 2):\n            mod_1_str = \"b0000010110\"\n        else:\n            mod_1_str = \"b0000000110\"\n            print(\"Invalid AL/CL values!\")\n            exit(1)\n\n        prefix_str = \"\"\"\n        initial begin : test\n            parameter [31:0] REP = DQ_BITS/8.0;\n            reg         [BA_BITS-1:0] r_bank;\n            reg        [ROW_BITS-1:0] r_row;\n            reg        [COL_BITS-1:0] r_col;\n            reg  [BL_MAX*DQ_BITS-1:0] r_data;\n            integer                   r_i, r_j;\n            real original_tck;\n            reg [8*DQ_BITS-1:0] d0, d1, d2, d3;\n            d0 = {\n            {REP{8'h07}}, {REP{8'h06}}, {REP{8'h05}}, {REP{8'h04}},\n            {REP{8'h03}}, {REP{8'h02}}, {REP{8'h01}}, {REP{8'h00}}\n            };\n            d1 = {\n            {REP{8'h17}}, {REP{8'h16}}, {REP{8'h15}}, {REP{8'h14}},\n            {REP{8'h13}}, {REP{8'h12}}, {REP{8'h11}}, {REP{8'h10}}\n            };\n            d2 = {\n            {REP{8'h27}}, {REP{8'h26}}, {REP{8'h25}}, {REP{8'h24}},\n            {REP{8'h23}}, {REP{8'h22}}, {REP{8'h21}}, {REP{8'h20}}\n            };\n            d3 = {\n            {REP{8'h37}}, {REP{8'h36}}, {REP{8'h35}}, {REP{8'h34}},\n            {REP{8'h33}}, {REP{8'h32}}, {REP{8'h31}}, {REP{8'h30}}\n            };\n            rst_n   <=  1'b0;\n            cke     <=  1'b0;\n            cs_n    <=  1'b1;\n            ras_n   <=  1'b1;\n            cas_n   <=  1'b1;\n            we_n    <=  1'b1;\n            ba      <=  {BA_BITS{1'bz}};\n            a       <=  {ADDR_BITS{1'bz}};\n            odt_out <=  1'b0;\n            dq_en   <=  1'b0;\n            dqs_en  <=  1'b0;\n            // POWERUP SECTION\n            power_up;\n            // INITIALIZE SECTION\n            zq_calibration  (1);                            // perform Long ZQ Calibration\n            load_mode       (3, 14'b00000000000000);        // Extended Mode Register (3)\n            nop             (tmrd-1);\n            load_mode       (2, {14'b00001000_000_000} | mr_cwl<<3); // Extended Mode Register 2 with DCC Disable\n            nop             (tmrd-1);\n            load_mode       (1, 14'%s);            // Extended Mode Register with DLL Enable\n            nop             (tmrd-1);\n            load_mode       (0, {14'b0_1_000_1_0_000_1_0_00} | mr_wr<<9 | mr_cl<<2); // Mode Register with DLL Reset\n            nop             (683);  // make sure tDLLK and tZQINIT satisify\n            odt_out         <= 0;                           // turn off odt, making life much easier...\n            nop (7);\n            \"\"\" % (mod_1_str)\n        return prefix_str\n\n    def generate_modelsim_script(self, script_name=\"\"):\n        if not self.script_out:\n            self.script_out = \"run_modelsim_ddr3.sh\"\n\n        megs = calculate_megs_per_device(self.configs)\n        if megs == 1024:\n            density = \"den1024Mb\"\n        elif megs == 2048:\n            density = \"den2048Mb\"\n        elif megs == 4096:\n            density = \"den4096Mb\"\n        elif megs == 8192:\n            density = \"den8192Mb\"\n        else:\n            print(\"unknown device density: %d! MBs\" % (megs))\n            exit(1)\n        width = self.configs[\"dram_structure\"][\"device_width\"]\n        tck = self.configs[\"timing\"][\"tck\"]\n        speed_table = {  # based on 1Gb device\n            0.938: \"sg093\",  # 2133\n            1.07 : \"sg107\",  # 1866\n            1.25 : \"sg125\", # 1600\n            1.50 : \"sg15\",  # 1333J, there is also sg15E\n            1.875: \"sg187\", # 1066G, there is also sg187E\n            2.5:   \"sg25\",  # 800, there is also sg25E\n        }\n        if tck not in speed_table.keys():\n            print(\"Invalid tCK value in ini file, use the followings for DDR3:\" +\\\n                str([k for k in speed_table]))\n        speed = speed_table[tck]\n\n        # generate script to run modelsim simulation in command line mode\n        # note this will generate a run_modelsim.sh script file\n        # also a v_out.log file after running the script\n        cmd_str = \\\n        \"\"\"\n        vlib work\n        vlog -quiet -suppress 2597 +define+%s +define+x%d +define+%s tb.v ddr3.v\n        vsim -quiet -nostdout -c -l v_out.log -novopt tb -do \"run -all\"\n\n        \"\"\" % (density, width, speed)\n\n        with open(self.script_out, \"w\") as fp:\n            fp.write(cmd_str)\n        return\n\n    def generate_verilog_bench(self, bench_name=\"\"):\n        with open(self.verilog_out, \"w\") as fp:\n            # write prefix that initializes device\n            fp.write(self.get_prefix_str())\n\n            # convert trace file\n            last_clk = 0\n            for cmd_str in self.commands:\n                cmd = Command(cmd_str)\n                this_clk = cmd.clk\n                nop_cycles = this_clk - last_clk - 1\n                if nop_cycles > 0:\n                    nop_str = \"nop(%d);\\n\" % nop_cycles\n                    fp.write(nop_str)\n                last_clk = this_clk\n                fp.write(cmd.get_ddr3_str())\n\n            # finishing up\n            fp.write(self.get_postfix_str())\n        return\n\n\nclass DDR4Validation(DRAMValidation):\n\n    def get_prefix_str(self):\n        \"\"\"\n        this is necessary for setting up a verilog workbench\n        depending on the config, some of the values in this string will change correspondingly\n        \"\"\"\n        ts_table = {  # tCK -> [min_ts, nominal_ts, max_ts]\n            1.875: [\"TS_1875\", \"TS_1875\", \"TS_1875\"],  # 1066MHz\n            1.500: [\"TS_1500\", \"TS_1500\", \"TS_1875\"],  # 1333MHz\n            1.250: [\"TS_1250\", \"TS_1250\", \"TS_1500\"],  # 1600MHz\n            1.072: [\"TS_1072\", \"TS_1072\", \"TS_1250\"],  # 1866MHz\n            0.938: [\"TS_938\", \"TS_938\", \"TS_1072\"],    # 2133MHz\n            0.833: [\"TS_833\", \"TS_833\", \"TS_938\"],     # 2400MHz\n            0.750: [\"TS_750\", \"TS_750\", \"TS_833\"],     # 2667MHz\n            0.682: [\"TS_682\", \"TS_682\", \"TS_750\"],     # 2934MHz\n            0.625: [\"TS_625\", \"TS_625\", \"TS_682\"]      # 3200MHz\n        }\n        ts = self.configs[\"timing\"][\"tck\"]\n        if ts not in ts_table.keys():\n            print(\"Invalid tCK value in ini file, use the followings for DDR4:\" +\\\n                str([k for k in ts_table]))\n        ddr4_prefix_str = \"\"\"\n        initial begin : test\n                UTYPE_TS min_ts, nominal_ts, max_ts;\n                reg [MAX_BURST_LEN*MAX_DQ_BITS-1:0] b0to7, b8tof, b7to0, bfto8;\n                reg [MODEREG_BITS-1:0] mode_regs[MAX_MODEREGS];\n                UTYPE_DutModeConfig dut_mode_config;\n                bit failure;\n        min_ts = %s;\n        nominal_ts = %s;\n        max_ts = %s;\n        b0to7 = { {MAX_DQ_BITS/4{4'h7}}, {MAX_DQ_BITS/4{4'h6}}, {MAX_DQ_BITS/4{4'h5}}, {MAX_DQ_BITS/4{4'h4}},\n                    {MAX_DQ_BITS/4{4'h3}}, {MAX_DQ_BITS/4{4'h2}}, {MAX_DQ_BITS/4{4'h1}}, {MAX_DQ_BITS/4{4'h0}} };\n        b8tof = { {MAX_DQ_BITS/4{4'hf}}, {MAX_DQ_BITS/4{4'he}}, {MAX_DQ_BITS/4{4'hd}}, {MAX_DQ_BITS/4{4'hc}},\n                    {MAX_DQ_BITS/4{4'hb}}, {MAX_DQ_BITS/4{4'ha}}, {MAX_DQ_BITS/4{4'h9}}, {MAX_DQ_BITS/4{4'h8}} };\n        b7to0 = { {MAX_DQ_BITS/4{4'h0}}, {MAX_DQ_BITS/4{4'h1}}, {MAX_DQ_BITS/4{4'h2}}, {MAX_DQ_BITS/4{4'h3}},\n                    {MAX_DQ_BITS/4{4'h4}}, {MAX_DQ_BITS/4{4'h5}}, {MAX_DQ_BITS/4{4'h6}}, {MAX_DQ_BITS/4{4'h7}} };\n        bfto8 = { {MAX_DQ_BITS/4{4'h8}}, {MAX_DQ_BITS/4{4'h9}}, {MAX_DQ_BITS/4{4'ha}}, {MAX_DQ_BITS/4{4'hb}},\n                    {MAX_DQ_BITS/4{4'hc}}, {MAX_DQ_BITS/4{4'hd}}, {MAX_DQ_BITS/4{4'he}}, {MAX_DQ_BITS/4{4'hf}} };\n        iDDR4.RESET_n <= 1'b1;\n        iDDR4.CKE <= 1'b0;\n        iDDR4.CS_n  <= 1'b1;\n        iDDR4.ACT_n <= 1'b1;\n        iDDR4.RAS_n_A16 <= 1'b1;\n        iDDR4.CAS_n_A15 <= 1'b1;\n        iDDR4.WE_n_A14 <= 1'b1;\n        iDDR4.BG <= '1;\n        iDDR4.BA <= '1;\n        iDDR4.ADDR <= '1;\n        iDDR4.ADDR_17 <= '0;\n        iDDR4.ODT <= 1'b0;\n        iDDR4.PARITY <= 0;\n        iDDR4.ALERT_n <= 1;\n        iDDR4.PWR <= 0;\n        iDDR4.TEN <= 0;\n        iDDR4.VREF_CA <= 0;\n        iDDR4.VREF_DQ <= 0;\n        iDDR4.ZQ <= 0;\n        dq_en <= 1'b0;\n        dqs_en <= 1'b0;\n        default_period(nominal_ts);\n        // POWERUP SECTION\n        power_up();\n        // Reset DLL\n        dut_mode_config = _state.DefaultDutModeConfig(.cl(%d),\n                                                        .write_recovery(%d),\n                                                        .qoff(0),\n                                                        .cwl(%d),\n                                                        .rd_preamble_clocks(%d),\n                                                        .wr_preamble_clocks(%d),\n                                                        .read_dbi(0),\n                                                        .write_dbi(0),\n                                                        .bl_reg(rBL8),\n                                                        .dll_enable(1),\n                                                        .dll_reset(1),\n                                                        .dm_enable(0));\n        dut_mode_config.AL = 0;\n        dut_mode_config.BL = 8;\n        _state.ModeToAddrDecode(dut_mode_config, mode_regs);\n        load_mode(.bg(0), .ba(1), .addr(mode_regs[1]));\n        deselect(timing.tDLLKc);\n        dut_mode_config.DLL_reset = 0;\n        _state.ModeToAddrDecode(dut_mode_config, mode_regs);\n        load_mode(.bg(0), .ba(3), .addr(mode_regs[3]));\n        deselect(timing.tMOD/timing.tCK);\n        load_mode(.bg(1), .ba(2), .addr(mode_regs[6]));\n        deselect(timing.tMOD/timing.tCK);\n        load_mode(.bg(1), .ba(1), .addr(mode_regs[5]));\n        deselect(timing.tMOD/timing.tCK);\n        load_mode(.bg(1), .ba(0), .addr(mode_regs[4]));\n        deselect(timing.tMOD/timing.tCK);\n        load_mode(.bg(0), .ba(2), .addr(mode_regs[2]));\n        deselect(timing.tMOD/timing.tCK);\n        load_mode(.bg(0), .ba(1), .addr(mode_regs[1]));\n        deselect(timing.tMOD/timing.tCK);\n        load_mode(.bg(0), .ba(0), .addr(mode_regs[0]));\n        deselect(timing.tMOD/timing.tCK);\n        zq_cl();\n        deselect(timing.tZQinitc);\n        odt_out <= 0;                           // turn off odt\n\n        golden_model.SetDutModeConfig(dut_mode_config);\n        golden_model.set_timing_parameter_lock(.locked(1), .recalculate_params(1), .non_spec_tck(%s)); // Prevent tCK changes from changing the loaded timeset.\n        \"\"\" % (ts_table[ts][0],  # min_ts, not used\n               ts_table[ts][1],\n               ts_table[ts][2],  # max_ts, not used\n               self.configs[\"timing\"][\"cl\"],\n               self.configs[\"timing\"][\"twr\"] + 1,  # have to + 1 to make verilog model happy..\n               self.configs[\"timing\"][\"cwl\"],\n               self.configs[\"timing\"][\"trpre\"],\n               self.configs[\"timing\"][\"twpre\"],\n               ts_table[ts][1][3:],  # non_spec_tck, throw away TS_ and only leaves clock\n              )\n        return ddr4_prefix_str\n\n    def generate_modelsim_script(self, script_name=\"\"):\n        \"\"\"\n        This function should:\n        - generate a verilog file for the validation workbench\n        - generate the command based on the config file\n        \"\"\"\n        if not self.script_out:\n            self.script_out = \"run_modelsim_ddr4.sh\"\n\n        dev_str = \"DDR4_\"\n        megs = calculate_megs_per_device(self.configs)\n        if megs == 4096:\n            density = \"4G\"\n        elif megs == 8192:\n            density = \"8G\"\n        elif megs == 16384:\n            density = \"16G\"\n        else:\n            print(\"unknown device density: %d! MBs\" % (megs))\n            exit(1)\n\n        width = self.configs[\"dram_structure\"][\"device_width\"]\n\n        dev_str = dev_str + density + \"_X\" + str(width)  # should be something like DDR4_8G_X8\n\n        vlib_str = \"vlib work\\n\"\n        cmd_str = \"vlog -quiet -suppress 2597 -work work +acc -l vcs.log -novopt -sv \"\\\n                  \"+define+%s arch_package.sv proj_package.sv \" \\\n                  \"interface.sv StateTable.svp MemoryArray.svp ddr4_model.svp tb.sv \\n\" % dev_str\n        vsim_str = \"vsim -quiet -nostdout -c -l v_out.log -novopt tb -do \\\"run -all\\\"\\n\"\n\n        with open(self.script_out, \"w\") as fp:\n            fp.write(vlib_str)\n            fp.write(cmd_str)\n            fp.write(vsim_str)\n        return\n\n    def generate_verilog_bench(self, bench_name=\"\"):\n        with open(self.verilog_out, \"w\") as fp:\n            # write prefix that initializes device\n            fp.write(self.get_prefix_str())\n\n            # convert trace file\n            last_clk = 0\n            for cmd_str in self.commands:\n                cmd = Command(cmd_str)\n                this_clk = cmd.clk\n                nop_cycles = this_clk - last_clk - 1\n                if nop_cycles > 0:\n                    nop_str = \"deselect(%d);\\n\" % nop_cycles\n                    fp.write(nop_str)\n                last_clk = this_clk\n                fp.write(cmd.get_ddr4_str())\n\n            # finishing up\n            fp.write(self.get_postfix_str())\n        return\n\n\nclass LPDDRValidtion(DRAMValidation):\n\n    def get_prefix_str(self):\n        cl = self.configs[\"timing\"][\"cl\"]\n        bl = self.configs[\"dram_structure\"][\"bl\"]\n\n        if bl == 2:\n            bl_bits = \"001\"\n        elif bl == 4:\n            bl_bits = \"010\"\n        elif bl == 8:\n            bl_bits = \"011\"\n        else:  # BL=16\n            bl_bits = \"100\"\n\n        if cl == 2:\n            cl_bits = \"10\"\n        else:\n            cl_bits = \"11\"\n\n        prefix = \"\"\"\n        initial begin:test\n        //ck     <= 1'b0;\n        cke    <= 1'b0;\n        cs_n   <= 1'bz;\n        ras_n  <= 1'bz;\n        cas_n  <= 1'bz;\n        we_n   <= 1'bz;\n        a      <= {ADDR_BITS{1'bz}};\n        ba     <= {BA_BITS{1'bz}};\n        dq_en  <= 1'b0;\n        dqs_en <= 1'b0;\n        power_up;\n        nop (10); // wait 10 clocks intead of 200 us for simulation purposes\n        precharge('h00000000, 1);\n        nop(trp);\n        refresh;\n        nop(trfc);\n        refresh;\n        nop(trfc);\n        load_mode('h0, 'b0%s_0_%s); // setting CL and BL correctly\n        nop(tmrd);\n        load_mode('h2, 'b0);\n        nop(tmrd);\n        \"\"\" % (cl_bits, bl_bits)\n        return prefix\n\n    def generate_modelsim_script(self, script_name=\"\"):\n        if not self.script_out:\n            self.script_out = \"run_modelsim_lpddr.sh\"\n        megs = calculate_megs_per_device(self.configs)\n        density = \"den%dMb\" % megs\n        tck = self.configs[\"timing\"][\"tck\"]\n        speed_table = {  # based on 1Gb device\n            4.8: \"sg5\",\n            5.4 : \"sg54\",\n            6.0 : \"sg6\",\n            7.5 : \"sg75\",\n        }\n        if tck not in speed_table.keys():\n            print(\"Invalid tCK value in ini file, use the followings for DDR3:\" +\\\n                str([k for k in speed_table]))\n        speed = speed_table[tck]\n        width = self.configs[\"dram_structure\"][\"device_width\"]\n        cmd_str = \\\n        \"\"\"\n        vlib work\n        vlog -quiet -suppress 2597 +define+%s +define+%s +define+x%d tb.v mobile_ddr.v\n        vsim -quiet -nostdout -c -l v_out.log -novopt tb -do \"run -all\"\n        \"\"\" % (density, speed, width)\n\n        with open(self.script_out, \"w\") as fp:\n            fp.write(cmd_str)\n        return\n\n    def generate_verilog_bench(self, bench_name=\"\"):\n        with open(self.verilog_out, \"w\") as fp:\n            # write prefix that initializes device\n            fp.write(self.get_prefix_str())\n\n            # convert trace file\n            last_clk = 0\n            for cmd_str in self.commands:\n                cmd = Command(cmd_str)\n                this_clk = cmd.clk\n                nop_cycles = this_clk - last_clk - 1\n                if nop_cycles > 0:\n                    nop_str = \"nop(%d);\\n\" % nop_cycles\n                    fp.write(nop_str)\n                last_clk = this_clk\n                fp.write(cmd.get_ddr3_str())\n\n            # finishing up\n            fp.write(self.get_postfix_str())\n        return\n\n\nif __name__ == \"__main__\":\n    assert len(sys.argv) == 3, \"Need 2 arguments, 1. config file name  2. command trace file name\"\n\n    if not (os.path.exists(sys.argv[1]) and os.path.exists(sys.argv[2])):\n        print(\"cannot locate input files, please check your input file name and path\")\n        exit(1)\n\n    ini_file = sys.argv[1]\n    cmd_trace_file = sys.argv[2]\n\n    configs = parse_config.get_dict(ini_file)\n\n    validation = None\n    if configs[\"dram_structure\"][\"protocol\"] == \"DDR4\":\n        validation = DDR4Validation(ini_file, cmd_trace_file)\n    elif configs[\"dram_structure\"][\"protocol\"] == \"DDR3\":\n        validation = DDR3Validation(ini_file, cmd_trace_file)\n    elif configs[\"dram_structure\"][\"protocol\"] == \"LPDDR\":\n        validation = LPDDRValidtion(ini_file, cmd_trace_file)\n    else:\n        pass\n\n    validation.validation()\n\n\n\n\n\n"
  },
  {
    "path": "src/DRAMsim3/src/bankstate.cc",
    "content": "#include \"bankstate.h\"\n\nnamespace dramsim3 {\n\nBankState::BankState()\n    : state_(State::CLOSED),\n      cmd_timing_(static_cast<int>(CommandType::SIZE)),\n      open_row_(-1),\n      row_hit_count_(0) {\n    cmd_timing_[static_cast<int>(CommandType::READ)] = 0;\n    cmd_timing_[static_cast<int>(CommandType::READ_PRECHARGE)] = 0;\n    cmd_timing_[static_cast<int>(CommandType::WRITE)] = 0;\n    cmd_timing_[static_cast<int>(CommandType::WRITE_PRECHARGE)] = 0;\n    cmd_timing_[static_cast<int>(CommandType::ACTIVATE)] = 0;\n    cmd_timing_[static_cast<int>(CommandType::PRECHARGE)] = 0;\n    cmd_timing_[static_cast<int>(CommandType::REFRESH)] = 0;\n    cmd_timing_[static_cast<int>(CommandType::SREF_ENTER)] = 0;\n    cmd_timing_[static_cast<int>(CommandType::SREF_EXIT)] = 0;\n}\n\n\nCommand BankState::GetReadyCommand(const Command& cmd, uint64_t clk) const {\n    CommandType required_type = CommandType::SIZE;\n    switch (state_) {\n        case State::CLOSED:\n            switch (cmd.cmd_type) {\n                case CommandType::READ:\n                case CommandType::READ_PRECHARGE:\n                case CommandType::WRITE:\n                case CommandType::WRITE_PRECHARGE:\n                    required_type = CommandType::ACTIVATE;\n                    break;\n                case CommandType::REFRESH:\n                case CommandType::REFRESH_BANK:\n                case CommandType::SREF_ENTER:\n                    required_type = cmd.cmd_type;\n                    break;\n                default:\n                    std::cerr << \"Unknown type!\" << std::endl;\n                    AbruptExit(__FILE__, __LINE__);\n                    break;\n            }\n            break;\n        case State::OPEN:\n            switch (cmd.cmd_type) {\n                case CommandType::READ:\n                case CommandType::READ_PRECHARGE:\n                case CommandType::WRITE:\n                case CommandType::WRITE_PRECHARGE:\n                    if (cmd.Row() == open_row_) {\n                        required_type = cmd.cmd_type;\n                    } else {\n                        required_type = CommandType::PRECHARGE;\n                    }\n                    break;\n                case CommandType::REFRESH:\n                case CommandType::REFRESH_BANK:\n                case CommandType::SREF_ENTER:\n                    required_type = CommandType::PRECHARGE;\n                    break;\n                default:\n                    std::cerr << \"Unknown type!\" << std::endl;\n                    AbruptExit(__FILE__, __LINE__);\n                    break;\n            }\n            break;\n        case State::SREF:\n            switch (cmd.cmd_type) {\n                case CommandType::READ:\n                case CommandType::READ_PRECHARGE:\n                case CommandType::WRITE:\n                case CommandType::WRITE_PRECHARGE:\n                    required_type = CommandType::SREF_EXIT;\n                    break;\n                default:\n                    std::cerr << \"Unknown type!\" << std::endl;\n                    AbruptExit(__FILE__, __LINE__);\n                    break;\n            }\n            break;\n        case State::PD:\n        case State::SIZE:\n            std::cerr << \"In unknown state\" << std::endl;\n            AbruptExit(__FILE__, __LINE__);\n            break;\n    }\n\n    if (required_type != CommandType::SIZE) {\n        if (clk >= cmd_timing_[static_cast<int>(required_type)]) {\n            return Command(required_type, cmd.addr, cmd.hex_addr);\n        }\n    }\n    return Command();\n}\n\nvoid BankState::UpdateState(const Command& cmd) {\n    switch (state_) {\n        case State::OPEN:\n            switch (cmd.cmd_type) {\n                case CommandType::READ:\n                case CommandType::WRITE:\n                    row_hit_count_++;\n                    break;\n                case CommandType::READ_PRECHARGE:\n                case CommandType::WRITE_PRECHARGE:\n                case CommandType::PRECHARGE:\n                    state_ = State::CLOSED;\n                    open_row_ = -1;\n                    row_hit_count_ = 0;\n                    break;\n                case CommandType::ACTIVATE:\n                case CommandType::REFRESH:\n                case CommandType::REFRESH_BANK:\n                case CommandType::SREF_ENTER:\n                case CommandType::SREF_EXIT:\n                default:\n                    AbruptExit(__FILE__, __LINE__);\n            }\n            break;\n        case State::CLOSED:\n            switch (cmd.cmd_type) {\n                case CommandType::REFRESH:\n                case CommandType::REFRESH_BANK:\n                    break;\n                case CommandType::ACTIVATE:\n                    state_ = State::OPEN;\n                    open_row_ = cmd.Row();\n                    break;\n                case CommandType::SREF_ENTER:\n                    state_ = State::SREF;\n                    break;\n                case CommandType::READ:\n                case CommandType::WRITE:\n                case CommandType::READ_PRECHARGE:\n                case CommandType::WRITE_PRECHARGE:\n                case CommandType::PRECHARGE:\n                case CommandType::SREF_EXIT:\n                default:\n                    std::cout << cmd << std::endl;\n                    AbruptExit(__FILE__, __LINE__);\n            }\n            break;\n        case State::SREF:\n            switch (cmd.cmd_type) {\n                case CommandType::SREF_EXIT:\n                    state_ = State::CLOSED;\n                    break;\n                case CommandType::READ:\n                case CommandType::WRITE:\n                case CommandType::READ_PRECHARGE:\n                case CommandType::WRITE_PRECHARGE:\n                case CommandType::ACTIVATE:\n                case CommandType::PRECHARGE:\n                case CommandType::REFRESH:\n                case CommandType::REFRESH_BANK:\n                case CommandType::SREF_ENTER:\n                default:\n                    AbruptExit(__FILE__, __LINE__);\n            }\n            break;\n        default:\n            AbruptExit(__FILE__, __LINE__);\n    }\n    return;\n}\n\nvoid BankState::UpdateTiming(CommandType cmd_type, uint64_t time) {\n    cmd_timing_[static_cast<int>(cmd_type)] =\n        std::max(cmd_timing_[static_cast<int>(cmd_type)], time);\n    return;\n}\n\n}  // namespace dramsim3\n"
  },
  {
    "path": "src/DRAMsim3/src/bankstate.h",
    "content": "#ifndef __BANKSTATE_H\n#define __BANKSTATE_H\n\n#include <vector>\n#include \"common.h\"\n\nnamespace dramsim3 {\n\nclass BankState {\n   public:\n    BankState();\n\n    enum class State { OPEN, CLOSED, SREF, PD, SIZE };\n    Command GetReadyCommand(const Command& cmd, uint64_t clk) const;\n\n    // Update the state of the bank resulting after the execution of the command\n    void UpdateState(const Command& cmd);\n\n    // Update the existing timing constraints for the command\n    void UpdateTiming(const CommandType cmd_type, uint64_t time);\n\n    bool IsRowOpen() const { return state_ == State::OPEN; }\n    int OpenRow() const { return open_row_; }\n    int RowHitCount() const { return row_hit_count_; }\n\n   private:\n    // Current state of the Bank\n    // Apriori or instantaneously transitions on a command.\n    State state_;\n\n    // Earliest time when the particular Command can be executed in this bank\n    std::vector<uint64_t> cmd_timing_;\n\n    // Currently open row\n    int open_row_;\n\n    // consecutive accesses to one row\n    int row_hit_count_;\n};\n\n}  // namespace dramsim3\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/channel_state.cc",
    "content": "#include \"channel_state.h\"\n\nnamespace dramsim3 {\nChannelState::ChannelState(const Config& config, const Timing& timing)\n    : rank_idle_cycles(config.ranks, 0),\n      config_(config),\n      timing_(timing),\n      rank_is_sref_(config.ranks, false),\n      four_aw_(config_.ranks, std::vector<uint64_t>()),\n      thirty_two_aw_(config_.ranks, std::vector<uint64_t>()) {\n    bank_states_.reserve(config_.ranks);\n    for (auto i = 0; i < config_.ranks; i++) {\n        auto rank_states = std::vector<std::vector<BankState>>();\n        rank_states.reserve(config_.bankgroups);\n        for (auto j = 0; j < config_.bankgroups; j++) {\n            auto bg_states =\n                std::vector<BankState>(config_.banks_per_group, BankState());\n            rank_states.push_back(bg_states);\n        }\n        bank_states_.push_back(rank_states);\n    }\n}\n\nbool ChannelState::IsAllBankIdleInRank(int rank) const {\n    for (int j = 0; j < config_.bankgroups; j++) {\n        for (int k = 0; k < config_.banks_per_group; k++) {\n            if (bank_states_[rank][j][k].IsRowOpen()) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\nbool ChannelState::IsRWPendingOnRef(const Command& cmd) const {\n    int rank = cmd.Rank();\n    int bankgroup = cmd.Bankgroup();\n    int bank = cmd.Bank();\n    return (IsRowOpen(rank, bankgroup, bank) &&\n            RowHitCount(rank, bankgroup, bank) == 0 &&\n            bank_states_[rank][bankgroup][bank].OpenRow() == cmd.Row());\n}\n\nvoid ChannelState::BankNeedRefresh(int rank, int bankgroup, int bank,\n                                   bool need) {\n    if (need) {\n        Address addr = Address(-1, rank, bankgroup, bank, -1, -1);\n        refresh_q_.emplace_back(CommandType::REFRESH_BANK, addr, -1);\n    } else {\n        for (auto it = refresh_q_.begin(); it != refresh_q_.end(); it++) {\n            if (it->Rank() == rank && it->Bankgroup() == bankgroup &&\n                it->Bank() == bank) {\n                refresh_q_.erase(it);\n                break;\n            }\n        }\n    }\n    return;\n}\n\nvoid ChannelState::RankNeedRefresh(int rank, bool need) {\n    if (need) {\n        Address addr = Address(-1, rank, -1, -1, -1, -1);\n        refresh_q_.emplace_back(CommandType::REFRESH, addr, -1);\n    } else {\n        for (auto it = refresh_q_.begin(); it != refresh_q_.end(); it++) {\n            if (it->Rank() == rank) {\n                refresh_q_.erase(it);\n                break;\n            }\n        }\n    }\n    return;\n}\n\nCommand ChannelState::GetReadyCommand(const Command& cmd, uint64_t clk) const {\n    Command ready_cmd = Command();\n    if (cmd.IsRankCMD()) {\n        int num_ready = 0;\n        for (auto j = 0; j < config_.bankgroups; j++) {\n            for (auto k = 0; k < config_.banks_per_group; k++) {\n                ready_cmd =\n                    bank_states_[cmd.Rank()][j][k].GetReadyCommand(cmd, clk);\n                if (!ready_cmd.IsValid()) {  // Not ready\n                    continue;\n                }\n                if (ready_cmd.cmd_type != cmd.cmd_type) {  // likely PRECHARGE\n                    Address new_addr = Address(-1, cmd.Rank(), j, k, -1, -1);\n                    ready_cmd.addr = new_addr;\n                    return ready_cmd;\n                } else {\n                    num_ready++;\n                }\n            }\n        }\n        // All bank ready\n        if (num_ready == config_.banks) {\n            return ready_cmd;\n        } else {\n            return Command();\n        }\n    } else {\n        ready_cmd = bank_states_[cmd.Rank()][cmd.Bankgroup()][cmd.Bank()]\n                        .GetReadyCommand(cmd, clk);\n        if (!ready_cmd.IsValid()) {\n            return Command();\n        }\n        if (ready_cmd.cmd_type == CommandType::ACTIVATE) {\n            if (!ActivationWindowOk(ready_cmd.Rank(), clk)) {\n                return Command();\n            }\n        }\n        return ready_cmd;\n    }\n}\n\nvoid ChannelState::UpdateState(const Command& cmd) {\n    if (cmd.IsRankCMD()) {\n        for (auto j = 0; j < config_.bankgroups; j++) {\n            for (auto k = 0; k < config_.banks_per_group; k++) {\n                bank_states_[cmd.Rank()][j][k].UpdateState(cmd);\n            }\n        }\n        if (cmd.IsRefresh()) {\n            RankNeedRefresh(cmd.Rank(), false);\n        } else if (cmd.cmd_type == CommandType::SREF_ENTER) {\n            rank_is_sref_[cmd.Rank()] = true;\n        } else if (cmd.cmd_type == CommandType::SREF_EXIT) {\n            rank_is_sref_[cmd.Rank()] = false;\n        }\n    } else {\n        bank_states_[cmd.Rank()][cmd.Bankgroup()][cmd.Bank()].UpdateState(cmd);\n        if (cmd.IsRefresh()) {\n            BankNeedRefresh(cmd.Rank(), cmd.Bankgroup(), cmd.Bank(), false);\n        }\n    }\n    return;\n}\n\nvoid ChannelState::UpdateTiming(const Command& cmd, uint64_t clk) {\n    switch (cmd.cmd_type) {\n        case CommandType::ACTIVATE:\n            UpdateActivationTimes(cmd.Rank(), clk);\n        case CommandType::READ:\n        case CommandType::READ_PRECHARGE:\n        case CommandType::WRITE:\n        case CommandType::WRITE_PRECHARGE:\n        case CommandType::PRECHARGE:\n        case CommandType::REFRESH_BANK:\n            // TODO - simulator speed? - Speciazlize which of the below\n            // functions to call depending on the command type  Same Bank\n            UpdateSameBankTiming(\n                cmd.addr, timing_.same_bank[static_cast<int>(cmd.cmd_type)],\n                clk);\n\n            // Same Bankgroup other banks\n            UpdateOtherBanksSameBankgroupTiming(\n                cmd.addr,\n                timing_\n                    .other_banks_same_bankgroup[static_cast<int>(cmd.cmd_type)],\n                clk);\n\n            // Other bankgroups\n            UpdateOtherBankgroupsSameRankTiming(\n                cmd.addr,\n                timing_\n                    .other_bankgroups_same_rank[static_cast<int>(cmd.cmd_type)],\n                clk);\n\n            // Other ranks\n            UpdateOtherRanksTiming(\n                cmd.addr, timing_.other_ranks[static_cast<int>(cmd.cmd_type)],\n                clk);\n            break;\n        case CommandType::REFRESH:\n        case CommandType::SREF_ENTER:\n        case CommandType::SREF_EXIT:\n            UpdateSameRankTiming(\n                cmd.addr, timing_.same_rank[static_cast<int>(cmd.cmd_type)],\n                clk);\n            break;\n        default:\n            AbruptExit(__FILE__, __LINE__);\n    }\n    return;\n}\n\nvoid ChannelState::UpdateSameBankTiming(\n    const Address& addr,\n    const std::vector<std::pair<CommandType, int>>& cmd_timing_list,\n    uint64_t clk) {\n    for (auto cmd_timing : cmd_timing_list) {\n        bank_states_[addr.rank][addr.bankgroup][addr.bank].UpdateTiming(\n            cmd_timing.first, clk + cmd_timing.second);\n    }\n    return;\n}\n\nvoid ChannelState::UpdateOtherBanksSameBankgroupTiming(\n    const Address& addr,\n    const std::vector<std::pair<CommandType, int>>& cmd_timing_list,\n    uint64_t clk) {\n    for (auto k = 0; k < config_.banks_per_group; k++) {\n        if (k != addr.bank) {\n            for (auto cmd_timing : cmd_timing_list) {\n                bank_states_[addr.rank][addr.bankgroup][k].UpdateTiming(\n                    cmd_timing.first, clk + cmd_timing.second);\n            }\n        }\n    }\n    return;\n}\n\nvoid ChannelState::UpdateOtherBankgroupsSameRankTiming(\n    const Address& addr,\n    const std::vector<std::pair<CommandType, int>>& cmd_timing_list,\n    uint64_t clk) {\n    for (auto j = 0; j < config_.bankgroups; j++) {\n        if (j != addr.bankgroup) {\n            for (auto k = 0; k < config_.banks_per_group; k++) {\n                for (auto cmd_timing : cmd_timing_list) {\n                    bank_states_[addr.rank][j][k].UpdateTiming(\n                        cmd_timing.first, clk + cmd_timing.second);\n                }\n            }\n        }\n    }\n    return;\n}\n\nvoid ChannelState::UpdateOtherRanksTiming(\n    const Address& addr,\n    const std::vector<std::pair<CommandType, int>>& cmd_timing_list,\n    uint64_t clk) {\n    for (auto i = 0; i < config_.ranks; i++) {\n        if (i != addr.rank) {\n            for (auto j = 0; j < config_.bankgroups; j++) {\n                for (auto k = 0; k < config_.banks_per_group; k++) {\n                    for (auto cmd_timing : cmd_timing_list) {\n                        bank_states_[i][j][k].UpdateTiming(\n                            cmd_timing.first, clk + cmd_timing.second);\n                    }\n                }\n            }\n        }\n    }\n    return;\n}\n\nvoid ChannelState::UpdateSameRankTiming(\n    const Address& addr,\n    const std::vector<std::pair<CommandType, int>>& cmd_timing_list,\n    uint64_t clk) {\n    for (auto j = 0; j < config_.bankgroups; j++) {\n        for (auto k = 0; k < config_.banks_per_group; k++) {\n            for (auto cmd_timing : cmd_timing_list) {\n                bank_states_[addr.rank][j][k].UpdateTiming(\n                    cmd_timing.first, clk + cmd_timing.second);\n            }\n        }\n    }\n    return;\n}\n\nvoid ChannelState::UpdateTimingAndStates(const Command& cmd, uint64_t clk) {\n    UpdateState(cmd);\n    UpdateTiming(cmd, clk);\n    return;\n}\n\nbool ChannelState::ActivationWindowOk(int rank, uint64_t curr_time) const {\n    bool tfaw_ok = IsFAWReady(rank, curr_time);\n    if (config_.IsGDDR()) {\n        if (!tfaw_ok)\n            return false;\n        else\n            return Is32AWReady(rank, curr_time);\n    }\n    return tfaw_ok;\n}\n\nvoid ChannelState::UpdateActivationTimes(int rank, uint64_t curr_time) {\n    if (!four_aw_[rank].empty() && curr_time >= four_aw_[rank][0]) {\n        four_aw_[rank].erase(four_aw_[rank].begin());\n    }\n    four_aw_[rank].push_back(curr_time + config_.tFAW);\n    if (config_.IsGDDR()) {\n        if (!thirty_two_aw_[rank].empty() &&\n            curr_time >= thirty_two_aw_[rank][0]) {\n            thirty_two_aw_[rank].erase(thirty_two_aw_[rank].begin());\n        }\n        thirty_two_aw_[rank].push_back(curr_time + config_.t32AW);\n    }\n    return;\n}\n\nbool ChannelState::IsFAWReady(int rank, uint64_t curr_time) const {\n    if (!four_aw_[rank].empty()) {\n        if (curr_time < four_aw_[rank][0] && four_aw_[rank].size() >= 4) {\n            return false;\n        }\n    }\n    return true;\n}\n\nbool ChannelState::Is32AWReady(int rank, uint64_t curr_time) const {\n    if (!thirty_two_aw_[rank].empty()) {\n        if (curr_time < thirty_two_aw_[rank][0] &&\n            thirty_two_aw_[rank].size() >= 32) {\n            return false;\n        }\n    }\n    return true;\n}\n\n}  // namespace dramsim3\n"
  },
  {
    "path": "src/DRAMsim3/src/channel_state.h",
    "content": "#ifndef __CHANNEL_STATE_H\n#define __CHANNEL_STATE_H\n\n#include <vector>\n#include \"bankstate.h\"\n#include \"common.h\"\n#include \"configuration.h\"\n#include \"timing.h\"\n\nnamespace dramsim3 {\n\nclass ChannelState {\n   public:\n    ChannelState(const Config& config, const Timing& timing);\n    Command GetReadyCommand(const Command& cmd, uint64_t clk) const;\n    void UpdateState(const Command& cmd);\n    void UpdateTiming(const Command& cmd, uint64_t clk);\n    void UpdateTimingAndStates(const Command& cmd, uint64_t clk);\n    bool ActivationWindowOk(int rank, uint64_t curr_time) const;\n    void UpdateActivationTimes(int rank, uint64_t curr_time);\n    bool IsRowOpen(int rank, int bankgroup, int bank) const {\n        return bank_states_[rank][bankgroup][bank].IsRowOpen();\n    }\n    bool IsAllBankIdleInRank(int rank) const;\n    bool IsRankSelfRefreshing(int rank) const { return rank_is_sref_[rank]; }\n    bool IsRefreshWaiting() const { return !refresh_q_.empty(); }\n    bool IsRWPendingOnRef(const Command& cmd) const;\n    const Command& PendingRefCommand() const {return refresh_q_.front(); }\n    void BankNeedRefresh(int rank, int bankgroup, int bank, bool need);\n    void RankNeedRefresh(int rank, bool need);\n    int OpenRow(int rank, int bankgroup, int bank) const {\n        return bank_states_[rank][bankgroup][bank].OpenRow();\n    }\n    int RowHitCount(int rank, int bankgroup, int bank) const {\n        return bank_states_[rank][bankgroup][bank].RowHitCount();\n    };\n\n    std::vector<int> rank_idle_cycles;\n\n   private:\n    const Config& config_;\n    const Timing& timing_;\n\n    std::vector<bool> rank_is_sref_;\n    std::vector<std::vector<std::vector<BankState> > > bank_states_;\n    std::vector<Command> refresh_q_;\n\n    std::vector<std::vector<uint64_t> > four_aw_;\n    std::vector<std::vector<uint64_t> > thirty_two_aw_;\n    bool IsFAWReady(int rank, uint64_t curr_time) const;\n    bool Is32AWReady(int rank, uint64_t curr_time) const;\n    // Update timing of the bank the command corresponds to\n    void UpdateSameBankTiming(\n        const Address& addr,\n        const std::vector<std::pair<CommandType, int> >& cmd_timing_list,\n        uint64_t clk);\n\n    // Update timing of the other banks in the same bankgroup as the command\n    void UpdateOtherBanksSameBankgroupTiming(\n        const Address& addr,\n        const std::vector<std::pair<CommandType, int> >& cmd_timing_list,\n        uint64_t clk);\n\n    // Update timing of banks in the same rank but different bankgroup as the\n    // command\n    void UpdateOtherBankgroupsSameRankTiming(\n        const Address& addr,\n        const std::vector<std::pair<CommandType, int> >& cmd_timing_list,\n        uint64_t clk);\n\n    // Update timing of banks in a different rank as the command\n    void UpdateOtherRanksTiming(\n        const Address& addr,\n        const std::vector<std::pair<CommandType, int> >& cmd_timing_list,\n        uint64_t clk);\n\n    // Update timing of the entire rank (for rank level commands)\n    void UpdateSameRankTiming(\n        const Address& addr,\n        const std::vector<std::pair<CommandType, int> >& cmd_timing_list,\n        uint64_t clk);\n};\n\n}  // namespace dramsim3\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/command_queue.cc",
    "content": "#include \"command_queue.h\"\n\nnamespace dramsim3 {\n\nCommandQueue::CommandQueue(int channel_id, const Config& config,\n                           const ChannelState& channel_state,\n                           SimpleStats& simple_stats)\n    : rank_q_empty(config.ranks, true),\n      config_(config),\n      channel_state_(channel_state),\n      simple_stats_(simple_stats),\n      is_in_ref_(false),\n      queue_size_(static_cast<size_t>(config_.cmd_queue_size)),\n      queue_idx_(0),\n      clk_(0) {\n    if (config_.queue_structure == \"PER_BANK\") {\n        queue_structure_ = QueueStructure::PER_BANK;\n        num_queues_ = config_.banks * config_.ranks;\n    } else if (config_.queue_structure == \"PER_RANK\") {\n        queue_structure_ = QueueStructure::PER_RANK;\n        num_queues_ = config_.ranks;\n    } else {\n        std::cerr << \"Unsupportted queueing structure \"\n                  << config_.queue_structure << std::endl;\n        AbruptExit(__FILE__, __LINE__);\n    }\n\n    queues_.reserve(num_queues_);\n    for (int i = 0; i < num_queues_; i++) {\n        auto cmd_queue = std::vector<Command>();\n        cmd_queue.reserve(config_.cmd_queue_size);\n        queues_.push_back(cmd_queue);\n    }\n}\n\nCommand CommandQueue::GetCommandToIssue() {\n    for (int i = 0; i < num_queues_; i++) {\n        auto& queue = GetNextQueue();\n        // if we're refresing, skip the command queues that are involved\n        if (is_in_ref_) {\n            if (ref_q_indices_.find(queue_idx_) != ref_q_indices_.end()) {\n                continue;\n            }\n        }\n        auto cmd = GetFirstReadyInQueue(queue);\n        if (cmd.IsValid()) {\n            if (cmd.IsReadWrite()) {\n                EraseRWCommand(cmd);\n            }\n            return cmd;\n        }\n    }\n    return Command();\n}\n\nCommand CommandQueue::FinishRefresh() {\n    // we can do something fancy here like clearing the R/Ws\n    // that already had ACT on the way but by doing that we\n    // significantly pushes back the timing for a refresh\n    // so we simply implement an ASAP approach\n    auto ref = channel_state_.PendingRefCommand();\n    if (!is_in_ref_) {\n        GetRefQIndices(ref);\n        is_in_ref_ = true;\n    }\n\n    // either precharge or refresh\n    auto cmd = channel_state_.GetReadyCommand(ref, clk_);\n\n    if (cmd.IsRefresh()) {\n        ref_q_indices_.clear();\n        is_in_ref_ = false;\n    }\n    return cmd;\n}\n\nbool CommandQueue::ArbitratePrecharge(const CMDIterator& cmd_it,\n                                      const CMDQueue& queue) const {\n    auto cmd = *cmd_it;\n\n    for (auto prev_itr = queue.begin(); prev_itr != cmd_it; prev_itr++) {\n        if (prev_itr->Rank() == cmd.Rank() &&\n            prev_itr->Bankgroup() == cmd.Bankgroup() &&\n            prev_itr->Bank() == cmd.Bank()) {\n            return false;\n        }\n    }\n\n    bool pending_row_hits_exist = false;\n    int open_row =\n        channel_state_.OpenRow(cmd.Rank(), cmd.Bankgroup(), cmd.Bank());\n    for (auto pending_itr = cmd_it; pending_itr != queue.end(); pending_itr++) {\n        if (pending_itr->Row() == open_row &&\n            pending_itr->Bank() == cmd.Bank() &&\n            pending_itr->Bankgroup() == cmd.Bankgroup() &&\n            pending_itr->Rank() == cmd.Rank()) {\n            pending_row_hits_exist = true;\n            break;\n        }\n    }\n\n    bool rowhit_limit_reached =\n        channel_state_.RowHitCount(cmd.Rank(), cmd.Bankgroup(), cmd.Bank()) >=\n        4;\n    if (!pending_row_hits_exist || rowhit_limit_reached) {\n        simple_stats_.Increment(\"num_ondemand_pres\");\n        return true;\n    }\n    return false;\n}\n\nbool CommandQueue::WillAcceptCommand(int rank, int bankgroup, int bank) const {\n    int q_idx = GetQueueIndex(rank, bankgroup, bank);\n    return queues_[q_idx].size() < queue_size_;\n}\n\nbool CommandQueue::QueueEmpty() const {\n    for (const auto q : queues_) {\n        if (!q.empty()) {\n            return false;\n        }\n    }\n    return true;\n}\n\n\nbool CommandQueue::AddCommand(Command cmd) {\n    auto& queue = GetQueue(cmd.Rank(), cmd.Bankgroup(), cmd.Bank());\n    if (queue.size() < queue_size_) {\n        queue.push_back(cmd);\n        rank_q_empty[cmd.Rank()] = false;\n        return true;\n    } else {\n        return false;\n    }\n}\n\nCMDQueue& CommandQueue::GetNextQueue() {\n    queue_idx_++;\n    if (queue_idx_ == num_queues_) {\n        queue_idx_ = 0;\n    }\n    return queues_[queue_idx_];\n}\n\nvoid CommandQueue::GetRefQIndices(const Command& ref) {\n    if (ref.cmd_type == CommandType::REFRESH) {\n        if (queue_structure_ == QueueStructure::PER_BANK) {\n            for (int i = 0; i < num_queues_; i++) {\n                if (i / config_.banks == ref.Rank()) {\n                    ref_q_indices_.insert(i);\n                }\n            }\n        } else {\n            ref_q_indices_.insert(ref.Rank());\n        }\n    } else {  // refb\n        int idx = GetQueueIndex(ref.Rank(), ref.Bankgroup(), ref.Bank());\n        ref_q_indices_.insert(idx);\n    }\n    return;\n}\n\nint CommandQueue::GetQueueIndex(int rank, int bankgroup, int bank) const {\n    if (queue_structure_ == QueueStructure::PER_RANK) {\n        return rank;\n    } else {\n        return rank * config_.banks + bankgroup * config_.banks_per_group +\n               bank;\n    }\n}\n\nCMDQueue& CommandQueue::GetQueue(int rank, int bankgroup, int bank) {\n    int index = GetQueueIndex(rank, bankgroup, bank);\n    return queues_[index];\n}\n\nCommand CommandQueue::GetFirstReadyInQueue(CMDQueue& queue) const {\n    for (auto cmd_it = queue.begin(); cmd_it != queue.end(); cmd_it++) {\n        Command cmd = channel_state_.GetReadyCommand(*cmd_it, clk_);\n        if (!cmd.IsValid()) {\n            continue;\n        }\n        if (cmd.cmd_type == CommandType::PRECHARGE) {\n            if (!ArbitratePrecharge(cmd_it, queue)) {\n                continue;\n            }\n        } else if (cmd.IsWrite()) {\n            if (HasRWDependency(cmd_it, queue)) {\n                continue;\n            }\n        }\n        return cmd;\n    }\n    return Command();\n}\n\nvoid CommandQueue::EraseRWCommand(const Command& cmd) {\n    auto& queue = GetQueue(cmd.Rank(), cmd.Bankgroup(), cmd.Bank());\n    for (auto cmd_it = queue.begin(); cmd_it != queue.end(); cmd_it++) {\n        if (cmd.hex_addr == cmd_it->hex_addr && cmd.cmd_type == cmd_it->cmd_type) {\n            queue.erase(cmd_it);\n            return;\n        }\n    }\n    std::cerr << \"cannot find cmd!\" << std::endl;\n    exit(1);\n}\n\nint CommandQueue::QueueUsage() const {\n    int usage = 0;\n    for (auto i = queues_.begin(); i != queues_.end(); i++) {\n        usage += i->size();\n    }\n    return usage;\n}\n\nbool CommandQueue::HasRWDependency(const CMDIterator& cmd_it,\n                                   const CMDQueue& queue) const {\n    // Read after write has been checked in controller so we only\n    // check write after read here\n    for (auto it = queue.begin(); it != cmd_it; it++) {\n        if (it->IsRead() && it->Row() == cmd_it->Row() &&\n            it->Column() == cmd_it->Column() && it->Bank() == cmd_it->Bank() &&\n            it->Bankgroup() == cmd_it->Bankgroup()) {\n            return true;\n        }\n    }\n    return false;\n}\n\n}  // namespace dramsim3\n"
  },
  {
    "path": "src/DRAMsim3/src/command_queue.h",
    "content": "#ifndef __COMMAND_QUEUE_H\n#define __COMMAND_QUEUE_H\n\n#include <unordered_set>\n#include <vector>\n#include \"channel_state.h\"\n#include \"common.h\"\n#include \"configuration.h\"\n#include \"simple_stats.h\"\n\nnamespace dramsim3 {\n\nusing CMDIterator = std::vector<Command>::iterator;\nusing CMDQueue = std::vector<Command>;\nenum class QueueStructure { PER_RANK, PER_BANK, SIZE };\n\nclass CommandQueue {\n   public:\n    CommandQueue(int channel_id, const Config& config,\n                 const ChannelState& channel_state, SimpleStats& simple_stats);\n    Command GetCommandToIssue();\n    Command FinishRefresh();\n    void ClockTick() { clk_ += 1; };\n    bool WillAcceptCommand(int rank, int bankgroup, int bank) const;\n    bool AddCommand(Command cmd);\n    bool QueueEmpty() const;\n    int QueueUsage() const;\n    std::vector<bool> rank_q_empty;\n\n   private:\n    bool ArbitratePrecharge(const CMDIterator& cmd_it,\n                            const CMDQueue& queue) const;\n    bool HasRWDependency(const CMDIterator& cmd_it,\n                         const CMDQueue& queue) const;\n    Command GetFirstReadyInQueue(CMDQueue& queue) const;\n    int GetQueueIndex(int rank, int bankgroup, int bank) const;\n    CMDQueue& GetQueue(int rank, int bankgroup, int bank);\n    CMDQueue& GetNextQueue();\n    void GetRefQIndices(const Command& ref);\n    void EraseRWCommand(const Command& cmd);\n    Command PrepRefCmd(const CMDIterator& it, const Command& ref) const;\n\n    QueueStructure queue_structure_;\n    const Config& config_;\n    const ChannelState& channel_state_;\n    SimpleStats& simple_stats_;\n\n    std::vector<CMDQueue> queues_;\n\n    // Refresh related data structures\n    std::unordered_set<int> ref_q_indices_;\n    bool is_in_ref_;\n\n    int num_queues_;\n    size_t queue_size_;\n    int queue_idx_;\n    uint64_t clk_;\n};\n\n}  // namespace dramsim3\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/common.cc",
    "content": "#include \"common.h\"\n#include \"fmt/format.h\"\n#include <sstream>\n#include <unordered_set>\n#include <sys/stat.h>\n\nnamespace dramsim3 {\n\nstd::ostream& operator<<(std::ostream& os, const Command& cmd) {\n    std::vector<std::string> command_string = {\n        \"read\",\n        \"read_p\",\n        \"write\",\n        \"write_p\",\n        \"activate\",\n        \"precharge\",\n        \"refresh_bank\",  // verilog model doesn't distinguish bank/rank refresh\n        \"refresh\",\n        \"self_refresh_enter\",\n        \"self_refresh_exit\",\n        \"WRONG\"};\n    os << fmt::format(\"{:<20} {:>3} {:>3} {:>3} {:>3} {:>#8x} {:>#8x}\",\n                      command_string[static_cast<int>(cmd.cmd_type)],\n                      cmd.Channel(), cmd.Rank(), cmd.Bankgroup(), cmd.Bank(),\n                      cmd.Row(), cmd.Column());\n    return os;\n}\n\nstd::ostream& operator<<(std::ostream& os, const Transaction& trans) {\n    const std::string trans_type = trans.is_write ? \"WRITE\" : \"READ\";\n    os << fmt::format(\"{:<30} {:>8}\", trans.addr, trans_type);\n    return os;\n}\n\nstd::istream& operator>>(std::istream& is, Transaction& trans) {\n    std::unordered_set<std::string> write_types = {\"WRITE\", \"write\", \"P_MEM_WR\",\n                                                   \"BOFF\"};\n    std::string mem_op;\n    is >> std::hex >> trans.addr >> mem_op >> std::dec >> trans.added_cycle;\n    trans.is_write = write_types.count(mem_op) == 1;\n    return is;\n}\n\nint GetBitInPos(uint64_t bits, int pos) {\n    // given a uint64_t value get the binary value of pos-th bit\n    // from MSB to LSB indexed as 63 - 0\n    return (bits >> pos) & 1;\n}\n\nint LogBase2(int power_of_two) {\n    int i = 0;\n    while (power_of_two > 1) {\n        power_of_two /= 2;\n        i++;\n    }\n    return i;\n}\n\nstd::vector<std::string> StringSplit(const std::string& s, char delim) {\n    std::vector<std::string> elems;\n    StringSplit(s, delim, std::back_inserter(elems));\n    return elems;\n}\n\ntemplate <typename Out>\nvoid StringSplit(const std::string& s, char delim, Out result) {\n    std::stringstream ss;\n    ss.str(s);\n    std::string item;\n    while (std::getline(ss, item, delim)) {\n        if (!item.empty()) {\n            *(result++) = item;\n        }\n    }\n}\n\nvoid AbruptExit(const std::string& file, int line) {\n    std::cerr << \"Exiting Abruptly - \" << file << \":\" << line << std::endl;\n    std::exit(-1);\n}\n\nbool DirExist(std::string dir) {\n    // courtesy to stackoverflow\n    struct stat info;\n    if (stat(dir.c_str(), &info) != 0) {\n        return false;\n    } else if (info.st_mode & S_IFDIR) {\n        return true;\n    } else {  // exists but is file\n        return false;\n    }\n}\n\n}  // namespace dramsim3\n"
  },
  {
    "path": "src/DRAMsim3/src/common.h",
    "content": "#ifndef __COMMON_H\n#define __COMMON_H\n\n#include <stdint.h>\n#include <iostream>\n#include <vector>\n\nnamespace dramsim3 {\n\nstruct Address {\n    Address()\n        : channel(-1), rank(-1), bankgroup(-1), bank(-1), row(-1), column(-1) {}\n    Address(int channel, int rank, int bankgroup, int bank, int row, int column)\n        : channel(channel),\n          rank(rank),\n          bankgroup(bankgroup),\n          bank(bank),\n          row(row),\n          column(column) {}\n    Address(const Address& addr)\n        : channel(addr.channel),\n          rank(addr.rank),\n          bankgroup(addr.bankgroup),\n          bank(addr.bank),\n          row(addr.row),\n          column(addr.column) {}\n    int channel;\n    int rank;\n    int bankgroup;\n    int bank;\n    int row;\n    int column;\n};\n\ninline uint32_t ModuloWidth(uint64_t addr, uint32_t bit_width, uint32_t pos) {\n    addr >>= pos;\n    auto store = addr;\n    addr >>= bit_width;\n    addr <<= bit_width;\n    return static_cast<uint32_t>(store ^ addr);\n}\n\n// extern std::function<Address(uint64_t)> AddressMapping;\nint GetBitInPos(uint64_t bits, int pos);\n// it's 2017 and c++ std::string still lacks a split function, oh well\nstd::vector<std::string> StringSplit(const std::string& s, char delim);\ntemplate <typename Out>\nvoid StringSplit(const std::string& s, char delim, Out result);\n\nint LogBase2(int power_of_two);\nvoid AbruptExit(const std::string& file, int line);\nbool DirExist(std::string dir);\n\nenum class CommandType {\n    READ,\n    READ_PRECHARGE,\n    WRITE,\n    WRITE_PRECHARGE,\n    ACTIVATE,\n    PRECHARGE,\n    REFRESH_BANK,\n    REFRESH,\n    SREF_ENTER,\n    SREF_EXIT,\n    SIZE\n};\n\nstruct Command {\n    Command() : cmd_type(CommandType::SIZE), hex_addr(0) {}\n    Command(CommandType cmd_type, const Address& addr, uint64_t hex_addr)\n        : cmd_type(cmd_type), addr(addr), hex_addr(hex_addr) {}\n    // Command(const Command& cmd) {}\n\n    bool IsValid() const { return cmd_type != CommandType::SIZE; }\n    bool IsRefresh() const {\n        return cmd_type == CommandType::REFRESH ||\n               cmd_type == CommandType::REFRESH_BANK;\n    }\n    bool IsRead() const {\n        return cmd_type == CommandType::READ ||\n               cmd_type == CommandType ::READ_PRECHARGE;\n    }\n    bool IsWrite() const {\n        return cmd_type == CommandType ::WRITE ||\n               cmd_type == CommandType ::WRITE_PRECHARGE;\n    }\n    bool IsReadWrite() const { return IsRead() || IsWrite(); }\n    bool IsRankCMD() const {\n        return cmd_type == CommandType::REFRESH ||\n               cmd_type == CommandType::SREF_ENTER ||\n               cmd_type == CommandType::SREF_EXIT;\n    }\n    CommandType cmd_type;\n    Address addr;\n    uint64_t hex_addr;\n\n    int Channel() const { return addr.channel; }\n    int Rank() const { return addr.rank; }\n    int Bankgroup() const { return addr.bankgroup; }\n    int Bank() const { return addr.bank; }\n    int Row() const { return addr.row; }\n    int Column() const { return addr.column; }\n\n    friend std::ostream& operator<<(std::ostream& os, const Command& cmd);\n};\n\nstruct Transaction {\n    Transaction() {}\n    Transaction(uint64_t addr, bool is_write)\n        : addr(addr),\n          added_cycle(0),\n          complete_cycle(0),\n          is_write(is_write) {}\n    Transaction(const Transaction& tran)\n        : addr(tran.addr),\n          added_cycle(tran.added_cycle),\n          complete_cycle(tran.complete_cycle),\n          is_write(tran.is_write) {}\n    uint64_t addr;\n    uint64_t added_cycle;\n    uint64_t complete_cycle;\n    bool is_write;\n\n    friend std::ostream& operator<<(std::ostream& os, const Transaction& trans);\n    friend std::istream& operator>>(std::istream& is, Transaction& trans);\n};\n\n}  // namespace dramsim3\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/configuration.cc",
    "content": "#include \"configuration.h\"\n\n#include <vector>\n\n#ifdef THERMAL\n#include <math.h>\n#endif  // THERMAL\n\nnamespace dramsim3 {\n\nConfig::Config(std::string config_file, std::string out_dir)\n    : output_dir(out_dir), reader_(new INIReader(config_file)) {\n    if (reader_->ParseError() < 0) {\n        std::cerr << \"Can't load config file - \" << config_file << std::endl;\n        AbruptExit(__FILE__, __LINE__);\n    }\n\n    // The initialization of the parameters has to be strictly in this order\n    // because of internal dependencies\n    InitSystemParams();\n    InitDRAMParams();\n    CalculateSize();\n    SetAddressMapping();\n    InitTimingParams();\n    InitPowerParams();\n    InitOtherParams();\n#ifdef THERMAL\n    InitThermalParams();\n#endif  // THERMAL\n    delete (reader_);\n}\n\nAddress Config::AddressMapping(uint64_t hex_addr) const {\n    hex_addr >>= shift_bits;\n    int channel = (hex_addr >> ch_pos) & ch_mask;\n    int rank = (hex_addr >> ra_pos) & ra_mask;\n    int bg = (hex_addr >> bg_pos) & bg_mask;\n    int ba = (hex_addr >> ba_pos) & ba_mask;\n    int ro = (hex_addr >> ro_pos) & ro_mask;\n    int co = (hex_addr >> co_pos) & co_mask;\n    return Address(channel, rank, bg, ba, ro, co);\n}\n\nvoid Config::CalculateSize() {\n    // calculate rank and re-calculate channel_size\n    devices_per_rank = bus_width / device_width;\n    int page_size = columns * device_width / 8;  // page size in bytes\n    int megs_per_bank = page_size * (rows / 1024) / 1024;\n    int megs_per_rank = megs_per_bank * banks * devices_per_rank;\n\n    if (megs_per_rank > channel_size) {\n        std::cout << \"WARNING: Cannot create memory system of size \"\n                  << channel_size\n                  << \"MB with given device choice! Using default size \"\n                  << megs_per_rank << \" instead!\" << std::endl;\n        ranks = 1;\n        channel_size = megs_per_rank;\n    } else {\n        ranks = channel_size / megs_per_rank;\n        channel_size = ranks * megs_per_rank;\n    }\n    return;\n}\n\nDRAMProtocol Config::GetDRAMProtocol(std::string protocol_str) {\n    std::map<std::string, DRAMProtocol> protocol_pairs = {\n        {\"DDR3\", DRAMProtocol::DDR3},     {\"DDR4\", DRAMProtocol::DDR4},\n        {\"GDDR5\", DRAMProtocol::GDDR5},   {\"GDDR5X\", DRAMProtocol::GDDR5X},  {\"GDDR6\", DRAMProtocol::GDDR6},\n        {\"LPDDR\", DRAMProtocol::LPDDR},   {\"LPDDR3\", DRAMProtocol::LPDDR3},\n        {\"LPDDR4\", DRAMProtocol::LPDDR4}, {\"HBM\", DRAMProtocol::HBM},\n        {\"HBM2\", DRAMProtocol::HBM2},     {\"HMC\", DRAMProtocol::HMC}};\n\n    if (protocol_pairs.find(protocol_str) == protocol_pairs.end()) {\n        std::cout << \"Unkwown/Unsupported DRAM Protocol: \" << protocol_str\n                  << \" Aborting!\" << std::endl;\n        AbruptExit(__FILE__, __LINE__);\n    }\n\n    return protocol_pairs[protocol_str];\n}\n\nint Config::GetInteger(const std::string& sec, const std::string& opt,\n                       int default_val) const {\n    return static_cast<int>(reader_->GetInteger(sec, opt, default_val));\n}\n\nvoid Config::InitDRAMParams() {\n    const auto& reader = *reader_;\n    protocol =\n        GetDRAMProtocol(reader.Get(\"dram_structure\", \"protocol\", \"DDR3\"));\n    bankgroups = GetInteger(\"dram_structure\", \"bankgroups\", 2);\n    banks_per_group = GetInteger(\"dram_structure\", \"banks_per_group\", 2);\n    bool bankgroup_enable =\n        reader.GetBoolean(\"dram_structure\", \"bankgroup_enable\", true);\n    // GDDR5/6 can chose to enable/disable bankgroups\n    if (!bankgroup_enable) {  // aggregating all banks to one group\n        banks_per_group *= bankgroups;\n        bankgroups = 1;\n    }\n    banks = bankgroups * banks_per_group;\n    rows = GetInteger(\"dram_structure\", \"rows\", 1 << 16);\n    columns = GetInteger(\"dram_structure\", \"columns\", 1 << 10);\n    device_width = GetInteger(\"dram_structure\", \"device_width\", 8);\n    BL = GetInteger(\"dram_structure\", \"BL\", 8);\n    num_dies = GetInteger(\"dram_structure\", \"num_dies\", 1);\n    // HBM specific parameters\n    enable_hbm_dual_cmd =\n        reader.GetBoolean(\"dram_structure\", \"hbm_dual_cmd\", true);\n    enable_hbm_dual_cmd &= IsHBM();  // Make sure only HBM enables this\n    // HMC specific parameters\n    num_links = GetInteger(\"hmc\", \"num_links\", 4);\n    link_width = GetInteger(\"hmc\", \"link_width\", 16);\n    link_speed = GetInteger(\"hmc\", \"link_speed\", 15000);  //MHz\n    block_size = GetInteger(\"hmc\", \"block_size\", 64);\n    xbar_queue_depth = GetInteger(\"hmc\", \"xbar_queue_depth\", 16);\n    if (IsHMC()) {\n        // the BL for HMC is determined by max block_size, which is a multiple\n        // of 32B, each \"device\" transfer 32b per half cycle therefore BL is 8\n        // for 32B block size\n        BL = block_size * 8 / device_width;\n    }\n    // set burst cycle according to protocol\n    // We use burst_cycle for timing and use BL for capacity calculation\n    // BL = 0 simulate perfect BW\n    if (protocol == DRAMProtocol::GDDR5) {\n        burst_cycle = (BL == 0) ? 0 : BL / 4;\n        BL = (BL == 0) ? 8 : BL;\n    } else if (protocol == DRAMProtocol::GDDR5X) {\n        burst_cycle = (BL == 0) ? 0 : BL / 8;\n        BL = (BL == 0) ? 8 : BL;\n    } else if (protocol == DRAMProtocol::GDDR6){\n        burst_cycle = (BL == 0) ? 0 : BL / 16;\n        BL = (BL == 0 ) ? 8 : BL;\n    } else {\n        burst_cycle = (BL == 0) ? 0 : BL / 2;\n        BL = (BL == 0) ? (IsHBM() ? 4 : 8) : BL;\n    }\n    // every protocol has a different definition of \"column\",\n    // in DDR3/4, each column is exactly device_width bits,\n    // but in GDDR5, a column is device_width * BL bits\n    // and for HBM each column is device_width * 2 (prefetch)\n    // as a result, different protocol has different method of calculating\n    // page size, and address mapping...\n    // To make life easier, we regulate the use of the term \"column\"\n    // to only represent physical column (device width)\n    if (IsGDDR()) {\n        columns *= BL;\n    } else if (IsHBM()) {\n        columns *= 2;\n    }\n    return;\n}\n\nvoid Config::InitOtherParams() {\n    const auto& reader = *reader_;\n    epoch_period = GetInteger(\"other\", \"epoch_period\", 100000);\n    // determine how much output we want:\n    // -1: no file output at all (NOT implemented yet)\n    // 0: no epoch file output, only outputs the summary in the end\n    // 1: default value, adds epoch CSV output on level 0\n    // 2: adds histogram outputs in a different CSV format\n    output_level = reader.GetInteger(\"other\", \"output_level\", 1);\n    // Other Parameters\n    // give a prefix instead of specify the output name one by one...\n    // this would allow outputing to a directory and you can always override\n    // these values\n    if (!DirExist(output_dir)) {\n        std::cout << \"WARNING: Output directory \" << output_dir\n                  << \" not exists! Using current directory for output!\"\n                  << std::endl;\n        output_dir = \"./\";\n    } else {\n        output_dir = output_dir + \"/\";\n    }\n    output_prefix =\n        output_dir + reader.Get(\"other\", \"output_prefix\", \"dramsim3\");\n    json_stats_name = output_prefix + \".json\";\n    json_epoch_name = output_prefix + \"epoch.json\";\n    txt_stats_name = output_prefix + \".txt\";\n    return;\n}\n\nvoid Config::InitPowerParams() {\n    const auto& reader = *reader_;\n    // Power-related parameters\n    double VDD = reader.GetReal(\"power\", \"VDD\", 1.2);\n    double IDD0 = reader.GetReal(\"power\", \"IDD0\", 48);\n    double IDD2P = reader.GetReal(\"power\", \"IDD2P\", 25);\n    double IDD2N = reader.GetReal(\"power\", \"IDD2N\", 34);\n    // double IDD3P = reader.GetReal(\"power\", \"IDD3P\", 37);\n    double IDD3N = reader.GetReal(\"power\", \"IDD3N\", 43);\n    double IDD4W = reader.GetReal(\"power\", \"IDD4W\", 123);\n    double IDD4R = reader.GetReal(\"power\", \"IDD4R\", 135);\n    double IDD5AB = reader.GetReal(\"power\", \"IDD5AB\", 250);  // all-bank ref\n    double IDD5PB = reader.GetReal(\"power\", \"IDD5PB\", 5);    // per-bank ref\n    double IDD6x = reader.GetReal(\"power\", \"IDD6x\", 31);\n\n    // energy increments per command/cycle, calculated as voltage * current *\n    // time(in cycles) units are V * mA * Cycles and if we convert cycles to ns\n    // then it's exactly pJ in energy and because a command take effects on all\n    // devices per rank, also multiply that number\n    double devices = static_cast<double>(devices_per_rank);\n    act_energy_inc =\n        VDD * (IDD0 * tRC - (IDD3N * tRAS + IDD2N * tRP)) * devices;\n    read_energy_inc = VDD * (IDD4R - IDD3N) * burst_cycle * devices;\n    write_energy_inc = VDD * (IDD4W - IDD3N) * burst_cycle * devices;\n    ref_energy_inc = VDD * (IDD5AB - IDD3N) * tRFC * devices;\n    refb_energy_inc = VDD * (IDD5PB - IDD3N) * tRFCb * devices;\n    // the following are added per cycle\n    act_stb_energy_inc = VDD * IDD3N * devices;\n    pre_stb_energy_inc = VDD * IDD2N * devices;\n    pre_pd_energy_inc = VDD * IDD2P * devices;\n    sref_energy_inc = VDD * IDD6x * devices;\n    return;\n}\n\nvoid Config::InitSystemParams() {\n    const auto& reader = *reader_;\n    channel_size = GetInteger(\"system\", \"channel_size\", 1024);\n    channels = GetInteger(\"system\", \"channels\", 1);\n    bus_width = GetInteger(\"system\", \"bus_width\", 64);\n    address_mapping = reader.Get(\"system\", \"address_mapping\", \"chrobabgraco\");\n    queue_structure = reader.Get(\"system\", \"queue_structure\", \"PER_BANK\");\n    row_buf_policy = reader.Get(\"system\", \"row_buf_policy\", \"OPEN_PAGE\");\n    cmd_queue_size = GetInteger(\"system\", \"cmd_queue_size\", 16);\n    trans_queue_size = GetInteger(\"system\", \"trans_queue_size\", 32);\n    unified_queue = reader.GetBoolean(\"system\", \"unified_queue\", false);\n    write_buf_size = GetInteger(\"system\", \"write_buf_size\", 16);\n    std::string ref_policy =\n        reader.Get(\"system\", \"refresh_policy\", \"RANK_LEVEL_STAGGERED\");\n    if (ref_policy == \"RANK_LEVEL_SIMULTANEOUS\") {\n        refresh_policy = RefreshPolicy::RANK_LEVEL_SIMULTANEOUS;\n    } else if (ref_policy == \"RANK_LEVEL_STAGGERED\") {\n        refresh_policy = RefreshPolicy::RANK_LEVEL_STAGGERED;\n    } else if (ref_policy == \"BANK_LEVEL_STAGGERED\") {\n        refresh_policy = RefreshPolicy::BANK_LEVEL_STAGGERED;\n    } else {\n        AbruptExit(__FILE__, __LINE__);\n    }\n\n    enable_self_refresh =\n        reader.GetBoolean(\"system\", \"enable_self_refresh\", false);\n    sref_threshold = GetInteger(\"system\", \"sref_threshold\", 1000);\n    aggressive_precharging_enabled =\n        reader.GetBoolean(\"system\", \"aggressive_precharging_enabled\", false);\n\n    return;\n}\n\n#ifdef THERMAL\nvoid Config::InitThermalParams() {\n    const auto& reader = *reader_;\n    const_logic_power = reader.GetReal(\"thermal\", \"const_logic_power\", 5.0);\n    mat_dim_x = GetInteger(\"thermal\", \"mat_dim_x\", 512);\n    mat_dim_y = GetInteger(\"thermal\", \"mat_dim_y\", 512);\n    // row_tile = GetInteger(\"thermal\", \"row_tile\", 1));\n    num_x_grids = rows / mat_dim_x;\n    tile_row_num = rows;\n\n    num_y_grids = columns * device_width / mat_dim_y;\n    bank_asr = (double)num_x_grids / num_y_grids;\n    row_tile = 1;\n    if (bank_asr > 4 && banks_per_group == 1) {\n        // YZY: I set the aspect ratio as 4\n        // I assume if bank_asr <= 4, the dimension can be corrected by\n        // arranging banks/vaults\n        while (row_tile * row_tile * 4 < bank_asr) {\n            row_tile *= 2;\n        }\n        // row_tile = num_x_grids / (num_y_grids * 8);\n#ifdef DEBUG_OUTPUT\n        std::cout << \"row_tile = \" << row_tile << std::endl;\n#endif  // DEBUG_OUTPUT\n        num_x_grids = num_x_grids / row_tile;\n        tile_row_num = tile_row_num / row_tile;\n        num_y_grids = num_y_grids * row_tile;\n        bank_asr = (double)num_x_grids / num_y_grids;\n    } else {\n#ifdef DEBUG_OUTPUT\n        std::cout << \"No Need to Tile Rows\\n\";\n#endif  // DEBUG_OUTPUT\n        loc_mapping = reader.Get(\"thermal\", \"loc_mapping\", \"\");\n        bank_order = GetInteger(\"thermal\", \"bank_order\", 1);\n        bank_layer_order = GetInteger(\"thermal\", \"bank_layer_order\", 0);\n        num_row_refresh =\n            static_cast<int>(ceil(rows / (64 * 1e6 / (tREFI * tCK))));\n        chip_dim_x = reader.GetReal(\"thermal\", \"chip_dim_x\", 0.01);\n        chip_dim_y = reader.GetReal(\"thermal\", \"chip_dim_y\", 0.01);\n        amb_temp = reader.GetReal(\"thermal\", \"amb_temp\", 40);\n    }\n    return;\n}\n#endif  // THERMAL\n\nvoid Config::InitTimingParams() {\n    // Timing Parameters\n    // TODO there is no need to keep all of these variables, they should\n    // just be temporary, ultimately we only need cmd to cmd Timing\n    const auto& reader = *reader_;\n    tCK = reader.GetReal(\"timing\", \"tCK\", 1.0);\n    AL = GetInteger(\"timing\", \"AL\", 0);\n    CL = GetInteger(\"timing\", \"CL\", 12);\n    CWL = GetInteger(\"timing\", \"CWL\", 12);\n    tCCD_L = GetInteger(\"timing\", \"tCCD_L\", 6);\n    tCCD_S = GetInteger(\"timing\", \"tCCD_S\", 4);\n    tRTRS = GetInteger(\"timing\", \"tRTRS\", 2);\n    tRTP = GetInteger(\"timing\", \"tRTP\", 5);\n    tWTR_L = GetInteger(\"timing\", \"tWTR_L\", 5);\n    tWTR_S = GetInteger(\"timing\", \"tWTR_S\", 5);\n    tWR = GetInteger(\"timing\", \"tWR\", 10);\n    tRP = GetInteger(\"timing\", \"tRP\", 10);\n    tRRD_L = GetInteger(\"timing\", \"tRRD_L\", 4);\n    tRRD_S = GetInteger(\"timing\", \"tRRD_S\", 4);\n    tRAS = GetInteger(\"timing\", \"tRAS\", 24);\n    tRCD = GetInteger(\"timing\", \"tRCD\", 10);\n    tRFC = GetInteger(\"timing\", \"tRFC\", 74);\n    tRC = tRAS + tRP;\n    tCKE = GetInteger(\"timing\", \"tCKE\", 6);\n    tCKESR = GetInteger(\"timing\", \"tCKESR\", 12);\n    tXS = GetInteger(\"timing\", \"tXS\", 432);\n    tXP = GetInteger(\"timing\", \"tXP\", 8);\n    tRFCb = GetInteger(\"timing\", \"tRFCb\", 20);\n    tREFI = GetInteger(\"timing\", \"tREFI\", 7800);\n    tREFIb = GetInteger(\"timing\", \"tREFIb\", 1950);\n    tFAW = GetInteger(\"timing\", \"tFAW\", 50);\n    tRPRE = GetInteger(\"timing\", \"tRPRE\", 1);\n    tWPRE = GetInteger(\"timing\", \"tWPRE\", 1);\n\n    // LPDDR4 and GDDR5/6\n    tPPD = GetInteger(\"timing\", \"tPPD\", 0);\n\n    // GDDR5/6\n    t32AW = GetInteger(\"timing\", \"t32AW\", 330);\n    tRCDRD = GetInteger(\"timing\", \"tRCDRD\", 24);\n    tRCDWR = GetInteger(\"timing\", \"tRCDWR\", 20);\n\n    ideal_memory_latency = GetInteger(\"timing\", \"ideal_memory_latency\", 10);\n\n    // calculated timing\n    RL = AL + CL;\n    WL = AL + CWL;\n    read_delay = RL + burst_cycle;\n    write_delay = WL + burst_cycle;\n    return;\n}\n\nvoid Config::SetAddressMapping() {\n    // memory addresses are byte addressable, but each request comes with\n    // multiple bytes because of bus width, and burst length\n    request_size_bytes = bus_width / 8 * BL;\n    shift_bits = LogBase2(request_size_bytes);\n    int col_low_bits = LogBase2(BL);\n    int actual_col_bits = LogBase2(columns) - col_low_bits;\n\n    // has to strictly follow the order of chan, rank, bg, bank, row, col\n    std::map<std::string, int> field_widths;\n    field_widths[\"ch\"] = LogBase2(channels);\n    field_widths[\"ra\"] = LogBase2(ranks);\n    field_widths[\"bg\"] = LogBase2(bankgroups);\n    field_widths[\"ba\"] = LogBase2(banks_per_group);\n    field_widths[\"ro\"] = LogBase2(rows);\n    field_widths[\"co\"] = actual_col_bits;\n\n    if (address_mapping.size() != 12) {\n        std::cerr << \"Unknown address mapping (6 fields each 2 chars required)\"\n                  << std::endl;\n        AbruptExit(__FILE__, __LINE__);\n    }\n\n    // // get address mapping position fields from config\n    // // each field must be 2 chars\n    std::vector<std::string> fields;\n    for (size_t i = 0; i < address_mapping.size(); i += 2) {\n        std::string token = address_mapping.substr(i, 2);\n        fields.push_back(token);\n    }\n\n    std::map<std::string, int> field_pos;\n    int pos = 0;\n    while (!fields.empty()) {\n        auto token = fields.back();\n        fields.pop_back();\n        if (field_widths.find(token) == field_widths.end()) {\n            std::cerr << \"Unrecognized field: \" << token << std::endl;\n            AbruptExit(__FILE__, __LINE__);\n        }\n        field_pos[token] = pos;\n        pos += field_widths[token];\n    }\n\n    ch_pos = field_pos.at(\"ch\");\n    ra_pos = field_pos.at(\"ra\");\n    bg_pos = field_pos.at(\"bg\");\n    ba_pos = field_pos.at(\"ba\");\n    ro_pos = field_pos.at(\"ro\");\n    co_pos = field_pos.at(\"co\");\n\n    ch_mask = (1 << field_widths.at(\"ch\")) - 1;\n    ra_mask = (1 << field_widths.at(\"ra\")) - 1;\n    bg_mask = (1 << field_widths.at(\"bg\")) - 1;\n    ba_mask = (1 << field_widths.at(\"ba\")) - 1;\n    ro_mask = (1 << field_widths.at(\"ro\")) - 1;\n    co_mask = (1 << field_widths.at(\"co\")) - 1;\n}\n\nvoid Config::SetOutputFileNames(const char *timestamp){\n    output_prefix = output_dir;\n    output_prefix.append(\"/dramsim3_\");\n    output_prefix.append(std::string(timestamp));\n    json_stats_name = output_prefix + \".json\";\n    json_epoch_name = output_prefix + \"epoch.json\";\n    txt_stats_name = output_prefix + \".txt\";\n}\n\n}  // namespace dramsim3\n"
  },
  {
    "path": "src/DRAMsim3/src/configuration.h",
    "content": "#ifndef __CONFIG_H\n#define __CONFIG_H\n\n#include <fstream>\n#include <string>\n#include \"common.h\"\n\n#include \"INIReader.h\"\n\nnamespace dramsim3 {\n\nenum class DRAMProtocol {\n    DDR3,\n    DDR4,\n    GDDR5,\n    GDDR5X,\n    GDDR6,\n    LPDDR,\n    LPDDR3,\n    LPDDR4,\n    HBM,\n    HBM2,\n    HMC,\n    SIZE\n};\n\nenum class RefreshPolicy {\n    RANK_LEVEL_SIMULTANEOUS,  // impractical due to high power requirement\n    RANK_LEVEL_STAGGERED,\n    BANK_LEVEL_STAGGERED,\n    SIZE \n};\n\nclass Config {\n   public:\n    Config(std::string config_file, std::string out_dir);\n    Address AddressMapping(uint64_t hex_addr) const;\n    // DRAM physical structure\n    DRAMProtocol protocol;\n    int channel_size;\n    int channels;\n    int ranks;\n    int banks;\n    int bankgroups;\n    int banks_per_group;\n    int rows;\n    int columns;\n    int device_width;\n    int bus_width;\n    int devices_per_rank;\n    int BL;\n\n    // Address mapping numbers\n    int shift_bits;\n    int ch_pos, ra_pos, bg_pos, ba_pos, ro_pos, co_pos;\n    uint64_t ch_mask, ra_mask, bg_mask, ba_mask, ro_mask, co_mask;\n\n    // Generic DRAM timing parameters\n    double tCK;\n    int burst_cycle;  // seperate BL with timing since for GDDRx it's not BL/2\n    int AL;\n    int CL;\n    int CWL;\n    int RL;\n    int WL;\n    int tCCD_L;\n    int tCCD_S;\n    int tRTRS;\n    int tRTP;\n    int tWTR_L;\n    int tWTR_S;\n    int tWR;\n    int tRP;\n    int tRRD_L;\n    int tRRD_S;\n    int tRAS;\n    int tRCD;\n    int tRFC;\n    int tRC;\n    // tCKSRE and tCKSRX are only useful for changing clock freq after entering\n    // SRE mode we are not doing that, so tCKESR is sufficient\n    int tCKE;\n    int tCKESR;\n    int tXS;\n    int tXP;\n    int tRFCb;\n    int tREFI;\n    int tREFIb;\n    int tFAW;\n    int tRPRE;  // read preamble and write preamble are important\n    int tWPRE;\n    int read_delay;\n    int write_delay;\n\n    // LPDDR4 and GDDR5\n    int tPPD;\n    // GDDR5\n    int t32AW;\n    int tRCDRD;\n    int tRCDWR;\n\n    // pre calculated power parameters\n    double act_energy_inc;\n    double pre_energy_inc;\n    double read_energy_inc;\n    double write_energy_inc;\n    double ref_energy_inc;\n    double refb_energy_inc;\n    double act_stb_energy_inc;\n    double pre_stb_energy_inc;\n    double pre_pd_energy_inc;\n    double sref_energy_inc;\n\n    // HMC\n    int num_links;\n    int num_dies;\n    int link_width;\n    int link_speed;\n    int num_vaults;\n    int block_size;  // block size in bytes\n    int xbar_queue_depth;\n\n    // System\n    std::string address_mapping;\n    std::string queue_structure;\n    std::string row_buf_policy;\n    RefreshPolicy refresh_policy;\n    int cmd_queue_size;\n    bool unified_queue;\n    int trans_queue_size;\n    int write_buf_size;\n    bool enable_self_refresh;\n    int sref_threshold;\n    bool aggressive_precharging_enabled;\n    bool enable_hbm_dual_cmd;\n\n\n    int epoch_period;\n    int output_level;\n    std::string output_dir;\n    std::string output_prefix;\n    std::string json_stats_name;\n    std::string json_epoch_name;\n    std::string txt_stats_name;\n\n    // Computed parameters\n    int request_size_bytes;\n\n    bool IsGDDR() const {\n        return (protocol == DRAMProtocol::GDDR5 ||\n                protocol == DRAMProtocol::GDDR5X ||\n                protocol == DRAMProtocol::GDDR6);\n    }\n    bool IsHBM() const {\n        return (protocol == DRAMProtocol::HBM ||\n                protocol == DRAMProtocol::HBM2);\n    }\n    bool IsHMC() const { return (protocol == DRAMProtocol::HMC); }\n    // yzy: add another function\n    bool IsDDR4() const { return (protocol == DRAMProtocol::DDR4); }\n\n    int ideal_memory_latency;\n\n#ifdef THERMAL\n    std::string loc_mapping;\n    int num_row_refresh;       // number of rows to be refreshed for one time\n    double amb_temp;         // the ambient temperature in [C]\n    double const_logic_power;\n\n    double chip_dim_x;\n    double chip_dim_y;\n    int num_x_grids;\n    int num_y_grids;\n    int mat_dim_x;\n    int mat_dim_y;\n    // 0: x-direction priority, 1: y-direction priority\n    int bank_order;\n    // 0; low-layer priority, 1: high-layer priority\n    int bank_layer_order;\n    int row_tile;\n    int tile_row_num;\n    double bank_asr;  // the aspect ratio of a bank: #row_bits / #col_bits\n#endif  // THERMAL\n\n    // Called from MARSS-RISCV to print stats\n    void SetOutputFileNames(const char *timestamp);\n\n  private:\n    INIReader* reader_;\n    void CalculateSize();\n    DRAMProtocol GetDRAMProtocol(std::string protocol_str);\n    int GetInteger(const std::string& sec, const std::string& opt,\n                   int default_val) const;\n    void InitDRAMParams();\n    void InitOtherParams();\n    void InitPowerParams();\n    void InitSystemParams();\n#ifdef THERMAL\n    void InitThermalParams();\n#endif  // THERMAL\n    void InitTimingParams();\n    void SetAddressMapping();\n};\n\n}  // namespace dramsim3\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/controller.cc",
    "content": "#include \"controller.h\"\n#include <iomanip>\n#include <iostream>\n#include <limits>\n\nnamespace dramsim3 {\n\n#ifdef THERMAL\nController::Controller(int channel, const Config &config, const Timing &timing,\n                       ThermalCalculator &thermal_calc)\n#else\nController::Controller(int channel, const Config &config, const Timing &timing)\n#endif  // THERMAL\n    : channel_id_(channel),\n      clk_(0),\n      config_(config),\n      simple_stats_(config_, channel_id_),\n      channel_state_(config, timing),\n      cmd_queue_(channel_id_, config, channel_state_, simple_stats_),\n      refresh_(config, channel_state_),\n#ifdef THERMAL\n      thermal_calc_(thermal_calc),\n#endif  // THERMAL\n      is_unified_queue_(config.unified_queue),\n      row_buf_policy_(config.row_buf_policy == \"CLOSE_PAGE\"\n                          ? RowBufPolicy::CLOSE_PAGE\n                          : RowBufPolicy::OPEN_PAGE),\n      last_trans_clk_(0),\n      write_draining_(0) {\n    if (is_unified_queue_) {\n        unified_queue_.reserve(config_.trans_queue_size);\n    } else {\n        read_queue_.reserve(config_.trans_queue_size);\n        write_buffer_.reserve(config_.trans_queue_size);\n    }\n\n#ifdef CMD_TRACE\n    std::string trace_file_name = config_.output_prefix + \"ch_\" +\n                                  std::to_string(channel_id_) + \"cmd.trace\";\n    std::cout << \"Command Trace write to \" << trace_file_name << std::endl;\n    cmd_trace_.open(trace_file_name, std::ofstream::out);\n#endif  // CMD_TRACE\n}\n\nstd::pair<uint64_t, int> Controller::ReturnDoneTrans(uint64_t clk) {\n    auto it = return_queue_.begin();\n    while (it != return_queue_.end()) {\n        if (clk >= it->complete_cycle) {\n            if (it->is_write) {\n                simple_stats_.Increment(\"num_writes_done\");\n            } else {\n                simple_stats_.Increment(\"num_reads_done\");\n                simple_stats_.AddValue(\"read_latency\", clk_ - it->added_cycle);\n            }\n            auto pair = std::make_pair(it->addr, it->is_write);\n            it = return_queue_.erase(it);\n            return pair;\n        } else {\n            ++it;\n        }\n    }\n    return std::make_pair(-1, -1);\n}\n\nvoid Controller::ClockTick() {\n    // update refresh counter\n    refresh_.ClockTick();\n\n    bool cmd_issued = false;\n    Command cmd;\n    if (channel_state_.IsRefreshWaiting()) {\n        cmd = cmd_queue_.FinishRefresh();\n    }\n\n    // cannot find a refresh related command or there's no refresh\n    if (!cmd.IsValid()) {\n        cmd = cmd_queue_.GetCommandToIssue();\n    }\n\n    if (cmd.IsValid()) {\n        IssueCommand(cmd);\n        cmd_issued = true;\n\n        if (config_.enable_hbm_dual_cmd) {\n            auto second_cmd = cmd_queue_.GetCommandToIssue();\n            if (second_cmd.IsValid()) {\n                if (second_cmd.IsReadWrite() != cmd.IsReadWrite()) {\n                    IssueCommand(second_cmd);\n                    simple_stats_.Increment(\"hbm_dual_cmds\");\n                }\n            }\n        }\n    }\n\n    // power updates pt 1\n    for (int i = 0; i < config_.ranks; i++) {\n        if (channel_state_.IsRankSelfRefreshing(i)) {\n            simple_stats_.IncrementVec(\"sref_cycles\", i);\n        } else {\n            bool all_idle = channel_state_.IsAllBankIdleInRank(i);\n            if (all_idle) {\n                simple_stats_.IncrementVec(\"all_bank_idle_cycles\", i);\n                channel_state_.rank_idle_cycles[i] += 1;\n            } else {\n                simple_stats_.IncrementVec(\"rank_active_cycles\", i);\n                // reset\n                channel_state_.rank_idle_cycles[i] = 0;\n            }\n        }\n    }\n\n    // power updates pt 2: move idle ranks into self-refresh mode to save power\n    if (config_.enable_self_refresh && !cmd_issued) {\n        for (auto i = 0; i < config_.ranks; i++) {\n            if (channel_state_.IsRankSelfRefreshing(i)) {\n                // wake up!\n                if (!cmd_queue_.rank_q_empty[i]) {\n                    auto addr = Address();\n                    addr.rank = i;\n                    auto cmd = Command(CommandType::SREF_EXIT, addr, -1);\n                    cmd = channel_state_.GetReadyCommand(cmd, clk_);\n                    if (cmd.IsValid()) {\n                        IssueCommand(cmd);\n                        break;\n                    }\n                }\n            } else {\n                if (cmd_queue_.rank_q_empty[i] &&\n                    channel_state_.rank_idle_cycles[i] >=\n                        config_.sref_threshold) {\n                    auto addr = Address();\n                    addr.rank = i;\n                    auto cmd = Command(CommandType::SREF_ENTER, addr, -1);\n                    cmd = channel_state_.GetReadyCommand(cmd, clk_);\n                    if (cmd.IsValid()) {\n                        IssueCommand(cmd);\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    ScheduleTransaction();\n    clk_++;\n    cmd_queue_.ClockTick();\n    simple_stats_.Increment(\"num_cycles\");\n    return;\n}\n\nbool Controller::WillAcceptTransaction(uint64_t hex_addr, bool is_write) const {\n    if (is_unified_queue_) {\n        return unified_queue_.size() < unified_queue_.capacity();\n    } else if (!is_write) {\n        return read_queue_.size() < read_queue_.capacity();\n    } else {\n        return write_buffer_.size() < write_buffer_.capacity();\n    }\n}\n\nbool Controller::AddTransaction(Transaction trans) {\n    trans.added_cycle = clk_;\n    simple_stats_.AddValue(\"interarrival_latency\", clk_ - last_trans_clk_);\n    last_trans_clk_ = clk_;\n\n    if (trans.is_write) {\n        if (pending_wr_q_.count(trans.addr) == 0) {  // can not merge writes\n            pending_wr_q_.insert(std::make_pair(trans.addr, trans));\n            if (is_unified_queue_) {\n                unified_queue_.push_back(trans);\n            } else {\n                write_buffer_.push_back(trans);\n            }\n        }\n        trans.complete_cycle = clk_ + 1;\n        return_queue_.push_back(trans);\n        return true;\n    } else {  // read\n        // if in write buffer, use the write buffer value\n        if (pending_wr_q_.count(trans.addr) > 0) {\n            trans.complete_cycle = clk_ + 1;\n            return_queue_.push_back(trans);\n            return true;\n        }\n        pending_rd_q_.insert(std::make_pair(trans.addr, trans));\n        if (pending_rd_q_.count(trans.addr) == 1) {\n            if (is_unified_queue_) {\n                unified_queue_.push_back(trans);\n            } else {\n                read_queue_.push_back(trans);\n            }\n        }\n        return true;\n    }\n}\n\nvoid Controller::ScheduleTransaction() {\n    // determine whether to schedule read or write\n    if (write_draining_ == 0 && !is_unified_queue_) {\n        // we basically have a upper and lower threshold for write buffer\n        if ((write_buffer_.size() >= write_buffer_.capacity()) ||\n            (write_buffer_.size() > 8 && cmd_queue_.QueueEmpty())) {\n            write_draining_ = write_buffer_.size();\n        }\n    }\n\n    std::vector<Transaction> &queue =\n        is_unified_queue_ ? unified_queue_\n                          : write_draining_ > 0 ? write_buffer_ : read_queue_;\n    for (auto it = queue.begin(); it != queue.end(); it++) {\n        auto cmd = TransToCommand(*it);\n        if (cmd_queue_.WillAcceptCommand(cmd.Rank(), cmd.Bankgroup(),\n                                         cmd.Bank())) {\n            if (!is_unified_queue_ && cmd.IsWrite()) {\n                // Enforce R->W dependency\n                if (pending_rd_q_.count(it->addr) > 0) {\n                    write_draining_ = 0;\n                    break;\n                }\n                write_draining_ -= 1;\n            }\n            cmd_queue_.AddCommand(cmd);\n            queue.erase(it);\n            break;\n        }\n    }\n}\n\nvoid Controller::IssueCommand(const Command &cmd) {\n#ifdef CMD_TRACE\n    cmd_trace_ << std::left << std::setw(18) << clk_ << \" \" << cmd << std::endl;\n#endif  // CMD_TRACE\n#ifdef THERMAL\n    // add channel in, only needed by thermal module\n    thermal_calc_.UpdateCMDPower(channel_id_, cmd, clk_);\n#endif  // THERMAL\n    // if read/write, update pending queue and return queue\n    if (cmd.IsRead()) {\n        auto num_reads = pending_rd_q_.count(cmd.hex_addr);\n        if (num_reads == 0) {\n            std::cerr << cmd.hex_addr << \" not in read queue! \" << std::endl;\n            exit(1);\n        }\n        // if there are multiple reads pending return them all\n        while (num_reads > 0) {\n            auto it = pending_rd_q_.find(cmd.hex_addr);\n            it->second.complete_cycle = clk_ + config_.read_delay;\n            return_queue_.push_back(it->second);\n            pending_rd_q_.erase(it);\n            num_reads -= 1;\n        }\n    } else if (cmd.IsWrite()) {\n        // there should be only 1 write to the same location at a time\n        auto it = pending_wr_q_.find(cmd.hex_addr);\n        if (it == pending_wr_q_.end()) {\n            std::cerr << cmd.hex_addr << \" not in write queue!\" << std::endl;\n            exit(1);\n        }\n        auto wr_lat = clk_ - it->second.added_cycle + config_.write_delay;\n        simple_stats_.AddValue(\"write_latency\", wr_lat);\n        pending_wr_q_.erase(it);\n    }\n    // must update stats before states (for row hits)\n    UpdateCommandStats(cmd);\n    channel_state_.UpdateTimingAndStates(cmd, clk_);\n}\n\nCommand Controller::TransToCommand(const Transaction &trans) {\n    auto addr = config_.AddressMapping(trans.addr);\n    CommandType cmd_type;\n    if (row_buf_policy_ == RowBufPolicy::OPEN_PAGE) {\n        cmd_type = trans.is_write ? CommandType::WRITE : CommandType::READ;\n    } else {\n        cmd_type = trans.is_write ? CommandType::WRITE_PRECHARGE\n                                  : CommandType::READ_PRECHARGE;\n    }\n    return Command(cmd_type, addr, trans.addr);\n}\n\nint Controller::QueueUsage() const { return cmd_queue_.QueueUsage(); }\n\nvoid Controller::PrintEpochStats() {\n    simple_stats_.Increment(\"epoch_num\");\n    simple_stats_.PrintEpochStats();\n#ifdef THERMAL\n    for (int r = 0; r < config_.ranks; r++) {\n        double bg_energy = simple_stats_.RankBackgroundEnergy(r);\n        thermal_calc_.UpdateBackgroundEnergy(channel_id_, r, bg_energy);\n    }\n#endif  // THERMAL\n    return;\n}\n\nvoid Controller::PrintFinalStats() {\n    simple_stats_.PrintFinalStats();\n\n#ifdef THERMAL\n    for (int r = 0; r < config_.ranks; r++) {\n        double bg_energy = simple_stats_.RankBackgroundEnergy(r);\n        thermal_calc_.UpdateBackgroundEnergy(channel_id_, r, bg_energy);\n    }\n#endif  // THERMAL\n    return;\n}\n\nvoid Controller::UpdateCommandStats(const Command &cmd) {\n    switch (cmd.cmd_type) {\n        case CommandType::READ:\n        case CommandType::READ_PRECHARGE:\n            simple_stats_.Increment(\"num_read_cmds\");\n            if (channel_state_.RowHitCount(cmd.Rank(), cmd.Bankgroup(),\n                                           cmd.Bank()) != 0) {\n                simple_stats_.Increment(\"num_read_row_hits\");\n            }\n            break;\n        case CommandType::WRITE:\n        case CommandType::WRITE_PRECHARGE:\n            simple_stats_.Increment(\"num_write_cmds\");\n            if (channel_state_.RowHitCount(cmd.Rank(), cmd.Bankgroup(),\n                                           cmd.Bank()) != 0) {\n                simple_stats_.Increment(\"num_write_row_hits\");\n            }\n            break;\n        case CommandType::ACTIVATE:\n            simple_stats_.Increment(\"num_act_cmds\");\n            break;\n        case CommandType::PRECHARGE:\n            simple_stats_.Increment(\"num_pre_cmds\");\n            break;\n        case CommandType::REFRESH:\n            simple_stats_.Increment(\"num_ref_cmds\");\n            break;\n        case CommandType::REFRESH_BANK:\n            simple_stats_.Increment(\"num_refb_cmds\");\n            break;\n        case CommandType::SREF_ENTER:\n            simple_stats_.Increment(\"num_srefe_cmds\");\n            break;\n        case CommandType::SREF_EXIT:\n            simple_stats_.Increment(\"num_srefx_cmds\");\n            break;\n        default:\n            AbruptExit(__FILE__, __LINE__);\n    }\n}\n\n}  // namespace dramsim3\n"
  },
  {
    "path": "src/DRAMsim3/src/controller.h",
    "content": "#ifndef __CONTROLLER_H\n#define __CONTROLLER_H\n\n#include <fstream>\n#include <map>\n#include <unordered_set>\n#include <vector>\n#include \"channel_state.h\"\n#include \"command_queue.h\"\n#include \"common.h\"\n#include \"refresh.h\"\n#include \"simple_stats.h\"\n\n#ifdef THERMAL\n#include \"thermal.h\"\n#endif  // THERMAL\n\nnamespace dramsim3 {\n\nenum class RowBufPolicy { OPEN_PAGE, CLOSE_PAGE, SIZE };\n\nclass Controller {\n   public:\n#ifdef THERMAL\n    Controller(int channel, const Config &config, const Timing &timing,\n               ThermalCalculator &thermalcalc);\n#else\n    Controller(int channel, const Config &config, const Timing &timing);\n#endif  // THERMAL\n    void ClockTick();\n    bool WillAcceptTransaction(uint64_t hex_addr, bool is_write) const;\n    bool AddTransaction(Transaction trans);\n    int QueueUsage() const;\n    // Stats output\n    void PrintEpochStats();\n    void PrintFinalStats();\n    void ResetStats() { simple_stats_.Reset(); }\n    std::pair<uint64_t, int> ReturnDoneTrans(uint64_t clock);\n\n    int channel_id_;\n\n   private:\n    uint64_t clk_;\n    const Config &config_;\n    SimpleStats simple_stats_;\n    ChannelState channel_state_;\n    CommandQueue cmd_queue_;\n    Refresh refresh_;\n\n#ifdef THERMAL\n    ThermalCalculator &thermal_calc_;\n#endif  // THERMAL\n\n    // queue that takes transactions from CPU side\n    bool is_unified_queue_;\n    std::vector<Transaction> unified_queue_;\n    std::vector<Transaction> read_queue_;\n    std::vector<Transaction> write_buffer_;\n\n    // transactions that are not completed, use map for convenience\n    std::multimap<uint64_t, Transaction> pending_rd_q_;\n    std::multimap<uint64_t, Transaction> pending_wr_q_;\n\n    // completed transactions\n    std::vector<Transaction> return_queue_;\n\n    // row buffer policy\n    RowBufPolicy row_buf_policy_;\n\n#ifdef CMD_TRACE\n    std::ofstream cmd_trace_;\n#endif  // CMD_TRACE\n\n    // used to calculate inter-arrival latency\n    uint64_t last_trans_clk_;\n\n    // transaction queueing\n    int write_draining_;\n    void ScheduleTransaction();\n    void IssueCommand(const Command &tmp_cmd);\n    Command TransToCommand(const Transaction &trans);\n    void UpdateCommandStats(const Command &cmd);\n};\n}  // namespace dramsim3\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/cpu.cc",
    "content": "#include \"cpu.h\"\n\nnamespace dramsim3 {\n\nvoid RandomCPU::ClockTick() {\n    // Create random CPU requests at full speed\n    // this is useful to exploit the parallelism of a DRAM protocol\n    // and is also immune to address mapping and scheduling policies\n    memory_system_.ClockTick();\n    if (get_next_) {\n        last_addr_ = gen();\n        last_write_ = (gen() % 3 == 0);\n    }\n    get_next_ = memory_system_.WillAcceptTransaction(last_addr_, last_write_);\n    if (get_next_) {\n        memory_system_.AddTransaction(last_addr_, last_write_);\n    }\n    clk_++;\n    return;\n}\n\nvoid StreamCPU::ClockTick() {\n    // stream-add, read 2 arrays, add them up to the third array\n    // this is a very simple approximate but should be able to produce\n    // enough buffer hits\n\n    // moving on to next set of arrays\n    memory_system_.ClockTick();\n    if (offset_ >= array_size_ || clk_ == 0) {\n        addr_a_ = gen();\n        addr_b_ = gen();\n        addr_c_ = gen();\n        offset_ = 0;\n    }\n\n    if (!inserted_a_ &&\n        memory_system_.WillAcceptTransaction(addr_a_ + offset_, false)) {\n        memory_system_.AddTransaction(addr_a_ + offset_, false);\n        inserted_a_ = true;\n    }\n    if (!inserted_b_ &&\n        memory_system_.WillAcceptTransaction(addr_b_ + offset_, false)) {\n        memory_system_.AddTransaction(addr_b_ + offset_, false);\n        inserted_b_ = true;\n    }\n    if (!inserted_c_ &&\n        memory_system_.WillAcceptTransaction(addr_c_ + offset_, true)) {\n        memory_system_.AddTransaction(addr_c_ + offset_, true);\n        inserted_c_ = true;\n    }\n    // moving on to next element\n    if (inserted_a_ && inserted_b_ && inserted_c_) {\n        offset_ += stride_;\n        inserted_a_ = false;\n        inserted_b_ = false;\n        inserted_c_ = false;\n    }\n    clk_++;\n    return;\n}\n\nTraceBasedCPU::TraceBasedCPU(const std::string& config_file,\n                             const std::string& output_dir,\n                             const std::string& trace_file)\n    : CPU(config_file, output_dir) {\n    trace_file_.open(trace_file);\n    if (trace_file_.fail()) {\n        std::cerr << \"Trace file does not exist\" << std::endl;\n        AbruptExit(__FILE__, __LINE__);\n    }\n}\n\nvoid TraceBasedCPU::ClockTick() {\n    memory_system_.ClockTick();\n    if (!trace_file_.eof()) {\n        if (get_next_) {\n            get_next_ = false;\n            trace_file_ >> trans_;\n        }\n        if (trans_.added_cycle <= clk_) {\n            get_next_ = memory_system_.WillAcceptTransaction(trans_.addr,\n                                                             trans_.is_write);\n            if (get_next_) {\n                memory_system_.AddTransaction(trans_.addr, trans_.is_write);\n            }\n        }\n    }\n    clk_++;\n    return;\n}\n\n}  // namespace dramsim3\n"
  },
  {
    "path": "src/DRAMsim3/src/cpu.h",
    "content": "#ifndef __CPU_H\n#define __CPU_H\n\n#include <fstream>\n#include <functional>\n#include <random>\n#include <string>\n#include \"memory_system.h\"\n\nnamespace dramsim3 {\n\nclass CPU {\n   public:\n    CPU(const std::string& config_file, const std::string& output_dir)\n        : memory_system_(\n              config_file, output_dir,\n              std::bind(&CPU::ReadCallBack, this, std::placeholders::_1),\n              std::bind(&CPU::WriteCallBack, this, std::placeholders::_1)),\n          clk_(0) {}\n    virtual void ClockTick() = 0;\n    void ReadCallBack(uint64_t addr) { return; }\n    void WriteCallBack(uint64_t addr) { return; }\n    void PrintStats() { memory_system_.PrintStats(); }\n\n   protected:\n    MemorySystem memory_system_;\n    uint64_t clk_;\n};\n\nclass RandomCPU : public CPU {\n   public:\n    using CPU::CPU;\n    void ClockTick() override;\n\n   private:\n    uint64_t last_addr_;\n    bool last_write_ = false;\n    std::mt19937_64 gen;\n    bool get_next_ = true;\n};\n\nclass StreamCPU : public CPU {\n   public:\n    using CPU::CPU;\n    void ClockTick() override;\n\n   private:\n    uint64_t addr_a_, addr_b_, addr_c_, offset_ = 0;\n    std::mt19937_64 gen;\n    bool inserted_a_ = false;\n    bool inserted_b_ = false;\n    bool inserted_c_ = false;\n    const uint64_t array_size_ = 2 << 20;  // elements in array\n    const int stride_ = 64;                // stride in bytes\n};\n\nclass TraceBasedCPU : public CPU {\n   public:\n    TraceBasedCPU(const std::string& config_file, const std::string& output_dir,\n                  const std::string& trace_file);\n    ~TraceBasedCPU() { trace_file_.close(); }\n    void ClockTick() override;\n\n   private:\n    std::ifstream trace_file_;\n    Transaction trans_;\n    bool get_next_ = true;\n};\n\n}  // namespace dramsim3\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/dram_system.cc",
    "content": "#include \"dram_system.h\"\n\n#include <assert.h>\n\nnamespace dramsim3 {\n\n// alternative way is to assign the id in constructor but this is less\n// destructive\nint BaseDRAMSystem::total_channels_ = 0;\n\nBaseDRAMSystem::BaseDRAMSystem(Config &config, const std::string &output_dir,\n                               std::function<void(uint64_t)> read_callback,\n                               std::function<void(uint64_t)> write_callback)\n    : read_callback_(read_callback),\n      write_callback_(write_callback),\n      last_req_clk_(0),\n      config_(config),\n      timing_(config_),\n#ifdef THERMAL\n      thermal_calc_(config_),\n#endif  // THERMAL\n      clk_(0) {\n    total_channels_ += config_.channels;\n\n#ifdef ADDR_TRACE\n    std::string addr_trace_name = config_.output_prefix + \"addr.trace\";\n    address_trace_.open(addr_trace_name);\n#endif\n}\n\nint BaseDRAMSystem::GetChannel(uint64_t hex_addr) const {\n    hex_addr >>= config_.shift_bits;\n    return (hex_addr >> config_.ch_pos) & config_.ch_mask;\n}\n\nvoid BaseDRAMSystem::PrintEpochStats() {\n    // first epoch, print bracket\n    if (clk_ - config_.epoch_period == 0) {\n        std::ofstream epoch_out(config_.json_epoch_name, std::ofstream::out);\n        epoch_out << \"[\";\n    }\n    for (size_t i = 0; i < ctrls_.size(); i++) {\n        ctrls_[i]->PrintEpochStats();\n        std::ofstream epoch_out(config_.json_epoch_name, std::ofstream::app);\n        epoch_out << \",\" << std::endl;\n    }\n#ifdef THERMAL\n    thermal_calc_.PrintTransPT(clk_);\n#endif  // THERMAL\n    return;\n}\n\nvoid BaseDRAMSystem::PrintStats() {\n    // Finish epoch output, remove last comma and append ]\n    std::ofstream epoch_out(config_.json_epoch_name, std::ios_base::in |\n                                                         std::ios_base::out |\n                                                         std::ios_base::ate);\n    epoch_out.seekp(-2, std::ios_base::cur);\n    epoch_out.write(\"]\", 1);\n    epoch_out.close();\n\n    std::ofstream json_out(config_.json_stats_name, std::ofstream::out);\n    json_out << \"{\";\n\n    // close it now so that each channel can handle it\n    json_out.close();\n    for (size_t i = 0; i < ctrls_.size(); i++) {\n        ctrls_[i]->PrintFinalStats();\n        if (i != ctrls_.size() - 1) {\n            std::ofstream chan_out(config_.json_stats_name, std::ofstream::app);\n            chan_out << \",\" << std::endl;\n        }\n    }\n    json_out.open(config_.json_stats_name, std::ofstream::app);\n    json_out << \"}\";\n\n#ifdef THERMAL\n    thermal_calc_.PrintFinalPT(clk_);\n#endif  // THERMAL\n}\n\nvoid BaseDRAMSystem::ResetStats() {\n    for (size_t i = 0; i < ctrls_.size(); i++) {\n        ctrls_[i]->ResetStats();\n    }\n}\n\nvoid BaseDRAMSystem::RegisterCallbacks(\n    std::function<void(uint64_t)> read_callback,\n    std::function<void(uint64_t)> write_callback) {\n    // TODO this should be propagated to controllers\n    read_callback_ = read_callback;\n    write_callback_ = write_callback;\n}\n\nJedecDRAMSystem::JedecDRAMSystem(Config &config, const std::string &output_dir,\n                                 std::function<void(uint64_t)> read_callback,\n                                 std::function<void(uint64_t)> write_callback)\n    : BaseDRAMSystem(config, output_dir, read_callback, write_callback) {\n    if (config_.IsHMC()) {\n        std::cerr << \"Initialized a memory system with an HMC config file!\"\n                  << std::endl;\n        AbruptExit(__FILE__, __LINE__);\n    }\n\n    ctrls_.reserve(config_.channels);\n    for (auto i = 0; i < config_.channels; i++) {\n#ifdef THERMAL\n        ctrls_.push_back(new Controller(i, config_, timing_, thermal_calc_));\n#else\n        ctrls_.push_back(new Controller(i, config_, timing_));\n#endif  // THERMAL\n    }\n}\n\nJedecDRAMSystem::~JedecDRAMSystem() {\n    for (auto it = ctrls_.begin(); it != ctrls_.end(); it++) {\n        delete (*it);\n    }\n}\n\nbool JedecDRAMSystem::WillAcceptTransaction(uint64_t hex_addr,\n                                            bool is_write) const {\n    int channel = GetChannel(hex_addr);\n    return ctrls_[channel]->WillAcceptTransaction(hex_addr, is_write);\n}\n\nbool JedecDRAMSystem::AddTransaction(uint64_t hex_addr, bool is_write) {\n// Record trace - Record address trace for debugging or other purposes\n#ifdef ADDR_TRACE\n    address_trace_ << std::hex << hex_addr << std::dec << \" \"\n                   << (is_write ? \"WRITE \" : \"READ \") << clk_ << std::endl;\n#endif\n\n    int channel = GetChannel(hex_addr);\n    bool ok = ctrls_[channel]->WillAcceptTransaction(hex_addr, is_write);\n\n    assert(ok);\n    if (ok) {\n        Transaction trans = Transaction(hex_addr, is_write);\n        ctrls_[channel]->AddTransaction(trans);\n    }\n    last_req_clk_ = clk_;\n    return ok;\n}\n\nvoid JedecDRAMSystem::ClockTick() {\n    for (size_t i = 0; i < ctrls_.size(); i++) {\n        // look ahead and return earlier\n        while (true) {\n            auto pair = ctrls_[i]->ReturnDoneTrans(clk_);\n            if (pair.second == 1) {\n                write_callback_(pair.first);\n            } else if (pair.second == 0) {\n                read_callback_(pair.first);\n            } else {\n                break;\n            }\n        }\n    }\n    for (size_t i = 0; i < ctrls_.size(); i++) {\n        ctrls_[i]->ClockTick();\n    }\n    clk_++;\n\n    if (clk_ % config_.epoch_period == 0) {\n        PrintEpochStats();\n    }\n    return;\n}\n\nIdealDRAMSystem::IdealDRAMSystem(Config &config, const std::string &output_dir,\n                                 std::function<void(uint64_t)> read_callback,\n                                 std::function<void(uint64_t)> write_callback)\n    : BaseDRAMSystem(config, output_dir, read_callback, write_callback),\n      latency_(config_.ideal_memory_latency) {}\n\nIdealDRAMSystem::~IdealDRAMSystem() {}\n\nbool IdealDRAMSystem::AddTransaction(uint64_t hex_addr, bool is_write) {\n    auto trans = Transaction(hex_addr, is_write);\n    trans.added_cycle = clk_;\n    infinite_buffer_q_.push_back(trans);\n    return true;\n}\n\nvoid IdealDRAMSystem::ClockTick() {\n    for (auto trans_it = infinite_buffer_q_.begin();\n         trans_it != infinite_buffer_q_.end();) {\n        if (clk_ - trans_it->added_cycle >= static_cast<uint64_t>(latency_)) {\n            if (trans_it->is_write) {\n                write_callback_(trans_it->addr);\n            } else {\n                read_callback_(trans_it->addr);\n            }\n            trans_it = infinite_buffer_q_.erase(trans_it++);\n        }\n        if (trans_it != infinite_buffer_q_.end()) {\n            ++trans_it;\n        }\n    }\n\n    clk_++;\n    return;\n}\n\n}  // namespace dramsim3\n"
  },
  {
    "path": "src/DRAMsim3/src/dram_system.h",
    "content": "#ifndef __DRAM_SYSTEM_H\n#define __DRAM_SYSTEM_H\n\n#include <fstream>\n#include <string>\n#include <vector>\n\n#include \"common.h\"\n#include \"configuration.h\"\n#include \"controller.h\"\n#include \"timing.h\"\n\n#ifdef THERMAL\n#include \"thermal.h\"\n#endif  // THERMAL\n\nnamespace dramsim3 {\n\nclass BaseDRAMSystem {\n   public:\n    BaseDRAMSystem(Config &config, const std::string &output_dir,\n                   std::function<void(uint64_t)> read_callback,\n                   std::function<void(uint64_t)> write_callback);\n    virtual ~BaseDRAMSystem() {}\n    void RegisterCallbacks(std::function<void(uint64_t)> read_callback,\n                           std::function<void(uint64_t)> write_callback);\n    void PrintEpochStats();\n    void PrintStats();\n    void ResetStats();\n\n    virtual bool WillAcceptTransaction(uint64_t hex_addr,\n                                       bool is_write) const = 0;\n    virtual bool AddTransaction(uint64_t hex_addr, bool is_write) = 0;\n    virtual void ClockTick() = 0;\n    int GetChannel(uint64_t hex_addr) const;\n\n    std::function<void(uint64_t req_id)> read_callback_, write_callback_;\n    static int total_channels_;\n\n   protected:\n    uint64_t id_;\n    uint64_t last_req_clk_;\n    Config &config_;\n    Timing timing_;\n    uint64_t parallel_cycles_;\n    uint64_t serial_cycles_;\n\n#ifdef THERMAL\n    ThermalCalculator thermal_calc_;\n#endif  // THERMAL\n\n    uint64_t clk_;\n    std::vector<Controller*> ctrls_;\n\n#ifdef ADDR_TRACE\n    std::ofstream address_trace_;\n#endif  // ADDR_TRACE\n};\n\n// hmmm not sure this is the best naming...\nclass JedecDRAMSystem : public BaseDRAMSystem {\n   public:\n    JedecDRAMSystem(Config &config, const std::string &output_dir,\n                    std::function<void(uint64_t)> read_callback,\n                    std::function<void(uint64_t)> write_callback);\n    ~JedecDRAMSystem();\n    bool WillAcceptTransaction(uint64_t hex_addr, bool is_write) const override;\n    bool AddTransaction(uint64_t hex_addr, bool is_write) override;\n    void ClockTick() override;\n};\n\n// Model a memorysystem with an infinite bandwidth and a fixed latency (possibly\n// zero) To establish a baseline for what a 'good' memory standard can and\n// cannot do for a given application\nclass IdealDRAMSystem : public BaseDRAMSystem {\n   public:\n    IdealDRAMSystem(Config &config, const std::string &output_dir,\n                    std::function<void(uint64_t)> read_callback,\n                    std::function<void(uint64_t)> write_callback);\n    ~IdealDRAMSystem();\n    bool WillAcceptTransaction(uint64_t hex_addr,\n                               bool is_write) const override {\n        return true;\n    };\n    bool AddTransaction(uint64_t hex_addr, bool is_write) override;\n    void ClockTick() override;\n\n   private:\n    int latency_;\n    std::vector<Transaction> infinite_buffer_q_;\n};\n\n}  // namespace dramsim3\n#endif  // __DRAM_SYSTEM_H\n"
  },
  {
    "path": "src/DRAMsim3/src/dramsim3.h",
    "content": "#ifndef __MEMORY_SYSTEM__H\n#define __MEMORY_SYSTEM__H\n\n#include <functional>\n#include <string>\n\nnamespace dramsim3 {\n\n// This should be the interface class that deals with CPU\nclass MemorySystem {\n   public:\n    MemorySystem(const std::string &config_file, const std::string &output_dir,\n                 std::function<void(uint64_t)> read_callback,\n                 std::function<void(uint64_t)> write_callback);\n    ~MemorySystem();\n    void ClockTick();\n    void RegisterCallbacks(std::function<void(uint64_t)> read_callback,\n                           std::function<void(uint64_t)> write_callback);\n    double GetTCK() const;\n    int GetBusBits() const;\n    int GetBurstLength() const;\n    int GetQueueSize() const;\n    void PrintStats() const;\n    void ResetStats();\n\n    bool WillAcceptTransaction(uint64_t hex_addr, bool is_write) const;\n    bool AddTransaction(uint64_t hex_addr, bool is_write);\n};\n\nMemorySystem* GetMemorySystem(const std::string &config_file, const std::string &output_dir,\n                 std::function<void(uint64_t)> read_callback,\n                 std::function<void(uint64_t)> write_callback);\n}  // namespace dramsim3\n\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/hmc.cc",
    "content": "#include \"hmc.h\"\n\nnamespace dramsim3 {\n\nHMCRequest::HMCRequest(HMCReqType req_type, uint64_t hex_addr, int vault)\n    : type(req_type), mem_operand(hex_addr), vault(vault) {\n    is_write = type >= HMCReqType::WR0 && type <= HMCReqType::P_WR256;\n    // given that vaults could be 16 (Gen1) or 32(Gen2), using % 4\n    // to partition vaults to quads\n    quad = vault % 4;\n    switch (req_type) {\n        case HMCReqType::RD0:\n        case HMCReqType::WR0:\n            flits = 0;\n            break;\n        case HMCReqType::RD16:\n        case HMCReqType::RD32:\n        case HMCReqType::RD48:\n        case HMCReqType::RD64:\n        case HMCReqType::RD80:\n        case HMCReqType::RD96:\n        case HMCReqType::RD112:\n        case HMCReqType::RD128:\n        case HMCReqType::RD256:\n            flits = 1;\n            break;\n        case HMCReqType::WR16:\n        case HMCReqType::P_WR16:\n            flits = 2;\n            break;\n        case HMCReqType::WR32:\n        case HMCReqType::P_WR32:\n            flits = 3;\n            break;\n        case HMCReqType::WR48:\n        case HMCReqType::P_WR48:\n            flits = 4;\n            break;\n        case HMCReqType::WR64:\n        case HMCReqType::P_WR64:\n            flits = 5;\n            break;\n        case HMCReqType::WR80:\n        case HMCReqType::P_WR80:\n            flits = 6;\n            break;\n        case HMCReqType::WR96:\n        case HMCReqType::P_WR96:\n            flits = 7;\n            break;\n        case HMCReqType::WR112:\n        case HMCReqType::P_WR112:\n            flits = 8;\n            break;\n        case HMCReqType::WR128:\n        case HMCReqType::P_WR128:\n            flits = 9;\n            break;\n        case HMCReqType::WR256:\n        case HMCReqType::P_WR256:\n            flits = 17;\n            break;\n        case HMCReqType::ADD8:\n        case HMCReqType::ADD16:\n            flits = 2;\n            break;\n        case HMCReqType::P_2ADD8:\n        case HMCReqType::P_ADD16:\n            flits = 2;\n            break;\n        case HMCReqType::ADDS8R:\n        case HMCReqType::ADDS16R:\n            flits = 2;\n            break;\n        case HMCReqType::INC8:\n            flits = 1;\n            break;\n        case HMCReqType::P_INC8:\n            flits = 1;\n            break;\n        case HMCReqType::XOR16:\n        case HMCReqType::OR16:\n        case HMCReqType::NOR16:\n        case HMCReqType::AND16:\n        case HMCReqType::NAND16:\n        case HMCReqType::CASGT8:\n        case HMCReqType::CASGT16:\n        case HMCReqType::CASLT8:\n        case HMCReqType::CASLT16:\n        case HMCReqType::CASEQ8:\n        case HMCReqType::CASZERO16:\n            flits = 2;\n            break;\n        case HMCReqType::EQ8:\n        case HMCReqType::EQ16:\n        case HMCReqType::BWR:\n            flits = 2;\n            break;\n        case HMCReqType::P_BWR:\n            flits = 2;\n            break;\n        case HMCReqType::BWR8R:\n        case HMCReqType::SWAP16:\n            flits = 2;\n            break;\n        default:\n            AbruptExit(__FILE__, __LINE__);\n            break;\n    }\n}\n\nHMCResponse::HMCResponse(uint64_t id, HMCReqType req_type, int dest_link,\n                         int src_quad)\n    : resp_id(id), link(dest_link), quad(src_quad) {\n    switch (req_type) {\n        case HMCReqType::RD0:\n            type = HMCRespType::RD_RS;\n            flits = 0;\n            break;\n        case HMCReqType::RD16:\n            type = HMCRespType::RD_RS;\n            flits = 2;\n            break;\n        case HMCReqType::RD32:\n            type = HMCRespType::RD_RS;\n            flits = 3;\n            break;\n        case HMCReqType::RD48:\n            type = HMCRespType::RD_RS;\n            flits = 4;\n            break;\n        case HMCReqType::RD64:\n            type = HMCRespType::RD_RS;\n            flits = 5;\n            break;\n        case HMCReqType::RD80:\n            type = HMCRespType::RD_RS;\n            flits = 6;\n            break;\n        case HMCReqType::RD96:\n            type = HMCRespType::RD_RS;\n            flits = 7;\n            break;\n        case HMCReqType::RD112:\n            type = HMCRespType::RD_RS;\n            flits = 8;\n            break;\n        case HMCReqType::RD128:\n            type = HMCRespType::RD_RS;\n            flits = 9;\n            break;\n        case HMCReqType::RD256:\n            type = HMCRespType::RD_RS;\n            flits = 17;\n            break;\n        case HMCReqType::WR0:\n            flits = 0;\n            type = HMCRespType::WR_RS;\n            break;\n        case HMCReqType::WR16:\n        case HMCReqType::WR32:\n        case HMCReqType::WR48:\n        case HMCReqType::WR64:\n        case HMCReqType::WR80:\n        case HMCReqType::WR96:\n        case HMCReqType::WR112:\n        case HMCReqType::WR128:\n        case HMCReqType::WR256:\n            type = HMCRespType::WR_RS;\n            flits = 1;\n            break;\n        case HMCReqType::P_WR16:\n        case HMCReqType::P_WR32:\n        case HMCReqType::P_WR48:\n        case HMCReqType::P_WR64:\n        case HMCReqType::P_WR80:\n        case HMCReqType::P_WR96:\n        case HMCReqType::P_WR112:\n        case HMCReqType::P_WR128:\n        case HMCReqType::P_WR256:\n            type = HMCRespType::NONE;\n            flits = 0;\n            break;\n        case HMCReqType::ADD8:\n        case HMCReqType::ADD16:\n            type = HMCRespType::WR_RS;\n            flits = 1;\n            break;\n        case HMCReqType::P_2ADD8:\n        case HMCReqType::P_ADD16:\n            type = HMCRespType::NONE;\n            flits = 0;\n            break;\n        case HMCReqType::ADDS8R:\n        case HMCReqType::ADDS16R:\n            type = HMCRespType::RD_RS;\n            flits = 2;\n            break;\n        case HMCReqType::INC8:\n            type = HMCRespType::WR_RS;\n            flits = 1;\n            break;\n        case HMCReqType::P_INC8:\n            type = HMCRespType::NONE;\n            flits = 0;\n            break;\n        case HMCReqType::XOR16:\n        case HMCReqType::OR16:\n        case HMCReqType::NOR16:\n        case HMCReqType::AND16:\n        case HMCReqType::NAND16:\n        case HMCReqType::CASGT8:\n        case HMCReqType::CASGT16:\n        case HMCReqType::CASLT8:\n        case HMCReqType::CASLT16:\n        case HMCReqType::CASEQ8:\n        case HMCReqType::CASZERO16:\n            type = HMCRespType::RD_RS;\n            flits = 2;\n            break;\n        case HMCReqType::EQ8:\n        case HMCReqType::EQ16:\n        case HMCReqType::BWR:\n            type = HMCRespType::WR_RS;\n            flits = 1;\n            break;\n        case HMCReqType::P_BWR:\n            type = HMCRespType::NONE;\n            flits = 0;\n            break;\n        case HMCReqType::BWR8R:\n        case HMCReqType::SWAP16:\n            type = HMCRespType::RD_RS;\n            flits = 2;\n            break;\n        default:\n            AbruptExit(__FILE__, __LINE__);\n            break;\n    }\n    return;\n}\n\nHMCMemorySystem::HMCMemorySystem(Config &config, const std::string &output_dir,\n                                 std::function<void(uint64_t)> read_callback,\n                                 std::function<void(uint64_t)> write_callback)\n    : BaseDRAMSystem(config, output_dir, read_callback, write_callback),\n      logic_clk_(0),\n      logic_ps_(0),\n      dram_ps_(0),\n      next_link_(0) {\n    // sanity check, this constructor should only be intialized using HMC\n    if (!config_.IsHMC()) {\n        std::cerr << \"Initialzed an HMC system without an HMC config file!\"\n                  << std::endl;\n        AbruptExit(__FILE__, __LINE__);\n    }\n\n    // setting up clock\n    SetClockRatio();\n\n    ctrls_.reserve(config_.channels);\n    for (int i = 0; i < config_.channels; i++) {\n#ifdef THERMAL\n        ctrls_.push_back(new Controller(i, config_, timing_, thermal_calc_));\n#else\n        ctrls_.push_back(new Controller(i, config_, timing_));\n#endif  // THERMAL\n    }\n    // initialize vaults and crossbar\n    // the first layer of xbar will be num_links * 4 (4 for quadrants)\n    // the second layer will be a 1:8 xbar\n    // (each quadrant has 8 vaults and each quadrant can access any ohter\n    // quadrant)\n    queue_depth_ = static_cast<size_t>(config_.xbar_queue_depth);\n    links_ = config_.num_links;\n    link_req_queues_.reserve(links_);\n    link_resp_queues_.reserve(links_);\n    for (int i = 0; i < links_; i++) {\n        link_req_queues_.push_back(std::vector<HMCRequest *>());\n        link_resp_queues_.push_back(std::vector<HMCResponse *>());\n    }\n\n    // don't want to hard coding it but there are 4 quads so it's kind of fixed\n    quad_req_queues_.reserve(4);\n    quad_resp_queues_.reserve(4);\n    for (int i = 0; i < 4; i++) {\n        quad_req_queues_.push_back(std::vector<HMCRequest *>());\n        quad_resp_queues_.push_back(std::vector<HMCResponse *>());\n    }\n\n    link_busy_.reserve(links_);\n    link_age_counter_.reserve(links_);\n    for (int i = 0; i < links_; i++) {\n        link_busy_.push_back(0);\n        link_age_counter_.push_back(0);\n    }\n}\n\nHMCMemorySystem::~HMCMemorySystem() {\n    for (auto &&vault_ptr : ctrls_) {\n        delete (vault_ptr);\n    }\n}\n\nvoid HMCMemorySystem::SetClockRatio() {\n    // There are 3 clock domains here, Link (super fast), logic (fast), DRAM\n    // (slow) We assume the logic process 1 flit per logic cycle and since the\n    // link takes several cycles to process 1 flit (128b), we can deduce logic\n    // speed according to link speed\n    ps_per_dram_ = 800;  // 800 ps\n    int link_cycles_per_flit = 128 / config_.link_width;\n    int logic_speed = config_.link_speed / link_cycles_per_flit;  // MHz\n    ps_per_logic_ =\n        static_cast<uint64_t>(1000000 / static_cast<double>(logic_speed));\n    if (ps_per_logic_ > ps_per_dram_) {\n        ps_per_logic_ = ps_per_dram_;\n    }\n    return;\n}\n\ninline void HMCMemorySystem::IterateNextLink() {\n    // determinining which link a request goes to has great impact on\n    // performance round robin , we can implement other schemes here later such\n    // as random but there're only at most 4 links so I suspect it would make a\n    // difference\n    next_link_ = (next_link_ + 1) % links_;\n    return;\n}\n\nbool HMCMemorySystem::WillAcceptTransaction(uint64_t hex_addr,\n                                            bool is_write) const {\n    bool insertable = false;\n    for (auto link_queue = link_req_queues_.begin();\n         link_queue != link_req_queues_.end(); link_queue++) {\n        if ((*link_queue).size() < queue_depth_) {\n            insertable = true;\n            break;\n        }\n    }\n    return insertable;\n}\n\nbool HMCMemorySystem::AddTransaction(uint64_t hex_addr, bool is_write) {\n    // to be compatible with other protocol we have this interface\n    // when using this intreface the size of each transaction will be block_size\n    HMCReqType req_type;\n    if (is_write) {\n        switch (config_.block_size) {\n            case 0:\n                req_type = HMCReqType::WR0;\n                break;\n            case 32:\n                req_type = HMCReqType::WR32;\n                break;\n            case 64:\n                req_type = HMCReqType::WR64;\n                break;\n            case 128:\n                req_type = HMCReqType::WR128;\n                break;\n            case 256:\n                req_type = HMCReqType::WR256;\n                break;\n            default:\n                req_type = HMCReqType::SIZE;\n                AbruptExit(__FILE__, __LINE__);\n                break;\n        }\n    } else {\n        switch (config_.block_size) {\n            case 0:\n                req_type = HMCReqType::RD0;\n                break;\n            case 32:\n                req_type = HMCReqType::RD32;\n                break;\n            case 64:\n                req_type = HMCReqType::RD64;\n                break;\n            case 128:\n                req_type = HMCReqType::RD128;\n                break;\n            case 256:\n                req_type = HMCReqType::RD256;\n                break;\n            default:\n                req_type = HMCReqType::SIZE;\n                AbruptExit(__FILE__, __LINE__);\n                break;\n        }\n    }\n    int vault = GetChannel(hex_addr);\n    HMCRequest *req = new HMCRequest(req_type, hex_addr, vault);\n    return InsertHMCReq(req);\n}\n\nbool HMCMemorySystem::InsertReqToLink(HMCRequest *req, int link) {\n    // These things need to happen when an HMC request is inserted to a link:\n    // 1. check if link queue full\n    // 2. set link field in the request packet\n    // 3. create corresponding response\n    // 4. increment link_age_counter_ so that arbitrate logic works\n    if (link_req_queues_[link].size() < queue_depth_) {\n        req->link = link;\n        link_req_queues_[link].push_back(req);\n        HMCResponse *resp =\n            new HMCResponse(req->mem_operand, req->type, link, req->quad);\n        resp_lookup_table_.insert(\n            std::pair<uint64_t, HMCResponse *>(resp->resp_id, resp));\n        link_age_counter_[link] = 1;\n        // stats_.interarrival_latency.AddValue(clk_ - last_req_clk_);\n        last_req_clk_ = clk_;\n        return true;\n    } else {\n        return false;\n    }\n}\n\nbool HMCMemorySystem::InsertHMCReq(HMCRequest *req) {\n    // most CPU models does not support simultaneous insertions\n    // if you want to actually simulate the multi-link feature\n    // then you have to call this function multiple times in 1 cycle\n    // TODO put a cap limit on how many times you can call this function per\n    // cycle\n    bool is_inserted = InsertReqToLink(req, next_link_);\n    if (!is_inserted) {\n        int start_link = next_link_;\n        IterateNextLink();\n        while (start_link != next_link_) {\n            if (InsertReqToLink(req, next_link_)) {\n                IterateNextLink();\n                return true;\n            } else {\n                IterateNextLink();\n            }\n        }\n        return false;\n    } else {\n        IterateNextLink();\n        return true;\n    }\n}\n\nvoid HMCMemorySystem::DrainRequests() {\n    // drain quad request queue to vaults\n    for (int i = 0; i < 4; i++) {\n        if (!quad_req_queues_[i].empty() &&\n            quad_resp_queues_[i].size() < queue_depth_) {\n            HMCRequest *req = quad_req_queues_[i].front();\n            if (req->exit_time <= logic_clk_) {\n                if (ctrls_[req->vault]->WillAcceptTransaction(req->mem_operand,\n                                                              req->is_write)) {\n                    InsertReqToDRAM(req);\n                    delete (req);\n                    quad_req_queues_[i].erase(quad_req_queues_[i].begin());\n                }\n            }\n        }\n    }\n\n    // drain xbar\n    for (auto &&i : quad_busy_) {\n        if (i > 0) {\n            i -= 2;\n        }\n    }\n\n    // drain requests from link to quad buffers\n    std::vector<int> age_queue = BuildAgeQueue(link_age_counter_);\n    while (!age_queue.empty()) {\n        int src_link = age_queue.front();\n        int dest_quad = link_req_queues_[src_link].front()->quad;\n        if (quad_req_queues_[dest_quad].size() < queue_depth_ &&\n            quad_busy_[dest_quad] <= 0) {\n            HMCRequest *req = link_req_queues_[src_link].front();\n            link_req_queues_[src_link].erase(\n                link_req_queues_[src_link].begin());\n            quad_req_queues_[dest_quad].push_back(req);\n            quad_busy_[dest_quad] = req->flits;\n            req->exit_time = logic_clk_ + req->flits;\n            if (link_req_queues_[src_link].empty()) {\n                link_age_counter_[src_link] = 0;\n            } else {\n                link_age_counter_[src_link] = 1;\n            }\n        } else {  // stalled this cycle, update age counter\n            link_age_counter_[src_link]++;\n        }\n        age_queue.erase(age_queue.begin());\n    }\n    age_queue.clear();\n}\n\nvoid HMCMemorySystem::DrainResponses() {\n    // Link resp to CPU\n    for (int i = 0; i < links_; i++) {\n        if (!link_resp_queues_[i].empty()) {\n            HMCResponse *resp = link_resp_queues_[i].front();\n            if (resp->exit_time <= logic_clk_) {\n                if (resp->type == HMCRespType::RD_RS) {\n                    read_callback_(resp->resp_id);\n                } else {\n                    write_callback_(resp->resp_id);\n                }\n                delete (resp);\n                link_resp_queues_[i].erase(link_resp_queues_[i].begin());\n            }\n        }\n    }\n\n    // drain xbar\n    for (auto &&i : link_busy_) {\n        if (i > 0) {\n            i -= 2;\n        }\n    }\n\n    // drain responses from quad to link buffers\n    auto age_queue = BuildAgeQueue(quad_age_counter_);\n    while (!age_queue.empty()) {\n        int src_quad = age_queue.front();\n        int dest_link = quad_resp_queues_[src_quad].front()->link;\n        if (link_resp_queues_[dest_link].size() < queue_depth_ &&\n            link_busy_[dest_link] <= 0) {\n            HMCResponse *resp = quad_resp_queues_[src_quad].front();\n            quad_resp_queues_[src_quad].erase(\n                quad_resp_queues_[src_quad].begin());\n            link_resp_queues_[dest_link].push_back(resp);\n            link_busy_[dest_link] = resp->flits;\n            resp->exit_time = logic_clk_ + resp->flits;\n            if (quad_resp_queues_[src_quad].size() == 0) {\n                quad_age_counter_[src_quad] = 0;\n            } else {\n                quad_age_counter_[src_quad] = 1;\n            }\n        } else {  // stalled this cycle, update age counter\n            quad_age_counter_[src_quad]++;\n        }\n        age_queue.erase(age_queue.begin());\n    }\n    age_queue.clear();\n}\n\nvoid HMCMemorySystem::DRAMClockTick() {\n    for (size_t i = 0; i < ctrls_.size(); i++) {\n        // look ahead and return earlier\n        while (true) {\n            auto pair = ctrls_[i]->ReturnDoneTrans(clk_);\n            if (pair.second == 1) {  // write\n                VaultCallback(pair.first);\n            } else if (pair.second == 0) {  // read\n                VaultCallback(pair.first);\n            } else {\n                break;\n            }\n        }\n    }\n    for (size_t i = 0; i < ctrls_.size(); i++) {\n        ctrls_[i]->ClockTick();\n    }\n    clk_++;\n\n    if (clk_ % config_.epoch_period == 0) {\n        PrintEpochStats();\n    }\n    return;\n}\n\nvoid HMCMemorySystem::ClockTick() {\n    if (dram_ps_ == logic_ps_) {\n        DrainResponses();\n        DRAMClockTick();\n        DrainRequests();\n        logic_ps_ += ps_per_logic_;\n        logic_clk_ += 1;\n    } else {\n        DRAMClockTick();\n    }\n    while (logic_ps_ < dram_ps_ + ps_per_dram_) {\n        DrainResponses();\n        DrainRequests();\n        logic_ps_ += ps_per_logic_;\n        logic_clk_ += 1;\n    }\n    dram_ps_ += ps_per_dram_;\n    return;\n}\n\nstd::vector<int> HMCMemorySystem::BuildAgeQueue(std::vector<int> &age_counter) {\n    // return a vector of indices sorted in decending order\n    // meaning that the oldest age link/quad should be processed first\n    std::vector<int> age_queue;\n    int queue_len = age_counter.size();\n    age_queue.reserve(queue_len);\n    int start_pos = logic_clk_ % queue_len;  // round robin start pos\n    for (int i = 0; i < queue_len; i++) {\n        int pos = (i + start_pos) % queue_len;\n        if (age_counter[pos] > 0) {\n            bool is_inserted = false;\n            for (auto it = age_queue.begin(); it != age_queue.end(); it++) {\n                if (age_counter[pos] > *it) {\n                    age_queue.insert(it, pos);\n                    is_inserted = true;\n                    break;\n                }\n            }\n            if (!is_inserted) {\n                age_queue.push_back(pos);\n            }\n        }\n    }\n    return age_queue;\n}\n\nvoid HMCMemorySystem::InsertReqToDRAM(HMCRequest *req) {\n    Transaction trans(req->mem_operand, req->is_write);\n    ctrls_[req->vault]->AddTransaction(trans);\n    return;\n}\n\nvoid HMCMemorySystem::VaultCallback(uint64_t req_id) {\n    // we will use hex addr as the req_id and use a multimap to lookup the\n    // requests the vaults cannot directly talk to the CPU so this callback will\n    // be passed to the vaults and is responsible to put the responses back to\n    // response queues\n\n    auto it = resp_lookup_table_.find(req_id);\n    HMCResponse *resp = it->second;\n    // all data from dram received, put packet in xbar and return\n    resp_lookup_table_.erase(it);\n    // put it in xbar\n    quad_resp_queues_[resp->quad].push_back(resp);\n    quad_age_counter_[resp->quad] = 1;\n    return;\n}\n\n}  // namespace dramsim3\n"
  },
  {
    "path": "src/DRAMsim3/src/hmc.h",
    "content": "#ifndef __HMC_H\n#define __HMC_H\n\n#include <functional>\n#include <map>\n#include <vector>\n\n#include \"dram_system.h\"\n\nnamespace dramsim3 {\n\nenum class HMCReqType {\n    RD0,\n    RD16,\n    RD32,\n    RD48,\n    RD64,\n    RD80,\n    RD96,\n    RD112,\n    RD128,\n    RD256,\n    WR0,\n    WR16,\n    WR32,\n    WR48,\n    WR64,\n    WR80,\n    WR96,\n    WR112,\n    WR128,\n    WR256,\n    P_WR16,\n    P_WR32,\n    P_WR48,\n    P_WR64,\n    P_WR80,\n    P_WR96,\n    P_WR112,\n    P_WR128,\n    P_WR256,\n    // TODO haven't properly implement the following atomic operations\n    ADD8,  // 2ADD8, cannot name it like that in c++...\n    ADD16,\n    P_2ADD8,  // 2 8Byte imm operands + 8 8Byte mem operands read then write\n    P_ADD16,\n    ADDS8R,  // 2ADD8, cannot name it like that...\n    ADDS16R,\n    INC8,  // read, return(the original), then write\n    P_INC8, // read, return(the original), then posted write\n    // boolean op on imm operand and mem operand, read update write\n    XOR16,  \n    OR16,\n    NOR16,\n    AND16,\n    NAND16,\n    // comparison instructions, not sure if there's write untill read done\n    CASGT8,\n    CASGT16,\n    CASLT8,\n    CASLT16,\n    CASEQ8,\n    CASZERO16,\n    // eq, only read\n    EQ8,\n    EQ16,\n    BWR,\n    P_BWR,  // bit write, 8B mask, 8B value, read update write\n    BWR8R,  // bit write with return\n    SWAP16,  // swap imm operand and mem operand, read then write\n    SIZE\n};\n\nenum class HMCRespType { NONE, RD_RS, WR_RS, ERR, SIZE };\n\n// for future use\nenum class HMCLinkType { HOST_TO_DEV, DEV_TO_DEV, SIZE };\n\nclass HMCRequest {\n   public:\n    HMCRequest(HMCReqType req_type, uint64_t hex_addr, int vault);\n    HMCReqType type;\n    uint64_t mem_operand;\n    int link;\n    int quad;\n    int vault;\n    int flits;\n    bool is_write;\n    // this exit_time is the time to exit xbar to vaults\n    uint64_t exit_time;\n};\n\nclass HMCResponse {\n   public:\n    HMCResponse(uint64_t id, HMCReqType reqtype, int dest_link, int src_quad);\n    uint64_t resp_id;\n    HMCRespType type;\n    int link;\n    int quad;\n    int flits;\n    // this exit_time is the time to exit xbar to cpu\n    uint64_t exit_time;\n};\n\nclass HMCMemorySystem : public BaseDRAMSystem {\n   public:\n    HMCMemorySystem(Config& config, const std::string& output_dir,\n                    std::function<void(uint64_t)> read_callback,\n                    std::function<void(uint64_t)> write_callback);\n    ~HMCMemorySystem();\n    // assuming there are 2 clock domains one for logic die one for DRAM\n    // we can unify them as one but then we'll have to convert all the\n    // slow dram time units to faster logic units...\n    void ClockTick() override;\n\n    // had to have 3 insert interfaces cuz HMC is so different...\n    bool WillAcceptTransaction(uint64_t hex_addr, bool is_write) const override;\n    bool AddTransaction(uint64_t hex_addr, bool is_write) override;\n    bool InsertReqToLink(HMCRequest* req, int link);\n    bool InsertHMCReq(HMCRequest* req);\n\n   private:\n    uint64_t logic_clk_, ps_per_dram_, ps_per_logic_, logic_ps_, dram_ps_;\n\n    void SetClockRatio();\n    void DRAMClockTick();\n    void DrainRequests();\n    void DrainResponses();\n    void InsertReqToDRAM(HMCRequest* req);\n    void VaultCallback(uint64_t req_id);\n    std::vector<int> BuildAgeQueue(std::vector<int>& age_counter);\n    void XbarArbitrate();\n    inline void IterateNextLink();\n\n    int next_link_;\n    int links_;\n    size_t queue_depth_;\n\n    // number of flits xbar can process per logic cycle\n    const int xbar_bandwidth_ = 2;\n\n    // had to use a multimap because the controller callback return hex addr\n    // instead of unique id\n    std::multimap<uint64_t, HMCResponse*> resp_lookup_table_;\n    // these are essentially input/output buffers for xbars\n    std::vector<std::vector<HMCRequest*>> link_req_queues_;\n    std::vector<std::vector<HMCResponse*>> link_resp_queues_;\n    std::vector<std::vector<HMCRequest*>> quad_req_queues_;\n    std::vector<std::vector<HMCResponse*>> quad_resp_queues_;\n\n    // input/output busy indicators, since each packet could be several\n    // flits, as long as this != 0 then they're busy\n    std::vector<int> link_busy_;\n    std::vector<int> quad_busy_ = {0, 0, 0, 0};\n    // used for arbitration\n    std::vector<int> link_age_counter_;\n    std::vector<int> quad_age_counter_ = {0, 0, 0, 0};\n};\n\n}  // namespace dramsim3\n\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/main.cc",
    "content": "#include <iostream>\n#include \"./../ext/headers/args.hxx\"\n#include \"cpu.h\"\n\nusing namespace dramsim3;\n\nint main(int argc, const char **argv) {\n    args::ArgumentParser parser(\n        \"DRAM Simulator.\",\n        \"Examples: \\n.\"\n        \"./build/dramsim3main configs/DDR4_8Gb_x8_3200.ini -c 100 -t \"\n        \"sample_trace.txt\\n\"\n        \"./build/dramsim3main configs/DDR4_8Gb_x8_3200.ini -s random -c 100\");\n    args::HelpFlag help(parser, \"help\", \"Display the help menu\", {'h', \"help\"});\n    args::ValueFlag<uint64_t> num_cycles_arg(parser, \"num_cycles\",\n                                             \"Number of cycles to simulate\",\n                                             {'c', \"cycles\"}, 100000);\n    args::ValueFlag<std::string> output_dir_arg(\n        parser, \"output_dir\", \"Output directory for stats files\",\n        {'o', \"output-dir\"}, \".\");\n    args::ValueFlag<std::string> stream_arg(\n        parser, \"stream_type\", \"address stream generator - (random), stream\",\n        {'s', \"stream\"}, \"\");\n    args::ValueFlag<std::string> trace_file_arg(\n        parser, \"trace\",\n        \"Trace file, setting this option will ignore -s option\",\n        {'t', \"trace\"});\n    args::Positional<std::string> config_arg(\n        parser, \"config\", \"The config file name (mandatory)\");\n\n    try {\n        parser.ParseCLI(argc, argv);\n    } catch (args::Help) {\n        std::cout << parser;\n        return 0;\n    } catch (args::ParseError e) {\n        std::cerr << e.what() << std::endl;\n        std::cerr << parser;\n        return 1;\n    }\n\n    std::string config_file = args::get(config_arg);\n    if (config_file.empty()) {\n        std::cerr << parser;\n        return 1;\n    }\n\n    uint64_t cycles = args::get(num_cycles_arg);\n    std::string output_dir = args::get(output_dir_arg);\n    std::string trace_file = args::get(trace_file_arg);\n    std::string stream_type = args::get(stream_arg);\n\n    CPU *cpu;\n    if (!trace_file.empty()) {\n        cpu = new TraceBasedCPU(config_file, output_dir, trace_file);\n    } else {\n        if (stream_type == \"stream\" || stream_type == \"s\") {\n            cpu = new StreamCPU(config_file, output_dir);\n        } else {\n            cpu = new RandomCPU(config_file, output_dir);\n        }\n    }\n\n    for (uint64_t clk = 0; clk < cycles; clk++) {\n        cpu->ClockTick();\n    }\n    cpu->PrintStats();\n\n    delete cpu;\n\n    return 0;\n}\n"
  },
  {
    "path": "src/DRAMsim3/src/memory_system.cc",
    "content": "#include \"memory_system.h\"\n\nnamespace dramsim3 {\nMemorySystem::MemorySystem(const std::string &config_file,\n                           const std::string &output_dir,\n                           std::function<void(uint64_t)> read_callback,\n                           std::function<void(uint64_t)> write_callback)\n    : config_(new Config(config_file, output_dir)) {\n    // TODO: ideal memory type?\n    if (config_->IsHMC()) {\n        dram_system_ = new HMCMemorySystem(*config_, output_dir, read_callback,\n                                           write_callback);\n    } else {\n        dram_system_ = new JedecDRAMSystem(*config_, output_dir, read_callback,\n                                           write_callback);\n    }\n}\n\nMemorySystem::~MemorySystem() {\n    delete (dram_system_);\n    delete (config_);\n}\n\nvoid MemorySystem::ClockTick() { dram_system_->ClockTick(); }\n\ndouble MemorySystem::GetTCK() const { return config_->tCK; }\n\nint MemorySystem::GetBusBits() const { return config_->bus_width; }\n\nint MemorySystem::GetBurstLength() const { return config_->BL; }\n\nint MemorySystem::GetQueueSize() const { return config_->trans_queue_size; }\n\nvoid MemorySystem::RegisterCallbacks(\n    std::function<void(uint64_t)> read_callback,\n    std::function<void(uint64_t)> write_callback) {\n    dram_system_->RegisterCallbacks(read_callback, write_callback);\n}\n\nbool MemorySystem::WillAcceptTransaction(uint64_t hex_addr,\n                                         bool is_write) const {\n    return dram_system_->WillAcceptTransaction(hex_addr, is_write);\n}\n\nbool MemorySystem::AddTransaction(uint64_t hex_addr, bool is_write) {\n    return dram_system_->AddTransaction(hex_addr, is_write);\n}\n\nvoid MemorySystem::PrintStats() const { dram_system_->PrintStats(); }\n\nvoid MemorySystem::ResetStats() { dram_system_->ResetStats(); }\n\nMemorySystem* GetMemorySystem(const std::string &config_file, const std::string &output_dir,\n                 std::function<void(uint64_t)> read_callback,\n                 std::function<void(uint64_t)> write_callback) {\n    return new MemorySystem(config_file, output_dir, read_callback, write_callback);\n}\n\nvoid MemorySystem::PrintStats(const char *timestamp) {\n    config_->SetOutputFileNames(timestamp);\n    dram_system_->PrintStats();\n}\n\n}  // namespace dramsim3\n\n// This function can be used by autoconf AC_CHECK_LIB since\n// apparently it can't detect C++ functions.\n// Basically just an entry in the symbol table\nextern \"C\" {\nvoid libdramsim3_is_present(void) { ; }\n}\n"
  },
  {
    "path": "src/DRAMsim3/src/memory_system.h",
    "content": "#ifndef __MEMORY_SYSTEM__H\n#define __MEMORY_SYSTEM__H\n\n#include <functional>\n#include <string>\n\n#include \"configuration.h\"\n#include \"dram_system.h\"\n#include \"hmc.h\"\n\nnamespace dramsim3 {\n\n// This should be the interface class that deals with CPU\nclass MemorySystem {\n   public:\n    MemorySystem(const std::string &config_file, const std::string &output_dir,\n                 std::function<void(uint64_t)> read_callback,\n                 std::function<void(uint64_t)> write_callback);\n    ~MemorySystem();\n    void ClockTick();\n    void RegisterCallbacks(std::function<void(uint64_t)> read_callback,\n                           std::function<void(uint64_t)> write_callback);\n    double GetTCK() const;\n    int GetBusBits() const;\n    int GetBurstLength() const;\n    int GetQueueSize() const;\n    void PrintStats() const;\n    void PrintStats(const char *timestamp);\n    void ResetStats();\n\n    bool WillAcceptTransaction(uint64_t hex_addr, bool is_write) const;\n    bool AddTransaction(uint64_t hex_addr, bool is_write);\n\n   private:\n    // These have to be pointers because Gem5 will try to push this object\n    // into container which will invoke a copy constructor, using pointers\n    // here is safe\n    Config *config_;\n    BaseDRAMSystem *dram_system_;\n};\n\nMemorySystem* GetMemorySystem(const std::string &config_file, const std::string &output_dir,\n                 std::function<void(uint64_t)> read_callback,\n                 std::function<void(uint64_t)> write_callback);\n\n}  // namespace dramsim3\n\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/refresh.cc",
    "content": "#include \"refresh.h\"\n\nnamespace dramsim3 {\nRefresh::Refresh(const Config &config, ChannelState &channel_state)\n    : clk_(0),\n      config_(config),\n      channel_state_(channel_state),\n      refresh_policy_(config.refresh_policy),\n      next_rank_(0),\n      next_bg_(0),\n      next_bank_(0) {\n    if (refresh_policy_ == RefreshPolicy::RANK_LEVEL_SIMULTANEOUS) {\n        refresh_interval_ = config_.tREFI;\n    } else if (refresh_policy_ == RefreshPolicy::BANK_LEVEL_STAGGERED) {\n        refresh_interval_ = config_.tREFIb;\n    } else {  // default refresh scheme: RANK STAGGERED\n        refresh_interval_ = config_.tREFI / config_.ranks;\n    }\n}\n\nvoid Refresh::ClockTick() {\n    if (clk_ % refresh_interval_ == 0 && clk_ > 0) {\n        InsertRefresh();\n    }\n    clk_++;\n    return;\n}\n\nvoid Refresh::InsertRefresh() {\n    switch (refresh_policy_) {\n        // Simultaneous all rank refresh\n        case RefreshPolicy::RANK_LEVEL_SIMULTANEOUS:\n            for (auto i = 0; i < config_.ranks; i++) {\n                if (!channel_state_.IsRankSelfRefreshing(i)) {\n                    channel_state_.RankNeedRefresh(i, true);\n                    break;\n                }\n            }\n            break;\n        // Staggered all rank refresh\n        case RefreshPolicy::RANK_LEVEL_STAGGERED:\n            if (!channel_state_.IsRankSelfRefreshing(next_rank_)) {\n                channel_state_.RankNeedRefresh(next_rank_, true);\n            }\n            IterateNext();\n            break;\n        // Fully staggered per bank refresh\n        case RefreshPolicy::BANK_LEVEL_STAGGERED:\n            if (!channel_state_.IsRankSelfRefreshing(next_rank_)) {\n                channel_state_.BankNeedRefresh(next_rank_, next_bg_, next_bank_,\n                                               true);\n            }\n            IterateNext();\n            break;\n        default:\n            AbruptExit(__FILE__, __LINE__);\n            break;\n    }\n    return;\n}\n\nvoid Refresh::IterateNext() {\n    switch (refresh_policy_) {\n        case RefreshPolicy::RANK_LEVEL_STAGGERED:\n            next_rank_ = (next_rank_ + 1) % config_.ranks;\n            return;\n        case RefreshPolicy::BANK_LEVEL_STAGGERED:\n            // Note - the order issuing bank refresh commands is static and\n            // non-configurable as per JEDEC standard\n            next_bg_ = (next_bg_ + 1) % config_.bankgroups;\n            if (next_bg_ == 0) {\n                next_bank_ = (next_bank_ + 1) % config_.banks_per_group;\n                if (next_bank_ == 0) {\n                    next_rank_ = (next_rank_ + 1) % config_.ranks;\n                }\n            }\n            return;\n        default:\n            AbruptExit(__FILE__, __LINE__);\n            return;\n    }\n}\n\n}  // namespace dramsim3\n"
  },
  {
    "path": "src/DRAMsim3/src/refresh.h",
    "content": "#ifndef __REFRESH_H\n#define __REFRESH_H\n\n#include <vector>\n#include \"channel_state.h\"\n#include \"common.h\"\n#include \"configuration.h\"\n\nnamespace dramsim3 {\n\nclass Refresh {\n   public:\n    Refresh(const Config& config, ChannelState& channel_state);\n    void ClockTick();\n\n   private:\n    uint64_t clk_;\n    int refresh_interval_;\n    const Config& config_;\n    ChannelState& channel_state_;\n    RefreshPolicy refresh_policy_;\n\n    int next_rank_, next_bg_, next_bank_;\n\n    void InsertRefresh();\n\n    void IterateNext();\n};\n\n}  // namespace dramsim3\n\n#endif"
  },
  {
    "path": "src/DRAMsim3/src/simple_stats.cc",
    "content": "#include <iostream>\n\n#include \"fmt/format.h\"\n#include \"simple_stats.h\"\n\nnamespace dramsim3 {\n\ntemplate <class T>\nvoid PrintStatText(std::ostream& where, std::string name, T value,\n                   std::string description) {\n    // not making this a class method because we need to calculate\n    // power & bw later, which are not BaseStat members\n    where << fmt::format(\"{:<30}{:^3}{:>12}{:>5}{}\", name, \" = \", value, \" # \",\n                         description)\n          << std::endl;\n    return;\n}\n\nSimpleStats::SimpleStats(const Config& config, int channel_id)\n    : config_(config), channel_id_(channel_id) {\n    // counter stats\n    InitStat(\"num_cycles\", \"counter\", \"Number of DRAM cycles\");\n    InitStat(\"epoch_num\", \"counter\", \"Number of epochs\");\n    InitStat(\"num_reads_done\", \"counter\", \"Number of read requests issued\");\n    InitStat(\"num_writes_done\", \"counter\", \"Number of read requests issued\");\n    InitStat(\"num_write_buf_hits\", \"counter\", \"Number of write buffer hits\");\n    InitStat(\"num_read_row_hits\", \"counter\", \"Number of read row buffer hits\");\n    InitStat(\"num_write_row_hits\", \"counter\",\n             \"Number of write row buffer hits\");\n    InitStat(\"num_read_cmds\", \"counter\", \"Number of READ/READP commands\");\n    InitStat(\"num_write_cmds\", \"counter\", \"Number of WRITE/WRITEP commands\");\n    InitStat(\"num_act_cmds\", \"counter\", \"Number of ACT commands\");\n    InitStat(\"num_pre_cmds\", \"counter\", \"Number of PRE commands\");\n    InitStat(\"num_ondemand_pres\", \"counter\", \"Number of ondemend PRE commands\");\n    InitStat(\"num_ref_cmds\", \"counter\", \"Number of REF commands\");\n    InitStat(\"num_refb_cmds\", \"counter\", \"Number of REFb commands\");\n    InitStat(\"num_srefe_cmds\", \"counter\", \"Number of SREFE commands\");\n    InitStat(\"num_srefx_cmds\", \"counter\", \"Number of SREFX commands\");\n    InitStat(\"hbm_dual_cmds\", \"counter\", \"Number of cycles dual cmds issued\");\n\n    // double stats\n    InitStat(\"act_energy\", \"double\", \"Activation energy\");\n    InitStat(\"read_energy\", \"double\", \"Read energy\");\n    InitStat(\"write_energy\", \"double\", \"Write energy\");\n    InitStat(\"ref_energy\", \"double\", \"Refresh energy\");\n    InitStat(\"refb_energy\", \"double\", \"Refresh-bank energy\");\n\n    // Vector counter stats\n    InitVecStat(\"all_bank_idle_cycles\", \"vec_counter\",\n                \"Cyles of all bank idle in rank\", \"rank\", config_.ranks);\n    InitVecStat(\"rank_active_cycles\", \"vec_counter\", \"Cyles of rank active\",\n                \"rank\", config_.ranks);\n    InitVecStat(\"sref_cycles\", \"vec_counter\", \"Cyles of rank in SREF mode\",\n                \"rank\", config_.ranks);\n\n    // Vector of double stats\n    InitVecStat(\"act_stb_energy\", \"vec_double\", \"Active standby energy\", \"rank\",\n                config_.ranks);\n    InitVecStat(\"pre_stb_energy\", \"vec_double\", \"Precharge standby energy\",\n                \"rank\", config_.ranks);\n    InitVecStat(\"sref_energy\", \"vec_double\", \"SREF energy\", \"rank\",\n                config_.ranks);\n\n    // Histogram stats\n    InitHistoStat(\"read_latency\", \"Read request latency (cycles)\", 0, 200, 10);\n    InitHistoStat(\"write_latency\", \"Write cmd latency (cycles)\", 0, 200, 10);\n    InitHistoStat(\"interarrival_latency\",\n                  \"Request interarrival latency (cycles)\", 0, 100, 10);\n\n    // some irregular stats\n    InitStat(\"average_bandwidth\", \"calculated\", \"Average bandwidth\");\n    InitStat(\"total_energy\", \"calculated\", \"Total energy (pJ)\");\n    InitStat(\"average_power\", \"calculated\", \"Average power (mW)\");\n    InitStat(\"average_read_latency\", \"calculated\",\n             \"Average read request latency (cycles)\");\n    InitStat(\"average_interarrival\", \"calculated\",\n             \"Average request interarrival latency (cycles)\");\n}\n\nvoid SimpleStats::AddValue(const std::string name, const int value) {\n    auto& epoch_counts = epoch_histo_counts_[name];\n    if (epoch_counts.count(value) <= 0) {\n        epoch_counts[value] = 1;\n    } else {\n        epoch_counts[value] += 1;\n    }\n}\n\nstd::string SimpleStats::GetTextHeader(bool is_final) const {\n    std::string header =\n        \"###########################################\\n## Statistics of \"\n        \"Channel \" +\n        std::to_string(channel_id_);\n    if (!is_final) {\n        header += \" of epoch \" + std::to_string(counters_.at(\"epoch_num\"));\n    }\n    header += \"\\n###########################################\\n\";\n    return header;\n}\n\nvoid SimpleStats::PrintEpochStats() {\n    UpdateEpochStats();\n    if (config_.output_level >= 1) {\n        std::ofstream j_out(config_.json_epoch_name, std::ofstream::app);\n        j_out << j_data_;\n    }\n    if (config_.output_level >= 2) {\n        std::cout << GetTextHeader(false);\n        for (const auto& it : print_pairs_) {\n            PrintStatText(std::cout, it.first, it.second,\n                          header_descs_[it.first]);\n        }\n    }\n    print_pairs_.clear();\n}\n\nvoid SimpleStats::PrintFinalStats() {\n    UpdateFinalStats();\n\n    if (config_.output_level >= 0) {\n        std::ofstream j_out(config_.json_stats_name, std::ofstream::app);\n        j_out << \"\\\"\" << std::to_string(channel_id_) << \"\\\":\";\n        j_out << j_data_;\n    }\n\n    if (config_.output_level >= 1) {\n        // HACK: overwrite existing file if this is first channel\n        auto perm = channel_id_ == 0 ? std::ofstream::out : std::ofstream::app;\n        std::ofstream txt_out(config_.txt_stats_name, perm);\n        txt_out << GetTextHeader(true);\n        for (const auto& it : print_pairs_) {\n            PrintStatText(txt_out, it.first, it.second,\n                          header_descs_[it.first]);\n        }\n    }\n\n    print_pairs_.clear();\n}\n\nvoid SimpleStats::Reset() {\n    for (auto& it : counters_) {\n        it.second = 0;\n    }\n    for (auto& it : epoch_counters_) {\n        it.second = 0;\n    }\n    for (auto& vec : vec_counters_) {\n        std::fill(vec.second.begin(), vec.second.end(), 0);\n    }\n    for (auto& vec : epoch_vec_counters_) {\n        std::fill(vec.second.begin(), vec.second.end(), 0);\n    }\n    for (auto& it : doubles_) {\n        it.second = 0.0;\n    }\n    for (auto& vec : vec_doubles_) {\n        std::fill(vec.second.begin(), vec.second.end(), 0.0);\n    }\n    for (auto& it : calculated_) {\n        it.second = 0.0;\n    }\n    for (auto& it : histo_counts_) {\n        it.second.clear();\n    }\n    for (auto& it : epoch_histo_counts_) {\n        it.second.clear();\n    }\n}\n\nvoid SimpleStats::InitStat(std::string name, std::string stat_type,\n                           std::string description) {\n    header_descs_.emplace(name, description);\n    if (stat_type == \"counter\") {\n        counters_.emplace(name, 0);\n        epoch_counters_.emplace(name, 0);\n    } else if (stat_type == \"double\") {\n        doubles_.emplace(name, 0.0);\n    } else if (stat_type == \"calculated\") {\n        calculated_.emplace(name, 0.0);\n    }\n}\n\nvoid SimpleStats::InitVecStat(std::string name, std::string stat_type,\n                              std::string description, std::string part_name,\n                              int vec_len) {\n    for (int i = 0; i < vec_len; i++) {\n        std::string trailing = \".\" + std::to_string(i);\n        std::string actual_name = name + trailing;\n        std::string actual_desc = description + \" \" + part_name + trailing;\n        header_descs_.emplace(actual_name, actual_desc);\n    }\n    if (stat_type == \"vec_counter\") {\n        vec_counters_.emplace(name, std::vector<uint64_t>(vec_len, 0));\n        epoch_vec_counters_.emplace(name, std::vector<uint64_t>(vec_len, 0));\n    } else if (stat_type == \"vec_double\") {\n        vec_doubles_.emplace(name, std::vector<double>(vec_len, 0));\n    }\n}\n\nvoid SimpleStats::InitHistoStat(std::string name, std::string description,\n                                int start_val, int end_val, int num_bins) {\n    int bin_width = (end_val - start_val) / num_bins;\n    bin_widths_.emplace(name, bin_width);\n    histo_bounds_.emplace(name, std::make_pair(start_val, end_val));\n    histo_counts_.emplace(name, std::unordered_map<int, uint64_t>());\n    epoch_histo_counts_.emplace(name, std::unordered_map<int, uint64_t>());\n\n    // initialize headers, descriptions\n    std::vector<std::string> headers;\n    auto header = fmt::format(\"{}[-{}]\", name, start_val);\n    headers.push_back(header);\n    header_descs_.emplace(header, description);\n    for (int i = 1; i < num_bins + 1; i++) {\n        int bucket_start = start_val + (i - 1) * bin_width;\n        int bucket_end = start_val + i * bin_width - 1;\n        header = fmt::format(\"{}[{}-{}]\", name, bucket_start, bucket_end);\n        headers.push_back(header);\n        header_descs_.emplace(header, description);\n    }\n    header = fmt::format(\"{}[{}-]\", name, end_val);\n    headers.push_back(header);\n    header_descs_.emplace(header, description);\n\n    histo_headers_.emplace(name, headers);\n\n    // +2 for front and end\n    histo_bins_.emplace(name, std::vector<uint64_t>(num_bins + 2, 0));\n    epoch_histo_bins_.emplace(name, std::vector<uint64_t>(num_bins + 2, 0));\n}\n\nvoid SimpleStats::UpdateCounters() {\n    for (const auto& it : epoch_counters_) {\n        counters_[it.first] += it.second;\n    }\n    for (const auto& vec : epoch_vec_counters_) {\n        for (size_t i = 0; i < vec.second.size(); i++) {\n            vec_counters_[vec.first][i] += vec.second[i];\n        }\n    }\n}\n\nvoid SimpleStats::UpdateHistoBins() {\n    for (auto& name_bins : epoch_histo_bins_) {\n        const auto& name = name_bins.first;\n        auto& bins = name_bins.second;\n        std::fill(bins.begin(), bins.end(), 0);\n        for (const auto it : epoch_histo_counts_[name]) {\n            int value = it.first;\n            uint64_t count = it.second;\n            int bin_idx = 0;\n            if (value < histo_bounds_[name].first) {\n                bin_idx = 0;\n            } else if (value > histo_bounds_[name].second) {\n                bin_idx = bins.size() - 1;\n            } else {\n                bin_idx =\n                    (value - histo_bounds_[name].first) / bin_widths_[name] + 1;\n            }\n            bins[bin_idx] += count;\n        }\n    }\n\n    // update overall histogram counts based on epoch histo counts\n    for (auto& name_counts : epoch_histo_counts_) {\n        const auto& name = name_counts.first;\n        auto& epoch_counts = name_counts.second;\n        auto& final_counts = histo_counts_[name];\n        for (const auto& val_cnt : epoch_counts) {\n            if (final_counts.count(val_cnt.first) <= 0) {\n                final_counts[val_cnt.first] = val_cnt.second;\n            } else {\n                final_counts[val_cnt.first] += val_cnt.second;\n            }\n        }\n        auto& final_bins = histo_bins_[name];\n        for (size_t i = 0; i < final_bins.size(); i++) {\n            final_bins[i] += epoch_histo_bins_[name][i];\n        }\n    }\n}\n\ndouble SimpleStats::GetHistoAvg(const HistoCount& hist_counts) const {\n    uint64_t accu_sum = 0;\n    uint64_t count = 0;\n    for (auto i = hist_counts.begin(); i != hist_counts.end(); i++) {\n        accu_sum += i->first * i->second;\n        count += i->second;\n    }\n    return count == 0\n               ? 0.0\n               : static_cast<double>(accu_sum) / static_cast<double>(count);\n}\n\nvoid SimpleStats::UpdatePrints(bool epoch) {\n    j_data_[\"channel\"] = channel_id_;\n\n    std::unordered_map<std::string, uint64_t>& ref_counters =\n        epoch ? epoch_counters_ : counters_;\n    for (const auto& it : ref_counters) {\n        print_pairs_.emplace_back(it.first, std::to_string(it.second));\n        j_data_[it.first] = it.second;\n    }\n    j_data_[\"epoch_num\"] = counters_[\"epoch_num\"];\n\n    VecStat& ref_vcounter = epoch ? epoch_vec_counters_ : vec_counters_;\n    for (const auto& it : ref_vcounter) {\n        Json j_list;\n        for (size_t i = 0; i < it.second.size(); i++) {\n            std::string name = it.first + \".\" + std::to_string(i);\n            print_pairs_.emplace_back(name, std::to_string(it.second[i]));\n            j_list[std::to_string(i)] = it.second[i];\n        }\n        j_data_[it.first] = j_list;\n    }\n    VecStat& ref_hbins = epoch ? epoch_histo_bins_ : histo_bins_;\n    for (const auto& it : ref_hbins) {\n        const auto& names = histo_headers_[it.first];\n        for (size_t i = 0; i < it.second.size(); i++) {\n            print_pairs_.emplace_back(names[i], std::to_string(it.second[i]));\n            j_data_[names[i]] = it.second[i];\n        }\n    }\n\n    // if we dump complete histogram data each epoch the output file will be\n    // huge therefore we only put aggregated histo in each epoch but\n    // complete data at the end\n    if (!epoch) {\n        for (const auto& name_hist : histo_counts_) {\n            Json j_list;\n            for (const auto& it : name_hist.second) {\n                j_list[std::to_string(it.first)] = it.second;\n            }\n            j_data_[name_hist.first] = j_list;\n        }\n    }\n\n    for (const auto& it : doubles_) {\n        print_pairs_.emplace_back(it.first, fmt::format(\"{}\", it.second));\n        j_data_[it.first] = it.second;\n    }\n\n    for (const auto& it : vec_doubles_) {\n        Json j_list;\n        for (size_t i = 0; i < it.second.size(); i++) {\n            std::string name = it.first + \".\" + std::to_string(i);\n            print_pairs_.emplace_back(name, fmt::format(\"{}\", it.second[i]));\n            j_list[std::to_string(i)] = it.second[i];\n        }\n        j_data_[it.first] = j_list;\n    }\n    for (const auto& it : calculated_) {\n        print_pairs_.emplace_back(it.first, fmt::format(\"{}\", it.second));\n        j_data_[it.first] = it.second;\n    }\n}\n\nvoid SimpleStats::UpdateEpochStats() {\n    // push counter values as is\n    UpdateCounters();\n\n    // update computed stats\n    doubles_[\"act_energy\"] =\n        epoch_counters_[\"num_act_cmds\"] * config_.act_energy_inc;\n    doubles_[\"read_energy\"] =\n        epoch_counters_[\"num_read_cmds\"] * config_.read_energy_inc;\n    doubles_[\"write_energy\"] =\n        epoch_counters_[\"num_write_cmds\"] * config_.write_energy_inc;\n    doubles_[\"ref_energy\"] =\n        epoch_counters_[\"num_ref_cmds\"] * config_.ref_energy_inc;\n    doubles_[\"refb_energy\"] =\n        epoch_counters_[\"num_refb_cmds\"] * config_.refb_energy_inc;\n\n    // vector doubles, update first, then push\n    double background_energy = 0.0;\n    for (int i = 0; i < config_.ranks; i++) {\n        double act_stb = epoch_vec_counters_[\"rank_active_cycles\"][i] *\n                         config_.act_stb_energy_inc;\n        double pre_stb = epoch_vec_counters_[\"all_bank_idle_cycles\"][i] *\n                         config_.pre_stb_energy_inc;\n        double sref_energy =\n            epoch_vec_counters_[\"sref_cycles\"][i] * config_.sref_energy_inc;\n        vec_doubles_[\"act_stb_energy\"][i] = act_stb;\n        vec_doubles_[\"pre_stb_energy\"][i] = pre_stb;\n        vec_doubles_[\"sref_energy\"][i] = sref_energy;\n        background_energy += act_stb + pre_stb + sref_energy;\n    }\n\n    UpdateHistoBins();\n\n    // calculated stats\n    uint64_t total_reqs =\n        epoch_counters_[\"num_reads_done\"] + epoch_counters_[\"num_writes_done\"];\n    double total_time = epoch_counters_[\"num_cycles\"] * config_.tCK;\n    double avg_bw = total_reqs * config_.request_size_bytes / total_time;\n    calculated_[\"average_bandwidth\"] = avg_bw;\n\n    double total_energy = doubles_[\"act_energy\"] + doubles_[\"read_energy\"] +\n                          doubles_[\"write_energy\"] + doubles_[\"ref_energy\"] +\n                          doubles_[\"refb_energy\"] + background_energy;\n    calculated_[\"total_energy\"] = total_energy;\n    calculated_[\"average_power\"] = total_energy / epoch_counters_[\"num_cycles\"];\n    calculated_[\"average_read_latency\"] =\n        GetHistoAvg(epoch_histo_counts_.at(\"read_latency\"));\n    calculated_[\"average_interarrival\"] =\n        GetHistoAvg(epoch_histo_counts_.at(\"interarrival_latency\"));\n\n    UpdatePrints(true);\n    for (auto& it : epoch_counters_) {\n        it.second = 0;\n    }\n    for (auto& vec : epoch_vec_counters_) {\n        std::fill(vec.second.begin(), vec.second.end(), 0);\n    }\n    for (auto& it : epoch_histo_counts_) {\n        it.second.clear();\n    }\n    return;\n}\n\nvoid SimpleStats::UpdateFinalStats() {\n    UpdateCounters();\n\n    // update computed stats\n    doubles_[\"act_energy\"] = counters_[\"num_act_cmds\"] * config_.act_energy_inc;\n    doubles_[\"read_energy\"] =\n        counters_[\"num_read_cmds\"] * config_.read_energy_inc;\n    doubles_[\"write_energy\"] =\n        counters_[\"num_write_cmds\"] * config_.write_energy_inc;\n    doubles_[\"ref_energy\"] = counters_[\"num_ref_cmds\"] * config_.ref_energy_inc;\n    doubles_[\"refb_energy\"] =\n        counters_[\"num_refb_cmds\"] * config_.refb_energy_inc;\n\n    // vector doubles, update first, then push\n    double background_energy = 0.0;\n    for (int i = 0; i < config_.ranks; i++) {\n        double act_stb =\n            vec_counters_[\"rank_active_cycles\"][i] * config_.act_stb_energy_inc;\n        double pre_stb = vec_counters_[\"all_bank_idle_cycles\"][i] *\n                         config_.pre_stb_energy_inc;\n        double sref_energy =\n            vec_counters_[\"sref_cycles\"][i] * config_.sref_energy_inc;\n        vec_doubles_[\"act_stb_energy\"][i] = act_stb;\n        vec_doubles_[\"pre_stb_energy\"][i] = pre_stb;\n        vec_doubles_[\"sref_energy\"][i] = sref_energy;\n        background_energy += act_stb + pre_stb + sref_energy;\n    }\n\n    // histograms\n    UpdateHistoBins();\n\n    // calculated stats\n    uint64_t total_reqs =\n        counters_[\"num_reads_done\"] + counters_[\"num_writes_done\"];\n    double total_time = counters_[\"num_cycles\"] * config_.tCK;\n    double avg_bw = total_reqs * config_.request_size_bytes / total_time;\n    calculated_[\"average_bandwidth\"] = avg_bw;\n\n    double total_energy = doubles_[\"act_energy\"] + doubles_[\"read_energy\"] +\n                          doubles_[\"write_energy\"] + doubles_[\"ref_energy\"] +\n                          doubles_[\"refb_energy\"] + background_energy;\n    calculated_[\"total_energy\"] = total_energy;\n    calculated_[\"average_power\"] = total_energy / counters_[\"num_cycles\"];\n    // calculated_[\"average_read_latency\"] = GetHistoAvg(\"read_latency\");\n    calculated_[\"average_read_latency\"] =\n        GetHistoAvg(histo_counts_.at(\"read_latency\"));\n    calculated_[\"average_interarrival\"] =\n        GetHistoAvg(histo_counts_.at(\"interarrival_latency\"));\n\n    UpdatePrints(false);\n    return;\n}\n\n}  // namespace dramsim3"
  },
  {
    "path": "src/DRAMsim3/src/simple_stats.h",
    "content": "#ifndef __SIMPLE_STATS_\n#define __SIMPLE_STATS_\n\n#include <fstream>\n#include <string>\n#include <unordered_map>\n#include <vector>\n\n#include \"configuration.h\"\n#include \"json.hpp\"\n\nnamespace dramsim3 {\n\nclass SimpleStats {\n   public:\n    SimpleStats(const Config& config, int channel_id);\n    // incrementing counter\n    void Increment(const std::string name) { epoch_counters_[name] += 1; }\n\n    // incrementing for vec counter\n    void IncrementVec(const std::string name, int pos) {\n        epoch_vec_counters_[name][pos] += 1;\n    }\n\n    // increment vec counter by number\n    void IncrementVecBy(const std::string name, int pos, int num) {\n        epoch_vec_counters_[name][pos] += num;\n    }\n\n    // add historgram value\n    void AddValue(const std::string name, const int value);\n\n    // Epoch update\n    void PrintEpochStats();\n\n    // Final statas output\n    void PrintFinalStats();\n\n    // Reset (usually after one phase of simulation)\n    void Reset();\n\n   private:\n    using VecStat = std::unordered_map<std::string, std::vector<uint64_t> >;\n    using HistoCount = std::unordered_map<int, uint64_t>;\n    using Json = nlohmann::json;\n    void InitStat(std::string name, std::string stat_type,\n                  std::string description);\n    void InitVecStat(std::string name, std::string stat_type,\n                     std::string description, std::string part_name,\n                     int vec_len);\n    void InitHistoStat(std::string name, std::string description, int start_val,\n                       int end_val, int num_bins);\n\n    void UpdateCounters();\n    void UpdateHistoBins();\n    void UpdatePrints(bool epoch);\n    double GetHistoAvg(const HistoCount& histo_counts) const;\n    std::string GetTextHeader(bool is_final) const;\n    void UpdateEpochStats();\n    void UpdateFinalStats();\n\n    const Config& config_;\n    int channel_id_;\n\n    // map names to descriptions\n    std::unordered_map<std::string, std::string> header_descs_;\n\n    // counter stats, indexed by their name\n    std::unordered_map<std::string, uint64_t> counters_;\n    std::unordered_map<std::string, uint64_t> epoch_counters_;\n\n    // vectored counter stats, first indexed by name then by index\n    VecStat vec_counters_;\n    VecStat epoch_vec_counters_;\n\n    // NOTE: doubles_ vec_doubles_ and calculated_ are basically one time\n    // placeholders after each epoch they store the value for that epoch\n    // (different from the counters) and in the end updated to the overall value\n    std::unordered_map<std::string, double> doubles_;\n\n    std::unordered_map<std::string, std::vector<double> > vec_doubles_;\n\n    // calculated stats, similar to double, but not the same\n    std::unordered_map<std::string, double> calculated_;\n\n    // histogram stats\n    std::unordered_map<std::string, std::vector<std::string> > histo_headers_;\n\n    std::unordered_map<std::string, std::pair<int, int> > histo_bounds_;\n    std::unordered_map<std::string, int> bin_widths_;\n    std::unordered_map<std::string, HistoCount> histo_counts_;\n    std::unordered_map<std::string, HistoCount> epoch_histo_counts_;\n    VecStat histo_bins_;\n    VecStat epoch_histo_bins_;\n\n    // outputs\n    Json j_data_;\n    std::vector<std::pair<std::string, std::string> > print_pairs_;\n};\n\n}  // namespace dramsim3\n#endif"
  },
  {
    "path": "src/DRAMsim3/src/sp_ienv.c",
    "content": "/*! \\file\nCopyright (c) 2003, The Regents of the University of California, through\nLawrence Berkeley National Laboratory (subject to receipt of any required\napprovals from U.S. Dept. of Energy)\n\nAll rights reserved.\n\nThe source code is distributed under BSD license, see the file License.txt\nat the top-level directory.\n*/\n#include \"../ext/SuperLU_MT_3.1/SRC/slu_mt_ddefs.h\"\n#include \"../ext/SuperLU_MT_3.1/SRC/slu_mt_machines.h\"\n\nint_t sp_ienv(int_t ispec) {\n    /*\n     * -- SuperLU MT routine (version 1.0) --\n     * Univ. of California Berkeley, Xerox Palo Alto Research Center,\n     * and Lawrence Berkeley National Lab.\n     * August 15, 1997\n     *\n     *  Purpose\n     *  =======\n     *\n     *  sp_ienv() is inquired to choose machine-dependent parameters for the\n     *  local environment. See ISPEC for a description of the parameters.\n     *\n     *  This version provides a set of parameters which should give good,\n     *  but not optimal, performance on many of the currently available\n     *  computers.  Users are encouraged to modify this subroutine to set\n     *  the tuning parameters for their particular machine using the option\n     *  and problem size information in the arguments.\n     *\n     *  Arguments\n     *  =========\n     *\n     *  ISPEC   (input) int\n     *          Specifies the parameter to be returned as the value of SP_IENV.\n     *          = 1: the panel size w; a panel consists of w consecutive\n     *               columns of matrix A in the process of Gaussian elimination.\n     *               The best value depends on machine's cache characters.\n     *          = 2: the relaxation parameter relax; if the number of\n     *               nodes (columns) in a subtree of the elimination tree is\n     * less than relax, this subtree is considered as one supernode, regardless\n     * of the their row structures. = 3: the maximum size for a\n     * supernode; = 4: the minimum row dimension for 2-D blocking to be\n     * used; = 5: the minimum column dimension for 2-D blocking to be\n     * used; = 6: size of the array to store the values of the L\n     * supernodes; a negative number represents the fills growth\n     * factor, i.e., the product of its magnitude and the number\n     * of nonzeros in the original A will be used to allocate\n     * storage; a positive number represents the number of\n     * nonzeros; = 7: size of the array to store the columns in U;\n     *               a negative number represents the fills growth factor, i.e.,\n     *               the product of its magnitude and the number of nonzeros in\n     * the original A will be used to allocate storage; a positive number\n     * represents the number of nonzeros; = 8: size of the array\n     * to store the subscripts of the L supernodes; a negative number\n     * represents the fills growth factor, i.e., the product of\n     * its magnitude and the number of nonzeros in the original A\n     * will be used to allocate storage; a positive number\n     * represents the number of nonzeros;\n     *\n     * (SP_IENV) (output) int\n     *          >= 0: the value of the parameter specified by ISPEC\n     *          < 0:  if SP_IENV = -k, the k-th argument had an illegal value.\n     *\n     *  =====================================================================\n     */\n    int i;\n\n    switch (ispec) {\n#if (MACH == SGI)\n        case 1:\n            return (20);\n        case 2:\n            return (6);\n        case 3:\n            return (100);\n        case 4:\n            return (800);\n        case 5:\n            return (100);\n#elif (MACH == ORIGIN)\n        case 1:\n            return (12);\n        case 2:\n            return (6);\n        case 3:\n            return (100);\n        case 4:\n            return (400);\n        case 5:\n            return (100);\n#elif (MACH == DEC)\n        case 1:\n            return (16);\n        case 2:\n            return (6);\n        case 3:\n            return (50);\n        case 4:\n            return (100);\n        case 5:\n            return (40);\n#elif (MACH == CRAY_PVP)\n        case 1:\n            return (1);\n        case 2:\n            return (6);\n        case 3:\n            return (64);\n        case 4:\n            return (400);\n        case 5:\n            return (200);\n#elif (MACH == SUN)\n        case 1:\n            return (8);\n        case 2:\n            return (6);\n        case 3:\n            return (100);\n        case 4:\n            return (400);\n        case 5:\n            return (40);\n#else\n        case 1:\n            return (8);\n        case 2:\n            return (1);\n        case 3:\n            return (200);\n        case 4:\n            return (200);\n        case 5:\n            return (40);\n#endif\n        case 6:\n            return (-20);\n        case 7:\n            return (-1000000);\n        case 8:\n            return (-1000000);\n    }\n\n    /* Invalid value for ISPEC */\n    i = 1;\n    xerbla_(\"sp_ienv\", &i);\n    return 0;\n\n} /* sp_ienv_ */\n"
  },
  {
    "path": "src/DRAMsim3/src/thermal.cc",
    "content": "#include \"thermal.h\"\n\nextern \"C\" double *steady_thermal_solver(double ***powerM, double W, double Lc,\n                                         int numP, int dimX, int dimZ,\n                                         double **Midx, int count,\n                                         double Tamb_);\nextern \"C\" double *transient_thermal_solver(double ***powerM, double W,\n                                            double L, int numP, int dimX,\n                                            int dimZ, double **Midx,\n                                            int MidxSize, double *Cap,\n                                            int CapSize, double time, int iter,\n                                            double *T_trans, double Tamb_);\nextern \"C\" double **calculate_Midx_array(double W, double Lc, int numP,\n                                         int dimX, int dimZ, int *MidxSize,\n                                         double Tamb_);\nextern \"C\" double *calculate_Cap_array(double W, double Lc, int numP, int dimX,\n                                       int dimZ, int *CapSize);\nextern \"C\" double *initialize_Temperature(double W, double Lc, int numP,\n                                          int dimX, int dimZ, double Tamb_);\n\nnamespace dramsim3 {\n\nstd::function<Address(const Address &addr)> GetPhyAddress;\n\nThermalCalculator::ThermalCalculator(const Config &config)\n    : config_(config),\n      time_iter0(10),\n      sample_id(0),\n      background_energy_(config_.channels,\n                         std::vector<double>(config_.ranks, 0)),\n      avg_logic_power_(0.0) {\n    // Initialize dimX, dimY, numP\n    // The dimension of the chip is determined such that the floorplan is\n    // as square as possilbe. If a square floorplan cannot be reached,\n    // x-dimension is larger\n    if (config_.IsHMC()) {\n        numP = config_.num_dies + 1;  // add logic layer for HMC\n        bank_x = 1;\n        bank_y = 2;\n\n        double xd = bank_x * config_.bank_asr;\n        double yd = bank_y * 1.0;\n        vault_x = determineXY(xd, yd, config_.channels);\n        vault_y = config_.channels / vault_x;\n\n        dimX = vault_x * bank_x * config_.num_x_grids;\n        dimY = vault_y * bank_y * config_.num_y_grids;\n\n        num_case = 1;\n    } else if (config_.IsHBM()) {\n        numP = config_.num_dies + 1;  // add logic layer for HBM\n        bank_x = 8;\n        bank_y = 2;\n        vault_x = 1;\n        vault_y = 2;\n        dimX = vault_x * bank_x * config_.num_x_grids;\n        dimY = vault_y * bank_y * config_.num_y_grids;\n\n        num_case = 1;\n    } else {\n        numP = 1;\n        bank_x = determineXY(config_.bank_asr, 1.0, config_.banks);\n        bank_y = config_.banks / bank_x;\n\n        dimX = bank_x * config_.num_x_grids;\n        dimY = bank_y * config_.num_y_grids;\n\n        num_case = config_.ranks * config_.channels;\n    }\n\n    Tamb = config_.amb_temp + T0;\n\n    std::cout << \"bank aspect ratio = \" << config_.bank_asr << std::endl;\n    // std::cout << \"#rows = \" << config_.rows << \"; #columns = \" <<\n    // config_.rows / config_.bank_asr << std::endl;\n    std::cout << \"num_x_grids = \" << config_.num_x_grids\n              << \"; num_y_grids = \" << config_.num_y_grids << std::endl;\n    std::cout << \"vault_x = \" << vault_x << \"; vault_y = \" << vault_y\n              << std::endl;\n    std::cout << \"bank_x = \" << bank_x << \"; bank_y = \" << bank_y << std::endl;\n    std::cout << \"dimX = \" << dimX << \"; dimY = \" << dimY << \"; numP = \" << numP\n              << std::endl;\n    std::cout << \"number of devices is \" << config_.devices_per_rank\n              << std::endl;\n\n    SetPhyAddressMapping();\n\n    // Initialize the vectors\n    accu_Pmap = std::vector<std::vector<double>>(\n        num_case, std::vector<double>(numP * dimX * dimY, 0));\n    cur_Pmap = std::vector<std::vector<double>>(\n        num_case, std::vector<double>(numP * dimX * dimY, 0));\n    T_size = (numP * 3 + 1) * (dimX + num_dummy) * (dimY + num_dummy);\n    T_trans = new double *[num_case];\n    T_final = new double *[num_case];\n    for (int i = 0; i < num_case; i++) {\n        T_trans[i] = new double[T_size];\n    }\n\n    InitialParameters();\n\n    refresh_count = std::vector<std::vector<int>>(\n        config_.channels * config_.ranks, std::vector<int>(config_.banks, 0));\n\n    if (config_.output_level >= 0) {\n        // Initialize the output file\n        final_temperature_file_csv_.open(config_.output_prefix +\n                                         \"final_temp.csv\");\n        PrintCSVHeader_final(final_temperature_file_csv_);\n\n        // print bank position\n        bank_position_csv_.open(config_.output_prefix + \"bank_pos.csv\");\n        PrintCSV_bank(bank_position_csv_);\n\n        // a quick preview of max temperature for each layer of each epoch\n        epoch_max_temp_file_csv_.open(config_.output_prefix +\n                                      \"epoch_max_temp.csv\");\n        epoch_max_temp_file_csv_ << \"layer,max_temp,epoch_time\" << std::endl;\n    }\n\n    // print header to csv files\n    if (config_.output_level >= 2) {\n        epoch_temperature_file_csv_.open(config_.output_prefix +\n                                         \"epoch_temp.csv\");\n        epoch_temperature_file_csv_\n            << \"rank_channel_index,x,y,z,power,temperature,epoch\" << std::endl;\n    }\n}\n\nThermalCalculator::~ThermalCalculator() {}\n\nvoid ThermalCalculator::SetPhyAddressMapping() {\n    std::string mapping_string = config_.loc_mapping;\n    if (mapping_string.empty()) {\n        // if no location mapping specified, then do not map and use default\n        // mapping...\n        GetPhyAddress = [](const Address &addr) { return Address(addr); };\n        return;\n    }\n    std::vector<std::string> bit_fields = StringSplit(mapping_string, ',');\n    if (bit_fields.size() != 6) {\n        std::cerr << \"loc_mapping should have 6 fields!\" << std::endl;\n        std::exit(1);\n    }\n    std::vector<std::vector<int>> mapped_pos(bit_fields.size(),\n                                             std::vector<int>());\n    for (unsigned i = 0; i < bit_fields.size(); i++) {\n        std::vector<std::string> bit_pos = StringSplit(bit_fields[i], '-');\n        for (unsigned j = 0; j < bit_pos.size(); j++) {\n            if (!bit_pos[j].empty()) {\n                auto colon_pos = bit_pos[j].find(\":\");\n                if (colon_pos ==\n                    std::string::npos) {  // no \"start:end\" short cuts\n                    int pos = std::stoi(bit_pos[j]);\n                    mapped_pos[i].push_back(pos);\n                } else {\n                    // for string like start:end (both inclusive), push all\n                    // numbers in between into mapped_pos\n                    int start_pos = std::stoi(bit_pos[j].substr(0, colon_pos));\n                    int end_pos = std::stoi(\n                        bit_pos[j].substr(colon_pos + 1, std::string::npos));\n                    if (start_pos > end_pos) {  // seriously there is no smart\n                                                // way in c++ to do this?\n                        for (int k = start_pos; k >= end_pos; k--) {\n                            mapped_pos[i].push_back(k);\n                        }\n                    } else {\n                        for (int k = start_pos; k <= end_pos; k++) {\n                            mapped_pos[i].push_back(k);\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n#ifdef DEBUG_LOC_MAPPING\n    std::cout << \"final mapped pos:\";\n    for (unsigned i = 0; i < mapped_pos.size(); i++) {\n        for (unsigned j = 0; j < mapped_pos[i].size(); j++) {\n            std::cout << mapped_pos[i][j] << \" \";\n        }\n        std::cout << std::endl;\n    }\n    std::cout << std::endl;\n#endif  // DEBUG_LOC_MAPPING\n\n    int column_offset = LogBase2(config_.BL);\n\n    GetPhyAddress = [mapped_pos, column_offset](const Address &addr) {\n        uint64_t new_hex = 0;\n        // ch - ra - bg - ba - ro - co\n        int origin_pos[] = {addr.channel, addr.rank, addr.bankgroup,\n                            addr.bank,    addr.row,  addr.column};\n        int new_pos[] = {0, 0, 0, 0, 0, 0};\n        for (unsigned i = 0; i < mapped_pos.size(); i++) {\n            int field_width = mapped_pos[i].size();\n            for (int j = 0; j < field_width; j++) {\n                uint64_t this_bit =\n                    GetBitInPos(origin_pos[i], field_width - j - 1);\n                uint64_t new_bit = (this_bit << mapped_pos[i][j]);\n                new_hex |= new_bit;\n#ifdef DEBUG_LOC_MAPPING\n                std::cout << \"mapping \" << this_bit << \" to \"\n                          << mapped_pos[i][j] << \", result:\" << std::hex\n                          << new_hex << std::dec << std::endl;\n#endif  // DEBUG_LOC_MAPPING\n            }\n        }\n\n        int pos = column_offset;\n        for (int i = mapped_pos.size() - 1; i >= 0; i--) {\n            new_pos[i] = ModuloWidth(new_hex, mapped_pos[i].size(), pos);\n            pos += mapped_pos[i].size();\n        }\n\n#ifdef DEBUG_LOC_MAPPING\n        std::cout << \"new channel \" << new_pos[0] << \" vs old channel \"\n                  << addr.channel << std::endl;\n        std::cout << \"new rank \" << new_pos[1] << \" vs old rank \" << addr.rank\n                  << std::endl;\n        std::cout << \"new bg \" << new_pos[2] << \" vs old bg \" << addr.bankgroup\n                  << std::endl;\n        std::cout << \"new bank \" << new_pos[3] << \" vs old bank \" << addr.bank_\n                  << std::endl;\n        std::cout << \"new row \" << new_pos[4] << \" vs old row \" << addr.row\n                  << std::endl;\n        std::cout << \"new col \" << new_pos[5] << \" vs old col \" << addr.column\n                  << std::endl;\n        std::cout << std::dec;\n#endif\n\n        return Address(new_pos[0], new_pos[1], new_pos[2], new_pos[3],\n                       new_pos[4], new_pos[5]);\n    };\n}\n\nstd::pair<int, int> ThermalCalculator::MapToVault(int channel_id) {\n    int vault_id_x = 0;\n    int vault_id_y = 0;\n    if (config_.IsHMC()) {\n        int vault_factor = vault_y;\n        if (config_.bank_order == 0) {\n            vault_factor = vault_x;\n        }\n        vault_id_x = channel_id / vault_factor;\n        vault_id_y = channel_id % vault_factor;\n        if (config_.bank_order == 0) {\n            std::swap(vault_id_x, vault_id_y);\n        }\n    } else if (config_.IsHBM()) {\n        vault_id_y = channel_id % 2;\n        vault_id_x = 0;\n    }\n    return std::make_pair(vault_id_x, vault_id_y);\n}\n\n// bank_id is the bank_id within a group, capped at config_.bankg_per_group\nstd::pair<int, int> ThermalCalculator::MapToBank(int bankgroup_id,\n                                                 int bank_id) {\n    int bank_id_x, bank_id_y;\n    // we're gonna assume bankgroup_id and bank_id are valid input\n    int abs_bank_id = bankgroup_id * config_.banks_per_group + bank_id;\n    int bank_factor = config_.bank_order ? bank_y : bank_x;\n\n    if (config_.IsHMC()) {\n        int num_bank_per_layer = config_.banks / config_.num_dies;\n        int bank_same_layer = abs_bank_id % num_bank_per_layer;\n        bank_id_x = bank_same_layer / bank_factor;\n        bank_id_y = bank_same_layer % bank_factor;\n        if (config_.bank_order == 0) {\n            std::swap(bank_id_x, bank_id_y);\n        }\n    } else if (config_.IsHBM()) {\n        bank_id_x = bankgroup_id * 2 + bank_id / 2;\n        bank_id_y = bank_id % 2;\n    } else {\n        if (config_.bankgroups > 1) {\n            // banks in a group always form like a square\n            // bank_groups are arranged in a line -- either in x or y direction\n            // default calculate bank_order y, reverse it later if not\n            bank_id_x = bank_id / 2;\n            bank_id_y = bank_id % 2;\n            if (config_.bank_order == 0) {\n                std::swap(bank_id_x, bank_id_y);\n            }\n            if (bank_x <= bank_y)\n                bank_id_y += bankgroup_id * 2;\n            else\n                bank_id_x += bankgroup_id * 2;\n        } else {\n            bank_id_x = abs_bank_id / bank_factor;\n            bank_id_y = abs_bank_id % bank_factor;\n            if (config_.bank_order == 0) {\n                std::swap(bank_id_x, bank_id_y);\n            }\n        }\n    }\n    return std::make_pair(bank_id_x, bank_id_y);\n}\n\nint ThermalCalculator::MapToZ(int channel_id, int bank_id) {\n    int z;\n    if (config_.IsHMC()) {\n        int num_bank_per_layer = config_.banks / config_.num_dies;\n        if (config_.bank_layer_order == 0)\n            z = bank_id / num_bank_per_layer;\n        else\n            z = numP - bank_id / num_bank_per_layer - 2;\n    } else if (config_.IsHBM()) {\n        z = channel_id / 2;\n    } else {\n        z = 0;\n    }\n    return z;\n}\n\nstd::pair<std::vector<int>, std::vector<int>> ThermalCalculator::MapToXY(\n    const Command &cmd, int vault_id_x, int vault_id_y, int bank_id_x,\n    int bank_id_y) {\n    std::vector<int> x;\n    std::vector<int> y;\n\n    int row_id = cmd.Row();\n    int col_tile_id = row_id / config_.tile_row_num;\n    int grid_id_x = row_id / config_.mat_dim_x / config_.row_tile;\n\n    Address temp_addr = Address(cmd.addr);\n    for (int i = 0; i < config_.BL; i++) {\n        Address phy_loc = GetPhyAddress(temp_addr);\n        int col_id = phy_loc.column * config_.device_width;\n        int bank_x_offset = bank_x * config_.num_x_grids;\n        int bank_y_offset = bank_y * config_.num_y_grids;\n        for (int j = 0; j < config_.device_width; j++) {\n            int grid_id_y =\n                col_id / config_.mat_dim_y +\n                col_tile_id * (config_.num_y_grids / config_.row_tile);\n            int temp_x = vault_id_x * bank_x_offset +\n                         bank_id_x * config_.num_x_grids + grid_id_x;\n            x.push_back(temp_x);\n            int temp_y = vault_id_y * bank_y_offset +\n                         bank_id_y * config_.num_y_grids + grid_id_y;\n            y.push_back(temp_y);\n            col_id++;\n        }\n        temp_addr.column++;\n    }\n    return std::make_pair(x, y);\n}\n\nvoid ThermalCalculator::LocationMappingANDaddEnergy(const int channel,\n                                                    const Command &cmd,\n                                                    int bank0, int row0,\n                                                    int caseID_,\n                                                    double add_energy) {\n    // get vault x y first\n    int vault_id_x, vault_id_y;\n    std::tie(vault_id_x, vault_id_y) = MapToVault(channel);\n\n    // get bank id x y\n    int bank_id_x, bank_id_y;\n    std::tie(bank_id_x, bank_id_y) = MapToBank(cmd.Bankgroup(), cmd.Bank());\n\n    // calculate x y z\n    auto xy = MapToXY(cmd, vault_id_x, vault_id_y, bank_id_x, bank_id_y);\n    auto &x = xy.first;\n    auto &y = xy.second;\n    int z = MapToZ(channel, cmd.Bank());\n\n    int z_offset = z * dimX * dimY;\n    double energy = add_energy / config_.device_width;\n    // add energy to engergy map\n    // iterate x y (they have same size)\n    for (size_t i = 0; i < x.size(); i++) {\n        int y_offset = y[i] * dimX;\n        int idx = z_offset + y_offset + x[i];\n        accu_Pmap[caseID_][idx] += energy;\n        cur_Pmap[caseID_][idx] += energy;\n    }\n}\n\nvoid ThermalCalculator::LocationMappingANDaddEnergy_RF(const int channel,\n                                                       const Command &cmd,\n                                                       int bank0, int row0,\n                                                       int caseID_,\n                                                       double add_energy) {\n    // the caller will provide bank and row that needs to be refreshed\n    // so we get a new address and modify it to obtain the actual mapping\n    // bank0 passed here is the absolute bank index within a rank, need to\n    // reverse it\n    int bankgroup_id = bank0 / config_.banks_per_group;\n    int bank_id = bank0 % config_.banks_per_group;\n    Address new_addr = Address(cmd.addr);\n    new_addr.row = row0;\n    new_addr.bankgroup = bankgroup_id;\n    new_addr.bank = bank_id;\n\n    int vault_id_x, vault_id_y;\n    std::tie(vault_id_x, vault_id_y) = MapToVault(channel);\n\n    // get bank id x y\n    int bank_id_x, bank_id_y;\n    std::tie(bank_id_x, bank_id_y) = MapToBank(bankgroup_id, bank_id);\n\n    int z = MapToZ(channel, bank_id);\n\n    Address phy_addr = GetPhyAddress(new_addr);  // actual row after mapping\n    // calculate x y z\n    int row_id = phy_addr.row;\n    int col_id = 0;  // refresh all units\n    int col_tile_id = row_id / config_.tile_row_num;\n    int grid_id_x = row_id / config_.mat_dim_x / config_.row_tile;\n    int grid_id_y = col_id / config_.mat_dim_y +\n                    col_tile_id * (config_.num_y_grids / config_.row_tile);\n    int x = vault_id_x * (bank_x * config_.num_x_grids) +\n            bank_id_x * config_.num_x_grids + grid_id_x;\n    int y = vault_id_y * (bank_y * config_.num_y_grids) +\n            bank_id_y * config_.num_y_grids + grid_id_y;\n\n    int z_offset = z * (dimX * dimY);\n    for (int i = 0; i < config_.num_y_grids; i++) {\n        int y_offset = y * dimX;\n        int idx = z_offset + y_offset + x;\n        accu_Pmap[caseID_][idx] += add_energy;\n        cur_Pmap[caseID_][idx] += add_energy;\n        y++;\n    }\n}\n\nvoid ThermalCalculator::UpdatePowerMaps(double add_energy, bool trans,\n                                        uint64_t clk) {\n    auto &p_map = trans ? cur_Pmap : accu_Pmap;\n    double period = trans ? static_cast<double>(config_.epoch_period)\n                          : static_cast<double>(clk);\n    for (int j = 0; j < num_case; j++) {\n        // universally update power map\n        for (int i = 0; i < dimX * dimY * (numP - 1); i++) {\n            p_map[j][i] += add_energy;\n        }\n        // update logic power map\n        // UpdateLogicPower();\n        for (int i = dimX * dimY * (numP - 1); i < dimX * dimY * numP; i++) {\n            p_map[j][i] += avg_logic_power_ / dimX / dimY * period;\n        }\n    }\n}\n\nvoid ThermalCalculator::UpdateCMDPower(const int channel, const Command &cmd,\n                                       const uint64_t clk) {\n    int rank = cmd.Rank();\n    // int channel = cmd.Channel();\n    int case_id;\n    double device_scale;\n    if (config_.IsHMC() || config_.IsHBM()) {\n        device_scale = 1;\n        case_id = 0;\n    } else {\n        device_scale = (double)config_.devices_per_rank;\n        case_id = channel * config_.ranks + rank;\n    }\n\n    double energy = 0.0;\n    if (cmd.cmd_type == CommandType::REFRESH) {\n        int rank_idx = channel * config_.ranks + rank;\n        for (int ib = 0; ib < config_.banks; ib++) {\n            int row_s = refresh_count[rank_idx][ib] * config_.num_row_refresh;\n            refresh_count[rank_idx][ib]++;\n            if (refresh_count[rank_idx][ib] * config_.num_row_refresh ==\n                config_.rows)\n                refresh_count[rank_idx][ib] = 0;\n            energy = config_.ref_energy_inc / config_.num_row_refresh /\n                     config_.banks / config_.num_y_grids;\n            for (int ir = row_s; ir < row_s + config_.num_row_refresh; ir++) {\n                LocationMappingANDaddEnergy_RF(channel, cmd, ib, ir, case_id,\n                                               energy / 1000.0 / device_scale);\n            }\n        }\n    } else if (cmd.cmd_type == CommandType::REFRESH_BANK) {\n        int ib = cmd.Bank();\n        int rank_idx = channel * config_.ranks + rank;\n        int row_s = refresh_count[rank_idx][ib] * config_.num_row_refresh;\n        refresh_count[rank_idx][ib]++;\n        if (refresh_count[rank_idx][ib] * config_.num_row_refresh ==\n            config_.rows)\n            refresh_count[rank_idx][ib] = 0;\n        energy = config_.refb_energy_inc / config_.num_row_refresh /\n                 config_.num_y_grids;\n        for (int ir = row_s; ir < row_s + config_.num_row_refresh; ir++) {\n            LocationMappingANDaddEnergy_RF(channel, cmd, ib, ir, case_id,\n                                           energy / 1000.0 / device_scale);\n        }\n    } else {\n        switch (cmd.cmd_type) {\n            case CommandType::ACTIVATE:\n                energy = config_.act_energy_inc;\n                break;\n            case CommandType::READ:\n            case CommandType::READ_PRECHARGE:\n                energy = config_.read_energy_inc;\n                break;\n            case CommandType::WRITE:\n            case CommandType::WRITE_PRECHARGE:\n                energy = config_.write_energy_inc;\n                break;\n            default:\n                energy = 0.0;\n                break;\n        }\n        if (energy > 0) {\n            energy /= config_.BL;\n            LocationMappingANDaddEnergy(channel, cmd, -1, -1, case_id,\n                                        energy / 1000.0 / device_scale);\n        }\n    }\n    return;\n}\n\nvoid ThermalCalculator::UpdateBackgroundEnergy(const int channel,\n                                               const int rank,\n                                               const double energy) {\n    background_energy_[channel][rank] = energy;\n}\n\nvoid ThermalCalculator::UpdateEpoch(uint64_t clk) {\n    if (config_.IsHBM() || config_.IsHMC()) {\n        double bg_energy = 0;\n        for (const auto &vec_rank_energy : background_energy_) {\n            for (const auto &rank_energy : vec_rank_energy) {\n                bg_energy += rank_energy;\n            }\n        }\n        bg_energy = bg_energy / (dimX * dimY * (numP - 1));\n        UpdatePowerMaps(bg_energy / 1000, true, config_.epoch_period);\n    } else {\n        double num_devices = static_cast<double>(config_.devices_per_rank);\n        for (int i = 0; i < config_.channels; i++) {\n            for (int j = 0; j < config_.ranks; j++) {\n                int case_id = i * config_.ranks + j;\n                double bg_energy =\n                    background_energy_[i][j] / (dimX * dimY * numP);\n                for (int k = 0; k < dimX * dimY * numP; i++) {\n                    cur_Pmap[case_id][k] += bg_energy / 1000 / num_devices;\n                }\n            }\n        }\n    }\n    return;\n}\n\nvoid ThermalCalculator::SetLogicPower(double logic_power) {\n    avg_logic_power_ = logic_power;\n}\n\nvoid ThermalCalculator::PrintTransPT(uint64_t clk) {\n    UpdateEpoch(clk);\n    double ms = clk * config_.tCK * 1e-6;\n    for (int ir = 0; ir < num_case; ir++) {\n        CalcTransT(ir);\n        double maxT = 0;\n        for (int layer = 0; layer < numP; layer++) {\n            double maxT_layer = GetMaxTofCaseLayer(T_trans, ir, layer);\n            epoch_max_temp_file_csv_ << layer << \",\" << maxT_layer << \",\" << ms\n                                     << std::endl;\n            // << layer << \",\" << stats_.average_power.epoch_value << \",\"\n            // << maxT_layer << \",\" << bw_usage_ << \",\" << ms << std::endl;\n            std::cout << \"MaxT of case \" << ir << \" in layer \" << layer\n                      << \" is \" << maxT_layer << \" [C]\\n\";\n            maxT = maxT > maxT_layer ? maxT : maxT_layer;\n        }\n        std::cout << \"MaxT of case \" << ir << \" is \" << maxT << \" [C] at \" << ms\n                  << \" ms\\n\";\n        // only outputs full file when output level >= 2\n        if (config_.output_level >= 2) {\n            PrintCSV_trans(epoch_temperature_file_csv_, cur_Pmap, T_trans, ir,\n                           config_.epoch_period);\n        }\n    }\n    for (size_t i = 0; i < cur_Pmap.size(); i++) {\n        std::fill_n(cur_Pmap[i].begin(), numP * dimX * dimY, 0.0);\n    }\n    sample_id += 1;\n}\n\nvoid ThermalCalculator::PrintFinalPT(uint64_t clk) {\n    if (config_.IsHBM() || config_.IsHMC()) {\n        double bg_energy = 0;\n        for (const auto &vec_rank_energy : background_energy_) {\n            for (const auto &rank_energy : vec_rank_energy) {\n                bg_energy += rank_energy;\n            }\n        }\n        bg_energy /= (dimX * dimY * (numP - 1));\n        UpdatePowerMaps(bg_energy / 1000, false, clk);\n    } else {\n        double num_devices = static_cast<double>(config_.devices_per_rank);\n        for (int i = 0; i < config_.channels; i++) {\n            for (int j = 0; j < config_.ranks; j++) {\n                int case_id = i * config_.ranks + j;\n                double bg_energy =\n                    background_energy_[i][j] / (dimX * dimY * numP);\n                for (int k = 0; k < dimX * dimY * numP; i++) {\n                    accu_Pmap[case_id][i] += bg_energy / 1000 / num_devices;\n                }\n            }\n        }\n    }\n    // calculate the final temperature for each case\n    for (int ir = 0; ir < num_case; ir++) {\n        CalcFinalT(ir, clk);\n        double maxT = GetMaxTofCase(T_final, ir);\n        std::cout << \"MaxT of case \" << ir << \" is \" << maxT << \" [C]\\n\";\n        // print to file\n        PrintCSV_final(final_temperature_file_csv_, accu_Pmap, T_final, ir,\n                       clk);\n    }\n\n    // close all the csv files\n    final_temperature_file_csv_.close();\n    epoch_max_temp_file_csv_.close();\n    if (config_.output_level >= 2) {\n        epoch_temperature_file_csv_.close();\n    }\n}\n\nvoid ThermalCalculator::CalcTransT(int case_id) {\n    double time = config_.epoch_period * config_.tCK * 1e-9;\n    double ***powerM = InitPowerM(case_id, 0);\n    double totP = GetTotalPower(powerM);\n    std::cout << \"total trans power is \" << totP * 1000 << \" [mW]\" << std::endl;\n    T_trans[case_id] = transient_thermal_solver(\n        powerM, config_.chip_dim_x, config_.chip_dim_y, numP, dimX + num_dummy,\n        dimY + num_dummy, Midx, MidxSize, Cap, CapSize, time, time_iter,\n        T_trans[case_id], Tamb);\n}\n\nvoid ThermalCalculator::CalcFinalT(int case_id, uint64_t clk) {\n    double ***powerM = InitPowerM(case_id, clk);\n    double totP = GetTotalPower(powerM);\n    std::cout << \"total final power is \" << totP * 1000 << \" [mW]\" << std::endl;\n    double *T = steady_thermal_solver(\n        powerM, config_.chip_dim_x, config_.chip_dim_y, numP, dimX + num_dummy,\n        dimY + num_dummy, Midx, MidxSize, Tamb);\n    T_final[case_id] = T;\n}\n\ndouble ***ThermalCalculator::InitPowerM(int case_id, uint64_t clk) {\n    double ***powerM;\n    // assert in powerM\n    powerM = new double **[dimX + num_dummy];\n    for (int i = 0; i < dimX + num_dummy; i++) {\n        powerM[i] = new double *[dimY + num_dummy];\n        for (int j = 0; j < dimY + num_dummy; j++) {\n            powerM[i][j] = new double[numP];\n        }\n    }\n    // initialize powerM\n    for (int i = 0; i < dimX + num_dummy; i++)\n        for (int j = 0; j < dimY + num_dummy; j++)\n            std::fill_n(powerM[i][j], numP, 0.0);\n\n    // when clk is 0 then it's trans otherwise it's final\n    double div = clk == 0 ? (double)config_.epoch_period : (double)clk;\n    auto &power_map = clk == 0 ? cur_Pmap : accu_Pmap;\n    // fill in powerM\n    for (int i = 0; i < dimX; i++) {\n        for (int j = 0; j < dimY; j++) {\n            for (int l = 0; l < numP; l++) {\n                powerM[i + num_dummy / 2][j + num_dummy / 2][l] =\n                    power_map[case_id][l * (dimX * dimY) + j * dimX + i] / div;\n            }\n        }\n    }\n    return powerM;\n}\n\ndouble ThermalCalculator::GetTotalPower(double ***powerM) {\n    double total_power = 0.0;\n    for (int i = 0; i < dimX; i++) {\n        for (int j = 0; j < dimY; j++) {\n            for (int l = 0; l < numP; l++) {\n                total_power += powerM[i + num_dummy / 2][j + num_dummy / 2][l];\n            }\n        }\n    }\n    return total_power;\n}\n\nvoid ThermalCalculator::InitialParameters() {\n    layerP = std::vector<int>(numP, 0);\n    for (int l = 0; l < numP; l++) layerP[l] = l * 3;\n    Midx = calculate_Midx_array(config_.chip_dim_x, config_.chip_dim_y, numP,\n                                dimX + num_dummy, dimY + num_dummy, &MidxSize,\n                                Tamb);\n    Cap = calculate_Cap_array(config_.chip_dim_x, config_.chip_dim_y, numP,\n                              dimX + num_dummy, dimY + num_dummy, &CapSize);\n    calculate_time_step();\n\n    for (int ir = 0; ir < num_case; ir++) {\n        double *T =\n            initialize_Temperature(config_.chip_dim_x, config_.chip_dim_y, numP,\n                                   dimX + num_dummy, dimY + num_dummy, Tamb);\n        for (int i = 0; i < T_size; i++) T_trans[ir][i] = T[i];\n        free(T);\n    }\n}\n\nint ThermalCalculator::square_array(int total_grids_) {\n    int x, y, x_re = 1;\n    for (x = 1; x <= sqrt(total_grids_); x++) {\n        y = total_grids_ / x;\n        if (x * y == total_grids_) x_re = x;\n    }\n    return x_re;\n}\n\nint ThermalCalculator::determineXY(double xd, double yd, int total_grids_) {\n    int x, y, x_re = 1;\n    double asr, asr_re = 1000;\n    for (y = 1; y <= total_grids_; y++) {\n        x = total_grids_ / y;\n        if (x * y == total_grids_) {\n            // total_grids_ can be factored by x and y\n            asr = (x * xd >= y * yd) ? (x * xd / y / yd) : (y * yd / x / xd);\n            if (asr < asr_re) {\n                std::cout << \"asr = \" << asr << \"; x = \" << x << \"; y = \" << y\n                          << \"; xd = \" << xd << std::endl;\n                x_re = total_grids_ / y;\n                asr_re = asr;\n            }\n        }\n    }\n    return x_re;\n}\n\nvoid ThermalCalculator::calculate_time_step() {\n    double dt = 100.0;\n    int layer_dim = (dimX + num_dummy) * (dimY + num_dummy);\n\n    for (int j = 0; j < MidxSize; j++) {\n        int idx0 = (int)(Midx[j][0] + 0.01);\n        int idx1 = (int)(Midx[j][1] + 0.01);\n        int idxC = idx0 / layer_dim;\n\n        if (idx0 == idx1) {\n            double g = Midx[j][2];\n            double c = Cap[idxC];\n            if (c / g < dt) dt = c / g;\n        }\n    }\n\n    std::cout << \"maximum dt is \" << dt << std::endl;\n\n    // calculate time_iter\n    double power_epoch_time = config_.epoch_period * config_.tCK * 1e-9;  // [s]\n    std::cout << \"power_epoch_time = \" << power_epoch_time << std::endl;\n    time_iter = time_iter0;\n    while (power_epoch_time / time_iter >= dt) time_iter++;\n    // time_iter += 10;\n    std::cout << \"time_iter = \" << time_iter << std::endl;\n}\n\ndouble ThermalCalculator::GetMaxTofCase(double **temp_map, int case_id) {\n    double maxT = 0;\n    for (int i = 0; i < T_size; i++) {\n        if (temp_map[case_id][i] > maxT) {\n            maxT = temp_map[case_id][i];\n        }\n    }\n    return maxT;\n}\n\ndouble ThermalCalculator::GetMaxTofCaseLayer(double **temp_map, int case_id,\n                                             int layer) {\n    double maxT = 0;\n    int layer_pos_offset =\n        (layerP[layer] + 1) * ((dimX + num_dummy) * (dimY + num_dummy));\n    for (int j = num_dummy / 2; j < dimY + num_dummy / 2; j++) {\n        for (int i = num_dummy / 2; i < dimX + num_dummy / 2; i++) {\n            double t = temp_map[case_id]\n                               [layer_pos_offset + j * (dimX + num_dummy) + i] -\n                       T0;\n            maxT = maxT > t ? maxT : t;\n        }\n    }\n    return maxT;\n}\n\nvoid ThermalCalculator::PrintCSV_trans(std::ofstream &csvfile,\n                                       std::vector<std::vector<double>> P_,\n                                       double **T_, int id, uint64_t scale) {\n    for (int l = 0; l < numP; l++) {\n        for (int j = num_dummy / 2; j < dimY + num_dummy / 2; j++) {\n            for (int i = num_dummy / 2; i < dimX + num_dummy / 2; i++) {\n                double pw =\n                    P_[id][l * ((dimX) * (dimY)) +\n                           (j - num_dummy / 2) * (dimX) + (i - num_dummy / 2)] /\n                    (double)scale;\n                double tm = T_[id][(layerP[l] + 1) * ((dimX + num_dummy) *\n                                                      (dimY + num_dummy)) +\n                                   j * (dimX + num_dummy) + i] -\n                            T0;\n                csvfile << id << \",\" << i - num_dummy / 2 << \",\"\n                        << j - num_dummy / 2 << \",\" << l << \",\" << pw << \",\"\n                        << tm << \",\" << sample_id << std::endl;\n            }\n        }\n    }\n}\n\nvoid ThermalCalculator::PrintCSV_final(std::ofstream &csvfile,\n                                       std::vector<std::vector<double>> P_,\n                                       double **T_, int id, uint64_t scale) {\n    for (int l = 0; l < numP; l++) {\n        for (int j = num_dummy / 2; j < dimY + num_dummy / 2; j++) {\n            for (int i = num_dummy / 2; i < dimX + num_dummy / 2; i++) {\n                double pw =\n                    P_[id][l * (dimX * dimY) + (j - num_dummy / 2) * dimX +\n                           (i - num_dummy / 2)] /\n                    (double)scale;\n                double tm = T_[id][(layerP[l] + 1) * ((dimX + num_dummy) *\n                                                      (dimY + num_dummy)) +\n                                   j * (dimX + num_dummy) + i];\n                csvfile << id << \",\" << i - num_dummy / 2 << \",\"\n                        << j - num_dummy / 2 << \",\" << l << \",\" << pw << \",\"\n                        << tm << std::endl;\n            }\n        }\n    }\n}\n\nvoid ThermalCalculator::PrintCSV_bank(std::ofstream &csvfile) {\n    // header\n    csvfile << \"vault_id,bank_id,start_x,end_x,start_y,end_y,z\" << std::endl;\n\n    for (int vault_id = 0; vault_id < config_.channels; vault_id++) {\n        int vault_id_x, vault_id_y;\n        std::tie(vault_id_x, vault_id_y) = MapToVault(vault_id);\n        for (int bg = 0; bg < config_.bankgroups; bg++) {\n            for (int bank = 0; bank < config_.banks_per_group; bank++) {\n                int abs_bank_id = bg * config_.banks_per_group + bank;\n                int z = MapToZ(vault_id, abs_bank_id);\n                int bank_id_x, bank_id_y;\n                std::tie(bank_id_x, bank_id_y) = MapToBank(bg, bank);\n\n                int bank_offset = bank_x * config_.num_x_grids;\n                int start_x =\n                    vault_id_x * bank_offset + bank_id_x * config_.num_x_grids;\n                int end_x = vault_id_x * bank_offset +\n                            (bank_id_x + 1) * config_.num_x_grids - 1;\n\n                bank_offset = bank_y * config_.num_y_grids;\n                int start_y =\n                    vault_id_y * bank_offset + bank_id_y * config_.num_y_grids;\n                int end_y = vault_id_y * bank_offset +\n                            (bank_id_y + 1) * config_.num_y_grids - 1;\n                csvfile << vault_id << \",\" << abs_bank_id << \",\" << start_x\n                        << \",\" << end_x << \",\" << start_y << \",\" << end_y << \",\"\n                        << z << std::endl;\n            }\n        }\n    }\n}\n\nvoid ThermalCalculator::PrintCSVHeader_final(std::ofstream &csvfile) {\n    csvfile << \"rank_channel_index,x,y,z,power,temperature\" << std::endl;\n}\n\n}  // namespace dramsim3\n"
  },
  {
    "path": "src/DRAMsim3/src/thermal.h",
    "content": "#ifndef __THERMAL_H\n#define __THERMAL_H\n\n#include <time.h>\n#include <cmath>\n#include <fstream>\n#include <functional>\n#include <iostream>\n#include <vector>\n#include \"bankstate.h\"\n#include \"common.h\"\n#include \"configuration.h\"\n#include \"thermal_config.h\"\n\nnamespace dramsim3 {\n\nextern std::function<Address(const Address &addr)> GetPhyAddress;\n\nclass ThermalCalculator {\n   public:\n    ThermalCalculator(const Config &config);\n    ~ThermalCalculator();\n    void UpdateCMDPower(const int channel, const Command &cmd,\n                        const uint64_t clk);\n    void UpdateBackgroundEnergy(const int channel, const int rank,\n                                const double energy);\n    // assuming evenly distributed logic layer power\n    void UpdateEpoch(const uint64_t clk);\n    void SetLogicPower(double logic_power);\n    void PrintTransPT(uint64_t clk);\n    void PrintFinalPT(uint64_t clk);\n    void UpdateLogicPower(double logic_power);\n\n   private:\n    // Initialization\n    double ***InitPowerM(int case_id, uint64_t clk);\n    void InitialParameters();\n\n    // location mapping functions\n    void SetPhyAddressMapping();\n    std::pair<int, int> MapToVault(int channel_id);\n    std::pair<int, int> MapToBank(int bankgroup_id, int bank_id);\n    int MapToZ(int channel_id, int bank_id);\n    std::pair<std::vector<int>, std::vector<int>> MapToXY(const Command &cmd,\n                                                          int vault_id_x,\n                                                          int vault_id_y,\n                                                          int bank_id_x,\n                                                          int bank_id_y);\n    void LocationMappingANDaddEnergy_RF(const int channel, const Command &cmd,\n                                        int bank0, int row0, int caseID_,\n                                        double add_energy);\n    void LocationMappingANDaddEnergy(const int channel, const Command &cmd,\n                                     int bank0, int row0, int caseID_,\n                                     double add_energy);\n    void UpdatePowerMaps(double add_energy, bool trans, uint64_t clk);\n\n    // calculations\n    void CalcTransT(int case_id);\n    void CalcFinalT(int case_id, uint64_t clk);\n    double GetTotalPower(double ***powerM);\n    int square_array(int total_grids_);\n    int determineXY(double xd, double yd, int total_grids_);\n    double GetMaxTofCase(double **temp_map, int case_id);\n    double GetMaxTofCaseLayer(double **temp_map, int case_id, int layer);\n    void calculate_time_step();\n\n    // print to csv-files\n    void PrintCSV_trans(std::ofstream &csvfile,\n                        std::vector<std::vector<double>> P_, double **T_,\n                        int id, uint64_t scale);\n    void PrintCSV_final(std::ofstream &csvfile,\n                        std::vector<std::vector<double>> P_, double **T_,\n                        int id, uint64_t scale);\n    void PrintCSVHeader_final(std::ofstream &csvfile);\n    void PrintCSV_bank(std::ofstream &csvfile);\n\n\n    const Config &config_;\n\n    int time_iter0, time_iter;\n    double Tamb;  // The ambient temperature in Kelvin\n    const int num_dummy = 2;  // dummy cells around the calculatd die\n\n    int dimX, dimY, numP;   // Dimension of the memory\n    double **Midx;          // Midx storing thermal conductance\n    double *Cap;            // Cap storing the thermal capacitance\n    int MidxSize, CapSize;  // first dimension size of Midx and Cap\n    int T_size;\n    double **T_trans, **T_final;\n\n    int sample_id;  // index of the sampling power\n\n    std::vector<std::vector<double>> accu_Pmap;  // accumulative power map\n    std::vector<std::vector<double>> cur_Pmap;   // current power map\n\n    std::vector<std::vector<int>> refresh_count;\n\n    // other intermediate parameters\n    // not need to be defined here but it will be easy to use if it is defined\n    int vault_x, vault_y, bank_x, bank_y;\n    int num_case;  // number of different cases where the thermal simulation is\n                   // performed\n    std::vector<int> layerP;\n\n    // Output files\n    std::ofstream epoch_max_temp_file_csv_;\n    std::ofstream epoch_temperature_file_csv_;\n    std::ofstream final_temperature_file_csv_;\n    std::ofstream bank_position_csv_;\n\n    std::vector<std::vector<double>> background_energy_;\n    double avg_logic_power_;\n};\n}  // namespace dramsim3\n\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/thermal_config.h",
    "content": "#ifndef THERMALCONFIG_H\n#define THERMALCONFIG_H\n\n#ifndef M_PI\nconst double M_PI = 3.141592653;\n#endif\n\nconst double T0 = 273.15;  // [C]\n\nconst double R_TSV = 5e-6;  // [m]\n\n/* Thermal conductance */\nconst double Ksi = 148.0;  // Silicon\nconst double Kcu = 401.0;  // Copper\nconst double Kin = 1.5;    // insulator\nconst double Khs = 4.0;    // Heat sink\n\n/* Thermal capacitance */\nconst double Csi = 1.66e6;  // Silicon\nconst double Ccu = 3.2e6;   // Copper\nconst double Cin = 1.65e6;  // insulator\nconst double Chs = 2.42e6;  // Heat sink\n\n/* Layer Hight */\nconst double Hsi = 400e-6;   // Silicon\nconst double Hcu = 5e-6;     // Copper\nconst double Hin = 20e-6;    // Insulator\nconst double Hhs = 1000e-6;  // Heat sink\n\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/thermal_replay.cc",
    "content": "#include \"thermal_replay.h\"\n#include \"./../ext/headers/args.hxx\"\n\n// this will not be used in a library file so it's ok to do this\nusing namespace dramsim3;\n\nThermalReplay::ThermalReplay(std::string trace_name, std::string config_file,\n                             std::string output_dir, uint64_t repeat)\n    : config_(config_file, output_dir),\n      thermal_calc_(config_),\n      repeat_(repeat),\n      last_clk_(0) {\n    for (int i = 0; i < config_.channels; i++) {\n        channel_stats_.emplace_back(config_, i);\n    }\n\n    // Initialize bank states, for power calculation we only need to know\n    // if it's active\n    for (int i = 0; i < config_.channels; i++) {\n        std::vector<std::vector<std::vector<bool>>> chan_vec;\n        for (int j = 0; j < config_.ranks; j++) {\n            std::vector<std::vector<bool>> rank_vec;\n            for (int k = 0; k < config_.bankgroups; k++) {\n                std::vector<bool> bank_vec(config_.banks_per_group, false);\n                rank_vec.push_back(bank_vec);\n            }\n            chan_vec.push_back(rank_vec);\n        }\n        bank_active_.push_back(chan_vec);\n    }\n\n    // read commands into memory\n    std::ifstream trace_file(trace_name);\n    if (!trace_file) {\n        std::cout << \"cannot open trace file \" << trace_name << std::endl;\n        std::exit(1);\n    }\n\n    std::string line;\n    uint64_t clk = 0;\n    while (std::getline(trace_file, line)) {\n        Command cmd;\n        ParseLine(line, clk, cmd);\n        timed_commands_.push_back(std::pair<uint64_t, Command>(clk, cmd));\n    }\n    trace_file.close();\n}\n\nThermalReplay::~ThermalReplay() {}\n\nvoid ThermalReplay::Run() {\n    uint64_t clk = 0;\n    for (uint64_t i = 0; i < repeat_; i++) {\n        uint64_t clk_offset = 0;\n        for (size_t j = 0; j < timed_commands_.size(); j++) {\n            // for (int j = 0; j < cmds_.size(); j++) {\n            // Command &cmd = cmds_[j];\n            // clk_offset = clks_[j];\n            clk_offset = timed_commands_[j].first;\n            Command &cmd = timed_commands_[j].second;\n            ProcessCMD(cmd, clk + clk_offset);\n            thermal_calc_.UpdateCMDPower(0, cmd, clk + clk_offset);\n        }\n        clk += clk_offset;\n\n        // reset bank states\n        for (int c = 0; c < config_.channels; c++) {\n            for (int r = 0; r < config_.ranks; r++) {\n                for (int g = 0; g < config_.bankgroups; g++) {\n                    for (int b = 0; b < config_.banks_per_group; b++) {\n                        bank_active_[c][r][g][b] = false;\n                    }\n                }\n            }\n        }\n    }\n    for (int c = 0; c < config_.channels; c++) {\n        channel_stats_[c].PrintFinalStats(clk, std::cout, std::cout, std::cout);\n    }\n    thermal_calc_.PrintFinalPT(clk);\n}\n\n// parsing line from trace file into a command\nvoid ThermalReplay::ParseLine(std::string line, uint64_t &clk, Command &cmd) {\n    std::map<std::string, CommandType> cmd_map = {\n        {\"read\", CommandType::READ},\n        {\"read_p\", CommandType::READ_PRECHARGE},\n        {\"write\", CommandType::WRITE},\n        {\"write_p\", CommandType::WRITE_PRECHARGE},\n        {\"activate\", CommandType::ACTIVATE},\n        {\"precharge\", CommandType::PRECHARGE},\n        {\"refresh_bank\", CommandType::REFRESH_BANK},  // verilog model doesn't\n                                                      // distinguish bank/rank\n                                                      // refresh\n        {\"refresh\", CommandType::REFRESH},\n        {\"self_refresh_enter\", CommandType::SREF_ENTER},\n        {\"self_refresh_exit\", CommandType::SREF_EXIT},\n    };\n    std::vector<std::string> tokens = StringSplit(line, ' ');\n\n    // basic sanity check\n    if (tokens.size() != 8) {\n        std::cerr << \"Check trace format!\" << std::endl;\n        AbruptExit(__FILE__, __LINE__);\n    }\n\n    // converting clock\n    clk = stoull(tokens[0]);\n\n    // converting address\n    Address addr(std::stoi(tokens[2]), std::stoi(tokens[3]),\n                 std::stoi(tokens[4]), std::stoi(tokens[5]),\n                 std::stoi(tokens[6]), std::stoi(tokens[7]));\n\n    // reassign cmd\n    cmd.addr = addr;\n    cmd.cmd_type = cmd_map[tokens[1]];\n    return;\n}\n\nvoid ThermalReplay::ProcessCMD(Command &cmd, uint64_t clk) {\n    // calculate background power\n    // TODO add self-ref later\n    uint64_t past_clks = clk - last_clk_;\n    for (int i = 0; i < config_.channels; i++) {\n        for (int j = 0; j < config_.ranks; j++) {\n            if (IsRankActive(i, j)) {\n                channel_stats_[i].IncrementVecBy(\"rank_active_cycles\", j,\n                                                 past_clks);\n            } else {\n                channel_stats_[i].IncrementVecBy(\"all_bank_idle_cycles\", j,\n                                                 past_clks);\n            }\n        }\n    }\n\n    int channel = cmd.Channel();\n    // update cmd count\n    switch (cmd.cmd_type) {\n        case CommandType::READ:\n        case CommandType::READ_PRECHARGE:\n            channel_stats_[channel].Increment(\"num_read_cmds\");\n            break;\n        case CommandType::WRITE:\n        case CommandType::WRITE_PRECHARGE:\n            channel_stats_[channel].Increment(\"num_write_cmds\");\n            break;\n        case CommandType::ACTIVATE:\n            channel_stats_[channel].Increment(\"num_act_cmds\");\n            break;\n        case CommandType::PRECHARGE:\n            channel_stats_[channel].Increment(\"num_pre_cmds\");\n            break;\n        case CommandType::REFRESH:\n            channel_stats_[channel].Increment(\"num_ref_cmds\");\n            break;\n        case CommandType::REFRESH_BANK:\n            channel_stats_[channel].Increment(\"num_refb_cmds\");\n            break;\n        case CommandType::SREF_ENTER:\n            channel_stats_[channel].Increment(\"num_srefe_cmds\");\n            break;\n        case CommandType::SREF_EXIT:\n            channel_stats_[channel].Increment(\"num_srefx_cmds\");\n            break;\n        default:\n            AbruptExit(__FILE__, __LINE__);\n    }\n\n    // update bank states\n    switch (cmd.cmd_type) {\n        case CommandType::ACTIVATE:\n            bank_active_[cmd.Channel()][cmd.Rank()][cmd.Bankgroup()]\n                        [cmd.Bank()] = true;\n            break;\n        case CommandType::READ_PRECHARGE:\n        case CommandType::WRITE_PRECHARGE:\n        case CommandType::PRECHARGE:\n            bank_active_[cmd.Channel()][cmd.Rank()][cmd.Bankgroup()]\n                        [cmd.Bank()] = false;\n            break;\n        default:\n            break;\n    }\n\n    if (clk % config_.epoch_period) {\n        for (int c = 0; c < config_.channels; c++) {\n            // where to print isn't important here what we really need is the\n            // updated stats\n            channel_stats_[c].PrintEpochStats(clk, std::cout);\n            for (int r = 0; r < config_.ranks; r++) {\n                double bg_energy = channel_stats_[c].RankBackgroundEnergy(r);\n                thermal_calc_.UpdateBackgroundEnergy(c, r, bg_energy);\n            }\n        }\n    }\n    last_clk_ = clk;\n    return;\n}\n\nbool ThermalReplay::IsRankActive(int channel, int rank) {\n    std::vector<std::vector<bool>> &rank_active = bank_active_[channel][rank];\n    for (size_t i = 0; i < rank_active.size(); i++) {\n        std::vector<bool> &bg_active = rank_active[i];\n        for (size_t j = 0; j < bg_active.size(); j++) {\n            if (bg_active[j]) {\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nint main(int argc, const char **argv) {\n    args::ArgumentParser parser(\"Thermal Replay Module\", \"\");\n    args::HelpFlag help(parser, \"help\", \"Display the help menu\", {\"h\", \"help\"});\n    args::ValueFlag<uint64_t> repeat_arg(parser, \"repeats\", \"Number of repeats\",\n                                         {'r', \"num-repeats\"}, 10);\n    args::ValueFlag<std::string> config_arg(parser, \"config\", \"The config file\",\n                                            {'c', \"config-file\"});\n    args::ValueFlag<std::string> output_dir_arg(\n        parser, \"output-dir\", \"Output directory for stats files\",\n        {'o', \"output-dir\"}, \"results\");\n    args::ValueFlag<std::string> memory_type_arg(\n        parser, \"memory_type\", \"Type of memory system - default, hmc, ideal\",\n        {\"memory-type\"}, \"default\");\n    args::ValueFlag<std::string> trace_file_arg(\n        parser, \"trace\", \"The trace file\", {'t', \"trace-file\"});\n\n    try {\n        parser.ParseCLI(argc, argv);\n    } catch (args::Help) {\n        std::cout << parser;\n        return 0;\n    } catch (args::ParseError e) {\n        std::cerr << e.what() << std::endl;\n        std::cerr << parser;\n        return 1;\n    }\n\n    uint64_t repeats = args::get(repeat_arg);\n    std::string config_file, output_dir, trace_file, memory_system_type;\n    config_file = args::get(config_arg);\n    output_dir = args::get(output_dir_arg);\n    trace_file = args::get(trace_file_arg);\n    memory_system_type = args::get(memory_type_arg);\n\n    ThermalReplay thermal_replay(trace_file, config_file, output_dir, repeats);\n\n    thermal_replay.Run();\n\n    return 0;\n}\n"
  },
  {
    "path": "src/DRAMsim3/src/thermal_replay.h",
    "content": "#ifndef __THERMAL_REPLAY_H\n#define __THERMAL_REPLAY_H\n\n#include <fstream>\n#include <string>\n#include <vector>\n\n#include \"common.h\"\n#include \"configuration.h\"\n#include \"simple_stats.h\"\n#include \"thermal.h\"\n\nnamespace dramsim3 {\n\nclass ThermalReplay {\n   public:\n    ThermalReplay(std::string trace_name, std::string config_file,\n                  std::string output_dir, uint64_t repeat);\n    ~ThermalReplay();\n    void Run();\n\n   private:\n    std::vector<std::pair<uint64_t, Command>> timed_commands_;\n    Config config_;\n    ThermalCalculator thermal_calc_;\n    uint64_t repeat_;\n    uint64_t last_clk_;\n    std::vector<SimpleStats> channel_stats_;\n    std::vector<std::vector<std::vector<std::vector<bool>>>> bank_active_;\n    void ParseLine(std::string line, uint64_t &clk, Command &cmd);\n    void ProcessCMD(Command &cmd, uint64_t clk);\n    bool IsRankActive(int channel, int rank);\n};\n\n}  // namespace dramsim3\n\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/src/thermal_solver.c",
    "content": "/* thermal solver\n * based on superLU\n * zhiyuan yang\n */\n#include <math.h>\n#include <omp.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <time.h>\n#include \"../ext/SuperLU_MT_3.1/SRC/slu_mt_ddefs.h\"\n#include \"thermal_config.h\"\n\n//#define DEBUG\n//#define DEBUGMIDX\n//#define DEBUGMAT\n\ndouble get_maxT(double *T, int Tsize);\n\ndouble *initialize_Temperature(double W, double Lc, int numP, int dimX,\n                               int dimZ, double Tamb) {\n    int numLayer, l;\n    double *T;\n\n    numLayer = numP * 3;\n\n    // define the temperature array\n    if (!(T = doubleMalloc(dimX * dimZ * (numLayer + 1))))\n        SUPERLU_ABORT(\"Malloc fails for K[].\");\n    for (l = 0; l < dimX * dimZ * (numLayer + 1); l++) T[l] = Tamb;\n\n    return T;\n}\n\ndouble *calculate_Cap_array(double W, double Lc, int numP, int dimX, int dimZ,\n                            int *CapSize) {\n    double Wsink, Lsink, Hsink;\n    int numLayer;\n    double *C, *H, Csink;\n\n    // initialize the parameters\n    numLayer = numP * 3;\n    Wsink = W;\n    Lsink = Lc;\n    Hsink = Hhs;\n    Csink = Chs;\n\n    // define the thermal capacitance and height array\n    if (!(C = doubleMalloc(numLayer + 1)))\n        SUPERLU_ABORT(\"Malloc fails for K[].\");\n    if (!(H = doubleMalloc(numLayer))) SUPERLU_ABORT(\"Malloc fails for H[].\");\n    for (int i = 0; i < numLayer; i++) {\n        switch (i % 3) {\n            case 0:\n                C[i + 1] = Csi;\n                H[i] = Hsi;\n                break;\n            case 1:\n                C[i + 1] = Ccu;\n                H[i] = Hcu;\n                break;\n            case 2:\n                C[i + 1] = Cin;\n                H[i] = Hin;\n                break;\n            default:\n                printf(\"Error!\");\n        }\n    }\n    C[0] = Csink;\n\n    ///////////// modify the cap vector with the physical parameters\n    ///////////////\n    double gridX, gridZ, gridXsink, gridZsink;\n    gridX = W / dimX;\n    gridZ = Lc / dimZ;\n    gridXsink = Wsink / dimX;\n    gridZsink = Lsink / dimZ;\n    for (int i = 0; i < numLayer + 1; i++) {\n        if (i == 0)\n            C[i] = C[i] * Hsink * gridXsink * gridZsink;\n        else\n            C[i] = C[i] * H[i - 1] * gridX * gridZ;\n    }\n\n    *CapSize = numLayer + 1;\n    return C;\n}\n\ndouble **calculate_Midx_array(double W, double Lc, int numP, int dimX, int dimZ,\n                              int *MidxSize, double Tamb) {\n    double Wsink, Lsink, Hsink, Ksink, rTSV, Ktsv;\n    int numLayer;\n    double *K, *H;\n    int_t *layerP, *mapTSV;\n    int ***TSV;      // number of TSVs in each grid\n    int i, j, k, l;  // iterators\n\n    // initialize the parameters\n    numLayer = numP * 3;\n    Wsink = W;\n    Lsink = Lc;\n    Hsink = Hhs;\n    Ksink = Khs;\n\n    rTSV = R_TSV;\n    Ktsv = Kcu;\n\n    // define the thermal conductance and height array\n    if (!(K = doubleMalloc(numLayer))) SUPERLU_ABORT(\"Malloc fails for K[].\");\n    if (!(H = doubleMalloc(numLayer))) SUPERLU_ABORT(\"Malloc fails for H[].\");\n    for (i = 0; i < numLayer; i++) {\n        switch (i % 3) {\n            case 0:\n                K[i] = Ksi;\n                H[i] = Hsi;\n                break;\n            case 1:\n                K[i] = Kcu;\n                H[i] = Hcu;\n                break;\n            case 2:\n                K[i] = Kin;\n                H[i] = Hin;\n                break;\n            default:\n                printf(\"Error!\");\n        }\n    }\n\n    // define the active layer array\n    if (!(layerP = intMalloc(numP))) SUPERLU_ABORT(\"Malloc fails for numP[].\");\n    for (l = 0; l < numP; l++) layerP[l] = l * 3;\n\n    // define the mapTSV array\n    if (!(mapTSV = intMalloc(numLayer)))\n        SUPERLU_ABORT(\"Malloc fails for mapTSV[].\");\n\n    for (i = 0; i < numLayer; i++) {\n        if (i == 0 || i == numLayer - 1)\n            mapTSV[i] = 0;\n        else\n            mapTSV[i] = ((i - 1) / 3) + 1;\n    }\n    mapTSV[numLayer - 2] = numP - 1;\n\n    printf(\"================= STEADY TEMPERATURE SOLVER ===============\\n\\n\");\n    printf(\"Dimension of the Chip: %d x %d x %d (dimX x dimZ x numP)\\n\", dimX,\n           dimZ, numP);\n    printf(\n        \"Total Number of layers: %d (each tier contains an active layer, a \"\n        \"wire layer and a \"\n        \"dielectric layer\\n\",\n        numLayer);\n    printf(\"NOTE: ANOTHER HEAT SINK LAYER IS ATTACHED TO THE 1st LAYER\\n\");\n    printf(\"Active layer(s) is(are) on the following layer(s): \");\n    for (l = 0; l < numP; l++) printf(\"%lld, \", layerP[l]);\n    printf(\"\\n\");\n    printf(\"Distribution of TSVs arcoss layers: \");\n    for (i = 0; i < numLayer; i++) printf(\"%lld, \", mapTSV[i]);\n    printf(\"\\n\");\n    printf(\"The ambient temperature is %.2f C\\n\", Tamb - T0);\n    printf(\"------------------------------------------------------------\\n\\n\");\n\n    // define the TSV array (3D-int array!)\n    if (!(TSV = (int ***)malloc(dimX * sizeof(int **))))\n        printf(\"Malloc fails for TSV[].\\n\");\n    for (i = 0; i < dimX; i++) {\n        if (!(TSV[i] = (int **)malloc(dimZ * sizeof(int *))))\n            printf(\"Malloc fails for TSV[%d][].\\n\", i);\n        for (j = 0; j < dimZ; j++) {\n            if (!(TSV[i][j] = (int *)malloc((numP - 1) * sizeof(int))))\n                printf(\"Malloc fails for TSV[%d][%d][]. \\n\", i, j);\n        }\n    }\n    // initialize TSV array\n    for (i = 0; i < dimX; i++)\n        for (j = 0; j < dimZ; j++)\n            for (k = 0; k < numP - 1; k++) TSV[i][j][k] = 0;\n\n    // generate the G matrix following\n    double gridX, gridZ, gridXsink, gridZsink;\n    double Rsinkx, Rsinky, Rsinkz, Ramb;\n    double ***Rvert;  // vertical resistance\n    double **Rhori;   // horizontal resistance\n    int tier;\n\n    gridX = W / dimX;\n    gridZ = Lc / dimZ;\n    gridXsink = Wsink / dimX;\n    gridZsink = Lsink / dimZ;\n\n    Rsinkx = gridXsink / Ksink / gridZsink / Hsink;  // x direction\n    Rsinky = Hsink / Ksink / gridXsink / gridZsink;  // y direction\n    Rsinkz = gridZsink / Ksink / gridXsink / Hsink;  // z direction\n    Ramb = Rsinky / 2;\n\n    // alloc Rvert mat\n    if (!(Rvert = (double ***)malloc(dimX * sizeof(double **))))\n        printf(\"Malloc fails for Rvert[].\\n\");\n    for (i = 0; i < dimX; i++) {\n        if (!(Rvert[i] = (double **)malloc(dimZ * sizeof(double *))))\n            printf(\"Malloc fails for Rvert[%d][].\\n\", i);\n        for (j = 0; j < dimZ; j++) {\n            if (!(Rvert[i][j] =\n                      (double *)malloc((numLayer + 1) * sizeof(double))))\n                printf(\"Malloc fails for Rvert[%d][%d][]. \\n\", i, j);\n        }\n    }\n    // initialize Rvert mat\n    for (l = 0; l < numLayer; l++)  // one layer less than Rvert\n    {\n        tier = mapTSV[l];\n        for (i = 0; i < dimX; i++) {\n            for (j = 0; j < dimZ; j++) {\n                if (l == 0) Rvert[i][j][l] = Rsinky;\n\n                if (tier)\n                    Rvert[i][j][l + 1] =\n                        1 / (1 / (H[l] / K[l] /\n                                  (gridX * gridZ -\n                                   M_PI * rTSV * rTSV * TSV[i][j][tier - 1])) +\n                             1 / (H[l] / Ktsv /\n                                  (M_PI * rTSV * rTSV * TSV[i][j][tier - 1])));\n                else\n                    Rvert[i][j][l + 1] = H[l] / K[l] / (gridX * gridZ);\n            }\n        }\n    }\n\n    // alloc Rhori mat\n    if (!(Rhori = (double **)malloc((numLayer + 1) * sizeof(double *))))\n        printf(\"Malloc fails for Rhori[].\\n\");\n    for (i = 0; i < numLayer + 1; i++) {\n        if (!(Rhori[i] = (double *)malloc(2 * sizeof(double))))\n            printf(\"Malloc fails for Rvert[%d][].\\n\", i);\n    }\n    // initialize Rhori mat\n    for (i = 0; i < numLayer + 1; i++) {\n        if (i == 0) {\n            Rhori[i][0] = Rsinkx;\n            Rhori[i][1] = Rsinkz;\n        } else {\n            Rhori[i][0] = gridX / K[i - 1] / gridZ / H[i - 1] * 10;\n            Rhori[i][1] = gridZ / K[i - 1] / gridZ / H[i - 1] * 10;\n        }\n    }\n\n    /* free the space of mapTSV and TSV */\n    free(mapTSV);\n    for (i = 0; i < dimX; i++) {\n        for (j = 0; j < dimZ; j++) {\n            free(TSV[i][j]);\n        }\n        free(TSV[i]);\n    }\n    free(TSV);\n\n    /* now I calculate the number of non-zero entries and build Mid\n     */\n    int count = 0;  // count the number of non-zeros\n    for (l = 0; l < numLayer + 1; l++) {\n        for (i = 0; i < dimX; i++) {\n            for (j = 0; j < dimZ; j++) {\n                if (i - 1 >= 0) count++;\n                if (i + 1 < dimX) count++;\n                if (j - 1 >= 0) count++;\n                if (j + 1 < dimZ) count++;\n                if (l < numLayer) count++;\n                if (l > 0) count++;\n            }\n        }\n    }\n\n    // printf(\"count = %d\\n\", count);\n    // printf(\"Dimention is %d x %d\\n\", dimX*dimZ*(numLayer+1),\n    // dimX*dimZ*(numLayer+1));\n\n    count = count + dimX * dimZ * (numLayer + 1);\n    // * since the previous calculation does not count the diagonal values\n    // * here we update number of non-zero values by adding the number\n    // * of the diagnal values\n\n    double **Midx;\n    // allocate space for Midx\n    if (!(Midx = (double **)malloc((count) * sizeof(double *))))\n        printf(\"Malloc fails for Midx[].\\n\");\n    for (i = 0; i < count; i++)\n        if (!(Midx[i] = (double *)malloc((3) * sizeof(double))))\n            printf(\"Malloc fails for Midx[%d][].\\n\", i);\n\n    // try to initialize Midx\n    for (i = 0; i < count; i++)\n        for (j = 0; j < 3; j++) Midx[i][j] = 0;\n\n    // fill in the off-diagnal values\n    int idx = 0,\n        idx_re;  // idx_re records the idx of the first item of each row\n    double row_t, col_t, val_t;  // for swap values\n    for (l = 0; l < numLayer + 1; l++) {\n        for (j = 0; j < dimZ; j++) {\n            for (i = 0; i < dimX; i++) {\n                idx_re = idx;\n                if (l > 0) {\n                    Midx[idx][0] = l * dimX * dimZ + j * dimX + i;\n                    Midx[idx][1] = (l - 1) * dimX * dimZ + j * dimX + i;\n                    Midx[idx][2] =\n                        -1 / (Rvert[i][j][l] / 2 + Rvert[i][j][l - 1] / 2);\n                    // printf(\"%d:%f\\t%f\\t%.5f\\n\", idx, Midx[idx][0],\n                    // Midx[idx][1], Midx[idx][2]);\n                    idx++;\n                }\n                if (j - 1 >= 0) {\n                    Midx[idx][0] = l * dimX * dimZ + j * dimX + i;\n                    Midx[idx][1] = l * dimX * dimZ + (j - 1) * dimX + i;\n                    Midx[idx][2] = -1 / Rhori[l][1];\n                    // printf(\"%d:%f\\t%f\\t%.5f\\n\", idx, Midx[idx][0],\n                    // Midx[idx][1], Midx[idx][2]);\n                    idx++;\n                }\n                if (i - 1 >= 0) {\n                    Midx[idx][0] = l * dimX * dimZ + j * dimX + i;\n                    Midx[idx][1] = l * dimX * dimZ + j * dimX + i - 1;\n                    Midx[idx][2] = -1 / Rhori[l][0];\n                    // printf(\"%d:%f\\t%f\\t%.5f\\n\", idx, Midx[idx][0],\n                    // Midx[idx][1], Midx[idx][2]);\n                    idx++;\n                }\n                if (i + 1 < dimX) {\n                    Midx[idx][0] = l * dimX * dimZ + j * dimX + i;\n                    Midx[idx][1] = l * dimX * dimZ + j * dimX + i + 1;\n                    Midx[idx][2] = -1 / Rhori[l][0];\n                    // printf(\"%d:%f\\t%f\\t%.5f\\n\", idx, Midx[idx][0],\n                    // Midx[idx][1], Midx[idx][2]);\n                    idx++;\n                }\n\n                if (j + 1 < dimZ) {\n                    Midx[idx][0] = l * dimX * dimZ + j * dimX + i;\n                    Midx[idx][1] = l * dimX * dimZ + (j + 1) * dimX + i;\n                    Midx[idx][2] = -1 / Rhori[l][1];\n                    // printf(\"%d:%f\\t%f\\t%.5f\\n\", idx, Midx[idx][0],\n                    // Midx[idx][1], Midx[idx][2]);\n                    idx++;\n                }\n                if (l < numLayer) {\n                    Midx[idx][0] = l * dimX * dimZ + j * dimX + i;\n                    Midx[idx][1] = (l + 1) * dimX * dimZ + j * dimX + i;\n                    Midx[idx][2] =\n                        -1 / (Rvert[i][j][l] / 2 + Rvert[i][j][l + 1] / 2);\n                    // printf(\"%d:%f\\t%f\\t%.5f\\n\", idx, Midx[idx][0],\n                    // Midx[idx][1], Midx[idx][2]);\n                    idx++;\n                }\n\n                // calculate the diagnal values\n                // printf(\"idx_re = %d; idx = %d\\n\", idx_re, idx);\n                Midx[idx][0] = l * dimX * dimZ + j * dimX + i;\n                Midx[idx][1] = l * dimX * dimZ + j * dimX + i;\n\n                // printf(\"ATENTION: idx_re = %d, idx = %d\\n\", idx_re, idx);\n                for (k = idx_re; k < idx; k++) {\n                    // if (Midx[idx][0] == 5)\n                    // printf(\"Midx[idx][2] = %.6f\\n\", Midx[idx][2]);\n                    Midx[idx][2] -= Midx[k][2];\n                }\n                if (Midx[idx][0] < dimX * dimZ) {  // heat sink nodes\n                    // if (Midx[idx][0] == 5)\n                    // printf(\"Midx[idx][2] = %.6f\\n\", Midx[idx][2]);\n                    Midx[idx][2] += 1 / Ramb;\n                }\n                // printf(\"%d:%f\\t%f\\t%.5f\\t, %d\\t%d\\n\", idx, Midx[idx][0],\n                // Midx[idx][1], Midx[idx][2], idx_re, idx);\n                idx++;\n                // sort this row\n                for (k = idx - 2; k >= idx_re; k--) {\n                    if (Midx[k][1] > Midx[k + 1][1]) {\n                        row_t = Midx[k][0];\n                        col_t = Midx[k][1];\n                        val_t = Midx[k][2];\n                        Midx[k][0] = Midx[k + 1][0];\n                        Midx[k][1] = Midx[k + 1][1];\n                        Midx[k][2] = Midx[k + 1][2];\n                        Midx[k + 1][0] = row_t;\n                        Midx[k + 1][1] = col_t;\n                        Midx[k + 1][2] = val_t;\n                    } else\n                        break;\n                }\n\n                if (idx > count) printf(\"Error: exceed the Midx dimension!\\n\");\n            }\n        }\n    }\n\n    /*  int iidx;\n      for (iidx = 0; iidx < count; iidx ++)\n        printf(\"%f\\t%f\\t%.5f\\n\", Midx[iidx][0], Midx[iidx][1], Midx[iidx][2]);\n    */\n\n    // printf(\"size of Midx is %d\\n\", sizeof Midx /sizeof Midx[0]);\n\n    /* free the space of Rvert and Rhori */\n    for (i = 0; i < dimX; i++) {\n        for (j = 0; j < dimZ; j++) {\n            free(Rvert[i][j]);\n        }\n        free(Rvert[i]);\n    }\n    free(Rvert);\n\n    for (i = 0; i < numLayer + 1; i++) {\n        free(Rhori[i]);\n    }\n    free(Rhori);\n    SUPERLU_FREE(K);\n    SUPERLU_FREE(H);\n    SUPERLU_FREE(layerP);\n\n    *MidxSize = count;\n    return Midx;\n}\n\ndouble *steady_thermal_solver(double ***powerM, double W, double Lc, int numP,\n                              int dimX, int dimZ, double **Midx, int count,\n                              double Tamb) {\n    int numLayer = numP * 3;\n    int_t *layerP;\n    // define the active layer array\n    if (!(layerP = intMalloc(numP))) SUPERLU_ABORT(\"Malloc fails for numP[].\");\n    for (int l = 0; l < numP; l++) layerP[l] = l * 3;\n\n    double Wsink = W;\n    double Lsink = Lc;\n    double Hsink = Hhs;\n    double Ksink = Khs;\n    double gridXsink = Wsink / dimX;\n    double gridZsink = Lsink / dimZ;\n    double Rsinky = Hsink / Ksink / gridXsink / gridZsink;  // y direction\n    double Ramb = Rsinky / 2;\n\n    // convert the values to the SuperMatrix format\n    SuperMatrix A, L, U, B;\n    double *a;\n    int_t *asub, *xa;\n    int_t *perm_r; /* row permutations from partial pivoting */\n    int_t *perm_c; /* column permutation vector */\n    SCPformat *Lstore;\n    NCPformat *Ustore;\n    int_t nrhs, info, m, n, nnz, b;\n    int_t nprocs; /* maximum number of processors to use. */\n    int_t panel_size, relax, maxsup;\n    int_t permc_spec;\n    trans_t trans;\n    double *rhs;\n    superlu_memusage_t superlu_memusage;\n\n    nrhs = 1;\n    trans = NOTRANS;\n    nprocs = omp_get_max_threads();\n    b = 1;\n    panel_size = sp_ienv(1);\n    relax = sp_ienv(2);\n    maxsup = sp_ienv(3);\n\n    /* Initialize matrix A. */\n    m = n = dimX * dimZ * (numLayer + 1);\n    nnz = count;\n    if (!(a = doubleMalloc(nnz)))\n        SUPERLU_ABORT(\"Malloc fails for a[].\");  // I cannot free the space\n    if (!(asub = intMalloc(nnz)))\n        SUPERLU_ABORT(\"Malloc fails for asub[].\");  // I cannot free the space\n    if (!(xa = intMalloc(n + 1)))\n        SUPERLU_ABORT(\"Malloc fails for xa[].\");  // I cannot free the space\n\n    /* assign values to the arrays: a, asub and xa */\n    int row = -1;\n    for (int i = 0; i < count; i++) {\n        if (Midx[i][0] > row) {\n            row = Midx[i][0];  // enter a new column\n            xa[row] = i;       // index of the first item of each row\n        }\n        a[i] = Midx[i][2];\n        asub[i] = (int)Midx[i][1];  // column index of each item\n    }\n    xa[row + 1] = count;\n\n    printf(\"Using %lld Cores to calculate\\n\", nprocs);\n    printf(\"Building the sparse matrix ...\\n\");\n    printf(\"Dimension of the G matrix is %lld x %lld\\n\", m, n);\n    printf(\"Number of non-zero entries is %lld\\n\", nnz);\n\n    /* Create matrix A in the format expected by SuperLU. */\n    dCreate_CompCol_Matrix(&A, m, n, nnz, a, asub, xa, SLU_NC, SLU_D, SLU_GE);\n    // dPrint_CompCol_Matrix(\"A\", &A);\n    /* Create right-hand side matrix B. */\n    if (!(rhs = doubleMalloc(m * nrhs)))\n        SUPERLU_ABORT(\"Malloc fails for rhs[].\");\n\n    // assign values to B\n    for (int i = 0; i < m; i++)  // initialize rhs to 0\n        rhs[i] = 0;\n    for (int i = 0; i < dimX * dimZ; i++) rhs[i] = Tamb / Ramb;\n    for (int l = 0; l < numP; l++)\n        for (int i = 0; i < dimX; i++)\n            for (int j = 0; j < dimZ; j++) {\n                rhs[dimX * dimZ * (layerP[l] + 1) + j * dimX + i] =\n                    powerM[i][j][l];\n                // rhs[dimX*dimZ*(layerP[l]+1) + i*dimZ + j] = powerM[i][j][l];\n                // printf(\"%.6f\\n\", powerM[i][j][l]);\n            }\n\n    // free the space\n    for (int i = 0; i < dimX; i++) {\n        for (int j = 0; j < dimZ; j++) {\n            free(powerM[i][j]);\n        }\n        free(powerM[i]);\n    }\n    free(powerM);\n\n    dCreate_Dense_Matrix(&B, m, nrhs, rhs, m, SLU_DN, SLU_D, SLU_GE);\n\n    // dPrint_Dense_Matrix(\"B\", &B);\n\n    if (!(perm_r = intMalloc(m))) SUPERLU_ABORT(\"Malloc fails for perm_r[].\");\n    if (!(perm_c = intMalloc(n))) SUPERLU_ABORT(\"Malloc fails for perm_c[].\");\n\n    /*\n     * Get column permutation vector perm_c[], according to permc_spec:\n     *   permc_spec = 0: natural ordering\n     *   permc_spec = 1: minimum degree ordering on structure of A'*A\n     *   permc_spec = 2: minimum degree ordering on structure of A'+A\n     *   permc_spec = 3: approximate minimum degree for unsymmetric matrices\n     */\n    permc_spec = 1;\n    get_perm_c(permc_spec, &A, perm_c);\n\n    printf(\"Finish building the sparse matrix\\n\");\n    printf(\"------------------------------------------------------------\\n\\n\");\n\n    /* Solve the linear system. */\n    pdgssv(nprocs, &A, perm_c, perm_r, &L, &U, &B, &info);\n\n    printf(\"Finish solving the linear equation\\n\");\n\n    // dPrint_Dense_Matrix(\"B\", &B);\n\n    // extract the Temperature from B\n    DNformat *Astore = (DNformat *)B.Store;\n    // double *Tt; // vector stores the temperature for all grids\n\n    double *Ttp, *Tt;\n    if (!(Tt = (double *)malloc(dimX * dimZ * (numP * 3 + 1) * sizeof(double))))\n        printf(\"Malloc fails for Tt\\n\");\n    Ttp = (double *)Astore->nzval;\n    printf(\"B.nrow is %lld\\n\", B.nrow);\n    for (int i = 0; i < B.nrow; ++i) {\n        Tt[i] = Ttp[i] - T0;\n        // printf(\"Tt[%d] = %.2f\\n\", i, Tt[i]);\n    }\n\n    /*Tt = (double *) Astore->nzval;\n    printf(\"B.nrow is %d\\n\", B.nrow);\n    for (i = 0; i < B.nrow; ++i)\n    {\n        Tt[i] = Tt[i] - T0;\n        //printf(\"%.2f\\n\", T[i]);\n    }*/\n\n    printf(\"Finish converting the temperature matrix\\n\");\n    printf(\"Free the space...\\n\");\n\n    if (info == 0) {\n        // dinf_norm_error(nrhs, &B, xact); /* Inf. norm of the error */\n\n        Lstore = (SCPformat *)L.Store;\n        Ustore = (NCPformat *)U.Store;\n        printf(\"#NZ in factor L = \" IFMT \"\\n\", Lstore->nnz);\n        printf(\"#NZ in factor U = \" IFMT \"\\n\", Ustore->nnz);\n        printf(\"#NZ in L+U = \" IFMT \"\\n\", Lstore->nnz + Ustore->nnz - L.ncol);\n\n        superlu_dQuerySpace(nprocs, &L, &U, panel_size, &superlu_memusage);\n        printf(\"L\\\\U MB %.3f\\ttotal MB needed %.3f\\texpansions \" IFMT \"\\n\",\n               superlu_memusage.for_lu / 1024 / 1024,\n               superlu_memusage.total_needed / 1024 / 1024,\n               superlu_memusage.expansions);\n    }\n\n    /* De-allocate storage */\n    // free the arrays defined by myself\n    SUPERLU_FREE(layerP);\n    SUPERLU_FREE(rhs);\n    SUPERLU_FREE(perm_r);\n    SUPERLU_FREE(perm_c);\n    printf(\"finish SUPERLU_FREE\\n\");\n    Destroy_CompCol_Matrix(&A);\n    Destroy_SuperMatrix_Store(&B);\n    Destroy_SuperNode_SCP(&L);\n    Destroy_CompCol_NCP(&U);\n    /* De-allocate other storage */\n    // free(K); free(H); free(layerP); free(Tt);\n\n    printf(\n        \"================= FINISH STEADY TEMPERATURE SOLVER \"\n        \"===============\\n\\n\");\n\n    return Tt;\n}\n\ndouble *transient_thermal_solver(double ***powerM, double W, double Lc,\n                                 int numP, int dimX, int dimZ, double **Midx,\n                                 int MidxSize, double *Cap, int CapSize,\n                                 double time, int iter, double *T_trans,\n                                 double Tamb) {\n    int numLayer = numP * 3;\n\n    // define the active layer array\n    int_t *layerP;\n    if (!(layerP = intMalloc(numP))) SUPERLU_ABORT(\"Malloc fails for numP[].\");\n    for (int l = 0; l < numP; l++) layerP[l] = l * 3;\n\n    double Wsink = W;\n    double Lsink = Lc;\n    double Hsink = Hhs;\n    double Ksink = Khs;\n    double gridXsink = Wsink / dimX;\n    double gridZsink = Lsink / dimZ;\n    double Rsinky = Hsink / Ksink / gridXsink / gridZsink;  // y direction\n    double Ramb = Rsinky / 2;\n\n    double *Tp = T_trans;\n    double *T, *P;\n    int T_size = dimX * dimZ * (numLayer + 1);\n    if (!(T = doubleMalloc(T_size))) SUPERLU_ABORT(\"Malloc fails for rhs[].\");\n    if (!(P = doubleMalloc(T_size))) SUPERLU_ABORT(\"Malloc fails for rhs[].\");\n\n    // initialize T and P\n    memset(T, 0, T_size * sizeof(*T));\n    memset(P, 0, T_size * sizeof(*T));\n\n    for (int i = 0; i < dimX * dimZ; i++) P[i] = Tamb / Ramb;\n    for (int l = 0; l < numP; l++)\n        for (int j = 0; j < dimZ; j++)\n            for (int i = 0; i < dimX; i++) {\n                P[dimX * dimZ * (layerP[l] + 1) + i * dimZ + j] =\n                    powerM[i][j][l];\n                // printf(\"%.6f\\n\", powerM[i][j][l]);\n            }\n\n    double dt = time / (double)iter;\n\n    ////////////// iteratively update the temperature /////////////////\n\n    // tried to optimize the following code\n    // multi-threading won't work unless you figure out T[idx0] access patterns\n    // also tried a variety of loop tiling technique, on our server block_size=8\n    // or 4 yields best performance, so let it be...\n    const int block_size = 8;\n    for (int iit = 0; iit < iter; iit++) {\n        // main calculation of the new T\n        for (int j = 0; j < MidxSize; j += block_size) {\n            int bound = j + block_size < MidxSize ? (j + block_size) : MidxSize;\n            for (int b = j; b < bound; b++) {\n                int idx0 = (int)(Midx[b][0] + 0.01);\n                int idx1 = (int)(Midx[b][1] + 0.01);\n                double tmp_c = Midx[b][2];\n                int idxC = idx0 / (dimX * dimZ);\n\n                if (idx0 == idx1) {\n                    // if (1-Midx[j][2]*dt/Cap[idxC] < 0)\n                    //    printf(\"NEGATIVE: idx0 = %d\\n\", idx0);\n                    double tmp_a = 1 - tmp_c * dt / Cap[idxC];\n                    double tmp_b = tmp_a * Tp[idx1] + P[idx0] * dt / Cap[idxC];\n                    T[idx0] += tmp_b;\n                } else {\n                    double tmp_a = tmp_c * Tp[idx1] * dt / Cap[idxC];\n                    T[idx0] -= tmp_a;\n                }\n            }\n        }\n\n        // give value for the next T\n        double *Tt;  // for swap the storage between T and Tp\n        Tt = Tp;\n        Tp = T;\n        T = Tt;  // exchange T, Tp\n        memset(T, 0, dimX * dimZ * (numLayer + 1) * sizeof(*T));\n    }\n\n    // free the space\n    for (int i = 0; i < dimX; i++) {\n        for (int j = 0; j < dimZ; j++) {\n            free(powerM[i][j]);\n        }\n        free(powerM[i]);\n    }\n    free(powerM);\n\n    SUPERLU_FREE(layerP);\n    SUPERLU_FREE(P);\n    SUPERLU_FREE(T);\n\n    return Tp;\n}\n\ndouble get_maxT(double *T, int Tsize) {\n    double maxT = 0.0;\n    int i;\n\n    for (i = 0; i < Tsize; i++) {\n        if (T[i] > maxT) maxT = T[i];\n    }\n\n    return maxT;\n}\n"
  },
  {
    "path": "src/DRAMsim3/src/timing.cc",
    "content": "#include \"timing.h\"\n#include <algorithm>\n#include <utility>\n\nnamespace dramsim3 {\n\nTiming::Timing(const Config& config)\n    : same_bank(static_cast<int>(CommandType::SIZE)),\n      other_banks_same_bankgroup(static_cast<int>(CommandType::SIZE)),\n      other_bankgroups_same_rank(static_cast<int>(CommandType::SIZE)),\n      other_ranks(static_cast<int>(CommandType::SIZE)),\n      same_rank(static_cast<int>(CommandType::SIZE)) {\n    int read_to_read_l = std::max(config.burst_cycle, config.tCCD_L);\n    int read_to_read_s = std::max(config.burst_cycle, config.tCCD_S);\n    int read_to_read_o = config.burst_cycle + config.tRTRS;\n    int read_to_write = config.RL + config.burst_cycle - config.WL +\n                        config.tRTRS;\n    int read_to_write_o = config.read_delay + config.burst_cycle +\n                          config.tRTRS - config.write_delay;\n    int read_to_precharge = config.AL + config.tRTP;\n    int readp_to_act =\n        config.AL + config.burst_cycle + config.tRTP + config.tRP;\n\n    int write_to_read_l = config.write_delay + config.tWTR_L;\n    int write_to_read_s = config.write_delay + config.tWTR_S;\n    int write_to_read_o = config.write_delay + config.burst_cycle +\n                          config.tRTRS - config.read_delay;\n    int write_to_write_l = std::max(config.burst_cycle, config.tCCD_L);\n    int write_to_write_s = std::max(config.burst_cycle, config.tCCD_S);\n    int write_to_write_o = config.burst_cycle;\n    int write_to_precharge = config.WL + config.burst_cycle + config.tWR;\n\n    int precharge_to_activate = config.tRP;\n    int precharge_to_precharge = config.tPPD;\n    int read_to_activate = read_to_precharge + precharge_to_activate;\n    int write_to_activate = write_to_precharge + precharge_to_activate;\n\n    int activate_to_activate = config.tRC;\n    int activate_to_activate_l = config.tRRD_L;\n    int activate_to_activate_s = config.tRRD_S;\n    int activate_to_precharge = config.tRAS;\n    int activate_to_read, activate_to_write;\n    if (config.IsGDDR() || config.IsHBM()) {\n        activate_to_read = config.tRCDRD;\n        activate_to_write = config.tRCDWR;\n    } else {\n        activate_to_read = config.tRCD - config.AL;\n        activate_to_write = config.tRCD - config.AL;\n    }\n    int activate_to_refresh =\n        config.tRC;  // need to precharge before ref, so it's tRC\n\n    // TODO: deal with different refresh rate\n    int refresh_to_refresh =\n        config.tREFI;  // refresh intervals (per rank level)\n    int refresh_to_activate = config.tRFC;  // tRFC is defined as ref to act\n    int refresh_to_activate_bank = config.tRFCb;\n\n    int self_refresh_entry_to_exit = config.tCKESR;\n    int self_refresh_exit = config.tXS;\n    // int powerdown_to_exit = config.tCKE;\n    // int powerdown_exit = config.tXP;\n\n    if (config.bankgroups == 1) {\n        // for a bankgroup can be disabled, in that case\n        // the value of tXXX_S should be used instead of tXXX_L\n        // (because now the device is running at a lower freq)\n        // we overwrite the following values so that we don't have\n        // to change the assignement of the vectors\n        read_to_read_l = std::max(config.burst_cycle, config.tCCD_S);\n        write_to_read_l = config.write_delay + config.tWTR_S;\n        write_to_write_l = std::max(config.burst_cycle, config.tCCD_S);\n        activate_to_activate_l = config.tRRD_S;\n    }\n\n    // command READ\n    same_bank[static_cast<int>(CommandType::READ)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, read_to_read_l},\n            {CommandType::WRITE, read_to_write},\n            {CommandType::READ_PRECHARGE, read_to_read_l},\n            {CommandType::WRITE_PRECHARGE, read_to_write},\n            {CommandType::PRECHARGE, read_to_precharge}};\n    other_banks_same_bankgroup[static_cast<int>(CommandType::READ)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, read_to_read_l},\n            {CommandType::WRITE, read_to_write},\n            {CommandType::READ_PRECHARGE, read_to_read_l},\n            {CommandType::WRITE_PRECHARGE, read_to_write}};\n    other_bankgroups_same_rank[static_cast<int>(CommandType::READ)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, read_to_read_s},\n            {CommandType::WRITE, read_to_write},\n            {CommandType::READ_PRECHARGE, read_to_read_s},\n            {CommandType::WRITE_PRECHARGE, read_to_write}};\n    other_ranks[static_cast<int>(CommandType::READ)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, read_to_read_o},\n            {CommandType::WRITE, read_to_write_o},\n            {CommandType::READ_PRECHARGE, read_to_read_o},\n            {CommandType::WRITE_PRECHARGE, read_to_write_o}};\n\n    // command WRITE\n    same_bank[static_cast<int>(CommandType::WRITE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, write_to_read_l},\n            {CommandType::WRITE, write_to_write_l},\n            {CommandType::READ_PRECHARGE, write_to_read_l},\n            {CommandType::WRITE_PRECHARGE, write_to_write_l},\n            {CommandType::PRECHARGE, write_to_precharge}};\n    other_banks_same_bankgroup[static_cast<int>(CommandType::WRITE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, write_to_read_l},\n            {CommandType::WRITE, write_to_write_l},\n            {CommandType::READ_PRECHARGE, write_to_read_l},\n            {CommandType::WRITE_PRECHARGE, write_to_write_l}};\n    other_bankgroups_same_rank[static_cast<int>(CommandType::WRITE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, write_to_read_s},\n            {CommandType::WRITE, write_to_write_s},\n            {CommandType::READ_PRECHARGE, write_to_read_s},\n            {CommandType::WRITE_PRECHARGE, write_to_write_s}};\n    other_ranks[static_cast<int>(CommandType::WRITE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, write_to_read_o},\n            {CommandType::WRITE, write_to_write_o},\n            {CommandType::READ_PRECHARGE, write_to_read_o},\n            {CommandType::WRITE_PRECHARGE, write_to_write_o}};\n\n    // command READ_PRECHARGE\n    same_bank[static_cast<int>(CommandType::READ_PRECHARGE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::ACTIVATE, readp_to_act},\n            {CommandType::REFRESH, read_to_activate},\n            {CommandType::REFRESH_BANK, read_to_activate},\n            {CommandType::SREF_ENTER, read_to_activate}};\n    other_banks_same_bankgroup[static_cast<int>(CommandType::READ_PRECHARGE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, read_to_read_l},\n            {CommandType::WRITE, read_to_write},\n            {CommandType::READ_PRECHARGE, read_to_read_l},\n            {CommandType::WRITE_PRECHARGE, read_to_write}};\n    other_bankgroups_same_rank[static_cast<int>(CommandType::READ_PRECHARGE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, read_to_read_s},\n            {CommandType::WRITE, read_to_write},\n            {CommandType::READ_PRECHARGE, read_to_read_s},\n            {CommandType::WRITE_PRECHARGE, read_to_write}};\n    other_ranks[static_cast<int>(CommandType::READ_PRECHARGE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, read_to_read_o},\n            {CommandType::WRITE, read_to_write_o},\n            {CommandType::READ_PRECHARGE, read_to_read_o},\n            {CommandType::WRITE_PRECHARGE, read_to_write_o}};\n\n    // command WRITE_PRECHARGE\n    same_bank[static_cast<int>(CommandType::WRITE_PRECHARGE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::ACTIVATE, write_to_activate},\n            {CommandType::REFRESH, write_to_activate},\n            {CommandType::REFRESH_BANK, write_to_activate},\n            {CommandType::SREF_ENTER, write_to_activate}};\n    other_banks_same_bankgroup[static_cast<int>(CommandType::WRITE_PRECHARGE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, write_to_read_l},\n            {CommandType::WRITE, write_to_write_l},\n            {CommandType::READ_PRECHARGE, write_to_read_l},\n            {CommandType::WRITE_PRECHARGE, write_to_write_l}};\n    other_bankgroups_same_rank[static_cast<int>(CommandType::WRITE_PRECHARGE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, write_to_read_s},\n            {CommandType::WRITE, write_to_write_s},\n            {CommandType::READ_PRECHARGE, write_to_read_s},\n            {CommandType::WRITE_PRECHARGE, write_to_write_s}};\n    other_ranks[static_cast<int>(CommandType::WRITE_PRECHARGE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::READ, write_to_read_o},\n            {CommandType::WRITE, write_to_write_o},\n            {CommandType::READ_PRECHARGE, write_to_read_o},\n            {CommandType::WRITE_PRECHARGE, write_to_write_o}};\n\n    // command ACTIVATE\n    same_bank[static_cast<int>(CommandType::ACTIVATE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::ACTIVATE, activate_to_activate},\n            {CommandType::READ, activate_to_read},\n            {CommandType::WRITE, activate_to_write},\n            {CommandType::READ_PRECHARGE, activate_to_read},\n            {CommandType::WRITE_PRECHARGE, activate_to_write},\n            {CommandType::PRECHARGE, activate_to_precharge},\n        };\n\n    other_banks_same_bankgroup[static_cast<int>(CommandType::ACTIVATE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::ACTIVATE, activate_to_activate_l},\n            {CommandType::REFRESH_BANK, activate_to_refresh}};\n\n    other_bankgroups_same_rank[static_cast<int>(CommandType::ACTIVATE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::ACTIVATE, activate_to_activate_s},\n            {CommandType::REFRESH_BANK, activate_to_refresh}};\n\n    // command PRECHARGE\n    same_bank[static_cast<int>(CommandType::PRECHARGE)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::ACTIVATE, precharge_to_activate},\n            {CommandType::REFRESH, precharge_to_activate},\n            {CommandType::REFRESH_BANK, precharge_to_activate},\n            {CommandType::SREF_ENTER, precharge_to_activate}};\n\n    // for those who need tPPD\n    if (config.IsGDDR() || config.protocol == DRAMProtocol::LPDDR4) {\n        other_banks_same_bankgroup[static_cast<int>(CommandType::PRECHARGE)] =\n            std::vector<std::pair<CommandType, int> >{\n                {CommandType::PRECHARGE, precharge_to_precharge},\n            };\n\n        other_bankgroups_same_rank[static_cast<int>(CommandType::PRECHARGE)] =\n            std::vector<std::pair<CommandType, int> >{\n                {CommandType::PRECHARGE, precharge_to_precharge},\n            };\n    }\n\n    // command REFRESH_BANK\n    same_rank[static_cast<int>(CommandType::REFRESH_BANK)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::ACTIVATE, refresh_to_activate_bank},\n            {CommandType::REFRESH, refresh_to_activate_bank},\n            {CommandType::REFRESH_BANK, refresh_to_activate_bank},\n            {CommandType::SREF_ENTER, refresh_to_activate_bank}};\n\n    other_banks_same_bankgroup[static_cast<int>(CommandType::REFRESH_BANK)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::ACTIVATE, refresh_to_activate},\n            {CommandType::REFRESH_BANK, refresh_to_refresh},\n        };\n\n    other_bankgroups_same_rank[static_cast<int>(CommandType::REFRESH_BANK)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::ACTIVATE, refresh_to_activate},\n            {CommandType::REFRESH_BANK, refresh_to_refresh},\n        };\n\n    // REFRESH, SREF_ENTER and SREF_EXIT are isued to the entire\n    // rank  command REFRESH\n    same_rank[static_cast<int>(CommandType::REFRESH)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::ACTIVATE, refresh_to_activate},\n            {CommandType::REFRESH, refresh_to_activate},\n            {CommandType::SREF_ENTER, refresh_to_activate}};\n\n    // command SREF_ENTER\n    // TODO: add power down commands\n    same_rank[static_cast<int>(CommandType::SREF_ENTER)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::SREF_EXIT, self_refresh_entry_to_exit}};\n\n    // command SREF_EXIT\n    same_rank[static_cast<int>(CommandType::SREF_EXIT)] =\n        std::vector<std::pair<CommandType, int> >{\n            {CommandType::ACTIVATE, self_refresh_exit},\n            {CommandType::REFRESH, self_refresh_exit},\n            {CommandType::REFRESH_BANK, self_refresh_exit},\n            {CommandType::SREF_ENTER, self_refresh_exit}};\n}\n\n}  // namespace dramsim3\n"
  },
  {
    "path": "src/DRAMsim3/src/timing.h",
    "content": "#ifndef __TIMING_H\n#define __TIMING_H\n\n#include <vector>\n#include \"common.h\"\n#include \"configuration.h\"\n\nnamespace dramsim3 {\n\nclass Timing {\n   public:\n    Timing(const Config& config);\n    std::vector<std::vector<std::pair<CommandType, int> > > same_bank;\n    std::vector<std::vector<std::pair<CommandType, int> > >\n        other_banks_same_bankgroup;\n    std::vector<std::vector<std::pair<CommandType, int> > >\n        other_bankgroups_same_rank;\n    std::vector<std::vector<std::pair<CommandType, int> > > other_ranks;\n    std::vector<std::vector<std::pair<CommandType, int> > > same_rank;\n};\n\n}  // namespace dramsim3\n#endif\n"
  },
  {
    "path": "src/DRAMsim3/tests/example.trace",
    "content": "0x2000D5C0 READ  30\n0x1FF96FC0 WRITE   160\n0x2000D600 READ  165\n0x1FF97000 READ    192\n0x2000A340 READ    278\n0x1FF97080 READ    305\n0x2004EF40 READ  432\n0x1FF970C0 READ    606\n0x1FF97100 READ    687\n0x1FF97140 READ    767\n0x1FF97180 READ    847\n0x1FF971C0 READ    927\n0x1FF97200 READ    1007\n0x40009F40 WRITE   1088\n0x2001C800 READ  1128\n0x2001C840 READ  1274\n0x2000AB00 READ    1280\n0x40009E00 READ    1281\n0x2001F600 READ  1390\n0x2001F640 READ  1620\n0x2001C9C0 READ  1715\n0x2000AEC0 READ    1717\n0x2001CA00 READ  1794\n0x2001CA80 READ  1923\n0x2000AA80 READ    1924\n0x40009EC0 READ    1925\n0x2001CA40 READ  2007\n0x1FF96F80 READ    2108\n0x2001C040 READ  2237\n0x40008380 WRITE   2239\n0x2000AAC0 READ    2240\n0x2001C080 READ  2314\n0x40000040 WRITE   2447\n0x40000080 WRITE   2447\n0x40008440 READ    2447\n0x400000C0 WRITE   2449\n0x2001FB80 READ  2612\n0x2001FBC0 READ  2721\n0x40003340 READ    2757\n0x2001FC80 READ  2818\n0x2001FCC0 READ  2912\n0x40003380 WRITE   3022\n0x2001FD00 READ  3022\n0x400033C0 WRITE   3028\n0x4000A040 WRITE   3029\n0x2001C880 READ  3103\n0x2001C8C0 READ  3241\n0x2004EF80 READ  3351\n0x2000D640 READ  3433\n0x40000000 READ    3599\n0x20011680 READ  3712\n0x1FF96F40 WRITE   3842\n0x200116C0 READ  3842\n0x20011700 READ  3940\n0x20011740 READ  4051\n0x2001A4C0 READ  4180\n0x1FF97240 READ    4308\n0x2001A540 READ  4308\n0x20000BC0 READ    4339\n0x2001A5C0 READ  4429\n0x2001A600 READ  4574\n0x2001A580 READ  4674\n0x2001A500 READ  4768\n0x20011780 READ  4856\n0x20011AC0 READ  4937\n0x1FF97280 READ    5025\n0x200117C0 READ  5138\n0x20000B80 READ    5230\n0x20011800 READ  5328\n0x1FF972C0 READ    5422\n0x1FF97040 READ    5552\n0x20011840 READ  5578\n0x20000E80 READ    5690\n0x20011880 READ  5776\n0x200118C0 READ  5875\n0x20011900 READ  5953\n0x20011940 READ  6054\n0x20011980 READ  6151\n0x1FF97300 READ    6263\n0x200119C0 READ  6354\n0x20015640 READ  6467\n0x20015680 READ  6624\n0x2000A7C0 READ    6713\n0x200156C0 READ  6720\n0x20015700 READ  6823\n0x40009C40 READ    6872\n0x20015740 READ  7034\n0x20009C40 READ    7062\n0x20009C00 READ    7062\n0x20003F00 READ    7253\n0x20015780 READ  7286\n0x200157C0 READ  7436\n0x20011A00 READ  8585\n0x20011B00 READ  8755\n0x20011B40 READ  8845\n0x20011B80 READ  8932\n0x20010180 READ  9042\n0x1FF96EC0 WRITE   9125\n0x200101C0 READ  9126\n0x1FF96F00 WRITE   9133\n0x20019FC0 READ  9241\n0x20010200 READ  9425\n0x20010280 READ  9507\n0x2000A480 READ    9594\n0x2001A440 READ  9599\n0x200102C0 READ  9762\n0x2000A440 READ    9844\n0x20010300 READ  9847\n0x40009F80 READ    9927\n0x20010340 READ  10134\n0x20016200 READ  10288\n0x20016240 READ  10456\n0x1FF96E80 WRITE   10462\n0x2000A800 READ    10463\n0x400015C0 READ    10668\n0x20015E40 READ  10827\n0x20015E80 READ  10989\n0x20016080 READ  11079\n0x200162C0 READ  11161\n0x2000A880 READ    11243\n0x40009DC0 READ    11244\n0x20016300 READ  11250\n0x20026DC0 READ  11371\n0x1FF96E40 WRITE   11467\n0x20026E00 READ  11523\n0x40008580 READ    11613\n0x2001BD40 READ  11650\n0x20016380 READ  11757\n0x200163C0 READ  11929\n0x40001640 READ    11934\n0x20018400 READ  12054\n0x1FF96E00 WRITE   12145\n0x20018440 READ  12147\n0x20018480 READ  12243\n0x20018500 READ  12333\n0x2001BD80 READ  12443\n0x40008400 READ    12524\n0x20020740 READ  12637\n0x20020780 READ  12758\n0x20018540 READ  12854\n0x40001600 READ    12860\n0x40001680 READ    12860\n0x40009C80 READ    12948\n0x20018580 READ  13028\n0x200185C0 READ  13118\n0x20018C80 READ  13202\n0x20018CC0 READ  13279\n0x2000A900 READ    13283\n0x20018D00 READ  13362\n0x20018D40 READ  13438\n0x1FF96DC0 WRITE   13487\n0x20026D00 READ  13560\n0x20018D80 READ  13657\n0x20018E00 READ  13743\n0x20018E40 READ  13831\n0x20018E80 READ  13908\n0x1FF96D80 WRITE   13995\n0x20018EC0 READ  14004\n0x200202C0 READ  14141\n0x2000B240 READ    14163\n0x20020300 READ  14230\n0x40002140 READ    14297\n0x20020340 READ  14328\n0x200343C0 READ  14480\n0x20026E40 READ  14625\n0x40008480 READ    14709\n0x20020380 READ  14879\n0x20019000 READ  14990\n0x2000A9C0 READ    14992\n0x20019040 READ  15083\n0x20019080 READ  15163\n0x40009E80 READ    15268\n0x200190C0 READ  15278\n0x20018640 READ  15422\n0x40010880 WRITE   15509\n0x20018DC0 READ  15513\n0x20018900 READ  15609\n0x20018940 READ  15751\n0x200189C0 READ  15843\n0x20018A00 READ  15931\n0x20018B40 READ  16017\n0x200192C0 READ  16096\n0x20019300 READ  16180\n0x20018B80 READ  16264\n0x400108C0 WRITE   16269\n0x20002780 READ    16394\n0x20018680 READ  16577\n0x200186C0 READ  16662\n0x20018740 READ  16748\n0x20019100 READ  16833\n0x20018780 READ  16921\n0x200187C0 READ  17027\n0x4005B8C0 WRITE   17110\n0x20019340 READ  17143\n0x200193C0 READ  17429\n0x20019400 READ  17514\n0x20019440 READ  17592\n0x20018800 READ  17681\n0x2000A840 READ    17686\n0x20018840 READ  17777\n0x20018880 READ  17853\n0x20016400 READ  17960\n0x20018C00 READ  18127\n0x20016440 READ  18210\n0x20016480 READ  18299\n0x20010380 READ  18398\n0x20016280 READ  18557\n0x200103C0 READ  18642\n0x20015EC0 READ  18750\n0x20015F00 READ  18837\n0x20002740 READ    18838\n0x40001540 READ    18918\n0x20015F40 READ  18922\n0x20015F80 READ  19012\n0x20015FC0 READ  19107\n0x40001240 READ    19144\n0x400013C0 READ    19198\n0x20016000 READ  19206\n0x20016500 READ  19363\n0x20016540 READ  19451\n0x20002700 READ    19547\n0x200184C0 READ  19726\n0x1FF96D40 WRITE   19946\n0x4005C880 WRITE   20006\n0x20018980 READ  20059\n0x20019280 READ  20186\n0x4005DFC0 WRITE   20429\n0x4005E000 WRITE   20463\n0x20016580 READ  20466\n0x4005BFC0 WRITE   20471\n0x200165C0 READ  20656\n0x200178C0 READ  20791\n0x20017900 READ  20869\n0x20017940 READ  20965\n0x20018700 READ  21131\n0x4005BAC0 READ    21353\n0x20017980 READ  21376\n0x200179C0 READ  21472\n0x4005B900 WRITE   21572\n0x4005B940 WRITE   21599\n0x4005B980 WRITE   21623\n0x4005B9C0 WRITE   21647\n0x4005BA00 WRITE   21671\n0x4005BA40 WRITE   21695\n0x4005BA80 WRITE   21719\n0x20017A00 READ  21764\n0x20017A40 READ  21944\n0x20017A80 READ  22035\n0x20016600 READ  22134\n0x20016680 READ  22220\n0x200166C0 READ  22303\n0x4005C000 WRITE   22389\n0x40001400 READ    22392\n0x20016040 READ  22612\n0x4005D000 WRITE   22699\n0x4005CFC0 WRITE   22708\n0x40001280 READ    22708\n0x20016700 READ  22725\n0x20016740 READ  22833\n0x20010400 READ  23014\n0x2000A400 READ    23018\n0x20010440 READ  23108\n0x40000EC0 READ    23239\n0x400014C0 READ    23239\n0x40001040 READ    23240\n0x40001340 READ    23244\n0x400011C0 READ    23244\n0x400017C0 READ    23245\n0x40001940 READ    23358\n0x4005F7C0 WRITE   23645\n0x4005F800 WRITE   23679\n0x40001380 READ    23731\n0x4005EC00 WRITE   23860\n0x40001200 READ    23861\n0x4005EBC0 WRITE   23862\n0x4005E600 WRITE   23945\n0x40001080 READ    23945\n0x4005E5C0 WRITE   23947\n0x4005E300 WRITE   24045\n0x40000F00 READ    24045\n0x4005E2C0 WRITE   24047\n0x20010480 READ  24153\n0x200104C0 READ  24394\n0x200026C0 READ    24589\n0x4005E900 WRITE   24750\n0x4005E8C0 WRITE   24752\n0x4005F200 WRITE   24881\n0x4005F1C0 WRITE   24883\n0x4005EF00 WRITE   24891\n0x4005EEC0 WRITE   24893\n0x4005F500 WRITE   25018\n0x4005F4C0 WRITE   25021\n0x40060FC0 WRITE   25207\n0x40061000 WRITE   25240\n0x40060400 WRITE   25329\n0x400603C0 WRITE   25331\n0x4005FE00 WRITE   25338\n0x4005FDC0 WRITE   25340\n0x4005FB00 WRITE   25350\n0x4005FAC0 WRITE   25352\n0x4005C040 WRITE   25377\n0x40060100 WRITE   25508\n0x400600C0 WRITE   25511\n0x40060A00 WRITE   25629\n0x400609C0 WRITE   25631\n0x40060700 WRITE   25638\n0x400606C0 WRITE   25640\n0x40060D00 WRITE   25759\n0x40060CC0 WRITE   25762\n0x400627C0 WRITE   25942\n0x40062800 WRITE   25975\n0x40061C00 WRITE   26064\n0x40061BC0 WRITE   26066\n0x40061600 WRITE   26073\n0x400615C0 WRITE   26075\n0x40061300 WRITE   26085\n0x400612C0 WRITE   26087\n0x4005C080 WRITE   26112\n0x40061900 WRITE   26243\n0x400618C0 WRITE   26246\n0x40062200 WRITE   26364\n0x400621C0 WRITE   26366\n0x40061F00 WRITE   26373\n0x40061EC0 WRITE   26375\n0x40062500 WRITE   26494\n0x400624C0 WRITE   26497\n0x40063FC0 WRITE   26677\n0x40064000 WRITE   26710\n0x40063400 WRITE   26799\n0x400633C0 WRITE   26801\n0x40062E00 WRITE   26808\n0x40062DC0 WRITE   26810\n0x40062B00 WRITE   26820\n0x40062AC0 WRITE   26822\n0x4005C0C0 WRITE   26847\n0x40063100 WRITE   26978\n0x400630C0 WRITE   26981\n0x40063A00 WRITE   27099\n0x400639C0 WRITE   27101\n0x40063700 WRITE   27108\n0x400636C0 WRITE   27110\n0x40063D00 WRITE   27229\n0x40063CC0 WRITE   27232\n0x400657C0 WRITE   27412\n0x40065800 WRITE   27445\n0x40064C00 WRITE   27534\n0x40064BC0 WRITE   27536\n0x40064600 WRITE   27543\n0x400645C0 WRITE   27545\n0x40064300 WRITE   27555\n0x400642C0 WRITE   27557\n0x4005C100 WRITE   27582\n0x40064900 WRITE   27713\n0x400648C0 WRITE   27716\n0x40065200 WRITE   27834\n0x400651C0 WRITE   27836\n0x40064F00 WRITE   27843\n0x40064EC0 WRITE   27845\n0x40065500 WRITE   27964\n0x400654C0 WRITE   27967\n0x40066FC0 WRITE   28147\n0x40067000 WRITE   28180\n0x40066400 WRITE   28269\n0x400663C0 WRITE   28271\n0x40065E00 WRITE   28278\n0x40065DC0 WRITE   28280\n0x40065B00 WRITE   28290\n0x40065AC0 WRITE   28292\n0x4005C140 WRITE   28317\n0x40066100 WRITE   28448\n0x400660C0 WRITE   28451\n0x40066A00 WRITE   28569\n0x400669C0 WRITE   28571\n0x40066700 WRITE   28578\n0x400666C0 WRITE   28580\n0x40066D00 WRITE   28699\n0x40066CC0 WRITE   28702\n0x400687C0 WRITE   28882\n0x40068800 WRITE   28915\n0x40067C00 WRITE   29004\n0x40067BC0 WRITE   29006\n0x40067600 WRITE   29013\n0x400675C0 WRITE   29015\n0x40067300 WRITE   29025\n0x400672C0 WRITE   29027\n0x4005C180 WRITE   29052\n0x40067900 WRITE   29183\n0x400678C0 WRITE   29186\n0x40068200 WRITE   29304\n0x400681C0 WRITE   29306\n0x40067F00 WRITE   29313\n0x40067EC0 WRITE   29315\n0x40068500 WRITE   29434\n0x400684C0 WRITE   29437\n0x40069FC0 WRITE   29617\n0x4006A000 WRITE   29650\n0x40069400 WRITE   29739\n0x400693C0 WRITE   29741\n0x40068E00 WRITE   29748\n0x40068DC0 WRITE   29750\n0x40068B00 WRITE   29760\n0x40068AC0 WRITE   29762\n0x4005C1C0 WRITE   29787\n0x40069100 WRITE   29918\n0x400690C0 WRITE   29921\n0x40069A00 WRITE   30039\n0x400699C0 WRITE   30041\n0x40069700 WRITE   30048\n0x400696C0 WRITE   30050\n0x40069D00 WRITE   30169\n0x40069CC0 WRITE   30172\n0x4006A880 WRITE   30494\n0x4006B7C0 WRITE   30634\n0x4006B800 WRITE   30668\n0x4006AC00 WRITE   30762\n0x4006ABC0 WRITE   30764\n0x4006A600 WRITE   30771\n0x4006A5C0 WRITE   30773\n0x4006A300 WRITE   30783\n0x4006A2C0 WRITE   30785\n0x4005C200 WRITE   30810\n0x4006A900 WRITE   30941\n0x4006A8C0 WRITE   30944\n0x4006B200 WRITE   31062\n0x4006B1C0 WRITE   31064\n0x4006AF00 WRITE   31071\n0x4006AEC0 WRITE   31073\n0x4006B500 WRITE   31192\n0x4006B4C0 WRITE   31195\n0x4006CFC0 WRITE   31375\n0x4006D000 WRITE   31408\n0x4006C400 WRITE   31497\n0x4006C3C0 WRITE   31499\n0x4006BE00 WRITE   31506\n0x4006BDC0 WRITE   31508\n0x4006BB00 WRITE   31518\n0x4006BAC0 WRITE   31520\n0x4005C240 WRITE   31545\n0x4006C100 WRITE   31676\n0x4006C0C0 WRITE   31679\n0x4006CA00 WRITE   31797\n0x4006C9C0 WRITE   31799\n0x4006C700 WRITE   31806\n0x4006C6C0 WRITE   31808\n0x4006CD00 WRITE   31927\n0x4006CCC0 WRITE   31930\n0x4006E7C0 WRITE   32110\n0x4006E800 WRITE   32143\n0x4006DC00 WRITE   32232\n0x4006DBC0 WRITE   32234\n0x4006D600 WRITE   32241\n0x4006D5C0 WRITE   32243\n0x4006D300 WRITE   32253\n0x4006D2C0 WRITE   32255\n0x4005C280 WRITE   32280\n0x4006D900 WRITE   32411\n0x4006D8C0 WRITE   32414\n0x4006E200 WRITE   32532\n0x4006E1C0 WRITE   32534\n0x4006DF00 WRITE   32541\n0x4006DEC0 WRITE   32543\n0x4006E500 WRITE   32662\n0x4006E4C0 WRITE   32665\n0x4006FFC0 WRITE   32845\n0x40070000 WRITE   32878\n0x4006F400 WRITE   32967\n0x4006F3C0 WRITE   32969\n0x4006EE00 WRITE   32976\n0x4006EDC0 WRITE   32978\n0x4006EB00 WRITE   32988\n0x4006EAC0 WRITE   32990\n0x4005C2C0 WRITE   33015\n0x4006F100 WRITE   33146\n0x4006F0C0 WRITE   33149\n0x4006FA00 WRITE   33267\n0x4006F9C0 WRITE   33269\n0x4006F700 WRITE   33276\n0x4006F6C0 WRITE   33278\n0x4006FD00 WRITE   33397\n0x4006FCC0 WRITE   33400\n0x400717C0 WRITE   33580\n0x40071800 WRITE   33613\n0x40070C00 WRITE   33702\n0x40070BC0 WRITE   33704\n0x40070600 WRITE   33711\n0x400705C0 WRITE   33713\n0x40070300 WRITE   33723\n0x400702C0 WRITE   33725\n0x4005C300 WRITE   33750\n0x40070900 WRITE   33881\n0x400708C0 WRITE   33884\n0x40071200 WRITE   34002\n0x400711C0 WRITE   34004\n0x40070F00 WRITE   34011\n0x40070EC0 WRITE   34013\n0x40071500 WRITE   34132\n0x400714C0 WRITE   34135\n0x40072FC0 WRITE   34315\n0x40073000 WRITE   34348\n0x40072400 WRITE   34437\n0x400723C0 WRITE   34439\n0x40071E00 WRITE   34446\n0x40071DC0 WRITE   34448\n0x40071B00 WRITE   34458\n0x40071AC0 WRITE   34460\n0x4005C340 WRITE   34485\n0x40072100 WRITE   34616\n0x400720C0 WRITE   34619\n0x40072A00 WRITE   34737\n0x400729C0 WRITE   34739\n0x40072700 WRITE   34746\n0x400726C0 WRITE   34748\n0x40072D00 WRITE   34867\n0x40072CC0 WRITE   34870\n0x400747C0 WRITE   35050\n0x40074800 WRITE   35083\n0x40073C00 WRITE   35172\n0x40073BC0 WRITE   35174\n0x40073600 WRITE   35181\n0x400735C0 WRITE   35183\n0x40073300 WRITE   35193\n0x400732C0 WRITE   35195\n0x4005C380 WRITE   35220\n0x40073900 WRITE   35351\n0x400738C0 WRITE   35354\n0x40074200 WRITE   35472\n0x400741C0 WRITE   35474\n0x40073F00 WRITE   35481\n0x40073EC0 WRITE   35483\n0x40074500 WRITE   35602\n0x400744C0 WRITE   35605\n0x40075FC0 WRITE   35785\n0x40076000 WRITE   35818\n0x40075400 WRITE   35923\n0x400753C0 WRITE   35925\n0x40074E00 WRITE   35932\n0x40074DC0 WRITE   35934\n0x40074B00 WRITE   35944\n0x40074AC0 WRITE   35946\n0x4005C3C0 WRITE   35971\n0x40075100 WRITE   36102\n0x400750C0 WRITE   36105\n0x40075A00 WRITE   36223\n0x400759C0 WRITE   36225\n0x40075700 WRITE   36232\n0x400756C0 WRITE   36234\n0x40075D00 WRITE   36353\n0x40075CC0 WRITE   36356\n0x400777C0 WRITE   36536\n0x40077800 WRITE   36569\n0x40076C00 WRITE   36658\n0x40076BC0 WRITE   36660\n0x40076600 WRITE   36667\n0x400765C0 WRITE   36669\n0x40076300 WRITE   36679\n0x400762C0 WRITE   36681\n0x4005C400 WRITE   36706\n0x40076900 WRITE   36837\n0x400768C0 WRITE   36840\n0x40077200 WRITE   36958\n0x400771C0 WRITE   36960\n0x40076F00 WRITE   36967\n0x40076EC0 WRITE   36969\n0x40077500 WRITE   37088\n0x400774C0 WRITE   37091\n0x40078880 WRITE   37395\n0x40078FC0 READ    37547\n0x40079000 WRITE   37555\n0x40078400 WRITE   37645\n0x400783C0 WRITE   37647\n0x40077E00 WRITE   37654\n0x40077DC0 WRITE   37656\n0x40077B00 WRITE   37666\n0x40077AC0 WRITE   37668\n0x4005C440 WRITE   37693\n0x40078100 WRITE   37824\n0x400780C0 WRITE   37827\n0x40078A00 WRITE   37945\n0x400789C0 WRITE   37947\n0x40078700 WRITE   37954\n0x400786C0 WRITE   37956\n0x40078D00 WRITE   38075\n0x40078CC0 WRITE   38078\n0x4007A7C0 WRITE   38258\n0x4007A800 WRITE   38291\n0x40079C00 WRITE   38380\n0x40079BC0 WRITE   38382\n0x40079600 WRITE   38389\n0x400795C0 WRITE   38391\n0x40079300 WRITE   38401\n0x400792C0 WRITE   38403\n0x4005C480 WRITE   38428\n0x40079900 WRITE   38559\n0x400798C0 WRITE   38562\n0x4007A200 WRITE   38680\n0x4007A1C0 WRITE   38682\n0x40079F00 WRITE   38689\n0x40079EC0 WRITE   38691\n0x4007A500 WRITE   38810\n0x4007A4C0 WRITE   38813\n0x4007BFC0 WRITE   38993\n0x4007C000 WRITE   39026\n0x4007B400 WRITE   39115\n0x4007B3C0 WRITE   39117\n0x4007AE00 WRITE   39124\n0x4007ADC0 WRITE   39126\n0x4007AB00 WRITE   39136\n0x4007AAC0 WRITE   39138\n0x4005C4C0 WRITE   39163\n0x4007B100 WRITE   39294\n0x4007B0C0 WRITE   39297\n0x4007BA00 WRITE   39415\n0x4007B9C0 WRITE   39417\n0x4007B700 WRITE   39424\n0x4007B6C0 WRITE   39426\n0x4007BD00 WRITE   39545\n0x4007BCC0 WRITE   39548\n0x4007D7C0 WRITE   39728\n0x4007D800 WRITE   39761\n0x4007CC00 WRITE   39855\n0x4007CBC0 WRITE   39857\n0x4007C600 WRITE   39864\n0x4007C5C0 WRITE   39866\n0x4007C300 WRITE   39876\n0x4007C2C0 WRITE   39878\n0x4005C500 WRITE   39903\n0x4007C900 WRITE   40034\n0x4007C8C0 WRITE   40037\n0x4007D200 WRITE   40155\n0x4007D1C0 WRITE   40157\n0x4007CF00 WRITE   40164\n0x4007CEC0 WRITE   40166\n0x4007D500 WRITE   40285\n0x4007D4C0 WRITE   40288\n0x4007EFC0 WRITE   40468\n0x4007F000 WRITE   40501\n0x4007E400 WRITE   40590\n0x4007E3C0 WRITE   40592\n0x4007DE00 WRITE   40599\n0x4007DDC0 WRITE   40601\n0x4007DB00 WRITE   40611\n0x4007DAC0 WRITE   40613\n0x4005C540 WRITE   40638\n0x4007E100 WRITE   40769\n0x4007E0C0 WRITE   40772\n0x4007EA00 WRITE   40890\n0x4007E9C0 WRITE   40892\n0x4007E700 WRITE   40899\n0x4007E6C0 WRITE   40901\n0x4007ED00 WRITE   41020\n0x4007ECC0 WRITE   41023\n0x400807C0 WRITE   41203\n0x40080800 WRITE   41236\n0x4007FC00 WRITE   41330\n0x4007FBC0 WRITE   41332\n0x4007F600 WRITE   41339\n0x4007F5C0 WRITE   41341\n0x4007F300 WRITE   41351\n0x4007F2C0 WRITE   41353\n0x4005C580 WRITE   41378\n0x4007F900 WRITE   41509\n0x4007F8C0 WRITE   41512\n0x40080200 WRITE   41630\n0x400801C0 WRITE   41632\n0x4007FF00 WRITE   41639\n0x4007FEC0 WRITE   41641\n0x40080500 WRITE   41760\n0x400804C0 WRITE   41763\n0x40081FC0 WRITE   41943\n0x40082000 WRITE   41976\n0x40081400 WRITE   42076\n0x400813C0 WRITE   42078\n0x40080E00 WRITE   42085\n0x40080DC0 WRITE   42087\n0x40080B00 WRITE   42097\n0x40080AC0 WRITE   42099\n0x4005C5C0 WRITE   42124\n0x40081100 WRITE   42255\n0x400810C0 WRITE   42258\n0x40081A00 WRITE   42376\n0x400819C0 WRITE   42378\n0x40081700 WRITE   42385\n0x400816C0 WRITE   42387\n0x40081D00 WRITE   42506\n0x40081CC0 WRITE   42509\n0x400837C0 WRITE   42689\n0x40083800 WRITE   42722\n0x40082C00 WRITE   42822\n0x40082BC0 WRITE   42824\n0x40082600 WRITE   42831\n0x400825C0 WRITE   42833\n0x40082300 WRITE   42843\n0x400822C0 WRITE   42845\n0x4005C600 WRITE   42870\n0x40082900 WRITE   43001\n0x400828C0 WRITE   43004\n0x40083200 WRITE   43122\n0x400831C0 WRITE   43124\n0x40082F00 WRITE   43131\n0x40082EC0 WRITE   43133\n0x40083500 WRITE   43252\n0x400834C0 WRITE   43255\n0x40084FC0 WRITE   43435\n0x40085000 WRITE   43468\n0x40084400 WRITE   43560\n0x400843C0 WRITE   43562\n0x40083E00 WRITE   43569\n0x40083DC0 WRITE   43571\n0x40083B00 WRITE   43581\n0x40083AC0 WRITE   43583\n0x4005C640 WRITE   43608\n0x40084100 WRITE   43739\n0x400840C0 WRITE   43742\n0x40084A00 WRITE   43860\n0x400849C0 WRITE   43862\n0x40084700 WRITE   43869\n0x400846C0 WRITE   43871\n0x40084D00 WRITE   43990\n0x40084CC0 WRITE   43993\n0x400867C0 WRITE   44173\n0x40086800 WRITE   44212\n0x40085C00 WRITE   44304\n0x40085BC0 WRITE   44306\n0x40085600 WRITE   44313\n0x400855C0 WRITE   44315\n0x40085300 WRITE   44325\n0x400852C0 WRITE   44327\n0x4005C680 WRITE   44352\n0x40085900 WRITE   44483\n0x400858C0 WRITE   44486\n0x40086200 WRITE   44604\n0x400861C0 WRITE   44606\n0x40085F00 WRITE   44613\n0x40085EC0 WRITE   44615\n0x40086500 WRITE   44734\n0x400864C0 WRITE   44737\n0x40086880 WRITE   45041\n0x40087FC0 WRITE   45166\n0x40088000 WRITE   45200\n0x40087400 WRITE   45292\n0x400873C0 WRITE   45294\n0x40086E00 WRITE   45301\n0x40086DC0 WRITE   45303\n0x40086B00 WRITE   45313\n0x40086AC0 WRITE   45315\n0x4005C6C0 WRITE   45340\n0x40087100 WRITE   45471\n0x400870C0 WRITE   45474\n0x40087A00 WRITE   45592\n0x400879C0 WRITE   45594\n0x40087700 WRITE   45601\n0x400876C0 WRITE   45603\n0x40087D00 WRITE   45722\n0x40087CC0 WRITE   45725\n0x400897C0 WRITE   45905\n0x40089800 WRITE   45938\n0x40088C00 WRITE   46030\n0x40088BC0 WRITE   46032\n0x40088600 WRITE   46039\n0x400885C0 WRITE   46041\n0x40088300 WRITE   46051\n0x400882C0 WRITE   46053\n0x4005C700 WRITE   46078\n0x40088900 WRITE   46209\n0x400888C0 WRITE   46212\n0x40089200 WRITE   46330\n0x400891C0 WRITE   46332\n0x40088F00 WRITE   46339\n0x40088EC0 WRITE   46341\n0x40089500 WRITE   46460\n0x400894C0 WRITE   46463\n0x4008AFC0 WRITE   46643\n0x4008B000 WRITE   46676\n0x4008A400 WRITE   46768\n0x4008A3C0 WRITE   46770\n0x40089E00 WRITE   46777\n0x40089DC0 WRITE   46779\n0x40089B00 WRITE   46789\n0x40089AC0 WRITE   46791\n0x4005C740 WRITE   46816\n0x4008A100 WRITE   46947\n0x4008A0C0 WRITE   46950\n0x4008AA00 WRITE   47068\n0x4008A9C0 WRITE   47070\n0x4008A700 WRITE   47077\n0x4008A6C0 WRITE   47079\n0x4008AD00 WRITE   47198\n0x4008ACC0 WRITE   47201\n0x4008C7C0 WRITE   47381\n0x4008C800 WRITE   47414\n0x4008BC00 WRITE   47533\n0x4008BBC0 WRITE   47535\n0x4008B600 WRITE   47542\n0x4008B5C0 WRITE   47544\n0x4008B300 WRITE   47554\n0x4008B2C0 WRITE   47556\n0x4005C780 WRITE   47581\n0x4008B900 WRITE   47712\n0x4008B8C0 WRITE   47715\n0x4008C200 WRITE   47833\n0x4008C1C0 WRITE   47835\n0x4008BF00 WRITE   47842\n0x4008BEC0 WRITE   47844\n0x4008C500 WRITE   47963\n0x4008C4C0 WRITE   47966\n0x4008DFC0 WRITE   48146\n0x4008E000 WRITE   48179\n0x4005BEC0 READ    48275\n0x4005BB00 WRITE   48320\n0x4005BB40 WRITE   48344\n0x4005BB80 WRITE   48368\n0x4005BBC0 WRITE   48392\n0x4005BC00 WRITE   48416\n0x4005BC40 WRITE   48440\n0x4005BC80 WRITE   48464\n0x4005BCC0 WRITE   48488\n0x4005BD00 WRITE   48512\n0x4005BD40 WRITE   48536\n0x4005BD80 WRITE   48560\n0x4005BDC0 WRITE   48584\n0x4005BE00 WRITE   48608\n0x4005BE40 WRITE   48632\n0x4005BE80 WRITE   48656\n0x40001580 READ    49982\n0x20018C40 READ  49983\n0x20019380 READ  50316\n0x4008D400 WRITE   50531\n0x4008D3C0 WRITE   50533\n0x4008CE00 WRITE   50540\n0x4008CDC0 WRITE   50542\n0x4008CB00 WRITE   50552\n0x4008CAC0 WRITE   50554\n0x4005C7C0 WRITE   50579\n0x4008D100 WRITE   50710\n0x4008D0C0 WRITE   50713\n0x4008DA00 WRITE   50831\n0x4008D9C0 WRITE   50833\n0x4008D700 WRITE   50840\n0x4008D6C0 WRITE   50842\n0x4008DD00 WRITE   50961\n0x4008DCC0 WRITE   50964\n0x4008F7C0 WRITE   51144\n0x4008F800 WRITE   51177\n0x4008EC00 WRITE   51305\n0x4008EBC0 WRITE   51307\n0x4008E600 WRITE   51314\n0x4008E5C0 WRITE   51316\n0x4008E300 WRITE   51326\n0x4008E2C0 WRITE   51328\n0x4005C800 WRITE   51353\n0x4008E900 WRITE   51484\n0x4008E8C0 WRITE   51487\n0x4008F200 WRITE   51605\n0x4008F1C0 WRITE   51607\n0x4008EF00 WRITE   51614\n0x4008EEC0 WRITE   51616\n0x4008F500 WRITE   51735\n0x4008F4C0 WRITE   51738\n0x40090FC0 WRITE   51918\n0x40091000 WRITE   51951\n0x40090400 WRITE   52053\n0x400903C0 WRITE   52055\n0x4008FE00 WRITE   52062\n0x4008FDC0 WRITE   52064\n0x4008FB00 WRITE   52074\n0x4008FAC0 WRITE   52076\n0x4005C840 WRITE   52101\n0x40090100 WRITE   52232\n0x400900C0 WRITE   52235\n0x40090A00 WRITE   52353\n0x400909C0 WRITE   52355\n0x40090700 WRITE   52362\n0x400906C0 WRITE   52364\n0x40090D00 WRITE   52483\n0x40090CC0 WRITE   52486\n0x400927C0 WRITE   52666\n0x40092800 WRITE   52699\n0x40091C00 WRITE   52793\n0x40091BC0 WRITE   52795\n0x40091600 WRITE   52802\n0x400915C0 WRITE   52804\n0x40091300 WRITE   52814\n0x400912C0 WRITE   52816\n0x40091900 WRITE   52972\n0x400918C0 WRITE   52975\n0x40092200 WRITE   53093\n0x400921C0 WRITE   53095\n0x40091F00 WRITE   53102\n0x40091EC0 WRITE   53104\n0x40092500 WRITE   53223\n0x400924C0 WRITE   53226\n0x40093FC0 WRITE   53406\n0x40094000 WRITE   53439\n0x40093400 WRITE   53533\n0x400933C0 WRITE   53535\n0x40092E00 WRITE   53542\n0x40092DC0 WRITE   53544\n0x40092B00 WRITE   53554\n0x40092AC0 WRITE   53556\n0x4005C8C0 WRITE   53581\n0x40093100 WRITE   53712\n0x400930C0 WRITE   53715\n0x40093A00 WRITE   53833\n0x400939C0 WRITE   53835\n0x40093700 WRITE   53842\n0x400936C0 WRITE   53844\n0x40093D00 WRITE   53963\n0x40093CC0 WRITE   53966\n0x40094880 WRITE   54270\n0x400957C0 WRITE   54392\n0x40095800 WRITE   54426\n0x40094C00 WRITE   54537\n0x40094BC0 WRITE   54539\n0x40094600 WRITE   54546\n0x400945C0 WRITE   54548\n0x40094300 WRITE   54558\n0x400942C0 WRITE   54560\n0x4005C900 WRITE   54585\n0x40094900 WRITE   54716\n0x400948C0 WRITE   54719\n0x40095200 WRITE   54837\n0x400951C0 WRITE   54839\n0x40094F00 WRITE   54846\n0x40094EC0 WRITE   54848\n0x40095500 WRITE   54967\n0x400954C0 WRITE   54970\n0x40096FC0 WRITE   55150\n0x40097000 WRITE   55183\n0x40096400 WRITE   55277\n0x400963C0 WRITE   55279\n0x40095E00 WRITE   55286\n0x40095DC0 WRITE   55288\n0x40095B00 WRITE   55298\n0x40095AC0 WRITE   55300\n0x4005C940 WRITE   55325\n0x40096100 WRITE   55456\n0x400960C0 WRITE   55459\n0x40096A00 WRITE   55577\n0x400969C0 WRITE   55579\n0x40096700 WRITE   55586\n0x400966C0 WRITE   55588\n0x40096D00 WRITE   55707\n0x40096CC0 WRITE   55710\n0x400987C0 WRITE   55890\n0x40098800 WRITE   55923\n0x40097C00 WRITE   56020\n0x40097BC0 WRITE   56022\n0x40097600 WRITE   56029\n0x400975C0 WRITE   56031\n0x40097300 WRITE   56041\n0x400972C0 WRITE   56043\n0x4005C980 WRITE   56068\n0x40097900 WRITE   56199\n0x400978C0 WRITE   56202\n0x40098200 WRITE   56320\n0x400981C0 WRITE   56322\n0x40097F00 WRITE   56329\n0x40097EC0 WRITE   56331\n0x40098500 WRITE   56450\n0x400984C0 WRITE   56453\n0x40099FC0 WRITE   56633\n0x4009A000 WRITE   56666\n0x40099400 WRITE   56771\n0x400993C0 WRITE   56773\n0x40098E00 WRITE   56780\n0x40098DC0 WRITE   56782\n0x40098B00 WRITE   56792\n0x40098AC0 WRITE   56794\n0x4005C9C0 WRITE   56819\n0x40099100 WRITE   56950\n0x400990C0 WRITE   56953\n0x40099A00 WRITE   57071\n0x400999C0 WRITE   57073\n0x40099700 WRITE   57080\n0x400996C0 WRITE   57082\n0x40099D00 WRITE   57201\n0x40099CC0 WRITE   57204\n0x4009B7C0 WRITE   57384\n0x4009B800 WRITE   57417\n0x4009AC00 WRITE   57522\n0x4009ABC0 WRITE   57524\n0x4009A600 WRITE   57531\n0x4009A5C0 WRITE   57533\n0x4009A300 WRITE   57543\n0x4009A2C0 WRITE   57545\n0x4005CA00 WRITE   57570\n0x4009A900 WRITE   57701\n0x4009A8C0 WRITE   57704\n0x4009B200 WRITE   57822\n0x4009B1C0 WRITE   57824\n0x4009AF00 WRITE   57831\n0x4009AEC0 WRITE   57833\n0x4009B500 WRITE   57952\n0x4009B4C0 WRITE   57955\n0x4009CFC0 WRITE   58135\n0x4009D000 WRITE   58168\n0x4009C400 WRITE   58268\n0x4009C3C0 WRITE   58270\n0x4009BE00 WRITE   58277\n0x4009BDC0 WRITE   58279\n0x4009BB00 WRITE   58289\n0x4009BAC0 WRITE   58291\n0x4005CA40 WRITE   58316\n0x4009C100 WRITE   58447\n0x4009C0C0 WRITE   58450\n0x4009CA00 WRITE   58568\n0x4009C9C0 WRITE   58570\n0x4009C700 WRITE   58577\n0x4009C6C0 WRITE   58579\n0x4009CD00 WRITE   58698\n0x4009CCC0 WRITE   58701\n0x4009E7C0 WRITE   58881\n0x4009E800 WRITE   58914\n0x4009DC00 WRITE   59008\n0x4009DBC0 WRITE   59010\n0x4009D600 WRITE   59017\n0x4009D5C0 WRITE   59019\n0x4009D300 WRITE   59029\n0x4009D2C0 WRITE   59031\n0x4005CA80 WRITE   59056\n0x4009D900 WRITE   59187\n0x4009D8C0 WRITE   59190\n0x4009E200 WRITE   59308\n0x4009E1C0 WRITE   59310\n0x4009DF00 WRITE   59317\n0x4009DEC0 WRITE   59319\n0x4009E500 WRITE   59438\n0x4009E4C0 WRITE   59441\n0x4009FFC0 WRITE   59621\n0x400A0000 WRITE   59654\n0x4009F400 WRITE   59770\n0x4009F3C0 WRITE   59772\n0x4009EE00 WRITE   59779\n0x4009EDC0 WRITE   59781\n0x4009EB00 WRITE   59791\n0x4009EAC0 WRITE   59793\n0x4005CAC0 WRITE   59818\n0x4009F100 WRITE   59949\n0x4009F0C0 WRITE   59952\n0x4009FA00 WRITE   60070\n0x4009F9C0 WRITE   60072\n0x4009F700 WRITE   60079\n0x4009F6C0 WRITE   60081\n0x4009FD00 WRITE   60200\n0x4009FCC0 WRITE   60203\n0x400A17C0 WRITE   60383\n0x400A1800 WRITE   60416\n0x400A0C00 WRITE   60514\n0x400A0BC0 WRITE   60516\n0x400A0600 WRITE   60523\n0x400A05C0 WRITE   60525\n0x400A0300 WRITE   60535\n0x400A02C0 WRITE   60537\n0x4005CB00 WRITE   60562\n0x400A0900 WRITE   60693\n0x400A08C0 WRITE   60696\n0x400A1200 WRITE   60814\n0x400A11C0 WRITE   60816\n0x400A0F00 WRITE   60823\n0x400A0EC0 WRITE   60825\n0x400A1500 WRITE   60944\n0x400A14C0 WRITE   60947\n0x400A2880 WRITE   61251\n0x400A2FC0 READ    61395\n0x400A3000 WRITE   61403\n0x400A2400 WRITE   61514\n0x400A23C0 WRITE   61516\n0x400A1E00 WRITE   61523\n0x400A1DC0 WRITE   61525\n0x400A1B00 WRITE   61535\n0x400A1AC0 WRITE   61537\n0x4005CB40 WRITE   61562\n0x400A2100 WRITE   61693\n0x400A20C0 WRITE   61696\n0x400A2A00 WRITE   61814\n0x400A29C0 WRITE   61816\n0x400A2700 WRITE   61823\n0x400A26C0 WRITE   61825\n0x400A2D00 WRITE   61944\n0x400A2CC0 WRITE   61947\n0x400A47C0 WRITE   62127\n0x400A4800 WRITE   62160\n0x400A3C00 WRITE   62258\n0x400A3BC0 WRITE   62260\n0x400A3600 WRITE   62267\n0x400A35C0 WRITE   62269\n0x400A3300 WRITE   62279\n0x400A32C0 WRITE   62281\n0x4005CB80 WRITE   62306\n0x400A3900 WRITE   62437\n0x400A38C0 WRITE   62440\n0x400A4200 WRITE   62558\n0x400A41C0 WRITE   62560\n0x400A3F00 WRITE   62567\n0x400A3EC0 WRITE   62569\n0x400A4500 WRITE   62688\n0x400A44C0 WRITE   62691\n0x400A5FC0 WRITE   62871\n0x400A6000 WRITE   62904\n0x400A5400 WRITE   63002\n0x400A53C0 WRITE   63004\n0x400A4E00 WRITE   63011\n0x400A4DC0 WRITE   63013\n0x400A4B00 WRITE   63023\n0x400A4AC0 WRITE   63025\n0x4005CBC0 WRITE   63050\n0x400A5100 WRITE   63181\n0x400A50C0 WRITE   63184\n0x400A5A00 WRITE   63302\n0x400A59C0 WRITE   63304\n0x400A5700 WRITE   63311\n0x400A56C0 WRITE   63313\n0x400A5D00 WRITE   63432\n0x400A5CC0 WRITE   63435\n0x400A77C0 WRITE   63615\n0x400A7800 WRITE   63648\n0x400A6C00 WRITE   63739\n0x400A6BC0 WRITE   63741\n0x400A6600 WRITE   63748\n0x400A65C0 WRITE   63750\n0x400A6300 WRITE   63760\n0x400A62C0 WRITE   63762\n0x4005CC00 WRITE   63787\n0x400A6900 WRITE   63918\n0x400A68C0 WRITE   63921\n0x400A7200 WRITE   64039\n0x400A71C0 WRITE   64041\n0x400A6F00 WRITE   64048\n0x400A6EC0 WRITE   64050\n0x400A7500 WRITE   64169\n0x400A74C0 WRITE   64172\n0x400A8FC0 WRITE   64352\n0x400A9000 WRITE   64385\n0x400A8400 WRITE   64476\n0x400A83C0 WRITE   64478\n0x400A7E00 WRITE   64485\n0x400A7DC0 WRITE   64487\n0x400A7B00 WRITE   64497\n0x400A7AC0 WRITE   64499\n0x4005CC40 WRITE   64524\n0x400A8100 WRITE   64655\n0x400A80C0 WRITE   64658\n0x400A8A00 WRITE   64776\n0x400A89C0 WRITE   64778\n0x400A8700 WRITE   64785\n0x400A86C0 WRITE   64787\n0x400A8D00 WRITE   64906\n0x400A8CC0 WRITE   64909\n0x400AA7C0 WRITE   65089\n0x400AA800 WRITE   65122\n0x400A9C00 WRITE   65218\n0x400A9BC0 WRITE   65220\n0x400A9600 WRITE   65227\n0x400A95C0 WRITE   65229\n0x400A9300 WRITE   65239\n0x400A92C0 WRITE   65241\n0x4005CC80 WRITE   65266\n0x400A9900 WRITE   65397\n0x400A98C0 WRITE   65400\n0x400AA200 WRITE   65518\n0x400AA1C0 WRITE   65520\n0x400A9F00 WRITE   65527\n0x400A9EC0 WRITE   65529\n0x400AA500 WRITE   65648\n0x400AA4C0 WRITE   65651\n0x400ABFC0 WRITE   65831\n0x400AC000 WRITE   65864\n0x400AB400 WRITE   65960\n0x400AB3C0 WRITE   65962\n0x400AAE00 WRITE   65969\n0x400AADC0 WRITE   65971\n0x400AAB00 WRITE   65981\n0x400AAAC0 WRITE   65983\n0x4005CCC0 WRITE   66008\n0x400AB100 WRITE   66139\n0x400AB0C0 WRITE   66142\n0x400ABA00 WRITE   66260\n0x400AB9C0 WRITE   66262\n0x400AB700 WRITE   66269\n0x400AB6C0 WRITE   66271\n0x400ABD00 WRITE   66390\n0x400ABCC0 WRITE   66393\n0x400AD7C0 WRITE   66573\n0x400AD800 WRITE   66606\n0x400ACC00 WRITE   66697\n0x400ACBC0 WRITE   66699\n0x400AC600 WRITE   66706\n0x400AC5C0 WRITE   66708\n0x400AC300 WRITE   66718\n0x400AC2C0 WRITE   66720\n0x4005CD00 WRITE   66745\n0x400AC900 WRITE   66876\n0x400AC8C0 WRITE   66879\n0x400AD200 WRITE   66997\n0x400AD1C0 WRITE   66999\n0x400ACF00 WRITE   67006\n0x400ACEC0 WRITE   67008\n0x400AD500 WRITE   67127\n0x400AD4C0 WRITE   67130\n0x400AEFC0 WRITE   67310\n0x400AF000 WRITE   67343\n0x400AE400 WRITE   67445\n0x400AE3C0 WRITE   67447\n0x400ADE00 WRITE   67454\n0x400ADDC0 WRITE   67456\n0x400ADB00 WRITE   67466\n0x400ADAC0 WRITE   67468\n0x4005CD40 WRITE   67493\n0x400AE100 WRITE   67624\n0x400AE0C0 WRITE   67627\n0x400AEA00 WRITE   67745\n0x400AE9C0 WRITE   67747\n0x400AE700 WRITE   67754\n0x400AE6C0 WRITE   67756\n0x400AED00 WRITE   67875\n0x400AECC0 WRITE   67878\n0x400B07C0 WRITE   68058\n0x400B0800 WRITE   68091\n0x400AFC00 WRITE   68182\n0x400AFBC0 WRITE   68184\n0x400AF600 WRITE   68191\n0x400AF5C0 WRITE   68193\n0x400AF300 WRITE   68203\n0x400AF2C0 WRITE   68205\n0x4005CD80 WRITE   68230\n0x400AF900 WRITE   68361\n0x400AF8C0 WRITE   68364\n0x400B0200 WRITE   68482\n0x400B01C0 WRITE   68484\n0x400AFF00 WRITE   68491\n0x400AFEC0 WRITE   68493\n0x400B0500 WRITE   68612\n0x400B04C0 WRITE   68615\n0x400B1FC0 WRITE   68795\n0x400B2000 WRITE   68828\n0x400B1400 WRITE   68942\n0x400B13C0 WRITE   68944\n0x400B0E00 WRITE   68951\n0x400B0DC0 WRITE   68953\n0x400B0B00 WRITE   68963\n0x400B0AC0 WRITE   68965\n0x4005CDC0 WRITE   68990\n0x400B1100 WRITE   69121\n0x400B10C0 WRITE   69124\n0x400B1A00 WRITE   69242\n0x400B19C0 WRITE   69244\n0x400B1700 WRITE   69251\n0x400B16C0 WRITE   69253\n0x400B1D00 WRITE   69372\n0x400B1CC0 WRITE   69375\n0x400B2880 WRITE   69679\n0x400B37C0 WRITE   69801\n0x400B3800 WRITE   69835\n0x400B2C00 WRITE   69926\n0x400B2BC0 WRITE   69928\n0x400B2600 WRITE   69935\n0x400B25C0 WRITE   69937\n0x400B2300 WRITE   69947\n0x400B22C0 WRITE   69949\n0x4005CE00 WRITE   69974\n0x400B2900 WRITE   70105\n0x400B28C0 WRITE   70108\n0x400B3200 WRITE   70226\n0x400B31C0 WRITE   70228\n0x400B2F00 WRITE   70235\n0x400B2EC0 WRITE   70237\n0x400B3500 WRITE   70356\n0x400B34C0 WRITE   70359\n0x400B4FC0 WRITE   70539\n0x400B5000 WRITE   70572\n0x400B4400 WRITE   70686\n0x400B43C0 WRITE   70688\n0x400B3E00 WRITE   70695\n0x400B3DC0 WRITE   70697\n0x400B3B00 WRITE   70707\n0x400B3AC0 WRITE   70709\n0x4005CE40 WRITE   70734\n0x400B4100 WRITE   70865\n0x400B40C0 WRITE   70868\n0x400B4A00 WRITE   70986\n0x400B49C0 WRITE   70988\n0x400B4700 WRITE   70995\n0x400B46C0 WRITE   70997\n0x400B4D00 WRITE   71116\n0x400B4CC0 WRITE   71119\n0x400B67C0 WRITE   71299\n0x400B6800 WRITE   71332\n0x400B5C00 WRITE   71423\n0x400B5BC0 WRITE   71425\n0x400B5600 WRITE   71432\n0x400B55C0 WRITE   71434\n0x400B5300 WRITE   71444\n0x400B52C0 WRITE   71446\n0x4005CE80 WRITE   71471\n0x400B5900 WRITE   71602\n0x400B58C0 WRITE   71605\n0x400B6200 WRITE   71723\n0x400B61C0 WRITE   71725\n0x400B5F00 WRITE   71732\n0x400B5EC0 WRITE   71734\n0x400B6500 WRITE   71853\n0x400B64C0 WRITE   71856\n0x400B7FC0 WRITE   72036\n0x400B8000 WRITE   72069\n0x400B7400 WRITE   72178\n0x400B73C0 WRITE   72180\n0x400B6E00 WRITE   72187\n0x400B6DC0 WRITE   72189\n0x400B6B00 WRITE   72199\n0x400B6AC0 WRITE   72201\n0x4005CEC0 WRITE   72226\n0x400B7100 WRITE   72357\n0x400B70C0 WRITE   72360\n0x400B7A00 WRITE   72478\n0x400B79C0 WRITE   72480\n0x400B7700 WRITE   72487\n0x400B76C0 WRITE   72489\n0x400B7D00 WRITE   72608\n0x400B7CC0 WRITE   72611\n0x20010500 READ  72713\n0x20010540 READ  72897\n0x40010900 READ    73377\n0x4005E040 WRITE   73665\n0x40010940 READ    74052\n0x4005E080 WRITE   74260\n0x40010980 READ    74647\n0x4005E0C0 WRITE   74855\n0x400109C0 READ    75242\n0x4005E100 WRITE   75450\n0x40010A00 READ    75837\n0x4005E140 WRITE   76045\n0x40010A40 READ    76432\n0x4005E180 WRITE   76640\n0x40010A80 READ    77027\n0x4005E1C0 WRITE   77235\n0x40010AC0 READ    77622\n0x4005E200 WRITE   77830\n0x40010B00 READ    78217\n0x4005E240 WRITE   78425\n0x40010B40 READ    78812\n0x40010B80 READ    79421\n0x4005E340 WRITE   79630\n0x40010BC0 READ    80017\n0x4005E380 WRITE   80225\n0x40010C00 READ    80612\n0x4005E3C0 WRITE   80820\n0x40010C40 READ    81207\n0x4005E400 WRITE   81415\n0x40010C80 READ    81802\n0x4005E440 WRITE   82010\n0x40010CC0 READ    82397\n0x4005E480 WRITE   82605\n0x40010D00 READ    82992\n0x4005E4C0 WRITE   83200\n0x40010D40 READ    83587\n0x4005E500 WRITE   83795\n0x40010D80 READ    84182\n0x4005E540 WRITE   84390\n0x40010DC0 READ    84777\n0x40010E00 READ    85383\n0x4005E640 WRITE   85590\n0x40010E40 READ    85977\n0x4005E680 WRITE   86185\n0x40010E80 READ    86572\n0x4005E6C0 WRITE   86780\n0x40010EC0 READ    87167\n0x4005E700 WRITE   87375\n0x40010F00 READ    87762\n0x4005E740 WRITE   87970\n0x40010F40 READ    88357\n0x4005E780 WRITE   88565\n0x40010F80 READ    88952\n0x4005E7C0 WRITE   89160\n0x40010FC0 READ    89547\n0x4005E800 WRITE   89755\n0x40011000 READ    90172\n0x4005E840 WRITE   90380\n0x40011040 READ    90767\n0x40011080 READ    91373\n0x4005E940 WRITE   91580\n0x400110C0 READ    91967\n0x4005E980 WRITE   92175\n0x40011100 READ    92562\n0x4005E9C0 WRITE   92770\n0x40011140 READ    93157\n0x4005EA00 WRITE   93365\n0x40011180 READ    93752\n0x4005EA40 WRITE   93960\n0x400111C0 READ    94347\n0x4005EA80 WRITE   94555\n0x40011200 READ    94942\n0x4005EAC0 WRITE   95150\n0x40011240 READ    95537\n0x4005EB00 WRITE   95745\n0x40011280 READ    96132\n0x4005EB40 WRITE   96340\n0x400112C0 READ    96727\n0x40011300 READ    97333\n0x4005EC40 WRITE   97540\n0x40011340 READ    97927\n0x4005EC80 WRITE   98135\n0x40011380 READ    98522\n0x4005ECC0 WRITE   98730\n0x400113C0 READ    99117\n0x4005ED00 WRITE   99325\n0x40011400 READ    99712\n0x4005ED40 WRITE   99920\n0x40011440 READ    100307\n0x4005ED80 WRITE   100515\n0x40011480 READ    100902\n0x4005EDC0 WRITE   101110\n0x400114C0 READ    101497\n0x4005EE00 WRITE   101705\n0x40011500 READ    102092\n0x4005EE40 WRITE   102300\n0x40011540 READ    102687\n0x40011580 READ    103293\n0x4005EF40 WRITE   103500\n0x400115C0 READ    103887\n0x4005EF80 WRITE   104095\n0x40011600 READ    104482\n0x4005EFC0 WRITE   104690\n0x40011640 READ    105077\n0x4005F000 WRITE   105285\n0x40011680 READ    105672\n0x4005F040 WRITE   105880\n0x400116C0 READ    106267\n0x4005F080 WRITE   106475\n0x40011700 READ    106862\n0x4005F0C0 WRITE   107070\n0x40011740 READ    107457\n0x4005F100 WRITE   107665\n0x40011780 READ    108052\n0x4005F140 WRITE   108260\n0x400117C0 READ    108647\n0x40011800 READ    109253\n0x4005F240 WRITE   109460\n0x40011840 READ    109847\n0x4005F280 WRITE   110055\n0x40011880 READ    110442\n0x4005F2C0 WRITE   110650\n0x400118C0 READ    111037\n0x4005F300 WRITE   111245\n0x40011900 READ    111632\n0x4005F340 WRITE   111840\n0x40011940 READ    112227\n0x4005F380 WRITE   112435\n0x40011980 READ    112822\n0x4005F3C0 WRITE   113030\n0x400119C0 READ    113417\n0x4005F400 WRITE   113625\n0x40011A00 READ    114012\n0x4005F440 WRITE   114220\n0x40011A40 READ    114607\n0x40011A80 READ    115213\n0x4005F540 WRITE   115420\n0x40011AC0 READ    115807\n0x4005F580 WRITE   116015\n0x40011B00 READ    116402\n0x4005F5C0 WRITE   116610\n0x40011B40 READ    116997\n0x4005F600 WRITE   117205\n0x40011B80 READ    117592\n0x4005F640 WRITE   117800\n0x40011BC0 READ    118187\n0x4005F680 WRITE   118395\n0x40011C00 READ    118782\n0x4005F6C0 WRITE   118990\n0x40011C40 READ    119377\n0x4005F700 WRITE   119585\n0x40011C80 READ    119972\n0x4005F740 WRITE   120180\n0x40011CC0 READ    120567\n0x40011D00 READ    121173\n0x4005F840 WRITE   121380\n0x40011D40 READ    121767\n0x4005F880 WRITE   121975\n0x40011D80 READ    122362\n0x4005F8C0 WRITE   122570\n0x40011DC0 READ    122957\n0x4005F900 WRITE   123165\n0x40011E00 READ    123552\n0x4005F940 WRITE   123760\n0x40011E40 READ    124147\n0x4005F980 WRITE   124355\n0x40011E80 READ    124742\n0x4005F9C0 WRITE   124950\n0x40011EC0 READ    125337\n0x4005FA00 WRITE   125545\n0x40011F00 READ    125932\n0x4005FA40 WRITE   126140\n0x40011F40 READ    126527\n0x40011F80 READ    127133\n0x4005FB40 WRITE   127340\n0x40011FC0 READ    127727\n0x4005FB80 WRITE   127935\n0x40012000 READ    128352\n0x4005FBC0 WRITE   128560\n0x40012040 READ    128947\n0x4005FC00 WRITE   129155\n0x40012080 READ    129542\n0x4005FC40 WRITE   129750\n0x400120C0 READ    130137\n0x4005FC80 WRITE   130345\n0x40012100 READ    130732\n0x4005FCC0 WRITE   130940\n0x40012140 READ    131327\n0x4005FD00 WRITE   131535\n0x40012180 READ    131922\n0x4005FD40 WRITE   132130\n0x400121C0 READ    132517\n0x40012200 READ    133123\n0x4005FE40 WRITE   133330\n0x40012240 READ    133717\n0x4005FE80 WRITE   133925\n0x40012280 READ    134312\n0x4005FEC0 WRITE   134520\n0x400122C0 READ    134907\n0x4005FF00 WRITE   135115\n0x40012300 READ    135502\n0x4005FF40 WRITE   135710\n0x40012340 READ    136097\n0x4005FF80 WRITE   136305\n0x40012380 READ    136692\n0x4005FFC0 WRITE   136900\n0x400123C0 READ    137287\n0x40060000 WRITE   137495\n0x40012400 READ    137882\n0x40060040 WRITE   138090\n0x40012440 READ    138477\n0x40012480 READ    139083\n0x40060140 WRITE   139290\n0x400124C0 READ    139677\n0x40060180 WRITE   139885\n0x40012500 READ    140272\n0x400601C0 WRITE   140480\n0x40012540 READ    140867\n0x40060200 WRITE   141075\n0x40012580 READ    141462\n0x40060240 WRITE   141670\n0x400125C0 READ    142057\n0x40060280 WRITE   142265\n0x40012600 READ    142652\n0x400602C0 WRITE   142860\n0x40012640 READ    143247\n0x40060300 WRITE   143455\n0x40012680 READ    143842\n0x40060340 WRITE   144050\n0x400126C0 READ    144437\n0x40012700 READ    145045\n0x40060440 WRITE   145255\n0x40012740 READ    145642\n0x40060480 WRITE   145850\n0x40012780 READ    146237\n0x400604C0 WRITE   146445\n0x400127C0 READ    146832\n0x40060500 WRITE   147040\n0x40012800 READ    147427\n0x40060540 WRITE   147635\n0x40012840 READ    148022\n0x40060580 WRITE   148230\n0x40012880 READ    148617\n0x400605C0 WRITE   148825\n0x400128C0 READ    149212\n0x40060600 WRITE   149420\n0x40012900 READ    149807\n0x40060640 WRITE   150015\n0x40012940 READ    150402\n0x40012980 READ    151008\n0x40060740 WRITE   151215\n0x400129C0 READ    151602\n0x40060780 WRITE   151810\n0x40012A00 READ    152197\n0x400607C0 WRITE   152405\n0x40012A40 READ    152792\n0x40060800 WRITE   153000\n0x40012A80 READ    153387\n0x40060840 WRITE   153595\n0x40012AC0 READ    153982\n0x40060880 WRITE   154190\n0x40012B00 READ    154577\n0x400608C0 WRITE   154785\n0x40012B40 READ    155172\n0x40060900 WRITE   155380\n0x40012B80 READ    155767\n0x40060940 WRITE   155975\n0x40012BC0 READ    156362\n0x40012C00 READ    156968\n0x40060A40 WRITE   157175\n0x40012C40 READ    157562\n0x40060A80 WRITE   157770\n0x40012C80 READ    158157\n0x40060AC0 WRITE   158365\n0x40012CC0 READ    158752\n0x40060B00 WRITE   158960\n0x40012D00 READ    159347\n0x40060B40 WRITE   159555\n0x40012D40 READ    159942\n0x40060B80 WRITE   160150\n0x40012D80 READ    160537\n0x40060BC0 WRITE   160745\n0x40012DC0 READ    161132\n0x40060C00 WRITE   161340\n0x40012E00 READ    161727\n0x40060C40 WRITE   161935\n0x40012E40 READ    162322\n0x40012E80 READ    162928\n0x40060D40 WRITE   163135\n0x40012EC0 READ    163522\n0x40060D80 WRITE   163730\n0x40012F00 READ    164117\n0x40060DC0 WRITE   164325\n0x40012F40 READ    164712\n0x40060E00 WRITE   164920\n0x40012F80 READ    165307\n0x40060E40 WRITE   165515\n0x40012FC0 READ    165902\n0x40060E80 WRITE   166110\n0x40013000 READ    166527\n0x40060EC0 WRITE   166735\n0x40013040 READ    167122\n0x40060F00 WRITE   167330\n0x40013080 READ    167717\n0x40060F40 WRITE   167925\n0x400130C0 READ    168312\n0x40013100 READ    168920\n0x40061040 WRITE   169130\n0x40013140 READ    169517\n0x40061080 WRITE   169725\n0x40013180 READ    170112\n0x400610C0 WRITE   170320\n0x400131C0 READ    170707\n0x40061100 WRITE   170915\n0x40013200 READ    171302\n0x40061140 WRITE   171510\n0x40013240 READ    171897\n0x40061180 WRITE   172105\n0x40013280 READ    172492\n0x400611C0 WRITE   172700\n0x400132C0 READ    173087\n0x40061200 WRITE   173295\n0x40013300 READ    173682\n0x40061240 WRITE   173890\n0x40013340 READ    174277\n0x40013380 READ    174883\n0x40061340 WRITE   175090\n0x400133C0 READ    175477\n0x40061380 WRITE   175685\n0x40013400 READ    176072\n0x400613C0 WRITE   176280\n0x40013440 READ    176667\n0x40061400 WRITE   176875\n0x40013480 READ    177262\n0x40061440 WRITE   177470\n0x400134C0 READ    177857\n0x40061480 WRITE   178065\n0x40013500 READ    178452\n0x400614C0 WRITE   178660\n0x40013540 READ    179047\n0x40061500 WRITE   179255\n0x40013580 READ    179642\n0x40061540 WRITE   179850\n0x400135C0 READ    180237\n0x40013600 READ    180843\n0x40061640 WRITE   181050\n0x40013640 READ    181437\n0x40061680 WRITE   181645\n0x40013680 READ    182032\n0x400616C0 WRITE   182240\n0x400136C0 READ    182627\n0x40061700 WRITE   182835\n0x40013700 READ    183222\n0x40061740 WRITE   183430\n0x40013740 READ    183817\n0x40061780 WRITE   184025\n0x40013780 READ    184412\n0x400617C0 WRITE   184620\n0x400137C0 READ    185007\n0x40061800 WRITE   185215\n0x40013800 READ    185602\n0x40061840 WRITE   185810\n0x40013840 READ    186197\n0x40013880 READ    186803\n0x40061940 WRITE   187010\n0x400138C0 READ    187397\n0x40061980 WRITE   187605\n0x40013900 READ    187992\n0x400619C0 WRITE   188200\n0x40013940 READ    188587\n0x40061A00 WRITE   188795\n0x40013980 READ    189182\n0x40061A40 WRITE   189390\n0x400139C0 READ    189777\n0x40061A80 WRITE   189985\n0x40013A00 READ    190372\n0x40061AC0 WRITE   190580\n0x40013A40 READ    190967\n0x40061B00 WRITE   191175\n0x40013A80 READ    191562\n0x40061B40 WRITE   191770\n0x40013AC0 READ    192157\n0x40013B00 READ    192765\n0x40061C40 WRITE   192975\n0x40013B40 READ    193362\n0x40061C80 WRITE   193570\n0x40013B80 READ    193957\n0x40061CC0 WRITE   194165\n0x40013BC0 READ    194552\n0x40061D00 WRITE   194760\n0x40013C00 READ    195147\n0x40061D40 WRITE   195355\n0x40013C40 READ    195742\n0x40061D80 WRITE   195950\n0x40013C80 READ    196337\n0x40061DC0 WRITE   196545\n0x40013CC0 READ    196932\n0x40061E00 WRITE   197140\n0x40013D00 READ    197527\n0x40061E40 WRITE   197735\n0x40013D40 READ    198122\n0x40013D80 READ    198728\n0x40061F40 WRITE   198935\n0x40013DC0 READ    199322\n0x40061F80 WRITE   199530\n0x40013E00 READ    199917\n0x40061FC0 WRITE   200125\n0x40013E40 READ    200512\n0x40062000 WRITE   200720\n0x40013E80 READ    201107\n0x40062040 WRITE   201315\n0x40013EC0 READ    201702\n0x40062080 WRITE   201910\n0x40013F00 READ    202297\n0x400620C0 WRITE   202505\n0x40013F40 READ    202892\n0x40062100 WRITE   203100\n0x40013F80 READ    203487\n0x40062140 WRITE   203695\n0x40013FC0 READ    204082\n0x40014000 READ    204718\n0x40062240 WRITE   205005\n0x40014040 READ    205392\n0x40062280 WRITE   205600\n0x40014080 READ    205987\n0x400622C0 WRITE   206195\n0x400140C0 READ    206582\n0x40062300 WRITE   206790\n0x40014100 READ    207177\n0x40062340 WRITE   207385\n0x40014140 READ    207772\n0x40062380 WRITE   207980\n0x40014180 READ    208367\n0x400623C0 WRITE   208575\n0x400141C0 READ    208962\n0x40062400 WRITE   209170\n0x40014200 READ    209557\n0x40062440 WRITE   209765\n0x40014240 READ    210152\n0x40014280 READ    210758\n0x40062540 WRITE   210965\n0x400142C0 READ    211352\n0x40062580 WRITE   211560\n0x40014300 READ    211947\n0x400625C0 WRITE   212155\n0x40014340 READ    212542\n0x40062600 WRITE   212750\n0x40014380 READ    213137\n0x40062640 WRITE   213345\n0x400143C0 READ    213732\n0x40062680 WRITE   213940\n0x40014400 READ    214327\n0x400626C0 WRITE   214535\n0x40014440 READ    214922\n0x40062700 WRITE   215130\n0x40014480 READ    215517\n0x40062740 WRITE   215725\n0x400144C0 READ    216112\n0x40014500 READ    216720\n0x40062840 WRITE   216930\n0x40014540 READ    217317\n0x40062880 WRITE   217525\n0x40014580 READ    217912\n0x400628C0 WRITE   218120\n0x400145C0 READ    218507\n0x40062900 WRITE   218715\n0x40014600 READ    219102\n0x40062940 WRITE   219310\n0x40014640 READ    219697\n0x40062980 WRITE   219905\n0x40014680 READ    220292\n0x400629C0 WRITE   220500\n0x400146C0 READ    220887\n0x40062A00 WRITE   221095\n0x40014700 READ    221482\n0x40062A40 WRITE   221690\n0x40014740 READ    222077\n0x40014780 READ    222683\n0x40062B40 WRITE   222890\n0x400147C0 READ    223277\n0x40062B80 WRITE   223485\n0x40014800 READ    223872\n0x40062BC0 WRITE   224080\n0x40014840 READ    224467\n0x40062C00 WRITE   224675\n0x40014880 READ    225062\n0x40062C40 WRITE   225270\n0x400148C0 READ    225657\n0x40062C80 WRITE   225865\n0x40014900 READ    226252\n0x40062CC0 WRITE   226460\n0x40014940 READ    226847\n0x40062D00 WRITE   227055\n0x40014980 READ    227442\n0x40062D40 WRITE   227650\n0x400149C0 READ    228037\n0x40014A00 READ    228643\n0x40062E40 WRITE   228850\n0x40014A40 READ    229237\n0x40062E80 WRITE   229445\n0x40014A80 READ    229832\n0x40062EC0 WRITE   230040\n0x40014AC0 READ    230427\n0x40062F00 WRITE   230635\n0x40014B00 READ    231022\n0x40062F40 WRITE   231230\n0x40014B40 READ    231617\n0x40062F80 WRITE   231825\n0x40014B80 READ    232212\n0x40062FC0 WRITE   232420\n0x40014BC0 READ    232807\n0x40063000 WRITE   233015\n0x40014C00 READ    233402\n0x40063040 WRITE   233610\n0x40014C40 READ    233997\n0x40014C80 READ    234603\n0x40063140 WRITE   234810\n0x40014CC0 READ    235197\n0x40063180 WRITE   235405\n0x40014D00 READ    235792\n0x400631C0 WRITE   236000\n0x40014D40 READ    236387\n0x40063200 WRITE   236595\n0x40014D80 READ    236982\n0x40063240 WRITE   237190\n0x40014DC0 READ    237577\n0x40063280 WRITE   237785\n0x40014E00 READ    238172\n0x400632C0 WRITE   238380\n0x40014E40 READ    238767\n0x40063300 WRITE   238975\n0x40014E80 READ    239362\n0x40063340 WRITE   239570\n0x40014EC0 READ    239957\n0x40014F00 READ    240565\n0x40063440 WRITE   240775\n0x40014F40 READ    241162\n0x40063480 WRITE   241370\n0x40014F80 READ    241757\n0x400634C0 WRITE   241965\n0x40014FC0 READ    242352\n0x40063500 WRITE   242560\n0x40015000 READ    242977\n0x40063540 WRITE   243185\n0x40015040 READ    243572\n0x40063580 WRITE   243780\n0x40015080 READ    244167\n0x400635C0 WRITE   244375\n0x400150C0 READ    244762\n0x40063600 WRITE   244970\n0x40015100 READ    245357\n0x40063640 WRITE   245565\n0x40015140 READ    245952\n0x40015180 READ    246558\n0x40063740 WRITE   246765\n0x400151C0 READ    247152\n0x40063780 WRITE   247360\n0x40015200 READ    247747\n0x400637C0 WRITE   247955\n0x40015240 READ    248342\n0x40063800 WRITE   248550\n0x40015280 READ    248937\n0x40063840 WRITE   249145\n0x400152C0 READ    249532\n0x40063880 WRITE   249740\n0x40015300 READ    250127\n0x400638C0 WRITE   250335\n0x40015340 READ    250722\n0x40063900 WRITE   250930\n0x40015380 READ    251317\n0x40063940 WRITE   251525\n0x400153C0 READ    251912\n0x40015400 READ    252518\n0x40063A40 WRITE   252725\n0x40015440 READ    253112\n0x40063A80 WRITE   253320\n0x40015480 READ    253707\n0x40063AC0 WRITE   253915\n0x400154C0 READ    254302\n0x40063B00 WRITE   254510\n0x40015500 READ    254897\n0x40063B40 WRITE   255105\n0x40015540 READ    255492\n0x40063B80 WRITE   255700\n0x40015580 READ    256087\n0x40063BC0 WRITE   256295\n0x400155C0 READ    256682\n0x40063C00 WRITE   256890\n0x40015600 READ    257277\n0x40063C40 WRITE   257485\n0x40015640 READ    257872\n0x40015680 READ    258478\n0x40063D40 WRITE   258685\n0x400156C0 READ    259072\n0x40063D80 WRITE   259280\n0x40015700 READ    259667\n0x40063DC0 WRITE   259875\n0x40015740 READ    260262\n0x40063E00 WRITE   260470\n0x40015780 READ    260857\n0x40063E40 WRITE   261065\n0x400157C0 READ    261452\n0x40063E80 WRITE   261660\n0x40015800 READ    262047\n0x40063EC0 WRITE   262255\n0x40015840 READ    262642\n0x40063F00 WRITE   262850\n0x40015880 READ    263237\n0x40063F40 WRITE   263445\n0x400158C0 READ    263832\n0x40015900 READ    264440\n0x40064040 WRITE   264650\n0x40015940 READ    265037\n0x40064080 WRITE   265245\n0x40015980 READ    265632\n0x400640C0 WRITE   265840\n0x400159C0 READ    266227\n0x40064100 WRITE   266435\n0x40015A00 READ    266822\n0x40064140 WRITE   267030\n0x40015A40 READ    267417\n0x40064180 WRITE   267625\n0x40015A80 READ    268012\n0x400641C0 WRITE   268220\n0x40015AC0 READ    268607\n0x40064200 WRITE   268815\n0x40015B00 READ    269202\n0x40064240 WRITE   269410\n0x40015B40 READ    269797\n0x40015B80 READ    270403\n0x40064340 WRITE   270610\n0x40015BC0 READ    270997\n0x40064380 WRITE   271205\n0x40015C00 READ    271592\n0x400643C0 WRITE   271800\n0x40015C40 READ    272187\n0x40064400 WRITE   272395\n0x40015C80 READ    272782\n0x40064440 WRITE   272990\n0x40015CC0 READ    273377\n0x40064480 WRITE   273585\n0x40015D00 READ    273972\n0x400644C0 WRITE   274180\n0x40015D40 READ    274567\n0x40064500 WRITE   274775\n0x40015D80 READ    275162\n0x40064540 WRITE   275370\n0x40015DC0 READ    275757\n0x40015E00 READ    276363\n0x40064640 WRITE   276570\n0x40015E40 READ    276957\n0x40064680 WRITE   277165\n0x40015E80 READ    277552\n0x400646C0 WRITE   277760\n0x40015EC0 READ    278147\n0x40064700 WRITE   278355\n0x40015F00 READ    278742\n0x40064740 WRITE   278950\n0x40015F40 READ    279337\n0x40064780 WRITE   279545\n0x40015F80 READ    279932\n0x400647C0 WRITE   280140\n0x40015FC0 READ    280527\n0x40064800 WRITE   280735\n0x40016000 READ    281152\n0x40064840 WRITE   281360\n0x40016040 READ    281747\n0x40016080 READ    282353\n0x40064940 WRITE   282560\n0x400160C0 READ    282947\n0x40064980 WRITE   283155\n0x40016100 READ    283542\n0x400649C0 WRITE   283750\n0x40016140 READ    284137\n0x40064A00 WRITE   284345\n0x40016180 READ    284732\n0x40064A40 WRITE   284940\n0x400161C0 READ    285327\n0x40064A80 WRITE   285535\n0x40016200 READ    285922\n0x40064AC0 WRITE   286130\n0x40016240 READ    286517\n0x40064B00 WRITE   286725\n0x40016280 READ    287112\n0x40064B40 WRITE   287320\n0x400162C0 READ    287707\n0x40016300 READ    288315\n0x40064C40 WRITE   288525\n0x40016340 READ    288912\n0x40064C80 WRITE   289120\n0x40016380 READ    289507\n0x40064CC0 WRITE   289715\n0x400163C0 READ    290102\n0x40064D00 WRITE   290310\n0x40016400 READ    290697\n0x40064D40 WRITE   290905\n0x40016440 READ    291292\n0x40064D80 WRITE   291500\n0x40016480 READ    291887\n0x40064DC0 WRITE   292095\n0x400164C0 READ    292482\n0x40064E00 WRITE   292690\n0x40016500 READ    293077\n0x40064E40 WRITE   293285\n0x40016540 READ    293672\n0x40016580 READ    294278\n0x40064F40 WRITE   294485\n0x400165C0 READ    294872\n0x40064F80 WRITE   295080\n0x40016600 READ    295467\n0x40064FC0 WRITE   295675\n0x40016640 READ    296062\n0x40065000 WRITE   296270\n0x40016680 READ    296657\n0x40065040 WRITE   296865\n0x400166C0 READ    297252\n0x40065080 WRITE   297460\n0x40016700 READ    297847\n0x400650C0 WRITE   298055\n0x40016740 READ    298442\n0x40065100 WRITE   298650\n0x40016780 READ    299037\n0x40065140 WRITE   299245\n0x400167C0 READ    299632\n0x40016800 READ    300238\n0x40065240 WRITE   300445\n0x40016840 READ    300832\n0x40065280 WRITE   301040\n0x40016880 READ    301427\n0x400652C0 WRITE   301635\n0x400168C0 READ    302022\n0x40065300 WRITE   302230\n0x40016900 READ    302617\n0x40065340 WRITE   302825\n0x40016940 READ    303212\n0x40065380 WRITE   303420\n0x40016980 READ    303807\n0x400653C0 WRITE   304015\n0x400169C0 READ    304402\n0x40065400 WRITE   304610\n0x40016A00 READ    304997\n0x40065440 WRITE   305205\n0x40016A40 READ    305592\n0x40016A80 READ    306198\n0x40065540 WRITE   306405\n0x40016AC0 READ    306792\n0x40065580 WRITE   307000\n0x40016B00 READ    307387\n0x400655C0 WRITE   307595\n0x40016B40 READ    307982\n0x40065600 WRITE   308190\n0x40016B80 READ    308577\n0x40065640 WRITE   308785\n0x40016BC0 READ    309172\n0x40065680 WRITE   309380\n0x40016C00 READ    309767\n0x400656C0 WRITE   309975\n0x40016C40 READ    310362\n0x40065700 WRITE   310570\n0x40016C80 READ    310957\n0x40065740 WRITE   311165\n0x40016CC0 READ    311552\n0x40016D00 READ    312160\n0x40065840 WRITE   312370\n0x40016D40 READ    312757\n0x40065880 WRITE   312965\n0x40016D80 READ    313352\n0x400658C0 WRITE   313560\n0x40016DC0 READ    313947\n0x40065900 WRITE   314155\n0x40016E00 READ    314542\n0x40065940 WRITE   314750\n0x40016E40 READ    315137\n0x40065980 WRITE   315345\n0x40016E80 READ    315732\n0x400659C0 WRITE   315940\n0x40016EC0 READ    316327\n0x40065A00 WRITE   316535\n0x40016F00 READ    316922\n0x40065A40 WRITE   317130\n0x40016F40 READ    317517\n0x40016F80 READ    318123\n0x40065B40 WRITE   318330\n0x40016FC0 READ    318717\n0x40065B80 WRITE   318925\n0x40017000 READ    319342\n0x40065BC0 WRITE   319550\n0x40017040 READ    319937\n0x40065C00 WRITE   320145\n0x40017080 READ    320532\n0x40065C40 WRITE   320740\n0x400170C0 READ    321127\n0x40065C80 WRITE   321335\n0x40017100 READ    321722\n0x40065CC0 WRITE   321930\n0x40017140 READ    322317\n0x40065D00 WRITE   322525\n0x40017180 READ    322912\n0x40065D40 WRITE   323120\n0x400171C0 READ    323507\n0x40017200 READ    324113\n0x40065E40 WRITE   324320\n0x40017240 READ    324707\n0x40065E80 WRITE   324915\n0x40017280 READ    325302\n0x40065EC0 WRITE   325510\n0x400172C0 READ    325897\n0x40065F00 WRITE   326105\n0x40017300 READ    326492\n0x40065F40 WRITE   326700\n0x40017340 READ    327087\n0x40065F80 WRITE   327295\n0x40017380 READ    327682\n0x40065FC0 WRITE   327890\n0x400173C0 READ    328277\n0x40066000 WRITE   328485\n0x40017400 READ    328872\n0x40066040 WRITE   329080\n0x40017440 READ    329467\n0x40017480 READ    330073\n0x40066140 WRITE   330280\n0x400174C0 READ    330667\n0x40066180 WRITE   330875\n0x40017500 READ    331262\n0x400661C0 WRITE   331470\n0x40017540 READ    331857\n0x40066200 WRITE   332065\n0x40017580 READ    332452\n0x40066240 WRITE   332660\n0x400175C0 READ    333047\n0x40066280 WRITE   333255\n0x40017600 READ    333642\n0x400662C0 WRITE   333850\n0x40017640 READ    334237\n0x40066300 WRITE   334445\n0x40017680 READ    334832\n0x40066340 WRITE   335040\n0x400176C0 READ    335427\n0x40017700 READ    336035\n0x40066440 WRITE   336245\n0x40017740 READ    336632\n0x40066480 WRITE   336840\n0x40017780 READ    337227\n0x400664C0 WRITE   337435\n0x400177C0 READ    337822\n0x40066500 WRITE   338030\n0x40017800 READ    338417\n0x40066540 WRITE   338625\n0x40017840 READ    339012\n0x40066580 WRITE   339220\n0x40017880 READ    339607\n0x400665C0 WRITE   339815\n0x400178C0 READ    340202\n0x40066600 WRITE   340410\n0x40017900 READ    340797\n0x40066640 WRITE   341005\n0x40017940 READ    341392\n0x40017980 READ    341998\n0x40066740 WRITE   342205\n0x400179C0 READ    342592\n0x40066780 WRITE   342800\n0x40017A00 READ    343187\n0x400667C0 WRITE   343395\n0x40017A40 READ    343782\n0x40066800 WRITE   343990\n0x40017A80 READ    344377\n0x40066840 WRITE   344585\n0x40017AC0 READ    344972\n0x40066880 WRITE   345180\n0x40017B00 READ    345567\n0x400668C0 WRITE   345775\n0x40017B40 READ    346162\n0x40066900 WRITE   346370\n0x40017B80 READ    346757\n0x40066940 WRITE   346965\n0x40017BC0 READ    347352\n0x40017C00 READ    347958\n0x40066A40 WRITE   348165\n0x40017C40 READ    348552\n0x40066A80 WRITE   348760\n0x40017C80 READ    349147\n0x40066AC0 WRITE   349355\n0x40017CC0 READ    349742\n0x40066B00 WRITE   349950\n0x40017D00 READ    350337\n0x40066B40 WRITE   350545\n0x40017D40 READ    350932\n0x40066B80 WRITE   351140\n0x40017D80 READ    351527\n0x40066BC0 WRITE   351735\n0x40017DC0 READ    352122\n0x40066C00 WRITE   352330\n0x40017E00 READ    352717\n0x40066C40 WRITE   352925\n0x40017E40 READ    353312\n0x40017E80 READ    353918\n0x40066D40 WRITE   354125\n0x40017EC0 READ    354512\n0x40066D80 WRITE   354720\n0x40017F00 READ    355107\n0x40066DC0 WRITE   355315\n0x40017F40 READ    355702\n0x40066E00 WRITE   355910\n0x40017F80 READ    356297\n0x40066E40 WRITE   356505\n0x40017FC0 READ    356892\n0x40066E80 WRITE   357100\n0x40018000 READ    357517\n0x40066EC0 WRITE   357805\n0x40018040 READ    358192\n0x40066F00 WRITE   358400\n0x40018080 READ    358787\n0x40066F40 WRITE   358995\n0x400180C0 READ    359382\n0x40018100 READ    359990\n0x40067040 WRITE   360200\n0x40018140 READ    360587\n0x40067080 WRITE   360795\n0x40018180 READ    361182\n0x400670C0 WRITE   361390\n0x400181C0 READ    361777\n0x40067100 WRITE   361985\n0x40018200 READ    362372\n0x40067140 WRITE   362580\n0x40018240 READ    362967\n0x40067180 WRITE   363175\n0x40018280 READ    363562\n0x400671C0 WRITE   363770\n0x400182C0 READ    364157\n0x40067200 WRITE   364365\n0x40018300 READ    364752\n0x40067240 WRITE   364960\n0x40018340 READ    365347\n0x40018380 READ    365953\n0x40067340 WRITE   366160\n0x400183C0 READ    366547\n0x40067380 WRITE   366755\n0x40018400 READ    367142\n0x400673C0 WRITE   367350\n0x40018440 READ    367737\n0x40067400 WRITE   367945\n0x40018480 READ    368332\n0x40067440 WRITE   368540\n0x400184C0 READ    368927\n0x40067480 WRITE   369135\n0x40018500 READ    369522\n0x400674C0 WRITE   369730\n0x40018540 READ    370117\n0x40067500 WRITE   370325\n0x40018580 READ    370712\n0x40067540 WRITE   370920\n0x400185C0 READ    371307\n0x40018600 READ    371913\n0x40067640 WRITE   372120\n0x40018640 READ    372507\n0x40067680 WRITE   372715\n0x40018680 READ    373102\n0x400676C0 WRITE   373310\n0x400186C0 READ    373697\n0x40067700 WRITE   373905\n0x40018700 READ    374292\n0x40067740 WRITE   374500\n0x40018740 READ    374887\n0x40067780 WRITE   375095\n0x40018780 READ    375482\n0x400677C0 WRITE   375690\n0x400187C0 READ    376077\n0x40067800 WRITE   376285\n0x40018800 READ    376672\n0x40067840 WRITE   376880\n0x40018840 READ    377267\n0x40018880 READ    377873\n0x40067940 WRITE   378080\n0x400188C0 READ    378467\n0x40067980 WRITE   378675\n0x40018900 READ    379062\n0x400679C0 WRITE   379270\n0x40018940 READ    379657\n0x40067A00 WRITE   379865\n0x40018980 READ    380252\n0x40067A40 WRITE   380460\n0x400189C0 READ    380847\n0x40067A80 WRITE   381055\n0x40018A00 READ    381442\n0x40067AC0 WRITE   381650\n0x40018A40 READ    382037\n0x40067B00 WRITE   382245\n0x40018A80 READ    382632\n0x40067B40 WRITE   382840\n0x40018AC0 READ    383227\n0x40018B00 READ    383835\n0x40067C40 WRITE   384045\n0x40018B40 READ    384432\n0x40067C80 WRITE   384640\n0x40018B80 READ    385027\n0x40067CC0 WRITE   385235\n0x40018BC0 READ    385622\n0x40067D00 WRITE   385830\n0x40018C00 READ    386217\n0x40067D40 WRITE   386425\n0x40018C40 READ    386812\n0x40067D80 WRITE   387020\n0x40018C80 READ    387407\n0x40067DC0 WRITE   387615\n0x40018CC0 READ    388002\n0x40067E00 WRITE   388210\n0x40018D00 READ    388597\n0x40067E40 WRITE   388805\n0x40018D40 READ    389192\n0x40018D80 READ    389798\n0x40067F40 WRITE   390005\n0x40018DC0 READ    390392\n0x40067F80 WRITE   390600\n0x40018E00 READ    390987\n0x40067FC0 WRITE   391195\n0x40018E40 READ    391582\n0x40068000 WRITE   391790\n0x40018E80 READ    392177\n0x40068040 WRITE   392385\n0x40018EC0 READ    392772\n0x40068080 WRITE   392980\n0x40018F00 READ    393367\n0x400680C0 WRITE   393575\n0x40018F40 READ    393962\n0x40068100 WRITE   394170\n0x40018F80 READ    394557\n0x40068140 WRITE   394765\n0x40018FC0 READ    395152\n0x40019000 READ    395788\n0x40068240 WRITE   395995\n0x40019040 READ    396382\n0x40068280 WRITE   396590\n0x40019080 READ    396977\n0x400682C0 WRITE   397185\n0x400190C0 READ    397572\n0x40068300 WRITE   397780\n0x40019100 READ    398167\n0x40068340 WRITE   398375\n0x40019140 READ    398762\n0x40068380 WRITE   398970\n0x40019180 READ    399357\n0x400683C0 WRITE   399565\n0x400191C0 READ    399952\n0x40068400 WRITE   400160\n0x40019200 READ    400547\n0x40068440 WRITE   400755\n0x40019240 READ    401142\n0x40019280 READ    401748\n0x40068540 WRITE   401955\n0x400192C0 READ    402342\n0x40068580 WRITE   402550\n0x40019300 READ    402937\n0x400685C0 WRITE   403145\n0x40019340 READ    403532\n0x40068600 WRITE   403740\n0x40019380 READ    404127\n0x40068640 WRITE   404335\n0x400193C0 READ    404722\n0x40068680 WRITE   404930\n0x40019400 READ    405317\n0x400686C0 WRITE   405525\n0x40019440 READ    405912\n0x40068700 WRITE   406120\n0x40019480 READ    406507\n0x40068740 WRITE   406715\n0x400194C0 READ    407102\n0x40019500 READ    407710\n0x40068840 WRITE   407920\n0x40019540 READ    408307\n0x40068880 WRITE   408515\n0x40019580 READ    408902\n0x400688C0 WRITE   409110\n0x400195C0 READ    409497\n0x40068900 WRITE   409705\n0x40019600 READ    410092\n0x40068940 WRITE   410300\n0x40019640 READ    410687\n0x40068980 WRITE   410895\n0x40019680 READ    411282\n0x400689C0 WRITE   411490\n0x400196C0 READ    411877\n0x40068A00 WRITE   412085\n0x40019700 READ    412472\n0x40068A40 WRITE   412680\n0x40019740 READ    413067\n0x40019780 READ    413673\n0x40068B40 WRITE   413880\n0x400197C0 READ    414267\n0x40068B80 WRITE   414475\n0x40019800 READ    414862\n0x40068BC0 WRITE   415070\n0x40019840 READ    415457\n0x40068C00 WRITE   415665\n0x40019880 READ    416052\n0x40068C40 WRITE   416260\n0x400198C0 READ    416647\n0x40068C80 WRITE   416855\n0x40019900 READ    417242\n0x40068CC0 WRITE   417450\n0x40019940 READ    417837\n0x40068D00 WRITE   418045\n0x40019980 READ    418432\n0x40068D40 WRITE   418640\n0x400199C0 READ    419027\n0x40019A00 READ    419633\n0x40068E40 WRITE   419840\n0x40019A40 READ    420227\n0x40068E80 WRITE   420435\n0x40019A80 READ    420822\n0x40068EC0 WRITE   421030\n0x40019AC0 READ    421417\n0x40068F00 WRITE   421625\n0x40019B00 READ    422012\n0x40068F40 WRITE   422220\n0x40019B40 READ    422607\n0x40068F80 WRITE   422815\n0x40019B80 READ    423202\n0x40068FC0 WRITE   423410\n0x40019BC0 READ    423797\n0x40069000 WRITE   424005\n0x40019C00 READ    424392\n0x40069040 WRITE   424600\n0x40019C40 READ    424987\n0x40019C80 READ    425593\n0x40069140 WRITE   425800\n0x40019CC0 READ    426187\n0x40069180 WRITE   426395\n0x40019D00 READ    426782\n0x400691C0 WRITE   426990\n0x40019D40 READ    427377\n0x40069200 WRITE   427585\n0x40019D80 READ    427972\n0x40069240 WRITE   428180\n0x40019DC0 READ    428567\n0x40069280 WRITE   428775\n0x40019E00 READ    429162\n0x400692C0 WRITE   429370\n0x40019E40 READ    429757\n0x40069300 WRITE   429965\n0x40019E80 READ    430352\n0x40069340 WRITE   430560\n0x40019EC0 READ    430947\n0x40019F00 READ    431555\n0x40069440 WRITE   431765\n0x40019F40 READ    432152\n0x40069480 WRITE   432360\n0x40019F80 READ    432747\n0x400694C0 WRITE   432955\n0x40019FC0 READ    433342\n0x40069500 WRITE   433550\n0x4001A000 READ    433967\n0x40069540 WRITE   434175\n0x4001A040 READ    434562\n0x40069580 WRITE   434770\n0x4001A080 READ    435157\n0x400695C0 WRITE   435365\n0x4001A0C0 READ    435752\n0x40069600 WRITE   435960\n0x4001A100 READ    436347\n0x40069640 WRITE   436555\n0x4001A140 READ    436942\n0x4001A180 READ    437548\n0x40069740 WRITE   437755\n0x4001A1C0 READ    438142\n0x40069780 WRITE   438350\n0x4001A200 READ    438737\n0x400697C0 WRITE   438945\n0x4001A240 READ    439332\n0x40069800 WRITE   439540\n0x4001A280 READ    439927\n0x40069840 WRITE   440135\n0x4001A2C0 READ    440522\n0x40069880 WRITE   440730\n0x4001A300 READ    441117\n0x400698C0 WRITE   441325\n0x4001A340 READ    441712\n0x40069900 WRITE   441920\n0x4001A380 READ    442307\n0x40069940 WRITE   442515\n0x4001A3C0 READ    442902\n0x4001A400 READ    443508\n0x40069A40 WRITE   443715\n0x4001A440 READ    444102\n0x40069A80 WRITE   444310\n0x4001A480 READ    444697\n0x40069AC0 WRITE   444905\n0x4001A4C0 READ    445292\n0x40069B00 WRITE   445500\n0x4001A500 READ    445887\n0x40069B40 WRITE   446095\n0x4001A540 READ    446482\n0x40069B80 WRITE   446690\n0x4001A580 READ    447077\n0x40069BC0 WRITE   447285\n0x4001A5C0 READ    447672\n0x40069C00 WRITE   447880\n0x4001A600 READ    448267\n0x40069C40 WRITE   448475\n0x4001A640 READ    448862\n0x4001A680 READ    449468\n0x40069D40 WRITE   449675\n0x4001A6C0 READ    450062\n0x40069D80 WRITE   450270\n0x4001A700 READ    450657\n0x40069DC0 WRITE   450865\n0x4001A740 READ    451252\n0x40069E00 WRITE   451460\n0x4001A780 READ    451847\n0x40069E40 WRITE   452055\n0x4001A7C0 READ    452442\n0x40069E80 WRITE   452650\n0x4001A800 READ    453037\n0x40069EC0 WRITE   453245\n0x4001A840 READ    453632\n0x40069F00 WRITE   453840\n0x4001A880 READ    454227\n0x40069F40 WRITE   454435\n0x4001A8C0 READ    454822\n0x4001A900 READ    455430\n0x4006A040 WRITE   455640\n0x4001A940 READ    456027\n0x4006A080 WRITE   456235\n0x4001A980 READ    456622\n0x4006A0C0 WRITE   456830\n0x4001A9C0 READ    457217\n0x4006A100 WRITE   457425\n0x4001AA00 READ    457812\n0x4006A140 WRITE   458020\n0x4001AA40 READ    458407\n0x4006A180 WRITE   458615\n0x4001AA80 READ    459002\n0x4006A1C0 WRITE   459210\n0x4001AAC0 READ    459597\n0x4006A200 WRITE   459805\n0x4001AB00 READ    460192\n0x4006A240 WRITE   460400\n0x4001AB40 READ    460787\n0x4001AB80 READ    461393\n0x4006A340 WRITE   461600\n0x4001ABC0 READ    461987\n0x4006A380 WRITE   462195\n0x4001AC00 READ    462582\n0x4006A3C0 WRITE   462790\n0x4001AC40 READ    463177\n0x4006A400 WRITE   463385\n0x4001AC80 READ    463772\n0x4006A440 WRITE   463980\n0x4001ACC0 READ    464367\n0x4006A480 WRITE   464575\n0x4001AD00 READ    464962\n0x4006A4C0 WRITE   465170\n0x4001AD40 READ    465557\n0x4006A500 WRITE   465765\n0x4001AD80 READ    466152\n0x4006A540 WRITE   466360\n0x4001ADC0 READ    466747\n0x4001AE00 READ    467353\n0x4006A640 WRITE   467560\n0x4001AE40 READ    467947\n0x4006A680 WRITE   468155\n0x4001AE80 READ    468542\n0x4006A6C0 WRITE   468750\n0x4001AEC0 READ    469137\n0x4006A700 WRITE   469345\n0x4001AF00 READ    469732\n0x4006A740 WRITE   469940\n0x4001AF40 READ    470327\n0x4006A780 WRITE   470535\n0x4001AF80 READ    470922\n0x4006A7C0 WRITE   471130\n0x4001AFC0 READ    471517\n0x4006A800 WRITE   471725\n0x4001B000 READ    472142\n0x4006A840 WRITE   472350\n0x4001B040 READ    472737\n0x4001B080 READ    473343\n0x4006A940 WRITE   473550\n0x4001B0C0 READ    473937\n0x4006A980 WRITE   474145\n0x4001B100 READ    474532\n0x4006A9C0 WRITE   474740\n0x4001B140 READ    475127\n0x4006AA00 WRITE   475335\n0x4001B180 READ    475722\n0x4006AA40 WRITE   475930\n0x4001B1C0 READ    476317\n0x4006AA80 WRITE   476525\n0x4001B200 READ    476912\n0x4006AAC0 WRITE   477120\n0x4001B240 READ    477507\n0x4006AB00 WRITE   477715\n0x4001B280 READ    478102\n0x4006AB40 WRITE   478310\n0x4001B2C0 READ    478697\n0x4001B300 READ    479305\n0x4006AC40 WRITE   479515\n0x4001B340 READ    479902\n0x4006AC80 WRITE   480110\n0x4001B380 READ    480497\n0x4006ACC0 WRITE   480705\n0x4001B3C0 READ    481092\n0x4006AD00 WRITE   481300\n0x4001B400 READ    481687\n0x4006AD40 WRITE   481895\n0x4001B440 READ    482282\n0x4006AD80 WRITE   482490\n0x4001B480 READ    482877\n0x4006ADC0 WRITE   483085\n0x4001B4C0 READ    483472\n0x4006AE00 WRITE   483680\n0x4001B500 READ    484067\n0x4006AE40 WRITE   484275\n0x4001B540 READ    484662\n0x4001B580 READ    485268\n0x4006AF40 WRITE   485475\n0x4001B5C0 READ    485862\n0x4006AF80 WRITE   486070\n0x4001B600 READ    486457\n0x4006AFC0 WRITE   486665\n0x4001B640 READ    487052\n0x4006B000 WRITE   487260\n0x4001B680 READ    487647\n0x4006B040 WRITE   487855\n0x4001B6C0 READ    488242\n0x4006B080 WRITE   488450\n0x4001B700 READ    488837\n0x4006B0C0 WRITE   489045\n0x4001B740 READ    489432\n0x4006B100 WRITE   489640\n0x4001B780 READ    490027\n0x4006B140 WRITE   490235\n0x4001B7C0 READ    490622\n0x4001B800 READ    491228\n0x4006B240 WRITE   491435\n0x4001B840 READ    491822\n0x4006B280 WRITE   492030\n0x4001B880 READ    492417\n0x4006B2C0 WRITE   492625\n0x4001B8C0 READ    493012\n0x4006B300 WRITE   493220\n0x4001B900 READ    493607\n0x4006B340 WRITE   493815\n0x4001B940 READ    494202\n0x4006B380 WRITE   494410\n0x4001B980 READ    494797\n0x4006B3C0 WRITE   495005\n0x4001B9C0 READ    495392\n0x4006B400 WRITE   495600\n0x4001BA00 READ    495987\n0x4006B440 WRITE   496195\n0x4001BA40 READ    496582\n0x4001BA80 READ    497188\n0x4006B540 WRITE   497395\n0x4001BAC0 READ    497782\n0x4006B580 WRITE   497990\n0x4001BB00 READ    498377\n0x4006B5C0 WRITE   498585\n0x4001BB40 READ    498972\n0x4006B600 WRITE   499180\n0x4001BB80 READ    499567\n0x4006B640 WRITE   499775\n0x4001BBC0 READ    500162\n0x4006B680 WRITE   500370\n0x4001BC00 READ    500757\n0x4006B6C0 WRITE   500965\n0x4001BC40 READ    501352\n0x4006B700 WRITE   501560\n0x4001BC80 READ    501947\n0x4006B740 WRITE   502155\n0x4001BCC0 READ    502542\n0x4001BD00 READ    503150\n0x4006B840 WRITE   503360\n0x4001BD40 READ    503747\n0x4006B880 WRITE   503955\n0x4001BD80 READ    504342\n0x4006B8C0 WRITE   504550\n0x4001BDC0 READ    504937\n0x4006B900 WRITE   505145\n0x4001BE00 READ    505532\n0x4006B940 WRITE   505740\n0x4001BE40 READ    506127\n0x4006B980 WRITE   506335\n0x4001BE80 READ    506722\n0x4006B9C0 WRITE   506930\n0x4001BEC0 READ    507317\n0x4006BA00 WRITE   507525\n0x4001BF00 READ    507912\n0x4006BA40 WRITE   508120\n0x4001BF40 READ    508507\n0x4001BF80 READ    509113\n0x4006BB40 WRITE   509320\n0x4001BFC0 READ    509707\n0x4006BB80 WRITE   509915\n0x4001C000 READ    510332\n0x4006BBC0 WRITE   510620\n0x4001C040 READ    511007\n0x4006BC00 WRITE   511215\n0x4001C080 READ    511602\n0x4006BC40 WRITE   511810\n0x4001C0C0 READ    512197\n0x4006BC80 WRITE   512405\n0x4001C100 READ    512792\n0x4006BCC0 WRITE   513000\n0x4001C140 READ    513387\n0x4006BD00 WRITE   513595\n0x4001C180 READ    513982\n0x4006BD40 WRITE   514190\n0x4001C1C0 READ    514577\n0x4001C200 READ    515183\n0x4006BE40 WRITE   515390\n0x4001C240 READ    515777\n0x4006BE80 WRITE   515985\n0x4001C280 READ    516372\n0x4006BEC0 WRITE   516580\n0x4001C2C0 READ    516967\n0x4006BF00 WRITE   517175\n0x4001C300 READ    517562\n0x4006BF40 WRITE   517770\n0x4001C340 READ    518157\n0x4006BF80 WRITE   518365\n0x4001C380 READ    518752\n0x4006BFC0 WRITE   518960\n0x4001C3C0 READ    519347\n0x4006C000 WRITE   519555\n0x4001C400 READ    519942\n0x4006C040 WRITE   520150\n0x4001C440 READ    520537\n0x4001C480 READ    521143\n0x4006C140 WRITE   521350\n0x4001C4C0 READ    521737\n0x4006C180 WRITE   521945\n0x4001C500 READ    522332\n0x4006C1C0 WRITE   522540\n0x4001C540 READ    522927\n0x4006C200 WRITE   523135\n0x4001C580 READ    523522\n0x4006C240 WRITE   523730\n0x4001C5C0 READ    524117\n0x4006C280 WRITE   524325\n0x4001C600 READ    524712\n0x4006C2C0 WRITE   524920\n0x4001C640 READ    525307\n0x4006C300 WRITE   525515\n0x4001C680 READ    525902\n0x4006C340 WRITE   526110\n0x4001C6C0 READ    526497\n0x4001C700 READ    527105\n0x4006C440 WRITE   527315\n0x4001C740 READ    527702\n0x4006C480 WRITE   527910\n0x4001C780 READ    528297\n0x4006C4C0 WRITE   528505\n0x4001C7C0 READ    528892\n0x4006C500 WRITE   529100\n0x4001C800 READ    529487\n0x4006C540 WRITE   529695\n0x4001C840 READ    530082\n0x4006C580 WRITE   530290\n0x4001C880 READ    530677\n0x4006C5C0 WRITE   530885\n0x4001C8C0 READ    531272\n0x4006C600 WRITE   531480\n0x4001C900 READ    531867\n0x4006C640 WRITE   532075\n0x4001C940 READ    532462\n0x4001C980 READ    533068\n0x4006C740 WRITE   533275\n0x4001C9C0 READ    533662\n0x4006C780 WRITE   533870\n0x4001CA00 READ    534257\n0x4006C7C0 WRITE   534465\n0x4001CA40 READ    534852\n0x4006C800 WRITE   535060\n0x4001CA80 READ    535447\n0x4006C840 WRITE   535655\n0x4001CAC0 READ    536042\n0x4006C880 WRITE   536250\n0x4001CB00 READ    536637\n0x4006C8C0 WRITE   536845\n0x4001CB40 READ    537232\n0x4006C900 WRITE   537440\n0x4001CB80 READ    537827\n0x4006C940 WRITE   538035\n0x4001CBC0 READ    538422\n0x4001CC00 READ    539028\n0x4006CA40 WRITE   539235\n0x4001CC40 READ    539622\n0x4006CA80 WRITE   539830\n0x4001CC80 READ    540217\n0x4006CAC0 WRITE   540425\n0x4001CCC0 READ    540812\n0x4006CB00 WRITE   541020\n0x4001CD00 READ    541407\n0x4006CB40 WRITE   541615\n0x4001CD40 READ    542002\n0x4006CB80 WRITE   542210\n0x4001CD80 READ    542597\n0x4006CBC0 WRITE   542805\n0x4001CDC0 READ    543192\n0x4006CC00 WRITE   543400\n0x4001CE00 READ    543787\n0x4006CC40 WRITE   543995\n0x4001CE40 READ    544382\n0x4001CE80 READ    544988\n0x4006CD40 WRITE   545195\n0x4001CEC0 READ    545582\n0x4006CD80 WRITE   545790\n0x4001CF00 READ    546177\n0x4006CDC0 WRITE   546385\n0x4001CF40 READ    546772\n0x4006CE00 WRITE   546980\n0x4001CF80 READ    547367\n0x4006CE40 WRITE   547575\n0x4001CFC0 READ    547962\n0x4006CE80 WRITE   548170\n0x4001D000 READ    548587\n0x4006CEC0 WRITE   548795\n0x4001D040 READ    549182\n0x4006CF00 WRITE   549390\n0x4001D080 READ    549777\n0x4006CF40 WRITE   549985\n0x4001D0C0 READ    550372\n0x4001D100 READ    550980\n0x4006D040 WRITE   551190\n0x4001D140 READ    551577\n0x4006D080 WRITE   551785\n0x4001D180 READ    552172\n0x4006D0C0 WRITE   552380\n0x4001D1C0 READ    552767\n0x4006D100 WRITE   552975\n0x4001D200 READ    553362\n0x4006D140 WRITE   553570\n0x4001D240 READ    553957\n0x4006D180 WRITE   554165\n0x4001D280 READ    554552\n0x4006D1C0 WRITE   554760\n0x4001D2C0 READ    555147\n0x4006D200 WRITE   555355\n0x4001D300 READ    555742\n0x4006D240 WRITE   555950\n0x4001D340 READ    556337\n0x4001D380 READ    556943\n0x4006D340 WRITE   557150\n0x4001D3C0 READ    557537\n0x4006D380 WRITE   557745\n0x4001D400 READ    558132\n0x4006D3C0 WRITE   558340\n0x4001D440 READ    558727\n0x4006D400 WRITE   558935\n0x4001D480 READ    559322\n0x4006D440 WRITE   559530\n0x4001D4C0 READ    559917\n0x4006D480 WRITE   560125\n0x4001D500 READ    560512\n0x4006D4C0 WRITE   560720\n0x4001D540 READ    561107\n0x4006D500 WRITE   561315\n0x4001D580 READ    561702\n0x4006D540 WRITE   561910\n0x4001D5C0 READ    562297\n0x4001D600 READ    562903\n0x4006D640 WRITE   563110\n0x4001D640 READ    563497\n0x4006D680 WRITE   563705\n0x4001D680 READ    564092\n0x4006D6C0 WRITE   564300\n0x4001D6C0 READ    564687\n0x4006D700 WRITE   564895\n0x4001D700 READ    565282\n0x4006D740 WRITE   565490\n0x4001D740 READ    565877\n0x4006D780 WRITE   566085\n0x4001D780 READ    566472\n0x4006D7C0 WRITE   566680\n0x4001D7C0 READ    567067\n0x4006D800 WRITE   567275\n0x4001D800 READ    567662\n0x4006D840 WRITE   567870\n0x4001D840 READ    568257\n0x4001D880 READ    568863\n0x4006D940 WRITE   569070\n0x4001D8C0 READ    569457\n0x4006D980 WRITE   569665\n0x4001D900 READ    570052\n0x4006D9C0 WRITE   570260\n0x4001D940 READ    570647\n0x4006DA00 WRITE   570855\n0x4001D980 READ    571242\n0x4006DA40 WRITE   571450\n0x4001D9C0 READ    571837\n0x4006DA80 WRITE   572045\n0x4001DA00 READ    572432\n0x4006DAC0 WRITE   572640\n0x4001DA40 READ    573027\n0x4006DB00 WRITE   573235\n0x4001DA80 READ    573622\n0x4006DB40 WRITE   573830\n0x4001DAC0 READ    574217\n0x4001DB00 READ    574825\n0x4006DC40 WRITE   575035\n0x4001DB40 READ    575422\n0x4006DC80 WRITE   575630\n0x4001DB80 READ    576017\n0x4006DCC0 WRITE   576225\n0x4001DBC0 READ    576612\n0x4006DD00 WRITE   576820\n0x4001DC00 READ    577207\n0x4006DD40 WRITE   577415\n0x4001DC40 READ    577802\n0x4006DD80 WRITE   578010\n0x4001DC80 READ    578397\n0x4006DDC0 WRITE   578605\n0x4001DCC0 READ    578992\n0x4006DE00 WRITE   579200\n0x4001DD00 READ    579587\n0x4006DE40 WRITE   579795\n0x4001DD40 READ    580182\n0x4001DD80 READ    580788\n0x4006DF40 WRITE   580995\n0x4001DDC0 READ    581382\n0x4006DF80 WRITE   581590\n0x4001DE00 READ    581977\n0x4006DFC0 WRITE   582185\n0x4001DE40 READ    582572\n0x4006E000 WRITE   582780\n0x4001DE80 READ    583167\n0x4006E040 WRITE   583375\n0x4001DEC0 READ    583762\n0x4006E080 WRITE   583970\n0x4001DF00 READ    584357\n0x4006E0C0 WRITE   584565\n0x4001DF40 READ    584952\n0x4006E100 WRITE   585160\n0x4001DF80 READ    585547\n0x4006E140 WRITE   585755\n0x4001DFC0 READ    586142\n0x4001E000 READ    586778\n0x4006E240 WRITE   586985\n0x4001E040 READ    587372\n0x4006E280 WRITE   587580\n0x4001E080 READ    587967\n0x4006E2C0 WRITE   588175\n0x4001E0C0 READ    588562\n0x4006E300 WRITE   588770\n0x4001E100 READ    589157\n0x4006E340 WRITE   589365\n0x4001E140 READ    589752\n0x4006E380 WRITE   589960\n0x4001E180 READ    590347\n0x4006E3C0 WRITE   590555\n0x4001E1C0 READ    590942\n0x4006E400 WRITE   591150\n0x4001E200 READ    591537\n0x4006E440 WRITE   591745\n0x4001E240 READ    592132\n0x4001E280 READ    592738\n0x4006E540 WRITE   592945\n0x4001E2C0 READ    593332\n0x4006E580 WRITE   593540\n0x4001E300 READ    593927\n0x4006E5C0 WRITE   594135\n0x4001E340 READ    594522\n0x4006E600 WRITE   594730\n0x4001E380 READ    595117\n0x4006E640 WRITE   595325\n0x4001E3C0 READ    595712\n0x4006E680 WRITE   595920\n0x4001E400 READ    596307\n0x4006E6C0 WRITE   596515\n0x4001E440 READ    596902\n0x4006E700 WRITE   597110\n0x4001E480 READ    597497\n0x4006E740 WRITE   597705\n0x4001E4C0 READ    598092\n0x4001E500 READ    598700\n0x4006E840 WRITE   598910\n0x4001E540 READ    599297\n0x4006E880 WRITE   599505\n0x4001E580 READ    599892\n0x4006E8C0 WRITE   600100\n0x4001E5C0 READ    600487\n0x4006E900 WRITE   600695\n0x4001E600 READ    601082\n0x4006E940 WRITE   601290\n0x4001E640 READ    601677\n0x4006E980 WRITE   601885\n0x4001E680 READ    602272\n0x4006E9C0 WRITE   602480\n0x4001E6C0 READ    602867\n0x4006EA00 WRITE   603075\n0x4001E700 READ    603462\n0x4006EA40 WRITE   603670\n0x4001E740 READ    604057\n0x4001E780 READ    604663\n0x4006EB40 WRITE   604870\n0x4001E7C0 READ    605257\n0x4006EB80 WRITE   605465\n0x4001E800 READ    605852\n0x4006EBC0 WRITE   606060\n0x4001E840 READ    606447\n0x4006EC00 WRITE   606655\n0x4001E880 READ    607042\n0x4006EC40 WRITE   607250\n0x4001E8C0 READ    607637\n0x4006EC80 WRITE   607845\n0x4001E900 READ    608232\n0x4006ECC0 WRITE   608440\n0x4001E940 READ    608827\n0x4006ED00 WRITE   609035\n0x4001E980 READ    609422\n0x4006ED40 WRITE   609630\n0x4001E9C0 READ    610017\n0x4001EA00 READ    610623\n0x4006EE40 WRITE   610830\n0x4001EA40 READ    611217\n0x4006EE80 WRITE   611425\n0x4001EA80 READ    611812\n0x4006EEC0 WRITE   612020\n0x4001EAC0 READ    612407\n0x4006EF00 WRITE   612615\n0x4001EB00 READ    613002\n0x4006EF40 WRITE   613210\n0x4001EB40 READ    613597\n0x4006EF80 WRITE   613805\n0x4001EB80 READ    614192\n0x4006EFC0 WRITE   614400\n0x4001EBC0 READ    614787\n0x4006F000 WRITE   614995\n0x4001EC00 READ    615382\n0x4006F040 WRITE   615590\n0x4001EC40 READ    615977\n0x4001EC80 READ    616583\n0x4006F140 WRITE   616790\n0x4001ECC0 READ    617177\n0x4006F180 WRITE   617385\n0x4001ED00 READ    617772\n0x4006F1C0 WRITE   617980\n0x4001ED40 READ    618367\n0x4006F200 WRITE   618575\n0x4001ED80 READ    618962\n0x4006F240 WRITE   619170\n0x4001EDC0 READ    619557\n0x4006F280 WRITE   619765\n0x4001EE00 READ    620152\n0x4006F2C0 WRITE   620360\n0x4001EE40 READ    620747\n0x4006F300 WRITE   620955\n0x4001EE80 READ    621342\n0x4006F340 WRITE   621550\n0x4001EEC0 READ    621937\n0x4001EF00 READ    622545\n0x4006F440 WRITE   622755\n0x4001EF40 READ    623142\n0x4006F480 WRITE   623350\n0x4001EF80 READ    623737\n0x4006F4C0 WRITE   623945\n0x4001EFC0 READ    624332\n0x4006F500 WRITE   624540\n0x4001F000 READ    624957\n0x4006F540 WRITE   625165\n0x4001F040 READ    625552\n0x4006F580 WRITE   625760\n0x4001F080 READ    626147\n0x4006F5C0 WRITE   626355\n0x4001F0C0 READ    626742\n0x4006F600 WRITE   626950\n0x4001F100 READ    627337\n0x4006F640 WRITE   627545\n0x4001F140 READ    627932\n0x4001F180 READ    628538\n0x4006F740 WRITE   628745\n0x4001F1C0 READ    629132\n0x4006F780 WRITE   629340\n0x4001F200 READ    629727\n0x4006F7C0 WRITE   629935\n0x4001F240 READ    630322\n0x4006F800 WRITE   630530\n0x4001F280 READ    630917\n0x4006F840 WRITE   631125\n0x4001F2C0 READ    631512\n0x4006F880 WRITE   631720\n0x4001F300 READ    632107\n0x4006F8C0 WRITE   632315\n0x4001F340 READ    632702\n0x4006F900 WRITE   632910\n0x4001F380 READ    633297\n0x4006F940 WRITE   633505\n0x4001F3C0 READ    633892\n0x4001F400 READ    634498\n0x4006FA40 WRITE   634705\n0x4001F440 READ    635092\n0x4006FA80 WRITE   635300\n0x4001F480 READ    635687\n0x4006FAC0 WRITE   635895\n0x4001F4C0 READ    636282\n0x4006FB00 WRITE   636490\n0x4001F500 READ    636877\n0x4006FB40 WRITE   637085\n0x4001F540 READ    637472\n0x4006FB80 WRITE   637680\n0x4001F580 READ    638067\n0x4006FBC0 WRITE   638275\n0x4001F5C0 READ    638662\n0x4006FC00 WRITE   638870\n0x4001F600 READ    639257\n0x4006FC40 WRITE   639465\n0x4001F640 READ    639852\n0x4001F680 READ    640458\n0x4006FD40 WRITE   640665\n0x4001F6C0 READ    641052\n0x4006FD80 WRITE   641260\n0x4001F700 READ    641647\n0x4006FDC0 WRITE   641855\n0x4001F740 READ    642242\n0x4006FE00 WRITE   642450\n0x4001F780 READ    642837\n0x4006FE40 WRITE   643045\n0x4001F7C0 READ    643432\n0x4006FE80 WRITE   643640\n0x4001F800 READ    644027\n0x4006FEC0 WRITE   644235\n0x4001F840 READ    644622\n0x4006FF00 WRITE   644830\n0x4001F880 READ    645217\n0x4006FF40 WRITE   645425\n0x4001F8C0 READ    645812\n0x4001F900 READ    646420\n0x40070040 WRITE   646630\n0x4001F940 READ    647017\n0x40070080 WRITE   647225\n0x4001F980 READ    647612\n0x400700C0 WRITE   647820\n0x4001F9C0 READ    648207\n0x40070100 WRITE   648415\n0x4001FA00 READ    648802\n0x40070140 WRITE   649010\n0x4001FA40 READ    649397\n0x40070180 WRITE   649605\n0x4001FA80 READ    649992\n0x400701C0 WRITE   650200\n0x4001FAC0 READ    650587\n0x40070200 WRITE   650795\n0x4001FB00 READ    651182\n0x40070240 WRITE   651390\n0x4001FB40 READ    651777\n0x4001FB80 READ    652383\n0x40070340 WRITE   652590\n0x4001FBC0 READ    652977\n0x40070380 WRITE   653185\n0x4001FC00 READ    653572\n0x400703C0 WRITE   653780\n0x4001FC40 READ    654167\n0x40070400 WRITE   654375\n0x4001FC80 READ    654762\n0x40070440 WRITE   654970\n0x4001FCC0 READ    655357\n0x40070480 WRITE   655565\n0x4001FD00 READ    655952\n0x400704C0 WRITE   656160\n0x4001FD40 READ    656547\n0x40070500 WRITE   656755\n0x4001FD80 READ    657142\n0x40070540 WRITE   657350\n0x4001FDC0 READ    657737\n0x4001FE00 READ    658343\n0x40070640 WRITE   658550\n0x4001FE40 READ    658937\n0x40070680 WRITE   659145\n0x4001FE80 READ    659532\n0x400706C0 WRITE   659740\n0x4001FEC0 READ    660127\n0x40070700 WRITE   660335\n0x4001FF00 READ    660722\n0x40070740 WRITE   660930\n0x4001FF40 READ    661317\n0x40070780 WRITE   661525\n0x4001FF80 READ    661912\n0x400707C0 WRITE   662120\n0x4001FFC0 READ    662507\n0x40070800 WRITE   662715\n0x40020000 READ    663132\n0x40070840 WRITE   663420\n0x40020040 READ    663807\n0x40020080 READ    664413\n0x40070940 WRITE   664620\n0x400200C0 READ    665007\n0x40070980 WRITE   665215\n0x40020100 READ    665602\n0x400709C0 WRITE   665810\n0x40020140 READ    666197\n0x40070A00 WRITE   666405\n0x40020180 READ    666792\n0x40070A40 WRITE   667000\n0x400201C0 READ    667387\n0x40070A80 WRITE   667595\n0x40020200 READ    667982\n0x40070AC0 WRITE   668190\n0x40020240 READ    668577\n0x40070B00 WRITE   668785\n0x40020280 READ    669172\n0x40070B40 WRITE   669380\n0x400202C0 READ    669767\n0x40020300 READ    670375\n0x40070C40 WRITE   670585\n0x40020340 READ    670972\n0x40070C80 WRITE   671180\n0x40020380 READ    671567\n0x40070CC0 WRITE   671775\n0x400203C0 READ    672162\n0x40070D00 WRITE   672370\n0x40020400 READ    672757\n0x40070D40 WRITE   672965\n0x40020440 READ    673352\n0x40070D80 WRITE   673560\n0x40020480 READ    673947\n0x40070DC0 WRITE   674155\n0x400204C0 READ    674542\n0x40070E00 WRITE   674750\n0x40020500 READ    675137\n0x40070E40 WRITE   675345\n0x40020540 READ    675732\n0x40020580 READ    676338\n0x40070F40 WRITE   676545\n0x400205C0 READ    676932\n0x40070F80 WRITE   677140\n0x40020600 READ    677527\n0x40070FC0 WRITE   677735\n0x40020640 READ    678122\n0x40071000 WRITE   678330\n0x40020680 READ    678717\n0x40071040 WRITE   678925\n0x400206C0 READ    679312\n0x40071080 WRITE   679520\n0x40020700 READ    679907\n0x400710C0 WRITE   680115\n0x40020740 READ    680502\n0x40071100 WRITE   680710\n0x40020780 READ    681097\n0x40071140 WRITE   681305\n0x400207C0 READ    681692\n0x40020800 READ    682298\n0x40071240 WRITE   682505\n0x40020840 READ    682892\n0x40071280 WRITE   683100\n0x40020880 READ    683487\n0x400712C0 WRITE   683695\n0x400208C0 READ    684082\n0x40071300 WRITE   684290\n0x40020900 READ    684677\n0x40071340 WRITE   684885\n0x40020940 READ    685272\n0x40071380 WRITE   685480\n0x40020980 READ    685867\n0x400713C0 WRITE   686075\n0x400209C0 READ    686462\n0x40071400 WRITE   686670\n0x40020A00 READ    687057\n0x40071440 WRITE   687265\n0x40020A40 READ    687652\n0x40020A80 READ    688258\n0x40071540 WRITE   688465\n0x40020AC0 READ    688852\n0x40071580 WRITE   689060\n0x40020B00 READ    689447\n0x400715C0 WRITE   689655\n0x40020B40 READ    690042\n0x40071600 WRITE   690250\n0x40020B80 READ    690637\n0x40071640 WRITE   690845\n0x40020BC0 READ    691232\n0x40071680 WRITE   691440\n0x40020C00 READ    691827\n0x400716C0 WRITE   692035\n0x40020C40 READ    692422\n0x40071700 WRITE   692630\n0x40020C80 READ    693017\n0x40071740 WRITE   693225\n0x40020CC0 READ    693612\n0x40020D00 READ    694220\n0x40071840 WRITE   694430\n0x40020D40 READ    694817\n0x40071880 WRITE   695025\n0x40020D80 READ    695412\n0x400718C0 WRITE   695620\n0x40020DC0 READ    696007\n0x40071900 WRITE   696215\n0x40020E00 READ    696602\n0x40071940 WRITE   696810\n0x40020E40 READ    697197\n0x40071980 WRITE   697405\n0x40020E80 READ    697792\n0x400719C0 WRITE   698000\n0x40020EC0 READ    698387\n0x40071A00 WRITE   698595\n0x40020F00 READ    698982\n0x40071A40 WRITE   699190\n0x40020F40 READ    699577\n0x40020F80 READ    700183\n0x40071B40 WRITE   700390\n0x40020FC0 READ    700777\n0x40071B80 WRITE   700985\n0x40021000 READ    701402\n0x40071BC0 WRITE   701610\n0x40021040 READ    701997\n0x40071C00 WRITE   702205\n0x40021080 READ    702592\n0x40071C40 WRITE   702800\n0x400210C0 READ    703187\n0x40071C80 WRITE   703395\n0x40021100 READ    703782\n0x40071CC0 WRITE   703990\n0x40021140 READ    704377\n0x40071D00 WRITE   704585\n0x40021180 READ    704972\n0x40071D40 WRITE   705180\n0x400211C0 READ    705567\n0x40021200 READ    706173\n0x40071E40 WRITE   706380\n0x40021240 READ    706767\n0x40071E80 WRITE   706975\n0x40021280 READ    707362\n0x40071EC0 WRITE   707570\n0x400212C0 READ    707957\n0x40071F00 WRITE   708165\n0x40021300 READ    708552\n0x40071F40 WRITE   708760\n0x40021340 READ    709147\n0x40071F80 WRITE   709355\n0x40021380 READ    709742\n0x40071FC0 WRITE   709950\n0x400213C0 READ    710337\n0x40072000 WRITE   710545\n0x40021400 READ    710932\n0x40072040 WRITE   711140\n0x40021440 READ    711527\n0x40021480 READ    712133\n0x40072140 WRITE   712340\n0x400214C0 READ    712727\n0x40072180 WRITE   712935\n0x40021500 READ    713322\n0x400721C0 WRITE   713530\n0x40021540 READ    713917\n0x40072200 WRITE   714125\n0x40021580 READ    714512\n0x40072240 WRITE   714720\n0x400215C0 READ    715107\n0x40072280 WRITE   715315\n0x40021600 READ    715702\n0x400722C0 WRITE   715910\n0x40021640 READ    716297\n0x40072300 WRITE   716505\n0x40021680 READ    716892\n0x40072340 WRITE   717100\n0x400216C0 READ    717487\n0x40021700 READ    718095\n0x40072440 WRITE   718305\n0x40021740 READ    718692\n0x40072480 WRITE   718900\n0x40021780 READ    719287\n0x400724C0 WRITE   719495\n0x400217C0 READ    719882\n0x40072500 WRITE   720090\n0x40021800 READ    720477\n0x40072540 WRITE   720685\n0x40021840 READ    721072\n0x40072580 WRITE   721280\n0x40021880 READ    721667\n0x400725C0 WRITE   721875\n0x400218C0 READ    722262\n0x40072600 WRITE   722470\n0x40021900 READ    722857\n0x40072640 WRITE   723065\n0x40021940 READ    723452\n0x40021980 READ    724058\n0x40072740 WRITE   724265\n0x400219C0 READ    724652\n0x40072780 WRITE   724860\n0x40021A00 READ    725247\n0x400727C0 WRITE   725455\n0x40021A40 READ    725842\n0x40072800 WRITE   726050\n0x40021A80 READ    726437\n0x40072840 WRITE   726645\n0x40021AC0 READ    727032\n0x40072880 WRITE   727240\n0x40021B00 READ    727627\n0x400728C0 WRITE   727835\n0x40021B40 READ    728222\n0x40072900 WRITE   728430\n0x40021B80 READ    728817\n0x40072940 WRITE   729025\n0x40021BC0 READ    729412\n0x40021C00 READ    730018\n0x40072A40 WRITE   730225\n0x40021C40 READ    730612\n0x40072A80 WRITE   730820\n0x40021C80 READ    731207\n0x40072AC0 WRITE   731415\n0x40021CC0 READ    731802\n0x40072B00 WRITE   732010\n0x40021D00 READ    732397\n0x40072B40 WRITE   732605\n0x40021D40 READ    732992\n0x40072B80 WRITE   733200\n0x40021D80 READ    733587\n0x40072BC0 WRITE   733795\n0x40021DC0 READ    734182\n0x40072C00 WRITE   734390\n0x40021E00 READ    734777\n0x40072C40 WRITE   734985\n0x40021E40 READ    735372\n0x40021E80 READ    735978\n0x40072D40 WRITE   736185\n0x40021EC0 READ    736572\n0x40072D80 WRITE   736780\n0x40021F00 READ    737167\n0x40072DC0 WRITE   737375\n0x40021F40 READ    737762\n0x40072E00 WRITE   737970\n0x40021F80 READ    738357\n0x40072E40 WRITE   738565\n0x40021FC0 READ    738952\n0x40072E80 WRITE   739160\n0x40022000 READ    739577\n0x40072EC0 WRITE   739785\n0x40022040 READ    740172\n0x40072F00 WRITE   740380\n0x40022080 READ    740767\n0x40072F40 WRITE   740975\n0x400220C0 READ    741362\n0x40022100 READ    741970\n0x40073040 WRITE   742180\n0x40022140 READ    742567\n0x40073080 WRITE   742775\n0x40022180 READ    743162\n0x400730C0 WRITE   743370\n0x400221C0 READ    743757\n0x40073100 WRITE   743965\n0x40022200 READ    744352\n0x40073140 WRITE   744560\n0x40022240 READ    744947\n0x40073180 WRITE   745155\n0x40022280 READ    745542\n0x400731C0 WRITE   745750\n0x400222C0 READ    746137\n0x40073200 WRITE   746345\n0x40022300 READ    746732\n0x40073240 WRITE   746940\n0x40022340 READ    747327\n0x40022380 READ    747933\n0x40073340 WRITE   748140\n0x400223C0 READ    748527\n0x40073380 WRITE   748735\n0x40022400 READ    749122\n0x400733C0 WRITE   749330\n0x40022440 READ    749717\n0x40073400 WRITE   749925\n0x40022480 READ    750312\n0x40073440 WRITE   750520\n0x400224C0 READ    750907\n0x40073480 WRITE   751115\n0x40022500 READ    751502\n0x400734C0 WRITE   751710\n0x40022540 READ    752097\n0x40073500 WRITE   752305\n0x40022580 READ    752692\n0x40073540 WRITE   752900\n0x400225C0 READ    753287\n0x40022600 READ    753893\n0x40073640 WRITE   754100\n0x40022640 READ    754487\n0x40073680 WRITE   754695\n0x40022680 READ    755082\n0x400736C0 WRITE   755290\n0x400226C0 READ    755677\n0x40073700 WRITE   755885\n0x40022700 READ    756272\n0x40073740 WRITE   756480\n0x40022740 READ    756867\n0x40073780 WRITE   757075\n0x40022780 READ    757462\n0x400737C0 WRITE   757670\n0x400227C0 READ    758057\n0x40073800 WRITE   758265\n0x40022800 READ    758652\n0x40073840 WRITE   758860\n0x40022840 READ    759247\n0x40022880 READ    759853\n0x40073940 WRITE   760060\n0x400228C0 READ    760447\n0x40073980 WRITE   760655\n0x40022900 READ    761042\n0x400739C0 WRITE   761250\n0x40022940 READ    761637\n0x40073A00 WRITE   761845\n0x40022980 READ    762232\n0x40073A40 WRITE   762440\n0x400229C0 READ    762827\n0x40073A80 WRITE   763035\n0x40022A00 READ    763422\n0x40073AC0 WRITE   763630\n0x40022A40 READ    764017\n0x40073B00 WRITE   764225\n0x40022A80 READ    764612\n0x40073B40 WRITE   764820\n0x40022AC0 READ    765207\n0x40022B00 READ    765815\n0x40073C40 WRITE   766025\n0x40022B40 READ    766412\n0x40073C80 WRITE   766620\n0x40022B80 READ    767007\n0x40073CC0 WRITE   767215\n0x40022BC0 READ    767602\n0x40073D00 WRITE   767810\n0x40022C00 READ    768197\n0x40073D40 WRITE   768405\n0x40022C40 READ    768792\n0x40073D80 WRITE   769000\n0x40022C80 READ    769387\n0x40073DC0 WRITE   769595\n0x40022CC0 READ    769982\n0x40073E00 WRITE   770190\n0x40022D00 READ    770577\n0x40073E40 WRITE   770785\n0x40022D40 READ    771172\n0x40022D80 READ    771778\n0x40073F40 WRITE   771985\n0x40022DC0 READ    772372\n0x40073F80 WRITE   772580\n0x40022E00 READ    772967\n0x40073FC0 WRITE   773175\n0x40022E40 READ    773562\n0x40074000 WRITE   773770\n0x40022E80 READ    774157\n0x40074040 WRITE   774365\n0x40022EC0 READ    774752\n0x40074080 WRITE   774960\n0x40022F00 READ    775347\n0x400740C0 WRITE   775555\n0x40022F40 READ    775942\n0x40074100 WRITE   776150\n0x40022F80 READ    776537\n0x40074140 WRITE   776745\n0x40022FC0 READ    777132\n0x40023000 READ    777768\n0x40074240 WRITE   777975\n0x40023040 READ    778362\n0x40074280 WRITE   778570\n0x40023080 READ    778957\n0x400742C0 WRITE   779165\n0x400230C0 READ    779552\n0x40074300 WRITE   779760\n0x40023100 READ    780147\n0x40074340 WRITE   780355\n0x40023140 READ    780742\n0x40074380 WRITE   780950\n0x40023180 READ    781337\n0x400743C0 WRITE   781545\n0x400231C0 READ    781932\n0x40074400 WRITE   782140\n0x40023200 READ    782527\n0x40074440 WRITE   782735\n0x40023240 READ    783122\n0x40023280 READ    783728\n0x40074540 WRITE   783935\n0x400232C0 READ    784322\n0x40074580 WRITE   784530\n0x40023300 READ    784917\n0x400745C0 WRITE   785125\n0x40023340 READ    785512\n0x40074600 WRITE   785720\n0x40023380 READ    786107\n0x40074640 WRITE   786315\n0x400233C0 READ    786702\n0x40074680 WRITE   786910\n0x40023400 READ    787297\n0x400746C0 WRITE   787505\n0x40023440 READ    787892\n0x40074700 WRITE   788100\n0x40023480 READ    788487\n0x40074740 WRITE   788695\n0x400234C0 READ    789082\n0x40023500 READ    789690\n0x40074840 WRITE   789900\n0x40023540 READ    790287\n0x40074880 WRITE   790495\n0x40023580 READ    790882\n0x400748C0 WRITE   791090\n0x400235C0 READ    791477\n0x40074900 WRITE   791685\n0x40023600 READ    792072\n0x40074940 WRITE   792280\n0x40023640 READ    792667\n0x40074980 WRITE   792875\n0x40023680 READ    793262\n0x400749C0 WRITE   793470\n0x400236C0 READ    793857\n0x40074A00 WRITE   794065\n0x40023700 READ    794452\n0x40074A40 WRITE   794660\n0x40023740 READ    795047\n0x40023780 READ    795653\n0x40074B40 WRITE   795860\n0x400237C0 READ    796247\n0x40074B80 WRITE   796455\n0x40023800 READ    796842\n0x40074BC0 WRITE   797050\n0x40023840 READ    797437\n0x40074C00 WRITE   797645\n0x40023880 READ    798032\n0x40074C40 WRITE   798240\n0x400238C0 READ    798627\n0x40074C80 WRITE   798835\n0x40023900 READ    799222\n0x40074CC0 WRITE   799430\n0x40023940 READ    799817\n0x40074D00 WRITE   800025\n0x40023980 READ    800412\n0x40074D40 WRITE   800620\n0x400239C0 READ    801007\n0x40023A00 READ    801613\n0x40074E40 WRITE   801820\n0x40023A40 READ    802207\n0x40074E80 WRITE   802415\n0x40023A80 READ    802802\n0x40074EC0 WRITE   803010\n0x40023AC0 READ    803397\n0x40074F00 WRITE   803605\n0x40023B00 READ    803992\n0x40074F40 WRITE   804200\n0x40023B40 READ    804587\n0x40074F80 WRITE   804795\n0x40023B80 READ    805182\n0x40074FC0 WRITE   805390\n0x40023BC0 READ    805777\n0x40075000 WRITE   805985\n0x40023C00 READ    806372\n0x40075040 WRITE   806580\n0x40023C40 READ    806967\n0x40023C80 READ    807573\n0x40075140 WRITE   807780\n0x40023CC0 READ    808167\n0x40075180 WRITE   808375\n0x40023D00 READ    808762\n0x400751C0 WRITE   808970\n0x40023D40 READ    809357\n0x40075200 WRITE   809565\n0x40023D80 READ    809952\n0x40075240 WRITE   810160\n0x40023DC0 READ    810547\n0x40075280 WRITE   810755\n0x40023E00 READ    811142\n0x400752C0 WRITE   811350\n0x40023E40 READ    811737\n0x40075300 WRITE   811945\n0x40023E80 READ    812332\n0x40075340 WRITE   812540\n0x40023EC0 READ    812927\n0x40023F00 READ    813535\n0x40075440 WRITE   813745\n0x40023F40 READ    814132\n0x40075480 WRITE   814340\n0x40023F80 READ    814727\n0x400754C0 WRITE   814935\n0x40023FC0 READ    815322\n0x40075500 WRITE   815530\n0x40024000 READ    815947\n0x40075540 WRITE   816235\n0x40024040 READ    816622\n0x40075580 WRITE   816830\n0x40024080 READ    817217\n0x400755C0 WRITE   817425\n0x400240C0 READ    817812\n0x40075600 WRITE   818020\n0x40024100 READ    818407\n0x40075640 WRITE   818615\n0x40024140 READ    819002\n0x40024180 READ    819608\n0x40075740 WRITE   819815\n0x400241C0 READ    820202\n0x40075780 WRITE   820410\n0x40024200 READ    820797\n0x400757C0 WRITE   821005\n0x40024240 READ    821392\n0x40075800 WRITE   821600\n0x40024280 READ    821987\n0x40075840 WRITE   822195\n0x400242C0 READ    822582\n0x40075880 WRITE   822790\n0x40024300 READ    823177\n0x400758C0 WRITE   823385\n0x40024340 READ    823772\n0x40075900 WRITE   823980\n0x40024380 READ    824367\n0x40075940 WRITE   824575\n0x400243C0 READ    824962\n0x40024400 READ    825568\n0x40075A40 WRITE   825775\n0x40024440 READ    826162\n0x40075A80 WRITE   826370\n0x40024480 READ    826757\n0x40075AC0 WRITE   826965\n0x400244C0 READ    827352\n0x40075B00 WRITE   827560\n0x40024500 READ    827947\n0x40075B40 WRITE   828155\n0x40024540 READ    828542\n0x40075B80 WRITE   828750\n0x40024580 READ    829137\n0x40075BC0 WRITE   829345\n0x400245C0 READ    829732\n0x40075C00 WRITE   829940\n0x40024600 READ    830327\n0x40075C40 WRITE   830535\n0x40024640 READ    830922\n0x40024680 READ    831528\n0x40075D40 WRITE   831735\n0x400246C0 READ    832122\n0x40075D80 WRITE   832330\n0x40024700 READ    832717\n0x40075DC0 WRITE   832925\n0x40024740 READ    833312\n0x40075E00 WRITE   833520\n0x40024780 READ    833907\n0x40075E40 WRITE   834115\n0x400247C0 READ    834502\n0x40075E80 WRITE   834710\n0x40024800 READ    835097\n0x40075EC0 WRITE   835305\n0x40024840 READ    835692\n0x40075F00 WRITE   835900\n0x40024880 READ    836287\n0x40075F40 WRITE   836495\n0x400248C0 READ    836882\n0x40024900 READ    837490\n0x40076040 WRITE   837700\n0x40024940 READ    838087\n0x40076080 WRITE   838295\n0x40024980 READ    838682\n0x400760C0 WRITE   838890\n0x400249C0 READ    839277\n0x40076100 WRITE   839485\n0x40024A00 READ    839872\n0x40076140 WRITE   840080\n0x40024A40 READ    840467\n0x40076180 WRITE   840675\n0x40024A80 READ    841062\n0x400761C0 WRITE   841270\n0x40024AC0 READ    841657\n0x40076200 WRITE   841865\n0x40024B00 READ    842252\n0x40076240 WRITE   842460\n0x40024B40 READ    842847\n0x40024B80 READ    843453\n0x40076340 WRITE   843660\n0x40024BC0 READ    844047\n0x40076380 WRITE   844255\n0x40024C00 READ    844642\n0x400763C0 WRITE   844850\n0x40024C40 READ    845237\n0x40076400 WRITE   845445\n0x40024C80 READ    845832\n0x40076440 WRITE   846040\n0x40024CC0 READ    846427\n0x40076480 WRITE   846635\n0x40024D00 READ    847022\n0x400764C0 WRITE   847230\n0x40024D40 READ    847617\n0x40076500 WRITE   847825\n0x40024D80 READ    848212\n0x40076540 WRITE   848420\n0x40024DC0 READ    848807\n0x40024E00 READ    849413\n0x40076640 WRITE   849620\n0x40024E40 READ    850007\n0x40076680 WRITE   850215\n0x40024E80 READ    850602\n0x400766C0 WRITE   850810\n0x40024EC0 READ    851197\n0x40076700 WRITE   851405\n0x40024F00 READ    851792\n0x40076740 WRITE   852000\n0x40024F40 READ    852387\n0x40076780 WRITE   852595\n0x40024F80 READ    852982\n0x400767C0 WRITE   853190\n0x40024FC0 READ    853577\n0x40076800 WRITE   853785\n0x40025000 READ    854202\n0x40076840 WRITE   854410\n0x40025040 READ    854797\n0x40025080 READ    855403\n0x40076940 WRITE   855610\n0x400250C0 READ    855997\n0x40076980 WRITE   856205\n0x40025100 READ    856592\n0x400769C0 WRITE   856800\n0x40025140 READ    857187\n0x40076A00 WRITE   857395\n0x40025180 READ    857782\n0x40076A40 WRITE   857990\n0x400251C0 READ    858377\n0x40076A80 WRITE   858585\n0x40025200 READ    858972\n0x40076AC0 WRITE   859180\n0x40025240 READ    859567\n0x40076B00 WRITE   859775\n0x40025280 READ    860162\n0x40076B40 WRITE   860370\n0x400252C0 READ    860757\n0x40025300 READ    861365\n0x40076C40 WRITE   861575\n0x40025340 READ    861962\n0x40076C80 WRITE   862170\n0x40025380 READ    862557\n0x40076CC0 WRITE   862765\n0x400253C0 READ    863152\n0x40076D00 WRITE   863360\n0x40025400 READ    863747\n0x40076D40 WRITE   863955\n0x40025440 READ    864342\n0x40076D80 WRITE   864550\n0x40025480 READ    864937\n0x40076DC0 WRITE   865145\n0x400254C0 READ    865532\n0x40076E00 WRITE   865740\n0x40025500 READ    866127\n0x40076E40 WRITE   866335\n0x40025540 READ    866722\n0x40025580 READ    867328\n0x40076F40 WRITE   867535\n0x400255C0 READ    867922\n0x40076F80 WRITE   868130\n0x40025600 READ    868517\n0x40076FC0 WRITE   868725\n0x40025640 READ    869112\n0x40077000 WRITE   869320\n0x40025680 READ    869707\n0x40077040 WRITE   869915\n0x400256C0 READ    870302\n0x40077080 WRITE   870510\n0x40025700 READ    870897\n0x400770C0 WRITE   871105\n0x40025740 READ    871492\n0x40077100 WRITE   871700\n0x40025780 READ    872087\n0x40077140 WRITE   872295\n0x400257C0 READ    872682\n0x40025800 READ    873288\n0x40077240 WRITE   873495\n0x40025840 READ    873882\n0x40077280 WRITE   874090\n0x40025880 READ    874477\n0x400772C0 WRITE   874685\n0x400258C0 READ    875072\n0x40077300 WRITE   875280\n0x40025900 READ    875667\n0x40077340 WRITE   875875\n0x40025940 READ    876262\n0x40077380 WRITE   876470\n0x40025980 READ    876857\n0x400773C0 WRITE   877065\n0x400259C0 READ    877452\n0x40077400 WRITE   877660\n0x40025A00 READ    878047\n0x40077440 WRITE   878255\n0x40025A40 READ    878642\n0x40025A80 READ    879248\n0x40077540 WRITE   879455\n0x40025AC0 READ    879842\n0x40077580 WRITE   880050\n0x40025B00 READ    880437\n0x400775C0 WRITE   880645\n0x40025B40 READ    881032\n0x40077600 WRITE   881240\n0x40025B80 READ    881627\n0x40077640 WRITE   881835\n0x40025BC0 READ    882222\n0x40077680 WRITE   882430\n0x40025C00 READ    882817\n0x400776C0 WRITE   883025\n0x40025C40 READ    883412\n0x40077700 WRITE   883620\n0x40025C80 READ    884007\n0x40077740 WRITE   884215\n0x40025CC0 READ    884602\n0x40025D00 READ    885210\n0x40077840 WRITE   885420\n0x40025D40 READ    885807\n0x40077880 WRITE   886015\n0x40025D80 READ    886402\n0x400778C0 WRITE   886610\n0x40025DC0 READ    886997\n0x40077900 WRITE   887205\n0x40025E00 READ    887592\n0x40077940 WRITE   887800\n0x40025E40 READ    888187\n0x40077980 WRITE   888395\n0x40025E80 READ    888782\n0x400779C0 WRITE   888990\n0x40025EC0 READ    889377\n0x40077A00 WRITE   889585\n0x40025F00 READ    889972\n0x40077A40 WRITE   890180\n0x40025F40 READ    890567\n0x40025F80 READ    891173\n0x40077B40 WRITE   891380\n0x40025FC0 READ    891767\n0x40077B80 WRITE   891975\n0x40026000 READ    892392\n0x40077BC0 WRITE   892600\n0x40026040 READ    892987\n0x40077C00 WRITE   893195\n0x40026080 READ    893582\n0x40077C40 WRITE   893790\n0x400260C0 READ    894177\n0x40077C80 WRITE   894385\n0x40026100 READ    894772\n0x40077CC0 WRITE   894980\n0x40026140 READ    895367\n0x40077D00 WRITE   895575\n0x40026180 READ    895962\n0x40077D40 WRITE   896170\n0x400261C0 READ    896557\n0x40026200 READ    897163\n0x40077E40 WRITE   897370\n0x40026240 READ    897757\n0x40077E80 WRITE   897965\n0x40026280 READ    898352\n0x40077EC0 WRITE   898560\n0x400262C0 READ    898947\n0x40077F00 WRITE   899155\n0x40026300 READ    899542\n0x40077F40 WRITE   899750\n0x40026340 READ    900137\n0x40077F80 WRITE   900345\n0x40026380 READ    900732\n0x40077FC0 WRITE   900940\n0x400263C0 READ    901327\n0x40078000 WRITE   901535\n0x40026400 READ    901922\n0x40078040 WRITE   902130\n0x40026440 READ    902517\n0x40026480 READ    903123\n0x40078140 WRITE   903330\n0x400264C0 READ    903717\n0x40078180 WRITE   903925\n0x40026500 READ    904312\n0x400781C0 WRITE   904520\n0x40026540 READ    904907\n0x40078200 WRITE   905115\n0x40026580 READ    905502\n0x40078240 WRITE   905710\n0x400265C0 READ    906097\n0x40078280 WRITE   906305\n0x40026600 READ    906692\n0x400782C0 WRITE   906900\n0x40026640 READ    907287\n0x40078300 WRITE   907495\n0x40026680 READ    907882\n0x40078340 WRITE   908090\n0x400266C0 READ    908477\n0x40026700 READ    909085\n0x40078440 WRITE   909295\n0x40026740 READ    909682\n0x40078480 WRITE   909890\n0x40026780 READ    910277\n0x400784C0 WRITE   910485\n0x400267C0 READ    910872\n0x40078500 WRITE   911080\n0x40026800 READ    911467\n0x40078540 WRITE   911675\n0x40026840 READ    912062\n0x40078580 WRITE   912270\n0x40026880 READ    912657\n0x400785C0 WRITE   912865\n0x400268C0 READ    913252\n0x40078600 WRITE   913460\n0x40026900 READ    913847\n0x40078640 WRITE   914055\n0x40026940 READ    914442\n0x40026980 READ    915048\n0x40078740 WRITE   915255\n0x400269C0 READ    915642\n0x40078780 WRITE   915850\n0x40026A00 READ    916237\n0x400787C0 WRITE   916445\n0x40026A40 READ    916832\n0x40078800 WRITE   917040\n0x40026A80 READ    917427\n0x40078840 WRITE   917635\n0x40026AC0 READ    918022\n0x40026B00 READ    918617\n0x400788C0 WRITE   918825\n0x40026B40 READ    919212\n0x40078900 WRITE   919420\n0x40026B80 READ    919807\n0x40078940 WRITE   920015\n0x40026BC0 READ    920402\n0x40026C00 READ    921008\n0x40078A40 WRITE   921215\n0x40026C40 READ    921602\n0x40078A80 WRITE   921810\n0x40026C80 READ    922197\n0x40078AC0 WRITE   922405\n0x40026CC0 READ    922792\n0x40078B00 WRITE   923000\n0x40026D00 READ    923387\n0x40078B40 WRITE   923595\n0x40026D40 READ    923982\n0x40078B80 WRITE   924190\n0x40026D80 READ    924577\n0x40078BC0 WRITE   924785\n0x40026DC0 READ    925172\n0x40078C00 WRITE   925380\n0x40026E00 READ    925767\n0x40078C40 WRITE   925975\n0x40026E40 READ    926362\n0x40026E80 READ    926968\n0x40078D40 WRITE   927175\n0x40026EC0 READ    927562\n0x40078D80 WRITE   927770\n0x40026F00 READ    928157\n0x40078DC0 WRITE   928365\n0x40026F40 READ    928752\n0x40078E00 WRITE   928960\n0x40026F80 READ    929347\n0x40078E40 WRITE   929555\n0x40026FC0 READ    929942\n0x40078E80 WRITE   930150\n0x40027000 READ    930567\n0x40078EC0 WRITE   930775\n0x40027040 READ    931162\n0x40078F00 WRITE   931370\n0x40027080 READ    931757\n0x40078F40 WRITE   931965\n0x400270C0 READ    932352\n0x40027100 READ    932960\n0x40079040 WRITE   933170\n0x40027140 READ    933557\n0x40079080 WRITE   933765\n0x40027180 READ    934152\n0x400790C0 WRITE   934360\n0x400271C0 READ    934747\n0x40079100 WRITE   934955\n0x40027200 READ    935342\n0x40079140 WRITE   935550\n0x40027240 READ    935937\n0x40079180 WRITE   936145\n0x40027280 READ    936532\n0x400791C0 WRITE   936740\n0x400272C0 READ    937127\n0x40079200 WRITE   937335\n0x40027300 READ    937722\n0x40079240 WRITE   937930\n0x40027340 READ    938317\n0x40027380 READ    938923\n0x40079340 WRITE   939130\n0x400273C0 READ    939517\n0x40079380 WRITE   939725\n0x40027400 READ    940112\n0x400793C0 WRITE   940320\n0x40027440 READ    940707\n0x40079400 WRITE   940915\n0x40027480 READ    941302\n0x40079440 WRITE   941510\n0x400274C0 READ    941897\n0x40079480 WRITE   942105\n0x40027500 READ    942492\n0x400794C0 WRITE   942700\n0x40027540 READ    943087\n0x40079500 WRITE   943295\n0x40027580 READ    943682\n0x40079540 WRITE   943890\n0x400275C0 READ    944277\n0x40027600 READ    944883\n0x40079640 WRITE   945090\n0x40027640 READ    945477\n0x40079680 WRITE   945685\n0x40027680 READ    946072\n0x400796C0 WRITE   946280\n0x400276C0 READ    946667\n0x40079700 WRITE   946875\n0x40027700 READ    947262\n0x40079740 WRITE   947470\n0x40027740 READ    947857\n0x40079780 WRITE   948065\n0x40027780 READ    948452\n0x400797C0 WRITE   948660\n0x400277C0 READ    949047\n0x40079800 WRITE   949255\n0x40027800 READ    949642\n0x40079840 WRITE   949850\n0x40027840 READ    950237\n0x40027880 READ    950843\n0x40079940 WRITE   951050\n0x400278C0 READ    951437\n0x40079980 WRITE   951645\n0x40027900 READ    952032\n0x400799C0 WRITE   952240\n0x40027940 READ    952627\n0x40079A00 WRITE   952835\n0x40027980 READ    953222\n0x40079A40 WRITE   953430\n0x400279C0 READ    953817\n0x40079A80 WRITE   954025\n0x40027A00 READ    954412\n0x40079AC0 WRITE   954620\n0x40027A40 READ    955007\n0x40079B00 WRITE   955215\n0x40027A80 READ    955602\n0x40079B40 WRITE   955810\n0x40027AC0 READ    956197\n0x40027B00 READ    956805\n0x40079C40 WRITE   957015\n0x40027B40 READ    957402\n0x40079C80 WRITE   957610\n0x40027B80 READ    957997\n0x40079CC0 WRITE   958205\n0x40027BC0 READ    958592\n0x40079D00 WRITE   958800\n0x40027C00 READ    959187\n0x40079D40 WRITE   959395\n0x40027C40 READ    959782\n0x40079D80 WRITE   959990\n0x40027C80 READ    960377\n0x40079DC0 WRITE   960585\n0x40027CC0 READ    960972\n0x40079E00 WRITE   961180\n0x40027D00 READ    961567\n0x40079E40 WRITE   961775\n0x40027D40 READ    962162\n0x40027D80 READ    962768\n0x40079F40 WRITE   962975\n0x40027DC0 READ    963362\n0x40079F80 WRITE   963570\n0x40027E00 READ    963957\n0x40079FC0 WRITE   964165\n0x40027E40 READ    964552\n0x4007A000 WRITE   964760\n0x40027E80 READ    965147\n0x4007A040 WRITE   965355\n0x40027EC0 READ    965742\n0x4007A080 WRITE   965950\n0x40027F00 READ    966337\n0x4007A0C0 WRITE   966545\n0x40027F40 READ    966932\n0x4007A100 WRITE   967140\n0x40027F80 READ    967527\n0x4007A140 WRITE   967735\n0x40027FC0 READ    968122\n0x40028000 READ    968758\n0x4007A240 WRITE   969045\n0x40028040 READ    969432\n0x4007A280 WRITE   969640\n0x40028080 READ    970027\n0x4007A2C0 WRITE   970235\n0x400280C0 READ    970622\n0x4007A300 WRITE   970830\n0x40028100 READ    971217\n0x4007A340 WRITE   971425\n0x40028140 READ    971812\n0x4007A380 WRITE   972020\n0x40028180 READ    972407\n0x4007A3C0 WRITE   972615\n0x400281C0 READ    973002\n0x4007A400 WRITE   973210\n0x40028200 READ    973597\n0x4007A440 WRITE   973805\n0x40028240 READ    974192\n0x40028280 READ    974798\n0x4007A540 WRITE   975005\n0x400282C0 READ    975392\n0x4007A580 WRITE   975600\n0x40028300 READ    975987\n0x4007A5C0 WRITE   976195\n0x40028340 READ    976582\n0x4007A600 WRITE   976790\n0x40028380 READ    977177\n0x4007A640 WRITE   977385\n0x400283C0 READ    977772\n0x4007A680 WRITE   977980\n0x40028400 READ    978367\n0x4007A6C0 WRITE   978575\n0x40028440 READ    978962\n0x4007A700 WRITE   979170\n0x40028480 READ    979557\n0x4007A740 WRITE   979765\n0x400284C0 READ    980152\n0x40028500 READ    980760\n0x4007A840 WRITE   980970\n0x40028540 READ    981357\n0x4007A880 WRITE   981565\n0x40028580 READ    981952\n0x4007A8C0 WRITE   982160\n0x400285C0 READ    982547\n0x4007A900 WRITE   982755\n0x40028600 READ    983142\n0x4007A940 WRITE   983350\n0x40028640 READ    983737\n0x4007A980 WRITE   983945\n0x40028680 READ    984332\n0x4007A9C0 WRITE   984540\n0x400286C0 READ    984927\n0x4007AA00 WRITE   985135\n0x40028700 READ    985522\n0x4007AA40 WRITE   985730\n0x40028740 READ    986117\n0x40028780 READ    986723\n0x4007AB40 WRITE   986930\n0x400287C0 READ    987317\n0x4007AB80 WRITE   987525\n0x40028800 READ    987912\n0x4007ABC0 WRITE   988120\n0x40028840 READ    988507\n0x4007AC00 WRITE   988715\n0x40028880 READ    989102\n0x4007AC40 WRITE   989310\n0x400288C0 READ    989697\n0x4007AC80 WRITE   989905\n0x40028900 READ    990292\n0x4007ACC0 WRITE   990500\n0x40028940 READ    990887\n0x4007AD00 WRITE   991095\n0x40028980 READ    991482\n0x4007AD40 WRITE   991690\n0x400289C0 READ    992077\n0x40028A00 READ    992683\n0x4007AE40 WRITE   992890\n0x40028A40 READ    993277\n0x4007AE80 WRITE   993485\n0x40028A80 READ    993872\n0x4007AEC0 WRITE   994080\n0x40028AC0 READ    994467\n0x4007AF00 WRITE   994675\n0x40028B00 READ    995062\n0x4007AF40 WRITE   995270\n0x40028B40 READ    995657\n0x4007AF80 WRITE   995865\n0x40028B80 READ    996252\n0x4007AFC0 WRITE   996460\n0x40028BC0 READ    996847\n0x4007B000 WRITE   997055\n0x40028C00 READ    997442\n0x4007B040 WRITE   997650\n0x40028C40 READ    998037\n0x40028C80 READ    998643\n0x4007B140 WRITE   998850\n0x40028CC0 READ    999237\n0x4007B180 WRITE   999445\n0x40028D00 READ    999832\n0x4007B1C0 WRITE   1000040\n0x40028D40 READ    1000427\n0x4007B200 WRITE   1000635\n0x40028D80 READ    1001022\n0x4007B240 WRITE   1001230\n0x40028DC0 READ    1001617\n0x4007B280 WRITE   1001825\n0x40028E00 READ    1002212\n0x4007B2C0 WRITE   1002420\n0x40028E40 READ    1002807\n0x4007B300 WRITE   1003015\n0x40028E80 READ    1003402\n0x4007B340 WRITE   1003610\n0x40028EC0 READ    1003997\n0x40028F00 READ    1004605\n0x4007B440 WRITE   1004815\n0x40028F40 READ    1005202\n0x4007B480 WRITE   1005410\n0x40028F80 READ    1005797\n0x4007B4C0 WRITE   1006005\n0x40028FC0 READ    1006392\n0x4007B500 WRITE   1006600\n0x40029000 READ    1007017\n0x4007B540 WRITE   1007225\n0x40029040 READ    1007612\n0x4007B580 WRITE   1007820\n0x40029080 READ    1008207\n0x4007B5C0 WRITE   1008415\n0x400290C0 READ    1008802\n0x4007B600 WRITE   1009010\n0x40029100 READ    1009397\n0x4007B640 WRITE   1009605\n0x40029140 READ    1009992\n0x40029180 READ    1010598\n0x4007B740 WRITE   1010805\n0x400291C0 READ    1011192\n0x4007B780 WRITE   1011400\n0x40029200 READ    1011787\n0x4007B7C0 WRITE   1011995\n0x40029240 READ    1012382\n0x4007B800 WRITE   1012590\n0x40029280 READ    1012977\n0x4007B840 WRITE   1013185\n0x400292C0 READ    1013572\n0x4007B880 WRITE   1013780\n0x40029300 READ    1014167\n0x4007B8C0 WRITE   1014375\n0x40029340 READ    1014762\n0x4007B900 WRITE   1014970\n0x40029380 READ    1015357\n0x4007B940 WRITE   1015565\n0x400293C0 READ    1015952\n0x40029400 READ    1016558\n0x4007BA40 WRITE   1016765\n0x40029440 READ    1017152\n0x4007BA80 WRITE   1017360\n0x40029480 READ    1017747\n0x4007BAC0 WRITE   1017955\n0x400294C0 READ    1018342\n0x4007BB00 WRITE   1018550\n0x40029500 READ    1018937\n0x4007BB40 WRITE   1019145\n0x40029540 READ    1019532\n0x4007BB80 WRITE   1019740\n0x40029580 READ    1020127\n0x4007BBC0 WRITE   1020335\n0x400295C0 READ    1020722\n0x4007BC00 WRITE   1020930\n0x40029600 READ    1021317\n0x4007BC40 WRITE   1021525\n0x40029640 READ    1021912\n0x40029680 READ    1022518\n0x4007BD40 WRITE   1022725\n0x400296C0 READ    1023112\n0x4007BD80 WRITE   1023320\n0x40029700 READ    1023707\n0x4007BDC0 WRITE   1023915\n0x40029740 READ    1024302\n0x4007BE00 WRITE   1024510\n0x40029780 READ    1024897\n0x4007BE40 WRITE   1025105\n0x400297C0 READ    1025492\n0x4007BE80 WRITE   1025700\n0x40029800 READ    1026087\n0x4007BEC0 WRITE   1026295\n0x40029840 READ    1026682\n0x4007BF00 WRITE   1026890\n0x40029880 READ    1027277\n0x4007BF40 WRITE   1027485\n0x400298C0 READ    1027872\n0x40029900 READ    1028480\n0x4007C040 WRITE   1028690\n0x40029940 READ    1029077\n0x4007C080 WRITE   1029285\n0x40029980 READ    1029672\n0x4007C0C0 WRITE   1029880\n0x400299C0 READ    1030267\n0x4007C100 WRITE   1030475\n0x40029A00 READ    1030862\n0x4007C140 WRITE   1031070\n0x40029A40 READ    1031457\n0x4007C180 WRITE   1031665\n0x40029A80 READ    1032052\n0x4007C1C0 WRITE   1032260\n0x40029AC0 READ    1032647\n0x4007C200 WRITE   1032855\n0x40029B00 READ    1033242\n0x4007C240 WRITE   1033450\n0x40029B40 READ    1033837\n0x40029B80 READ    1034443\n0x4007C340 WRITE   1034650\n0x40029BC0 READ    1035037\n0x4007C380 WRITE   1035245\n0x40029C00 READ    1035632\n0x4007C3C0 WRITE   1035840\n0x40029C40 READ    1036227\n0x4007C400 WRITE   1036435\n0x40029C80 READ    1036822\n0x4007C440 WRITE   1037030\n0x40029CC0 READ    1037417\n0x4007C480 WRITE   1037625\n0x40029D00 READ    1038012\n0x4007C4C0 WRITE   1038220\n0x40029D40 READ    1038607\n0x4007C500 WRITE   1038815\n0x40029D80 READ    1039202\n0x4007C540 WRITE   1039410\n0x40029DC0 READ    1039797\n0x40029E00 READ    1040403\n0x4007C640 WRITE   1040610\n0x40029E40 READ    1040997\n0x4007C680 WRITE   1041205\n0x40029E80 READ    1041592\n0x4007C6C0 WRITE   1041800\n0x40029EC0 READ    1042187\n0x4007C700 WRITE   1042395\n0x40029F00 READ    1042782\n0x4007C740 WRITE   1042990\n0x40029F40 READ    1043377\n0x4007C780 WRITE   1043585\n0x40029F80 READ    1043972\n0x4007C7C0 WRITE   1044180\n0x40029FC0 READ    1044567\n0x4007C800 WRITE   1044775\n0x4002A000 READ    1045192\n0x4007C840 WRITE   1045400\n0x4002A040 READ    1045787\n0x4002A080 READ    1046393\n0x4007C940 WRITE   1046600\n0x4002A0C0 READ    1046987\n0x4007C980 WRITE   1047195\n0x4002A100 READ    1047582\n0x4007C9C0 WRITE   1047790\n0x4002A140 READ    1048177\n0x4007CA00 WRITE   1048385\n0x4002A180 READ    1048772\n0x4007CA40 WRITE   1048980\n0x4002A1C0 READ    1049367\n0x4007CA80 WRITE   1049575\n0x4002A200 READ    1049962\n0x4007CAC0 WRITE   1050170\n0x4002A240 READ    1050557\n0x4007CB00 WRITE   1050765\n0x4002A280 READ    1051152\n0x4007CB40 WRITE   1051360\n0x4002A2C0 READ    1051747\n0x4002A300 READ    1052355\n0x4007CC40 WRITE   1052565\n0x4002A340 READ    1052952\n0x4007CC80 WRITE   1053160\n0x4002A380 READ    1053547\n0x4007CCC0 WRITE   1053755\n0x4002A3C0 READ    1054142\n0x4007CD00 WRITE   1054350\n0x4002A400 READ    1054737\n0x4007CD40 WRITE   1054945\n0x4002A440 READ    1055332\n0x4007CD80 WRITE   1055540\n0x4002A480 READ    1055927\n0x4007CDC0 WRITE   1056135\n0x4002A4C0 READ    1056522\n0x4007CE00 WRITE   1056730\n0x4002A500 READ    1057117\n0x4007CE40 WRITE   1057325\n0x4002A540 READ    1057712\n0x4002A580 READ    1058318\n0x4007CF40 WRITE   1058525\n0x4002A5C0 READ    1058912\n0x4007CF80 WRITE   1059120\n0x4002A600 READ    1059507\n0x4007CFC0 WRITE   1059715\n0x4002A640 READ    1060102\n0x4007D000 WRITE   1060310\n0x4002A680 READ    1060697\n0x4007D040 WRITE   1060905\n0x4002A6C0 READ    1061292\n0x4007D080 WRITE   1061500\n0x4002A700 READ    1061887\n0x4007D0C0 WRITE   1062095\n0x4002A740 READ    1062482\n0x4007D100 WRITE   1062690\n0x4002A780 READ    1063077\n0x4007D140 WRITE   1063285\n0x4002A7C0 READ    1063672\n0x4002A800 READ    1064278\n0x4007D240 WRITE   1064485\n0x4002A840 READ    1064872\n0x4007D280 WRITE   1065080\n0x4002A880 READ    1065467\n0x4007D2C0 WRITE   1065675\n0x4002A8C0 READ    1066062\n0x4007D300 WRITE   1066270\n0x4002A900 READ    1066657\n0x4007D340 WRITE   1066865\n0x4002A940 READ    1067252\n0x4007D380 WRITE   1067460\n0x4002A980 READ    1067847\n0x4007D3C0 WRITE   1068055\n0x4002A9C0 READ    1068442\n0x4007D400 WRITE   1068650\n0x4002AA00 READ    1069037\n0x4007D440 WRITE   1069245\n0x4002AA40 READ    1069632\n0x4002AA80 READ    1070238\n0x4007D540 WRITE   1070445\n0x4002AAC0 READ    1070832\n0x4007D580 WRITE   1071040\n0x4002AB00 READ    1071427\n0x4007D5C0 WRITE   1071635\n0x4002AB40 READ    1072022\n0x4007D600 WRITE   1072230\n0x4002AB80 READ    1072617\n0x4007D640 WRITE   1072825\n0x4002ABC0 READ    1073212\n0x4007D680 WRITE   1073420\n0x4002AC00 READ    1073807\n0x4007D6C0 WRITE   1074015\n0x4002AC40 READ    1074402\n0x4007D700 WRITE   1074610\n0x4002AC80 READ    1074997\n0x4007D740 WRITE   1075205\n0x4002ACC0 READ    1075592\n0x4002AD00 READ    1076200\n0x4007D840 WRITE   1076410\n0x4002AD40 READ    1076797\n0x4007D880 WRITE   1077005\n0x4002AD80 READ    1077392\n0x4007D8C0 WRITE   1077600\n0x4002ADC0 READ    1077987\n0x4007D900 WRITE   1078195\n0x4002AE00 READ    1078582\n0x4007D940 WRITE   1078790\n0x4002AE40 READ    1079177\n0x4007D980 WRITE   1079385\n0x4002AE80 READ    1079772\n0x4007D9C0 WRITE   1079980\n0x4002AEC0 READ    1080367\n0x4007DA00 WRITE   1080575\n0x4002AF00 READ    1080962\n0x4007DA40 WRITE   1081170\n0x4002AF40 READ    1081557\n0x4002AF80 READ    1082163\n0x4007DB40 WRITE   1082370\n0x4002AFC0 READ    1082757\n0x4007DB80 WRITE   1082965\n0x4002B000 READ    1083382\n0x4007DBC0 WRITE   1083590\n0x4002B040 READ    1083977\n0x4007DC00 WRITE   1084185\n0x4002B080 READ    1084572\n0x4007DC40 WRITE   1084780\n0x4002B0C0 READ    1085167\n0x4007DC80 WRITE   1085375\n0x4002B100 READ    1085762\n0x4007DCC0 WRITE   1085970\n0x4002B140 READ    1086357\n0x4007DD00 WRITE   1086565\n0x4002B180 READ    1086952\n0x4007DD40 WRITE   1087160\n0x4002B1C0 READ    1087547\n0x4002B200 READ    1088153\n0x4007DE40 WRITE   1088360\n0x4002B240 READ    1088747\n0x4007DE80 WRITE   1088955\n0x4002B280 READ    1089342\n0x4007DEC0 WRITE   1089550\n0x4002B2C0 READ    1089937\n0x4007DF00 WRITE   1090145\n0x4002B300 READ    1090532\n0x4007DF40 WRITE   1090740\n0x4002B340 READ    1091127\n0x4007DF80 WRITE   1091335\n0x4002B380 READ    1091722\n0x4007DFC0 WRITE   1091930\n0x4002B3C0 READ    1092317\n0x4007E000 WRITE   1092525\n0x4002B400 READ    1092912\n0x4007E040 WRITE   1093120\n0x4002B440 READ    1093507\n0x4002B480 READ    1094113\n0x4007E140 WRITE   1094320\n0x4002B4C0 READ    1094707\n0x4007E180 WRITE   1094915\n0x4002B500 READ    1095302\n0x4007E1C0 WRITE   1095510\n0x4002B540 READ    1095897\n0x4007E200 WRITE   1096105\n0x4002B580 READ    1096492\n0x4007E240 WRITE   1096700\n0x4002B5C0 READ    1097087\n0x4007E280 WRITE   1097295\n0x4002B600 READ    1097682\n0x4007E2C0 WRITE   1097890\n0x4002B640 READ    1098277\n0x4007E300 WRITE   1098485\n0x4002B680 READ    1098872\n0x4007E340 WRITE   1099080\n0x4002B6C0 READ    1099467\n0x4002B700 READ    1100075\n0x4007E440 WRITE   1100285\n0x4002B740 READ    1100672\n0x4007E480 WRITE   1100880\n0x4002B780 READ    1101267\n0x4007E4C0 WRITE   1101475\n0x4002B7C0 READ    1101862\n0x4007E500 WRITE   1102070\n0x4002B800 READ    1102457\n0x4007E540 WRITE   1102665\n0x4002B840 READ    1103052\n0x4007E580 WRITE   1103260\n0x4002B880 READ    1103647\n0x4007E5C0 WRITE   1103855\n0x4002B8C0 READ    1104242\n0x4007E600 WRITE   1104450\n0x4002B900 READ    1104837\n0x4007E640 WRITE   1105045\n0x4002B940 READ    1105432\n0x4002B980 READ    1106038\n0x4007E740 WRITE   1106245\n0x4002B9C0 READ    1106632\n0x4007E780 WRITE   1106840\n0x4002BA00 READ    1107227\n0x4007E7C0 WRITE   1107435\n0x4002BA40 READ    1107822\n0x4007E800 WRITE   1108030\n0x4002BA80 READ    1108417\n0x4007E840 WRITE   1108625\n0x4002BAC0 READ    1109012\n0x4007E880 WRITE   1109220\n0x4002BB00 READ    1109607\n0x4007E8C0 WRITE   1109815\n0x4002BB40 READ    1110202\n0x4007E900 WRITE   1110410\n0x4002BB80 READ    1110797\n0x4007E940 WRITE   1111005\n0x4002BBC0 READ    1111392\n0x4002BC00 READ    1111998\n0x4007EA40 WRITE   1112205\n0x4002BC40 READ    1112592\n0x4007EA80 WRITE   1112800\n0x4002BC80 READ    1113187\n0x4007EAC0 WRITE   1113395\n0x4002BCC0 READ    1113782\n0x4007EB00 WRITE   1113990\n0x4002BD00 READ    1114377\n0x4007EB40 WRITE   1114585\n0x4002BD40 READ    1114972\n0x4007EB80 WRITE   1115180\n0x4002BD80 READ    1115567\n0x4007EBC0 WRITE   1115775\n0x4002BDC0 READ    1116162\n0x4007EC00 WRITE   1116370\n0x4002BE00 READ    1116757\n0x4007EC40 WRITE   1116965\n0x4002BE40 READ    1117352\n0x4002BE80 READ    1117958\n0x4007ED40 WRITE   1118165\n0x4002BEC0 READ    1118552\n0x4007ED80 WRITE   1118760\n0x4002BF00 READ    1119147\n0x4007EDC0 WRITE   1119355\n0x4002BF40 READ    1119742\n0x4007EE00 WRITE   1119950\n0x4002BF80 READ    1120337\n0x4007EE40 WRITE   1120545\n0x4002BFC0 READ    1120932\n0x4007EE80 WRITE   1121140\n0x4002C000 READ    1121557\n0x4007EEC0 WRITE   1121845\n0x4002C040 READ    1122232\n0x4007EF00 WRITE   1122440\n0x4002C080 READ    1122827\n0x4007EF40 WRITE   1123035\n0x4002C0C0 READ    1123422\n0x4002C100 READ    1124030\n0x4007F040 WRITE   1124240\n0x4002C140 READ    1124627\n0x4007F080 WRITE   1124835\n0x4002C180 READ    1125222\n0x4007F0C0 WRITE   1125430\n0x4002C1C0 READ    1125817\n0x4007F100 WRITE   1126025\n0x4002C200 READ    1126412\n0x4007F140 WRITE   1126620\n0x4002C240 READ    1127007\n0x4007F180 WRITE   1127215\n0x4002C280 READ    1127602\n0x4007F1C0 WRITE   1127810\n0x4002C2C0 READ    1128197\n0x4007F200 WRITE   1128405\n0x4002C300 READ    1128792\n0x4007F240 WRITE   1129000\n0x4002C340 READ    1129387\n0x4002C380 READ    1129993\n0x4007F340 WRITE   1130200\n0x4002C3C0 READ    1130587\n0x4007F380 WRITE   1130795\n0x4002C400 READ    1131182\n0x4007F3C0 WRITE   1131390\n0x4002C440 READ    1131777\n0x4007F400 WRITE   1131985\n0x4002C480 READ    1132372\n0x4007F440 WRITE   1132580\n0x4002C4C0 READ    1132967\n0x4007F480 WRITE   1133175\n0x4002C500 READ    1133562\n0x4007F4C0 WRITE   1133770\n0x4002C540 READ    1134157\n0x4007F500 WRITE   1134365\n0x4002C580 READ    1134752\n0x4007F540 WRITE   1134960\n0x4002C5C0 READ    1135347\n0x4002C600 READ    1135953\n0x4007F640 WRITE   1136160\n0x4002C640 READ    1136547\n0x4007F680 WRITE   1136755\n0x4002C680 READ    1137142\n0x4007F6C0 WRITE   1137350\n0x4002C6C0 READ    1137737\n0x4007F700 WRITE   1137945\n0x4002C700 READ    1138332\n0x4007F740 WRITE   1138540\n0x4002C740 READ    1138927\n0x4007F780 WRITE   1139135\n0x4002C780 READ    1139522\n0x4007F7C0 WRITE   1139730\n0x4002C7C0 READ    1140117\n0x4007F800 WRITE   1140325\n0x4002C800 READ    1140712\n0x4007F840 WRITE   1140920\n0x4002C840 READ    1141307\n0x4002C880 READ    1141913\n0x4007F940 WRITE   1142120\n0x4002C8C0 READ    1142507\n0x4007F980 WRITE   1142715\n0x4002C900 READ    1143102\n0x4007F9C0 WRITE   1143310\n0x4002C940 READ    1143697\n0x4007FA00 WRITE   1143905\n0x4002C980 READ    1144292\n0x4007FA40 WRITE   1144500\n0x4002C9C0 READ    1144887\n0x4007FA80 WRITE   1145095\n0x4002CA00 READ    1145482\n0x4007FAC0 WRITE   1145690\n0x4002CA40 READ    1146077\n0x4007FB00 WRITE   1146285\n0x4002CA80 READ    1146672\n0x4007FB40 WRITE   1146880\n0x4002CAC0 READ    1147267\n0x4002CB00 READ    1147875\n0x4007FC40 WRITE   1148085\n0x4002CB40 READ    1148472\n0x4007FC80 WRITE   1148680\n0x4002CB80 READ    1149067\n0x4007FCC0 WRITE   1149275\n0x4002CBC0 READ    1149662\n0x4007FD00 WRITE   1149870\n0x4002CC00 READ    1150257\n0x4007FD40 WRITE   1150465\n0x4002CC40 READ    1150852\n0x4007FD80 WRITE   1151060\n0x4002CC80 READ    1151447\n0x4007FDC0 WRITE   1151655\n0x4002CCC0 READ    1152042\n0x4007FE00 WRITE   1152250\n0x4002CD00 READ    1152637\n0x4007FE40 WRITE   1152845\n0x4002CD40 READ    1153232\n0x4002CD80 READ    1153838\n0x4007FF40 WRITE   1154045\n0x4002CDC0 READ    1154432\n0x4007FF80 WRITE   1154640\n0x4002CE00 READ    1155027\n0x4007FFC0 WRITE   1155235\n0x4002CE40 READ    1155622\n0x40080000 WRITE   1155830\n0x4002CE80 READ    1156217\n0x40080040 WRITE   1156425\n0x4002CEC0 READ    1156812\n0x40080080 WRITE   1157020\n0x4002CF00 READ    1157407\n0x400800C0 WRITE   1157615\n0x4002CF40 READ    1158002\n0x40080100 WRITE   1158210\n0x4002CF80 READ    1158597\n0x40080140 WRITE   1158805\n0x4002CFC0 READ    1159192\n0x4002D000 READ    1159828\n0x40080240 WRITE   1160035\n0x4002D040 READ    1160422\n0x40080280 WRITE   1160630\n0x4002D080 READ    1161017\n0x400802C0 WRITE   1161225\n0x4002D0C0 READ    1161612\n0x40080300 WRITE   1161820\n0x4002D100 READ    1162207\n0x40080340 WRITE   1162415\n0x4002D140 READ    1162802\n0x40080380 WRITE   1163010\n0x4002D180 READ    1163397\n0x400803C0 WRITE   1163605\n0x4002D1C0 READ    1163992\n0x40080400 WRITE   1164200\n0x4002D200 READ    1164587\n0x40080440 WRITE   1164795\n0x4002D240 READ    1165182\n0x4002D280 READ    1165788\n0x40080540 WRITE   1165995\n0x4002D2C0 READ    1166382\n0x40080580 WRITE   1166590\n0x4002D300 READ    1166977\n0x400805C0 WRITE   1167185\n0x4002D340 READ    1167572\n0x40080600 WRITE   1167780\n0x4002D380 READ    1168167\n0x40080640 WRITE   1168375\n0x4002D3C0 READ    1168762\n0x40080680 WRITE   1168970\n0x4002D400 READ    1169357\n0x400806C0 WRITE   1169565\n0x4002D440 READ    1169952\n0x40080700 WRITE   1170160\n0x4002D480 READ    1170547\n0x40080740 WRITE   1170755\n0x4002D4C0 READ    1171142\n0x4002D500 READ    1171750\n0x40080840 WRITE   1171960\n0x4002D540 READ    1172347\n0x40080880 WRITE   1172555\n0x4002D580 READ    1172942\n0x400808C0 WRITE   1173150\n0x4002D5C0 READ    1173537\n0x40080900 WRITE   1173745\n0x4002D600 READ    1174132\n0x40080940 WRITE   1174340\n0x4002D640 READ    1174727\n0x40080980 WRITE   1174935\n0x4002D680 READ    1175322\n0x400809C0 WRITE   1175530\n0x4002D6C0 READ    1175917\n0x40080A00 WRITE   1176125\n0x4002D700 READ    1176512\n0x40080A40 WRITE   1176720\n0x4002D740 READ    1177107\n0x4002D780 READ    1177713\n0x40080B40 WRITE   1177920\n0x4002D7C0 READ    1178307\n0x40080B80 WRITE   1178515\n0x4002D800 READ    1178902\n0x40080BC0 WRITE   1179110\n0x4002D840 READ    1179497\n0x40080C00 WRITE   1179705\n0x4002D880 READ    1180092\n0x40080C40 WRITE   1180300\n0x4002D8C0 READ    1180687\n0x40080C80 WRITE   1180895\n0x4002D900 READ    1181282\n0x40080CC0 WRITE   1181490\n0x4002D940 READ    1181877\n0x40080D00 WRITE   1182085\n0x4002D980 READ    1182472\n0x40080D40 WRITE   1182680\n0x4002D9C0 READ    1183067\n0x4002DA00 READ    1183673\n0x40080E40 WRITE   1183880\n0x4002DA40 READ    1184267\n0x40080E80 WRITE   1184475\n0x4002DA80 READ    1184862\n0x40080EC0 WRITE   1185070\n0x4002DAC0 READ    1185457\n0x40080F00 WRITE   1185665\n0x4002DB00 READ    1186052\n0x40080F40 WRITE   1186260\n0x4002DB40 READ    1186647\n0x40080F80 WRITE   1186855\n0x4002DB80 READ    1187242\n0x40080FC0 WRITE   1187450\n0x4002DBC0 READ    1187837\n0x40081000 WRITE   1188045\n0x4002DC00 READ    1188432\n0x40081040 WRITE   1188640\n0x4002DC40 READ    1189027\n0x4002DC80 READ    1189633\n0x40081140 WRITE   1189840\n0x4002DCC0 READ    1190227\n0x40081180 WRITE   1190435\n0x4002DD00 READ    1190822\n0x400811C0 WRITE   1191030\n0x4002DD40 READ    1191417\n0x40081200 WRITE   1191625\n0x4002DD80 READ    1192012\n0x40081240 WRITE   1192220\n0x4002DDC0 READ    1192607\n0x40081280 WRITE   1192815\n0x4002DE00 READ    1193202\n0x400812C0 WRITE   1193410\n0x4002DE40 READ    1193797\n0x40081300 WRITE   1194005\n0x4002DE80 READ    1194392\n0x40081340 WRITE   1194600\n0x4002DEC0 READ    1194987\n0x4002DF00 READ    1195595\n0x40081440 WRITE   1195805\n0x4002DF40 READ    1196192\n0x40081480 WRITE   1196400\n0x4002DF80 READ    1196787\n0x400814C0 WRITE   1196995\n0x4002DFC0 READ    1197382\n0x40081500 WRITE   1197590\n0x4002E000 READ    1198007\n0x40081540 WRITE   1198215\n0x4002E040 READ    1198602\n0x40081580 WRITE   1198810\n0x4002E080 READ    1199197\n0x400815C0 WRITE   1199405\n0x4002E0C0 READ    1199792\n0x40081600 WRITE   1200000\n0x4002E100 READ    1200387\n0x40081640 WRITE   1200595\n0x4002E140 READ    1200982\n0x4002E180 READ    1201588\n0x40081740 WRITE   1201795\n0x4002E1C0 READ    1202182\n0x40081780 WRITE   1202390\n0x4002E200 READ    1202777\n0x400817C0 WRITE   1202985\n0x4002E240 READ    1203372\n0x40081800 WRITE   1203580\n0x4002E280 READ    1203967\n0x40081840 WRITE   1204175\n0x4002E2C0 READ    1204562\n0x40081880 WRITE   1204770\n0x4002E300 READ    1205157\n0x400818C0 WRITE   1205365\n0x4002E340 READ    1205752\n0x40081900 WRITE   1205960\n0x4002E380 READ    1206347\n0x40081940 WRITE   1206555\n0x4002E3C0 READ    1206942\n0x4002E400 READ    1207548\n0x40081A40 WRITE   1207755\n0x4002E440 READ    1208142\n0x40081A80 WRITE   1208350\n0x4002E480 READ    1208737\n0x40081AC0 WRITE   1208945\n0x4002E4C0 READ    1209332\n0x40081B00 WRITE   1209540\n0x4002E500 READ    1209927\n0x40081B40 WRITE   1210135\n0x4002E540 READ    1210522\n0x40081B80 WRITE   1210730\n0x4002E580 READ    1211117\n0x40081BC0 WRITE   1211325\n0x4002E5C0 READ    1211712\n0x40081C00 WRITE   1211920\n0x4002E600 READ    1212307\n0x40081C40 WRITE   1212515\n0x4002E640 READ    1212902\n0x4002E680 READ    1213508\n0x40081D40 WRITE   1213715\n0x4002E6C0 READ    1214102\n0x40081D80 WRITE   1214310\n0x4002E700 READ    1214697\n0x40081DC0 WRITE   1214905\n0x4002E740 READ    1215292\n0x40081E00 WRITE   1215500\n0x4002E780 READ    1215887\n0x40081E40 WRITE   1216095\n0x4002E7C0 READ    1216482\n0x40081E80 WRITE   1216690\n0x4002E800 READ    1217077\n0x40081EC0 WRITE   1217285\n0x4002E840 READ    1217672\n0x40081F00 WRITE   1217880\n0x4002E880 READ    1218267\n0x40081F40 WRITE   1218475\n0x4002E8C0 READ    1218862\n0x4002E900 READ    1219470\n0x40082040 WRITE   1219680\n0x4002E940 READ    1220067\n0x40082080 WRITE   1220275\n0x4002E980 READ    1220662\n0x400820C0 WRITE   1220870\n0x4002E9C0 READ    1221257\n0x40082100 WRITE   1221465\n0x4002EA00 READ    1221852\n0x40082140 WRITE   1222060\n0x4002EA40 READ    1222447\n0x40082180 WRITE   1222655\n0x4002EA80 READ    1223042\n0x400821C0 WRITE   1223250\n0x4002EAC0 READ    1223637\n0x40082200 WRITE   1223845\n0x4002EB00 READ    1224232\n0x40082240 WRITE   1224440\n0x4002EB40 READ    1224827\n0x4002EB80 READ    1225433\n0x40082340 WRITE   1225640\n0x4002EBC0 READ    1226027\n0x40082380 WRITE   1226235\n0x4002EC00 READ    1226622\n0x400823C0 WRITE   1226830\n0x4002EC40 READ    1227217\n0x40082400 WRITE   1227425\n0x4002EC80 READ    1227812\n0x40082440 WRITE   1228020\n0x4002ECC0 READ    1228407\n0x40082480 WRITE   1228615\n0x4002ED00 READ    1229002\n0x400824C0 WRITE   1229210\n0x4002ED40 READ    1229597\n0x40082500 WRITE   1229805\n0x4002ED80 READ    1230192\n0x40082540 WRITE   1230400\n0x4002EDC0 READ    1230787\n0x4002EE00 READ    1231393\n0x40082640 WRITE   1231600\n0x4002EE40 READ    1231987\n0x40082680 WRITE   1232195\n0x4002EE80 READ    1232582\n0x400826C0 WRITE   1232790\n0x4002EEC0 READ    1233177\n0x40082700 WRITE   1233385\n0x4002EF00 READ    1233772\n0x40082740 WRITE   1233980\n0x4002EF40 READ    1234367\n0x40082780 WRITE   1234575\n0x4002EF80 READ    1234962\n0x400827C0 WRITE   1235170\n0x4002EFC0 READ    1235557\n0x40082800 WRITE   1235765\n0x4002F000 READ    1236182\n0x40082840 WRITE   1236390\n0x4002F040 READ    1236777\n0x4002F080 READ    1237383\n0x40082940 WRITE   1237590\n0x4002F0C0 READ    1237977\n0x40082980 WRITE   1238185\n0x4002F100 READ    1238572\n0x400829C0 WRITE   1238780\n0x4002F140 READ    1239167\n0x40082A00 WRITE   1239375\n0x4002F180 READ    1239762\n0x40082A40 WRITE   1239970\n0x4002F1C0 READ    1240357\n0x40082A80 WRITE   1240565\n0x4002F200 READ    1240952\n0x40082AC0 WRITE   1241160\n0x4002F240 READ    1241547\n0x40082B00 WRITE   1241755\n0x4002F280 READ    1242142\n0x40082B40 WRITE   1242350\n0x4002F2C0 READ    1242737\n0x4002F300 READ    1243345\n0x40082C40 WRITE   1243555\n0x4002F340 READ    1243942\n0x40082C80 WRITE   1244150\n0x4002F380 READ    1244537\n0x40082CC0 WRITE   1244745\n0x4002F3C0 READ    1245132\n0x40082D00 WRITE   1245340\n0x4002F400 READ    1245727\n0x40082D40 WRITE   1245935\n0x4002F440 READ    1246322\n0x40082D80 WRITE   1246530\n0x4002F480 READ    1246917\n0x40082DC0 WRITE   1247125\n0x4002F4C0 READ    1247512\n0x40082E00 WRITE   1247720\n0x4002F500 READ    1248107\n0x40082E40 WRITE   1248315\n0x4002F540 READ    1248702\n0x4002F580 READ    1249308\n0x40082F40 WRITE   1249515\n0x4002F5C0 READ    1249902\n0x40082F80 WRITE   1250110\n0x4002F600 READ    1250497\n0x40082FC0 WRITE   1250705\n0x4002F640 READ    1251092\n0x40083000 WRITE   1251300\n0x4002F680 READ    1251687\n0x40083040 WRITE   1251895\n0x4002F6C0 READ    1252282\n0x40083080 WRITE   1252490\n0x4002F700 READ    1252877\n0x400830C0 WRITE   1253085\n0x4002F740 READ    1253472\n0x40083100 WRITE   1253680\n0x4002F780 READ    1254067\n0x40083140 WRITE   1254275\n0x4002F7C0 READ    1254662\n0x4002F800 READ    1255268\n0x40083240 WRITE   1255475\n0x4002F840 READ    1255862\n0x40083280 WRITE   1256070\n0x4002F880 READ    1256457\n0x400832C0 WRITE   1256665\n0x4002F8C0 READ    1257052\n0x40083300 WRITE   1257260\n0x4002F900 READ    1257647\n0x40083340 WRITE   1257855\n0x4002F940 READ    1258242\n0x40083380 WRITE   1258450\n0x4002F980 READ    1258837\n0x400833C0 WRITE   1259045\n0x4002F9C0 READ    1259432\n0x40083400 WRITE   1259640\n0x4002FA00 READ    1260027\n0x40083440 WRITE   1260235\n0x4002FA40 READ    1260622\n0x4002FA80 READ    1261228\n0x40083540 WRITE   1261435\n0x4002FAC0 READ    1261822\n0x40083580 WRITE   1262030\n0x4002FB00 READ    1262417\n0x400835C0 WRITE   1262625\n0x4002FB40 READ    1263012\n0x40083600 WRITE   1263220\n0x4002FB80 READ    1263607\n0x40083640 WRITE   1263815\n0x4002FBC0 READ    1264202\n0x40083680 WRITE   1264410\n0x4002FC00 READ    1264797\n0x400836C0 WRITE   1265005\n0x4002FC40 READ    1265392\n0x40083700 WRITE   1265600\n0x4002FC80 READ    1265987\n0x40083740 WRITE   1266195\n0x4002FCC0 READ    1266582\n0x4002FD00 READ    1267190\n0x40083840 WRITE   1267400\n0x4002FD40 READ    1267787\n0x40083880 WRITE   1267995\n0x4002FD80 READ    1268382\n0x400838C0 WRITE   1268590\n0x4002FDC0 READ    1268977\n0x40083900 WRITE   1269185\n0x4002FE00 READ    1269572\n0x40083940 WRITE   1269780\n0x4002FE40 READ    1270167\n0x40083980 WRITE   1270375\n0x4002FE80 READ    1270762\n0x400839C0 WRITE   1270970\n0x4002FEC0 READ    1271357\n0x40083A00 WRITE   1271565\n0x4002FF00 READ    1271952\n0x40083A40 WRITE   1272160\n0x4002FF40 READ    1272547\n0x4002FF80 READ    1273153\n0x40083B40 WRITE   1273360\n0x4002FFC0 READ    1273747\n0x40083B80 WRITE   1273955\n0x40030000 READ    1274372\n0x40083BC0 WRITE   1274660\n0x40030040 READ    1275047\n0x40083C00 WRITE   1275255\n0x40030080 READ    1275642\n0x40083C40 WRITE   1275850\n0x400300C0 READ    1276237\n0x40083C80 WRITE   1276445\n0x40030100 READ    1276832\n0x40083CC0 WRITE   1277040\n0x40030140 READ    1277427\n0x40083D00 WRITE   1277635\n0x40030180 READ    1278022\n0x40083D40 WRITE   1278230\n0x400301C0 READ    1278617\n0x40030200 READ    1279223\n0x40083E40 WRITE   1279430\n0x40030240 READ    1279817\n0x40083E80 WRITE   1280025\n0x40030280 READ    1280412\n0x40083EC0 WRITE   1280620\n0x400302C0 READ    1281007\n0x40083F00 WRITE   1281215\n0x40030300 READ    1281602\n0x40083F40 WRITE   1281810\n0x40030340 READ    1282197\n0x40083F80 WRITE   1282405\n0x40030380 READ    1282792\n0x40083FC0 WRITE   1283000\n0x400303C0 READ    1283387\n0x40084000 WRITE   1283595\n0x40030400 READ    1283982\n0x40084040 WRITE   1284190\n0x40030440 READ    1284577\n0x40030480 READ    1285183\n0x40084140 WRITE   1285390\n0x400304C0 READ    1285777\n0x40084180 WRITE   1285985\n0x40030500 READ    1286372\n0x400841C0 WRITE   1286580\n0x40030540 READ    1286967\n0x40084200 WRITE   1287175\n0x40030580 READ    1287562\n0x40084240 WRITE   1287770\n0x400305C0 READ    1288157\n0x40084280 WRITE   1288365\n0x40030600 READ    1288752\n0x400842C0 WRITE   1288960\n0x40030640 READ    1289347\n0x40084300 WRITE   1289555\n0x40030680 READ    1289942\n0x40084340 WRITE   1290150\n0x400306C0 READ    1290537\n0x40030700 READ    1291145\n0x40084440 WRITE   1291355\n0x40030740 READ    1291742\n0x40084480 WRITE   1291950\n0x40030780 READ    1292337\n0x400844C0 WRITE   1292545\n0x400307C0 READ    1292932\n0x40084500 WRITE   1293140\n0x40030800 READ    1293527\n0x40084540 WRITE   1293735\n0x40030840 READ    1294122\n0x40084580 WRITE   1294330\n0x40030880 READ    1294717\n0x400845C0 WRITE   1294925\n0x400308C0 READ    1295312\n0x40084600 WRITE   1295520\n0x40030900 READ    1295907\n0x40084640 WRITE   1296115\n0x40030940 READ    1296502\n0x40030980 READ    1297108\n0x40084740 WRITE   1297315\n0x400309C0 READ    1297702\n0x40084780 WRITE   1297910\n0x40030A00 READ    1298297\n0x400847C0 WRITE   1298505\n0x40030A40 READ    1298892\n0x40084800 WRITE   1299100\n0x40030A80 READ    1299487\n0x40084840 WRITE   1299695\n0x40030AC0 READ    1300082\n0x40084880 WRITE   1300290\n0x40030B00 READ    1300677\n0x400848C0 WRITE   1300885\n0x40030B40 READ    1301272\n0x40084900 WRITE   1301480\n0x40030B80 READ    1301867\n0x40084940 WRITE   1302075\n0x40030BC0 READ    1302462\n0x40030C00 READ    1303068\n0x40084A40 WRITE   1303275\n0x40030C40 READ    1303662\n0x40084A80 WRITE   1303870\n0x40030C80 READ    1304257\n0x40084AC0 WRITE   1304465\n0x40030CC0 READ    1304852\n0x40084B00 WRITE   1305060\n0x40030D00 READ    1305447\n0x40084B40 WRITE   1305655\n0x40030D40 READ    1306042\n0x40084B80 WRITE   1306250\n0x40030D80 READ    1306637\n0x40084BC0 WRITE   1306845\n0x40030DC0 READ    1307232\n0x40084C00 WRITE   1307440\n0x40030E00 READ    1307827\n0x40084C40 WRITE   1308035\n0x40030E40 READ    1308422\n0x40030E80 READ    1309028\n0x40084D40 WRITE   1309235\n0x40030EC0 READ    1309622\n0x40084D80 WRITE   1309830\n0x40030F00 READ    1310217\n0x40084DC0 WRITE   1310425\n0x40030F40 READ    1310812\n0x40084E00 WRITE   1311020\n0x40030F80 READ    1311407\n0x40084E40 WRITE   1311615\n0x40030FC0 READ    1312002\n0x40084E80 WRITE   1312210\n0x40031000 READ    1312627\n0x40084EC0 WRITE   1312835\n0x40031040 READ    1313222\n0x40084F00 WRITE   1313430\n0x40031080 READ    1313817\n0x40084F40 WRITE   1314025\n0x400310C0 READ    1314412\n0x40031100 READ    1315020\n0x40085040 WRITE   1315230\n0x40031140 READ    1315617\n0x40085080 WRITE   1315825\n0x40031180 READ    1316212\n0x400850C0 WRITE   1316420\n0x400311C0 READ    1316807\n0x40085100 WRITE   1317015\n0x40031200 READ    1317402\n0x40085140 WRITE   1317610\n0x40031240 READ    1317997\n0x40085180 WRITE   1318205\n0x40031280 READ    1318592\n0x400851C0 WRITE   1318800\n0x400312C0 READ    1319187\n0x40085200 WRITE   1319395\n0x40031300 READ    1319782\n0x40085240 WRITE   1319990\n0x40031340 READ    1320377\n0x40031380 READ    1320983\n0x40085340 WRITE   1321190\n0x400313C0 READ    1321577\n0x40085380 WRITE   1321785\n0x40031400 READ    1322172\n0x400853C0 WRITE   1322380\n0x40031440 READ    1322767\n0x40085400 WRITE   1322975\n0x40031480 READ    1323362\n0x40085440 WRITE   1323570\n0x400314C0 READ    1323957\n0x40085480 WRITE   1324165\n0x40031500 READ    1324552\n0x400854C0 WRITE   1324760\n0x40031540 READ    1325147\n0x40085500 WRITE   1325355\n0x40031580 READ    1325742\n0x40085540 WRITE   1325950\n0x400315C0 READ    1326337\n0x40031600 READ    1326943\n0x40085640 WRITE   1327150\n0x40031640 READ    1327537\n0x40085680 WRITE   1327745\n0x40031680 READ    1328132\n0x400856C0 WRITE   1328340\n0x400316C0 READ    1328727\n0x40085700 WRITE   1328935\n0x40031700 READ    1329322\n0x40085740 WRITE   1329530\n0x40031740 READ    1329917\n0x40085780 WRITE   1330125\n0x40031780 READ    1330512\n0x400857C0 WRITE   1330720\n0x400317C0 READ    1331107\n0x40085800 WRITE   1331315\n0x40031800 READ    1331702\n0x40085840 WRITE   1331910\n0x40031840 READ    1332297\n0x40031880 READ    1332903\n0x40085940 WRITE   1333110\n0x400318C0 READ    1333497\n0x40085980 WRITE   1333705\n0x40031900 READ    1334092\n0x400859C0 WRITE   1334300\n0x40031940 READ    1334687\n0x40085A00 WRITE   1334895\n0x40031980 READ    1335282\n0x40085A40 WRITE   1335490\n0x400319C0 READ    1335877\n0x40085A80 WRITE   1336085\n0x40031A00 READ    1336472\n0x40085AC0 WRITE   1336680\n0x40031A40 READ    1337067\n0x40085B00 WRITE   1337275\n0x40031A80 READ    1337662\n0x40085B40 WRITE   1337870\n0x40031AC0 READ    1338257\n0x40031B00 READ    1338865\n0x40085C40 WRITE   1339075\n0x40031B40 READ    1339462\n0x40085C80 WRITE   1339670\n0x40031B80 READ    1340057\n0x40085CC0 WRITE   1340265\n0x40031BC0 READ    1340652\n0x40085D00 WRITE   1340860\n0x40031C00 READ    1341247\n0x40085D40 WRITE   1341455\n0x40031C40 READ    1341842\n0x40085D80 WRITE   1342050\n0x40031C80 READ    1342437\n0x40085DC0 WRITE   1342645\n0x40031CC0 READ    1343032\n0x40085E00 WRITE   1343240\n0x40031D00 READ    1343627\n0x40085E40 WRITE   1343835\n0x40031D40 READ    1344222\n0x40031D80 READ    1344828\n0x40085F40 WRITE   1345035\n0x40031DC0 READ    1345422\n0x40085F80 WRITE   1345630\n0x40031E00 READ    1346017\n0x40085FC0 WRITE   1346225\n0x40031E40 READ    1346612\n0x40086000 WRITE   1346820\n0x40031E80 READ    1347207\n0x40086040 WRITE   1347415\n0x40031EC0 READ    1347802\n0x40086080 WRITE   1348010\n0x40031F00 READ    1348397\n0x400860C0 WRITE   1348605\n0x40031F40 READ    1348992\n0x40086100 WRITE   1349200\n0x40031F80 READ    1349587\n0x40086140 WRITE   1349795\n0x40031FC0 READ    1350182\n0x40032000 READ    1350818\n0x40086240 WRITE   1351025\n0x40032040 READ    1351412\n0x40086280 WRITE   1351620\n0x40032080 READ    1352007\n0x400862C0 WRITE   1352215\n0x400320C0 READ    1352602\n0x40086300 WRITE   1352810\n0x40032100 READ    1353197\n0x40086340 WRITE   1353405\n0x40032140 READ    1353792\n0x40086380 WRITE   1354000\n0x40032180 READ    1354387\n0x400863C0 WRITE   1354595\n0x400321C0 READ    1354982\n0x40086400 WRITE   1355190\n0x40032200 READ    1355577\n0x40086440 WRITE   1355785\n0x40032240 READ    1356172\n0x40032280 READ    1356778\n0x40086540 WRITE   1356985\n0x400322C0 READ    1357372\n0x40086580 WRITE   1357580\n0x40032300 READ    1357967\n0x400865C0 WRITE   1358175\n0x40032340 READ    1358562\n0x40086600 WRITE   1358770\n0x40032380 READ    1359157\n0x40086640 WRITE   1359365\n0x400323C0 READ    1359752\n0x40086680 WRITE   1359960\n0x40032400 READ    1360347\n0x400866C0 WRITE   1360555\n0x40032440 READ    1360942\n0x40086700 WRITE   1361150\n0x40032480 READ    1361537\n0x40086740 WRITE   1361745\n0x400324C0 READ    1362132\n0x40032500 READ    1362740\n0x40086840 WRITE   1362950\n0x40032540 READ    1363337\n0x40032580 READ    1363932\n0x400868C0 WRITE   1364140\n0x400325C0 READ    1364527\n0x40086900 WRITE   1364735\n0x40032600 READ    1365122\n0x40086940 WRITE   1365330\n0x40032640 READ    1365717\n0x40086980 WRITE   1365925\n0x40032680 READ    1366312\n0x400869C0 WRITE   1366520\n0x400326C0 READ    1366907\n0x40086A00 WRITE   1367115\n0x40032700 READ    1367502\n0x40086A40 WRITE   1367710\n0x40032740 READ    1368097\n0x40032780 READ    1368703\n0x40086B40 WRITE   1368910\n0x400327C0 READ    1369297\n0x40086B80 WRITE   1369505\n0x40032800 READ    1369892\n0x40086BC0 WRITE   1370100\n0x40032840 READ    1370487\n0x40086C00 WRITE   1370695\n0x40032880 READ    1371082\n0x40086C40 WRITE   1371290\n0x400328C0 READ    1371677\n0x40086C80 WRITE   1371885\n0x40032900 READ    1372272\n0x40086CC0 WRITE   1372480\n0x40032940 READ    1372867\n0x40086D00 WRITE   1373075\n0x40032980 READ    1373462\n0x40086D40 WRITE   1373670\n0x400329C0 READ    1374057\n0x40032A00 READ    1374663\n0x40086E40 WRITE   1374870\n0x40032A40 READ    1375257\n0x40086E80 WRITE   1375465\n0x40032A80 READ    1375852\n0x40086EC0 WRITE   1376060\n0x40032AC0 READ    1376447\n0x40086F00 WRITE   1376655\n0x40032B00 READ    1377042\n0x40086F40 WRITE   1377250\n0x40032B40 READ    1377637\n0x40086F80 WRITE   1377845\n0x40032B80 READ    1378232\n0x40086FC0 WRITE   1378440\n0x40032BC0 READ    1378827\n0x40087000 WRITE   1379035\n0x40032C00 READ    1379422\n0x40087040 WRITE   1379630\n0x40032C40 READ    1380017\n0x40032C80 READ    1380623\n0x40087140 WRITE   1380830\n0x40032CC0 READ    1381217\n0x40087180 WRITE   1381425\n0x40032D00 READ    1381812\n0x400871C0 WRITE   1382020\n0x40032D40 READ    1382407\n0x40087200 WRITE   1382615\n0x40032D80 READ    1383002\n0x40087240 WRITE   1383210\n0x40032DC0 READ    1383597\n0x40087280 WRITE   1383805\n0x40032E00 READ    1384192\n0x400872C0 WRITE   1384400\n0x40032E40 READ    1384787\n0x40087300 WRITE   1384995\n0x40032E80 READ    1385382\n0x40087340 WRITE   1385590\n0x40032EC0 READ    1385977\n0x40032F00 READ    1386585\n0x40087440 WRITE   1386795\n0x40032F40 READ    1387182\n0x40087480 WRITE   1387390\n0x40032F80 READ    1387777\n0x400874C0 WRITE   1387985\n0x40032FC0 READ    1388372\n0x40087500 WRITE   1388580\n0x40033000 READ    1388997\n0x40087540 WRITE   1389205\n0x40033040 READ    1389592\n0x40087580 WRITE   1389800\n0x40033080 READ    1390187\n0x400875C0 WRITE   1390395\n0x400330C0 READ    1390782\n0x40087600 WRITE   1390990\n0x40033100 READ    1391377\n0x40087640 WRITE   1391585\n0x40033140 READ    1391972\n0x40033180 READ    1392578\n0x40087740 WRITE   1392785\n0x400331C0 READ    1393172\n0x40087780 WRITE   1393380\n0x40033200 READ    1393767\n0x400877C0 WRITE   1393975\n0x40033240 READ    1394362\n0x40087800 WRITE   1394570\n0x40033280 READ    1394957\n0x40087840 WRITE   1395165\n0x400332C0 READ    1395552\n0x40087880 WRITE   1395760\n0x40033300 READ    1396147\n0x400878C0 WRITE   1396355\n0x40033340 READ    1396742\n0x40087900 WRITE   1396950\n0x40033380 READ    1397337\n0x40087940 WRITE   1397545\n0x400333C0 READ    1397932\n0x40033400 READ    1398538\n0x40087A40 WRITE   1398745\n0x40033440 READ    1399132\n0x40087A80 WRITE   1399340\n0x40033480 READ    1399727\n0x40087AC0 WRITE   1399935\n0x400334C0 READ    1400322\n0x40087B00 WRITE   1400530\n0x40033500 READ    1400917\n0x40087B40 WRITE   1401125\n0x40033540 READ    1401512\n0x40087B80 WRITE   1401720\n0x40033580 READ    1402107\n0x40087BC0 WRITE   1402315\n0x400335C0 READ    1402702\n0x40087C00 WRITE   1402910\n0x40033600 READ    1403297\n0x40087C40 WRITE   1403505\n0x40033640 READ    1403892\n0x40033680 READ    1404498\n0x40087D40 WRITE   1404705\n0x400336C0 READ    1405092\n0x40087D80 WRITE   1405300\n0x40033700 READ    1405687\n0x40087DC0 WRITE   1405895\n0x40033740 READ    1406282\n0x40087E00 WRITE   1406490\n0x40033780 READ    1406877\n0x40087E40 WRITE   1407085\n0x400337C0 READ    1407472\n0x40087E80 WRITE   1407680\n0x40033800 READ    1408067\n0x40087EC0 WRITE   1408275\n0x40033840 READ    1408662\n0x40087F00 WRITE   1408870\n0x40033880 READ    1409257\n0x40087F40 WRITE   1409465\n0x400338C0 READ    1409852\n0x40033900 READ    1410460\n0x40088040 WRITE   1410670\n0x40033940 READ    1411057\n0x40088080 WRITE   1411265\n0x40033980 READ    1411652\n0x400880C0 WRITE   1411860\n0x400339C0 READ    1412247\n0x40088100 WRITE   1412455\n0x40033A00 READ    1412842\n0x40088140 WRITE   1413050\n0x40033A40 READ    1413437\n0x40088180 WRITE   1413645\n0x40033A80 READ    1414032\n0x400881C0 WRITE   1414240\n0x40033AC0 READ    1414627\n0x40088200 WRITE   1414835\n0x40033B00 READ    1415222\n0x40088240 WRITE   1415430\n0x40033B40 READ    1415817\n0x40033B80 READ    1416423\n0x40088340 WRITE   1416630\n0x40033BC0 READ    1417017\n0x40088380 WRITE   1417225\n0x40033C00 READ    1417612\n0x400883C0 WRITE   1417820\n0x40033C40 READ    1418207\n0x40088400 WRITE   1418415\n0x40033C80 READ    1418802\n0x40088440 WRITE   1419010\n0x40033CC0 READ    1419397\n0x40088480 WRITE   1419605\n0x40033D00 READ    1419992\n0x400884C0 WRITE   1420200\n0x40033D40 READ    1420587\n0x40088500 WRITE   1420795\n0x40033D80 READ    1421182\n0x40088540 WRITE   1421390\n0x40033DC0 READ    1421777\n0x40033E00 READ    1422383\n0x40088640 WRITE   1422590\n0x40033E40 READ    1422977\n0x40088680 WRITE   1423185\n0x40033E80 READ    1423572\n0x400886C0 WRITE   1423780\n0x40033EC0 READ    1424167\n0x40088700 WRITE   1424375\n0x40033F00 READ    1424762\n0x40088740 WRITE   1424970\n0x40033F40 READ    1425357\n0x40088780 WRITE   1425565\n0x40033F80 READ    1425952\n0x400887C0 WRITE   1426160\n0x40033FC0 READ    1426547\n0x40088800 WRITE   1426755\n0x40034000 READ    1427172\n0x40088840 WRITE   1427460\n0x40034040 READ    1427847\n0x40034080 READ    1428453\n0x40088940 WRITE   1428660\n0x400340C0 READ    1429047\n0x40088980 WRITE   1429255\n0x40034100 READ    1429642\n0x400889C0 WRITE   1429850\n0x40034140 READ    1430237\n0x40088A00 WRITE   1430445\n0x40034180 READ    1430832\n0x40088A40 WRITE   1431040\n0x400341C0 READ    1431427\n0x40088A80 WRITE   1431635\n0x40034200 READ    1432022\n0x40088AC0 WRITE   1432230\n0x40034240 READ    1432617\n0x40088B00 WRITE   1432825\n0x40034280 READ    1433212\n0x40088B40 WRITE   1433420\n0x400342C0 READ    1433807\n0x40034300 READ    1434415\n0x40088C40 WRITE   1434625\n0x40034340 READ    1435012\n0x40088C80 WRITE   1435220\n0x40034380 READ    1435607\n0x40088CC0 WRITE   1435815\n0x400343C0 READ    1436202\n0x40088D00 WRITE   1436410\n0x40034400 READ    1436797\n0x40088D40 WRITE   1437005\n0x40034440 READ    1437392\n0x40088D80 WRITE   1437600\n0x40034480 READ    1437987\n0x40088DC0 WRITE   1438195\n0x400344C0 READ    1438582\n0x40088E00 WRITE   1438790\n0x40034500 READ    1439177\n0x40088E40 WRITE   1439385\n0x40034540 READ    1439772\n0x40034580 READ    1440378\n0x40088F40 WRITE   1440585\n0x400345C0 READ    1440972\n0x40088F80 WRITE   1441180\n0x40034600 READ    1441567\n0x40088FC0 WRITE   1441775\n0x40034640 READ    1442162\n0x40089000 WRITE   1442370\n0x40034680 READ    1442757\n0x40089040 WRITE   1442965\n0x400346C0 READ    1443352\n0x40089080 WRITE   1443560\n0x40034700 READ    1443947\n0x400890C0 WRITE   1444155\n0x40034740 READ    1444542\n0x40089100 WRITE   1444750\n0x40034780 READ    1445137\n0x40089140 WRITE   1445345\n0x400347C0 READ    1445732\n0x40034800 READ    1446338\n0x40089240 WRITE   1446545\n0x40034840 READ    1446932\n0x40089280 WRITE   1447140\n0x40034880 READ    1447527\n0x400892C0 WRITE   1447735\n0x400348C0 READ    1448122\n0x40089300 WRITE   1448330\n0x40034900 READ    1448717\n0x40089340 WRITE   1448925\n0x40034940 READ    1449312\n0x40089380 WRITE   1449520\n0x40034980 READ    1449907\n0x400893C0 WRITE   1450115\n0x400349C0 READ    1450502\n0x40089400 WRITE   1450710\n0x40034A00 READ    1451097\n0x40089440 WRITE   1451305\n0x40034A40 READ    1451692\n0x40034A80 READ    1452298\n0x40089540 WRITE   1452505\n0x40034AC0 READ    1452892\n0x40089580 WRITE   1453100\n0x40034B00 READ    1453487\n0x400895C0 WRITE   1453695\n0x40034B40 READ    1454082\n0x40089600 WRITE   1454290\n0x40034B80 READ    1454677\n0x40089640 WRITE   1454885\n0x40034BC0 READ    1455272\n0x40089680 WRITE   1455480\n0x40034C00 READ    1455867\n0x400896C0 WRITE   1456075\n0x40034C40 READ    1456462\n0x40089700 WRITE   1456670\n0x40034C80 READ    1457057\n0x40089740 WRITE   1457265\n0x40034CC0 READ    1457652\n0x40034D00 READ    1458260\n0x40089840 WRITE   1458470\n0x40034D40 READ    1458857\n0x40089880 WRITE   1459065\n0x40034D80 READ    1459452\n0x400898C0 WRITE   1459660\n0x40034DC0 READ    1460047\n0x40089900 WRITE   1460255\n0x40034E00 READ    1460642\n0x40089940 WRITE   1460850\n0x40034E40 READ    1461237\n0x40089980 WRITE   1461445\n0x40034E80 READ    1461832\n0x400899C0 WRITE   1462040\n0x40034EC0 READ    1462427\n0x40089A00 WRITE   1462635\n0x40034F00 READ    1463022\n0x40089A40 WRITE   1463230\n0x40034F40 READ    1463617\n0x40034F80 READ    1464223\n0x40089B40 WRITE   1464430\n0x40034FC0 READ    1464817\n0x40089B80 WRITE   1465025\n0x40035000 READ    1465442\n0x40089BC0 WRITE   1465650\n0x40035040 READ    1466037\n0x40089C00 WRITE   1466245\n0x40035080 READ    1466632\n0x40089C40 WRITE   1466840\n0x400350C0 READ    1467227\n0x40089C80 WRITE   1467435\n0x40035100 READ    1467822\n0x40089CC0 WRITE   1468030\n0x40035140 READ    1468417\n0x40089D00 WRITE   1468625\n0x40035180 READ    1469012\n0x40089D40 WRITE   1469220\n0x400351C0 READ    1469607\n0x40035200 READ    1470213\n0x40089E40 WRITE   1470420\n0x40035240 READ    1470807\n0x40089E80 WRITE   1471015\n0x40035280 READ    1471402\n0x40089EC0 WRITE   1471610\n0x400352C0 READ    1471997\n0x40089F00 WRITE   1472205\n0x40035300 READ    1472592\n0x40089F40 WRITE   1472800\n0x40035340 READ    1473187\n0x40089F80 WRITE   1473395\n0x40035380 READ    1473782\n0x40089FC0 WRITE   1473990\n0x400353C0 READ    1474377\n0x4008A000 WRITE   1474585\n0x40035400 READ    1474972\n0x4008A040 WRITE   1475180\n0x40035440 READ    1475567\n0x40035480 READ    1476173\n0x4008A140 WRITE   1476380\n0x400354C0 READ    1476767\n0x4008A180 WRITE   1476975\n0x40035500 READ    1477362\n0x4008A1C0 WRITE   1477570\n0x40035540 READ    1477957\n0x4008A200 WRITE   1478165\n0x40035580 READ    1478552\n0x4008A240 WRITE   1478760\n0x400355C0 READ    1479147\n0x4008A280 WRITE   1479355\n0x40035600 READ    1479742\n0x4008A2C0 WRITE   1479950\n0x40035640 READ    1480337\n0x4008A300 WRITE   1480545\n0x40035680 READ    1480932\n0x4008A340 WRITE   1481140\n0x400356C0 READ    1481527\n0x40035700 READ    1482135\n0x4008A440 WRITE   1482345\n0x40035740 READ    1482732\n0x4008A480 WRITE   1482940\n0x40035780 READ    1483327\n0x4008A4C0 WRITE   1483535\n0x400357C0 READ    1483922\n0x4008A500 WRITE   1484130\n0x40035800 READ    1484517\n0x4008A540 WRITE   1484725\n0x40035840 READ    1485112\n0x4008A580 WRITE   1485320\n0x40035880 READ    1485707\n0x4008A5C0 WRITE   1485915\n0x400358C0 READ    1486302\n0x4008A600 WRITE   1486510\n0x40035900 READ    1486897\n0x4008A640 WRITE   1487105\n0x40035940 READ    1487492\n0x40035980 READ    1488098\n0x4008A740 WRITE   1488305\n0x400359C0 READ    1488692\n0x4008A780 WRITE   1488900\n0x40035A00 READ    1489287\n0x4008A7C0 WRITE   1489495\n0x40035A40 READ    1489882\n0x4008A800 WRITE   1490090\n0x40035A80 READ    1490477\n0x4008A840 WRITE   1490685\n0x40035AC0 READ    1491072\n0x4008A880 WRITE   1491280\n0x40035B00 READ    1491667\n0x4008A8C0 WRITE   1491875\n0x40035B40 READ    1492262\n0x4008A900 WRITE   1492470\n0x40035B80 READ    1492857\n0x4008A940 WRITE   1493065\n0x40035BC0 READ    1493452\n0x40035C00 READ    1494058\n0x4008AA40 WRITE   1494265\n0x40035C40 READ    1494652\n0x4008AA80 WRITE   1494860\n0x40035C80 READ    1495247\n0x4008AAC0 WRITE   1495455\n0x40035CC0 READ    1495842\n0x4008AB00 WRITE   1496050\n0x40035D00 READ    1496437\n0x4008AB40 WRITE   1496645\n0x40035D40 READ    1497032\n0x4008AB80 WRITE   1497240\n0x40035D80 READ    1497627\n0x4008ABC0 WRITE   1497835\n0x40035DC0 READ    1498222\n0x4008AC00 WRITE   1498430\n0x40035E00 READ    1498817\n0x4008AC40 WRITE   1499025\n0x40035E40 READ    1499412\n0x40035E80 READ    1500018\n0x4008AD40 WRITE   1500225\n0x40035EC0 READ    1500612\n0x4008AD80 WRITE   1500820\n0x40035F00 READ    1501207\n0x4008ADC0 WRITE   1501415\n0x40035F40 READ    1501802\n0x4008AE00 WRITE   1502010\n0x40035F80 READ    1502397\n0x4008AE40 WRITE   1502605\n0x40035FC0 READ    1502992\n0x4008AE80 WRITE   1503200\n0x40036000 READ    1503617\n0x4008AEC0 WRITE   1503825\n0x40036040 READ    1504212\n0x4008AF00 WRITE   1504420\n0x40036080 READ    1504807\n0x4008AF40 WRITE   1505015\n0x400360C0 READ    1505402\n0x40036100 READ    1506010\n0x4008B040 WRITE   1506220\n0x40036140 READ    1506607\n0x4008B080 WRITE   1506815\n0x40036180 READ    1507202\n0x4008B0C0 WRITE   1507410\n0x400361C0 READ    1507797\n0x4008B100 WRITE   1508005\n0x40036200 READ    1508392\n0x4008B140 WRITE   1508600\n0x40036240 READ    1508987\n0x4008B180 WRITE   1509195\n0x40036280 READ    1509582\n0x4008B1C0 WRITE   1509790\n0x400362C0 READ    1510177\n0x4008B200 WRITE   1510385\n0x40036300 READ    1510772\n0x4008B240 WRITE   1510980\n0x40036340 READ    1511367\n0x40036380 READ    1511973\n0x4008B340 WRITE   1512180\n0x400363C0 READ    1512567\n0x4008B380 WRITE   1512775\n0x40036400 READ    1513162\n0x4008B3C0 WRITE   1513370\n0x40036440 READ    1513757\n0x4008B400 WRITE   1513965\n0x40036480 READ    1514352\n0x4008B440 WRITE   1514560\n0x400364C0 READ    1514947\n0x4008B480 WRITE   1515155\n0x40036500 READ    1515542\n0x4008B4C0 WRITE   1515750\n0x40036540 READ    1516137\n0x4008B500 WRITE   1516345\n0x40036580 READ    1516732\n0x4008B540 WRITE   1516940\n0x400365C0 READ    1517327\n0x40036600 READ    1517933\n0x4008B640 WRITE   1518140\n0x40036640 READ    1518527\n0x4008B680 WRITE   1518735\n0x40036680 READ    1519122\n0x4008B6C0 WRITE   1519330\n0x400366C0 READ    1519717\n0x4008B700 WRITE   1519925\n0x40036700 READ    1520312\n0x4008B740 WRITE   1520520\n0x40036740 READ    1520907\n0x4008B780 WRITE   1521115\n0x40036780 READ    1521502\n0x4008B7C0 WRITE   1521710\n0x400367C0 READ    1522097\n0x4008B800 WRITE   1522305\n0x40036800 READ    1522692\n0x4008B840 WRITE   1522900\n0x40036840 READ    1523287\n0x40036880 READ    1523893\n0x4008B940 WRITE   1524100\n0x400368C0 READ    1524487\n0x4008B980 WRITE   1524695\n0x40036900 READ    1525082\n0x4008B9C0 WRITE   1525290\n0x40036940 READ    1525677\n0x4008BA00 WRITE   1525885\n0x40036980 READ    1526272\n0x4008BA40 WRITE   1526480\n0x400369C0 READ    1526867\n0x4008BA80 WRITE   1527075\n0x40036A00 READ    1527462\n0x4008BAC0 WRITE   1527670\n0x40036A40 READ    1528057\n0x4008BB00 WRITE   1528265\n0x40036A80 READ    1528652\n0x4008BB40 WRITE   1528860\n0x40036AC0 READ    1529247\n0x40036B00 READ    1529855\n0x4008BC40 WRITE   1530065\n0x40036B40 READ    1530452\n0x4008BC80 WRITE   1530660\n0x40036B80 READ    1531047\n0x4008BCC0 WRITE   1531255\n0x40036BC0 READ    1531642\n0x4008BD00 WRITE   1531850\n0x40036C00 READ    1532237\n0x4008BD40 WRITE   1532445\n0x40036C40 READ    1532832\n0x4008BD80 WRITE   1533040\n0x40036C80 READ    1533427\n0x4008BDC0 WRITE   1533635\n0x40036CC0 READ    1534022\n0x4008BE00 WRITE   1534230\n0x40036D00 READ    1534617\n0x4008BE40 WRITE   1534825\n0x40036D40 READ    1535212\n0x40036D80 READ    1535818\n0x4008BF40 WRITE   1536025\n0x40036DC0 READ    1536412\n0x4008BF80 WRITE   1536620\n0x40036E00 READ    1537007\n0x4008BFC0 WRITE   1537215\n0x40036E40 READ    1537602\n0x4008C000 WRITE   1537810\n0x40036E80 READ    1538197\n0x4008C040 WRITE   1538405\n0x40036EC0 READ    1538792\n0x4008C080 WRITE   1539000\n0x40036F00 READ    1539387\n0x4008C0C0 WRITE   1539595\n0x40036F40 READ    1539982\n0x4008C100 WRITE   1540190\n0x40036F80 READ    1540577\n0x4008C140 WRITE   1540785\n0x40036FC0 READ    1541172\n0x40037000 READ    1541808\n0x4008C240 WRITE   1542015\n0x40037040 READ    1542402\n0x4008C280 WRITE   1542610\n0x40037080 READ    1542997\n0x4008C2C0 WRITE   1543205\n0x400370C0 READ    1543592\n0x4008C300 WRITE   1543800\n0x40037100 READ    1544187\n0x4008C340 WRITE   1544395\n0x40037140 READ    1544782\n0x4008C380 WRITE   1544990\n0x40037180 READ    1545377\n0x4008C3C0 WRITE   1545585\n0x400371C0 READ    1545972\n0x4008C400 WRITE   1546180\n0x40037200 READ    1546567\n0x4008C440 WRITE   1546775\n0x40037240 READ    1547162\n0x40037280 READ    1547768\n0x4008C540 WRITE   1547975\n0x400372C0 READ    1548362\n0x4008C580 WRITE   1548570\n0x40037300 READ    1548957\n0x4008C5C0 WRITE   1549165\n0x40037340 READ    1549552\n0x4008C600 WRITE   1549760\n0x40037380 READ    1550147\n0x4008C640 WRITE   1550355\n0x400373C0 READ    1550742\n0x4008C680 WRITE   1550950\n0x40037400 READ    1551337\n0x4008C6C0 WRITE   1551545\n0x40037440 READ    1551932\n0x4008C700 WRITE   1552140\n0x40037480 READ    1552527\n0x4008C740 WRITE   1552735\n0x400374C0 READ    1553122\n0x40037500 READ    1553730\n0x4008C840 WRITE   1553940\n0x40037540 READ    1554327\n0x4008C880 WRITE   1554535\n0x40037580 READ    1554922\n0x4008C8C0 WRITE   1555130\n0x400375C0 READ    1555517\n0x4008C900 WRITE   1555725\n0x40037600 READ    1556112\n0x4008C940 WRITE   1556320\n0x40037640 READ    1556707\n0x4008C980 WRITE   1556915\n0x40037680 READ    1557302\n0x4008C9C0 WRITE   1557510\n0x400376C0 READ    1557897\n0x4008CA00 WRITE   1558105\n0x40037700 READ    1558492\n0x4008CA40 WRITE   1558700\n0x40037740 READ    1559087\n0x40037780 READ    1559693\n0x4008CB40 WRITE   1559900\n0x400377C0 READ    1560287\n0x4008CB80 WRITE   1560495\n0x40037800 READ    1560882\n0x4008CBC0 WRITE   1561090\n0x40037840 READ    1561477\n0x4008CC00 WRITE   1561685\n0x40037880 READ    1562072\n0x4008CC40 WRITE   1562280\n0x400378C0 READ    1562667\n0x4008CC80 WRITE   1562875\n0x40037900 READ    1563262\n0x4008CCC0 WRITE   1563470\n0x40037940 READ    1563857\n0x4008CD00 WRITE   1564065\n0x40037980 READ    1564452\n0x4008CD40 WRITE   1564660\n0x400379C0 READ    1565047\n0x40037A00 READ    1565653\n0x4008CE40 WRITE   1565860\n0x40037A40 READ    1566247\n0x4008CE80 WRITE   1566455\n0x40037A80 READ    1566842\n0x4008CEC0 WRITE   1567050\n0x40037AC0 READ    1567437\n0x4008CF00 WRITE   1567645\n0x40037B00 READ    1568032\n0x4008CF40 WRITE   1568240\n0x40037B40 READ    1568627\n0x4008CF80 WRITE   1568835\n0x40037B80 READ    1569222\n0x4008CFC0 WRITE   1569430\n0x40037BC0 READ    1569817\n0x4008D000 WRITE   1570025\n0x40037C00 READ    1570412\n0x4008D040 WRITE   1570620\n0x40037C40 READ    1571007\n0x40037C80 READ    1571613\n0x4008D140 WRITE   1571820\n0x40037CC0 READ    1572207\n0x4008D180 WRITE   1572415\n0x40037D00 READ    1572802\n0x4008D1C0 WRITE   1573010\n0x40037D40 READ    1573397\n0x4008D200 WRITE   1573605\n0x40037D80 READ    1573992\n0x4008D240 WRITE   1574200\n0x40037DC0 READ    1574587\n0x4008D280 WRITE   1574795\n0x40037E00 READ    1575182\n0x4008D2C0 WRITE   1575390\n0x40037E40 READ    1575777\n0x4008D300 WRITE   1575985\n0x40037E80 READ    1576372\n0x4008D340 WRITE   1576580\n0x40037EC0 READ    1576967\n0x40037F00 READ    1577575\n0x4008D440 WRITE   1577785\n0x40037F40 READ    1578172\n0x4008D480 WRITE   1578380\n0x40037F80 READ    1578767\n0x4008D4C0 WRITE   1578975\n0x40037FC0 READ    1579362\n0x4008D500 WRITE   1579570\n0x40038000 READ    1579987\n0x4008D540 WRITE   1580275\n0x40038040 READ    1580662\n0x4008D580 WRITE   1580870\n0x40038080 READ    1581257\n0x4008D5C0 WRITE   1581465\n0x400380C0 READ    1581852\n0x4008D600 WRITE   1582060\n0x40038100 READ    1582447\n0x4008D640 WRITE   1582655\n0x40038140 READ    1583042\n0x40038180 READ    1583648\n0x4008D740 WRITE   1583855\n0x400381C0 READ    1584242\n0x4008D780 WRITE   1584450\n0x40038200 READ    1584837\n0x4008D7C0 WRITE   1585045\n0x40038240 READ    1585432\n0x4008D800 WRITE   1585640\n0x40038280 READ    1586027\n0x4008D840 WRITE   1586235\n0x400382C0 READ    1586622\n0x4008D880 WRITE   1586830\n0x40038300 READ    1587217\n0x4008D8C0 WRITE   1587425\n0x40038340 READ    1587812\n0x4008D900 WRITE   1588020\n0x40038380 READ    1588407\n0x4008D940 WRITE   1588615\n0x400383C0 READ    1589002\n0x40038400 READ    1589608\n0x4008DA40 WRITE   1589815\n0x40038440 READ    1590202\n0x4008DA80 WRITE   1590410\n0x40038480 READ    1590797\n0x4008DAC0 WRITE   1591005\n0x400384C0 READ    1591392\n0x4008DB00 WRITE   1591600\n0x40038500 READ    1591987\n0x4008DB40 WRITE   1592195\n0x40038540 READ    1592582\n0x4008DB80 WRITE   1592790\n0x40038580 READ    1593177\n0x4008DBC0 WRITE   1593385\n0x400385C0 READ    1593772\n0x4008DC00 WRITE   1593980\n0x40038600 READ    1594367\n0x4008DC40 WRITE   1594575\n0x40038640 READ    1594962\n0x40038680 READ    1595568\n0x4008DD40 WRITE   1595775\n0x400386C0 READ    1596162\n0x4008DD80 WRITE   1596370\n0x40038700 READ    1596757\n0x4008DDC0 WRITE   1596965\n0x40038740 READ    1597352\n0x4008DE00 WRITE   1597560\n0x40038780 READ    1597947\n0x4008DE40 WRITE   1598155\n0x400387C0 READ    1598542\n0x4008DE80 WRITE   1598750\n0x40038800 READ    1599137\n0x4008DEC0 WRITE   1599345\n0x40038840 READ    1599732\n0x4008DF00 WRITE   1599940\n0x40038880 READ    1600327\n0x4008DF40 WRITE   1600535\n0x400388C0 READ    1600922\n0x40038900 READ    1601530\n0x4008E040 WRITE   1601740\n0x40038940 READ    1602127\n0x4008E080 WRITE   1602335\n0x40038980 READ    1602722\n0x4008E0C0 WRITE   1602930\n0x400389C0 READ    1603317\n0x4008E100 WRITE   1603525\n0x40038A00 READ    1603912\n0x4008E140 WRITE   1604120\n0x40038A40 READ    1604507\n0x4008E180 WRITE   1604715\n0x40038A80 READ    1605102\n0x4008E1C0 WRITE   1605310\n0x40038AC0 READ    1605697\n0x4008E200 WRITE   1605905\n0x40038B00 READ    1606292\n0x4008E240 WRITE   1606500\n0x40038B40 READ    1606887\n0x40038B80 READ    1607493\n0x4008E340 WRITE   1607700\n0x40038BC0 READ    1608087\n0x4008E380 WRITE   1608295\n0x40038C00 READ    1608682\n0x4008E3C0 WRITE   1608890\n0x40038C40 READ    1609277\n0x4008E400 WRITE   1609485\n0x40038C80 READ    1609872\n0x4008E440 WRITE   1610080\n0x40038CC0 READ    1610467\n0x4008E480 WRITE   1610675\n0x40038D00 READ    1611062\n0x4008E4C0 WRITE   1611270\n0x40038D40 READ    1611657\n0x4008E500 WRITE   1611865\n0x40038D80 READ    1612252\n0x4008E540 WRITE   1612460\n0x40038DC0 READ    1612847\n0x40038E00 READ    1613453\n0x4008E640 WRITE   1613660\n0x40038E40 READ    1614047\n0x4008E680 WRITE   1614255\n0x40038E80 READ    1614642\n0x4008E6C0 WRITE   1614850\n0x40038EC0 READ    1615237\n0x4008E700 WRITE   1615445\n0x40038F00 READ    1615832\n0x4008E740 WRITE   1616040\n0x40038F40 READ    1616427\n0x4008E780 WRITE   1616635\n0x40038F80 READ    1617022\n0x4008E7C0 WRITE   1617230\n0x40038FC0 READ    1617617\n0x4008E800 WRITE   1617825\n0x40039000 READ    1618242\n0x4008E840 WRITE   1618450\n0x40039040 READ    1618837\n0x40039080 READ    1619443\n0x4008E940 WRITE   1619650\n0x400390C0 READ    1620037\n0x4008E980 WRITE   1620245\n0x40039100 READ    1620632\n0x4008E9C0 WRITE   1620840\n0x40039140 READ    1621227\n0x4008EA00 WRITE   1621435\n0x40039180 READ    1621822\n0x4008EA40 WRITE   1622030\n0x400391C0 READ    1622417\n0x4008EA80 WRITE   1622625\n0x40039200 READ    1623012\n0x4008EAC0 WRITE   1623220\n0x40039240 READ    1623607\n0x4008EB00 WRITE   1623815\n0x40039280 READ    1624202\n0x4008EB40 WRITE   1624410\n0x400392C0 READ    1624797\n0x40039300 READ    1625405\n0x4008EC40 WRITE   1625615\n0x40039340 READ    1626002\n0x4008EC80 WRITE   1626210\n0x40039380 READ    1626597\n0x4008ECC0 WRITE   1626805\n0x400393C0 READ    1627192\n0x4008ED00 WRITE   1627400\n0x40039400 READ    1627787\n0x4008ED40 WRITE   1627995\n0x40039440 READ    1628382\n0x4008ED80 WRITE   1628590\n0x40039480 READ    1628977\n0x4008EDC0 WRITE   1629185\n0x400394C0 READ    1629572\n0x4008EE00 WRITE   1629780\n0x40039500 READ    1630167\n0x4008EE40 WRITE   1630375\n0x40039540 READ    1630762\n0x40039580 READ    1631368\n0x4008EF40 WRITE   1631575\n0x400395C0 READ    1631962\n0x4008EF80 WRITE   1632170\n0x40039600 READ    1632557\n0x4008EFC0 WRITE   1632765\n0x40039640 READ    1633152\n0x4008F000 WRITE   1633360\n0x40039680 READ    1633747\n0x4008F040 WRITE   1633955\n0x400396C0 READ    1634342\n0x4008F080 WRITE   1634550\n0x40039700 READ    1634937\n0x4008F0C0 WRITE   1635145\n0x40039740 READ    1635532\n0x4008F100 WRITE   1635740\n0x40039780 READ    1636127\n0x4008F140 WRITE   1636335\n0x400397C0 READ    1636722\n0x40039800 READ    1637328\n0x4008F240 WRITE   1637535\n0x40039840 READ    1637922\n0x4008F280 WRITE   1638130\n0x40039880 READ    1638517\n0x4008F2C0 WRITE   1638725\n0x400398C0 READ    1639112\n0x4008F300 WRITE   1639320\n0x40039900 READ    1639707\n0x4008F340 WRITE   1639915\n0x40039940 READ    1640302\n0x4008F380 WRITE   1640510\n0x40039980 READ    1640897\n0x4008F3C0 WRITE   1641105\n0x400399C0 READ    1641492\n0x4008F400 WRITE   1641700\n0x40039A00 READ    1642087\n0x4008F440 WRITE   1642295\n0x40039A40 READ    1642682\n0x40039A80 READ    1643288\n0x4008F540 WRITE   1643495\n0x40039AC0 READ    1643882\n0x4008F580 WRITE   1644090\n0x40039B00 READ    1644477\n0x4008F5C0 WRITE   1644685\n0x40039B40 READ    1645072\n0x4008F600 WRITE   1645280\n0x40039B80 READ    1645667\n0x4008F640 WRITE   1645875\n0x40039BC0 READ    1646262\n0x4008F680 WRITE   1646470\n0x40039C00 READ    1646857\n0x4008F6C0 WRITE   1647065\n0x40039C40 READ    1647452\n0x4008F700 WRITE   1647660\n0x40039C80 READ    1648047\n0x4008F740 WRITE   1648255\n0x40039CC0 READ    1648642\n0x40039D00 READ    1649250\n0x4008F840 WRITE   1649460\n0x40039D40 READ    1649847\n0x4008F880 WRITE   1650055\n0x40039D80 READ    1650442\n0x4008F8C0 WRITE   1650650\n0x40039DC0 READ    1651037\n0x4008F900 WRITE   1651245\n0x40039E00 READ    1651632\n0x4008F940 WRITE   1651840\n0x40039E40 READ    1652227\n0x4008F980 WRITE   1652435\n0x40039E80 READ    1652822\n0x4008F9C0 WRITE   1653030\n0x40039EC0 READ    1653417\n0x4008FA00 WRITE   1653625\n0x40039F00 READ    1654012\n0x4008FA40 WRITE   1654220\n0x40039F40 READ    1654607\n0x40039F80 READ    1655213\n0x4008FB40 WRITE   1655420\n0x40039FC0 READ    1655807\n0x4008FB80 WRITE   1656015\n0x4003A000 READ    1656432\n0x4008FBC0 WRITE   1656640\n0x4003A040 READ    1657027\n0x4008FC00 WRITE   1657235\n0x4003A080 READ    1657622\n0x4008FC40 WRITE   1657830\n0x4003A0C0 READ    1658217\n0x4008FC80 WRITE   1658425\n0x4003A100 READ    1658812\n0x4008FCC0 WRITE   1659020\n0x4003A140 READ    1659407\n0x4008FD00 WRITE   1659615\n0x4003A180 READ    1660002\n0x4008FD40 WRITE   1660210\n0x4003A1C0 READ    1660597\n0x4003A200 READ    1661203\n0x4008FE40 WRITE   1661410\n0x4003A240 READ    1661797\n0x4008FE80 WRITE   1662005\n0x4003A280 READ    1662392\n0x4008FEC0 WRITE   1662600\n0x4003A2C0 READ    1662987\n0x4008FF00 WRITE   1663195\n0x4003A300 READ    1663582\n0x4008FF40 WRITE   1663790\n0x4003A340 READ    1664177\n0x4008FF80 WRITE   1664385\n0x4003A380 READ    1664772\n0x4008FFC0 WRITE   1664980\n0x4003A3C0 READ    1665367\n0x40090000 WRITE   1665575\n0x4003A400 READ    1665962\n0x40090040 WRITE   1666170\n0x4003A440 READ    1666557\n0x4003A480 READ    1667163\n0x40090140 WRITE   1667370\n0x4003A4C0 READ    1667757\n0x40090180 WRITE   1667965\n0x4003A500 READ    1668352\n0x400901C0 WRITE   1668560\n0x4003A540 READ    1668947\n0x40090200 WRITE   1669155\n0x4003A580 READ    1669542\n0x40090240 WRITE   1669750\n0x4003A5C0 READ    1670137\n0x40090280 WRITE   1670345\n0x4003A600 READ    1670732\n0x400902C0 WRITE   1670940\n0x4003A640 READ    1671327\n0x40090300 WRITE   1671535\n0x4003A680 READ    1671922\n0x40090340 WRITE   1672130\n0x4003A6C0 READ    1672517\n0x4003A700 READ    1673125\n0x40090440 WRITE   1673335\n0x4003A740 READ    1673722\n0x40090480 WRITE   1673930\n0x4003A780 READ    1674317\n0x400904C0 WRITE   1674525\n0x4003A7C0 READ    1674912\n0x40090500 WRITE   1675120\n0x4003A800 READ    1675507\n0x40090540 WRITE   1675715\n0x4003A840 READ    1676102\n0x40090580 WRITE   1676310\n0x4003A880 READ    1676697\n0x400905C0 WRITE   1676905\n0x4003A8C0 READ    1677292\n0x40090600 WRITE   1677500\n0x4003A900 READ    1677887\n0x40090640 WRITE   1678095\n0x4003A940 READ    1678482\n0x4003A980 READ    1679088\n0x40090740 WRITE   1679295\n0x4003A9C0 READ    1679682\n0x40090780 WRITE   1679890\n0x4003AA00 READ    1680277\n0x400907C0 WRITE   1680485\n0x4003AA40 READ    1680872\n0x40090800 WRITE   1681080\n0x4003AA80 READ    1681467\n0x40090840 WRITE   1681675\n0x4003AAC0 READ    1682062\n0x40090880 WRITE   1682270\n0x4003AB00 READ    1682657\n0x400908C0 WRITE   1682865\n0x4003AB40 READ    1683252\n0x40090900 WRITE   1683460\n0x4003AB80 READ    1683847\n0x40090940 WRITE   1684055\n0x4003ABC0 READ    1684442\n0x4003AC00 READ    1685048\n0x40090A40 WRITE   1685255\n0x4003AC40 READ    1685642\n0x40090A80 WRITE   1685850\n0x4003AC80 READ    1686237\n0x40090AC0 WRITE   1686445\n0x4003ACC0 READ    1686832\n0x40090B00 WRITE   1687040\n0x4003AD00 READ    1687427\n0x40090B40 WRITE   1687635\n0x4003AD40 READ    1688022\n0x40090B80 WRITE   1688230\n0x4003AD80 READ    1688617\n0x40090BC0 WRITE   1688825\n0x4003ADC0 READ    1689212\n0x40090C00 WRITE   1689420\n0x4003AE00 READ    1689807\n0x40090C40 WRITE   1690015\n0x4003AE40 READ    1690402\n0x4003AE80 READ    1691008\n0x40090D40 WRITE   1691215\n0x4003AEC0 READ    1691602\n0x40090D80 WRITE   1691810\n0x4003AF00 READ    1692197\n0x40090DC0 WRITE   1692405\n0x4003AF40 READ    1692792\n0x40090E00 WRITE   1693000\n0x4003AF80 READ    1693387\n0x40090E40 WRITE   1693595\n0x4003AFC0 READ    1693982\n0x40090E80 WRITE   1694190\n0x4003B000 READ    1694607\n0x40090EC0 WRITE   1694815\n0x4003B040 READ    1695202\n0x40090F00 WRITE   1695410\n0x4003B080 READ    1695797\n0x40090F40 WRITE   1696005\n0x4003B0C0 READ    1696392\n0x4003B100 READ    1697000\n0x40091040 WRITE   1697210\n0x4003B140 READ    1697597\n0x40091080 WRITE   1697805\n0x4003B180 READ    1698192\n0x400910C0 WRITE   1698400\n0x4003B1C0 READ    1698787\n0x40091100 WRITE   1698995\n0x4003B200 READ    1699382\n0x40091140 WRITE   1699590\n0x4003B240 READ    1699977\n0x40091180 WRITE   1700185\n0x4003B280 READ    1700572\n0x400911C0 WRITE   1700780\n0x4003B2C0 READ    1701167\n0x40091200 WRITE   1701375\n0x4003B300 READ    1701762\n0x40091240 WRITE   1701970\n0x4003B340 READ    1702357\n0x4003B380 READ    1702963\n0x40091340 WRITE   1703170\n0x4003B3C0 READ    1703557\n0x40091380 WRITE   1703765\n0x4003B400 READ    1704152\n0x400913C0 WRITE   1704360\n0x4003B440 READ    1704747\n0x40091400 WRITE   1704955\n0x4003B480 READ    1705342\n0x40091440 WRITE   1705550\n0x4003B4C0 READ    1705937\n0x40091480 WRITE   1706145\n0x4003B500 READ    1706532\n0x400914C0 WRITE   1706740\n0x4003B540 READ    1707127\n0x40091500 WRITE   1707335\n0x4003B580 READ    1707722\n0x40091540 WRITE   1707930\n0x4003B5C0 READ    1708317\n0x4003B600 READ    1708923\n0x40091640 WRITE   1709130\n0x4003B640 READ    1709517\n0x40091680 WRITE   1709725\n0x4003B680 READ    1710112\n0x400916C0 WRITE   1710320\n0x4003B6C0 READ    1710707\n0x40091700 WRITE   1710915\n0x4003B700 READ    1711302\n0x40091740 WRITE   1711510\n0x4003B740 READ    1711897\n0x40091780 WRITE   1712105\n0x4003B780 READ    1712492\n0x400917C0 WRITE   1712700\n0x4003B7C0 READ    1713087\n0x40091800 WRITE   1713295\n0x4003B800 READ    1713682\n0x40091840 WRITE   1713890\n0x4003B840 READ    1714277\n0x4003B880 READ    1714883\n0x40091940 WRITE   1715090\n0x4003B8C0 READ    1715477\n0x40091980 WRITE   1715685\n0x4003B900 READ    1716072\n0x400919C0 WRITE   1716280\n0x4003B940 READ    1716667\n0x40091A00 WRITE   1716875\n0x4003B980 READ    1717262\n0x40091A40 WRITE   1717470\n0x4003B9C0 READ    1717857\n0x40091A80 WRITE   1718065\n0x4003BA00 READ    1718452\n0x40091AC0 WRITE   1718660\n0x4003BA40 READ    1719047\n0x40091B00 WRITE   1719255\n0x4003BA80 READ    1719642\n0x40091B40 WRITE   1719850\n0x4003BAC0 READ    1720237\n0x4003BB00 READ    1720845\n0x40091C40 WRITE   1721055\n0x4003BB40 READ    1721442\n0x40091C80 WRITE   1721650\n0x4003BB80 READ    1722037\n0x40091CC0 WRITE   1722245\n0x4003BBC0 READ    1722632\n0x40091D00 WRITE   1722840\n0x4003BC00 READ    1723227\n0x40091D40 WRITE   1723435\n0x4003BC40 READ    1723822\n0x40091D80 WRITE   1724030\n0x4003BC80 READ    1724417\n0x40091DC0 WRITE   1724625\n0x4003BCC0 READ    1725012\n0x40091E00 WRITE   1725220\n0x4003BD00 READ    1725607\n0x40091E40 WRITE   1725815\n0x4003BD40 READ    1726202\n0x4003BD80 READ    1726808\n0x40091F40 WRITE   1727015\n0x4003BDC0 READ    1727402\n0x40091F80 WRITE   1727610\n0x4003BE00 READ    1727997\n0x40091FC0 WRITE   1728205\n0x4003BE40 READ    1728592\n0x40092000 WRITE   1728800\n0x4003BE80 READ    1729187\n0x40092040 WRITE   1729395\n0x4003BEC0 READ    1729782\n0x40092080 WRITE   1729990\n0x4003BF00 READ    1730377\n0x400920C0 WRITE   1730585\n0x4003BF40 READ    1730972\n0x40092100 WRITE   1731180\n0x4003BF80 READ    1731567\n0x40092140 WRITE   1731775\n0x4003BFC0 READ    1732162\n0x4003C000 READ    1732798\n0x40092240 WRITE   1733085\n0x4003C040 READ    1733472\n0x40092280 WRITE   1733680\n0x4003C080 READ    1734067\n0x400922C0 WRITE   1734275\n0x4003C0C0 READ    1734662\n0x40092300 WRITE   1734870\n0x4003C100 READ    1735257\n0x40092340 WRITE   1735465\n0x4003C140 READ    1735852\n0x40092380 WRITE   1736060\n0x4003C180 READ    1736447\n0x400923C0 WRITE   1736655\n0x4003C1C0 READ    1737042\n0x40092400 WRITE   1737250\n0x4003C200 READ    1737637\n0x40092440 WRITE   1737845\n0x4003C240 READ    1738232\n0x4003C280 READ    1738838\n0x40092540 WRITE   1739045\n0x4003C2C0 READ    1739432\n0x40092580 WRITE   1739640\n0x4003C300 READ    1740027\n0x400925C0 WRITE   1740235\n0x4003C340 READ    1740622\n0x40092600 WRITE   1740830\n0x4003C380 READ    1741217\n0x40092640 WRITE   1741425\n0x4003C3C0 READ    1741812\n0x40092680 WRITE   1742020\n0x4003C400 READ    1742407\n0x400926C0 WRITE   1742615\n0x4003C440 READ    1743002\n0x40092700 WRITE   1743210\n0x4003C480 READ    1743597\n0x40092740 WRITE   1743805\n0x4003C4C0 READ    1744192\n0x4003C500 READ    1744800\n0x40092840 WRITE   1745010\n0x4003C540 READ    1745397\n0x40092880 WRITE   1745605\n0x4003C580 READ    1745992\n0x400928C0 WRITE   1746200\n0x4003C5C0 READ    1746587\n0x40092900 WRITE   1746795\n0x4003C600 READ    1747182\n0x40092940 WRITE   1747390\n0x4003C640 READ    1747777\n0x40092980 WRITE   1747985\n0x4003C680 READ    1748372\n0x400929C0 WRITE   1748580\n0x4003C6C0 READ    1748967\n0x40092A00 WRITE   1749175\n0x4003C700 READ    1749562\n0x40092A40 WRITE   1749770\n0x4003C740 READ    1750157\n0x4003C780 READ    1750763\n0x40092B40 WRITE   1750970\n0x4003C7C0 READ    1751357\n0x40092B80 WRITE   1751565\n0x4003C800 READ    1751952\n0x40092BC0 WRITE   1752160\n0x4003C840 READ    1752547\n0x40092C00 WRITE   1752755\n0x4003C880 READ    1753142\n0x40092C40 WRITE   1753350\n0x4003C8C0 READ    1753737\n0x40092C80 WRITE   1753945\n0x4003C900 READ    1754332\n0x40092CC0 WRITE   1754540\n0x4003C940 READ    1754927\n0x40092D00 WRITE   1755135\n0x4003C980 READ    1755522\n0x40092D40 WRITE   1755730\n0x4003C9C0 READ    1756117\n0x4003CA00 READ    1756723\n0x40092E40 WRITE   1756930\n0x4003CA40 READ    1757317\n0x40092E80 WRITE   1757525\n0x4003CA80 READ    1757912\n0x40092EC0 WRITE   1758120\n0x4003CAC0 READ    1758507\n0x40092F00 WRITE   1758715\n0x4003CB00 READ    1759102\n0x40092F40 WRITE   1759310\n0x4003CB40 READ    1759697\n0x40092F80 WRITE   1759905\n0x4003CB80 READ    1760292\n0x40092FC0 WRITE   1760500\n0x4003CBC0 READ    1760887\n0x40093000 WRITE   1761095\n0x4003CC00 READ    1761482\n0x40093040 WRITE   1761690\n0x4003CC40 READ    1762077\n0x4003CC80 READ    1762683\n0x40093140 WRITE   1762890\n0x4003CCC0 READ    1763277\n0x40093180 WRITE   1763485\n0x4003CD00 READ    1763872\n0x400931C0 WRITE   1764080\n0x4003CD40 READ    1764467\n0x40093200 WRITE   1764675\n0x4003CD80 READ    1765062\n0x40093240 WRITE   1765270\n0x4003CDC0 READ    1765657\n0x40093280 WRITE   1765865\n0x4003CE00 READ    1766252\n0x400932C0 WRITE   1766460\n0x4003CE40 READ    1766847\n0x40093300 WRITE   1767055\n0x4003CE80 READ    1767442\n0x40093340 WRITE   1767650\n0x4003CEC0 READ    1768037\n0x4003CF00 READ    1768645\n0x40093440 WRITE   1768855\n0x4003CF40 READ    1769242\n0x40093480 WRITE   1769450\n0x4003CF80 READ    1769837\n0x400934C0 WRITE   1770045\n0x4003CFC0 READ    1770432\n0x40093500 WRITE   1770640\n0x4003D000 READ    1771057\n0x40093540 WRITE   1771265\n0x4003D040 READ    1771652\n0x40093580 WRITE   1771860\n0x4003D080 READ    1772247\n0x400935C0 WRITE   1772455\n0x4003D0C0 READ    1772842\n0x40093600 WRITE   1773050\n0x4003D100 READ    1773437\n0x40093640 WRITE   1773645\n0x4003D140 READ    1774032\n0x4003D180 READ    1774638\n0x40093740 WRITE   1774845\n0x4003D1C0 READ    1775232\n0x40093780 WRITE   1775440\n0x4003D200 READ    1775827\n0x400937C0 WRITE   1776035\n0x4003D240 READ    1776422\n0x40093800 WRITE   1776630\n0x4003D280 READ    1777017\n0x40093840 WRITE   1777225\n0x4003D2C0 READ    1777612\n0x40093880 WRITE   1777820\n0x4003D300 READ    1778207\n0x400938C0 WRITE   1778415\n0x4003D340 READ    1778802\n0x40093900 WRITE   1779010\n0x4003D380 READ    1779397\n0x40093940 WRITE   1779605\n0x4003D3C0 READ    1779992\n0x4003D400 READ    1780598\n0x40093A40 WRITE   1780805\n0x4003D440 READ    1781192\n0x40093A80 WRITE   1781400\n0x4003D480 READ    1781787\n0x40093AC0 WRITE   1781995\n0x4003D4C0 READ    1782382\n0x40093B00 WRITE   1782590\n0x4003D500 READ    1782977\n0x40093B40 WRITE   1783185\n0x4003D540 READ    1783572\n0x40093B80 WRITE   1783780\n0x4003D580 READ    1784167\n0x40093BC0 WRITE   1784375\n0x4003D5C0 READ    1784762\n0x40093C00 WRITE   1784970\n0x4003D600 READ    1785357\n0x40093C40 WRITE   1785565\n0x4003D640 READ    1785952\n0x4003D680 READ    1786558\n0x40093D40 WRITE   1786765\n0x4003D6C0 READ    1787152\n0x40093D80 WRITE   1787360\n0x4003D700 READ    1787747\n0x40093DC0 WRITE   1787955\n0x4003D740 READ    1788342\n0x40093E00 WRITE   1788550\n0x4003D780 READ    1788937\n0x40093E40 WRITE   1789145\n0x4003D7C0 READ    1789532\n0x40093E80 WRITE   1789740\n0x4003D800 READ    1790127\n0x40093EC0 WRITE   1790335\n0x4003D840 READ    1790722\n0x40093F00 WRITE   1790930\n0x4003D880 READ    1791317\n0x40093F40 WRITE   1791525\n0x4003D8C0 READ    1791912\n0x4003D900 READ    1792520\n0x40094040 WRITE   1792730\n0x4003D940 READ    1793117\n0x40094080 WRITE   1793325\n0x4003D980 READ    1793712\n0x400940C0 WRITE   1793920\n0x4003D9C0 READ    1794307\n0x40094100 WRITE   1794515\n0x4003DA00 READ    1794902\n0x40094140 WRITE   1795110\n0x4003DA40 READ    1795497\n0x40094180 WRITE   1795705\n0x4003DA80 READ    1796092\n0x400941C0 WRITE   1796300\n0x4003DAC0 READ    1796687\n0x40094200 WRITE   1796895\n0x4003DB00 READ    1797282\n0x40094240 WRITE   1797490\n0x4003DB40 READ    1797877\n0x4003DB80 READ    1798483\n0x40094340 WRITE   1798690\n0x4003DBC0 READ    1799077\n0x40094380 WRITE   1799285\n0x4003DC00 READ    1799672\n0x400943C0 WRITE   1799880\n0x4003DC40 READ    1800267\n0x40094400 WRITE   1800475\n0x4003DC80 READ    1800862\n0x40094440 WRITE   1801070\n0x4003DCC0 READ    1801457\n0x40094480 WRITE   1801665\n0x4003DD00 READ    1802052\n0x400944C0 WRITE   1802260\n0x4003DD40 READ    1802647\n0x40094500 WRITE   1802855\n0x4003DD80 READ    1803242\n0x40094540 WRITE   1803450\n0x4003DDC0 READ    1803837\n0x4003DE00 READ    1804443\n0x40094640 WRITE   1804650\n0x4003DE40 READ    1805037\n0x40094680 WRITE   1805245\n0x4003DE80 READ    1805632\n0x400946C0 WRITE   1805840\n0x4003DEC0 READ    1806227\n0x40094700 WRITE   1806435\n0x4003DF00 READ    1806822\n0x40094740 WRITE   1807030\n0x4003DF40 READ    1807417\n0x40094780 WRITE   1807625\n0x4003DF80 READ    1808012\n0x400947C0 WRITE   1808220\n0x4003DFC0 READ    1808607\n0x40094800 WRITE   1808815\n0x4003E000 READ    1809232\n0x40094840 WRITE   1809440\n0x4003E040 READ    1809827\n0x4003E080 READ    1810433\n0x40094940 WRITE   1810640\n0x4003E0C0 READ    1811027\n0x40094980 WRITE   1811235\n0x4003E100 READ    1811622\n0x400949C0 WRITE   1811830\n0x4003E140 READ    1812217\n0x40094A00 WRITE   1812425\n0x4003E180 READ    1812812\n0x40094A40 WRITE   1813020\n0x4003E1C0 READ    1813407\n0x40094A80 WRITE   1813615\n0x4003E200 READ    1814002\n0x40094AC0 WRITE   1814210\n0x4003E240 READ    1814597\n0x40094B00 WRITE   1814805\n0x4003E280 READ    1815192\n0x40094B40 WRITE   1815400\n0x4003E2C0 READ    1815787\n0x4003E300 READ    1816395\n0x40094C40 WRITE   1816605\n0x4003E340 READ    1816992\n0x40094C80 WRITE   1817200\n0x4003E380 READ    1817587\n0x40094CC0 WRITE   1817795\n0x4003E3C0 READ    1818182\n0x40094D00 WRITE   1818390\n0x4003E400 READ    1818777\n0x40094D40 WRITE   1818985\n0x4003E440 READ    1819372\n0x40094D80 WRITE   1819580\n0x4003E480 READ    1819967\n0x40094DC0 WRITE   1820175\n0x4003E4C0 READ    1820562\n0x40094E00 WRITE   1820770\n0x4003E500 READ    1821157\n0x40094E40 WRITE   1821365\n0x4003E540 READ    1821752\n0x4003E580 READ    1822358\n0x40094F40 WRITE   1822565\n0x4003E5C0 READ    1822952\n0x40094F80 WRITE   1823160\n0x4003E600 READ    1823547\n0x40094FC0 WRITE   1823755\n0x4003E640 READ    1824142\n0x40095000 WRITE   1824350\n0x4003E680 READ    1824737\n0x40095040 WRITE   1824945\n0x4003E6C0 READ    1825332\n0x40095080 WRITE   1825540\n0x4003E700 READ    1825927\n0x400950C0 WRITE   1826135\n0x4003E740 READ    1826522\n0x40095100 WRITE   1826730\n0x4003E780 READ    1827117\n0x40095140 WRITE   1827325\n0x4003E7C0 READ    1827712\n0x4003E800 READ    1828318\n0x40095240 WRITE   1828525\n0x4003E840 READ    1828912\n0x40095280 WRITE   1829120\n0x4003E880 READ    1829507\n0x400952C0 WRITE   1829715\n0x4003E8C0 READ    1830102\n0x40095300 WRITE   1830310\n0x4003E900 READ    1830697\n0x40095340 WRITE   1830905\n0x4003E940 READ    1831292\n0x40095380 WRITE   1831500\n0x4003E980 READ    1831887\n0x400953C0 WRITE   1832095\n0x4003E9C0 READ    1832482\n0x40095400 WRITE   1832690\n0x4003EA00 READ    1833077\n0x40095440 WRITE   1833285\n0x4003EA40 READ    1833672\n0x4003EA80 READ    1834278\n0x40095540 WRITE   1834485\n0x4003EAC0 READ    1834872\n0x40095580 WRITE   1835080\n0x4003EB00 READ    1835467\n0x400955C0 WRITE   1835675\n0x4003EB40 READ    1836062\n0x40095600 WRITE   1836270\n0x4003EB80 READ    1836657\n0x40095640 WRITE   1836865\n0x4003EBC0 READ    1837252\n0x40095680 WRITE   1837460\n0x4003EC00 READ    1837847\n0x400956C0 WRITE   1838055\n0x4003EC40 READ    1838442\n0x40095700 WRITE   1838650\n0x4003EC80 READ    1839037\n0x40095740 WRITE   1839245\n0x4003ECC0 READ    1839632\n0x4003ED00 READ    1840240\n0x40095840 WRITE   1840450\n0x4003ED40 READ    1840837\n0x40095880 WRITE   1841045\n0x4003ED80 READ    1841432\n0x400958C0 WRITE   1841640\n0x4003EDC0 READ    1842027\n0x40095900 WRITE   1842235\n0x4003EE00 READ    1842622\n0x40095940 WRITE   1842830\n0x4003EE40 READ    1843217\n0x40095980 WRITE   1843425\n0x4003EE80 READ    1843812\n0x400959C0 WRITE   1844020\n0x4003EEC0 READ    1844407\n0x40095A00 WRITE   1844615\n0x4003EF00 READ    1845002\n0x40095A40 WRITE   1845210\n0x4003EF40 READ    1845597\n0x4003EF80 READ    1846203\n0x40095B40 WRITE   1846410\n0x4003EFC0 READ    1846797\n0x40095B80 WRITE   1847005\n0x4003F000 READ    1847422\n0x40095BC0 WRITE   1847630\n0x4003F040 READ    1848017\n0x40095C00 WRITE   1848225\n0x4003F080 READ    1848612\n0x40095C40 WRITE   1848820\n0x4003F0C0 READ    1849207\n0x40095C80 WRITE   1849415\n0x4003F100 READ    1849802\n0x40095CC0 WRITE   1850010\n0x4003F140 READ    1850397\n0x40095D00 WRITE   1850605\n0x4003F180 READ    1850992\n0x40095D40 WRITE   1851200\n0x4003F1C0 READ    1851587\n0x4003F200 READ    1852193\n0x40095E40 WRITE   1852400\n0x4003F240 READ    1852787\n0x40095E80 WRITE   1852995\n0x4003F280 READ    1853382\n0x40095EC0 WRITE   1853590\n0x4003F2C0 READ    1853977\n0x40095F00 WRITE   1854185\n0x4003F300 READ    1854572\n0x40095F40 WRITE   1854780\n0x4003F340 READ    1855167\n0x40095F80 WRITE   1855375\n0x4003F380 READ    1855762\n0x40095FC0 WRITE   1855970\n0x4003F3C0 READ    1856357\n0x40096000 WRITE   1856565\n0x4003F400 READ    1856952\n0x40096040 WRITE   1857160\n0x4003F440 READ    1857547\n0x4003F480 READ    1858153\n0x40096140 WRITE   1858360\n0x4003F4C0 READ    1858747\n0x40096180 WRITE   1858955\n0x4003F500 READ    1859342\n0x400961C0 WRITE   1859550\n0x4003F540 READ    1859937\n0x40096200 WRITE   1860145\n0x4003F580 READ    1860532\n0x40096240 WRITE   1860740\n0x4003F5C0 READ    1861127\n0x40096280 WRITE   1861335\n0x4003F600 READ    1861722\n0x400962C0 WRITE   1861930\n0x4003F640 READ    1862317\n0x40096300 WRITE   1862525\n0x4003F680 READ    1862912\n0x40096340 WRITE   1863120\n0x4003F6C0 READ    1863507\n0x4003F700 READ    1864115\n0x40096440 WRITE   1864325\n0x4003F740 READ    1864712\n0x40096480 WRITE   1864920\n0x4003F780 READ    1865307\n0x400964C0 WRITE   1865515\n0x4003F7C0 READ    1865902\n0x40096500 WRITE   1866110\n0x4003F800 READ    1866497\n0x40096540 WRITE   1866705\n0x4003F840 READ    1867092\n0x40096580 WRITE   1867300\n0x4003F880 READ    1867687\n0x400965C0 WRITE   1867895\n0x4003F8C0 READ    1868282\n0x40096600 WRITE   1868490\n0x4003F900 READ    1868877\n0x40096640 WRITE   1869085\n0x4003F940 READ    1869472\n0x4003F980 READ    1870078\n0x40096740 WRITE   1870285\n0x4003F9C0 READ    1870672\n0x40096780 WRITE   1870880\n0x4003FA00 READ    1871267\n0x400967C0 WRITE   1871475\n0x4003FA40 READ    1871862\n0x40096800 WRITE   1872070\n0x4003FA80 READ    1872457\n0x40096840 WRITE   1872665\n0x4003FAC0 READ    1873052\n0x40096880 WRITE   1873260\n0x4003FB00 READ    1873647\n0x400968C0 WRITE   1873855\n0x4003FB40 READ    1874242\n0x40096900 WRITE   1874450\n0x4003FB80 READ    1874837\n0x40096940 WRITE   1875045\n0x4003FBC0 READ    1875432\n0x4003FC00 READ    1876038\n0x40096A40 WRITE   1876245\n0x4003FC40 READ    1876632\n0x40096A80 WRITE   1876840\n0x4003FC80 READ    1877227\n0x40096AC0 WRITE   1877435\n0x4003FCC0 READ    1877822\n0x40096B00 WRITE   1878030\n0x4003FD00 READ    1878417\n0x40096B40 WRITE   1878625\n0x4003FD40 READ    1879012\n0x40096B80 WRITE   1879220\n0x4003FD80 READ    1879607\n0x40096BC0 WRITE   1879815\n0x4003FDC0 READ    1880202\n0x40096C00 WRITE   1880410\n0x4003FE00 READ    1880797\n0x40096C40 WRITE   1881005\n0x4003FE40 READ    1881392\n0x4003FE80 READ    1881998\n0x40096D40 WRITE   1882205\n0x4003FEC0 READ    1882592\n0x40096D80 WRITE   1882800\n0x4003FF00 READ    1883187\n0x40096DC0 WRITE   1883395\n0x4003FF40 READ    1883782\n0x40096E00 WRITE   1883990\n0x4003FF80 READ    1884377\n0x40096E40 WRITE   1884585\n0x4003FFC0 READ    1884972\n0x40096E80 WRITE   1885180\n0x40040000 READ    1885597\n0x40096EC0 WRITE   1885885\n0x40040040 READ    1886272\n0x40096F00 WRITE   1886480\n0x40040080 READ    1886867\n0x40096F40 WRITE   1887075\n0x400400C0 READ    1887462\n0x40040100 READ    1888070\n0x40097040 WRITE   1888280\n0x40040140 READ    1888667\n0x40097080 WRITE   1888875\n0x40040180 READ    1889262\n0x400970C0 WRITE   1889470\n0x400401C0 READ    1889857\n0x40097100 WRITE   1890065\n0x40040200 READ    1890452\n0x40097140 WRITE   1890660\n0x40040240 READ    1891047\n0x40097180 WRITE   1891255\n0x40040280 READ    1891642\n0x400971C0 WRITE   1891850\n0x400402C0 READ    1892237\n0x40097200 WRITE   1892445\n0x40040300 READ    1892832\n0x40097240 WRITE   1893040\n0x40040340 READ    1893427\n0x40040380 READ    1894033\n0x40097340 WRITE   1894240\n0x400403C0 READ    1894627\n0x40097380 WRITE   1894835\n0x40040400 READ    1895222\n0x400973C0 WRITE   1895430\n0x40040440 READ    1895817\n0x40097400 WRITE   1896025\n0x40040480 READ    1896412\n0x40097440 WRITE   1896620\n0x400404C0 READ    1897007\n0x40097480 WRITE   1897215\n0x40040500 READ    1897602\n0x400974C0 WRITE   1897810\n0x40040540 READ    1898197\n0x40097500 WRITE   1898405\n0x40040580 READ    1898792\n0x40097540 WRITE   1899000\n0x400405C0 READ    1899387\n0x40040600 READ    1899993\n0x40097640 WRITE   1900200\n0x40040640 READ    1900587\n0x40097680 WRITE   1900795\n0x40040680 READ    1901182\n0x400976C0 WRITE   1901390\n0x400406C0 READ    1901777\n0x40097700 WRITE   1901985\n0x40040700 READ    1902372\n0x40097740 WRITE   1902580\n0x40040740 READ    1902967\n0x40097780 WRITE   1903175\n0x40040780 READ    1903562\n0x400977C0 WRITE   1903770\n0x400407C0 READ    1904157\n0x40097800 WRITE   1904365\n0x40040800 READ    1904752\n0x40097840 WRITE   1904960\n0x40040840 READ    1905347\n0x40040880 READ    1905953\n0x40097940 WRITE   1906160\n0x400408C0 READ    1906547\n0x40097980 WRITE   1906755\n0x40040900 READ    1907142\n0x400979C0 WRITE   1907350\n0x40040940 READ    1907737\n0x40097A00 WRITE   1907945\n0x40040980 READ    1908332\n0x40097A40 WRITE   1908540\n0x400409C0 READ    1908927\n0x40097A80 WRITE   1909135\n0x40040A00 READ    1909522\n0x40097AC0 WRITE   1909730\n0x40040A40 READ    1910117\n0x40097B00 WRITE   1910325\n0x40040A80 READ    1910712\n0x40097B40 WRITE   1910920\n0x40040AC0 READ    1911307\n0x40040B00 READ    1911915\n0x40097C40 WRITE   1912125\n0x40040B40 READ    1912512\n0x40097C80 WRITE   1912720\n0x40040B80 READ    1913107\n0x40097CC0 WRITE   1913315\n0x40040BC0 READ    1913702\n0x40097D00 WRITE   1913910\n0x40040C00 READ    1914297\n0x40097D40 WRITE   1914505\n0x40040C40 READ    1914892\n0x40097D80 WRITE   1915100\n0x40040C80 READ    1915487\n0x40097DC0 WRITE   1915695\n0x40040CC0 READ    1916082\n0x40097E00 WRITE   1916290\n0x40040D00 READ    1916677\n0x40097E40 WRITE   1916885\n0x40040D40 READ    1917272\n0x40040D80 READ    1917878\n0x40097F40 WRITE   1918085\n0x40040DC0 READ    1918472\n0x40097F80 WRITE   1918680\n0x40040E00 READ    1919067\n0x40097FC0 WRITE   1919275\n0x40040E40 READ    1919662\n0x40098000 WRITE   1919870\n0x40040E80 READ    1920257\n0x40098040 WRITE   1920465\n0x40040EC0 READ    1920852\n0x40098080 WRITE   1921060\n0x40040F00 READ    1921447\n0x400980C0 WRITE   1921655\n0x40040F40 READ    1922042\n0x40098100 WRITE   1922250\n0x40040F80 READ    1922637\n0x40098140 WRITE   1922845\n0x40040FC0 READ    1923232\n0x40041000 READ    1923868\n0x40098240 WRITE   1924075\n0x40041040 READ    1924462\n0x40098280 WRITE   1924670\n0x40041080 READ    1925057\n0x400982C0 WRITE   1925265\n0x400410C0 READ    1925652\n0x40098300 WRITE   1925860\n0x40041100 READ    1926247\n0x40098340 WRITE   1926455\n0x40041140 READ    1926842\n0x40098380 WRITE   1927050\n0x40041180 READ    1927437\n0x400983C0 WRITE   1927645\n0x400411C0 READ    1928032\n0x40098400 WRITE   1928240\n0x40041200 READ    1928627\n0x40098440 WRITE   1928835\n0x40041240 READ    1929222\n0x40041280 READ    1929828\n0x40098540 WRITE   1930035\n0x400412C0 READ    1930422\n0x40098580 WRITE   1930630\n0x40041300 READ    1931017\n0x400985C0 WRITE   1931225\n0x40041340 READ    1931612\n0x40098600 WRITE   1931820\n0x40041380 READ    1932207\n0x40098640 WRITE   1932415\n0x400413C0 READ    1932802\n0x40098680 WRITE   1933010\n0x40041400 READ    1933397\n0x400986C0 WRITE   1933605\n0x40041440 READ    1933992\n0x40098700 WRITE   1934200\n0x40041480 READ    1934587\n0x40098740 WRITE   1934795\n0x400414C0 READ    1935182\n0x40041500 READ    1935790\n0x40098840 WRITE   1936000\n0x40041540 READ    1936387\n0x40098880 WRITE   1936595\n0x40041580 READ    1936982\n0x400988C0 WRITE   1937190\n0x400415C0 READ    1937577\n0x40098900 WRITE   1937785\n0x40041600 READ    1938172\n0x40098940 WRITE   1938380\n0x40041640 READ    1938767\n0x40098980 WRITE   1938975\n0x40041680 READ    1939362\n0x400989C0 WRITE   1939570\n0x400416C0 READ    1939957\n0x40098A00 WRITE   1940165\n0x40041700 READ    1940552\n0x40098A40 WRITE   1940760\n0x40041740 READ    1941147\n0x40041780 READ    1941753\n0x40098B40 WRITE   1941960\n0x400417C0 READ    1942347\n0x40098B80 WRITE   1942555\n0x40041800 READ    1942942\n0x40098BC0 WRITE   1943150\n0x40041840 READ    1943537\n0x40098C00 WRITE   1943745\n0x40041880 READ    1944132\n0x40098C40 WRITE   1944340\n0x400418C0 READ    1944727\n0x40098C80 WRITE   1944935\n0x40041900 READ    1945322\n0x40098CC0 WRITE   1945530\n0x40041940 READ    1945917\n0x40098D00 WRITE   1946125\n0x40041980 READ    1946512\n0x40098D40 WRITE   1946720\n0x400419C0 READ    1947107\n0x40041A00 READ    1947713\n0x40098E40 WRITE   1947920\n0x40041A40 READ    1948307\n0x40098E80 WRITE   1948515\n0x40041A80 READ    1948902\n0x40098EC0 WRITE   1949110\n0x40041AC0 READ    1949497\n0x40098F00 WRITE   1949705\n0x40041B00 READ    1950092\n0x40098F40 WRITE   1950300\n0x40041B40 READ    1950687\n0x40098F80 WRITE   1950895\n0x40041B80 READ    1951282\n0x40098FC0 WRITE   1951490\n0x40041BC0 READ    1951877\n0x40099000 WRITE   1952085\n0x40041C00 READ    1952472\n0x40099040 WRITE   1952680\n0x40041C40 READ    1953067\n0x40041C80 READ    1953673\n0x40099140 WRITE   1953880\n0x40041CC0 READ    1954267\n0x40099180 WRITE   1954475\n0x40041D00 READ    1954862\n0x400991C0 WRITE   1955070\n0x40041D40 READ    1955457\n0x40099200 WRITE   1955665\n0x40041D80 READ    1956052\n0x40099240 WRITE   1956260\n0x40041DC0 READ    1956647\n0x40099280 WRITE   1956855\n0x40041E00 READ    1957242\n0x400992C0 WRITE   1957450\n0x40041E40 READ    1957837\n0x40099300 WRITE   1958045\n0x40041E80 READ    1958432\n0x40099340 WRITE   1958640\n0x40041EC0 READ    1959027\n0x40041F00 READ    1959635\n0x40099440 WRITE   1959845\n0x40041F40 READ    1960232\n0x40099480 WRITE   1960440\n0x40041F80 READ    1960827\n0x400994C0 WRITE   1961035\n0x40041FC0 READ    1961422\n0x40099500 WRITE   1961630\n0x40042000 READ    1962047\n0x40099540 WRITE   1962255\n0x40042040 READ    1962642\n0x40099580 WRITE   1962850\n0x40042080 READ    1963237\n0x400995C0 WRITE   1963445\n0x400420C0 READ    1963832\n0x40099600 WRITE   1964040\n0x40042100 READ    1964427\n0x40099640 WRITE   1964635\n0x40042140 READ    1965022\n0x40042180 READ    1965628\n0x40099740 WRITE   1965835\n0x400421C0 READ    1966222\n0x40099780 WRITE   1966430\n0x40042200 READ    1966817\n0x400997C0 WRITE   1967025\n0x40042240 READ    1967412\n0x40099800 WRITE   1967620\n0x40042280 READ    1968007\n0x40099840 WRITE   1968215\n0x400422C0 READ    1968602\n0x40099880 WRITE   1968810\n0x40042300 READ    1969197\n0x400998C0 WRITE   1969405\n0x40042340 READ    1969792\n0x40099900 WRITE   1970000\n0x40042380 READ    1970387\n0x40099940 WRITE   1970595\n0x400423C0 READ    1970982\n0x40042400 READ    1971588\n0x40099A40 WRITE   1971795\n0x40042440 READ    1972182\n0x40099A80 WRITE   1972390\n0x40042480 READ    1972777\n0x40099AC0 WRITE   1972985\n0x400424C0 READ    1973372\n0x40099B00 WRITE   1973580\n0x40042500 READ    1973967\n0x40099B40 WRITE   1974175\n0x40042540 READ    1974562\n0x40099B80 WRITE   1974770\n0x40042580 READ    1975157\n0x40099BC0 WRITE   1975365\n0x400425C0 READ    1975752\n0x40099C00 WRITE   1975960\n0x40042600 READ    1976347\n0x40099C40 WRITE   1976555\n0x40042640 READ    1976942\n0x40042680 READ    1977548\n0x40099D40 WRITE   1977755\n0x400426C0 READ    1978142\n0x40099D80 WRITE   1978350\n0x40042700 READ    1978737\n0x40099DC0 WRITE   1978945\n0x40042740 READ    1979332\n0x40099E00 WRITE   1979540\n0x40042780 READ    1979927\n0x40099E40 WRITE   1980135\n0x400427C0 READ    1980522\n0x40099E80 WRITE   1980730\n0x40042800 READ    1981117\n0x40099EC0 WRITE   1981325\n0x40042840 READ    1981712\n0x40099F00 WRITE   1981920\n0x40042880 READ    1982307\n0x40099F40 WRITE   1982515\n0x400428C0 READ    1982902\n0x40042900 READ    1983510\n0x4009A040 WRITE   1983720\n0x40042940 READ    1984107\n0x4009A080 WRITE   1984315\n0x40042980 READ    1984702\n0x4009A0C0 WRITE   1984910\n0x400429C0 READ    1985297\n0x4009A100 WRITE   1985505\n0x40042A00 READ    1985892\n0x4009A140 WRITE   1986100\n0x40042A40 READ    1986487\n0x4009A180 WRITE   1986695\n0x40042A80 READ    1987082\n0x4009A1C0 WRITE   1987290\n0x40042AC0 READ    1987677\n0x4009A200 WRITE   1987885\n0x40042B00 READ    1988272\n0x4009A240 WRITE   1988480\n0x40042B40 READ    1988867\n0x40042B80 READ    1989473\n0x4009A340 WRITE   1989680\n0x40042BC0 READ    1990067\n0x4009A380 WRITE   1990275\n0x40042C00 READ    1990662\n0x4009A3C0 WRITE   1990870\n0x40042C40 READ    1991257\n0x4009A400 WRITE   1991465\n0x40042C80 READ    1991852\n0x4009A440 WRITE   1992060\n0x40042CC0 READ    1992447\n0x4009A480 WRITE   1992655\n0x40042D00 READ    1993042\n0x4009A4C0 WRITE   1993250\n0x40042D40 READ    1993637\n0x4009A500 WRITE   1993845\n0x40042D80 READ    1994232\n0x4009A540 WRITE   1994440\n0x40042DC0 READ    1994827\n0x40042E00 READ    1995433\n0x4009A640 WRITE   1995640\n0x40042E40 READ    1996027\n0x4009A680 WRITE   1996235\n0x40042E80 READ    1996622\n0x4009A6C0 WRITE   1996830\n0x40042EC0 READ    1997217\n0x4009A700 WRITE   1997425\n0x40042F00 READ    1997812\n0x4009A740 WRITE   1998020\n0x40042F40 READ    1998407\n0x4009A780 WRITE   1998615\n0x40042F80 READ    1999002\n0x4009A7C0 WRITE   1999210\n0x40042FC0 READ    1999597\n0x4009A800 WRITE   1999805\n0x40043000 READ    2000222\n0x4009A840 WRITE   2000430\n0x40043040 READ    2000817\n0x40043080 READ    2001423\n0x4009A940 WRITE   2001630\n0x400430C0 READ    2002017\n0x4009A980 WRITE   2002225\n0x40043100 READ    2002612\n0x4009A9C0 WRITE   2002820\n0x40043140 READ    2003207\n0x4009AA00 WRITE   2003415\n0x40043180 READ    2003802\n0x4009AA40 WRITE   2004010\n0x400431C0 READ    2004397\n0x4009AA80 WRITE   2004605\n0x40043200 READ    2004992\n0x4009AAC0 WRITE   2005200\n0x40043240 READ    2005587\n0x4009AB00 WRITE   2005795\n0x40043280 READ    2006182\n0x4009AB40 WRITE   2006390\n0x400432C0 READ    2006777\n0x40043300 READ    2007385\n0x4009AC40 WRITE   2007595\n0x40043340 READ    2007982\n0x4009AC80 WRITE   2008190\n0x40043380 READ    2008577\n0x4009ACC0 WRITE   2008785\n0x400433C0 READ    2009172\n0x4009AD00 WRITE   2009380\n0x40043400 READ    2009767\n0x4009AD40 WRITE   2009975\n0x40043440 READ    2010362\n0x4009AD80 WRITE   2010570\n0x40043480 READ    2010957\n0x4009ADC0 WRITE   2011165\n0x400434C0 READ    2011552\n0x4009AE00 WRITE   2011760\n0x40043500 READ    2012147\n0x4009AE40 WRITE   2012355\n0x40043540 READ    2012742\n0x40043580 READ    2013348\n0x4009AF40 WRITE   2013555\n0x400435C0 READ    2013942\n0x4009AF80 WRITE   2014150\n0x40043600 READ    2014537\n0x4009AFC0 WRITE   2014745\n0x40043640 READ    2015132\n0x4009B000 WRITE   2015340\n0x40043680 READ    2015727\n0x4009B040 WRITE   2015935\n0x400436C0 READ    2016322\n0x4009B080 WRITE   2016530\n0x40043700 READ    2016917\n0x4009B0C0 WRITE   2017125\n0x40043740 READ    2017512\n0x4009B100 WRITE   2017720\n0x40043780 READ    2018107\n0x4009B140 WRITE   2018315\n0x400437C0 READ    2018702\n0x40043800 READ    2019308\n0x4009B240 WRITE   2019515\n0x40043840 READ    2019902\n0x4009B280 WRITE   2020110\n0x40043880 READ    2020497\n0x4009B2C0 WRITE   2020705\n0x400438C0 READ    2021092\n0x4009B300 WRITE   2021300\n0x40043900 READ    2021687\n0x4009B340 WRITE   2021895\n0x40043940 READ    2022282\n0x4009B380 WRITE   2022490\n0x40043980 READ    2022877\n0x4009B3C0 WRITE   2023085\n0x400439C0 READ    2023472\n0x4009B400 WRITE   2023680\n0x40043A00 READ    2024067\n0x4009B440 WRITE   2024275\n0x40043A40 READ    2024662\n0x40043A80 READ    2025268\n0x4009B540 WRITE   2025475\n0x40043AC0 READ    2025862\n0x4009B580 WRITE   2026070\n0x40043B00 READ    2026457\n0x4009B5C0 WRITE   2026665\n0x40043B40 READ    2027052\n0x4009B600 WRITE   2027260\n0x40043B80 READ    2027647\n0x4009B640 WRITE   2027855\n0x40043BC0 READ    2028242\n0x4009B680 WRITE   2028450\n0x40043C00 READ    2028837\n0x4009B6C0 WRITE   2029045\n0x40043C40 READ    2029432\n0x4009B700 WRITE   2029640\n0x40043C80 READ    2030027\n0x4009B740 WRITE   2030235\n0x40043CC0 READ    2030622\n0x40043D00 READ    2031230\n0x4009B840 WRITE   2031440\n0x40043D40 READ    2031827\n0x4009B880 WRITE   2032035\n0x40043D80 READ    2032422\n0x4009B8C0 WRITE   2032630\n0x40043DC0 READ    2033017\n0x4009B900 WRITE   2033225\n0x40043E00 READ    2033612\n0x4009B940 WRITE   2033820\n0x40043E40 READ    2034207\n0x4009B980 WRITE   2034415\n0x40043E80 READ    2034802\n0x4009B9C0 WRITE   2035010\n0x40043EC0 READ    2035397\n0x4009BA00 WRITE   2035605\n0x40043F00 READ    2035992\n0x4009BA40 WRITE   2036200\n0x40043F40 READ    2036587\n0x40043F80 READ    2037193\n0x4009BB40 WRITE   2037400\n0x40043FC0 READ    2037787\n0x4009BB80 WRITE   2037995\n0x40044000 READ    2038412\n0x4009BBC0 WRITE   2038700\n0x40044040 READ    2039087\n0x4009BC00 WRITE   2039295\n0x40044080 READ    2039682\n0x4009BC40 WRITE   2039890\n0x400440C0 READ    2040277\n0x4009BC80 WRITE   2040485\n0x40044100 READ    2040872\n0x4009BCC0 WRITE   2041080\n0x40044140 READ    2041467\n0x4009BD00 WRITE   2041675\n0x40044180 READ    2042062\n0x4009BD40 WRITE   2042270\n0x400441C0 READ    2042657\n0x40044200 READ    2043263\n0x4009BE40 WRITE   2043470\n0x40044240 READ    2043857\n0x4009BE80 WRITE   2044065\n0x40044280 READ    2044452\n0x4009BEC0 WRITE   2044660\n0x400442C0 READ    2045047\n0x4009BF00 WRITE   2045255\n0x40044300 READ    2045642\n0x4009BF40 WRITE   2045850\n0x40044340 READ    2046237\n0x4009BF80 WRITE   2046445\n0x40044380 READ    2046832\n0x4009BFC0 WRITE   2047040\n0x400443C0 READ    2047427\n0x4009C000 WRITE   2047635\n0x40044400 READ    2048022\n0x4009C040 WRITE   2048230\n0x40044440 READ    2048617\n0x40044480 READ    2049223\n0x4009C140 WRITE   2049430\n0x400444C0 READ    2049817\n0x4009C180 WRITE   2050025\n0x40044500 READ    2050412\n0x4009C1C0 WRITE   2050620\n0x40044540 READ    2051007\n0x4009C200 WRITE   2051215\n0x40044580 READ    2051602\n0x4009C240 WRITE   2051810\n0x400445C0 READ    2052197\n0x4009C280 WRITE   2052405\n0x40044600 READ    2052792\n0x4009C2C0 WRITE   2053000\n0x40044640 READ    2053387\n0x4009C300 WRITE   2053595\n0x40044680 READ    2053982\n0x4009C340 WRITE   2054190\n0x400446C0 READ    2054577\n0x40044700 READ    2055185\n0x4009C440 WRITE   2055395\n0x40044740 READ    2055782\n0x4009C480 WRITE   2055990\n0x40044780 READ    2056377\n0x4009C4C0 WRITE   2056585\n0x400447C0 READ    2056972\n0x4009C500 WRITE   2057180\n0x40044800 READ    2057567\n0x4009C540 WRITE   2057775\n0x40044840 READ    2058162\n0x4009C580 WRITE   2058370\n0x40044880 READ    2058757\n0x4009C5C0 WRITE   2058965\n0x400448C0 READ    2059352\n0x4009C600 WRITE   2059560\n0x40044900 READ    2059947\n0x4009C640 WRITE   2060155\n0x40044940 READ    2060542\n0x40044980 READ    2061148\n0x4009C740 WRITE   2061355\n0x400449C0 READ    2061742\n0x4009C780 WRITE   2061950\n0x40044A00 READ    2062337\n0x4009C7C0 WRITE   2062545\n0x40044A40 READ    2062932\n0x4009C800 WRITE   2063140\n0x40044A80 READ    2063527\n0x4009C840 WRITE   2063735\n0x40044AC0 READ    2064122\n0x4009C880 WRITE   2064330\n0x40044B00 READ    2064717\n0x4009C8C0 WRITE   2064925\n0x40044B40 READ    2065312\n0x4009C900 WRITE   2065520\n0x40044B80 READ    2065907\n0x4009C940 WRITE   2066115\n0x40044BC0 READ    2066502\n0x40044C00 READ    2067108\n0x4009CA40 WRITE   2067315\n0x40044C40 READ    2067702\n0x4009CA80 WRITE   2067910\n0x40044C80 READ    2068297\n0x4009CAC0 WRITE   2068505\n0x40044CC0 READ    2068892\n0x4009CB00 WRITE   2069100\n0x40044D00 READ    2069487\n0x4009CB40 WRITE   2069695\n0x40044D40 READ    2070082\n0x4009CB80 WRITE   2070290\n0x40044D80 READ    2070677\n0x4009CBC0 WRITE   2070885\n0x40044DC0 READ    2071272\n0x4009CC00 WRITE   2071480\n0x40044E00 READ    2071867\n0x4009CC40 WRITE   2072075\n0x40044E40 READ    2072462\n0x40044E80 READ    2073068\n0x4009CD40 WRITE   2073275\n0x40044EC0 READ    2073662\n0x4009CD80 WRITE   2073870\n0x40044F00 READ    2074257\n0x4009CDC0 WRITE   2074465\n0x40044F40 READ    2074852\n0x4009CE00 WRITE   2075060\n0x40044F80 READ    2075447\n0x4009CE40 WRITE   2075655\n0x40044FC0 READ    2076042\n0x4009CE80 WRITE   2076250\n0x40045000 READ    2076667\n0x4009CEC0 WRITE   2076875\n0x40045040 READ    2077262\n0x4009CF00 WRITE   2077470\n0x40045080 READ    2077857\n0x4009CF40 WRITE   2078065\n0x400450C0 READ    2078452\n0x40045100 READ    2079060\n0x4009D040 WRITE   2079270\n0x40045140 READ    2079657\n0x4009D080 WRITE   2079865\n0x40045180 READ    2080252\n0x4009D0C0 WRITE   2080460\n0x400451C0 READ    2080847\n0x4009D100 WRITE   2081055\n0x40045200 READ    2081442\n0x4009D140 WRITE   2081650\n0x40045240 READ    2082037\n0x4009D180 WRITE   2082245\n0x40045280 READ    2082632\n0x4009D1C0 WRITE   2082840\n0x400452C0 READ    2083227\n0x4009D200 WRITE   2083435\n0x40045300 READ    2083822\n0x4009D240 WRITE   2084030\n0x40045340 READ    2084417\n0x40045380 READ    2085023\n0x4009D340 WRITE   2085230\n0x400453C0 READ    2085617\n0x4009D380 WRITE   2085825\n0x40045400 READ    2086212\n0x4009D3C0 WRITE   2086420\n0x40045440 READ    2086807\n0x4009D400 WRITE   2087015\n0x40045480 READ    2087402\n0x4009D440 WRITE   2087610\n0x400454C0 READ    2087997\n0x4009D480 WRITE   2088205\n0x40045500 READ    2088592\n0x4009D4C0 WRITE   2088800\n0x40045540 READ    2089187\n0x4009D500 WRITE   2089395\n0x40045580 READ    2089782\n0x4009D540 WRITE   2089990\n0x400455C0 READ    2090377\n0x40045600 READ    2090983\n0x4009D640 WRITE   2091190\n0x40045640 READ    2091577\n0x4009D680 WRITE   2091785\n0x40045680 READ    2092172\n0x4009D6C0 WRITE   2092380\n0x400456C0 READ    2092767\n0x4009D700 WRITE   2092975\n0x40045700 READ    2093362\n0x4009D740 WRITE   2093570\n0x40045740 READ    2093957\n0x4009D780 WRITE   2094165\n0x40045780 READ    2094552\n0x4009D7C0 WRITE   2094760\n0x400457C0 READ    2095147\n0x4009D800 WRITE   2095355\n0x40045800 READ    2095742\n0x4009D840 WRITE   2095950\n0x40045840 READ    2096337\n0x40045880 READ    2096943\n0x4009D940 WRITE   2097150\n0x400458C0 READ    2097537\n0x4009D980 WRITE   2097745\n0x40045900 READ    2098132\n0x4009D9C0 WRITE   2098340\n0x40045940 READ    2098727\n0x4009DA00 WRITE   2098935\n0x40045980 READ    2099322\n0x4009DA40 WRITE   2099530\n0x400459C0 READ    2099917\n0x4009DA80 WRITE   2100125\n0x40045A00 READ    2100512\n0x4009DAC0 WRITE   2100720\n0x40045A40 READ    2101107\n0x4009DB00 WRITE   2101315\n0x40045A80 READ    2101702\n0x4009DB40 WRITE   2101910\n0x40045AC0 READ    2102297\n0x40045B00 READ    2102905\n0x4009DC40 WRITE   2103115\n0x40045B40 READ    2103502\n0x4009DC80 WRITE   2103710\n0x40045B80 READ    2104097\n0x4009DCC0 WRITE   2104305\n0x40045BC0 READ    2104692\n0x4009DD00 WRITE   2104900\n0x40045C00 READ    2105287\n0x4009DD40 WRITE   2105495\n0x40045C40 READ    2105882\n0x4009DD80 WRITE   2106090\n0x40045C80 READ    2106477\n0x4009DDC0 WRITE   2106685\n0x40045CC0 READ    2107072\n0x4009DE00 WRITE   2107280\n0x40045D00 READ    2107667\n0x4009DE40 WRITE   2107875\n0x40045D40 READ    2108262\n0x40045D80 READ    2108868\n0x4009DF40 WRITE   2109075\n0x40045DC0 READ    2109462\n0x4009DF80 WRITE   2109670\n0x40045E00 READ    2110057\n0x4009DFC0 WRITE   2110265\n0x40045E40 READ    2110652\n0x4009E000 WRITE   2110860\n0x40045E80 READ    2111247\n0x4009E040 WRITE   2111455\n0x40045EC0 READ    2111842\n0x4009E080 WRITE   2112050\n0x40045F00 READ    2112437\n0x4009E0C0 WRITE   2112645\n0x40045F40 READ    2113032\n0x4009E100 WRITE   2113240\n0x40045F80 READ    2113627\n0x4009E140 WRITE   2113835\n0x40045FC0 READ    2114222\n0x40046000 READ    2114858\n0x4009E240 WRITE   2115065\n0x40046040 READ    2115452\n0x4009E280 WRITE   2115660\n0x40046080 READ    2116047\n0x4009E2C0 WRITE   2116255\n0x400460C0 READ    2116642\n0x4009E300 WRITE   2116850\n0x40046100 READ    2117237\n0x4009E340 WRITE   2117445\n0x40046140 READ    2117832\n0x4009E380 WRITE   2118040\n0x40046180 READ    2118427\n0x4009E3C0 WRITE   2118635\n0x400461C0 READ    2119022\n0x4009E400 WRITE   2119230\n0x40046200 READ    2119617\n0x4009E440 WRITE   2119825\n0x40046240 READ    2120212\n0x40046280 READ    2120818\n0x4009E540 WRITE   2121025\n0x400462C0 READ    2121412\n0x4009E580 WRITE   2121620\n0x40046300 READ    2122007\n0x4009E5C0 WRITE   2122215\n0x40046340 READ    2122602\n0x4009E600 WRITE   2122810\n0x40046380 READ    2123197\n0x4009E640 WRITE   2123405\n0x400463C0 READ    2123792\n0x4009E680 WRITE   2124000\n0x40046400 READ    2124387\n0x4009E6C0 WRITE   2124595\n0x40046440 READ    2124982\n0x4009E700 WRITE   2125190\n0x40046480 READ    2125577\n0x4009E740 WRITE   2125785\n0x400464C0 READ    2126172\n0x40046500 READ    2126780\n0x4009E840 WRITE   2126990\n0x40046540 READ    2127377\n0x4009E880 WRITE   2127585\n0x40046580 READ    2127972\n0x4009E8C0 WRITE   2128180\n0x400465C0 READ    2128567\n0x4009E900 WRITE   2128775\n0x40046600 READ    2129162\n0x4009E940 WRITE   2129370\n0x40046640 READ    2129757\n0x4009E980 WRITE   2129965\n0x40046680 READ    2130352\n0x4009E9C0 WRITE   2130560\n0x400466C0 READ    2130947\n0x4009EA00 WRITE   2131155\n0x40046700 READ    2131542\n0x4009EA40 WRITE   2131750\n0x40046740 READ    2132137\n0x40046780 READ    2132743\n0x4009EB40 WRITE   2132950\n0x400467C0 READ    2133337\n0x4009EB80 WRITE   2133545\n0x40046800 READ    2133932\n0x4009EBC0 WRITE   2134140\n0x40046840 READ    2134527\n0x4009EC00 WRITE   2134735\n0x40046880 READ    2135122\n0x4009EC40 WRITE   2135330\n0x400468C0 READ    2135717\n0x4009EC80 WRITE   2135925\n0x40046900 READ    2136312\n0x4009ECC0 WRITE   2136520\n0x40046940 READ    2136907\n0x4009ED00 WRITE   2137115\n0x40046980 READ    2137502\n0x4009ED40 WRITE   2137710\n0x400469C0 READ    2138097\n0x40046A00 READ    2138703\n0x4009EE40 WRITE   2138910\n0x40046A40 READ    2139297\n0x4009EE80 WRITE   2139505\n0x40046A80 READ    2139892\n0x4009EEC0 WRITE   2140100\n0x40046AC0 READ    2140487\n0x4009EF00 WRITE   2140695\n0x40046B00 READ    2141082\n0x4009EF40 WRITE   2141290\n0x40046B40 READ    2141677\n0x4009EF80 WRITE   2141885\n0x40046B80 READ    2142272\n0x4009EFC0 WRITE   2142480\n0x40046BC0 READ    2142867\n0x4009F000 WRITE   2143075\n0x40046C00 READ    2143462\n0x4009F040 WRITE   2143670\n0x40046C40 READ    2144057\n0x40046C80 READ    2144663\n0x4009F140 WRITE   2144870\n0x40046CC0 READ    2145257\n0x4009F180 WRITE   2145465\n0x40046D00 READ    2145852\n0x4009F1C0 WRITE   2146060\n0x40046D40 READ    2146447\n0x4009F200 WRITE   2146655\n0x40046D80 READ    2147042\n0x4009F240 WRITE   2147250\n0x40046DC0 READ    2147637\n0x4009F280 WRITE   2147845\n0x40046E00 READ    2148232\n0x4009F2C0 WRITE   2148440\n0x40046E40 READ    2148827\n0x4009F300 WRITE   2149035\n0x40046E80 READ    2149422\n0x4009F340 WRITE   2149630\n0x40046EC0 READ    2150017\n0x40046F00 READ    2150625\n0x4009F440 WRITE   2150835\n0x40046F40 READ    2151222\n0x4009F480 WRITE   2151430\n0x40046F80 READ    2151817\n0x4009F4C0 WRITE   2152025\n0x40046FC0 READ    2152412\n0x4009F500 WRITE   2152620\n0x40047000 READ    2153037\n0x4009F540 WRITE   2153245\n0x40047040 READ    2153632\n0x4009F580 WRITE   2153840\n0x40047080 READ    2154227\n0x4009F5C0 WRITE   2154435\n0x400470C0 READ    2154822\n0x4009F600 WRITE   2155030\n0x40047100 READ    2155417\n0x4009F640 WRITE   2155625\n0x40047140 READ    2156012\n0x40047180 READ    2156618\n0x4009F740 WRITE   2156825\n0x400471C0 READ    2157212\n0x4009F780 WRITE   2157420\n0x40047200 READ    2157807\n0x4009F7C0 WRITE   2158015\n0x40047240 READ    2158402\n0x4009F800 WRITE   2158610\n0x40047280 READ    2158997\n0x4009F840 WRITE   2159205\n0x400472C0 READ    2159592\n0x4009F880 WRITE   2159800\n0x40047300 READ    2160187\n0x4009F8C0 WRITE   2160395\n0x40047340 READ    2160782\n0x4009F900 WRITE   2160990\n0x40047380 READ    2161377\n0x4009F940 WRITE   2161585\n0x400473C0 READ    2161972\n0x40047400 READ    2162578\n0x4009FA40 WRITE   2162785\n0x40047440 READ    2163172\n0x4009FA80 WRITE   2163380\n0x40047480 READ    2163767\n0x4009FAC0 WRITE   2163975\n0x400474C0 READ    2164362\n0x4009FB00 WRITE   2164570\n0x40047500 READ    2164957\n0x4009FB40 WRITE   2165165\n0x40047540 READ    2165552\n0x4009FB80 WRITE   2165760\n0x40047580 READ    2166147\n0x4009FBC0 WRITE   2166355\n0x400475C0 READ    2166742\n0x4009FC00 WRITE   2166950\n0x40047600 READ    2167337\n0x4009FC40 WRITE   2167545\n0x40047640 READ    2167932\n0x40047680 READ    2168538\n0x4009FD40 WRITE   2168745\n0x400476C0 READ    2169132\n0x4009FD80 WRITE   2169340\n0x40047700 READ    2169727\n0x4009FDC0 WRITE   2169935\n0x40047740 READ    2170322\n0x4009FE00 WRITE   2170530\n0x40047780 READ    2170917\n0x4009FE40 WRITE   2171125\n0x400477C0 READ    2171512\n0x4009FE80 WRITE   2171720\n0x40047800 READ    2172107\n0x4009FEC0 WRITE   2172315\n0x40047840 READ    2172702\n0x4009FF00 WRITE   2172910\n0x40047880 READ    2173297\n0x4009FF40 WRITE   2173505\n0x400478C0 READ    2173892\n0x40047900 READ    2174500\n0x400A0040 WRITE   2174710\n0x40047940 READ    2175097\n0x400A0080 WRITE   2175305\n0x40047980 READ    2175692\n0x400A00C0 WRITE   2175900\n0x400479C0 READ    2176287\n0x400A0100 WRITE   2176495\n0x40047A00 READ    2176882\n0x400A0140 WRITE   2177090\n0x40047A40 READ    2177477\n0x400A0180 WRITE   2177685\n0x40047A80 READ    2178072\n0x400A01C0 WRITE   2178280\n0x40047AC0 READ    2178667\n0x400A0200 WRITE   2178875\n0x40047B00 READ    2179262\n0x400A0240 WRITE   2179470\n0x40047B40 READ    2179857\n0x40047B80 READ    2180463\n0x400A0340 WRITE   2180670\n0x40047BC0 READ    2181057\n0x400A0380 WRITE   2181265\n0x40047C00 READ    2181652\n0x400A03C0 WRITE   2181860\n0x40047C40 READ    2182247\n0x400A0400 WRITE   2182455\n0x40047C80 READ    2182842\n0x400A0440 WRITE   2183050\n0x40047CC0 READ    2183437\n0x400A0480 WRITE   2183645\n0x40047D00 READ    2184032\n0x400A04C0 WRITE   2184240\n0x40047D40 READ    2184627\n0x400A0500 WRITE   2184835\n0x40047D80 READ    2185222\n0x400A0540 WRITE   2185430\n0x40047DC0 READ    2185817\n0x40047E00 READ    2186423\n0x400A0640 WRITE   2186630\n0x40047E40 READ    2187017\n0x400A0680 WRITE   2187225\n0x40047E80 READ    2187612\n0x400A06C0 WRITE   2187820\n0x40047EC0 READ    2188207\n0x400A0700 WRITE   2188415\n0x40047F00 READ    2188802\n0x400A0740 WRITE   2189010\n0x40047F40 READ    2189397\n0x400A0780 WRITE   2189605\n0x40047F80 READ    2189992\n0x400A07C0 WRITE   2190200\n0x40047FC0 READ    2190587\n0x400A0800 WRITE   2190795\n0x40048000 READ    2191212\n0x400A0840 WRITE   2191500\n0x40048040 READ    2191887\n0x40048080 READ    2192493\n0x400A0940 WRITE   2192700\n0x400480C0 READ    2193087\n0x400A0980 WRITE   2193295\n0x40048100 READ    2193682\n0x400A09C0 WRITE   2193890\n0x40048140 READ    2194277\n0x400A0A00 WRITE   2194485\n0x40048180 READ    2194872\n0x400A0A40 WRITE   2195080\n0x400481C0 READ    2195467\n0x400A0A80 WRITE   2195675\n0x40048200 READ    2196062\n0x400A0AC0 WRITE   2196270\n0x40048240 READ    2196657\n0x400A0B00 WRITE   2196865\n0x40048280 READ    2197252\n0x400A0B40 WRITE   2197460\n0x400482C0 READ    2197847\n0x40048300 READ    2198455\n0x400A0C40 WRITE   2198665\n0x40048340 READ    2199052\n0x400A0C80 WRITE   2199260\n0x40048380 READ    2199647\n0x400A0CC0 WRITE   2199855\n0x400483C0 READ    2200242\n0x400A0D00 WRITE   2200450\n0x40048400 READ    2200837\n0x400A0D40 WRITE   2201045\n0x40048440 READ    2201432\n0x400A0D80 WRITE   2201640\n0x40048480 READ    2202027\n0x400A0DC0 WRITE   2202235\n0x400484C0 READ    2202622\n0x400A0E00 WRITE   2202830\n0x40048500 READ    2203217\n0x400A0E40 WRITE   2203425\n0x40048540 READ    2203812\n0x40048580 READ    2204418\n0x400A0F40 WRITE   2204625\n0x400485C0 READ    2205012\n0x400A0F80 WRITE   2205220\n0x40048600 READ    2205607\n0x400A0FC0 WRITE   2205815\n0x40048640 READ    2206202\n0x400A1000 WRITE   2206410\n0x40048680 READ    2206797\n0x400A1040 WRITE   2207005\n0x400486C0 READ    2207392\n0x400A1080 WRITE   2207600\n0x40048700 READ    2207987\n0x400A10C0 WRITE   2208195\n0x40048740 READ    2208582\n0x400A1100 WRITE   2208790\n0x40048780 READ    2209177\n0x400A1140 WRITE   2209385\n0x400487C0 READ    2209772\n0x40048800 READ    2210378\n0x400A1240 WRITE   2210585\n0x40048840 READ    2210972\n0x400A1280 WRITE   2211180\n0x40048880 READ    2211567\n0x400A12C0 WRITE   2211775\n0x400488C0 READ    2212162\n0x400A1300 WRITE   2212370\n0x40048900 READ    2212757\n0x400A1340 WRITE   2212965\n0x40048940 READ    2213352\n0x400A1380 WRITE   2213560\n0x40048980 READ    2213947\n0x400A13C0 WRITE   2214155\n0x400489C0 READ    2214542\n0x400A1400 WRITE   2214750\n0x40048A00 READ    2215137\n0x400A1440 WRITE   2215345\n0x40048A40 READ    2215732\n0x40048A80 READ    2216338\n0x400A1540 WRITE   2216545\n0x40048AC0 READ    2216932\n0x400A1580 WRITE   2217140\n0x40048B00 READ    2217527\n0x400A15C0 WRITE   2217735\n0x40048B40 READ    2218122\n0x400A1600 WRITE   2218330\n0x40048B80 READ    2218717\n0x400A1640 WRITE   2218925\n0x40048BC0 READ    2219312\n0x400A1680 WRITE   2219520\n0x40048C00 READ    2219907\n0x400A16C0 WRITE   2220115\n0x40048C40 READ    2220502\n0x400A1700 WRITE   2220710\n0x40048C80 READ    2221097\n0x400A1740 WRITE   2221305\n0x40048CC0 READ    2221692\n0x40048D00 READ    2222300\n0x400A1840 WRITE   2222510\n0x40048D40 READ    2222897\n0x400A1880 WRITE   2223105\n0x40048D80 READ    2223492\n0x400A18C0 WRITE   2223700\n0x40048DC0 READ    2224087\n0x400A1900 WRITE   2224295\n0x40048E00 READ    2224682\n0x400A1940 WRITE   2224890\n0x40048E40 READ    2225277\n0x400A1980 WRITE   2225485\n0x40048E80 READ    2225872\n0x400A19C0 WRITE   2226080\n0x40048EC0 READ    2226467\n0x400A1A00 WRITE   2226675\n0x40048F00 READ    2227062\n0x400A1A40 WRITE   2227270\n0x40048F40 READ    2227657\n0x40048F80 READ    2228263\n0x400A1B40 WRITE   2228470\n0x40048FC0 READ    2228857\n0x400A1B80 WRITE   2229065\n0x40049000 READ    2229482\n0x400A1BC0 WRITE   2229690\n0x40049040 READ    2230077\n0x400A1C00 WRITE   2230285\n0x40049080 READ    2230672\n0x400A1C40 WRITE   2230880\n0x400490C0 READ    2231267\n0x400A1C80 WRITE   2231475\n0x40049100 READ    2231862\n0x400A1CC0 WRITE   2232070\n0x40049140 READ    2232457\n0x400A1D00 WRITE   2232665\n0x40049180 READ    2233052\n0x400A1D40 WRITE   2233260\n0x400491C0 READ    2233647\n0x40049200 READ    2234253\n0x400A1E40 WRITE   2234460\n0x40049240 READ    2234847\n0x400A1E80 WRITE   2235055\n0x40049280 READ    2235442\n0x400A1EC0 WRITE   2235650\n0x400492C0 READ    2236037\n0x400A1F00 WRITE   2236245\n0x40049300 READ    2236632\n0x400A1F40 WRITE   2236840\n0x40049340 READ    2237227\n0x400A1F80 WRITE   2237435\n0x40049380 READ    2237822\n0x400A1FC0 WRITE   2238030\n0x400493C0 READ    2238417\n0x400A2000 WRITE   2238625\n0x40049400 READ    2239012\n0x400A2040 WRITE   2239220\n0x40049440 READ    2239607\n0x40049480 READ    2240213\n0x400A2140 WRITE   2240420\n0x400494C0 READ    2240807\n0x400A2180 WRITE   2241015\n0x40049500 READ    2241402\n0x400A21C0 WRITE   2241610\n0x40049540 READ    2241997\n0x400A2200 WRITE   2242205\n0x40049580 READ    2242592\n0x400A2240 WRITE   2242800\n0x400495C0 READ    2243187\n0x400A2280 WRITE   2243395\n0x40049600 READ    2243782\n0x400A22C0 WRITE   2243990\n0x40049640 READ    2244377\n0x400A2300 WRITE   2244585\n0x40049680 READ    2244972\n0x400A2340 WRITE   2245180\n0x400496C0 READ    2245567\n0x40049700 READ    2246175\n0x400A2440 WRITE   2246385\n0x40049740 READ    2246772\n0x400A2480 WRITE   2246980\n0x40049780 READ    2247367\n0x400A24C0 WRITE   2247575\n0x400497C0 READ    2247962\n0x400A2500 WRITE   2248170\n0x40049800 READ    2248557\n0x400A2540 WRITE   2248765\n0x40049840 READ    2249152\n0x400A2580 WRITE   2249360\n0x40049880 READ    2249747\n0x400A25C0 WRITE   2249955\n0x400498C0 READ    2250342\n0x400A2600 WRITE   2250550\n0x40049900 READ    2250937\n0x400A2640 WRITE   2251145\n0x40049940 READ    2251532\n0x40049980 READ    2252138\n0x400A2740 WRITE   2252345\n0x400499C0 READ    2252732\n0x400A2780 WRITE   2252940\n0x40049A00 READ    2253327\n0x400A27C0 WRITE   2253535\n0x40049A40 READ    2253922\n0x400A2800 WRITE   2254130\n0x40049A80 READ    2254517\n0x400A2840 WRITE   2254725\n0x40049AC0 READ    2255112\n0x40049B00 READ    2255707\n0x400A28C0 WRITE   2255915\n0x40049B40 READ    2256302\n0x400A2900 WRITE   2256510\n0x40049B80 READ    2256897\n0x400A2940 WRITE   2257105\n0x40049BC0 READ    2257492\n0x40049C00 READ    2258098\n0x400A2A40 WRITE   2258305\n0x40049C40 READ    2258692\n0x400A2A80 WRITE   2258900\n0x40049C80 READ    2259287\n0x400A2AC0 WRITE   2259495\n0x40049CC0 READ    2259882\n0x400A2B00 WRITE   2260090\n0x40049D00 READ    2260477\n0x400A2B40 WRITE   2260685\n0x40049D40 READ    2261072\n0x400A2B80 WRITE   2261280\n0x40049D80 READ    2261667\n0x400A2BC0 WRITE   2261875\n0x40049DC0 READ    2262262\n0x400A2C00 WRITE   2262470\n0x40049E00 READ    2262857\n0x400A2C40 WRITE   2263065\n0x40049E40 READ    2263452\n0x40049E80 READ    2264058\n0x400A2D40 WRITE   2264265\n0x40049EC0 READ    2264652\n0x400A2D80 WRITE   2264860\n0x40049F00 READ    2265247\n0x400A2DC0 WRITE   2265455\n0x40049F40 READ    2265842\n0x400A2E00 WRITE   2266050\n0x40049F80 READ    2266437\n0x400A2E40 WRITE   2266645\n0x40049FC0 READ    2267032\n0x400A2E80 WRITE   2267240\n0x4004A000 READ    2267657\n0x400A2EC0 WRITE   2267865\n0x4004A040 READ    2268252\n0x400A2F00 WRITE   2268460\n0x4004A080 READ    2268847\n0x400A2F40 WRITE   2269055\n0x4004A0C0 READ    2269442\n0x4004A100 READ    2270050\n0x400A3040 WRITE   2270260\n0x4004A140 READ    2270647\n0x400A3080 WRITE   2270855\n0x4004A180 READ    2271242\n0x400A30C0 WRITE   2271450\n0x4004A1C0 READ    2271837\n0x400A3100 WRITE   2272045\n0x4004A200 READ    2272432\n0x400A3140 WRITE   2272640\n0x4004A240 READ    2273027\n0x400A3180 WRITE   2273235\n0x4004A280 READ    2273622\n0x400A31C0 WRITE   2273830\n0x4004A2C0 READ    2274217\n0x400A3200 WRITE   2274425\n0x4004A300 READ    2274812\n0x400A3240 WRITE   2275020\n0x4004A340 READ    2275407\n0x4004A380 READ    2276013\n0x400A3340 WRITE   2276220\n0x4004A3C0 READ    2276607\n0x400A3380 WRITE   2276815\n0x4004A400 READ    2277202\n0x400A33C0 WRITE   2277410\n0x4004A440 READ    2277797\n0x400A3400 WRITE   2278005\n0x4004A480 READ    2278392\n0x400A3440 WRITE   2278600\n0x4004A4C0 READ    2278987\n0x400A3480 WRITE   2279195\n0x4004A500 READ    2279582\n0x400A34C0 WRITE   2279790\n0x4004A540 READ    2280177\n0x400A3500 WRITE   2280385\n0x4004A580 READ    2280772\n0x400A3540 WRITE   2280980\n0x4004A5C0 READ    2281367\n0x4004A600 READ    2281973\n0x400A3640 WRITE   2282180\n0x4004A640 READ    2282567\n0x400A3680 WRITE   2282775\n0x4004A680 READ    2283162\n0x400A36C0 WRITE   2283370\n0x4004A6C0 READ    2283757\n0x400A3700 WRITE   2283965\n0x4004A700 READ    2284352\n0x400A3740 WRITE   2284560\n0x4004A740 READ    2284947\n0x400A3780 WRITE   2285155\n0x4004A780 READ    2285542\n0x400A37C0 WRITE   2285750\n0x4004A7C0 READ    2286137\n0x400A3800 WRITE   2286345\n0x4004A800 READ    2286732\n0x400A3840 WRITE   2286940\n0x4004A840 READ    2287327\n0x4004A880 READ    2287933\n0x400A3940 WRITE   2288140\n0x4004A8C0 READ    2288527\n0x400A3980 WRITE   2288735\n0x4004A900 READ    2289122\n0x400A39C0 WRITE   2289330\n0x4004A940 READ    2289717\n0x400A3A00 WRITE   2289925\n0x4004A980 READ    2290312\n0x400A3A40 WRITE   2290520\n0x4004A9C0 READ    2290907\n0x400A3A80 WRITE   2291115\n0x4004AA00 READ    2291502\n0x400A3AC0 WRITE   2291710\n0x4004AA40 READ    2292097\n0x400A3B00 WRITE   2292305\n0x4004AA80 READ    2292692\n0x400A3B40 WRITE   2292900\n0x4004AAC0 READ    2293287\n0x4004AB00 READ    2293895\n0x400A3C40 WRITE   2294105\n0x4004AB40 READ    2294492\n0x400A3C80 WRITE   2294700\n0x4004AB80 READ    2295087\n0x400A3CC0 WRITE   2295295\n0x4004ABC0 READ    2295682\n0x400A3D00 WRITE   2295890\n0x4004AC00 READ    2296277\n0x400A3D40 WRITE   2296485\n0x4004AC40 READ    2296872\n0x400A3D80 WRITE   2297080\n0x4004AC80 READ    2297467\n0x400A3DC0 WRITE   2297675\n0x4004ACC0 READ    2298062\n0x400A3E00 WRITE   2298270\n0x4004AD00 READ    2298657\n0x400A3E40 WRITE   2298865\n0x4004AD40 READ    2299252\n0x4004AD80 READ    2299858\n0x400A3F40 WRITE   2300065\n0x4004ADC0 READ    2300452\n0x400A3F80 WRITE   2300660\n0x4004AE00 READ    2301047\n0x400A3FC0 WRITE   2301255\n0x4004AE40 READ    2301642\n0x400A4000 WRITE   2301850\n0x4004AE80 READ    2302237\n0x400A4040 WRITE   2302445\n0x4004AEC0 READ    2302832\n0x400A4080 WRITE   2303040\n0x4004AF00 READ    2303427\n0x400A40C0 WRITE   2303635\n0x4004AF40 READ    2304022\n0x400A4100 WRITE   2304230\n0x4004AF80 READ    2304617\n0x400A4140 WRITE   2304825\n0x4004AFC0 READ    2305212\n0x4004B000 READ    2305848\n0x400A4240 WRITE   2306055\n0x4004B040 READ    2306442\n0x400A4280 WRITE   2306650\n0x4004B080 READ    2307037\n0x400A42C0 WRITE   2307245\n0x4004B0C0 READ    2307632\n0x400A4300 WRITE   2307840\n0x4004B100 READ    2308227\n0x400A4340 WRITE   2308435\n0x4004B140 READ    2308822\n0x400A4380 WRITE   2309030\n0x4004B180 READ    2309417\n0x400A43C0 WRITE   2309625\n0x4004B1C0 READ    2310012\n0x400A4400 WRITE   2310220\n0x4004B200 READ    2310607\n0x400A4440 WRITE   2310815\n0x4004B240 READ    2311202\n0x4004B280 READ    2311808\n0x400A4540 WRITE   2312015\n0x4004B2C0 READ    2312402\n0x400A4580 WRITE   2312610\n0x4004B300 READ    2312997\n0x400A45C0 WRITE   2313205\n0x4004B340 READ    2313592\n0x400A4600 WRITE   2313800\n0x4004B380 READ    2314187\n0x400A4640 WRITE   2314395\n0x4004B3C0 READ    2314782\n0x400A4680 WRITE   2314990\n0x4004B400 READ    2315377\n0x400A46C0 WRITE   2315585\n0x4004B440 READ    2315972\n0x400A4700 WRITE   2316180\n0x4004B480 READ    2316567\n0x400A4740 WRITE   2316775\n0x4004B4C0 READ    2317162\n0x4004B500 READ    2317770\n0x400A4840 WRITE   2317980\n0x4004B540 READ    2318367\n0x400A4880 WRITE   2318575\n0x4004B580 READ    2318962\n0x400A48C0 WRITE   2319170\n0x4004B5C0 READ    2319557\n0x400A4900 WRITE   2319765\n0x4004B600 READ    2320152\n0x400A4940 WRITE   2320360\n0x4004B640 READ    2320747\n0x400A4980 WRITE   2320955\n0x4004B680 READ    2321342\n0x400A49C0 WRITE   2321550\n0x4004B6C0 READ    2321937\n0x400A4A00 WRITE   2322145\n0x4004B700 READ    2322532\n0x400A4A40 WRITE   2322740\n0x4004B740 READ    2323127\n0x4004B780 READ    2323733\n0x400A4B40 WRITE   2323940\n0x4004B7C0 READ    2324327\n0x400A4B80 WRITE   2324535\n0x4004B800 READ    2324922\n0x400A4BC0 WRITE   2325130\n0x4004B840 READ    2325517\n0x400A4C00 WRITE   2325725\n0x4004B880 READ    2326112\n0x400A4C40 WRITE   2326320\n0x4004B8C0 READ    2326707\n0x400A4C80 WRITE   2326915\n0x4004B900 READ    2327302\n0x400A4CC0 WRITE   2327510\n0x4004B940 READ    2327897\n0x400A4D00 WRITE   2328105\n0x4004B980 READ    2328492\n0x400A4D40 WRITE   2328700\n0x4004B9C0 READ    2329087\n0x4004BA00 READ    2329693\n0x400A4E40 WRITE   2329900\n0x4004BA40 READ    2330287\n0x400A4E80 WRITE   2330495\n0x4004BA80 READ    2330882\n0x400A4EC0 WRITE   2331090\n0x4004BAC0 READ    2331477\n0x400A4F00 WRITE   2331685\n0x4004BB00 READ    2332072\n0x400A4F40 WRITE   2332280\n0x4004BB40 READ    2332667\n0x400A4F80 WRITE   2332875\n0x4004BB80 READ    2333262\n0x400A4FC0 WRITE   2333470\n0x4004BBC0 READ    2333857\n0x400A5000 WRITE   2334065\n0x4004BC00 READ    2334452\n0x400A5040 WRITE   2334660\n0x4004BC40 READ    2335047\n0x4004BC80 READ    2335653\n0x400A5140 WRITE   2335860\n0x4004BCC0 READ    2336247\n0x400A5180 WRITE   2336455\n0x4004BD00 READ    2336842\n0x400A51C0 WRITE   2337050\n0x4004BD40 READ    2337437\n0x400A5200 WRITE   2337645\n0x4004BD80 READ    2338032\n0x400A5240 WRITE   2338240\n0x4004BDC0 READ    2338627\n0x400A5280 WRITE   2338835\n0x4004BE00 READ    2339222\n0x400A52C0 WRITE   2339430\n0x4004BE40 READ    2339817\n0x400A5300 WRITE   2340025\n0x4004BE80 READ    2340412\n0x400A5340 WRITE   2340620\n0x4004BEC0 READ    2341007\n0x4004BF00 READ    2341615\n0x400A5440 WRITE   2341825\n0x4004BF40 READ    2342212\n0x400A5480 WRITE   2342420\n0x4004BF80 READ    2342807\n0x400A54C0 WRITE   2343015\n0x4004BFC0 READ    2343402\n0x400A5500 WRITE   2343610\n0x4004C000 READ    2344027\n0x400A5540 WRITE   2344315\n0x4004C040 READ    2344702\n0x400A5580 WRITE   2344910\n0x4004C080 READ    2345297\n0x400A55C0 WRITE   2345505\n0x4004C0C0 READ    2345892\n0x400A5600 WRITE   2346100\n0x4004C100 READ    2346487\n0x400A5640 WRITE   2346695\n0x4004C140 READ    2347082\n0x4004C180 READ    2347688\n0x400A5740 WRITE   2347895\n0x4004C1C0 READ    2348282\n0x400A5780 WRITE   2348490\n0x4004C200 READ    2348877\n0x400A57C0 WRITE   2349085\n0x4004C240 READ    2349472\n0x400A5800 WRITE   2349680\n0x4004C280 READ    2350067\n0x400A5840 WRITE   2350275\n0x4004C2C0 READ    2350662\n0x400A5880 WRITE   2350870\n0x4004C300 READ    2351257\n0x400A58C0 WRITE   2351465\n0x4004C340 READ    2351852\n0x400A5900 WRITE   2352060\n0x4004C380 READ    2352447\n0x400A5940 WRITE   2352655\n0x4004C3C0 READ    2353042\n0x4004C400 READ    2353648\n0x400A5A40 WRITE   2353855\n0x4004C440 READ    2354242\n0x400A5A80 WRITE   2354450\n0x4004C480 READ    2354837\n0x400A5AC0 WRITE   2355045\n0x4004C4C0 READ    2355432\n0x400A5B00 WRITE   2355640\n0x4004C500 READ    2356027\n0x400A5B40 WRITE   2356235\n0x4004C540 READ    2356622\n0x400A5B80 WRITE   2356830\n0x4004C580 READ    2357217\n0x400A5BC0 WRITE   2357425\n0x4004C5C0 READ    2357812\n0x400A5C00 WRITE   2358020\n0x4004C600 READ    2358407\n0x400A5C40 WRITE   2358615\n0x4004C640 READ    2359002\n0x4004C680 READ    2359608\n0x400A5D40 WRITE   2359815\n0x4004C6C0 READ    2360202\n0x400A5D80 WRITE   2360410\n0x4004C700 READ    2360797\n0x400A5DC0 WRITE   2361005\n0x4004C740 READ    2361392\n0x400A5E00 WRITE   2361600\n0x4004C780 READ    2361987\n0x400A5E40 WRITE   2362195\n0x4004C7C0 READ    2362582\n0x400A5E80 WRITE   2362790\n0x4004C800 READ    2363177\n0x400A5EC0 WRITE   2363385\n0x4004C840 READ    2363772\n0x400A5F00 WRITE   2363980\n0x4004C880 READ    2364367\n0x400A5F40 WRITE   2364575\n0x4004C8C0 READ    2364962\n0x4004C900 READ    2365570\n0x400A6040 WRITE   2365780\n0x4004C940 READ    2366167\n0x400A6080 WRITE   2366375\n0x4004C980 READ    2366762\n0x400A60C0 WRITE   2366970\n0x4004C9C0 READ    2367357\n0x400A6100 WRITE   2367565\n0x4004CA00 READ    2367952\n0x400A6140 WRITE   2368160\n0x4004CA40 READ    2368547\n0x400A6180 WRITE   2368755\n0x4004CA80 READ    2369142\n0x400A61C0 WRITE   2369350\n0x4004CAC0 READ    2369737\n0x400A6200 WRITE   2369945\n0x4004CB00 READ    2370332\n0x400A6240 WRITE   2370540\n0x4004CB40 READ    2370927\n0x4004CB80 READ    2371533\n0x400A6340 WRITE   2371740\n0x4004CBC0 READ    2372127\n0x400A6380 WRITE   2372335\n0x4004CC00 READ    2372722\n0x400A63C0 WRITE   2372930\n0x4004CC40 READ    2373317\n0x400A6400 WRITE   2373525\n0x4004CC80 READ    2373912\n0x400A6440 WRITE   2374120\n0x4004CCC0 READ    2374507\n0x400A6480 WRITE   2374715\n0x4004CD00 READ    2375102\n0x400A64C0 WRITE   2375310\n0x4004CD40 READ    2375697\n0x400A6500 WRITE   2375905\n0x4004CD80 READ    2376292\n0x400A6540 WRITE   2376500\n0x4004CDC0 READ    2376887\n0x4004CE00 READ    2377493\n0x400A6640 WRITE   2377700\n0x4004CE40 READ    2378087\n0x400A6680 WRITE   2378295\n0x4004CE80 READ    2378682\n0x400A66C0 WRITE   2378890\n0x4004CEC0 READ    2379277\n0x400A6700 WRITE   2379485\n0x4004CF00 READ    2379872\n0x400A6740 WRITE   2380080\n0x4004CF40 READ    2380467\n0x400A6780 WRITE   2380675\n0x4004CF80 READ    2381062\n0x400A67C0 WRITE   2381270\n0x4004CFC0 READ    2381657\n0x400A6800 WRITE   2381865\n0x4004D000 READ    2382282\n0x400A6840 WRITE   2382490\n0x4004D040 READ    2382877\n0x4004D080 READ    2383483\n0x400A6940 WRITE   2383690\n0x4004D0C0 READ    2384077\n0x400A6980 WRITE   2384285\n0x4004D100 READ    2384672\n0x400A69C0 WRITE   2384880\n0x4004D140 READ    2385267\n0x400A6A00 WRITE   2385475\n0x4004D180 READ    2385862\n0x400A6A40 WRITE   2386070\n0x4004D1C0 READ    2386457\n0x400A6A80 WRITE   2386665\n0x4004D200 READ    2387052\n0x400A6AC0 WRITE   2387260\n0x4004D240 READ    2387647\n0x400A6B00 WRITE   2387855\n0x4004D280 READ    2388242\n0x400A6B40 WRITE   2388450\n0x4004D2C0 READ    2388837\n0x4004D300 READ    2389445\n0x400A6C40 WRITE   2389655\n0x4004D340 READ    2390042\n0x400A6C80 WRITE   2390250\n0x4004D380 READ    2390637\n0x400A6CC0 WRITE   2390845\n0x4004D3C0 READ    2391232\n0x400A6D00 WRITE   2391440\n0x4004D400 READ    2391827\n0x400A6D40 WRITE   2392035\n0x4004D440 READ    2392422\n0x400A6D80 WRITE   2392630\n0x4004D480 READ    2393017\n0x400A6DC0 WRITE   2393225\n0x4004D4C0 READ    2393612\n0x400A6E00 WRITE   2393820\n0x4004D500 READ    2394207\n0x400A6E40 WRITE   2394415\n0x4004D540 READ    2394802\n0x4004D580 READ    2395408\n0x400A6F40 WRITE   2395615\n0x4004D5C0 READ    2396002\n0x400A6F80 WRITE   2396210\n0x4004D600 READ    2396597\n0x400A6FC0 WRITE   2396805\n0x4004D640 READ    2397192\n0x400A7000 WRITE   2397400\n0x4004D680 READ    2397787\n0x400A7040 WRITE   2397995\n0x4004D6C0 READ    2398382\n0x400A7080 WRITE   2398590\n0x4004D700 READ    2398977\n0x400A70C0 WRITE   2399185\n0x4004D740 READ    2399572\n0x400A7100 WRITE   2399780\n0x4004D780 READ    2400167\n0x400A7140 WRITE   2400375\n0x4004D7C0 READ    2400762\n0x4004D800 READ    2401368\n0x400A7240 WRITE   2401575\n0x4004D840 READ    2401962\n0x400A7280 WRITE   2402170\n0x4004D880 READ    2402557\n0x400A72C0 WRITE   2402765\n0x4004D8C0 READ    2403152\n0x400A7300 WRITE   2403360\n0x4004D900 READ    2403747\n0x400A7340 WRITE   2403955\n0x4004D940 READ    2404342\n0x400A7380 WRITE   2404550\n0x4004D980 READ    2404937\n0x400A73C0 WRITE   2405145\n0x4004D9C0 READ    2405532\n0x400A7400 WRITE   2405740\n0x4004DA00 READ    2406127\n0x400A7440 WRITE   2406335\n0x4004DA40 READ    2406722\n0x4004DA80 READ    2407328\n0x400A7540 WRITE   2407535\n0x4004DAC0 READ    2407922\n0x400A7580 WRITE   2408130\n0x4004DB00 READ    2408517\n0x400A75C0 WRITE   2408725\n0x4004DB40 READ    2409112\n0x400A7600 WRITE   2409320\n0x4004DB80 READ    2409707\n0x400A7640 WRITE   2409915\n0x4004DBC0 READ    2410302\n0x400A7680 WRITE   2410510\n0x4004DC00 READ    2410897\n0x400A76C0 WRITE   2411105\n0x4004DC40 READ    2411492\n0x400A7700 WRITE   2411700\n0x4004DC80 READ    2412087\n0x400A7740 WRITE   2412295\n0x4004DCC0 READ    2412682\n0x4004DD00 READ    2413290\n0x400A7840 WRITE   2413500\n0x4004DD40 READ    2413887\n0x400A7880 WRITE   2414095\n0x4004DD80 READ    2414482\n0x400A78C0 WRITE   2414690\n0x4004DDC0 READ    2415077\n0x400A7900 WRITE   2415285\n0x4004DE00 READ    2415672\n0x400A7940 WRITE   2415880\n0x4004DE40 READ    2416267\n0x400A7980 WRITE   2416475\n0x4004DE80 READ    2416862\n0x400A79C0 WRITE   2417070\n0x4004DEC0 READ    2417457\n0x400A7A00 WRITE   2417665\n0x4004DF00 READ    2418052\n0x400A7A40 WRITE   2418260\n0x4004DF40 READ    2418647\n0x4004DF80 READ    2419253\n0x400A7B40 WRITE   2419460\n0x4004DFC0 READ    2419847\n0x400A7B80 WRITE   2420055\n0x4004E000 READ    2420472\n0x400A7BC0 WRITE   2420680\n0x4004E040 READ    2421067\n0x400A7C00 WRITE   2421275\n0x4004E080 READ    2421662\n0x400A7C40 WRITE   2421870\n0x4004E0C0 READ    2422257\n0x400A7C80 WRITE   2422465\n0x4004E100 READ    2422852\n0x400A7CC0 WRITE   2423060\n0x4004E140 READ    2423447\n0x400A7D00 WRITE   2423655\n0x4004E180 READ    2424042\n0x400A7D40 WRITE   2424250\n0x4004E1C0 READ    2424637\n0x4004E200 READ    2425243\n0x400A7E40 WRITE   2425450\n0x4004E240 READ    2425837\n0x400A7E80 WRITE   2426045\n0x4004E280 READ    2426432\n0x400A7EC0 WRITE   2426640\n0x4004E2C0 READ    2427027\n0x400A7F00 WRITE   2427235\n0x4004E300 READ    2427622\n0x400A7F40 WRITE   2427830\n0x4004E340 READ    2428217\n0x400A7F80 WRITE   2428425\n0x4004E380 READ    2428812\n0x400A7FC0 WRITE   2429020\n0x4004E3C0 READ    2429407\n0x400A8000 WRITE   2429615\n0x4004E400 READ    2430002\n0x400A8040 WRITE   2430210\n0x4004E440 READ    2430597\n0x4004E480 READ    2431203\n0x400A8140 WRITE   2431410\n0x4004E4C0 READ    2431797\n0x400A8180 WRITE   2432005\n0x4004E500 READ    2432392\n0x400A81C0 WRITE   2432600\n0x4004E540 READ    2432987\n0x400A8200 WRITE   2433195\n0x4004E580 READ    2433582\n0x400A8240 WRITE   2433790\n0x4004E5C0 READ    2434177\n0x400A8280 WRITE   2434385\n0x4004E600 READ    2434772\n0x400A82C0 WRITE   2434980\n0x4004E640 READ    2435367\n0x400A8300 WRITE   2435575\n0x4004E680 READ    2435962\n0x400A8340 WRITE   2436170\n0x4004E6C0 READ    2436557\n0x4004E700 READ    2437165\n0x400A8440 WRITE   2437375\n0x4004E740 READ    2437762\n0x400A8480 WRITE   2437970\n0x4004E780 READ    2438357\n0x400A84C0 WRITE   2438565\n0x4004E7C0 READ    2438952\n0x400A8500 WRITE   2439160\n0x4004E800 READ    2439547\n0x400A8540 WRITE   2439755\n0x4004E840 READ    2440142\n0x400A8580 WRITE   2440350\n0x4004E880 READ    2440737\n0x400A85C0 WRITE   2440945\n0x4004E8C0 READ    2441332\n0x400A8600 WRITE   2441540\n0x4004E900 READ    2441927\n0x400A8640 WRITE   2442135\n0x4004E940 READ    2442522\n0x4004E980 READ    2443128\n0x400A8740 WRITE   2443335\n0x4004E9C0 READ    2443722\n0x400A8780 WRITE   2443930\n0x4004EA00 READ    2444317\n0x400A87C0 WRITE   2444525\n0x4004EA40 READ    2444912\n0x400A8800 WRITE   2445120\n0x4004EA80 READ    2445507\n0x400A8840 WRITE   2445715\n0x4004EAC0 READ    2446102\n0x400A8880 WRITE   2446310\n0x4004EB00 READ    2446697\n0x400A88C0 WRITE   2446905\n0x4004EB40 READ    2447292\n0x400A8900 WRITE   2447500\n0x4004EB80 READ    2447887\n0x400A8940 WRITE   2448095\n0x4004EBC0 READ    2448482\n0x4004EC00 READ    2449088\n0x400A8A40 WRITE   2449295\n0x4004EC40 READ    2449682\n0x400A8A80 WRITE   2449890\n0x4004EC80 READ    2450277\n0x400A8AC0 WRITE   2450485\n0x4004ECC0 READ    2450872\n0x400A8B00 WRITE   2451080\n0x4004ED00 READ    2451467\n0x400A8B40 WRITE   2451675\n0x4004ED40 READ    2452062\n0x400A8B80 WRITE   2452270\n0x4004ED80 READ    2452657\n0x400A8BC0 WRITE   2452865\n0x4004EDC0 READ    2453252\n0x400A8C00 WRITE   2453460\n0x4004EE00 READ    2453847\n0x400A8C40 WRITE   2454055\n0x4004EE40 READ    2454442\n0x4004EE80 READ    2455048\n0x400A8D40 WRITE   2455255\n0x4004EEC0 READ    2455642\n0x400A8D80 WRITE   2455850\n0x4004EF00 READ    2456237\n0x400A8DC0 WRITE   2456445\n0x4004EF40 READ    2456832\n0x400A8E00 WRITE   2457040\n0x4004EF80 READ    2457427\n0x400A8E40 WRITE   2457635\n0x4004EFC0 READ    2458022\n0x400A8E80 WRITE   2458230\n0x4004F000 READ    2458647\n0x400A8EC0 WRITE   2458855\n0x4004F040 READ    2459242\n0x400A8F00 WRITE   2459450\n0x4004F080 READ    2459837\n0x400A8F40 WRITE   2460045\n0x4004F0C0 READ    2460432\n0x4004F100 READ    2461040\n0x400A9040 WRITE   2461250\n0x4004F140 READ    2461637\n0x400A9080 WRITE   2461845\n0x4004F180 READ    2462232\n0x400A90C0 WRITE   2462440\n0x4004F1C0 READ    2462827\n0x400A9100 WRITE   2463035\n0x4004F200 READ    2463422\n0x400A9140 WRITE   2463630\n0x4004F240 READ    2464017\n0x400A9180 WRITE   2464225\n0x4004F280 READ    2464612\n0x400A91C0 WRITE   2464820\n0x4004F2C0 READ    2465207\n0x400A9200 WRITE   2465415\n0x4004F300 READ    2465802\n0x400A9240 WRITE   2466010\n0x4004F340 READ    2466397\n0x4004F380 READ    2467003\n0x400A9340 WRITE   2467210\n0x4004F3C0 READ    2467597\n0x400A9380 WRITE   2467805\n0x4004F400 READ    2468192\n0x400A93C0 WRITE   2468400\n0x4004F440 READ    2468787\n0x400A9400 WRITE   2468995\n0x4004F480 READ    2469382\n0x400A9440 WRITE   2469590\n0x4004F4C0 READ    2469977\n0x400A9480 WRITE   2470185\n0x4004F500 READ    2470572\n0x400A94C0 WRITE   2470780\n0x4004F540 READ    2471167\n0x400A9500 WRITE   2471375\n0x4004F580 READ    2471762\n0x400A9540 WRITE   2471970\n0x4004F5C0 READ    2472357\n0x4004F600 READ    2472963\n0x400A9640 WRITE   2473170\n0x4004F640 READ    2473557\n0x400A9680 WRITE   2473765\n0x4004F680 READ    2474152\n0x400A96C0 WRITE   2474360\n0x4004F6C0 READ    2474747\n0x400A9700 WRITE   2474955\n0x4004F700 READ    2475342\n0x400A9740 WRITE   2475550\n0x4004F740 READ    2475937\n0x400A9780 WRITE   2476145\n0x4004F780 READ    2476532\n0x400A97C0 WRITE   2476740\n0x4004F7C0 READ    2477127\n0x400A9800 WRITE   2477335\n0x4004F800 READ    2477722\n0x400A9840 WRITE   2477930\n0x4004F840 READ    2478317\n0x4004F880 READ    2478923\n0x400A9940 WRITE   2479130\n0x4004F8C0 READ    2479517\n0x400A9980 WRITE   2479725\n0x4004F900 READ    2480112\n0x400A99C0 WRITE   2480320\n0x4004F940 READ    2480707\n0x400A9A00 WRITE   2480915\n0x4004F980 READ    2481302\n0x400A9A40 WRITE   2481510\n0x4004F9C0 READ    2481897\n0x400A9A80 WRITE   2482105\n0x4004FA00 READ    2482492\n0x400A9AC0 WRITE   2482700\n0x4004FA40 READ    2483087\n0x400A9B00 WRITE   2483295\n0x4004FA80 READ    2483682\n0x400A9B40 WRITE   2483890\n0x4004FAC0 READ    2484277\n0x4004FB00 READ    2484885\n0x400A9C40 WRITE   2485095\n0x4004FB40 READ    2485482\n0x400A9C80 WRITE   2485690\n0x4004FB80 READ    2486077\n0x400A9CC0 WRITE   2486285\n0x4004FBC0 READ    2486672\n0x400A9D00 WRITE   2486880\n0x4004FC00 READ    2487267\n0x400A9D40 WRITE   2487475\n0x4004FC40 READ    2487862\n0x400A9D80 WRITE   2488070\n0x4004FC80 READ    2488457\n0x400A9DC0 WRITE   2488665\n0x4004FCC0 READ    2489052\n0x400A9E00 WRITE   2489260\n0x4004FD00 READ    2489647\n0x400A9E40 WRITE   2489855\n0x4004FD40 READ    2490242\n0x4004FD80 READ    2490848\n0x400A9F40 WRITE   2491055\n0x4004FDC0 READ    2491442\n0x400A9F80 WRITE   2491650\n0x4004FE00 READ    2492037\n0x400A9FC0 WRITE   2492245\n0x4004FE40 READ    2492632\n0x400AA000 WRITE   2492840\n0x4004FE80 READ    2493227\n0x400AA040 WRITE   2493435\n0x4004FEC0 READ    2493822\n0x400AA080 WRITE   2494030\n0x4004FF00 READ    2494417\n0x400AA0C0 WRITE   2494625\n0x4004FF40 READ    2495012\n0x400AA100 WRITE   2495220\n0x4004FF80 READ    2495607\n0x400AA140 WRITE   2495815\n0x4004FFC0 READ    2496202\n0x40050000 READ    2496838\n0x400AA240 WRITE   2497125\n0x40050040 READ    2497512\n0x400AA280 WRITE   2497720\n0x40050080 READ    2498107\n0x400AA2C0 WRITE   2498315\n0x400500C0 READ    2498702\n0x400AA300 WRITE   2498910\n0x40050100 READ    2499297\n0x400AA340 WRITE   2499505\n0x40050140 READ    2499892\n0x400AA380 WRITE   2500100\n0x40050180 READ    2500487\n0x400AA3C0 WRITE   2500695\n0x400501C0 READ    2501082\n0x400AA400 WRITE   2501290\n0x40050200 READ    2501677\n0x400AA440 WRITE   2501885\n0x40050240 READ    2502272\n0x40050280 READ    2502878\n0x400AA540 WRITE   2503085\n0x400502C0 READ    2503472\n0x400AA580 WRITE   2503680\n0x40050300 READ    2504067\n0x400AA5C0 WRITE   2504275\n0x40050340 READ    2504662\n0x400AA600 WRITE   2504870\n0x40050380 READ    2505257\n0x400AA640 WRITE   2505465\n0x400503C0 READ    2505852\n0x400AA680 WRITE   2506060\n0x40050400 READ    2506447\n0x400AA6C0 WRITE   2506655\n0x40050440 READ    2507042\n0x400AA700 WRITE   2507250\n0x40050480 READ    2507637\n0x400AA740 WRITE   2507845\n0x400504C0 READ    2508232\n0x40050500 READ    2508840\n0x400AA840 WRITE   2509050\n0x40050540 READ    2509437\n0x400AA880 WRITE   2509645\n0x40050580 READ    2510032\n0x400AA8C0 WRITE   2510240\n0x400505C0 READ    2510627\n0x400AA900 WRITE   2510835\n0x40050600 READ    2511222\n0x400AA940 WRITE   2511430\n0x40050640 READ    2511817\n0x400AA980 WRITE   2512025\n0x40050680 READ    2512412\n0x400AA9C0 WRITE   2512620\n0x400506C0 READ    2513007\n0x400AAA00 WRITE   2513215\n0x40050700 READ    2513602\n0x400AAA40 WRITE   2513810\n0x40050740 READ    2514197\n0x40050780 READ    2514803\n0x400AAB40 WRITE   2515010\n0x400507C0 READ    2515397\n0x400AAB80 WRITE   2515605\n0x40050800 READ    2515992\n0x400AABC0 WRITE   2516200\n0x40050840 READ    2516587\n0x400AAC00 WRITE   2516795\n0x40050880 READ    2517182\n0x400AAC40 WRITE   2517390\n0x400508C0 READ    2517777\n0x400AAC80 WRITE   2517985\n0x40050900 READ    2518372\n0x400AACC0 WRITE   2518580\n0x40050940 READ    2518967\n0x400AAD00 WRITE   2519175\n0x40050980 READ    2519562\n0x400AAD40 WRITE   2519770\n0x400509C0 READ    2520157\n0x40050A00 READ    2520763\n0x400AAE40 WRITE   2520970\n0x40050A40 READ    2521357\n0x400AAE80 WRITE   2521565\n0x40050A80 READ    2521952\n0x400AAEC0 WRITE   2522160\n0x40050AC0 READ    2522547\n0x400AAF00 WRITE   2522755\n0x40050B00 READ    2523142\n0x400AAF40 WRITE   2523350\n0x40050B40 READ    2523737\n0x400AAF80 WRITE   2523945\n0x40050B80 READ    2524332\n0x400AAFC0 WRITE   2524540\n0x40050BC0 READ    2524927\n0x400AB000 WRITE   2525135\n0x40050C00 READ    2525522\n0x400AB040 WRITE   2525730\n0x40050C40 READ    2526117\n0x40050C80 READ    2526723\n0x400AB140 WRITE   2526930\n0x40050CC0 READ    2527317\n0x400AB180 WRITE   2527525\n0x40050D00 READ    2527912\n0x400AB1C0 WRITE   2528120\n0x40050D40 READ    2528507\n0x400AB200 WRITE   2528715\n0x40050D80 READ    2529102\n0x400AB240 WRITE   2529310\n0x40050DC0 READ    2529697\n0x400AB280 WRITE   2529905\n0x40050E00 READ    2530292\n0x400AB2C0 WRITE   2530500\n0x40050E40 READ    2530887\n0x400AB300 WRITE   2531095\n0x40050E80 READ    2531482\n0x400AB340 WRITE   2531690\n0x40050EC0 READ    2532077\n0x40050F00 READ    2532685\n0x400AB440 WRITE   2532895\n0x40050F40 READ    2533282\n0x400AB480 WRITE   2533490\n0x40050F80 READ    2533877\n0x400AB4C0 WRITE   2534085\n0x40050FC0 READ    2534472\n0x400AB500 WRITE   2534680\n0x40051000 READ    2535097\n0x400AB540 WRITE   2535305\n0x40051040 READ    2535692\n0x400AB580 WRITE   2535900\n0x40051080 READ    2536287\n0x400AB5C0 WRITE   2536495\n0x400510C0 READ    2536882\n0x400AB600 WRITE   2537090\n0x40051100 READ    2537477\n0x400AB640 WRITE   2537685\n0x40051140 READ    2538072\n0x40051180 READ    2538678\n0x400AB740 WRITE   2538885\n0x400511C0 READ    2539272\n0x400AB780 WRITE   2539480\n0x40051200 READ    2539867\n0x400AB7C0 WRITE   2540075\n0x40051240 READ    2540462\n0x400AB800 WRITE   2540670\n0x40051280 READ    2541057\n0x400AB840 WRITE   2541265\n0x400512C0 READ    2541652\n0x400AB880 WRITE   2541860\n0x40051300 READ    2542247\n0x400AB8C0 WRITE   2542455\n0x40051340 READ    2542842\n0x400AB900 WRITE   2543050\n0x40051380 READ    2543437\n0x400AB940 WRITE   2543645\n0x400513C0 READ    2544032\n0x40051400 READ    2544638\n0x400ABA40 WRITE   2544845\n0x40051440 READ    2545232\n0x400ABA80 WRITE   2545440\n0x40051480 READ    2545827\n0x400ABAC0 WRITE   2546035\n0x400514C0 READ    2546422\n0x400ABB00 WRITE   2546630\n0x40051500 READ    2547017\n0x400ABB40 WRITE   2547225\n0x40051540 READ    2547612\n0x400ABB80 WRITE   2547820\n0x40051580 READ    2548207\n0x400ABBC0 WRITE   2548415\n0x400515C0 READ    2548802\n0x400ABC00 WRITE   2549010\n0x40051600 READ    2549397\n0x400ABC40 WRITE   2549605\n0x40051640 READ    2549992\n0x40051680 READ    2550598\n0x400ABD40 WRITE   2550805\n0x400516C0 READ    2551192\n0x400ABD80 WRITE   2551400\n0x40051700 READ    2551787\n0x400ABDC0 WRITE   2551995\n0x40051740 READ    2552382\n0x400ABE00 WRITE   2552590\n0x40051780 READ    2552977\n0x400ABE40 WRITE   2553185\n0x400517C0 READ    2553572\n0x400ABE80 WRITE   2553780\n0x40051800 READ    2554167\n0x400ABEC0 WRITE   2554375\n0x40051840 READ    2554762\n0x400ABF00 WRITE   2554970\n0x40051880 READ    2555357\n0x400ABF40 WRITE   2555565\n0x400518C0 READ    2555952\n0x40051900 READ    2556560\n0x400AC040 WRITE   2556770\n0x40051940 READ    2557157\n0x400AC080 WRITE   2557365\n0x40051980 READ    2557752\n0x400AC0C0 WRITE   2557960\n0x400519C0 READ    2558347\n0x400AC100 WRITE   2558555\n0x40051A00 READ    2558942\n0x400AC140 WRITE   2559150\n0x40051A40 READ    2559537\n0x400AC180 WRITE   2559745\n0x40051A80 READ    2560132\n0x400AC1C0 WRITE   2560340\n0x40051AC0 READ    2560727\n0x400AC200 WRITE   2560935\n0x40051B00 READ    2561322\n0x400AC240 WRITE   2561530\n0x40051B40 READ    2561917\n0x40051B80 READ    2562523\n0x400AC340 WRITE   2562730\n0x40051BC0 READ    2563117\n0x400AC380 WRITE   2563325\n0x40051C00 READ    2563712\n0x400AC3C0 WRITE   2563920\n0x40051C40 READ    2564307\n0x400AC400 WRITE   2564515\n0x40051C80 READ    2564902\n0x400AC440 WRITE   2565110\n0x40051CC0 READ    2565497\n0x400AC480 WRITE   2565705\n0x40051D00 READ    2566092\n0x400AC4C0 WRITE   2566300\n0x40051D40 READ    2566687\n0x400AC500 WRITE   2566895\n0x40051D80 READ    2567282\n0x400AC540 WRITE   2567490\n0x40051DC0 READ    2567877\n0x40051E00 READ    2568483\n0x400AC640 WRITE   2568690\n0x40051E40 READ    2569077\n0x400AC680 WRITE   2569285\n0x40051E80 READ    2569672\n0x400AC6C0 WRITE   2569880\n0x40051EC0 READ    2570267\n0x400AC700 WRITE   2570475\n0x40051F00 READ    2570862\n0x400AC740 WRITE   2571070\n0x40051F40 READ    2571457\n0x400AC780 WRITE   2571665\n0x40051F80 READ    2572052\n0x400AC7C0 WRITE   2572260\n0x40051FC0 READ    2572647\n0x400AC800 WRITE   2572855\n0x40052000 READ    2573272\n0x400AC840 WRITE   2573480\n0x40052040 READ    2573867\n0x40052080 READ    2574473\n0x400AC940 WRITE   2574680\n0x400520C0 READ    2575067\n0x400AC980 WRITE   2575275\n0x40052100 READ    2575662\n0x400AC9C0 WRITE   2575870\n0x40052140 READ    2576257\n0x400ACA00 WRITE   2576465\n0x40052180 READ    2576852\n0x400ACA40 WRITE   2577060\n0x400521C0 READ    2577447\n0x400ACA80 WRITE   2577655\n0x40052200 READ    2578042\n0x400ACAC0 WRITE   2578250\n0x40052240 READ    2578637\n0x400ACB00 WRITE   2578845\n0x40052280 READ    2579232\n0x400ACB40 WRITE   2579440\n0x400522C0 READ    2579827\n0x40052300 READ    2580435\n0x400ACC40 WRITE   2580645\n0x40052340 READ    2581032\n0x400ACC80 WRITE   2581240\n0x40052380 READ    2581627\n0x400ACCC0 WRITE   2581835\n0x400523C0 READ    2582222\n0x400ACD00 WRITE   2582430\n0x40052400 READ    2582817\n0x400ACD40 WRITE   2583025\n0x40052440 READ    2583412\n0x400ACD80 WRITE   2583620\n0x40052480 READ    2584007\n0x400ACDC0 WRITE   2584215\n0x400524C0 READ    2584602\n0x400ACE00 WRITE   2584810\n0x40052500 READ    2585197\n0x400ACE40 WRITE   2585405\n0x40052540 READ    2585792\n0x40052580 READ    2586398\n0x400ACF40 WRITE   2586605\n0x400525C0 READ    2586992\n0x400ACF80 WRITE   2587200\n0x40052600 READ    2587587\n0x400ACFC0 WRITE   2587795\n0x40052640 READ    2588182\n0x400AD000 WRITE   2588390\n0x40052680 READ    2588777\n0x400AD040 WRITE   2588985\n0x400526C0 READ    2589372\n0x400AD080 WRITE   2589580\n0x40052700 READ    2589967\n0x400AD0C0 WRITE   2590175\n0x40052740 READ    2590562\n0x400AD100 WRITE   2590770\n0x40052780 READ    2591157\n0x400AD140 WRITE   2591365\n0x400527C0 READ    2591752\n0x40052800 READ    2592358\n0x400AD240 WRITE   2592565\n0x40052840 READ    2592952\n0x400AD280 WRITE   2593160\n0x40052880 READ    2593547\n0x400AD2C0 WRITE   2593755\n0x400528C0 READ    2594142\n0x400AD300 WRITE   2594350\n0x40052900 READ    2594737\n0x400AD340 WRITE   2594945\n0x40052940 READ    2595332\n0x400AD380 WRITE   2595540\n0x40052980 READ    2595927\n0x400AD3C0 WRITE   2596135\n0x400529C0 READ    2596522\n0x400AD400 WRITE   2596730\n0x40052A00 READ    2597117\n0x400AD440 WRITE   2597325\n0x40052A40 READ    2597712\n0x40052A80 READ    2598318\n0x400AD540 WRITE   2598525\n0x40052AC0 READ    2598912\n0x400AD580 WRITE   2599120\n0x40052B00 READ    2599507\n0x400AD5C0 WRITE   2599715\n0x40052B40 READ    2600102\n0x400AD600 WRITE   2600310\n0x40052B80 READ    2600697\n0x400AD640 WRITE   2600905\n0x40052BC0 READ    2601292\n0x400AD680 WRITE   2601500\n0x40052C00 READ    2601887\n0x400AD6C0 WRITE   2602095\n0x40052C40 READ    2602482\n0x400AD700 WRITE   2602690\n0x40052C80 READ    2603077\n0x400AD740 WRITE   2603285\n0x40052CC0 READ    2603672\n0x40052D00 READ    2604280\n0x400AD840 WRITE   2604490\n0x40052D40 READ    2604877\n0x400AD880 WRITE   2605085\n0x40052D80 READ    2605472\n0x400AD8C0 WRITE   2605680\n0x40052DC0 READ    2606067\n0x400AD900 WRITE   2606275\n0x40052E00 READ    2606662\n0x400AD940 WRITE   2606870\n0x40052E40 READ    2607257\n0x400AD980 WRITE   2607465\n0x40052E80 READ    2607852\n0x400AD9C0 WRITE   2608060\n0x40052EC0 READ    2608447\n0x400ADA00 WRITE   2608655\n0x40052F00 READ    2609042\n0x400ADA40 WRITE   2609250\n0x40052F40 READ    2609637\n0x40052F80 READ    2610243\n0x400ADB40 WRITE   2610450\n0x40052FC0 READ    2610837\n0x400ADB80 WRITE   2611045\n0x40053000 READ    2611462\n0x400ADBC0 WRITE   2611670\n0x40053040 READ    2612057\n0x400ADC00 WRITE   2612265\n0x40053080 READ    2612652\n0x400ADC40 WRITE   2612860\n0x400530C0 READ    2613247\n0x400ADC80 WRITE   2613455\n0x40053100 READ    2613842\n0x400ADCC0 WRITE   2614050\n0x40053140 READ    2614437\n0x400ADD00 WRITE   2614645\n0x40053180 READ    2615032\n0x400ADD40 WRITE   2615240\n0x400531C0 READ    2615627\n0x40053200 READ    2616233\n0x400ADE40 WRITE   2616440\n0x40053240 READ    2616827\n0x400ADE80 WRITE   2617035\n0x40053280 READ    2617422\n0x400ADEC0 WRITE   2617630\n0x400532C0 READ    2618017\n0x400ADF00 WRITE   2618225\n0x40053300 READ    2618612\n0x400ADF40 WRITE   2618820\n0x40053340 READ    2619207\n0x400ADF80 WRITE   2619415\n0x40053380 READ    2619802\n0x400ADFC0 WRITE   2620010\n0x400533C0 READ    2620397\n0x400AE000 WRITE   2620605\n0x40053400 READ    2620992\n0x400AE040 WRITE   2621200\n0x40053440 READ    2621587\n0x40053480 READ    2622193\n0x400AE140 WRITE   2622400\n0x400534C0 READ    2622787\n0x400AE180 WRITE   2622995\n0x40053500 READ    2623382\n0x400AE1C0 WRITE   2623590\n0x40053540 READ    2623977\n0x400AE200 WRITE   2624185\n0x40053580 READ    2624572\n0x400AE240 WRITE   2624780\n0x400535C0 READ    2625167\n0x400AE280 WRITE   2625375\n0x40053600 READ    2625762\n0x400AE2C0 WRITE   2625970\n0x40053640 READ    2626357\n0x400AE300 WRITE   2626565\n0x40053680 READ    2626952\n0x400AE340 WRITE   2627160\n0x400536C0 READ    2627547\n0x40053700 READ    2628155\n0x400AE440 WRITE   2628365\n0x40053740 READ    2628752\n0x400AE480 WRITE   2628960\n0x40053780 READ    2629347\n0x400AE4C0 WRITE   2629555\n0x400537C0 READ    2629942\n0x400AE500 WRITE   2630150\n0x40053800 READ    2630537\n0x400AE540 WRITE   2630745\n0x40053840 READ    2631132\n0x400AE580 WRITE   2631340\n0x40053880 READ    2631727\n0x400AE5C0 WRITE   2631935\n0x400538C0 READ    2632322\n0x400AE600 WRITE   2632530\n0x40053900 READ    2632917\n0x400AE640 WRITE   2633125\n0x40053940 READ    2633512\n0x40053980 READ    2634118\n0x400AE740 WRITE   2634325\n0x400539C0 READ    2634712\n0x400AE780 WRITE   2634920\n0x40053A00 READ    2635307\n0x400AE7C0 WRITE   2635515\n0x40053A40 READ    2635902\n0x400AE800 WRITE   2636110\n0x40053A80 READ    2636497\n0x400AE840 WRITE   2636705\n0x40053AC0 READ    2637092\n0x400AE880 WRITE   2637300\n0x40053B00 READ    2637687\n0x400AE8C0 WRITE   2637895\n0x40053B40 READ    2638282\n0x400AE900 WRITE   2638490\n0x40053B80 READ    2638877\n0x400AE940 WRITE   2639085\n0x40053BC0 READ    2639472\n0x40053C00 READ    2640078\n0x400AEA40 WRITE   2640285\n0x40053C40 READ    2640672\n0x400AEA80 WRITE   2640880\n0x40053C80 READ    2641267\n0x400AEAC0 WRITE   2641475\n0x40053CC0 READ    2641862\n0x400AEB00 WRITE   2642070\n0x40053D00 READ    2642457\n0x400AEB40 WRITE   2642665\n0x40053D40 READ    2643052\n0x400AEB80 WRITE   2643260\n0x40053D80 READ    2643647\n0x400AEBC0 WRITE   2643855\n0x40053DC0 READ    2644242\n0x400AEC00 WRITE   2644450\n0x40053E00 READ    2644837\n0x400AEC40 WRITE   2645045\n0x40053E40 READ    2645432\n0x40053E80 READ    2646038\n0x400AED40 WRITE   2646245\n0x40053EC0 READ    2646632\n0x400AED80 WRITE   2646840\n0x40053F00 READ    2647227\n0x400AEDC0 WRITE   2647435\n0x40053F40 READ    2647822\n0x400AEE00 WRITE   2648030\n0x40053F80 READ    2648417\n0x400AEE40 WRITE   2648625\n0x40053FC0 READ    2649012\n0x400AEE80 WRITE   2649220\n0x40054000 READ    2649637\n0x400AEEC0 WRITE   2649925\n0x40054040 READ    2650312\n0x400AEF00 WRITE   2650520\n0x40054080 READ    2650907\n0x400AEF40 WRITE   2651115\n0x400540C0 READ    2651502\n0x40054100 READ    2652110\n0x400AF040 WRITE   2652320\n0x40054140 READ    2652707\n0x400AF080 WRITE   2652915\n0x40054180 READ    2653302\n0x400AF0C0 WRITE   2653510\n0x400541C0 READ    2653897\n0x400AF100 WRITE   2654105\n0x40054200 READ    2654492\n0x400AF140 WRITE   2654700\n0x40054240 READ    2655087\n0x400AF180 WRITE   2655295\n0x40054280 READ    2655682\n0x400AF1C0 WRITE   2655890\n0x400542C0 READ    2656277\n0x400AF200 WRITE   2656485\n0x40054300 READ    2656872\n0x400AF240 WRITE   2657080\n0x40054340 READ    2657467\n0x40054380 READ    2658073\n0x400AF340 WRITE   2658280\n0x400543C0 READ    2658667\n0x400AF380 WRITE   2658875\n0x40054400 READ    2659262\n0x400AF3C0 WRITE   2659470\n0x40054440 READ    2659857\n0x400AF400 WRITE   2660065\n0x40054480 READ    2660452\n0x400AF440 WRITE   2660660\n0x400544C0 READ    2661047\n0x400AF480 WRITE   2661255\n0x40054500 READ    2661642\n0x400AF4C0 WRITE   2661850\n0x40054540 READ    2662237\n0x400AF500 WRITE   2662445\n0x40054580 READ    2662832\n0x400AF540 WRITE   2663040\n0x400545C0 READ    2663427\n0x40054600 READ    2664033\n0x400AF640 WRITE   2664240\n0x40054640 READ    2664627\n0x400AF680 WRITE   2664835\n0x40054680 READ    2665222\n0x400AF6C0 WRITE   2665430\n0x400546C0 READ    2665817\n0x400AF700 WRITE   2666025\n0x40054700 READ    2666412\n0x400AF740 WRITE   2666620\n0x40054740 READ    2667007\n0x400AF780 WRITE   2667215\n0x40054780 READ    2667602\n0x400AF7C0 WRITE   2667810\n0x400547C0 READ    2668197\n0x400AF800 WRITE   2668405\n0x40054800 READ    2668792\n0x400AF840 WRITE   2669000\n0x40054840 READ    2669387\n0x40054880 READ    2669993\n0x400AF940 WRITE   2670200\n0x400548C0 READ    2670587\n0x400AF980 WRITE   2670795\n0x40054900 READ    2671182\n0x400AF9C0 WRITE   2671390\n0x40054940 READ    2671777\n0x400AFA00 WRITE   2671985\n0x40054980 READ    2672372\n0x400AFA40 WRITE   2672580\n0x400549C0 READ    2672967\n0x400AFA80 WRITE   2673175\n0x40054A00 READ    2673562\n0x400AFAC0 WRITE   2673770\n0x40054A40 READ    2674157\n0x400AFB00 WRITE   2674365\n0x40054A80 READ    2674752\n0x400AFB40 WRITE   2674960\n0x40054AC0 READ    2675347\n0x40054B00 READ    2675955\n0x400AFC40 WRITE   2676165\n0x40054B40 READ    2676552\n0x400AFC80 WRITE   2676760\n0x40054B80 READ    2677147\n0x400AFCC0 WRITE   2677355\n0x40054BC0 READ    2677742\n0x400AFD00 WRITE   2677950\n0x40054C00 READ    2678337\n0x400AFD40 WRITE   2678545\n0x40054C40 READ    2678932\n0x400AFD80 WRITE   2679140\n0x40054C80 READ    2679527\n0x400AFDC0 WRITE   2679735\n0x40054CC0 READ    2680122\n0x400AFE00 WRITE   2680330\n0x40054D00 READ    2680717\n0x400AFE40 WRITE   2680925\n0x40054D40 READ    2681312\n0x40054D80 READ    2681918\n0x400AFF40 WRITE   2682125\n0x40054DC0 READ    2682512\n0x400AFF80 WRITE   2682720\n0x40054E00 READ    2683107\n0x400AFFC0 WRITE   2683315\n0x40054E40 READ    2683702\n0x400B0000 WRITE   2683910\n0x40054E80 READ    2684297\n0x400B0040 WRITE   2684505\n0x40054EC0 READ    2684892\n0x400B0080 WRITE   2685100\n0x40054F00 READ    2685487\n0x400B00C0 WRITE   2685695\n0x40054F40 READ    2686082\n0x400B0100 WRITE   2686290\n0x40054F80 READ    2686677\n0x400B0140 WRITE   2686885\n0x40054FC0 READ    2687272\n0x40055000 READ    2687908\n0x400B0240 WRITE   2688115\n0x40055040 READ    2688502\n0x400B0280 WRITE   2688710\n0x40055080 READ    2689097\n0x400B02C0 WRITE   2689305\n0x400550C0 READ    2689692\n0x400B0300 WRITE   2689900\n0x40055100 READ    2690287\n0x400B0340 WRITE   2690495\n0x40055140 READ    2690882\n0x400B0380 WRITE   2691090\n0x40055180 READ    2691477\n0x400B03C0 WRITE   2691685\n0x400551C0 READ    2692072\n0x400B0400 WRITE   2692280\n0x40055200 READ    2692667\n0x400B0440 WRITE   2692875\n0x40055240 READ    2693262\n0x40055280 READ    2693868\n0x400B0540 WRITE   2694075\n0x400552C0 READ    2694462\n0x400B0580 WRITE   2694670\n0x40055300 READ    2695057\n0x400B05C0 WRITE   2695265\n0x40055340 READ    2695652\n0x400B0600 WRITE   2695860\n0x40055380 READ    2696247\n0x400B0640 WRITE   2696455\n0x400553C0 READ    2696842\n0x400B0680 WRITE   2697050\n0x40055400 READ    2697437\n0x400B06C0 WRITE   2697645\n0x40055440 READ    2698032\n0x400B0700 WRITE   2698240\n0x40055480 READ    2698627\n0x400B0740 WRITE   2698835\n0x400554C0 READ    2699222\n0x40055500 READ    2699830\n0x400B0840 WRITE   2700040\n0x40055540 READ    2700427\n0x400B0880 WRITE   2700635\n0x40055580 READ    2701022\n0x400B08C0 WRITE   2701230\n0x400555C0 READ    2701617\n0x400B0900 WRITE   2701825\n0x40055600 READ    2702212\n0x400B0940 WRITE   2702420\n0x40055640 READ    2702807\n0x400B0980 WRITE   2703015\n0x40055680 READ    2703402\n0x400B09C0 WRITE   2703610\n0x400556C0 READ    2703997\n0x400B0A00 WRITE   2704205\n0x40055700 READ    2704592\n0x400B0A40 WRITE   2704800\n0x40055740 READ    2705187\n0x40055780 READ    2705793\n0x400B0B40 WRITE   2706000\n0x400557C0 READ    2706387\n0x400B0B80 WRITE   2706595\n0x40055800 READ    2706982\n0x400B0BC0 WRITE   2707190\n0x40055840 READ    2707577\n0x400B0C00 WRITE   2707785\n0x40055880 READ    2708172\n0x400B0C40 WRITE   2708380\n0x400558C0 READ    2708767\n0x400B0C80 WRITE   2708975\n0x40055900 READ    2709362\n0x400B0CC0 WRITE   2709570\n0x40055940 READ    2709957\n0x400B0D00 WRITE   2710165\n0x40055980 READ    2710552\n0x400B0D40 WRITE   2710760\n0x400559C0 READ    2711147\n0x40055A00 READ    2711753\n0x400B0E40 WRITE   2711960\n0x40055A40 READ    2712347\n0x400B0E80 WRITE   2712555\n0x40055A80 READ    2712942\n0x400B0EC0 WRITE   2713150\n0x40055AC0 READ    2713537\n0x400B0F00 WRITE   2713745\n0x40055B00 READ    2714132\n0x400B0F40 WRITE   2714340\n0x40055B40 READ    2714727\n0x400B0F80 WRITE   2714935\n0x40055B80 READ    2715322\n0x400B0FC0 WRITE   2715530\n0x40055BC0 READ    2715917\n0x400B1000 WRITE   2716125\n0x40055C00 READ    2716512\n0x400B1040 WRITE   2716720\n0x40055C40 READ    2717107\n0x40055C80 READ    2717713\n0x400B1140 WRITE   2717920\n0x40055CC0 READ    2718307\n0x400B1180 WRITE   2718515\n0x40055D00 READ    2718902\n0x400B11C0 WRITE   2719110\n0x40055D40 READ    2719497\n0x400B1200 WRITE   2719705\n0x40055D80 READ    2720092\n0x400B1240 WRITE   2720300\n0x40055DC0 READ    2720687\n0x400B1280 WRITE   2720895\n0x40055E00 READ    2721282\n0x400B12C0 WRITE   2721490\n0x40055E40 READ    2721877\n0x400B1300 WRITE   2722085\n0x40055E80 READ    2722472\n0x400B1340 WRITE   2722680\n0x40055EC0 READ    2723067\n0x40055F00 READ    2723675\n0x400B1440 WRITE   2723885\n0x40055F40 READ    2724272\n0x400B1480 WRITE   2724480\n0x40055F80 READ    2724867\n0x400B14C0 WRITE   2725075\n0x40055FC0 READ    2725462\n0x400B1500 WRITE   2725670\n0x40056000 READ    2726087\n0x400B1540 WRITE   2726295\n0x40056040 READ    2726682\n0x400B1580 WRITE   2726890\n0x40056080 READ    2727277\n0x400B15C0 WRITE   2727485\n0x400560C0 READ    2727872\n0x400B1600 WRITE   2728080\n0x40056100 READ    2728467\n0x400B1640 WRITE   2728675\n0x40056140 READ    2729062\n0x40056180 READ    2729668\n0x400B1740 WRITE   2729875\n0x400561C0 READ    2730262\n0x400B1780 WRITE   2730470\n0x40056200 READ    2730857\n0x400B17C0 WRITE   2731065\n0x40056240 READ    2731452\n0x400B1800 WRITE   2731660\n0x40056280 READ    2732047\n0x400B1840 WRITE   2732255\n0x400562C0 READ    2732642\n0x400B1880 WRITE   2732850\n0x40056300 READ    2733237\n0x400B18C0 WRITE   2733445\n0x40056340 READ    2733832\n0x400B1900 WRITE   2734040\n0x40056380 READ    2734427\n0x400B1940 WRITE   2734635\n0x400563C0 READ    2735022\n0x40056400 READ    2735628\n0x400B1A40 WRITE   2735835\n0x40056440 READ    2736222\n0x400B1A80 WRITE   2736430\n0x40056480 READ    2736817\n0x400B1AC0 WRITE   2737025\n0x400564C0 READ    2737412\n0x400B1B00 WRITE   2737620\n0x40056500 READ    2738007\n0x400B1B40 WRITE   2738215\n0x40056540 READ    2738602\n0x400B1B80 WRITE   2738810\n0x40056580 READ    2739197\n0x400B1BC0 WRITE   2739405\n0x400565C0 READ    2739792\n0x400B1C00 WRITE   2740000\n0x40056600 READ    2740387\n0x400B1C40 WRITE   2740595\n0x40056640 READ    2740982\n0x40056680 READ    2741588\n0x400B1D40 WRITE   2741795\n0x400566C0 READ    2742182\n0x400B1D80 WRITE   2742390\n0x40056700 READ    2742777\n0x400B1DC0 WRITE   2742985\n0x40056740 READ    2743372\n0x400B1E00 WRITE   2743580\n0x40056780 READ    2743967\n0x400B1E40 WRITE   2744175\n0x400567C0 READ    2744562\n0x400B1E80 WRITE   2744770\n0x40056800 READ    2745157\n0x400B1EC0 WRITE   2745365\n0x40056840 READ    2745752\n0x400B1F00 WRITE   2745960\n0x40056880 READ    2746347\n0x400B1F40 WRITE   2746555\n0x400568C0 READ    2746942\n0x40056900 READ    2747550\n0x400B2040 WRITE   2747760\n0x40056940 READ    2748147\n0x400B2080 WRITE   2748355\n0x40056980 READ    2748742\n0x400B20C0 WRITE   2748950\n0x400569C0 READ    2749337\n0x400B2100 WRITE   2749545\n0x40056A00 READ    2749932\n0x400B2140 WRITE   2750140\n0x40056A40 READ    2750527\n0x400B2180 WRITE   2750735\n0x40056A80 READ    2751122\n0x400B21C0 WRITE   2751330\n0x40056AC0 READ    2751717\n0x400B2200 WRITE   2751925\n0x40056B00 READ    2752312\n0x400B2240 WRITE   2752520\n0x40056B40 READ    2752907\n0x40056B80 READ    2753513\n0x400B2340 WRITE   2753720\n0x40056BC0 READ    2754107\n0x400B2380 WRITE   2754315\n0x40056C00 READ    2754702\n0x400B23C0 WRITE   2754910\n0x40056C40 READ    2755297\n0x400B2400 WRITE   2755505\n0x40056C80 READ    2755892\n0x400B2440 WRITE   2756100\n0x40056CC0 READ    2756487\n0x400B2480 WRITE   2756695\n0x40056D00 READ    2757082\n0x400B24C0 WRITE   2757290\n0x40056D40 READ    2757677\n0x400B2500 WRITE   2757885\n0x40056D80 READ    2758272\n0x400B2540 WRITE   2758480\n0x40056DC0 READ    2758867\n0x40056E00 READ    2759473\n0x400B2640 WRITE   2759680\n0x40056E40 READ    2760067\n0x400B2680 WRITE   2760275\n0x40056E80 READ    2760662\n0x400B26C0 WRITE   2760870\n0x40056EC0 READ    2761257\n0x400B2700 WRITE   2761465\n0x40056F00 READ    2761852\n0x400B2740 WRITE   2762060\n0x40056F40 READ    2762447\n0x400B2780 WRITE   2762655\n0x40056F80 READ    2763042\n0x400B27C0 WRITE   2763250\n0x40056FC0 READ    2763637\n0x400B2800 WRITE   2763845\n0x40057000 READ    2764262\n0x400B2840 WRITE   2764470\n0x40057040 READ    2764857\n0x40057080 READ    2765463\n0x400B2940 WRITE   2765670\n0x400570C0 READ    2766057\n0x400B2980 WRITE   2766265\n0x40057100 READ    2766652\n0x400B29C0 WRITE   2766860\n0x40057140 READ    2767247\n0x400B2A00 WRITE   2767455\n0x40057180 READ    2767842\n0x400B2A40 WRITE   2768050\n0x400571C0 READ    2768437\n0x400B2A80 WRITE   2768645\n0x40057200 READ    2769032\n0x400B2AC0 WRITE   2769240\n0x40057240 READ    2769627\n0x400B2B00 WRITE   2769835\n0x40057280 READ    2770222\n0x400B2B40 WRITE   2770430\n0x400572C0 READ    2770817\n0x40057300 READ    2771425\n0x400B2C40 WRITE   2771635\n0x40057340 READ    2772022\n0x400B2C80 WRITE   2772230\n0x40057380 READ    2772617\n0x400B2CC0 WRITE   2772825\n0x400573C0 READ    2773212\n0x400B2D00 WRITE   2773420\n0x40057400 READ    2773807\n0x400B2D40 WRITE   2774015\n0x40057440 READ    2774402\n0x400B2D80 WRITE   2774610\n0x40057480 READ    2774997\n0x400B2DC0 WRITE   2775205\n0x400574C0 READ    2775592\n0x400B2E00 WRITE   2775800\n0x40057500 READ    2776187\n0x400B2E40 WRITE   2776395\n0x40057540 READ    2776782\n0x40057580 READ    2777388\n0x400B2F40 WRITE   2777595\n0x400575C0 READ    2777982\n0x400B2F80 WRITE   2778190\n0x40057600 READ    2778577\n0x400B2FC0 WRITE   2778785\n0x40057640 READ    2779172\n0x400B3000 WRITE   2779380\n0x40057680 READ    2779767\n0x400B3040 WRITE   2779975\n0x400576C0 READ    2780362\n0x400B3080 WRITE   2780570\n0x40057700 READ    2780957\n0x400B30C0 WRITE   2781165\n0x40057740 READ    2781552\n0x400B3100 WRITE   2781760\n0x40057780 READ    2782147\n0x400B3140 WRITE   2782355\n0x400577C0 READ    2782742\n0x40057800 READ    2783348\n0x400B3240 WRITE   2783555\n0x40057840 READ    2783942\n0x400B3280 WRITE   2784150\n0x40057880 READ    2784537\n0x400B32C0 WRITE   2784745\n0x400578C0 READ    2785132\n0x400B3300 WRITE   2785340\n0x40057900 READ    2785727\n0x400B3340 WRITE   2785935\n0x40057940 READ    2786322\n0x400B3380 WRITE   2786530\n0x40057980 READ    2786917\n0x400B33C0 WRITE   2787125\n0x400579C0 READ    2787512\n0x400B3400 WRITE   2787720\n0x40057A00 READ    2788107\n0x400B3440 WRITE   2788315\n0x40057A40 READ    2788702\n0x40057A80 READ    2789308\n0x400B3540 WRITE   2789515\n0x40057AC0 READ    2789902\n0x400B3580 WRITE   2790110\n0x40057B00 READ    2790497\n0x400B35C0 WRITE   2790705\n0x40057B40 READ    2791092\n0x400B3600 WRITE   2791300\n0x40057B80 READ    2791687\n0x400B3640 WRITE   2791895\n0x40057BC0 READ    2792282\n0x400B3680 WRITE   2792490\n0x40057C00 READ    2792877\n0x400B36C0 WRITE   2793085\n0x40057C40 READ    2793472\n0x400B3700 WRITE   2793680\n0x40057C80 READ    2794067\n0x400B3740 WRITE   2794275\n0x40057CC0 READ    2794662\n0x40057D00 READ    2795270\n0x400B3840 WRITE   2795480\n0x40057D40 READ    2795867\n0x400B3880 WRITE   2796075\n0x40057D80 READ    2796462\n0x400B38C0 WRITE   2796670\n0x40057DC0 READ    2797057\n0x400B3900 WRITE   2797265\n0x40057E00 READ    2797652\n0x400B3940 WRITE   2797860\n0x40057E40 READ    2798247\n0x400B3980 WRITE   2798455\n0x40057E80 READ    2798842\n0x400B39C0 WRITE   2799050\n0x40057EC0 READ    2799437\n0x400B3A00 WRITE   2799645\n0x40057F00 READ    2800032\n0x400B3A40 WRITE   2800240\n0x40057F40 READ    2800627\n0x40057F80 READ    2801233\n0x400B3B40 WRITE   2801440\n0x40057FC0 READ    2801827\n0x400B3B80 WRITE   2802035\n0x40058000 READ    2802452\n0x400B3BC0 WRITE   2802740\n0x40058040 READ    2803127\n0x400B3C00 WRITE   2803335\n0x40058080 READ    2803722\n0x400B3C40 WRITE   2803930\n0x400580C0 READ    2804317\n0x400B3C80 WRITE   2804525\n0x40058100 READ    2804912\n0x400B3CC0 WRITE   2805120\n0x40058140 READ    2805507\n0x400B3D00 WRITE   2805715\n0x40058180 READ    2806102\n0x400B3D40 WRITE   2806310\n0x400581C0 READ    2806697\n0x40058200 READ    2807303\n0x400B3E40 WRITE   2807510\n0x40058240 READ    2807897\n0x400B3E80 WRITE   2808105\n0x40058280 READ    2808492\n0x400B3EC0 WRITE   2808700\n0x400582C0 READ    2809087\n0x400B3F00 WRITE   2809295\n0x40058300 READ    2809682\n0x400B3F40 WRITE   2809890\n0x40058340 READ    2810277\n0x400B3F80 WRITE   2810485\n0x40058380 READ    2810872\n0x400B3FC0 WRITE   2811080\n0x400583C0 READ    2811467\n0x400B4000 WRITE   2811675\n0x40058400 READ    2812062\n0x400B4040 WRITE   2812270\n0x40058440 READ    2812657\n0x40058480 READ    2813263\n0x400B4140 WRITE   2813470\n0x400584C0 READ    2813857\n0x400B4180 WRITE   2814065\n0x40058500 READ    2814452\n0x400B41C0 WRITE   2814660\n0x40058540 READ    2815047\n0x400B4200 WRITE   2815255\n0x40058580 READ    2815642\n0x400B4240 WRITE   2815850\n0x400585C0 READ    2816237\n0x400B4280 WRITE   2816445\n0x40058600 READ    2816832\n0x400B42C0 WRITE   2817040\n0x40058640 READ    2817427\n0x400B4300 WRITE   2817635\n0x40058680 READ    2818022\n0x400B4340 WRITE   2818230\n0x400586C0 READ    2818617\n0x40058700 READ    2819225\n0x400B4440 WRITE   2819435\n0x40058740 READ    2819822\n0x400B4480 WRITE   2820030\n0x40058780 READ    2820417\n0x400B44C0 WRITE   2820625\n0x400587C0 READ    2821012\n0x400B4500 WRITE   2821220\n0x40058800 READ    2821607\n0x400B4540 WRITE   2821815\n0x40058840 READ    2822202\n0x400B4580 WRITE   2822410\n0x40058880 READ    2822797\n0x400B45C0 WRITE   2823005\n0x400588C0 READ    2823392\n0x400B4600 WRITE   2823600\n0x40058900 READ    2823987\n0x400B4640 WRITE   2824195\n0x40058940 READ    2824582\n0x40058980 READ    2825188\n0x400B4740 WRITE   2825395\n0x400589C0 READ    2825782\n0x400B4780 WRITE   2825990\n0x40058A00 READ    2826377\n0x400B47C0 WRITE   2826585\n0x40058A40 READ    2826972\n0x400B4800 WRITE   2827180\n0x40058A80 READ    2827567\n0x400B4840 WRITE   2827775\n0x40058AC0 READ    2828162\n0x400B4880 WRITE   2828370\n0x40058B00 READ    2828757\n0x400B48C0 WRITE   2828965\n0x40058B40 READ    2829352\n0x400B4900 WRITE   2829560\n0x40058B80 READ    2829947\n0x400B4940 WRITE   2830155\n0x40058BC0 READ    2830542\n0x40058C00 READ    2831148\n0x400B4A40 WRITE   2831355\n0x40058C40 READ    2831742\n0x400B4A80 WRITE   2831950\n0x40058C80 READ    2832337\n0x400B4AC0 WRITE   2832545\n0x40058CC0 READ    2832932\n0x400B4B00 WRITE   2833140\n0x40058D00 READ    2833527\n0x400B4B40 WRITE   2833735\n0x40058D40 READ    2834122\n0x400B4B80 WRITE   2834330\n0x40058D80 READ    2834717\n0x400B4BC0 WRITE   2834925\n0x40058DC0 READ    2835312\n0x400B4C00 WRITE   2835520\n0x40058E00 READ    2835907\n0x400B4C40 WRITE   2836115\n0x40058E40 READ    2836502\n0x40058E80 READ    2837108\n0x400B4D40 WRITE   2837315\n0x40058EC0 READ    2837702\n0x400B4D80 WRITE   2837910\n0x40058F00 READ    2838297\n0x400B4DC0 WRITE   2838505\n0x40058F40 READ    2838892\n0x400B4E00 WRITE   2839100\n0x40058F80 READ    2839487\n0x400B4E40 WRITE   2839695\n0x40058FC0 READ    2840082\n0x400B4E80 WRITE   2840290\n0x40059000 READ    2840707\n0x400B4EC0 WRITE   2840915\n0x40059040 READ    2841302\n0x400B4F00 WRITE   2841510\n0x40059080 READ    2841897\n0x400B4F40 WRITE   2842105\n0x400590C0 READ    2842492\n0x40059100 READ    2843100\n0x400B5040 WRITE   2843310\n0x40059140 READ    2843697\n0x400B5080 WRITE   2843905\n0x40059180 READ    2844292\n0x400B50C0 WRITE   2844500\n0x400591C0 READ    2844887\n0x400B5100 WRITE   2845095\n0x40059200 READ    2845482\n0x400B5140 WRITE   2845690\n0x40059240 READ    2846077\n0x400B5180 WRITE   2846285\n0x40059280 READ    2846672\n0x400B51C0 WRITE   2846880\n0x400592C0 READ    2847267\n0x400B5200 WRITE   2847475\n0x40059300 READ    2847862\n0x400B5240 WRITE   2848070\n0x40059340 READ    2848457\n0x40059380 READ    2849063\n0x400B5340 WRITE   2849270\n0x400593C0 READ    2849657\n0x400B5380 WRITE   2849865\n0x40059400 READ    2850252\n0x400B53C0 WRITE   2850460\n0x40059440 READ    2850847\n0x400B5400 WRITE   2851055\n0x40059480 READ    2851442\n0x400B5440 WRITE   2851650\n0x400594C0 READ    2852037\n0x400B5480 WRITE   2852245\n0x40059500 READ    2852632\n0x400B54C0 WRITE   2852840\n0x40059540 READ    2853227\n0x400B5500 WRITE   2853435\n0x40059580 READ    2853822\n0x400B5540 WRITE   2854030\n0x400595C0 READ    2854417\n0x40059600 READ    2855023\n0x400B5640 WRITE   2855230\n0x40059640 READ    2855617\n0x400B5680 WRITE   2855825\n0x40059680 READ    2856212\n0x400B56C0 WRITE   2856420\n0x400596C0 READ    2856807\n0x400B5700 WRITE   2857015\n0x40059700 READ    2857402\n0x400B5740 WRITE   2857610\n0x40059740 READ    2857997\n0x400B5780 WRITE   2858205\n0x40059780 READ    2858592\n0x400B57C0 WRITE   2858800\n0x400597C0 READ    2859187\n0x400B5800 WRITE   2859395\n0x40059800 READ    2859782\n0x400B5840 WRITE   2859990\n0x40059840 READ    2860377\n0x40059880 READ    2860983\n0x400B5940 WRITE   2861190\n0x400598C0 READ    2861577\n0x400B5980 WRITE   2861785\n0x40059900 READ    2862172\n0x400B59C0 WRITE   2862380\n0x40059940 READ    2862767\n0x400B5A00 WRITE   2862975\n0x40059980 READ    2863362\n0x400B5A40 WRITE   2863570\n0x400599C0 READ    2863957\n0x400B5A80 WRITE   2864165\n0x40059A00 READ    2864552\n0x400B5AC0 WRITE   2864760\n0x40059A40 READ    2865147\n0x400B5B00 WRITE   2865355\n0x40059A80 READ    2865742\n0x400B5B40 WRITE   2865950\n0x40059AC0 READ    2866337\n0x40059B00 READ    2866945\n0x400B5C40 WRITE   2867155\n0x40059B40 READ    2867542\n0x400B5C80 WRITE   2867750\n0x40059B80 READ    2868137\n0x400B5CC0 WRITE   2868345\n0x40059BC0 READ    2868732\n0x400B5D00 WRITE   2868940\n0x40059C00 READ    2869327\n0x400B5D40 WRITE   2869535\n0x40059C40 READ    2869922\n0x400B5D80 WRITE   2870130\n0x40059C80 READ    2870517\n0x400B5DC0 WRITE   2870725\n0x40059CC0 READ    2871112\n0x400B5E00 WRITE   2871320\n0x40059D00 READ    2871707\n0x400B5E40 WRITE   2871915\n0x40059D40 READ    2872302\n0x40059D80 READ    2872908\n0x400B5F40 WRITE   2873115\n0x40059DC0 READ    2873502\n0x400B5F80 WRITE   2873710\n0x40059E00 READ    2874097\n0x400B5FC0 WRITE   2874305\n0x40059E40 READ    2874692\n0x400B6000 WRITE   2874900\n0x40059E80 READ    2875287\n0x400B6040 WRITE   2875495\n0x40059EC0 READ    2875882\n0x400B6080 WRITE   2876090\n0x40059F00 READ    2876477\n0x400B60C0 WRITE   2876685\n0x40059F40 READ    2877072\n0x400B6100 WRITE   2877280\n0x40059F80 READ    2877667\n0x400B6140 WRITE   2877875\n0x40059FC0 READ    2878262\n0x4005A000 READ    2878898\n0x400B6240 WRITE   2879105\n0x4005A040 READ    2879492\n0x400B6280 WRITE   2879700\n0x4005A080 READ    2880087\n0x400B62C0 WRITE   2880295\n0x4005A0C0 READ    2880682\n0x400B6300 WRITE   2880890\n0x4005A100 READ    2881277\n0x400B6340 WRITE   2881485\n0x4005A140 READ    2881872\n0x400B6380 WRITE   2882080\n0x4005A180 READ    2882467\n0x400B63C0 WRITE   2882675\n0x4005A1C0 READ    2883062\n0x400B6400 WRITE   2883270\n0x4005A200 READ    2883657\n0x400B6440 WRITE   2883865\n0x4005A240 READ    2884252\n0x4005A280 READ    2884858\n0x400B6540 WRITE   2885065\n0x4005A2C0 READ    2885452\n0x400B6580 WRITE   2885660\n0x4005A300 READ    2886047\n0x400B65C0 WRITE   2886255\n0x4005A340 READ    2886642\n0x400B6600 WRITE   2886850\n0x4005A380 READ    2887237\n0x400B6640 WRITE   2887445\n0x4005A3C0 READ    2887832\n0x400B6680 WRITE   2888040\n0x4005A400 READ    2888427\n0x400B66C0 WRITE   2888635\n0x4005A440 READ    2889022\n0x400B6700 WRITE   2889230\n0x4005A480 READ    2889617\n0x400B6740 WRITE   2889825\n0x4005A4C0 READ    2890212\n0x4005A500 READ    2890820\n0x400B6840 WRITE   2891030\n0x4005A540 READ    2891417\n0x400B6880 WRITE   2891625\n0x4005A580 READ    2892012\n0x400B68C0 WRITE   2892220\n0x4005A5C0 READ    2892607\n0x400B6900 WRITE   2892815\n0x4005A600 READ    2893202\n0x400B6940 WRITE   2893410\n0x4005A640 READ    2893797\n0x400B6980 WRITE   2894005\n0x4005A680 READ    2894392\n0x400B69C0 WRITE   2894600\n0x4005A6C0 READ    2894987\n0x400B6A00 WRITE   2895195\n0x4005A700 READ    2895582\n0x400B6A40 WRITE   2895790\n0x4005A740 READ    2896177\n0x4005A780 READ    2896783\n0x400B6B40 WRITE   2896990\n0x4005A7C0 READ    2897377\n0x400B6B80 WRITE   2897585\n0x4005A800 READ    2897972\n0x400B6BC0 WRITE   2898180\n0x4005A840 READ    2898567\n0x400B6C00 WRITE   2898775\n0x4005A880 READ    2899162\n0x400B6C40 WRITE   2899370\n0x4005A8C0 READ    2899757\n0x400B6C80 WRITE   2899965\n0x4005A900 READ    2900352\n0x400B6CC0 WRITE   2900560\n0x4005A940 READ    2900947\n0x400B6D00 WRITE   2901155\n0x4005A980 READ    2901542\n0x400B6D40 WRITE   2901750\n0x4005A9C0 READ    2902137\n0x4005AA00 READ    2902743\n0x400B6E40 WRITE   2902950\n0x4005AA40 READ    2903337\n0x400B6E80 WRITE   2903545\n0x4005AA80 READ    2903932\n0x400B6EC0 WRITE   2904140\n0x4005AAC0 READ    2904527\n0x400B6F00 WRITE   2904735\n0x4005AB00 READ    2905122\n0x400B6F40 WRITE   2905330\n0x4005AB40 READ    2905717\n0x400B6F80 WRITE   2905925\n0x4005AB80 READ    2906312\n0x400B6FC0 WRITE   2906520\n0x4005ABC0 READ    2906907\n0x400B7000 WRITE   2907115\n0x4005AC00 READ    2907502\n0x400B7040 WRITE   2907710\n0x4005AC40 READ    2908097\n0x4005AC80 READ    2908703\n0x400B7140 WRITE   2908910\n0x4005ACC0 READ    2909297\n0x400B7180 WRITE   2909505\n0x4005AD00 READ    2909892\n0x400B71C0 WRITE   2910100\n0x4005AD40 READ    2910487\n0x400B7200 WRITE   2910695\n0x4005AD80 READ    2911082\n0x400B7240 WRITE   2911290\n0x4005ADC0 READ    2911677\n0x400B7280 WRITE   2911885\n0x4005AE00 READ    2912272\n0x400B72C0 WRITE   2912480\n0x4005AE40 READ    2912867\n0x400B7300 WRITE   2913075\n0x4005AE80 READ    2913462\n0x400B7340 WRITE   2913670\n0x4005AEC0 READ    2914057\n0x4005AF00 READ    2914665\n0x400B7440 WRITE   2914875\n0x4005AF40 READ    2915262\n0x400B7480 WRITE   2915470\n0x4005AF80 READ    2915857\n0x400B74C0 WRITE   2916065\n0x4005AFC0 READ    2916452\n0x400B7500 WRITE   2916660\n0x4005B000 READ    2917077\n0x400B7540 WRITE   2917285\n0x4005B040 READ    2917672\n0x400B7580 WRITE   2917880\n0x4005B080 READ    2918267\n0x400B75C0 WRITE   2918475\n0x4005B0C0 READ    2918862\n0x400B7600 WRITE   2919070\n0x4005B100 READ    2919457\n0x400B7640 WRITE   2919665\n0x4005B140 READ    2920052\n0x4005B180 READ    2920658\n0x400B7740 WRITE   2920865\n0x4005B1C0 READ    2921252\n0x400B7780 WRITE   2921460\n0x4005B200 READ    2921847\n0x400B77C0 WRITE   2922055\n0x4005B240 READ    2922442\n0x400B7800 WRITE   2922650\n0x4005B280 READ    2923037\n0x400B7840 WRITE   2923245\n0x4005B2C0 READ    2923632\n0x400B7880 WRITE   2923840\n0x4005B300 READ    2924227\n0x400B78C0 WRITE   2924435\n0x4005B340 READ    2924822\n0x400B7900 WRITE   2925030\n0x4005B380 READ    2925417\n0x400B7940 WRITE   2925625\n0x4005B3C0 READ    2926012\n0x4005B400 READ    2926618\n0x400B7A40 WRITE   2926825\n0x4005B440 READ    2927212\n0x400B7A80 WRITE   2927420\n0x4005B480 READ    2927807\n0x400B7AC0 WRITE   2928015\n0x4005B4C0 READ    2928402\n0x400B7B00 WRITE   2928610\n0x4005B500 READ    2928997\n0x400B7B40 WRITE   2929205\n0x4005B540 READ    2929592\n0x400B7B80 WRITE   2929800\n0x4005B580 READ    2930187\n0x400B7BC0 WRITE   2930395\n0x4005B5C0 READ    2930782\n0x400B7C00 WRITE   2930990\n0x4005B600 READ    2931377\n0x400B7C40 WRITE   2931585\n0x4005B640 READ    2931972\n0x4005B680 READ    2932578\n0x400B7D40 WRITE   2932785\n0x4005B6C0 READ    2933172\n0x400B7D80 WRITE   2933380\n0x4005B700 READ    2933767\n0x400B7DC0 WRITE   2933975\n0x4005B740 READ    2934362\n0x400B7E00 WRITE   2934570\n0x4005B780 READ    2934957\n0x400B7E40 WRITE   2935165\n0x4005B7C0 READ    2935552\n0x400B7E80 WRITE   2935760\n0x4005B800 READ    2936147\n0x400B7EC0 WRITE   2936355\n0x4005B840 READ    2936742\n0x400B7F00 WRITE   2936950\n0x4005B880 READ    2937337\n0x400B7F40 WRITE   2937545\n0x20010580 READ  2938073\n0x20011BC0 READ  2938242\n0x2000A4C0 READ    2938274\n0x20010B00 READ  2938334\n0x20011C80 READ  2938412\n0x20011CC0 READ  2938513\n0x20010B40 READ  2938597\n0x4000A000 WRITE   2938599\n0x20010B80 READ  2938707\n0x20010C00 READ  2938810\n0x20010C40 READ  2938894\n0x20010C80 READ  2939010\n0x20010CC0 READ  2939135\n0x20010D00 READ  2939243\n0x20010D40 READ  2939356\n0x2000DF00 READ  2939442\n0x40009FC0 WRITE   2939444\n0x2000DF40 READ  2939598\n0x2000DF80 READ  2939677\n0x2000DFC0 READ  2939767\n0x20000E00 READ    2939794\n0x20000E40 READ    2939795\n0x2000E000 READ  2940028\n0x2000E040 READ  2940116\n0x2000A3C0 READ    2940122\n0x400C4880 WRITE   2940697\n0x40154400 WRITE   2940892\n0x2000E080 READ  2940977\n0x2000E0C0 READ  2941097\n0x40000440 READ    2941231\n0x40000F40 READ    2941396\n0x40000940 READ    2941397\n0x40000DC0 READ    2941398\n0x400007C0 READ    2941399\n0x40000C40 READ    2941400\n0x40000AC0 READ    2941401\n0x400010C0 READ    2941402\n0x40001840 READ    2941719\n0x400016C0 READ    2941720\n0x4005D800 WRITE   2941860\n0x40001100 READ    2941861\n0x4005D7C0 WRITE   2941862\n0x4005D400 WRITE   2941945\n0x40000F80 READ    2941946\n0x4005D3C0 WRITE   2941947\n0x4005D200 WRITE   2942025\n0x40000E00 READ    2942026\n0x4005D1C0 WRITE   2942027\n0x4005D100 WRITE   2942125\n0x40000C80 READ    2942126\n0x4005D0C0 WRITE   2942128\n0x4005D080 WRITE   2942225\n0x40000B00 READ    2942226\n0x4005D040 WRITE   2942228\n0x40000980 READ    2942326\n0x40000800 READ    2942425\n0x2000E100 READ  2942528\n0x2000E140 READ  2942631\n0x400B8040 WRITE   2942786\n0x20002680 READ    2942833\n0x400B8080 WRITE   2943020\n0x400B80C0 WRITE   2943076\n0x400B8100 WRITE   2943165\n0x400B8140 WRITE   2943221\n0x400B8180 WRITE   2943284\n0x400B81C0 WRITE   2943340\n0x4005D180 WRITE   2943396\n0x4005D140 WRITE   2943398\n0x400B8200 WRITE   2943434\n0x400B8240 WRITE   2943490\n0x400B8280 WRITE   2943553\n0x400B82C0 WRITE   2943609\n0x400B8300 WRITE   2943687\n0x400B8340 WRITE   2943743\n0x400B8380 WRITE   2943806\n0x400B83C0 WRITE   2943862\n0x4005D300 WRITE   2943939\n0x4005D2C0 WRITE   2943941\n0x4005D280 WRITE   2943949\n0x4005D240 WRITE   2943951\n0x400B8400 WRITE   2943984\n0x400B8440 WRITE   2944040\n0x400B8480 WRITE   2944114\n0x400B84C0 WRITE   2944170\n0x400B8500 WRITE   2944261\n0x400B8540 WRITE   2944317\n0x400B8580 WRITE   2944388\n0x400B85C0 WRITE   2944444\n0x4005D380 WRITE   2944508\n0x4005D340 WRITE   2944510\n0x400B8600 WRITE   2944546\n0x400B8640 WRITE   2944602\n0x400B8680 WRITE   2944673\n0x400B86C0 WRITE   2944729\n0x400B8700 WRITE   2944815\n0x400B8740 WRITE   2944871\n0x400B8780 WRITE   2944942\n0x400B87C0 WRITE   2944998\n0x4005D600 WRITE   2945078\n0x4005D5C0 WRITE   2945080\n0x4005D500 WRITE   2945088\n0x4005D4C0 WRITE   2945090\n0x4005D480 WRITE   2945100\n0x4005D440 WRITE   2945102\n0x400B8800 WRITE   2945129\n0x400B8840 WRITE   2945185\n0x400B8880 WRITE   2945251\n0x400B88C0 WRITE   2945307\n0x400B8900 WRITE   2945394\n0x400B8940 WRITE   2945450\n0x400B8980 WRITE   2945513\n0x400B89C0 WRITE   2945569\n0x4005D580 WRITE   2945631\n0x4005D540 WRITE   2945633\n0x400B8A00 WRITE   2945669\n0x400B8A40 WRITE   2945725\n0x400B8A80 WRITE   2945788\n0x400B8AC0 WRITE   2945844\n0x400B8B00 WRITE   2945926\n0x400B8B40 WRITE   2945982\n0x400B8B80 WRITE   2946045\n0x400B8BC0 WRITE   2946101\n0x4005D700 WRITE   2946173\n0x4005D6C0 WRITE   2946175\n0x4005D680 WRITE   2946182\n0x4005D640 WRITE   2946184\n0x400B8C00 WRITE   2946217\n0x400B8C40 WRITE   2946273\n0x400B8C80 WRITE   2946347\n0x400B8CC0 WRITE   2946403\n0x400B8D00 WRITE   2946498\n0x400B8D40 WRITE   2946554\n0x400B8D80 WRITE   2946625\n0x400B8DC0 WRITE   2946681\n0x4005D780 WRITE   2946751\n0x4005D740 WRITE   2946753\n0x400B8E00 WRITE   2946789\n0x400B8E40 WRITE   2946845\n0x400B8E80 WRITE   2946916\n0x400B8EC0 WRITE   2946972\n0x400B8F00 WRITE   2947062\n0x400B8F40 WRITE   2947118\n0x400B8F80 WRITE   2947189\n0x400B8FC0 WRITE   2947245\n0x4005DC00 WRITE   2947331\n0x4005DBC0 WRITE   2947333\n0x4005DA00 WRITE   2947340\n0x4005D9C0 WRITE   2947342\n0x4005D900 WRITE   2947352\n0x4005D8C0 WRITE   2947354\n0x4005D880 WRITE   2947359\n0x4005D840 WRITE   2947362\n0x400B9000 WRITE   2947387\n0x400B9040 WRITE   2947471\n0x400B9080 WRITE   2947537\n0x400B90C0 WRITE   2947593\n0x400B9100 WRITE   2947676\n0x400B9140 WRITE   2947732\n0x400B9180 WRITE   2947795\n0x400B91C0 WRITE   2947851\n0x4005D980 WRITE   2947915\n0x4005D940 WRITE   2947917\n0x400B9200 WRITE   2947953\n0x400B9240 WRITE   2948009\n0x400B9280 WRITE   2948072\n0x400B92C0 WRITE   2948128\n0x400B9300 WRITE   2948206\n0x400B9340 WRITE   2948262\n0x400B9380 WRITE   2948325\n0x400B93C0 WRITE   2948381\n0x4005DB00 WRITE   2948455\n0x4005DAC0 WRITE   2948457\n0x4005DA80 WRITE   2948464\n0x4005DA40 WRITE   2948466\n0x400B9400 WRITE   2948499\n0x400B9440 WRITE   2948555\n0x400B9480 WRITE   2948629\n0x400B94C0 WRITE   2948685\n0x400B9500 WRITE   2948776\n0x400B9540 WRITE   2948832\n0x400B9580 WRITE   2948903\n0x400B95C0 WRITE   2948959\n0x4005DB80 WRITE   2949031\n0x4005DB40 WRITE   2949033\n0x400B9600 WRITE   2949069\n0x400B9640 WRITE   2949125\n0x400B9680 WRITE   2949196\n0x400B96C0 WRITE   2949252\n0x400B9700 WRITE   2949338\n0x400B9740 WRITE   2949394\n0x400B9780 WRITE   2949465\n0x400B97C0 WRITE   2949521\n0x4005DE00 WRITE   2949604\n0x4005DDC0 WRITE   2949606\n0x4005DD00 WRITE   2949613\n0x4005DCC0 WRITE   2949615\n0x4005DC80 WRITE   2949625\n0x4005DC40 WRITE   2949627\n0x400B9800 WRITE   2949654\n0x400B9840 WRITE   2949710\n0x400B9880 WRITE   2949776\n0x400B98C0 WRITE   2949832\n0x400B9900 WRITE   2949919\n0x400B9940 WRITE   2949975\n0x400B9980 WRITE   2950038\n0x400B99C0 WRITE   2950094\n0x4005DD80 WRITE   2950163\n0x4005DD40 WRITE   2950165\n0x400B9A00 WRITE   2950201\n0x400B9A40 WRITE   2950257\n0x400B9A80 WRITE   2950320\n0x400B9AC0 WRITE   2950376\n0x400B9B00 WRITE   2950458\n0x400B9B40 WRITE   2950514\n0x400B9B80 WRITE   2950577\n0x400B9BC0 WRITE   2950633\n0x4005DF00 WRITE   2950712\n0x4005DEC0 WRITE   2950714\n0x4005DE80 WRITE   2950721\n0x4005DE40 WRITE   2950723\n0x400B9C00 WRITE   2950756\n0x400B9C40 WRITE   2950812\n0x400B9C80 WRITE   2950886\n0x400B9CC0 WRITE   2950942\n0x400B9D00 WRITE   2951037\n0x400B9D40 WRITE   2951093\n0x400B9D80 WRITE   2951164\n0x400B9DC0 WRITE   2951220\n0x4005DF80 WRITE   2951297\n0x4005DF40 WRITE   2951299\n0x400B9E00 WRITE   2951335\n0x400B9E40 WRITE   2951391\n0x400B9E80 WRITE   2951462\n0x400B9EC0 WRITE   2951518\n0x400B9F00 WRITE   2951608\n0x400B9F40 WRITE   2951664\n0x400B9F80 WRITE   2951735\n0x400B9FC0 WRITE   2951791\n0x400019C0 READ    2951865\n0x40157FC0 WRITE   2951968\n0x40158000 WRITE   2952002\n0x40155FC0 WRITE   2952013\n0x40156000 WRITE   2952056\n0x40157000 WRITE   2952131\n0x40156FC0 WRITE   2952133\n0x40156800 WRITE   2952140\n0x401567C0 WRITE   2952142\n0x40156400 WRITE   2952152\n0x401563C0 WRITE   2952154\n0x40156200 WRITE   2952159\n0x401561C0 WRITE   2952162\n0x40156100 WRITE   2952165\n0x401560C0 WRITE   2952168\n0x40156080 WRITE   2952171\n0x40156040 WRITE   2952174\n0x400BA000 WRITE   2952206\n0x400BA040 WRITE   2952294\n0x400BA080 WRITE   2952360\n0x400BA0C0 WRITE   2952416\n0x400BA100 WRITE   2952499\n0x400BA140 WRITE   2952555\n0x400BA180 WRITE   2952618\n0x400BA1C0 WRITE   2952674\n0x40156180 WRITE   2952730\n0x40156140 WRITE   2952732\n0x400BA200 WRITE   2952768\n0x400BA240 WRITE   2952824\n0x400BA280 WRITE   2952887\n0x400BA2C0 WRITE   2952943\n0x400BA300 WRITE   2953021\n0x400BA340 WRITE   2953077\n0x400BA380 WRITE   2953140\n0x400BA3C0 WRITE   2953196\n0x40156300 WRITE   2953257\n0x401562C0 WRITE   2953259\n0x40156280 WRITE   2953266\n0x40156240 WRITE   2953268\n0x400BA400 WRITE   2953301\n0x400BA440 WRITE   2953357\n0x400BA480 WRITE   2953431\n0x400BA4C0 WRITE   2953487\n0x400BA500 WRITE   2953578\n0x400BA540 WRITE   2953634\n0x400BA580 WRITE   2953705\n0x400BA5C0 WRITE   2953761\n0x40156380 WRITE   2953825\n0x40156340 WRITE   2953827\n0x400BA600 WRITE   2953863\n0x400BA640 WRITE   2953919\n0x400BA680 WRITE   2953990\n0x400BA6C0 WRITE   2954046\n0x400BA700 WRITE   2954132\n0x400BA740 WRITE   2954188\n0x400BA780 WRITE   2954259\n0x400BA7C0 WRITE   2954315\n0x40156600 WRITE   2954384\n0x401565C0 WRITE   2954386\n0x40156500 WRITE   2954393\n0x401564C0 WRITE   2954395\n0x40156480 WRITE   2954405\n0x40156440 WRITE   2954407\n0x400BA800 WRITE   2954434\n0x400BA840 WRITE   2954490\n0x400BA880 WRITE   2954556\n0x400BA8C0 WRITE   2954612\n0x400BA900 WRITE   2954699\n0x400BA940 WRITE   2954755\n0x400BA980 WRITE   2954818\n0x400BA9C0 WRITE   2954874\n0x40156580 WRITE   2954936\n0x40156540 WRITE   2954938\n0x400BAA00 WRITE   2954974\n0x400BAA40 WRITE   2955030\n0x400BAA80 WRITE   2955093\n0x400BAAC0 WRITE   2955149\n0x400BAB00 WRITE   2955231\n0x400BAB40 WRITE   2955287\n0x400BAB80 WRITE   2955350\n0x400BABC0 WRITE   2955406\n0x40156700 WRITE   2955472\n0x401566C0 WRITE   2955474\n0x40156680 WRITE   2955481\n0x40156640 WRITE   2955483\n0x400BAC00 WRITE   2955516\n0x400BAC40 WRITE   2955572\n0x400BAC80 WRITE   2955646\n0x400BACC0 WRITE   2955702\n0x400BAD00 WRITE   2955797\n0x400BAD40 WRITE   2955853\n0x400BAD80 WRITE   2955924\n0x400BADC0 WRITE   2955980\n0x40156780 WRITE   2956050\n0x40156740 WRITE   2956052\n0x400BAE00 WRITE   2956088\n0x400BAE40 WRITE   2956144\n0x400BAE80 WRITE   2956215\n0x400BAEC0 WRITE   2956271\n0x400BAF00 WRITE   2956361\n0x400BAF40 WRITE   2956417\n0x400BAF80 WRITE   2956488\n0x400BAFC0 WRITE   2956544\n0x40156C00 WRITE   2956624\n0x40156BC0 WRITE   2956626\n0x40156A00 WRITE   2956633\n0x401569C0 WRITE   2956635\n0x40156900 WRITE   2956645\n0x401568C0 WRITE   2956647\n0x40156880 WRITE   2956652\n0x40156840 WRITE   2956655\n0x400BB000 WRITE   2956680\n0x400BB040 WRITE   2956764\n0x400BB080 WRITE   2956830\n0x400BB0C0 WRITE   2956886\n0x400BB100 WRITE   2956969\n0x400BB140 WRITE   2957025\n0x400BB180 WRITE   2957088\n0x400BB1C0 WRITE   2957144\n0x40156980 WRITE   2957208\n0x40156940 WRITE   2957210\n0x400BB200 WRITE   2957246\n0x400BB240 WRITE   2957302\n0x400BB280 WRITE   2957365\n0x400BB2C0 WRITE   2957421\n0x400BB300 WRITE   2957499\n0x400BB340 WRITE   2957555\n0x400BB380 WRITE   2957618\n0x400BB3C0 WRITE   2957674\n0x40156B00 WRITE   2957742\n0x40156AC0 WRITE   2957744\n0x40156A80 WRITE   2957751\n0x40156A40 WRITE   2957753\n0x400BB400 WRITE   2957786\n0x400BB440 WRITE   2957842\n0x400BB480 WRITE   2957916\n0x400BB4C0 WRITE   2957972\n0x400BB500 WRITE   2958063\n0x400BB540 WRITE   2958119\n0x400BB580 WRITE   2958190\n0x400BB5C0 WRITE   2958246\n0x40156B80 WRITE   2958318\n0x40156B40 WRITE   2958320\n0x400BB600 WRITE   2958356\n0x400BB640 WRITE   2958412\n0x400BB680 WRITE   2958483\n0x400BB6C0 WRITE   2958539\n0x400BB700 WRITE   2958625\n0x400BB740 WRITE   2958681\n0x400BB780 WRITE   2958752\n0x400BB7C0 WRITE   2958808\n0x40156E00 WRITE   2958885\n0x40156DC0 WRITE   2958887\n0x40156D00 WRITE   2958894\n0x40156CC0 WRITE   2958896\n0x40156C80 WRITE   2958906\n0x40156C40 WRITE   2958908\n0x400BB800 WRITE   2958935\n0x400BB840 WRITE   2958991\n0x400BB880 WRITE   2959057\n0x400BB8C0 WRITE   2959113\n0x400BB900 WRITE   2959200\n0x400BB940 WRITE   2959256\n0x400BB980 WRITE   2959319\n0x400BB9C0 WRITE   2959375\n0x40156D80 WRITE   2959444\n0x40156D40 WRITE   2959446\n0x400BBA00 WRITE   2959482\n0x400BBA40 WRITE   2959538\n0x400BBA80 WRITE   2959601\n0x400BBAC0 WRITE   2959657\n0x400BBB00 WRITE   2959739\n0x400BBB40 WRITE   2959795\n0x400BBB80 WRITE   2959858\n0x400BBBC0 WRITE   2959914\n0x40156F00 WRITE   2959987\n0x40156EC0 WRITE   2959989\n0x40156E80 WRITE   2959996\n0x40156E40 WRITE   2959998\n0x400BBC00 WRITE   2960031\n0x400BBC40 WRITE   2960087\n0x400BBC80 WRITE   2960161\n0x400BBCC0 WRITE   2960217\n0x400BBD00 WRITE   2960312\n0x400BBD40 WRITE   2960368\n0x400BBD80 WRITE   2960439\n0x400BBDC0 WRITE   2960495\n0x40156F80 WRITE   2960572\n0x40156F40 WRITE   2960574\n0x400BBE00 WRITE   2960610\n0x400BBE40 WRITE   2960666\n0x400BBE80 WRITE   2960737\n0x400BBEC0 WRITE   2960793\n0x400BBF00 WRITE   2960883\n0x400BBF40 WRITE   2960939\n0x400BBF80 WRITE   2961010\n0x400BBFC0 WRITE   2961066\n0x40157800 WRITE   2961152\n0x401577C0 WRITE   2961154\n0x40157400 WRITE   2961161\n0x401573C0 WRITE   2961163\n0x40157200 WRITE   2961173\n0x401571C0 WRITE   2961175\n0x40157100 WRITE   2961180\n0x401570C0 WRITE   2961183\n0x40157080 WRITE   2961186\n0x40157040 WRITE   2961189\n0x400BC000 WRITE   2961214\n0x400BC040 WRITE   2961298\n0x400BC080 WRITE   2961364\n0x400BC0C0 WRITE   2961420\n0x400BC100 WRITE   2961503\n0x400BC140 WRITE   2961559\n0x400BC180 WRITE   2961622\n0x400BC1C0 WRITE   2961678\n0x40157180 WRITE   2961734\n0x40157140 WRITE   2961736\n0x400BC200 WRITE   2961772\n0x400BC240 WRITE   2961828\n0x400BC280 WRITE   2961891\n0x400BC2C0 WRITE   2961947\n0x400BC300 WRITE   2962025\n0x400BC340 WRITE   2962081\n0x400BC380 WRITE   2962144\n0x400BC3C0 WRITE   2962200\n0x40157300 WRITE   2962266\n0x401572C0 WRITE   2962268\n0x40157280 WRITE   2962275\n0x40157240 WRITE   2962277\n0x400BC400 WRITE   2962310\n0x400BC440 WRITE   2962366\n0x400BC480 WRITE   2962440\n0x400BC4C0 WRITE   2962496\n0x400BC500 WRITE   2962587\n0x400BC540 WRITE   2962643\n0x400BC580 WRITE   2962714\n0x400BC5C0 WRITE   2962770\n0x40157380 WRITE   2962834\n0x40157340 WRITE   2962836\n0x400BC600 WRITE   2962872\n0x400BC640 WRITE   2962928\n0x400BC680 WRITE   2962999\n0x400BC6C0 WRITE   2963055\n0x400BC700 WRITE   2963141\n0x400BC740 WRITE   2963197\n0x400BC780 WRITE   2963268\n0x400BC7C0 WRITE   2963324\n0x40157600 WRITE   2963399\n0x401575C0 WRITE   2963401\n0x40157500 WRITE   2963408\n0x401574C0 WRITE   2963410\n0x40157480 WRITE   2963420\n0x40157440 WRITE   2963422\n0x400BC800 WRITE   2963449\n0x400BC840 WRITE   2963505\n0x400BC880 WRITE   2963571\n0x400BC8C0 WRITE   2963627\n0x400BC900 WRITE   2963714\n0x400BC940 WRITE   2963770\n0x400BC980 WRITE   2963833\n0x400BC9C0 WRITE   2963889\n0x40157580 WRITE   2963951\n0x40157540 WRITE   2963953\n0x400BCA00 WRITE   2963989\n0x400BCA40 WRITE   2964045\n0x400BCA80 WRITE   2964108\n0x400BCAC0 WRITE   2964164\n0x400BCB00 WRITE   2964246\n0x400BCB40 WRITE   2964302\n0x400BCB80 WRITE   2964365\n0x400BCBC0 WRITE   2964421\n0x40157700 WRITE   2964493\n0x401576C0 WRITE   2964495\n0x40157680 WRITE   2964502\n0x40157640 WRITE   2964504\n0x400BCC00 WRITE   2964537\n0x400BCC40 WRITE   2964593\n0x400BCC80 WRITE   2964667\n0x400BCCC0 WRITE   2964723\n0x400BCD00 WRITE   2964818\n0x400BCD40 WRITE   2964874\n0x400BCD80 WRITE   2964945\n0x400BCDC0 WRITE   2965001\n0x40157780 WRITE   2965071\n0x40157740 WRITE   2965073\n0x400BCE00 WRITE   2965109\n0x400BCE40 WRITE   2965165\n0x400BCE80 WRITE   2965236\n0x400BCEC0 WRITE   2965292\n0x400BCF00 WRITE   2965382\n0x400BCF40 WRITE   2965438\n0x400BCF80 WRITE   2965509\n0x400BCFC0 WRITE   2965565\n0x40157C00 WRITE   2965651\n0x40157BC0 WRITE   2965653\n0x40157A00 WRITE   2965660\n0x401579C0 WRITE   2965662\n0x40157900 WRITE   2965672\n0x401578C0 WRITE   2965674\n0x40157880 WRITE   2965679\n0x40157840 WRITE   2965682\n0x400BD000 WRITE   2965707\n0x400BD040 WRITE   2965791\n0x400BD080 WRITE   2965857\n0x400BD0C0 WRITE   2965913\n0x400BD100 WRITE   2965996\n0x400BD140 WRITE   2966052\n0x400BD180 WRITE   2966115\n0x400BD1C0 WRITE   2966171\n0x40157980 WRITE   2966235\n0x40157940 WRITE   2966237\n0x400BD200 WRITE   2966273\n0x400BD240 WRITE   2966329\n0x400BD280 WRITE   2966392\n0x400BD2C0 WRITE   2966448\n0x400BD300 WRITE   2966526\n0x400BD340 WRITE   2966582\n0x400BD380 WRITE   2966645\n0x400BD3C0 WRITE   2966701\n0x40157B00 WRITE   2966775\n0x40157AC0 WRITE   2966777\n0x40157A80 WRITE   2966784\n0x40157A40 WRITE   2966786\n0x400BD400 WRITE   2966819\n0x400BD440 WRITE   2966875\n0x400BD480 WRITE   2966949\n0x400BD4C0 WRITE   2967005\n0x400BD500 WRITE   2967096\n0x400BD540 WRITE   2967152\n0x400BD580 WRITE   2967223\n0x400BD5C0 WRITE   2967279\n0x40157B80 WRITE   2967351\n0x40157B40 WRITE   2967353\n0x400BD600 WRITE   2967389\n0x400BD640 WRITE   2967445\n0x400BD680 WRITE   2967516\n0x400BD6C0 WRITE   2967572\n0x400BD700 WRITE   2967658\n0x400BD740 WRITE   2967714\n0x400BD780 WRITE   2967785\n0x400BD7C0 WRITE   2967841\n0x40157E00 WRITE   2967924\n0x40157DC0 WRITE   2967926\n0x40157D00 WRITE   2967933\n0x40157CC0 WRITE   2967935\n0x40157C80 WRITE   2967945\n0x40157C40 WRITE   2967947\n0x400BD800 WRITE   2967974\n0x400BD840 WRITE   2968030\n0x400BD880 WRITE   2968096\n0x400BD8C0 WRITE   2968152\n0x400BD900 WRITE   2968239\n0x400BD940 WRITE   2968295\n0x400BD980 WRITE   2968358\n0x400BD9C0 WRITE   2968414\n0x40157D80 WRITE   2968483\n0x40157D40 WRITE   2968485\n0x400BDA00 WRITE   2968521\n0x400BDA40 WRITE   2968577\n0x400BDA80 WRITE   2968640\n0x400BDAC0 WRITE   2968696\n0x400BDB00 WRITE   2968778\n0x400BDB40 WRITE   2968834\n0x400BDB80 WRITE   2968897\n0x400BDBC0 WRITE   2968953\n0x40157F00 WRITE   2969032\n0x40157EC0 WRITE   2969034\n0x40157E80 WRITE   2969041\n0x40157E40 WRITE   2969043\n0x400BDC00 WRITE   2969076\n0x400BDC40 WRITE   2969132\n0x400BDC80 WRITE   2969206\n0x400BDCC0 WRITE   2969262\n0x400BDD00 WRITE   2969357\n0x400BDD40 WRITE   2969413\n0x400BDD80 WRITE   2969484\n0x400BDDC0 WRITE   2969540\n0x40157F80 WRITE   2969617\n0x40157F40 WRITE   2969619\n0x400BDE00 WRITE   2969655\n0x400BDE40 WRITE   2969711\n0x400BDE80 WRITE   2969782\n0x400BDEC0 WRITE   2969838\n0x400BDF00 WRITE   2969928\n0x400BDF40 WRITE   2969984\n0x400BDF80 WRITE   2970055\n0x400BDFC0 WRITE   2970111\n0x40159FC0 WRITE   2970273\n0x4015A000 WRITE   2970305\n0x40159000 WRITE   2970475\n0x40158FC0 WRITE   2970477\n0x40158800 WRITE   2970484\n0x401587C0 WRITE   2970486\n0x40158400 WRITE   2970496\n0x401583C0 WRITE   2970498\n0x40158200 WRITE   2970503\n0x401581C0 WRITE   2970506\n0x40158100 WRITE   2970509\n0x401580C0 WRITE   2970512\n0x40158080 WRITE   2970515\n0x40158040 WRITE   2970518\n0x400BE000 WRITE   2970550\n0x400BE040 WRITE   2970638\n0x400BE080 WRITE   2970704\n0x400BE0C0 WRITE   2970760\n0x400BE100 WRITE   2970843\n0x400BE140 WRITE   2970899\n0x400BE180 WRITE   2970962\n0x400BE1C0 WRITE   2971018\n0x40158180 WRITE   2971074\n0x40158140 WRITE   2971076\n0x400BE200 WRITE   2971112\n0x400BE240 WRITE   2971168\n0x400BE280 WRITE   2971231\n0x400BE2C0 WRITE   2971287\n0x400BE300 WRITE   2971365\n0x400BE340 WRITE   2971421\n0x400BE380 WRITE   2971484\n0x400BE3C0 WRITE   2971540\n0x40158300 WRITE   2971601\n0x401582C0 WRITE   2971603\n0x40158280 WRITE   2971610\n0x40158240 WRITE   2971612\n0x400BE400 WRITE   2971645\n0x400BE440 WRITE   2971701\n0x400BE480 WRITE   2971775\n0x400BE4C0 WRITE   2971831\n0x400BE500 WRITE   2971922\n0x400BE540 WRITE   2971978\n0x400BE580 WRITE   2972049\n0x400BE5C0 WRITE   2972105\n0x40158380 WRITE   2972169\n0x40158340 WRITE   2972171\n0x400BE600 WRITE   2972207\n0x400BE640 WRITE   2972263\n0x400BE680 WRITE   2972334\n0x400BE6C0 WRITE   2972390\n0x400BE700 WRITE   2972476\n0x400BE740 WRITE   2972532\n0x400BE780 WRITE   2972603\n0x400BE7C0 WRITE   2972659\n0x40158600 WRITE   2972728\n0x401585C0 WRITE   2972730\n0x40158500 WRITE   2972737\n0x401584C0 WRITE   2972739\n0x40158480 WRITE   2972749\n0x40158440 WRITE   2972751\n0x400BE800 WRITE   2972778\n0x400BE840 WRITE   2972834\n0x400BE880 WRITE   2972900\n0x400BE8C0 WRITE   2972956\n0x400BE900 WRITE   2973043\n0x400BE940 WRITE   2973099\n0x400BE980 WRITE   2973162\n0x400BE9C0 WRITE   2973218\n0x40158580 WRITE   2973280\n0x40158540 WRITE   2973282\n0x400BEA00 WRITE   2973318\n0x400BEA40 WRITE   2973374\n0x400BEA80 WRITE   2973437\n0x400BEAC0 WRITE   2973493\n0x400BEB00 WRITE   2973575\n0x400BEB40 WRITE   2973631\n0x400BEB80 WRITE   2973694\n0x400BEBC0 WRITE   2973750\n0x40158700 WRITE   2973816\n0x401586C0 WRITE   2973818\n0x40158680 WRITE   2973825\n0x40158640 WRITE   2973827\n0x400BEC00 WRITE   2973860\n0x400BEC40 WRITE   2973916\n0x400BEC80 WRITE   2973990\n0x400BECC0 WRITE   2974046\n0x400BED00 WRITE   2974141\n0x400BED40 WRITE   2974197\n0x400BED80 WRITE   2974268\n0x400BEDC0 WRITE   2974324\n0x40158780 WRITE   2974394\n0x40158740 WRITE   2974396\n0x400BEE00 WRITE   2974432\n0x400BEE40 WRITE   2974488\n0x400BEE80 WRITE   2974559\n0x400BEEC0 WRITE   2974615\n0x400BEF00 WRITE   2974705\n0x400BEF40 WRITE   2974761\n0x400BEF80 WRITE   2974832\n0x400BEFC0 WRITE   2974888\n0x40158C00 WRITE   2974968\n0x40158BC0 WRITE   2974970\n0x40158A00 WRITE   2974977\n0x401589C0 WRITE   2974979\n0x40158900 WRITE   2974989\n0x401588C0 WRITE   2974991\n0x40158880 WRITE   2974996\n0x40158840 WRITE   2974999\n0x400BF000 WRITE   2975024\n0x400BF040 WRITE   2975108\n0x400BF080 WRITE   2975174\n0x400BF0C0 WRITE   2975230\n0x400BF100 WRITE   2975313\n0x400BF140 WRITE   2975369\n0x400BF180 WRITE   2975432\n0x400BF1C0 WRITE   2975488\n0x40158980 WRITE   2975552\n0x40158940 WRITE   2975554\n0x400BF200 WRITE   2975590\n0x400BF240 WRITE   2975646\n0x400BF280 WRITE   2975709\n0x400BF2C0 WRITE   2975765\n0x400BF300 WRITE   2975843\n0x400BF340 WRITE   2975899\n0x400BF380 WRITE   2975962\n0x400BF3C0 WRITE   2976018\n0x40158B00 WRITE   2976086\n0x40158AC0 WRITE   2976088\n0x40158A80 WRITE   2976095\n0x40158A40 WRITE   2976097\n0x400BF400 WRITE   2976130\n0x400BF440 WRITE   2976186\n0x400BF480 WRITE   2976260\n0x400BF4C0 WRITE   2976316\n0x400BF500 WRITE   2976407\n0x400BF540 WRITE   2976463\n0x400BF580 WRITE   2976534\n0x400BF5C0 WRITE   2976590\n0x40158B80 WRITE   2976662\n0x40158B40 WRITE   2976664\n0x400BF600 WRITE   2976700\n0x400BF640 WRITE   2976756\n0x400BF680 WRITE   2976827\n0x400BF6C0 WRITE   2976883\n0x400BF700 WRITE   2976969\n0x400BF740 WRITE   2977025\n0x400BF780 WRITE   2977096\n0x400BF7C0 WRITE   2977152\n0x40158E00 WRITE   2977229\n0x40158DC0 WRITE   2977231\n0x40158D00 WRITE   2977238\n0x40158CC0 WRITE   2977240\n0x40158C80 WRITE   2977250\n0x40158C40 WRITE   2977252\n0x400BF800 WRITE   2977279\n0x400BF840 WRITE   2977335\n0x400BF880 WRITE   2977401\n0x400BF8C0 WRITE   2977457\n0x400BF900 WRITE   2977544\n0x400BF940 WRITE   2977600\n0x400BF980 WRITE   2977663\n0x400BF9C0 WRITE   2977719\n0x40158D80 WRITE   2977788\n0x40158D40 WRITE   2977790\n0x400BFA00 WRITE   2977826\n0x400BFA40 WRITE   2977882\n0x400BFA80 WRITE   2977945\n0x400BFAC0 WRITE   2978001\n0x400BFB00 WRITE   2978083\n0x400BFB40 WRITE   2978139\n0x400BFB80 WRITE   2978202\n0x400BFBC0 WRITE   2978258\n0x40158F00 WRITE   2978331\n0x40158EC0 WRITE   2978333\n0x40158E80 WRITE   2978340\n0x40158E40 WRITE   2978342\n0x400BFC00 WRITE   2978375\n0x400BFC40 WRITE   2978431\n0x400BFC80 WRITE   2978505\n0x400BFCC0 WRITE   2978561\n0x400BFD00 WRITE   2978656\n0x400BFD40 WRITE   2978712\n0x400BFD80 WRITE   2978783\n0x400BFDC0 WRITE   2978839\n0x40158F80 WRITE   2978916\n0x40158F40 WRITE   2978918\n0x400BFE00 WRITE   2978954\n0x400BFE40 WRITE   2979010\n0x400BFE80 WRITE   2979081\n0x400BFEC0 WRITE   2979137\n0x400BFF00 WRITE   2979227\n0x400BFF40 WRITE   2979283\n0x400BFF80 WRITE   2979354\n0x400BFFC0 WRITE   2979410\n0x40159800 WRITE   2979496\n0x401597C0 WRITE   2979498\n0x40159400 WRITE   2979505\n0x401593C0 WRITE   2979507\n0x40159200 WRITE   2979517\n0x401591C0 WRITE   2979519\n0x40159100 WRITE   2979524\n0x401590C0 WRITE   2979527\n0x40159080 WRITE   2979530\n0x40159040 WRITE   2979533\n0x400C0000 WRITE   2979558\n0x400C0040 WRITE   2979642\n0x400C0080 WRITE   2979708\n0x400C00C0 WRITE   2979764\n0x400C0100 WRITE   2979847\n0x400C0140 WRITE   2979903\n0x400C0180 WRITE   2979966\n0x400C01C0 WRITE   2980022\n0x40159180 WRITE   2980078\n0x40159140 WRITE   2980080\n0x400C0200 WRITE   2980116\n0x400C0240 WRITE   2980172\n0x400C0280 WRITE   2980235\n0x400C02C0 WRITE   2980291\n0x400C0300 WRITE   2980369\n0x400C0340 WRITE   2980425\n0x400C0380 WRITE   2980488\n0x400C03C0 WRITE   2980544\n0x40159300 WRITE   2980610\n0x401592C0 WRITE   2980612\n0x40159280 WRITE   2980619\n0x40159240 WRITE   2980621\n0x400C0400 WRITE   2980654\n0x400C0440 WRITE   2980710\n0x400C0480 WRITE   2980784\n0x400C04C0 WRITE   2980840\n0x400C0500 WRITE   2980931\n0x400C0540 WRITE   2980987\n0x400C0580 WRITE   2981058\n0x400C05C0 WRITE   2981114\n0x40159380 WRITE   2981178\n0x40159340 WRITE   2981180\n0x400C0600 WRITE   2981216\n0x400C0640 WRITE   2981272\n0x400C0680 WRITE   2981343\n0x400C06C0 WRITE   2981399\n0x400C0700 WRITE   2981485\n0x400C0740 WRITE   2981541\n0x400C0780 WRITE   2981612\n0x400C07C0 WRITE   2981668\n0x40159600 WRITE   2981743\n0x401595C0 WRITE   2981745\n0x40159500 WRITE   2981752\n0x401594C0 WRITE   2981754\n0x40159480 WRITE   2981764\n0x40159440 WRITE   2981766\n0x400C0800 WRITE   2981793\n0x400C0840 WRITE   2981849\n0x400C0880 WRITE   2981915\n0x400C08C0 WRITE   2981971\n0x400C0900 WRITE   2982058\n0x400C0940 WRITE   2982114\n0x400C0980 WRITE   2982177\n0x400C09C0 WRITE   2982233\n0x40159580 WRITE   2982295\n0x40159540 WRITE   2982297\n0x400C0A00 WRITE   2982333\n0x400C0A40 WRITE   2982389\n0x400C0A80 WRITE   2982452\n0x400C0AC0 WRITE   2982508\n0x400C0B00 WRITE   2982590\n0x400C0B40 WRITE   2982646\n0x400C0B80 WRITE   2982709\n0x400C0BC0 WRITE   2982765\n0x40159700 WRITE   2982837\n0x401596C0 WRITE   2982839\n0x40159680 WRITE   2982846\n0x40159640 WRITE   2982848\n0x400C0C00 WRITE   2982881\n0x400C0C40 WRITE   2982937\n0x400C0C80 WRITE   2983011\n0x400C0CC0 WRITE   2983067\n0x400C0D00 WRITE   2983162\n0x400C0D40 WRITE   2983218\n0x400C0D80 WRITE   2983289\n0x400C0DC0 WRITE   2983345\n0x40159780 WRITE   2983415\n0x40159740 WRITE   2983417\n0x400C0E00 WRITE   2983453\n0x400C0E40 WRITE   2983509\n0x400C0E80 WRITE   2983580\n0x400C0EC0 WRITE   2983636\n0x400C0F00 WRITE   2983726\n0x400C0F40 WRITE   2983782\n0x400C0F80 WRITE   2983853\n0x400C0FC0 WRITE   2983909\n0x40159C00 WRITE   2983995\n0x40159BC0 WRITE   2983997\n0x40159A00 WRITE   2984004\n0x401599C0 WRITE   2984006\n0x40159900 WRITE   2984016\n0x401598C0 WRITE   2984018\n0x40159880 WRITE   2984023\n0x40159840 WRITE   2984026\n0x400C1000 WRITE   2984051\n0x400C1040 WRITE   2984135\n0x400C1080 WRITE   2984201\n0x400C10C0 WRITE   2984257\n0x400C1100 WRITE   2984340\n0x400C1140 WRITE   2984396\n0x400C1180 WRITE   2984459\n0x400C11C0 WRITE   2984515\n0x40159980 WRITE   2984579\n0x40159940 WRITE   2984581\n0x400C1200 WRITE   2984617\n0x400C1240 WRITE   2984673\n0x400C1280 WRITE   2984736\n0x400C12C0 WRITE   2984792\n0x400C1300 WRITE   2984870\n0x400C1340 WRITE   2984926\n0x400C1380 WRITE   2984989\n0x400C13C0 WRITE   2985045\n0x40159B00 WRITE   2985119\n0x40159AC0 WRITE   2985121\n0x40159A80 WRITE   2985128\n0x40159A40 WRITE   2985130\n0x400C1400 WRITE   2985163\n0x400C1440 WRITE   2985219\n0x400C1480 WRITE   2985293\n0x400C14C0 WRITE   2985349\n0x400C1500 WRITE   2985440\n0x400C1540 WRITE   2985496\n0x400C1580 WRITE   2985567\n0x400C15C0 WRITE   2985623\n0x40159B80 WRITE   2985695\n0x40159B40 WRITE   2985697\n0x400C1600 WRITE   2985733\n0x400C1640 WRITE   2985789\n0x400C1680 WRITE   2985860\n0x400C16C0 WRITE   2985916\n0x400C1700 WRITE   2986002\n0x400C1740 WRITE   2986058\n0x400C1780 WRITE   2986129\n0x400C17C0 WRITE   2986185\n0x40159E00 WRITE   2986268\n0x40159DC0 WRITE   2986270\n0x40159D00 WRITE   2986277\n0x40159CC0 WRITE   2986279\n0x40159C80 WRITE   2986289\n0x40159C40 WRITE   2986291\n0x400C1800 WRITE   2986318\n0x400C1840 WRITE   2986374\n0x400C1880 WRITE   2986440\n0x400C18C0 WRITE   2986496\n0x400C1900 WRITE   2986583\n0x400C1940 WRITE   2986639\n0x400C1980 WRITE   2986702\n0x400C19C0 WRITE   2986758\n0x40159D80 WRITE   2986827\n0x40159D40 WRITE   2986829\n0x400C1A00 WRITE   2986865\n0x400C1A40 WRITE   2986921\n0x400C1A80 WRITE   2986984\n0x400C1AC0 WRITE   2987040\n0x400C1B00 WRITE   2987122\n0x400C1B40 WRITE   2987178\n0x400C1B80 WRITE   2987241\n0x400C1BC0 WRITE   2987297\n0x40159F00 WRITE   2987376\n0x40159EC0 WRITE   2987378\n0x40159E80 WRITE   2987385\n0x40159E40 WRITE   2987387\n0x400C1C00 WRITE   2987420\n0x400C1C40 WRITE   2987476\n0x400C1C80 WRITE   2987550\n0x400C1CC0 WRITE   2987606\n0x400C1D00 WRITE   2987701\n0x400C1D40 WRITE   2987757\n0x400C1D80 WRITE   2987828\n0x400C1DC0 WRITE   2987884\n0x40159F80 WRITE   2987961\n0x40159F40 WRITE   2987963\n0x400C1E00 WRITE   2987999\n0x400C1E40 WRITE   2988055\n0x400C1E80 WRITE   2988126\n0x400C1EC0 WRITE   2988182\n0x400C1F00 WRITE   2988272\n0x400C1F40 WRITE   2988328\n0x400C1F80 WRITE   2988399\n0x400C1FC0 WRITE   2988455\n0x4015BFC0 WRITE   2988617\n0x4015C000 WRITE   2988649\n0x4015B000 WRITE   2988776\n0x4015AFC0 WRITE   2988778\n0x4015A800 WRITE   2988785\n0x4015A7C0 WRITE   2988787\n0x4015A400 WRITE   2988797\n0x4015A3C0 WRITE   2988799\n0x4015A200 WRITE   2988804\n0x4015A1C0 WRITE   2988807\n0x4015A100 WRITE   2988810\n0x4015A0C0 WRITE   2988813\n0x4015A080 WRITE   2988816\n0x4015A040 WRITE   2988819\n0x400C2000 WRITE   2988851\n0x400C2040 WRITE   2988939\n0x400C2080 WRITE   2989005\n0x400C20C0 WRITE   2989061\n0x400C2100 WRITE   2989144\n0x400C2140 WRITE   2989200\n0x400C2180 WRITE   2989263\n0x400C21C0 WRITE   2989319\n0x4015A180 WRITE   2989375\n0x4015A140 WRITE   2989377\n0x400C2200 WRITE   2989413\n0x400C2240 WRITE   2989469\n0x400C2280 WRITE   2989532\n0x400C22C0 WRITE   2989588\n0x400C2300 WRITE   2989666\n0x400C2340 WRITE   2989722\n0x400C2380 WRITE   2989785\n0x400C23C0 WRITE   2989841\n0x4015A300 WRITE   2989902\n0x4015A2C0 WRITE   2989904\n0x4015A280 WRITE   2989911\n0x4015A240 WRITE   2989913\n0x400C2400 WRITE   2989946\n0x400C2440 WRITE   2990002\n0x400C2480 WRITE   2990076\n0x400C24C0 WRITE   2990132\n0x400C2500 WRITE   2990223\n0x400C2540 WRITE   2990279\n0x400C2580 WRITE   2990350\n0x400C25C0 WRITE   2990406\n0x4015A380 WRITE   2990470\n0x4015A340 WRITE   2990472\n0x400C2600 WRITE   2990508\n0x400C2640 WRITE   2990564\n0x400C2680 WRITE   2990635\n0x400C26C0 WRITE   2990691\n0x400C2700 WRITE   2990777\n0x400C2740 WRITE   2990833\n0x400C2780 WRITE   2990904\n0x400C27C0 WRITE   2990960\n0x4015A600 WRITE   2991029\n0x4015A5C0 WRITE   2991031\n0x4015A500 WRITE   2991038\n0x4015A4C0 WRITE   2991040\n0x4015A480 WRITE   2991050\n0x4015A440 WRITE   2991052\n0x400C2800 WRITE   2991079\n0x400C2840 WRITE   2991135\n0x400C2880 WRITE   2991201\n0x400C28C0 WRITE   2991257\n0x400C2900 WRITE   2991344\n0x400C2940 WRITE   2991400\n0x400C2980 WRITE   2991463\n0x400C29C0 WRITE   2991519\n0x4015A580 WRITE   2991581\n0x4015A540 WRITE   2991583\n0x400C2A00 WRITE   2991619\n0x400C2A40 WRITE   2991675\n0x400C2A80 WRITE   2991738\n0x400C2AC0 WRITE   2991794\n0x400C2B00 WRITE   2991876\n0x400C2B40 WRITE   2991932\n0x400C2B80 WRITE   2991995\n0x400C2BC0 WRITE   2992051\n0x4015A700 WRITE   2992117\n0x4015A6C0 WRITE   2992119\n0x4015A680 WRITE   2992126\n0x4015A640 WRITE   2992128\n0x400C2C00 WRITE   2992161\n0x400C2C40 WRITE   2992217\n0x400C2C80 WRITE   2992291\n0x400C2CC0 WRITE   2992347\n0x400C2D00 WRITE   2992442\n0x400C2D40 WRITE   2992498\n0x400C2D80 WRITE   2992569\n0x400C2DC0 WRITE   2992625\n0x4015A780 WRITE   2992695\n0x4015A740 WRITE   2992697\n0x400C2E00 WRITE   2992733\n0x400C2E40 WRITE   2992789\n0x400C2E80 WRITE   2992860\n0x400C2EC0 WRITE   2992916\n0x400C2F00 WRITE   2993006\n0x400C2F40 WRITE   2993062\n0x400C2F80 WRITE   2993133\n0x400C2FC0 WRITE   2993189\n0x4015AC00 WRITE   2993269\n0x4015ABC0 WRITE   2993271\n0x4015AA00 WRITE   2993278\n0x4015A9C0 WRITE   2993280\n0x4015A900 WRITE   2993290\n0x4015A8C0 WRITE   2993292\n0x4015A880 WRITE   2993297\n0x4015A840 WRITE   2993300\n0x400C3000 WRITE   2993325\n0x400C3040 WRITE   2993409\n0x400C3080 WRITE   2993475\n0x400C30C0 WRITE   2993531\n0x400C3100 WRITE   2993614\n0x400C3140 WRITE   2993670\n0x400C3180 WRITE   2993733\n0x400C31C0 WRITE   2993789\n0x4015A980 WRITE   2993853\n0x4015A940 WRITE   2993855\n0x400C3200 WRITE   2993891\n0x400C3240 WRITE   2993947\n0x400C3280 WRITE   2994010\n0x400C32C0 WRITE   2994066\n0x400C3300 WRITE   2994144\n0x400C3340 WRITE   2994200\n0x400C3380 WRITE   2994263\n0x400C33C0 WRITE   2994319\n0x4015AB00 WRITE   2994387\n0x4015AAC0 WRITE   2994389\n0x4015AA80 WRITE   2994396\n0x4015AA40 WRITE   2994398\n0x400C3400 WRITE   2994431\n0x400C3440 WRITE   2994487\n0x400C3480 WRITE   2994561\n0x400C34C0 WRITE   2994617\n0x400C3500 WRITE   2994708\n0x400C3540 WRITE   2994764\n0x400C3580 WRITE   2994835\n0x400C35C0 WRITE   2994891\n0x4015AB80 WRITE   2994963\n0x4015AB40 WRITE   2994965\n0x400C3600 WRITE   2995001\n0x400C3640 WRITE   2995057\n0x400C3680 WRITE   2995128\n0x400C36C0 WRITE   2995184\n0x400C3700 WRITE   2995270\n0x400C3740 WRITE   2995326\n0x400C3780 WRITE   2995397\n0x400C37C0 WRITE   2995453\n0x4015AE00 WRITE   2995530\n0x4015ADC0 WRITE   2995532\n0x4015AD00 WRITE   2995539\n0x4015ACC0 WRITE   2995541\n0x4015AC80 WRITE   2995551\n0x4015AC40 WRITE   2995553\n0x400C3800 WRITE   2995580\n0x400C3840 WRITE   2995636\n0x400C3880 WRITE   2995702\n0x400C38C0 WRITE   2995758\n0x400C3900 WRITE   2995845\n0x400C3940 WRITE   2995901\n0x400C3980 WRITE   2995964\n0x400C39C0 WRITE   2996020\n0x4015AD80 WRITE   2996089\n0x4015AD40 WRITE   2996091\n0x400C3A00 WRITE   2996127\n0x400C3A40 WRITE   2996183\n0x400C3A80 WRITE   2996246\n0x400C3AC0 WRITE   2996302\n0x400C3B00 WRITE   2996384\n0x400C3B40 WRITE   2996440\n0x400C3B80 WRITE   2996503\n0x400C3BC0 WRITE   2996559\n0x4015AF00 WRITE   2996632\n0x4015AEC0 WRITE   2996634\n0x4015AE80 WRITE   2996641\n0x4015AE40 WRITE   2996643\n0x400C3C00 WRITE   2996676\n0x400C3C40 WRITE   2996732\n0x400C3C80 WRITE   2996806\n0x400C3CC0 WRITE   2996862\n0x400C3D00 WRITE   2996957\n0x400C3D40 WRITE   2997013\n0x400C3D80 WRITE   2997084\n0x400C3DC0 WRITE   2997140\n0x4015AF80 WRITE   2997217\n0x4015AF40 WRITE   2997219\n0x400C3E00 WRITE   2997255\n0x400C3E40 WRITE   2997311\n0x400C3E80 WRITE   2997382\n0x400C3EC0 WRITE   2997438\n0x400C3F00 WRITE   2997528\n0x400C3F40 WRITE   2997584\n0x400C3F80 WRITE   2997655\n0x400C3FC0 WRITE   2997711\n0x4015B800 WRITE   2997797\n0x4015B7C0 WRITE   2997799\n0x4015B400 WRITE   2997806\n0x4015B3C0 WRITE   2997808\n0x4015B200 WRITE   2997818\n0x4015B1C0 WRITE   2997820\n0x4015B100 WRITE   2997825\n0x4015B0C0 WRITE   2997828\n0x4015B080 WRITE   2997831\n0x4015B040 WRITE   2997834\n0x400C4000 WRITE   2997859\n0x400C4040 WRITE   2997915\n0x400C4080 WRITE   2997981\n0x400C40C0 WRITE   2998037\n0x400C4100 WRITE   2998120\n0x400C4140 WRITE   2998176\n0x400C4180 WRITE   2998239\n0x400C41C0 WRITE   2998295\n0x4015B180 WRITE   2998351\n0x4015B140 WRITE   2998353\n0x400C4200 WRITE   2998389\n0x400C4240 WRITE   2998445\n0x400C4280 WRITE   2998508\n0x400C42C0 WRITE   2998564\n0x400C4300 WRITE   2998642\n0x400C4340 WRITE   2998698\n0x400C4380 WRITE   2998761\n0x400C43C0 WRITE   2998817\n0x4015B300 WRITE   2998883\n0x4015B2C0 WRITE   2998885\n0x4015B280 WRITE   2998892\n0x4015B240 WRITE   2998894\n0x400C4400 WRITE   2998927\n0x400C4440 WRITE   2998983\n0x400C4480 WRITE   2999057\n0x400C44C0 WRITE   2999113\n0x400C4500 WRITE   2999204\n0x400C4540 WRITE   2999260\n0x400C4580 WRITE   2999331\n0x400C45C0 WRITE   2999387\n0x4015B380 WRITE   2999451\n0x4015B340 WRITE   2999453\n0x400C4600 WRITE   2999489\n0x400C4640 WRITE   2999545\n0x400C4680 WRITE   2999616\n0x400C46C0 WRITE   2999672\n0x400C4700 WRITE   2999758\n0x400C4740 WRITE   2999814\n0x400C4780 WRITE   2999885\n0x400C47C0 WRITE   2999941\n0x4015B600 WRITE   3000016\n0x4015B5C0 WRITE   3000018\n0x4015B500 WRITE   3000025\n0x4015B4C0 WRITE   3000027\n0x4015B480 WRITE   3000037\n0x4015B440 WRITE   3000039\n0x400C4800 WRITE   3000066\n0x400C4840 WRITE   3000122\n0x400C48C0 WRITE   3000247\n0x400C4900 WRITE   3000334\n0x400C4940 WRITE   3000390\n0x400C4980 WRITE   3000453\n0x400C49C0 WRITE   3000509\n0x4015B580 WRITE   3000571\n0x4015B540 WRITE   3000573\n0x400C4A00 WRITE   3000609\n0x400C4A40 WRITE   3000665\n0x400C4A80 WRITE   3000728\n0x400C4AC0 WRITE   3000784\n0x400C4B00 WRITE   3000866\n0x400C4B40 WRITE   3000922\n0x400C4B80 WRITE   3000985\n0x400C4BC0 WRITE   3001041\n0x4015B700 WRITE   3001113\n0x4015B6C0 WRITE   3001115\n0x4015B680 WRITE   3001122\n0x4015B640 WRITE   3001124\n0x400C4C00 WRITE   3001157\n0x400C4C40 WRITE   3001213\n0x400C4C80 WRITE   3001287\n0x400C4CC0 WRITE   3001343\n0x400C4D00 WRITE   3001438\n0x400C4D40 WRITE   3001494\n0x400C4D80 WRITE   3001565\n0x400C4DC0 WRITE   3001621\n0x4015B780 WRITE   3001691\n0x4015B740 WRITE   3001693\n0x400C4E00 WRITE   3001729\n0x400C4E40 WRITE   3001785\n0x400C4E80 WRITE   3001856\n0x400C4EC0 WRITE   3001912\n0x400C4F00 WRITE   3002002\n0x400C4F40 WRITE   3002058\n0x400C4F80 WRITE   3002129\n0x400C4FC0 WRITE   3002185\n0x4015BC00 WRITE   3002271\n0x4015BBC0 WRITE   3002273\n0x4015BA00 WRITE   3002280\n0x4015B9C0 WRITE   3002282\n0x4015B900 WRITE   3002292\n0x4015B8C0 WRITE   3002294\n0x4015B880 WRITE   3002299\n0x4015B840 WRITE   3002302\n0x400C5000 WRITE   3002327\n0x400C5040 WRITE   3002411\n0x400C5080 WRITE   3002477\n0x400C50C0 WRITE   3002533\n0x400C5100 WRITE   3002616\n0x400C5140 WRITE   3002672\n0x400C5180 WRITE   3002735\n0x400C51C0 WRITE   3002791\n0x4015B980 WRITE   3002855\n0x4015B940 WRITE   3002857\n0x400C5200 WRITE   3002893\n0x400C5240 WRITE   3002949\n0x400C5280 WRITE   3003012\n0x400C52C0 WRITE   3003068\n0x400C5300 WRITE   3003146\n0x400C5340 WRITE   3003202\n0x400C5380 WRITE   3003265\n0x400C53C0 WRITE   3003321\n0x4015BB00 WRITE   3003395\n0x4015BAC0 WRITE   3003397\n0x4015BA80 WRITE   3003404\n0x4015BA40 WRITE   3003406\n0x400C5400 WRITE   3003439\n0x400C5440 WRITE   3003495\n0x400C5480 WRITE   3003569\n0x400C54C0 WRITE   3003625\n0x400C5500 WRITE   3003716\n0x400C5540 WRITE   3003772\n0x400C5580 WRITE   3003843\n0x400C55C0 WRITE   3003899\n0x4015BB80 WRITE   3003971\n0x4015BB40 WRITE   3003973\n0x400C5600 WRITE   3004009\n0x400C5640 WRITE   3004065\n0x400C5680 WRITE   3004136\n0x400C56C0 WRITE   3004192\n0x400C5700 WRITE   3004278\n0x400C5740 WRITE   3004334\n0x400C5780 WRITE   3004405\n0x400C57C0 WRITE   3004461\n0x4015BE00 WRITE   3004544\n0x4015BDC0 WRITE   3004546\n0x4015BD00 WRITE   3004553\n0x4015BCC0 WRITE   3004555\n0x4015BC80 WRITE   3004565\n0x4015BC40 WRITE   3004567\n0x400C5800 WRITE   3004594\n0x400C5840 WRITE   3004650\n0x400C5880 WRITE   3004716\n0x400C58C0 WRITE   3004772\n0x400C5900 WRITE   3004859\n0x400C5940 WRITE   3004915\n0x400C5980 WRITE   3004978\n0x400C59C0 WRITE   3005034\n0x4015BD80 WRITE   3005103\n0x4015BD40 WRITE   3005105\n0x400C5A00 WRITE   3005141\n0x400C5A40 WRITE   3005197\n0x400C5A80 WRITE   3005260\n0x400C5AC0 WRITE   3005316\n0x400C5B00 WRITE   3005398\n0x400C5B40 WRITE   3005454\n0x400C5B80 WRITE   3005517\n0x400C5BC0 WRITE   3005573\n0x4015BF00 WRITE   3005652\n0x4015BEC0 WRITE   3005654\n0x4015BE80 WRITE   3005661\n0x4015BE40 WRITE   3005663\n0x400C5C00 WRITE   3005696\n0x400C5C40 WRITE   3005752\n0x400C5C80 WRITE   3005826\n0x400C5CC0 WRITE   3005882\n0x400C5D00 WRITE   3005977\n0x400C5D40 WRITE   3006033\n0x400C5D80 WRITE   3006104\n0x400C5DC0 WRITE   3006160\n0x4015BF80 WRITE   3006237\n0x4015BF40 WRITE   3006239\n0x400C5E00 WRITE   3006275\n0x400C5E40 WRITE   3006331\n0x400C5E80 WRITE   3006402\n0x400C5EC0 WRITE   3006458\n0x400C5F00 WRITE   3006548\n0x400C5F40 WRITE   3006604\n0x400C5F80 WRITE   3006675\n0x400C5FC0 WRITE   3006731\n0x4015DFC0 WRITE   3006893\n0x4015E000 WRITE   3006925\n0x40154C00 READ    3007026\n0x40154440 WRITE   3007082\n0x40154480 WRITE   3007106\n0x401544C0 WRITE   3007130\n0x40154500 WRITE   3007154\n0x40154540 WRITE   3007178\n0x40154580 WRITE   3007202\n0x401545C0 WRITE   3007226\n0x40154600 WRITE   3007250\n0x40154640 WRITE   3007274\n0x40154680 WRITE   3007298\n0x401546C0 WRITE   3007322\n0x40154700 WRITE   3007346\n0x40154740 WRITE   3007370\n0x40154780 WRITE   3007394\n0x401547C0 WRITE   3007418\n0x40154800 WRITE   3007442\n0x40154840 WRITE   3007466\n0x40154880 WRITE   3007490\n0x401548C0 WRITE   3007514\n0x40154900 WRITE   3007538\n0x40154940 WRITE   3007562\n0x40154980 WRITE   3007586\n0x401549C0 WRITE   3007610\n0x40154A00 WRITE   3007634\n0x40154A40 WRITE   3007658\n0x40154A80 WRITE   3007682\n0x40154AC0 WRITE   3007706\n0x40154B00 WRITE   3007730\n0x40154B40 WRITE   3007754\n0x40154B80 WRITE   3007782\n0x40154BC0 WRITE   3007822\n0x200191C0 READ  3010248\n0x20019200 READ  3010408\n0x4015D000 WRITE   3010715\n0x4015CFC0 WRITE   3010717\n0x4015C800 WRITE   3010724\n0x4015C7C0 WRITE   3010726\n0x4015C400 WRITE   3010736\n0x4015C3C0 WRITE   3010738\n0x4015C200 WRITE   3010743\n0x4015C1C0 WRITE   3010746\n0x4015C100 WRITE   3010754\n0x4015C0C0 WRITE   3010757\n0x4015C080 WRITE   3010760\n0x4015C040 WRITE   3010762\n0x400C6000 WRITE   3010794\n0x400C6040 WRITE   3010882\n0x400C6080 WRITE   3010948\n0x400C60C0 WRITE   3011004\n0x400C6100 WRITE   3011087\n0x400C6140 WRITE   3011143\n0x400C6180 WRITE   3011206\n0x400C61C0 WRITE   3011262\n0x4015C180 WRITE   3011318\n0x4015C140 WRITE   3011320\n0x400C6200 WRITE   3011356\n0x400C6240 WRITE   3011412\n0x400C6280 WRITE   3011475\n0x400C62C0 WRITE   3011531\n0x400C6300 WRITE   3011609\n0x400C6340 WRITE   3011665\n0x400C6380 WRITE   3011728\n0x400C63C0 WRITE   3011784\n0x4015C300 WRITE   3011845\n0x4015C2C0 WRITE   3011847\n0x4015C280 WRITE   3011854\n0x4015C240 WRITE   3011856\n0x400C6400 WRITE   3011889\n0x400C6440 WRITE   3011945\n0x400C6480 WRITE   3012019\n0x400C64C0 WRITE   3012075\n0x400C6500 WRITE   3012166\n0x400C6540 WRITE   3012222\n0x400C6580 WRITE   3012293\n0x400C65C0 WRITE   3012349\n0x4015C380 WRITE   3012413\n0x4015C340 WRITE   3012415\n0x400C6600 WRITE   3012451\n0x400C6640 WRITE   3012507\n0x400C6680 WRITE   3012578\n0x400C66C0 WRITE   3012634\n0x400C6700 WRITE   3012720\n0x400C6740 WRITE   3012776\n0x400C6780 WRITE   3012847\n0x400C67C0 WRITE   3012903\n0x4015C600 WRITE   3012972\n0x4015C5C0 WRITE   3012974\n0x4015C500 WRITE   3012981\n0x4015C4C0 WRITE   3012983\n0x4015C480 WRITE   3012993\n0x4015C440 WRITE   3012995\n0x400C6800 WRITE   3013022\n0x400C6840 WRITE   3013078\n0x400C6880 WRITE   3013144\n0x400C68C0 WRITE   3013200\n0x400C6900 WRITE   3013287\n0x400C6940 WRITE   3013343\n0x400C6980 WRITE   3013406\n0x400C69C0 WRITE   3013462\n0x4015C580 WRITE   3013524\n0x4015C540 WRITE   3013526\n0x400C6A00 WRITE   3013562\n0x400C6A40 WRITE   3013618\n0x400C6A80 WRITE   3013681\n0x400C6AC0 WRITE   3013737\n0x400C6B00 WRITE   3013819\n0x400C6B40 WRITE   3013875\n0x400C6B80 WRITE   3013938\n0x400C6BC0 WRITE   3013994\n0x4015C700 WRITE   3014060\n0x4015C6C0 WRITE   3014062\n0x4015C680 WRITE   3014069\n0x4015C640 WRITE   3014071\n0x400C6C00 WRITE   3014104\n0x400C6C40 WRITE   3014160\n0x400C6C80 WRITE   3014234\n0x400C6CC0 WRITE   3014290\n0x400C6D00 WRITE   3014385\n0x400C6D40 WRITE   3014441\n0x400C6D80 WRITE   3014512\n0x400C6DC0 WRITE   3014568\n0x4015C780 WRITE   3014638\n0x4015C740 WRITE   3014640\n0x400C6E00 WRITE   3014676\n0x400C6E40 WRITE   3014732\n0x400C6E80 WRITE   3014803\n0x400C6EC0 WRITE   3014859\n0x400C6F00 WRITE   3014949\n0x400C6F40 WRITE   3015005\n0x400C6F80 WRITE   3015076\n0x400C6FC0 WRITE   3015132\n0x4015CC00 WRITE   3015217\n0x4015CBC0 WRITE   3015219\n0x4015CA00 WRITE   3015227\n0x4015C9C0 WRITE   3015229\n0x4015C900 WRITE   3015239\n0x4015C8C0 WRITE   3015241\n0x4015C880 WRITE   3015246\n0x4015C840 WRITE   3015249\n0x400C7000 WRITE   3015274\n0x400C7040 WRITE   3015358\n0x400C7080 WRITE   3015424\n0x400C70C0 WRITE   3015480\n0x400C7100 WRITE   3015563\n0x400C7140 WRITE   3015619\n0x400C7180 WRITE   3015682\n0x400C71C0 WRITE   3015738\n0x4015C980 WRITE   3015802\n0x4015C940 WRITE   3015804\n0x400C7200 WRITE   3015840\n0x400C7240 WRITE   3015896\n0x400C7280 WRITE   3015959\n0x400C72C0 WRITE   3016015\n0x400C7300 WRITE   3016093\n0x400C7340 WRITE   3016149\n0x400C7380 WRITE   3016212\n0x400C73C0 WRITE   3016268\n0x4015CB00 WRITE   3016336\n0x4015CAC0 WRITE   3016338\n0x4015CA80 WRITE   3016345\n0x4015CA40 WRITE   3016347\n0x400C7400 WRITE   3016380\n0x400C7440 WRITE   3016436\n0x400C7480 WRITE   3016510\n0x400C74C0 WRITE   3016566\n0x400C7500 WRITE   3016657\n0x400C7540 WRITE   3016713\n0x400C7580 WRITE   3016784\n0x400C75C0 WRITE   3016840\n0x4015CB80 WRITE   3016912\n0x4015CB40 WRITE   3016914\n0x400C7600 WRITE   3016950\n0x400C7640 WRITE   3017006\n0x400C7680 WRITE   3017077\n0x400C76C0 WRITE   3017133\n0x400C7700 WRITE   3017219\n0x400C7740 WRITE   3017275\n0x400C7780 WRITE   3017346\n0x400C77C0 WRITE   3017402\n0x4015CE00 WRITE   3017479\n0x4015CDC0 WRITE   3017481\n0x4015CD00 WRITE   3017488\n0x4015CCC0 WRITE   3017490\n0x4015CC80 WRITE   3017500\n0x4015CC40 WRITE   3017502\n0x400C7800 WRITE   3017529\n0x400C7840 WRITE   3017585\n0x400C7880 WRITE   3017651\n0x400C78C0 WRITE   3017707\n0x400C7900 WRITE   3017794\n0x400C7940 WRITE   3017850\n0x400C7980 WRITE   3017913\n0x400C79C0 WRITE   3017969\n0x4015CD80 WRITE   3018038\n0x4015CD40 WRITE   3018040\n0x400C7A00 WRITE   3018076\n0x400C7A40 WRITE   3018132\n0x400C7A80 WRITE   3018195\n0x400C7AC0 WRITE   3018251\n0x400C7B00 WRITE   3018333\n0x400C7B40 WRITE   3018389\n0x400C7B80 WRITE   3018452\n0x400C7BC0 WRITE   3018508\n0x4015CF00 WRITE   3018581\n0x4015CEC0 WRITE   3018583\n0x4015CE80 WRITE   3018590\n0x4015CE40 WRITE   3018592\n0x400C7C00 WRITE   3018625\n0x400C7C40 WRITE   3018681\n0x400C7C80 WRITE   3018755\n0x400C7CC0 WRITE   3018811\n0x400C7D00 WRITE   3018906\n0x400C7D40 WRITE   3018962\n0x400C7D80 WRITE   3019033\n0x400C7DC0 WRITE   3019089\n0x4015CF80 WRITE   3019166\n0x4015CF40 WRITE   3019168\n0x400C7E00 WRITE   3019204\n0x400C7E40 WRITE   3019260\n0x400C7E80 WRITE   3019331\n0x400C7EC0 WRITE   3019387\n0x400C7F00 WRITE   3019477\n0x400C7F40 WRITE   3019533\n0x400C7F80 WRITE   3019604\n0x400C7FC0 WRITE   3019660\n0x4015D800 WRITE   3019746\n0x4015D7C0 WRITE   3019748\n0x4015D400 WRITE   3019755\n0x4015D3C0 WRITE   3019757\n0x4015D200 WRITE   3019767\n0x4015D1C0 WRITE   3019769\n0x4015D100 WRITE   3019774\n0x4015D0C0 WRITE   3019777\n0x4015D080 WRITE   3019780\n0x4015D040 WRITE   3019783\n0x400C8000 WRITE   3019808\n0x400C8040 WRITE   3019892\n0x400C8080 WRITE   3019958\n0x400C80C0 WRITE   3020014\n0x400C8100 WRITE   3020097\n0x400C8140 WRITE   3020153\n0x400C8180 WRITE   3020216\n0x400C81C0 WRITE   3020272\n0x4015D180 WRITE   3020328\n0x4015D140 WRITE   3020330\n0x400C8200 WRITE   3020366\n0x400C8240 WRITE   3020422\n0x400C8280 WRITE   3020485\n0x400C82C0 WRITE   3020541\n0x400C8300 WRITE   3020619\n0x400C8340 WRITE   3020675\n0x400C8380 WRITE   3020738\n0x400C83C0 WRITE   3020794\n0x4015D300 WRITE   3020860\n0x4015D2C0 WRITE   3020862\n0x4015D280 WRITE   3020869\n0x4015D240 WRITE   3020871\n0x400C8400 WRITE   3020904\n0x400C8440 WRITE   3020960\n0x400C8480 WRITE   3021034\n0x400C84C0 WRITE   3021090\n0x400C8500 WRITE   3021181\n0x400C8540 WRITE   3021237\n0x400C8580 WRITE   3021308\n0x400C85C0 WRITE   3021364\n0x4015D380 WRITE   3021428\n0x4015D340 WRITE   3021430\n0x400C8600 WRITE   3021466\n0x400C8640 WRITE   3021522\n0x400C8680 WRITE   3021593\n0x400C86C0 WRITE   3021649\n0x400C8700 WRITE   3021735\n0x400C8740 WRITE   3021791\n0x400C8780 WRITE   3021862\n0x400C87C0 WRITE   3021918\n0x4015D600 WRITE   3021993\n0x4015D5C0 WRITE   3021995\n0x4015D500 WRITE   3022002\n0x4015D4C0 WRITE   3022004\n0x4015D480 WRITE   3022014\n0x4015D440 WRITE   3022016\n0x400C8800 WRITE   3022043\n0x400C8840 WRITE   3022099\n0x400C8880 WRITE   3022165\n0x400C88C0 WRITE   3022221\n0x400C8900 WRITE   3022308\n0x400C8940 WRITE   3022364\n0x400C8980 WRITE   3022427\n0x400C89C0 WRITE   3022483\n0x4015D580 WRITE   3022545\n0x4015D540 WRITE   3022547\n0x400C8A00 WRITE   3022583\n0x400C8A40 WRITE   3022639\n0x400C8A80 WRITE   3022702\n0x400C8AC0 WRITE   3022758\n0x400C8B00 WRITE   3022840\n0x400C8B40 WRITE   3022896\n0x400C8B80 WRITE   3022959\n0x400C8BC0 WRITE   3023015\n0x4015D700 WRITE   3023087\n0x4015D6C0 WRITE   3023089\n0x4015D680 WRITE   3023096\n0x4015D640 WRITE   3023098\n0x400C8C00 WRITE   3023131\n0x400C8C40 WRITE   3023187\n0x400C8C80 WRITE   3023261\n0x400C8CC0 WRITE   3023317\n0x400C8D00 WRITE   3023412\n0x400C8D40 WRITE   3023468\n0x400C8D80 WRITE   3023539\n0x400C8DC0 WRITE   3023595\n0x4015D780 WRITE   3023665\n0x4015D740 WRITE   3023667\n0x400C8E00 WRITE   3023703\n0x400C8E40 WRITE   3023759\n0x400C8E80 WRITE   3023830\n0x400C8EC0 WRITE   3023886\n0x400C8F00 WRITE   3023976\n0x400C8F40 WRITE   3024032\n0x400C8F80 WRITE   3024103\n0x400C8FC0 WRITE   3024159\n0x4015DC00 WRITE   3024245\n0x4015DBC0 WRITE   3024247\n0x4015DA00 WRITE   3024254\n0x4015D9C0 WRITE   3024256\n0x4015D900 WRITE   3024266\n0x4015D8C0 WRITE   3024268\n0x4015D880 WRITE   3024273\n0x4015D840 WRITE   3024276\n0x400C9000 WRITE   3024301\n0x400C9040 WRITE   3024385\n0x400C9080 WRITE   3024451\n0x400C90C0 WRITE   3024507\n0x400C9100 WRITE   3024590\n0x400C9140 WRITE   3024646\n0x400C9180 WRITE   3024709\n0x400C91C0 WRITE   3024765\n0x4015D980 WRITE   3024829\n0x4015D940 WRITE   3024831\n0x400C9200 WRITE   3024867\n0x400C9240 WRITE   3024923\n0x400C9280 WRITE   3024986\n0x400C92C0 WRITE   3025042\n0x400C9300 WRITE   3025120\n0x400C9340 WRITE   3025176\n0x400C9380 WRITE   3025239\n0x400C93C0 WRITE   3025295\n0x4015DB00 WRITE   3025369\n0x4015DAC0 WRITE   3025371\n0x4015DA80 WRITE   3025378\n0x4015DA40 WRITE   3025380\n0x400C9400 WRITE   3025413\n0x400C9440 WRITE   3025469\n0x400C9480 WRITE   3025543\n0x400C94C0 WRITE   3025599\n0x400C9500 WRITE   3025690\n0x400C9540 WRITE   3025746\n0x400C9580 WRITE   3025817\n0x400C95C0 WRITE   3025873\n0x4015DB80 WRITE   3025945\n0x4015DB40 WRITE   3025947\n0x400C9600 WRITE   3025983\n0x400C9640 WRITE   3026039\n0x400C9680 WRITE   3026110\n0x400C96C0 WRITE   3026166\n0x400C9700 WRITE   3026252\n0x400C9740 WRITE   3026308\n0x400C9780 WRITE   3026379\n0x400C97C0 WRITE   3026435\n0x4015DE00 WRITE   3026518\n0x4015DDC0 WRITE   3026520\n0x4015DD00 WRITE   3026527\n0x4015DCC0 WRITE   3026529\n0x4015DC80 WRITE   3026539\n0x4015DC40 WRITE   3026541\n0x400C9800 WRITE   3026568\n0x400C9840 WRITE   3026624\n0x400C9880 WRITE   3026690\n0x400C98C0 WRITE   3026746\n0x400C9900 WRITE   3026833\n0x400C9940 WRITE   3026889\n0x400C9980 WRITE   3026952\n0x400C99C0 WRITE   3027008\n0x4015DD80 WRITE   3027077\n0x4015DD40 WRITE   3027079\n0x400C9A00 WRITE   3027115\n0x400C9A40 WRITE   3027171\n0x400C9A80 WRITE   3027234\n0x400C9AC0 WRITE   3027290\n0x400C9B00 WRITE   3027372\n0x400C9B40 WRITE   3027428\n0x400C9B80 WRITE   3027491\n0x400C9BC0 WRITE   3027547\n0x4015DF00 WRITE   3027626\n0x4015DEC0 WRITE   3027628\n0x4015DE80 WRITE   3027635\n0x4015DE40 WRITE   3027637\n0x400C9C00 WRITE   3027670\n0x400C9C40 WRITE   3027726\n0x400C9C80 WRITE   3027800\n0x400C9CC0 WRITE   3027856\n0x400C9D00 WRITE   3027951\n0x400C9D40 WRITE   3028007\n0x400C9D80 WRITE   3028078\n0x400C9DC0 WRITE   3028134\n0x4015DF80 WRITE   3028211\n0x4015DF40 WRITE   3028213\n0x400C9E00 WRITE   3028249\n0x400C9E40 WRITE   3028305\n0x400C9E80 WRITE   3028376\n0x400C9EC0 WRITE   3028432\n0x400C9F00 WRITE   3028522\n0x400C9F40 WRITE   3028578\n0x400C9F80 WRITE   3028649\n0x400C9FC0 WRITE   3028705\n0x4015FFC0 WRITE   3028867\n0x40160000 WRITE   3028899\n0x4015F000 WRITE   3029049\n0x4015EFC0 WRITE   3029051\n0x4015E800 WRITE   3029058\n0x4015E7C0 WRITE   3029060\n0x4015E400 WRITE   3029070\n0x4015E3C0 WRITE   3029072\n0x4015E200 WRITE   3029077\n0x4015E1C0 WRITE   3029080\n0x4015E100 WRITE   3029083\n0x4015E0C0 WRITE   3029086\n0x4015E080 WRITE   3029089\n0x4015E040 WRITE   3029092\n0x400CA000 WRITE   3029124\n0x400CA040 WRITE   3029212\n0x400CA080 WRITE   3029278\n0x400CA0C0 WRITE   3029334\n0x400CA100 WRITE   3029417\n0x400CA140 WRITE   3029473\n0x400CA180 WRITE   3029536\n0x400CA1C0 WRITE   3029592\n0x4015E180 WRITE   3029648\n0x4015E140 WRITE   3029650\n0x400CA200 WRITE   3029686\n0x400CA240 WRITE   3029742\n0x400CA280 WRITE   3029805\n0x400CA2C0 WRITE   3029861\n0x400CA300 WRITE   3029939\n0x400CA340 WRITE   3029995\n0x400CA380 WRITE   3030058\n0x400CA3C0 WRITE   3030114\n0x4015E300 WRITE   3030175\n0x4015E2C0 WRITE   3030177\n0x4015E280 WRITE   3030184\n0x4015E240 WRITE   3030186\n0x400CA400 WRITE   3030219\n0x400CA440 WRITE   3030275\n0x400CA480 WRITE   3030349\n0x400CA4C0 WRITE   3030405\n0x400CA500 WRITE   3030496\n0x400CA540 WRITE   3030552\n0x400CA580 WRITE   3030623\n0x400CA5C0 WRITE   3030679\n0x4015E380 WRITE   3030743\n0x4015E340 WRITE   3030745\n0x400CA600 WRITE   3030781\n0x400CA640 WRITE   3030837\n0x400CA680 WRITE   3030908\n0x400CA6C0 WRITE   3030964\n0x400CA700 WRITE   3031050\n0x400CA740 WRITE   3031106\n0x400CA780 WRITE   3031177\n0x400CA7C0 WRITE   3031233\n0x4015E600 WRITE   3031302\n0x4015E5C0 WRITE   3031304\n0x4015E500 WRITE   3031311\n0x4015E4C0 WRITE   3031313\n0x4015E480 WRITE   3031323\n0x4015E440 WRITE   3031325\n0x400CA800 WRITE   3031352\n0x400CA840 WRITE   3031408\n0x400CA880 WRITE   3031474\n0x400CA8C0 WRITE   3031530\n0x400CA900 WRITE   3031617\n0x400CA940 WRITE   3031673\n0x400CA980 WRITE   3031736\n0x400CA9C0 WRITE   3031792\n0x4015E580 WRITE   3031854\n0x4015E540 WRITE   3031856\n0x400CAA00 WRITE   3031892\n0x400CAA40 WRITE   3031948\n0x400CAA80 WRITE   3032011\n0x400CAAC0 WRITE   3032067\n0x400CAB00 WRITE   3032149\n0x400CAB40 WRITE   3032205\n0x400CAB80 WRITE   3032268\n0x400CABC0 WRITE   3032324\n0x4015E700 WRITE   3032390\n0x4015E6C0 WRITE   3032392\n0x4015E680 WRITE   3032399\n0x4015E640 WRITE   3032401\n0x400CAC00 WRITE   3032434\n0x400CAC40 WRITE   3032490\n0x400CAC80 WRITE   3032564\n0x400CACC0 WRITE   3032620\n0x400CAD00 WRITE   3032715\n0x400CAD40 WRITE   3032771\n0x400CAD80 WRITE   3032842\n0x400CADC0 WRITE   3032898\n0x4015E780 WRITE   3032968\n0x4015E740 WRITE   3032970\n0x400CAE00 WRITE   3033006\n0x400CAE40 WRITE   3033062\n0x400CAE80 WRITE   3033133\n0x400CAEC0 WRITE   3033189\n0x400CAF00 WRITE   3033279\n0x400CAF40 WRITE   3033335\n0x400CAF80 WRITE   3033406\n0x400CAFC0 WRITE   3033462\n0x4015EC00 WRITE   3033542\n0x4015EBC0 WRITE   3033544\n0x4015EA00 WRITE   3033551\n0x4015E9C0 WRITE   3033553\n0x4015E900 WRITE   3033563\n0x4015E8C0 WRITE   3033565\n0x4015E880 WRITE   3033570\n0x4015E840 WRITE   3033573\n0x400CB000 WRITE   3033598\n0x400CB040 WRITE   3033682\n0x400CB080 WRITE   3033748\n0x400CB0C0 WRITE   3033804\n0x400CB100 WRITE   3033887\n0x400CB140 WRITE   3033943\n0x400CB180 WRITE   3034006\n0x400CB1C0 WRITE   3034062\n0x4015E980 WRITE   3034126\n0x4015E940 WRITE   3034128\n0x400CB200 WRITE   3034164\n0x400CB240 WRITE   3034220\n0x400CB280 WRITE   3034283\n0x400CB2C0 WRITE   3034339\n0x400CB300 WRITE   3034417\n0x400CB340 WRITE   3034473\n0x400CB380 WRITE   3034536\n0x400CB3C0 WRITE   3034592\n0x4015EB00 WRITE   3034660\n0x4015EAC0 WRITE   3034662\n0x4015EA80 WRITE   3034669\n0x4015EA40 WRITE   3034671\n0x400CB400 WRITE   3034704\n0x400CB440 WRITE   3034760\n0x400CB480 WRITE   3034834\n0x400CB4C0 WRITE   3034890\n0x400CB500 WRITE   3034981\n0x400CB540 WRITE   3035037\n0x400CB580 WRITE   3035108\n0x400CB5C0 WRITE   3035164\n0x4015EB80 WRITE   3035236\n0x4015EB40 WRITE   3035238\n0x400CB600 WRITE   3035274\n0x400CB640 WRITE   3035330\n0x400CB680 WRITE   3035401\n0x400CB6C0 WRITE   3035457\n0x400CB700 WRITE   3035543\n0x400CB740 WRITE   3035599\n0x400CB780 WRITE   3035670\n0x400CB7C0 WRITE   3035726\n0x4015EE00 WRITE   3035803\n0x4015EDC0 WRITE   3035805\n0x4015ED00 WRITE   3035812\n0x4015ECC0 WRITE   3035814\n0x4015EC80 WRITE   3035824\n0x4015EC40 WRITE   3035826\n0x400CB800 WRITE   3035853\n0x400CB840 WRITE   3035909\n0x400CB880 WRITE   3035975\n0x400CB8C0 WRITE   3036031\n0x400CB900 WRITE   3036118\n0x400CB940 WRITE   3036174\n0x400CB980 WRITE   3036237\n0x400CB9C0 WRITE   3036293\n0x4015ED80 WRITE   3036362\n0x4015ED40 WRITE   3036364\n0x400CBA00 WRITE   3036400\n0x400CBA40 WRITE   3036456\n0x400CBA80 WRITE   3036519\n0x400CBAC0 WRITE   3036575\n0x400CBB00 WRITE   3036657\n0x400CBB40 WRITE   3036713\n0x400CBB80 WRITE   3036776\n0x400CBBC0 WRITE   3036832\n0x4015EF00 WRITE   3036905\n0x4015EEC0 WRITE   3036907\n0x4015EE80 WRITE   3036914\n0x4015EE40 WRITE   3036916\n0x400CBC00 WRITE   3036949\n0x400CBC40 WRITE   3037005\n0x400CBC80 WRITE   3037079\n0x400CBCC0 WRITE   3037135\n0x400CBD00 WRITE   3037230\n0x400CBD40 WRITE   3037286\n0x400CBD80 WRITE   3037357\n0x400CBDC0 WRITE   3037413\n0x4015EF80 WRITE   3037490\n0x4015EF40 WRITE   3037492\n0x400CBE00 WRITE   3037528\n0x400CBE40 WRITE   3037584\n0x400CBE80 WRITE   3037655\n0x400CBEC0 WRITE   3037711\n0x400CBF00 WRITE   3037801\n0x400CBF40 WRITE   3037857\n0x400CBF80 WRITE   3037928\n0x400CBFC0 WRITE   3037984\n0x4015F800 WRITE   3038070\n0x4015F7C0 WRITE   3038072\n0x4015F400 WRITE   3038079\n0x4015F3C0 WRITE   3038081\n0x4015F200 WRITE   3038091\n0x4015F1C0 WRITE   3038093\n0x4015F100 WRITE   3038098\n0x4015F0C0 WRITE   3038101\n0x4015F080 WRITE   3038104\n0x4015F040 WRITE   3038107\n0x400CC000 WRITE   3038132\n0x400CC040 WRITE   3038216\n0x400CC080 WRITE   3038282\n0x400CC0C0 WRITE   3038338\n0x400CC100 WRITE   3038421\n0x400CC140 WRITE   3038477\n0x400CC180 WRITE   3038540\n0x400CC1C0 WRITE   3038596\n0x4015F180 WRITE   3038652\n0x4015F140 WRITE   3038654\n0x400CC200 WRITE   3038690\n0x400CC240 WRITE   3038746\n0x400CC280 WRITE   3038809\n0x400CC2C0 WRITE   3038865\n0x400CC300 WRITE   3038943\n0x400CC340 WRITE   3038999\n0x400CC380 WRITE   3039062\n0x400CC3C0 WRITE   3039118\n0x4015F300 WRITE   3039184\n0x4015F2C0 WRITE   3039186\n0x4015F280 WRITE   3039193\n0x4015F240 WRITE   3039195\n0x400CC400 WRITE   3039228\n0x400CC440 WRITE   3039284\n0x400CC480 WRITE   3039358\n0x400CC4C0 WRITE   3039414\n0x400CC500 WRITE   3039505\n0x400CC540 WRITE   3039561\n0x400CC580 WRITE   3039632\n0x400CC5C0 WRITE   3039688\n0x4015F380 WRITE   3039752\n0x4015F340 WRITE   3039754\n0x400CC600 WRITE   3039790\n0x400CC640 WRITE   3039846\n0x400CC680 WRITE   3039917\n0x400CC6C0 WRITE   3039973\n0x400CC700 WRITE   3040059\n0x400CC740 WRITE   3040115\n0x400CC780 WRITE   3040186\n0x400CC7C0 WRITE   3040242\n0x4015F600 WRITE   3040317\n0x4015F5C0 WRITE   3040319\n0x4015F500 WRITE   3040326\n0x4015F4C0 WRITE   3040328\n0x4015F480 WRITE   3040338\n0x4015F440 WRITE   3040340\n0x400CC800 WRITE   3040367\n0x400CC840 WRITE   3040423\n0x400CC880 WRITE   3040489\n0x400CC8C0 WRITE   3040545\n0x400CC900 WRITE   3040632\n0x400CC940 WRITE   3040688\n0x400CC980 WRITE   3040751\n0x400CC9C0 WRITE   3040807\n0x4015F580 WRITE   3040869\n0x4015F540 WRITE   3040871\n0x400CCA00 WRITE   3040907\n0x400CCA40 WRITE   3040963\n0x400CCA80 WRITE   3041026\n0x400CCAC0 WRITE   3041082\n0x400CCB00 WRITE   3041164\n0x400CCB40 WRITE   3041220\n0x400CCB80 WRITE   3041283\n0x400CCBC0 WRITE   3041339\n0x4015F700 WRITE   3041411\n0x4015F6C0 WRITE   3041413\n0x4015F680 WRITE   3041420\n0x4015F640 WRITE   3041422\n0x400CCC00 WRITE   3041455\n0x400CCC40 WRITE   3041511\n0x400CCC80 WRITE   3041585\n0x400CCCC0 WRITE   3041641\n0x400CCD00 WRITE   3041736\n0x400CCD40 WRITE   3041792\n0x400CCD80 WRITE   3041863\n0x400CCDC0 WRITE   3041919\n0x4015F780 WRITE   3041989\n0x4015F740 WRITE   3041991\n0x400CCE00 WRITE   3042027\n0x400CCE40 WRITE   3042083\n0x400CCE80 WRITE   3042154\n0x400CCEC0 WRITE   3042210\n0x400CCF00 WRITE   3042300\n0x400CCF40 WRITE   3042356\n0x400CCF80 WRITE   3042427\n0x400CCFC0 WRITE   3042483\n0x4015FC00 WRITE   3042569\n0x4015FBC0 WRITE   3042571\n0x4015FA00 WRITE   3042578\n0x4015F9C0 WRITE   3042580\n0x4015F900 WRITE   3042590\n0x4015F8C0 WRITE   3042592\n0x4015F880 WRITE   3042597\n0x4015F840 WRITE   3042600\n0x400CD000 WRITE   3042625\n0x400CD040 WRITE   3042709\n0x400CD080 WRITE   3042775\n0x400CD0C0 WRITE   3042831\n0x400CD100 WRITE   3042914\n0x400CD140 WRITE   3042970\n0x400CD180 WRITE   3043033\n0x400CD1C0 WRITE   3043089\n0x4015F980 WRITE   3043153\n0x4015F940 WRITE   3043155\n0x400CD200 WRITE   3043191\n0x400CD240 WRITE   3043247\n0x400CD280 WRITE   3043310\n0x400CD2C0 WRITE   3043366\n0x400CD300 WRITE   3043444\n0x400CD340 WRITE   3043500\n0x400CD380 WRITE   3043563\n0x400CD3C0 WRITE   3043619\n0x4015FB00 WRITE   3043693\n0x4015FAC0 WRITE   3043695\n0x4015FA80 WRITE   3043702\n0x4015FA40 WRITE   3043704\n0x400CD400 WRITE   3043737\n0x400CD440 WRITE   3043793\n0x400CD480 WRITE   3043867\n0x400CD4C0 WRITE   3043923\n0x400CD500 WRITE   3044014\n0x400CD540 WRITE   3044070\n0x400CD580 WRITE   3044141\n0x400CD5C0 WRITE   3044197\n0x4015FB80 WRITE   3044269\n0x4015FB40 WRITE   3044271\n0x400CD600 WRITE   3044307\n0x400CD640 WRITE   3044363\n0x400CD680 WRITE   3044434\n0x400CD6C0 WRITE   3044490\n0x400CD700 WRITE   3044576\n0x400CD740 WRITE   3044632\n0x400CD780 WRITE   3044703\n0x400CD7C0 WRITE   3044759\n0x4015FE00 WRITE   3044842\n0x4015FDC0 WRITE   3044844\n0x4015FD00 WRITE   3044851\n0x4015FCC0 WRITE   3044853\n0x4015FC80 WRITE   3044863\n0x4015FC40 WRITE   3044865\n0x400CD800 WRITE   3044892\n0x400CD840 WRITE   3044948\n0x400CD880 WRITE   3045014\n0x400CD8C0 WRITE   3045070\n0x400CD900 WRITE   3045157\n0x400CD940 WRITE   3045213\n0x400CD980 WRITE   3045276\n0x400CD9C0 WRITE   3045332\n0x4015FD80 WRITE   3045401\n0x4015FD40 WRITE   3045403\n0x400CDA00 WRITE   3045439\n0x400CDA40 WRITE   3045495\n0x400CDA80 WRITE   3045558\n0x400CDAC0 WRITE   3045614\n0x400CDB00 WRITE   3045696\n0x400CDB40 WRITE   3045752\n0x400CDB80 WRITE   3045815\n0x400CDBC0 WRITE   3045871\n0x4015FF00 WRITE   3045950\n0x4015FEC0 WRITE   3045952\n0x4015FE80 WRITE   3045959\n0x4015FE40 WRITE   3045961\n0x400CDC00 WRITE   3045994\n0x400CDC40 WRITE   3046050\n0x400CDC80 WRITE   3046124\n0x400CDCC0 WRITE   3046180\n0x400CDD00 WRITE   3046275\n0x400CDD40 WRITE   3046331\n0x400CDD80 WRITE   3046402\n0x400CDDC0 WRITE   3046458\n0x4015FF80 WRITE   3046535\n0x4015FF40 WRITE   3046537\n0x400CDE00 WRITE   3046573\n0x400CDE40 WRITE   3046629\n0x400CDE80 WRITE   3046700\n0x400CDEC0 WRITE   3046756\n0x400CDF00 WRITE   3046846\n0x400CDF40 WRITE   3046902\n0x400CDF80 WRITE   3046973\n0x400CDFC0 WRITE   3047029\n0x40161FC0 WRITE   3047191\n0x40162000 WRITE   3047234\n0x40161000 WRITE   3047356\n0x40160FC0 WRITE   3047358\n0x40160800 WRITE   3047365\n0x401607C0 WRITE   3047367\n0x40160400 WRITE   3047377\n0x401603C0 WRITE   3047379\n0x40160200 WRITE   3047384\n0x401601C0 WRITE   3047387\n0x40160100 WRITE   3047390\n0x401600C0 WRITE   3047393\n0x40160080 WRITE   3047396\n0x40160040 WRITE   3047399\n0x400CE000 WRITE   3047431\n0x400CE040 WRITE   3047519\n0x400CE080 WRITE   3047585\n0x400CE0C0 WRITE   3047641\n0x400CE100 WRITE   3047724\n0x400CE140 WRITE   3047780\n0x400CE180 WRITE   3047843\n0x400CE1C0 WRITE   3047899\n0x40160180 WRITE   3047955\n0x40160140 WRITE   3047957\n0x400CE200 WRITE   3047993\n0x400CE240 WRITE   3048049\n0x400CE280 WRITE   3048112\n0x400CE2C0 WRITE   3048168\n0x400CE300 WRITE   3048246\n0x400CE340 WRITE   3048302\n0x400CE380 WRITE   3048365\n0x400CE3C0 WRITE   3048421\n0x40160300 WRITE   3048482\n0x401602C0 WRITE   3048484\n0x40160280 WRITE   3048491\n0x40160240 WRITE   3048493\n0x400CE400 WRITE   3048526\n0x400CE440 WRITE   3048582\n0x400CE480 WRITE   3048656\n0x400CE4C0 WRITE   3048712\n0x400CE500 WRITE   3048803\n0x400CE540 WRITE   3048859\n0x400CE580 WRITE   3048930\n0x400CE5C0 WRITE   3048986\n0x40160380 WRITE   3049050\n0x40160340 WRITE   3049052\n0x400CE600 WRITE   3049088\n0x400CE640 WRITE   3049144\n0x400CE680 WRITE   3049215\n0x400CE6C0 WRITE   3049271\n0x400CE700 WRITE   3049357\n0x400CE740 WRITE   3049413\n0x400CE780 WRITE   3049484\n0x400CE7C0 WRITE   3049540\n0x40160600 WRITE   3049609\n0x401605C0 WRITE   3049611\n0x40160500 WRITE   3049618\n0x401604C0 WRITE   3049620\n0x40160480 WRITE   3049630\n0x40160440 WRITE   3049632\n0x400CE800 WRITE   3049659\n0x400CE840 WRITE   3049715\n0x400CE880 WRITE   3049781\n0x400CE8C0 WRITE   3049837\n0x400CE900 WRITE   3049924\n0x400CE940 WRITE   3049980\n0x400CE980 WRITE   3050043\n0x400CE9C0 WRITE   3050099\n0x40160580 WRITE   3050161\n0x40160540 WRITE   3050163\n0x400CEA00 WRITE   3050199\n0x400CEA40 WRITE   3050255\n0x400CEA80 WRITE   3050318\n0x400CEAC0 WRITE   3050374\n0x400CEB00 WRITE   3050456\n0x400CEB40 WRITE   3050512\n0x400CEB80 WRITE   3050575\n0x400CEBC0 WRITE   3050631\n0x40160700 WRITE   3050697\n0x401606C0 WRITE   3050699\n0x40160680 WRITE   3050706\n0x40160640 WRITE   3050708\n0x400CEC00 WRITE   3050741\n0x400CEC40 WRITE   3050797\n0x400CEC80 WRITE   3050871\n0x400CECC0 WRITE   3050927\n0x400CED00 WRITE   3051022\n0x400CED40 WRITE   3051078\n0x400CED80 WRITE   3051149\n0x400CEDC0 WRITE   3051205\n0x40160780 WRITE   3051275\n0x40160740 WRITE   3051277\n0x400CEE00 WRITE   3051313\n0x400CEE40 WRITE   3051369\n0x400CEE80 WRITE   3051440\n0x400CEEC0 WRITE   3051496\n0x400CEF00 WRITE   3051586\n0x400CEF40 WRITE   3051642\n0x400CEF80 WRITE   3051713\n0x400CEFC0 WRITE   3051769\n0x40160C00 WRITE   3051849\n0x40160BC0 WRITE   3051851\n0x40160A00 WRITE   3051858\n0x401609C0 WRITE   3051860\n0x40160900 WRITE   3051870\n0x401608C0 WRITE   3051872\n0x40160880 WRITE   3051877\n0x40160840 WRITE   3051880\n0x400CF000 WRITE   3051905\n0x400CF040 WRITE   3051989\n0x400CF080 WRITE   3052055\n0x400CF0C0 WRITE   3052111\n0x400CF100 WRITE   3052194\n0x400CF140 WRITE   3052250\n0x400CF180 WRITE   3052313\n0x400CF1C0 WRITE   3052369\n0x40160980 WRITE   3052433\n0x40160940 WRITE   3052435\n0x400CF200 WRITE   3052471\n0x400CF240 WRITE   3052527\n0x400CF280 WRITE   3052590\n0x400CF2C0 WRITE   3052646\n0x400CF300 WRITE   3052724\n0x400CF340 WRITE   3052780\n0x400CF380 WRITE   3052843\n0x400CF3C0 WRITE   3052899\n0x40160B00 WRITE   3052967\n0x40160AC0 WRITE   3052969\n0x40160A80 WRITE   3052976\n0x40160A40 WRITE   3052978\n0x400CF400 WRITE   3053011\n0x400CF440 WRITE   3053067\n0x400CF480 WRITE   3053141\n0x400CF4C0 WRITE   3053197\n0x400CF500 WRITE   3053288\n0x400CF540 WRITE   3053344\n0x400CF580 WRITE   3053415\n0x400CF5C0 WRITE   3053471\n0x40160B80 WRITE   3053543\n0x40160B40 WRITE   3053545\n0x400CF600 WRITE   3053581\n0x400CF640 WRITE   3053637\n0x400CF680 WRITE   3053708\n0x400CF6C0 WRITE   3053764\n0x400CF700 WRITE   3053850\n0x400CF740 WRITE   3053906\n0x400CF780 WRITE   3053977\n0x400CF7C0 WRITE   3054033\n0x40160E00 WRITE   3054110\n0x40160DC0 WRITE   3054112\n0x40160D00 WRITE   3054119\n0x40160CC0 WRITE   3054121\n0x40160C80 WRITE   3054131\n0x40160C40 WRITE   3054133\n0x400CF800 WRITE   3054160\n0x400CF840 WRITE   3054216\n0x400CF880 WRITE   3054282\n0x400CF8C0 WRITE   3054338\n0x400CF900 WRITE   3054425\n0x400CF940 WRITE   3054481\n0x400CF980 WRITE   3054544\n0x400CF9C0 WRITE   3054600\n0x40160D80 WRITE   3054669\n0x40160D40 WRITE   3054671\n0x400CFA00 WRITE   3054707\n0x400CFA40 WRITE   3054763\n0x400CFA80 WRITE   3054826\n0x400CFAC0 WRITE   3054882\n0x400CFB00 WRITE   3054964\n0x400CFB40 WRITE   3055020\n0x400CFB80 WRITE   3055083\n0x400CFBC0 WRITE   3055139\n0x40160F00 WRITE   3055212\n0x40160EC0 WRITE   3055214\n0x40160E80 WRITE   3055221\n0x40160E40 WRITE   3055223\n0x400CFC00 WRITE   3055256\n0x400CFC40 WRITE   3055312\n0x400CFC80 WRITE   3055386\n0x400CFCC0 WRITE   3055442\n0x400CFD00 WRITE   3055537\n0x400CFD40 WRITE   3055593\n0x400CFD80 WRITE   3055664\n0x400CFDC0 WRITE   3055720\n0x40160F80 WRITE   3055797\n0x40160F40 WRITE   3055799\n0x400CFE00 WRITE   3055835\n0x400CFE40 WRITE   3055891\n0x400CFE80 WRITE   3055962\n0x400CFEC0 WRITE   3056018\n0x400CFF00 WRITE   3056108\n0x400CFF40 WRITE   3056164\n0x400CFF80 WRITE   3056235\n0x400CFFC0 WRITE   3056291\n0x40161800 WRITE   3056377\n0x401617C0 WRITE   3056379\n0x40161400 WRITE   3056386\n0x401613C0 WRITE   3056388\n0x40161200 WRITE   3056398\n0x401611C0 WRITE   3056400\n0x40161100 WRITE   3056405\n0x401610C0 WRITE   3056408\n0x40161080 WRITE   3056411\n0x40161040 WRITE   3056414\n0x400D0000 WRITE   3056439\n0x400D0040 WRITE   3056523\n0x400D0080 WRITE   3056589\n0x400D00C0 WRITE   3056645\n0x400D0100 WRITE   3056728\n0x400D0140 WRITE   3056784\n0x400D0180 WRITE   3056847\n0x400D01C0 WRITE   3056903\n0x40161180 WRITE   3056959\n0x40161140 WRITE   3056961\n0x400D0200 WRITE   3056997\n0x400D0240 WRITE   3057053\n0x400D0280 WRITE   3057116\n0x400D02C0 WRITE   3057172\n0x400D0300 WRITE   3057250\n0x400D0340 WRITE   3057306\n0x400D0380 WRITE   3057369\n0x400D03C0 WRITE   3057425\n0x40161300 WRITE   3057491\n0x401612C0 WRITE   3057493\n0x40161280 WRITE   3057500\n0x40161240 WRITE   3057502\n0x400D0400 WRITE   3057535\n0x400D0440 WRITE   3057591\n0x400D0480 WRITE   3057665\n0x400D04C0 WRITE   3057721\n0x400D0500 WRITE   3057812\n0x400D0540 WRITE   3057868\n0x400D0580 WRITE   3057939\n0x400D05C0 WRITE   3057995\n0x40161380 WRITE   3058059\n0x40161340 WRITE   3058061\n0x400D0600 WRITE   3058097\n0x400D0640 WRITE   3058153\n0x400D0680 WRITE   3058224\n0x400D06C0 WRITE   3058280\n0x400D0700 WRITE   3058366\n0x400D0740 WRITE   3058422\n0x400D0780 WRITE   3058493\n0x400D07C0 WRITE   3058549\n0x40161600 WRITE   3058624\n0x401615C0 WRITE   3058626\n0x40161500 WRITE   3058633\n0x401614C0 WRITE   3058635\n0x40161480 WRITE   3058645\n0x40161440 WRITE   3058647\n0x400D0800 WRITE   3058674\n0x400D0840 WRITE   3058730\n0x400D0880 WRITE   3058796\n0x400D08C0 WRITE   3058852\n0x400D0900 WRITE   3058939\n0x400D0940 WRITE   3058995\n0x400D0980 WRITE   3059058\n0x400D09C0 WRITE   3059114\n0x40161580 WRITE   3059176\n0x40161540 WRITE   3059178\n0x400D0A00 WRITE   3059214\n0x400D0A40 WRITE   3059270\n0x400D0A80 WRITE   3059333\n0x400D0AC0 WRITE   3059389\n0x400D0B00 WRITE   3059471\n0x400D0B40 WRITE   3059527\n0x400D0B80 WRITE   3059590\n0x400D0BC0 WRITE   3059646\n0x40161700 WRITE   3059718\n0x401616C0 WRITE   3059720\n0x40161680 WRITE   3059727\n0x40161640 WRITE   3059729\n0x400D0C00 WRITE   3059762\n0x400D0C40 WRITE   3059818\n0x400D0C80 WRITE   3059892\n0x400D0CC0 WRITE   3059948\n0x400D0D00 WRITE   3060043\n0x400D0D40 WRITE   3060099\n0x400D0D80 WRITE   3060170\n0x400D0DC0 WRITE   3060226\n0x40161780 WRITE   3060296\n0x40161740 WRITE   3060298\n0x400D0E00 WRITE   3060334\n0x400D0E40 WRITE   3060390\n0x400D0E80 WRITE   3060461\n0x400D0EC0 WRITE   3060517\n0x400D0F00 WRITE   3060607\n0x400D0F40 WRITE   3060663\n0x400D0F80 WRITE   3060734\n0x400D0FC0 WRITE   3060790\n0x40161C00 WRITE   3060876\n0x40161BC0 WRITE   3060878\n0x40161A00 WRITE   3060885\n0x401619C0 WRITE   3060887\n0x40161900 WRITE   3060897\n0x401618C0 WRITE   3060899\n0x40161880 WRITE   3060904\n0x40161840 WRITE   3060907\n0x400D1000 WRITE   3060932\n0x400D1040 WRITE   3061016\n0x400D1080 WRITE   3061082\n0x400D10C0 WRITE   3061138\n0x400D1100 WRITE   3061221\n0x400D1140 WRITE   3061277\n0x400D1180 WRITE   3061340\n0x400D11C0 WRITE   3061396\n0x40161980 WRITE   3061460\n0x40161940 WRITE   3061462\n0x400D1200 WRITE   3061498\n0x400D1240 WRITE   3061554\n0x400D1280 WRITE   3061617\n0x400D12C0 WRITE   3061673\n0x400D1300 WRITE   3061751\n0x400D1340 WRITE   3061807\n0x400D1380 WRITE   3061870\n0x400D13C0 WRITE   3061926\n0x40161B00 WRITE   3062000\n0x40161AC0 WRITE   3062002\n0x40161A80 WRITE   3062009\n0x40161A40 WRITE   3062011\n0x400D1400 WRITE   3062044\n0x400D1440 WRITE   3062100\n0x400D1480 WRITE   3062174\n0x400D14C0 WRITE   3062230\n0x400D1500 WRITE   3062321\n0x400D1540 WRITE   3062377\n0x400D1580 WRITE   3062448\n0x400D15C0 WRITE   3062504\n0x40161B80 WRITE   3062576\n0x40161B40 WRITE   3062578\n0x400D1600 WRITE   3062614\n0x400D1640 WRITE   3062670\n0x400D1680 WRITE   3062741\n0x400D16C0 WRITE   3062797\n0x400D1700 WRITE   3062883\n0x400D1740 WRITE   3062939\n0x400D1780 WRITE   3063010\n0x400D17C0 WRITE   3063066\n0x40161E00 WRITE   3063149\n0x40161DC0 WRITE   3063151\n0x40161D00 WRITE   3063158\n0x40161CC0 WRITE   3063160\n0x40161C80 WRITE   3063170\n0x40161C40 WRITE   3063172\n0x400D1800 WRITE   3063199\n0x400D1840 WRITE   3063255\n0x400D1880 WRITE   3063321\n0x400D18C0 WRITE   3063377\n0x400D1900 WRITE   3063464\n0x400D1940 WRITE   3063520\n0x400D1980 WRITE   3063583\n0x400D19C0 WRITE   3063639\n0x40161D80 WRITE   3063708\n0x40161D40 WRITE   3063710\n0x400D1A00 WRITE   3063746\n0x400D1A40 WRITE   3063802\n0x400D1A80 WRITE   3063865\n0x400D1AC0 WRITE   3063921\n0x400D1B00 WRITE   3064003\n0x400D1B40 WRITE   3064059\n0x400D1B80 WRITE   3064122\n0x400D1BC0 WRITE   3064178\n0x40161F00 WRITE   3064257\n0x40161EC0 WRITE   3064259\n0x40161E80 WRITE   3064266\n0x40161E40 WRITE   3064268\n0x400D1C00 WRITE   3064301\n0x400D1C40 WRITE   3064357\n0x400D1C80 WRITE   3064431\n0x400D1CC0 WRITE   3064487\n0x400D1D00 WRITE   3064582\n0x400D1D40 WRITE   3064638\n0x400D1D80 WRITE   3064709\n0x400D1DC0 WRITE   3064765\n0x40161F80 WRITE   3064842\n0x40161F40 WRITE   3064844\n0x400D1E00 WRITE   3064880\n0x400D1E40 WRITE   3064936\n0x400D1E80 WRITE   3065007\n0x400D1EC0 WRITE   3065063\n0x400D1F00 WRITE   3065153\n0x400D1F40 WRITE   3065209\n0x400D1F80 WRITE   3065280\n0x400D1FC0 WRITE   3065336\n0x1FF96D00 WRITE   3065575\n0x40162880 WRITE   3065637\n0x40163FC0 WRITE   3065755\n0x40164000 WRITE   3065789\n0x40163000 WRITE   3065908\n0x40162FC0 WRITE   3065910\n0x40162800 WRITE   3065917\n0x401627C0 WRITE   3065919\n0x40162400 WRITE   3065929\n0x401623C0 WRITE   3065931\n0x40162200 WRITE   3065936\n0x401621C0 WRITE   3065939\n0x40162100 WRITE   3065947\n0x401620C0 WRITE   3065950\n0x40162080 WRITE   3065953\n0x40162040 WRITE   3065955\n0x400D2000 WRITE   3065987\n0x400D2040 WRITE   3066075\n0x400D2080 WRITE   3066141\n0x400D20C0 WRITE   3066197\n0x400D2100 WRITE   3066280\n0x400D2140 WRITE   3066336\n0x400D2180 WRITE   3066399\n0x400D21C0 WRITE   3066455\n0x40162180 WRITE   3066511\n0x40162140 WRITE   3066513\n0x400D2200 WRITE   3066549\n0x400D2240 WRITE   3066605\n0x400D2280 WRITE   3066668\n0x400D22C0 WRITE   3066724\n0x400D2300 WRITE   3066802\n0x400D2340 WRITE   3066858\n0x400D2380 WRITE   3066921\n0x400D23C0 WRITE   3066977\n0x40162300 WRITE   3067038\n0x401622C0 WRITE   3067040\n0x40162280 WRITE   3067047\n0x40162240 WRITE   3067049\n0x400D2400 WRITE   3067082\n0x400D2440 WRITE   3067138\n0x400D2480 WRITE   3067212\n0x400D24C0 WRITE   3067268\n0x400D2500 WRITE   3067359\n0x400D2540 WRITE   3067415\n0x400D2580 WRITE   3067486\n0x400D25C0 WRITE   3067542\n0x40162380 WRITE   3067606\n0x40162340 WRITE   3067608\n0x400D2600 WRITE   3067644\n0x400D2640 WRITE   3067700\n0x400D2680 WRITE   3067771\n0x400D26C0 WRITE   3067827\n0x400D2700 WRITE   3067913\n0x400D2740 WRITE   3067969\n0x400D2780 WRITE   3068040\n0x400D27C0 WRITE   3068096\n0x40162600 WRITE   3068165\n0x401625C0 WRITE   3068167\n0x40162500 WRITE   3068174\n0x401624C0 WRITE   3068176\n0x40162480 WRITE   3068186\n0x40162440 WRITE   3068188\n0x400D2800 WRITE   3068215\n0x400D2840 WRITE   3068271\n0x400D2880 WRITE   3068337\n0x400D28C0 WRITE   3068393\n0x400D2900 WRITE   3068480\n0x400D2940 WRITE   3068536\n0x400D2980 WRITE   3068599\n0x400D29C0 WRITE   3068655\n0x40162580 WRITE   3068717\n0x40162540 WRITE   3068719\n0x400D2A00 WRITE   3068755\n0x400D2A40 WRITE   3068811\n0x400D2A80 WRITE   3068874\n0x400D2AC0 WRITE   3068930\n0x400D2B00 WRITE   3069012\n0x400D2B40 WRITE   3069068\n0x400D2B80 WRITE   3069131\n0x400D2BC0 WRITE   3069187\n0x40162700 WRITE   3069253\n0x401626C0 WRITE   3069255\n0x40162680 WRITE   3069262\n0x40162640 WRITE   3069264\n0x400D2C00 WRITE   3069297\n0x400D2C40 WRITE   3069353\n0x400D2C80 WRITE   3069427\n0x400D2CC0 WRITE   3069483\n0x400D2D00 WRITE   3069578\n0x400D2D40 WRITE   3069634\n0x400D2D80 WRITE   3069705\n0x400D2DC0 WRITE   3069761\n0x40162780 WRITE   3069831\n0x40162740 WRITE   3069833\n0x400D2E00 WRITE   3069869\n0x400D2E40 WRITE   3069925\n0x400D2E80 WRITE   3069996\n0x400D2EC0 WRITE   3070052\n0x400D2F00 WRITE   3070142\n0x400D2F40 WRITE   3070198\n0x400D2F80 WRITE   3070269\n0x400D2FC0 WRITE   3070325\n0x40162C00 WRITE   3070405\n0x40162BC0 WRITE   3070407\n0x40162A00 WRITE   3070414\n0x401629C0 WRITE   3070416\n0x40162900 WRITE   3070426\n0x401628C0 WRITE   3070428\n0x40162840 WRITE   3070436\n0x400D3000 WRITE   3070461\n0x400D3040 WRITE   3070545\n0x400D3080 WRITE   3070611\n0x400D30C0 WRITE   3070667\n0x400D3100 WRITE   3070750\n0x400D3140 WRITE   3070806\n0x400D3180 WRITE   3070869\n0x400D31C0 WRITE   3070925\n0x40162980 WRITE   3070989\n0x40162940 WRITE   3070991\n0x400D3200 WRITE   3071027\n0x400D3240 WRITE   3071083\n0x400D3280 WRITE   3071146\n0x400D32C0 WRITE   3071202\n0x400D3300 WRITE   3071280\n0x400D3340 WRITE   3071336\n0x400D3380 WRITE   3071399\n0x400D33C0 WRITE   3071455\n0x40162B00 WRITE   3071523\n0x40162AC0 WRITE   3071525\n0x40162A80 WRITE   3071532\n0x40162A40 WRITE   3071534\n0x400D3400 WRITE   3071567\n0x400D3440 WRITE   3071623\n0x400D3480 WRITE   3071697\n0x400D34C0 WRITE   3071753\n0x400D3500 WRITE   3071844\n0x400D3540 WRITE   3071900\n0x400D3580 WRITE   3071971\n0x400D35C0 WRITE   3072027\n0x40162B80 WRITE   3072099\n0x40162B40 WRITE   3072101\n0x400D3600 WRITE   3072137\n0x400D3640 WRITE   3072193\n0x400D3680 WRITE   3072264\n0x400D36C0 WRITE   3072320\n0x400D3700 WRITE   3072406\n0x400D3740 WRITE   3072462\n0x400D3780 WRITE   3072533\n0x400D37C0 WRITE   3072589\n0x40162E00 WRITE   3072666\n0x40162DC0 WRITE   3072668\n0x40162D00 WRITE   3072675\n0x40162CC0 WRITE   3072677\n0x40162C80 WRITE   3072687\n0x40162C40 WRITE   3072689\n0x400D3800 WRITE   3072716\n0x400D3840 WRITE   3072772\n0x400D3880 WRITE   3072838\n0x400D38C0 WRITE   3072894\n0x400D3900 WRITE   3072981\n0x400D3940 WRITE   3073037\n0x400D3980 WRITE   3073100\n0x400D39C0 WRITE   3073156\n0x40162D80 WRITE   3073225\n0x40162D40 WRITE   3073227\n0x400D3A00 WRITE   3073263\n0x400D3A40 WRITE   3073319\n0x400D3A80 WRITE   3073382\n0x400D3AC0 WRITE   3073438\n0x400D3B00 WRITE   3073520\n0x400D3B40 WRITE   3073576\n0x400D3B80 WRITE   3073639\n0x400D3BC0 WRITE   3073695\n0x40162F00 WRITE   3073768\n0x40162EC0 WRITE   3073770\n0x40162E80 WRITE   3073777\n0x40162E40 WRITE   3073779\n0x400D3C00 WRITE   3073812\n0x400D3C40 WRITE   3073868\n0x400D3C80 WRITE   3073942\n0x400D3CC0 WRITE   3073998\n0x400D3D00 WRITE   3074093\n0x400D3D40 WRITE   3074149\n0x400D3D80 WRITE   3074220\n0x400D3DC0 WRITE   3074276\n0x40162F80 WRITE   3074353\n0x40162F40 WRITE   3074355\n0x400D3E00 WRITE   3074391\n0x400D3E40 WRITE   3074447\n0x400D3E80 WRITE   3074518\n0x400D3EC0 WRITE   3074574\n0x400D3F00 WRITE   3074664\n0x400D3F40 WRITE   3074720\n0x400D3F80 WRITE   3074791\n0x400D3FC0 WRITE   3074847\n0x40163800 WRITE   3074933\n0x401637C0 WRITE   3074935\n0x40163400 WRITE   3074942\n0x401633C0 WRITE   3074944\n0x40163200 WRITE   3074954\n0x401631C0 WRITE   3074956\n0x40163100 WRITE   3074961\n0x401630C0 WRITE   3074964\n0x40163080 WRITE   3074967\n0x40163040 WRITE   3074970\n0x400D4000 WRITE   3074995\n0x400D4040 WRITE   3075079\n0x400D4080 WRITE   3075145\n0x400D40C0 WRITE   3075201\n0x400D4100 WRITE   3075284\n0x400D4140 WRITE   3075340\n0x400D4180 WRITE   3075403\n0x400D41C0 WRITE   3075459\n0x40163180 WRITE   3075515\n0x40163140 WRITE   3075517\n0x400D4200 WRITE   3075553\n0x400D4240 WRITE   3075609\n0x400D4280 WRITE   3075672\n0x400D42C0 WRITE   3075728\n0x400D4300 WRITE   3075806\n0x400D4340 WRITE   3075862\n0x400D4380 WRITE   3075925\n0x400D43C0 WRITE   3075981\n0x40163300 WRITE   3076047\n0x401632C0 WRITE   3076049\n0x40163280 WRITE   3076056\n0x40163240 WRITE   3076058\n0x400D4400 WRITE   3076091\n0x400D4440 WRITE   3076147\n0x400D4480 WRITE   3076221\n0x400D44C0 WRITE   3076277\n0x400D4500 WRITE   3076368\n0x400D4540 WRITE   3076424\n0x400D4580 WRITE   3076495\n0x400D45C0 WRITE   3076551\n0x40163380 WRITE   3076615\n0x40163340 WRITE   3076617\n0x400D4600 WRITE   3076653\n0x400D4640 WRITE   3076709\n0x400D4680 WRITE   3076780\n0x400D46C0 WRITE   3076836\n0x400D4700 WRITE   3076922\n0x400D4740 WRITE   3076978\n0x400D4780 WRITE   3077049\n0x400D47C0 WRITE   3077105\n0x40163600 WRITE   3077180\n0x401635C0 WRITE   3077182\n0x40163500 WRITE   3077189\n0x401634C0 WRITE   3077191\n0x40163480 WRITE   3077201\n0x40163440 WRITE   3077203\n0x400D4800 WRITE   3077230\n0x400D4840 WRITE   3077286\n0x400D4880 WRITE   3077352\n0x400D48C0 WRITE   3077408\n0x400D4900 WRITE   3077495\n0x400D4940 WRITE   3077551\n0x400D4980 WRITE   3077614\n0x400D49C0 WRITE   3077670\n0x40163580 WRITE   3077732\n0x40163540 WRITE   3077734\n0x400D4A00 WRITE   3077770\n0x400D4A40 WRITE   3077826\n0x400D4A80 WRITE   3077889\n0x400D4AC0 WRITE   3077945\n0x400D4B00 WRITE   3078027\n0x400D4B40 WRITE   3078083\n0x400D4B80 WRITE   3078146\n0x400D4BC0 WRITE   3078202\n0x40163700 WRITE   3078274\n0x401636C0 WRITE   3078276\n0x40163680 WRITE   3078283\n0x40163640 WRITE   3078285\n0x400D4C00 WRITE   3078318\n0x400D4C40 WRITE   3078374\n0x400D4C80 WRITE   3078448\n0x400D4CC0 WRITE   3078504\n0x400D4D00 WRITE   3078599\n0x400D4D40 WRITE   3078655\n0x400D4D80 WRITE   3078726\n0x400D4DC0 WRITE   3078782\n0x40163780 WRITE   3078852\n0x40163740 WRITE   3078854\n0x400D4E00 WRITE   3078890\n0x400D4E40 WRITE   3078946\n0x400D4E80 WRITE   3079017\n0x400D4EC0 WRITE   3079073\n0x400D4F00 WRITE   3079163\n0x400D4F40 WRITE   3079219\n0x400D4F80 WRITE   3079290\n0x400D4FC0 WRITE   3079346\n0x40163C00 WRITE   3079432\n0x40163BC0 WRITE   3079434\n0x40163A00 WRITE   3079441\n0x401639C0 WRITE   3079443\n0x40163900 WRITE   3079453\n0x401638C0 WRITE   3079455\n0x40163880 WRITE   3079460\n0x40163840 WRITE   3079463\n0x400D5000 WRITE   3079488\n0x400D5040 WRITE   3079572\n0x400D5080 WRITE   3079638\n0x400D50C0 WRITE   3079694\n0x400D5100 WRITE   3079777\n0x400D5140 WRITE   3079833\n0x400D5180 WRITE   3079896\n0x400D51C0 WRITE   3079952\n0x40163980 WRITE   3080016\n0x40163940 WRITE   3080018\n0x400D5200 WRITE   3080054\n0x400D5240 WRITE   3080110\n0x400D5280 WRITE   3080173\n0x400D52C0 WRITE   3080229\n0x400D5300 WRITE   3080307\n0x400D5340 WRITE   3080363\n0x400D5380 WRITE   3080426\n0x400D53C0 WRITE   3080482\n0x40163B00 WRITE   3080556\n0x40163AC0 WRITE   3080558\n0x40163A80 WRITE   3080565\n0x40163A40 WRITE   3080567\n0x400D5400 WRITE   3080600\n0x400D5440 WRITE   3080656\n0x400D5480 WRITE   3080730\n0x400D54C0 WRITE   3080786\n0x400D5500 WRITE   3080877\n0x400D5540 WRITE   3080933\n0x400D5580 WRITE   3081004\n0x400D55C0 WRITE   3081060\n0x40163B80 WRITE   3081132\n0x40163B40 WRITE   3081134\n0x400D5600 WRITE   3081170\n0x400D5640 WRITE   3081226\n0x400D5680 WRITE   3081297\n0x400D56C0 WRITE   3081353\n0x400D5700 WRITE   3081439\n0x400D5740 WRITE   3081495\n0x400D5780 WRITE   3081566\n0x400D57C0 WRITE   3081622\n0x40163E00 WRITE   3081705\n0x40163DC0 WRITE   3081707\n0x40163D00 WRITE   3081714\n0x40163CC0 WRITE   3081716\n0x40163C80 WRITE   3081726\n0x40163C40 WRITE   3081728\n0x400D5800 WRITE   3081755\n0x400D5840 WRITE   3081811\n0x400D5880 WRITE   3081877\n0x400D58C0 WRITE   3081933\n0x400D5900 WRITE   3082020\n0x400D5940 WRITE   3082076\n0x400D5980 WRITE   3082139\n0x400D59C0 WRITE   3082195\n0x40163D80 WRITE   3082264\n0x40163D40 WRITE   3082266\n0x400D5A00 WRITE   3082302\n0x400D5A40 WRITE   3082358\n0x400D5A80 WRITE   3082421\n0x400D5AC0 WRITE   3082477\n0x400D5B00 WRITE   3082559\n0x400D5B40 WRITE   3082615\n0x400D5B80 WRITE   3082678\n0x400D5BC0 WRITE   3082734\n0x40163F00 WRITE   3082813\n0x40163EC0 WRITE   3082815\n0x40163E80 WRITE   3082822\n0x40163E40 WRITE   3082824\n0x400D5C00 WRITE   3082857\n0x400D5C40 WRITE   3082913\n0x400D5C80 WRITE   3082987\n0x400D5CC0 WRITE   3083043\n0x400D5D00 WRITE   3083138\n0x400D5D40 WRITE   3083194\n0x400D5D80 WRITE   3083265\n0x400D5DC0 WRITE   3083321\n0x40163F80 WRITE   3083398\n0x40163F40 WRITE   3083400\n0x400D5E00 WRITE   3083436\n0x400D5E40 WRITE   3083492\n0x400D5E80 WRITE   3083563\n0x400D5EC0 WRITE   3083619\n0x400D5F00 WRITE   3083709\n0x400D5F40 WRITE   3083765\n0x400D5F80 WRITE   3083836\n0x400D5FC0 WRITE   3083892\n0x40165FC0 WRITE   3084054\n0x40166000 WRITE   3084086\n0x40165000 WRITE   3084236\n0x40164FC0 WRITE   3084238\n0x40164800 WRITE   3084245\n0x401647C0 WRITE   3084247\n0x40164400 WRITE   3084257\n0x401643C0 WRITE   3084259\n0x40164200 WRITE   3084264\n0x401641C0 WRITE   3084267\n0x40164100 WRITE   3084270\n0x401640C0 WRITE   3084273\n0x40164080 WRITE   3084276\n0x40164040 WRITE   3084279\n0x400D6000 WRITE   3084311\n0x400D6040 WRITE   3084399\n0x400D6080 WRITE   3084465\n0x400D60C0 WRITE   3084521\n0x400D6100 WRITE   3084604\n0x400D6140 WRITE   3084660\n0x400D6180 WRITE   3084723\n0x400D61C0 WRITE   3084779\n0x40164180 WRITE   3084835\n0x40164140 WRITE   3084837\n0x400D6200 WRITE   3084873\n0x400D6240 WRITE   3084929\n0x400D6280 WRITE   3084992\n0x400D62C0 WRITE   3085048\n0x400D6300 WRITE   3085126\n0x400D6340 WRITE   3085182\n0x400D6380 WRITE   3085245\n0x400D63C0 WRITE   3085301\n0x40164300 WRITE   3085362\n0x401642C0 WRITE   3085364\n0x40164280 WRITE   3085371\n0x40164240 WRITE   3085373\n0x400D6400 WRITE   3085406\n0x400D6440 WRITE   3085462\n0x400D6480 WRITE   3085536\n0x400D64C0 WRITE   3085592\n0x400D6500 WRITE   3085683\n0x400D6540 WRITE   3085739\n0x400D6580 WRITE   3085810\n0x400D65C0 WRITE   3085866\n0x40164380 WRITE   3085930\n0x40164340 WRITE   3085932\n0x400D6600 WRITE   3085968\n0x400D6640 WRITE   3086024\n0x400D6680 WRITE   3086095\n0x400D66C0 WRITE   3086151\n0x400D6700 WRITE   3086237\n0x400D6740 WRITE   3086293\n0x400D6780 WRITE   3086364\n0x400D67C0 WRITE   3086420\n0x40164600 WRITE   3086489\n0x401645C0 WRITE   3086491\n0x40164500 WRITE   3086498\n0x401644C0 WRITE   3086500\n0x40164480 WRITE   3086510\n0x40164440 WRITE   3086512\n0x400D6800 WRITE   3086539\n0x400D6840 WRITE   3086595\n0x400D6880 WRITE   3086661\n0x400D68C0 WRITE   3086717\n0x400D6900 WRITE   3086804\n0x400D6940 WRITE   3086860\n0x400D6980 WRITE   3086923\n0x400D69C0 WRITE   3086979\n0x40164580 WRITE   3087041\n0x40164540 WRITE   3087043\n0x400D6A00 WRITE   3087079\n0x400D6A40 WRITE   3087135\n0x400D6A80 WRITE   3087198\n0x400D6AC0 WRITE   3087254\n0x400D6B00 WRITE   3087336\n0x400D6B40 WRITE   3087392\n0x400D6B80 WRITE   3087455\n0x400D6BC0 WRITE   3087511\n0x40164700 WRITE   3087577\n0x401646C0 WRITE   3087579\n0x40164680 WRITE   3087586\n0x40164640 WRITE   3087588\n0x400D6C00 WRITE   3087621\n0x400D6C40 WRITE   3087677\n0x400D6C80 WRITE   3087751\n0x400D6CC0 WRITE   3087807\n0x400D6D00 WRITE   3087902\n0x400D6D40 WRITE   3087958\n0x400D6D80 WRITE   3088029\n0x400D6DC0 WRITE   3088085\n0x40164780 WRITE   3088155\n0x40164740 WRITE   3088157\n0x400D6E00 WRITE   3088193\n0x400D6E40 WRITE   3088249\n0x400D6E80 WRITE   3088320\n0x400D6EC0 WRITE   3088376\n0x400D6F00 WRITE   3088466\n0x400D6F40 WRITE   3088522\n0x400D6F80 WRITE   3088593\n0x400D6FC0 WRITE   3088649\n0x40164C00 WRITE   3088729\n0x40164BC0 WRITE   3088731\n0x40164A00 WRITE   3088738\n0x401649C0 WRITE   3088740\n0x40164900 WRITE   3088750\n0x401648C0 WRITE   3088752\n0x40164880 WRITE   3088757\n0x40164840 WRITE   3088760\n0x400D7000 WRITE   3088785\n0x400D7040 WRITE   3088869\n0x400D7080 WRITE   3088935\n0x400D70C0 WRITE   3088991\n0x400D7100 WRITE   3089074\n0x400D7140 WRITE   3089130\n0x400D7180 WRITE   3089193\n0x400D71C0 WRITE   3089249\n0x40164980 WRITE   3089313\n0x40164940 WRITE   3089315\n0x400D7200 WRITE   3089351\n0x400D7240 WRITE   3089407\n0x400D7280 WRITE   3089470\n0x400D72C0 WRITE   3089526\n0x400D7300 WRITE   3089604\n0x400D7340 WRITE   3089660\n0x400D7380 WRITE   3089723\n0x400D73C0 WRITE   3089779\n0x40164B00 WRITE   3089847\n0x40164AC0 WRITE   3089849\n0x40164A80 WRITE   3089856\n0x40164A40 WRITE   3089858\n0x400D7400 WRITE   3089891\n0x400D7440 WRITE   3089947\n0x400D7480 WRITE   3090021\n0x400D74C0 WRITE   3090077\n0x400D7500 WRITE   3090168\n0x400D7540 WRITE   3090224\n0x400D7580 WRITE   3090295\n0x400D75C0 WRITE   3090351\n0x40164B80 WRITE   3090423\n0x40164B40 WRITE   3090425\n0x400D7600 WRITE   3090461\n0x400D7640 WRITE   3090517\n0x400D7680 WRITE   3090588\n0x400D76C0 WRITE   3090644\n0x400D7700 WRITE   3090730\n0x400D7740 WRITE   3090786\n0x400D7780 WRITE   3090857\n0x400D77C0 WRITE   3090913\n0x40164E00 WRITE   3090990\n0x40164DC0 WRITE   3090992\n0x40164D00 WRITE   3090999\n0x40164CC0 WRITE   3091001\n0x40164C80 WRITE   3091011\n0x40164C40 WRITE   3091013\n0x400D7800 WRITE   3091040\n0x400D7840 WRITE   3091096\n0x400D7880 WRITE   3091162\n0x400D78C0 WRITE   3091218\n0x400D7900 WRITE   3091305\n0x400D7940 WRITE   3091361\n0x400D7980 WRITE   3091424\n0x400D79C0 WRITE   3091480\n0x40164D80 WRITE   3091549\n0x40164D40 WRITE   3091551\n0x400D7A00 WRITE   3091587\n0x400D7A40 WRITE   3091643\n0x400D7A80 WRITE   3091706\n0x400D7AC0 WRITE   3091762\n0x400D7B00 WRITE   3091844\n0x400D7B40 WRITE   3091900\n0x400D7B80 WRITE   3091963\n0x400D7BC0 WRITE   3092019\n0x40164F00 WRITE   3092092\n0x40164EC0 WRITE   3092094\n0x40164E80 WRITE   3092101\n0x40164E40 WRITE   3092103\n0x400D7C00 WRITE   3092136\n0x400D7C40 WRITE   3092192\n0x400D7C80 WRITE   3092266\n0x400D7CC0 WRITE   3092322\n0x400D7D00 WRITE   3092417\n0x400D7D40 WRITE   3092473\n0x400D7D80 WRITE   3092544\n0x400D7DC0 WRITE   3092600\n0x40164F80 WRITE   3092677\n0x40164F40 WRITE   3092679\n0x400D7E00 WRITE   3092715\n0x400D7E40 WRITE   3092771\n0x400D7E80 WRITE   3092842\n0x400D7EC0 WRITE   3092898\n0x400D7F00 WRITE   3092988\n0x400D7F40 WRITE   3093044\n0x400D7F80 WRITE   3093115\n0x400D7FC0 WRITE   3093171\n0x40165800 WRITE   3093257\n0x401657C0 WRITE   3093259\n0x40165400 WRITE   3093266\n0x401653C0 WRITE   3093268\n0x40165200 WRITE   3093278\n0x401651C0 WRITE   3093280\n0x40165100 WRITE   3093285\n0x401650C0 WRITE   3093288\n0x40165080 WRITE   3093291\n0x40165040 WRITE   3093294\n0x400D8000 WRITE   3093319\n0x400D8040 WRITE   3093403\n0x400D8080 WRITE   3093469\n0x400D80C0 WRITE   3093525\n0x400D8100 WRITE   3093608\n0x400D8140 WRITE   3093664\n0x400D8180 WRITE   3093727\n0x400D81C0 WRITE   3093783\n0x40165180 WRITE   3093839\n0x40165140 WRITE   3093841\n0x400D8200 WRITE   3093877\n0x400D8240 WRITE   3093933\n0x400D8280 WRITE   3093996\n0x400D82C0 WRITE   3094052\n0x400D8300 WRITE   3094130\n0x400D8340 WRITE   3094186\n0x400D8380 WRITE   3094249\n0x400D83C0 WRITE   3094305\n0x40165300 WRITE   3094371\n0x401652C0 WRITE   3094373\n0x40165280 WRITE   3094380\n0x40165240 WRITE   3094382\n0x400D8400 WRITE   3094415\n0x400D8440 WRITE   3094471\n0x400D8480 WRITE   3094545\n0x400D84C0 WRITE   3094601\n0x400D8500 WRITE   3094692\n0x400D8540 WRITE   3094748\n0x400D8580 WRITE   3094819\n0x400D85C0 WRITE   3094875\n0x40165380 WRITE   3094939\n0x40165340 WRITE   3094941\n0x400D8600 WRITE   3094977\n0x400D8640 WRITE   3095033\n0x400D8680 WRITE   3095104\n0x400D86C0 WRITE   3095160\n0x400D8700 WRITE   3095246\n0x400D8740 WRITE   3095302\n0x400D8780 WRITE   3095373\n0x400D87C0 WRITE   3095429\n0x40165600 WRITE   3095504\n0x401655C0 WRITE   3095506\n0x40165500 WRITE   3095513\n0x401654C0 WRITE   3095515\n0x40165480 WRITE   3095525\n0x40165440 WRITE   3095527\n0x400D8800 WRITE   3095554\n0x400D8840 WRITE   3095610\n0x400D8880 WRITE   3095676\n0x400D88C0 WRITE   3095732\n0x400D8900 WRITE   3095819\n0x400D8940 WRITE   3095875\n0x400D8980 WRITE   3095938\n0x400D89C0 WRITE   3095994\n0x40165580 WRITE   3096056\n0x40165540 WRITE   3096058\n0x400D8A00 WRITE   3096094\n0x400D8A40 WRITE   3096150\n0x400D8A80 WRITE   3096213\n0x400D8AC0 WRITE   3096269\n0x400D8B00 WRITE   3096351\n0x400D8B40 WRITE   3096407\n0x400D8B80 WRITE   3096470\n0x400D8BC0 WRITE   3096526\n0x40165700 WRITE   3096598\n0x401656C0 WRITE   3096600\n0x40165680 WRITE   3096607\n0x40165640 WRITE   3096609\n0x400D8C00 WRITE   3096642\n0x400D8C40 WRITE   3096698\n0x400D8C80 WRITE   3096772\n0x400D8CC0 WRITE   3096828\n0x400D8D00 WRITE   3096923\n0x400D8D40 WRITE   3096979\n0x400D8D80 WRITE   3097050\n0x400D8DC0 WRITE   3097106\n0x40165780 WRITE   3097176\n0x40165740 WRITE   3097178\n0x400D8E00 WRITE   3097214\n0x400D8E40 WRITE   3097270\n0x400D8E80 WRITE   3097341\n0x400D8EC0 WRITE   3097397\n0x400D8F00 WRITE   3097487\n0x400D8F40 WRITE   3097543\n0x400D8F80 WRITE   3097614\n0x400D8FC0 WRITE   3097670\n0x40165C00 WRITE   3097756\n0x40165BC0 WRITE   3097758\n0x40165A00 WRITE   3097765\n0x401659C0 WRITE   3097767\n0x40165900 WRITE   3097777\n0x401658C0 WRITE   3097779\n0x40165880 WRITE   3097784\n0x40165840 WRITE   3097787\n0x400D9000 WRITE   3097812\n0x400D9040 WRITE   3097896\n0x400D9080 WRITE   3097962\n0x400D90C0 WRITE   3098018\n0x400D9100 WRITE   3098101\n0x400D9140 WRITE   3098157\n0x400D9180 WRITE   3098220\n0x400D91C0 WRITE   3098276\n0x40165980 WRITE   3098340\n0x40165940 WRITE   3098342\n0x400D9200 WRITE   3098378\n0x400D9240 WRITE   3098434\n0x400D9280 WRITE   3098497\n0x400D92C0 WRITE   3098553\n0x400D9300 WRITE   3098631\n0x400D9340 WRITE   3098687\n0x400D9380 WRITE   3098750\n0x400D93C0 WRITE   3098806\n0x40165B00 WRITE   3098880\n0x40165AC0 WRITE   3098882\n0x40165A80 WRITE   3098889\n0x40165A40 WRITE   3098891\n0x400D9400 WRITE   3098924\n0x400D9440 WRITE   3098980\n0x400D9480 WRITE   3099054\n0x400D94C0 WRITE   3099110\n0x400D9500 WRITE   3099201\n0x400D9540 WRITE   3099257\n0x400D9580 WRITE   3099328\n0x400D95C0 WRITE   3099384\n0x40165B80 WRITE   3099456\n0x40165B40 WRITE   3099458\n0x400D9600 WRITE   3099494\n0x400D9640 WRITE   3099550\n0x400D9680 WRITE   3099621\n0x400D96C0 WRITE   3099677\n0x400D9700 WRITE   3099763\n0x400D9740 WRITE   3099819\n0x400D9780 WRITE   3099890\n0x400D97C0 WRITE   3099946\n0x40165E00 WRITE   3100029\n0x40165DC0 WRITE   3100031\n0x40165D00 WRITE   3100038\n0x40165CC0 WRITE   3100040\n0x40165C80 WRITE   3100050\n0x40165C40 WRITE   3100052\n0x400D9800 WRITE   3100079\n0x400D9840 WRITE   3100135\n0x400D9880 WRITE   3100201\n0x400D98C0 WRITE   3100257\n0x400D9900 WRITE   3100344\n0x400D9940 WRITE   3100400\n0x400D9980 WRITE   3100463\n0x400D99C0 WRITE   3100519\n0x40165D80 WRITE   3100588\n0x40165D40 WRITE   3100590\n0x400D9A00 WRITE   3100626\n0x400D9A40 WRITE   3100682\n0x400D9A80 WRITE   3100745\n0x400D9AC0 WRITE   3100801\n0x400D9B00 WRITE   3100883\n0x400D9B40 WRITE   3100939\n0x400D9B80 WRITE   3101002\n0x400D9BC0 WRITE   3101058\n0x40165F00 WRITE   3101137\n0x40165EC0 WRITE   3101139\n0x40165E80 WRITE   3101146\n0x40165E40 WRITE   3101148\n0x400D9C00 WRITE   3101181\n0x400D9C40 WRITE   3101237\n0x400D9C80 WRITE   3101311\n0x400D9CC0 WRITE   3101367\n0x400D9D00 WRITE   3101462\n0x400D9D40 WRITE   3101518\n0x400D9D80 WRITE   3101589\n0x400D9DC0 WRITE   3101645\n0x40165F80 WRITE   3101722\n0x40165F40 WRITE   3101724\n0x400D9E00 WRITE   3101760\n0x400D9E40 WRITE   3101816\n0x400D9E80 WRITE   3101887\n0x400D9EC0 WRITE   3101943\n0x400D9F00 WRITE   3102033\n0x400D9F40 WRITE   3102089\n0x400D9F80 WRITE   3102160\n0x400D9FC0 WRITE   3102216\n0x40167FC0 WRITE   3102378\n0x40168000 WRITE   3102410\n0x40167000 WRITE   3102537\n0x40166FC0 WRITE   3102539\n0x40166800 WRITE   3102546\n0x401667C0 WRITE   3102548\n0x40166400 WRITE   3102558\n0x401663C0 WRITE   3102560\n0x40166200 WRITE   3102565\n0x401661C0 WRITE   3102568\n0x40166100 WRITE   3102571\n0x401660C0 WRITE   3102574\n0x40166080 WRITE   3102577\n0x40166040 WRITE   3102580\n0x400DA000 WRITE   3102612\n0x400DA040 WRITE   3102700\n0x400DA080 WRITE   3102766\n0x400DA0C0 WRITE   3102822\n0x400DA100 WRITE   3102905\n0x400DA140 WRITE   3102961\n0x400DA180 WRITE   3103024\n0x400DA1C0 WRITE   3103080\n0x40166180 WRITE   3103136\n0x40166140 WRITE   3103138\n0x400DA200 WRITE   3103174\n0x400DA240 WRITE   3103230\n0x400DA280 WRITE   3103293\n0x400DA2C0 WRITE   3103349\n0x400DA300 WRITE   3103427\n0x400DA340 WRITE   3103483\n0x400DA380 WRITE   3103546\n0x400DA3C0 WRITE   3103602\n0x40166300 WRITE   3103663\n0x401662C0 WRITE   3103665\n0x40166280 WRITE   3103672\n0x40166240 WRITE   3103674\n0x400DA400 WRITE   3103707\n0x400DA440 WRITE   3103763\n0x400DA480 WRITE   3103837\n0x400DA4C0 WRITE   3103893\n0x400DA500 WRITE   3103984\n0x400DA540 WRITE   3104040\n0x400DA580 WRITE   3104111\n0x400DA5C0 WRITE   3104167\n0x40166380 WRITE   3104231\n0x40166340 WRITE   3104233\n0x400DA600 WRITE   3104269\n0x400DA640 WRITE   3104325\n0x400DA680 WRITE   3104396\n0x400DA6C0 WRITE   3104452\n0x400DA700 WRITE   3104538\n0x400DA740 WRITE   3104594\n0x400DA780 WRITE   3104665\n0x400DA7C0 WRITE   3104721\n0x40166600 WRITE   3104790\n0x401665C0 WRITE   3104792\n0x40166500 WRITE   3104799\n0x401664C0 WRITE   3104801\n0x40166480 WRITE   3104811\n0x40166440 WRITE   3104813\n0x400DA800 WRITE   3104840\n0x400DA840 WRITE   3104896\n0x400DA880 WRITE   3104962\n0x400DA8C0 WRITE   3105018\n0x400DA900 WRITE   3105105\n0x400DA940 WRITE   3105161\n0x400DA980 WRITE   3105224\n0x400DA9C0 WRITE   3105280\n0x40166580 WRITE   3105342\n0x40166540 WRITE   3105344\n0x400DAA00 WRITE   3105380\n0x400DAA40 WRITE   3105436\n0x400DAA80 WRITE   3105499\n0x400DAAC0 WRITE   3105555\n0x400DAB00 WRITE   3105637\n0x400DAB40 WRITE   3105693\n0x400DAB80 WRITE   3105756\n0x400DABC0 WRITE   3105812\n0x40166700 WRITE   3105878\n0x401666C0 WRITE   3105880\n0x40166680 WRITE   3105887\n0x40166640 WRITE   3105889\n0x400DAC00 WRITE   3105922\n0x400DAC40 WRITE   3105978\n0x400DAC80 WRITE   3106052\n0x400DACC0 WRITE   3106108\n0x400DAD00 WRITE   3106203\n0x400DAD40 WRITE   3106259\n0x400DAD80 WRITE   3106330\n0x400DADC0 WRITE   3106386\n0x40166780 WRITE   3106456\n0x40166740 WRITE   3106458\n0x400DAE00 WRITE   3106494\n0x400DAE40 WRITE   3106550\n0x400DAE80 WRITE   3106621\n0x400DAEC0 WRITE   3106677\n0x400DAF00 WRITE   3106767\n0x400DAF40 WRITE   3106823\n0x400DAF80 WRITE   3106894\n0x400DAFC0 WRITE   3106950\n0x40166C00 WRITE   3107030\n0x40166BC0 WRITE   3107032\n0x40166A00 WRITE   3107039\n0x401669C0 WRITE   3107041\n0x40166900 WRITE   3107051\n0x401668C0 WRITE   3107053\n0x40166880 WRITE   3107058\n0x40166840 WRITE   3107061\n0x400DB000 WRITE   3107086\n0x400DB040 WRITE   3107170\n0x400DB080 WRITE   3107236\n0x400DB0C0 WRITE   3107292\n0x400DB100 WRITE   3107375\n0x400DB140 WRITE   3107431\n0x400DB180 WRITE   3107494\n0x400DB1C0 WRITE   3107550\n0x40166980 WRITE   3107614\n0x40166940 WRITE   3107616\n0x400DB200 WRITE   3107652\n0x400DB240 WRITE   3107708\n0x400DB280 WRITE   3107771\n0x400DB2C0 WRITE   3107827\n0x400DB300 WRITE   3107905\n0x400DB340 WRITE   3107961\n0x400DB380 WRITE   3108024\n0x400DB3C0 WRITE   3108080\n0x40166B00 WRITE   3108148\n0x40166AC0 WRITE   3108150\n0x40166A80 WRITE   3108157\n0x40166A40 WRITE   3108159\n0x400DB400 WRITE   3108192\n0x400DB440 WRITE   3108248\n0x400DB480 WRITE   3108322\n0x400DB4C0 WRITE   3108378\n0x400DB500 WRITE   3108469\n0x400DB540 WRITE   3108525\n0x400DB580 WRITE   3108596\n0x400DB5C0 WRITE   3108652\n0x40166B80 WRITE   3108724\n0x40166B40 WRITE   3108726\n0x400DB600 WRITE   3108762\n0x400DB640 WRITE   3108818\n0x400DB680 WRITE   3108889\n0x400DB6C0 WRITE   3108945\n0x400DB700 WRITE   3109031\n0x400DB740 WRITE   3109087\n0x400DB780 WRITE   3109158\n0x400DB7C0 WRITE   3109214\n0x40166E00 WRITE   3109291\n0x40166DC0 WRITE   3109293\n0x40166D00 WRITE   3109300\n0x40166CC0 WRITE   3109302\n0x40166C80 WRITE   3109312\n0x40166C40 WRITE   3109314\n0x400DB800 WRITE   3109341\n0x400DB840 WRITE   3109397\n0x400DB880 WRITE   3109463\n0x400DB8C0 WRITE   3109519\n0x400DB900 WRITE   3109606\n0x400DB940 WRITE   3109662\n0x400DB980 WRITE   3109725\n0x400DB9C0 WRITE   3109781\n0x40166D80 WRITE   3109850\n0x40166D40 WRITE   3109852\n0x400DBA00 WRITE   3109888\n0x400DBA40 WRITE   3109944\n0x400DBA80 WRITE   3110007\n0x400DBAC0 WRITE   3110063\n0x400DBB00 WRITE   3110145\n0x400DBB40 WRITE   3110201\n0x400DBB80 WRITE   3110264\n0x400DBBC0 WRITE   3110320\n0x40166F00 WRITE   3110393\n0x40166EC0 WRITE   3110395\n0x40166E80 WRITE   3110402\n0x40166E40 WRITE   3110404\n0x400DBC00 WRITE   3110437\n0x400DBC40 WRITE   3110493\n0x400DBC80 WRITE   3110567\n0x400DBCC0 WRITE   3110623\n0x400DBD00 WRITE   3110718\n0x400DBD40 WRITE   3110774\n0x400DBD80 WRITE   3110845\n0x400DBDC0 WRITE   3110901\n0x40166F80 WRITE   3110978\n0x40166F40 WRITE   3110980\n0x400DBE00 WRITE   3111016\n0x400DBE40 WRITE   3111072\n0x400DBE80 WRITE   3111143\n0x400DBEC0 WRITE   3111199\n0x400DBF00 WRITE   3111289\n0x400DBF40 WRITE   3111345\n0x400DBF80 WRITE   3111416\n0x400DBFC0 WRITE   3111472\n0x40167800 WRITE   3111558\n0x401677C0 WRITE   3111560\n0x40167400 WRITE   3111567\n0x401673C0 WRITE   3111569\n0x40167200 WRITE   3111579\n0x401671C0 WRITE   3111581\n0x40167100 WRITE   3111586\n0x401670C0 WRITE   3111589\n0x40167080 WRITE   3111592\n0x40167040 WRITE   3111595\n0x400DC000 WRITE   3111620\n0x400DC040 WRITE   3111704\n0x400DC080 WRITE   3111770\n0x400DC0C0 WRITE   3111826\n0x400DC100 WRITE   3111909\n0x400DC140 WRITE   3111965\n0x400DC180 WRITE   3112028\n0x400DC1C0 WRITE   3112084\n0x40167180 WRITE   3112140\n0x40167140 WRITE   3112142\n0x400DC200 WRITE   3112178\n0x400DC240 WRITE   3112234\n0x400DC280 WRITE   3112297\n0x400DC2C0 WRITE   3112353\n0x400DC300 WRITE   3112431\n0x400DC340 WRITE   3112487\n0x400DC380 WRITE   3112550\n0x400DC3C0 WRITE   3112606\n0x40167300 WRITE   3112672\n0x401672C0 WRITE   3112674\n0x40167280 WRITE   3112681\n0x40167240 WRITE   3112683\n0x400DC400 WRITE   3112716\n0x400DC440 WRITE   3112772\n0x400DC480 WRITE   3112846\n0x400DC4C0 WRITE   3112902\n0x400DC500 WRITE   3112993\n0x400DC540 WRITE   3113049\n0x400DC580 WRITE   3113120\n0x400DC5C0 WRITE   3113176\n0x40167380 WRITE   3113240\n0x40167340 WRITE   3113242\n0x400DC600 WRITE   3113278\n0x400DC640 WRITE   3113334\n0x400DC680 WRITE   3113405\n0x400DC6C0 WRITE   3113461\n0x400DC700 WRITE   3113547\n0x400DC740 WRITE   3113603\n0x400DC780 WRITE   3113674\n0x400DC7C0 WRITE   3113730\n0x40167600 WRITE   3113805\n0x401675C0 WRITE   3113807\n0x40167500 WRITE   3113814\n0x401674C0 WRITE   3113816\n0x40167480 WRITE   3113826\n0x40167440 WRITE   3113828\n0x400DC800 WRITE   3113855\n0x400DC840 WRITE   3113911\n0x400DC880 WRITE   3113977\n0x400DC8C0 WRITE   3114033\n0x400DC900 WRITE   3114120\n0x400DC940 WRITE   3114176\n0x400DC980 WRITE   3114239\n0x400DC9C0 WRITE   3114295\n0x40167580 WRITE   3114357\n0x40167540 WRITE   3114359\n0x400DCA00 WRITE   3114395\n0x400DCA40 WRITE   3114451\n0x400DCA80 WRITE   3114514\n0x400DCAC0 WRITE   3114570\n0x400DCB00 WRITE   3114652\n0x400DCB40 WRITE   3114708\n0x400DCB80 WRITE   3114771\n0x400DCBC0 WRITE   3114827\n0x40167700 WRITE   3114899\n0x401676C0 WRITE   3114901\n0x40167680 WRITE   3114908\n0x40167640 WRITE   3114910\n0x400DCC00 WRITE   3114943\n0x400DCC40 WRITE   3114999\n0x400DCC80 WRITE   3115073\n0x400DCCC0 WRITE   3115129\n0x400DCD00 WRITE   3115224\n0x400DCD40 WRITE   3115280\n0x400DCD80 WRITE   3115351\n0x400DCDC0 WRITE   3115407\n0x40167780 WRITE   3115477\n0x40167740 WRITE   3115479\n0x400DCE00 WRITE   3115515\n0x400DCE40 WRITE   3115571\n0x400DCE80 WRITE   3115642\n0x400DCEC0 WRITE   3115698\n0x400DCF00 WRITE   3115788\n0x400DCF40 WRITE   3115844\n0x400DCF80 WRITE   3115915\n0x400DCFC0 WRITE   3115971\n0x40167C00 WRITE   3116057\n0x40167BC0 WRITE   3116059\n0x40167A00 WRITE   3116066\n0x401679C0 WRITE   3116068\n0x40167900 WRITE   3116078\n0x401678C0 WRITE   3116080\n0x40167880 WRITE   3116085\n0x40167840 WRITE   3116088\n0x400DD000 WRITE   3116113\n0x400DD040 WRITE   3116197\n0x400DD080 WRITE   3116263\n0x400DD0C0 WRITE   3116319\n0x400DD100 WRITE   3116402\n0x400DD140 WRITE   3116458\n0x400DD180 WRITE   3116521\n0x400DD1C0 WRITE   3116577\n0x40167980 WRITE   3116641\n0x40167940 WRITE   3116643\n0x400DD200 WRITE   3116679\n0x400DD240 WRITE   3116735\n0x400DD280 WRITE   3116798\n0x400DD2C0 WRITE   3116854\n0x400DD300 WRITE   3116932\n0x400DD340 WRITE   3116988\n0x400DD380 WRITE   3117051\n0x400DD3C0 WRITE   3117107\n0x40167B00 WRITE   3117181\n0x40167AC0 WRITE   3117183\n0x40167A80 WRITE   3117190\n0x40167A40 WRITE   3117192\n0x400DD400 WRITE   3117225\n0x400DD440 WRITE   3117281\n0x400DD480 WRITE   3117355\n0x400DD4C0 WRITE   3117411\n0x400DD500 WRITE   3117502\n0x400DD540 WRITE   3117558\n0x400DD580 WRITE   3117629\n0x400DD5C0 WRITE   3117685\n0x40167B80 WRITE   3117757\n0x40167B40 WRITE   3117759\n0x400DD600 WRITE   3117795\n0x400DD640 WRITE   3117851\n0x400DD680 WRITE   3117922\n0x400DD6C0 WRITE   3117978\n0x400DD700 WRITE   3118064\n0x400DD740 WRITE   3118120\n0x400DD780 WRITE   3118191\n0x400DD7C0 WRITE   3118247\n0x40167E00 WRITE   3118330\n0x40167DC0 WRITE   3118332\n0x40167D00 WRITE   3118339\n0x40167CC0 WRITE   3118341\n0x40167C80 WRITE   3118351\n0x40167C40 WRITE   3118353\n0x400DD800 WRITE   3118380\n0x400DD840 WRITE   3118436\n0x400DD880 WRITE   3118502\n0x400DD8C0 WRITE   3118558\n0x400DD900 WRITE   3118645\n0x400DD940 WRITE   3118701\n0x400DD980 WRITE   3118764\n0x400DD9C0 WRITE   3118820\n0x40167D80 WRITE   3118889\n0x40167D40 WRITE   3118891\n0x400DDA00 WRITE   3118927\n0x400DDA40 WRITE   3118983\n0x400DDA80 WRITE   3119046\n0x400DDAC0 WRITE   3119102\n0x400DDB00 WRITE   3119184\n0x400DDB40 WRITE   3119240\n0x400DDB80 WRITE   3119303\n0x400DDBC0 WRITE   3119359\n0x40167F00 WRITE   3119438\n0x40167EC0 WRITE   3119440\n0x40167E80 WRITE   3119447\n0x40167E40 WRITE   3119449\n0x400DDC00 WRITE   3119482\n0x400DDC40 WRITE   3119538\n0x400DDC80 WRITE   3119612\n0x400DDCC0 WRITE   3119668\n0x400DDD00 WRITE   3119763\n0x400DDD40 WRITE   3119819\n0x400DDD80 WRITE   3119890\n0x400DDDC0 WRITE   3119946\n0x40167F80 WRITE   3120023\n0x40167F40 WRITE   3120025\n0x400DDE00 WRITE   3120061\n0x400DDE40 WRITE   3120117\n0x400DDE80 WRITE   3120188\n0x400DDEC0 WRITE   3120244\n0x400DDF00 WRITE   3120334\n0x400DDF40 WRITE   3120390\n0x400DDF80 WRITE   3120461\n0x400DDFC0 WRITE   3120517\n0x40169FC0 WRITE   3120679\n0x4016A000 WRITE   3120711\n0x40169000 WRITE   3120838\n0x40168FC0 WRITE   3120840\n0x40168800 WRITE   3120847\n0x401687C0 WRITE   3120849\n0x40168400 WRITE   3120859\n0x401683C0 WRITE   3120861\n0x40168200 WRITE   3120866\n0x401681C0 WRITE   3120869\n0x40168100 WRITE   3120872\n0x401680C0 WRITE   3120875\n0x40168080 WRITE   3120878\n0x40168040 WRITE   3120881\n0x400DE000 WRITE   3120913\n0x400DE040 WRITE   3121001\n0x400DE080 WRITE   3121067\n0x400DE0C0 WRITE   3121123\n0x400DE100 WRITE   3121206\n0x400DE140 WRITE   3121262\n0x400DE180 WRITE   3121325\n0x400DE1C0 WRITE   3121381\n0x40168180 WRITE   3121437\n0x40168140 WRITE   3121439\n0x400DE200 WRITE   3121475\n0x400DE240 WRITE   3121531\n0x400DE280 WRITE   3121594\n0x400DE2C0 WRITE   3121650\n0x400DE300 WRITE   3121728\n0x400DE340 WRITE   3121784\n0x400DE380 WRITE   3121847\n0x400DE3C0 WRITE   3121903\n0x40168300 WRITE   3121964\n0x401682C0 WRITE   3121966\n0x40168280 WRITE   3121973\n0x40168240 WRITE   3121975\n0x400DE400 WRITE   3122008\n0x400DE440 WRITE   3122064\n0x400DE480 WRITE   3122138\n0x400DE4C0 WRITE   3122194\n0x400DE500 WRITE   3122285\n0x400DE540 WRITE   3122341\n0x400DE580 WRITE   3122412\n0x400DE5C0 WRITE   3122468\n0x40168380 WRITE   3122532\n0x40168340 WRITE   3122534\n0x400DE600 WRITE   3122570\n0x400DE640 WRITE   3122626\n0x400DE680 WRITE   3122697\n0x400DE6C0 WRITE   3122753\n0x400DE700 WRITE   3122839\n0x400DE740 WRITE   3122895\n0x400DE780 WRITE   3122966\n0x400DE7C0 WRITE   3123022\n0x40168600 WRITE   3123091\n0x401685C0 WRITE   3123093\n0x40168500 WRITE   3123100\n0x401684C0 WRITE   3123102\n0x40168480 WRITE   3123112\n0x40168440 WRITE   3123114\n0x400DE800 WRITE   3123141\n0x400DE840 WRITE   3123197\n0x400DE880 WRITE   3123263\n0x400DE8C0 WRITE   3123319\n0x400DE900 WRITE   3123406\n0x400DE940 WRITE   3123462\n0x400DE980 WRITE   3123525\n0x400DE9C0 WRITE   3123581\n0x40168580 WRITE   3123643\n0x40168540 WRITE   3123645\n0x400DEA00 WRITE   3123681\n0x400DEA40 WRITE   3123737\n0x400DEA80 WRITE   3123800\n0x400DEAC0 WRITE   3123856\n0x400DEB00 WRITE   3123938\n0x400DEB40 WRITE   3123994\n0x400DEB80 WRITE   3124057\n0x400DEBC0 WRITE   3124113\n0x40168700 WRITE   3124179\n0x401686C0 WRITE   3124181\n0x40168680 WRITE   3124188\n0x40168640 WRITE   3124190\n0x400DEC00 WRITE   3124223\n0x400DEC40 WRITE   3124279\n0x400DEC80 WRITE   3124353\n0x400DECC0 WRITE   3124409\n0x400DED00 WRITE   3124504\n0x400DED40 WRITE   3124560\n0x400DED80 WRITE   3124631\n0x400DEDC0 WRITE   3124687\n0x40168780 WRITE   3124757\n0x40168740 WRITE   3124759\n0x400DEE00 WRITE   3124795\n0x400DEE40 WRITE   3124851\n0x400DEE80 WRITE   3124922\n0x400DEEC0 WRITE   3124978\n0x400DEF00 WRITE   3125068\n0x400DEF40 WRITE   3125124\n0x400DEF80 WRITE   3125195\n0x400DEFC0 WRITE   3125251\n0x40168C00 WRITE   3125331\n0x40168BC0 WRITE   3125333\n0x40168A00 WRITE   3125340\n0x401689C0 WRITE   3125342\n0x40168900 WRITE   3125352\n0x401688C0 WRITE   3125354\n0x40168880 WRITE   3125359\n0x40168840 WRITE   3125362\n0x400DF000 WRITE   3125387\n0x400DF040 WRITE   3125471\n0x400DF080 WRITE   3125537\n0x400DF0C0 WRITE   3125593\n0x400DF100 WRITE   3125676\n0x400DF140 WRITE   3125732\n0x400DF180 WRITE   3125795\n0x400DF1C0 WRITE   3125851\n0x40168980 WRITE   3125915\n0x40168940 WRITE   3125917\n0x400DF200 WRITE   3125953\n0x400DF240 WRITE   3126009\n0x400DF280 WRITE   3126072\n0x400DF2C0 WRITE   3126128\n0x400DF300 WRITE   3126206\n0x400DF340 WRITE   3126262\n0x400DF380 WRITE   3126325\n0x400DF3C0 WRITE   3126381\n0x40168B00 WRITE   3126449\n0x40168AC0 WRITE   3126451\n0x40168A80 WRITE   3126458\n0x40168A40 WRITE   3126460\n0x400DF400 WRITE   3126493\n0x400DF440 WRITE   3126549\n0x400DF480 WRITE   3126623\n0x400DF4C0 WRITE   3126679\n0x400DF500 WRITE   3126770\n0x400DF540 WRITE   3126826\n0x400DF580 WRITE   3126897\n0x400DF5C0 WRITE   3126953\n0x40168B80 WRITE   3127025\n0x40168B40 WRITE   3127027\n0x400DF600 WRITE   3127063\n0x400DF640 WRITE   3127119\n0x400DF680 WRITE   3127190\n0x400DF6C0 WRITE   3127246\n0x400DF700 WRITE   3127332\n0x400DF740 WRITE   3127388\n0x400DF780 WRITE   3127459\n0x400DF7C0 WRITE   3127515\n0x40168E00 WRITE   3127592\n0x40168DC0 WRITE   3127594\n0x40168D00 WRITE   3127601\n0x40168CC0 WRITE   3127603\n0x40168C80 WRITE   3127613\n0x40168C40 WRITE   3127615\n0x400DF800 WRITE   3127642\n0x400DF840 WRITE   3127698\n0x400DF880 WRITE   3127764\n0x400DF8C0 WRITE   3127820\n0x400DF900 WRITE   3127907\n0x400DF940 WRITE   3127963\n0x400DF980 WRITE   3128026\n0x400DF9C0 WRITE   3128082\n0x40168D80 WRITE   3128151\n0x40168D40 WRITE   3128153\n0x400DFA00 WRITE   3128189\n0x400DFA40 WRITE   3128245\n0x400DFA80 WRITE   3128308\n0x400DFAC0 WRITE   3128364\n0x400DFB00 WRITE   3128446\n0x400DFB40 WRITE   3128502\n0x400DFB80 WRITE   3128565\n0x400DFBC0 WRITE   3128621\n0x40168F00 WRITE   3128694\n0x40168EC0 WRITE   3128696\n0x40168E80 WRITE   3128703\n0x40168E40 WRITE   3128705\n0x400DFC00 WRITE   3128738\n0x400DFC40 WRITE   3128794\n0x400DFC80 WRITE   3128868\n0x400DFCC0 WRITE   3128924\n0x400DFD00 WRITE   3129019\n0x400DFD40 WRITE   3129075\n0x400DFD80 WRITE   3129146\n0x400DFDC0 WRITE   3129202\n0x40168F80 WRITE   3129279\n0x40168F40 WRITE   3129281\n0x400DFE00 WRITE   3129317\n0x400DFE40 WRITE   3129373\n0x400DFE80 WRITE   3129444\n0x400DFEC0 WRITE   3129500\n0x400DFF00 WRITE   3129590\n0x400DFF40 WRITE   3129646\n0x400DFF80 WRITE   3129717\n0x400DFFC0 WRITE   3129773\n0x40169800 WRITE   3129859\n0x401697C0 WRITE   3129861\n0x40169400 WRITE   3129868\n0x401693C0 WRITE   3129870\n0x40169200 WRITE   3129880\n0x401691C0 WRITE   3129882\n0x40169100 WRITE   3129887\n0x401690C0 WRITE   3129890\n0x40169080 WRITE   3129893\n0x40169040 WRITE   3129896\n0x400E0000 WRITE   3129921\n0x400E0040 WRITE   3130005\n0x400E0080 WRITE   3130071\n0x400E00C0 WRITE   3130127\n0x400E0100 WRITE   3130210\n0x400E0140 WRITE   3130266\n0x400E0180 WRITE   3130329\n0x400E01C0 WRITE   3130385\n0x40169180 WRITE   3130441\n0x40169140 WRITE   3130443\n0x400E0200 WRITE   3130479\n0x400E0240 WRITE   3130535\n0x400E0280 WRITE   3130598\n0x400E02C0 WRITE   3130654\n0x400E0300 WRITE   3130732\n0x400E0340 WRITE   3130788\n0x400E0380 WRITE   3130851\n0x400E03C0 WRITE   3130907\n0x40169300 WRITE   3130973\n0x401692C0 WRITE   3130975\n0x40169280 WRITE   3130982\n0x40169240 WRITE   3130984\n0x400E0400 WRITE   3131017\n0x400E0440 WRITE   3131073\n0x400E0480 WRITE   3131147\n0x400E04C0 WRITE   3131203\n0x400E0500 WRITE   3131294\n0x400E0540 WRITE   3131350\n0x400E0580 WRITE   3131421\n0x400E05C0 WRITE   3131477\n0x40169380 WRITE   3131541\n0x40169340 WRITE   3131543\n0x400E0600 WRITE   3131579\n0x400E0640 WRITE   3131635\n0x400E0680 WRITE   3131706\n0x400E06C0 WRITE   3131762\n0x400E0700 WRITE   3131848\n0x400E0740 WRITE   3131904\n0x400E0780 WRITE   3131975\n0x400E07C0 WRITE   3132031\n0x40169600 WRITE   3132106\n0x401695C0 WRITE   3132108\n0x40169500 WRITE   3132115\n0x401694C0 WRITE   3132117\n0x40169480 WRITE   3132127\n0x40169440 WRITE   3132129\n0x400E0800 WRITE   3132156\n0x400E0840 WRITE   3132212\n0x400E0880 WRITE   3132278\n0x400E08C0 WRITE   3132334\n0x400E0900 WRITE   3132421\n0x400E0940 WRITE   3132477\n0x400E0980 WRITE   3132540\n0x400E09C0 WRITE   3132596\n0x40169580 WRITE   3132658\n0x40169540 WRITE   3132660\n0x400E0A00 WRITE   3132696\n0x400E0A40 WRITE   3132752\n0x400E0A80 WRITE   3132815\n0x400E0AC0 WRITE   3132871\n0x400E0B00 WRITE   3132953\n0x400E0B40 WRITE   3133009\n0x400E0B80 WRITE   3133072\n0x400E0BC0 WRITE   3133128\n0x40169700 WRITE   3133200\n0x401696C0 WRITE   3133202\n0x40169680 WRITE   3133209\n0x40169640 WRITE   3133211\n0x400E0C00 WRITE   3133244\n0x400E0C40 WRITE   3133300\n0x400E0C80 WRITE   3133374\n0x400E0CC0 WRITE   3133430\n0x400E0D00 WRITE   3133525\n0x400E0D40 WRITE   3133581\n0x400E0D80 WRITE   3133652\n0x400E0DC0 WRITE   3133708\n0x40169780 WRITE   3133778\n0x40169740 WRITE   3133780\n0x400E0E00 WRITE   3133816\n0x400E0E40 WRITE   3133872\n0x400E0E80 WRITE   3133943\n0x400E0EC0 WRITE   3133999\n0x400E0F00 WRITE   3134089\n0x400E0F40 WRITE   3134145\n0x400E0F80 WRITE   3134216\n0x400E0FC0 WRITE   3134272\n0x40169C00 WRITE   3134358\n0x40169BC0 WRITE   3134360\n0x40169A00 WRITE   3134367\n0x401699C0 WRITE   3134369\n0x40169900 WRITE   3134379\n0x401698C0 WRITE   3134381\n0x40169880 WRITE   3134386\n0x40169840 WRITE   3134389\n0x400E1000 WRITE   3134414\n0x400E1040 WRITE   3134498\n0x400E1080 WRITE   3134564\n0x400E10C0 WRITE   3134620\n0x400E1100 WRITE   3134703\n0x400E1140 WRITE   3134759\n0x400E1180 WRITE   3134822\n0x400E11C0 WRITE   3134878\n0x40169980 WRITE   3134942\n0x40169940 WRITE   3134944\n0x400E1200 WRITE   3134980\n0x400E1240 WRITE   3135036\n0x400E1280 WRITE   3135099\n0x400E12C0 WRITE   3135155\n0x400E1300 WRITE   3135233\n0x400E1340 WRITE   3135289\n0x400E1380 WRITE   3135352\n0x400E13C0 WRITE   3135408\n0x40169B00 WRITE   3135482\n0x40169AC0 WRITE   3135484\n0x40169A80 WRITE   3135491\n0x40169A40 WRITE   3135493\n0x400E1400 WRITE   3135526\n0x400E1440 WRITE   3135582\n0x400E1480 WRITE   3135656\n0x400E14C0 WRITE   3135712\n0x400E1500 WRITE   3135803\n0x400E1540 WRITE   3135859\n0x400E1580 WRITE   3135930\n0x400E15C0 WRITE   3135986\n0x40169B80 WRITE   3136058\n0x40169B40 WRITE   3136060\n0x400E1600 WRITE   3136096\n0x400E1640 WRITE   3136152\n0x400E1680 WRITE   3136223\n0x400E16C0 WRITE   3136279\n0x400E1700 WRITE   3136365\n0x400E1740 WRITE   3136421\n0x400E1780 WRITE   3136492\n0x400E17C0 WRITE   3136548\n0x40169E00 WRITE   3136631\n0x40169DC0 WRITE   3136633\n0x40169D00 WRITE   3136640\n0x40169CC0 WRITE   3136642\n0x40169C80 WRITE   3136652\n0x40169C40 WRITE   3136654\n0x400E1800 WRITE   3136681\n0x400E1840 WRITE   3136737\n0x400E1880 WRITE   3136803\n0x400E18C0 WRITE   3136859\n0x400E1900 WRITE   3136946\n0x400E1940 WRITE   3137002\n0x400E1980 WRITE   3137065\n0x400E19C0 WRITE   3137121\n0x40169D80 WRITE   3137190\n0x40169D40 WRITE   3137192\n0x400E1A00 WRITE   3137228\n0x400E1A40 WRITE   3137284\n0x400E1A80 WRITE   3137347\n0x400E1AC0 WRITE   3137403\n0x400E1B00 WRITE   3137485\n0x400E1B40 WRITE   3137541\n0x400E1B80 WRITE   3137604\n0x400E1BC0 WRITE   3137660\n0x40169F00 WRITE   3137739\n0x40169EC0 WRITE   3137741\n0x40169E80 WRITE   3137748\n0x40169E40 WRITE   3137750\n0x400E1C00 WRITE   3137783\n0x400E1C40 WRITE   3137839\n0x400E1C80 WRITE   3137913\n0x400E1CC0 WRITE   3137969\n0x400E1D00 WRITE   3138064\n0x400E1D40 WRITE   3138120\n0x400E1D80 WRITE   3138191\n0x400E1DC0 WRITE   3138247\n0x40169F80 WRITE   3138324\n0x40169F40 WRITE   3138326\n0x400E1E00 WRITE   3138362\n0x400E1E40 WRITE   3138418\n0x400E1E80 WRITE   3138489\n0x400E1EC0 WRITE   3138545\n0x400E1F00 WRITE   3138635\n0x400E1F40 WRITE   3138691\n0x400E1F80 WRITE   3138762\n0x400E1FC0 WRITE   3138818\n0x4016BFC0 WRITE   3138980\n0x4016C000 WRITE   3139012\n0x4016B000 WRITE   3139155\n0x4016AFC0 WRITE   3139157\n0x4016A800 WRITE   3139164\n0x4016A7C0 WRITE   3139166\n0x4016A400 WRITE   3139176\n0x4016A3C0 WRITE   3139178\n0x4016A200 WRITE   3139183\n0x4016A1C0 WRITE   3139186\n0x4016A100 WRITE   3139189\n0x4016A0C0 WRITE   3139192\n0x4016A080 WRITE   3139195\n0x4016A040 WRITE   3139198\n0x400E2000 WRITE   3139230\n0x400E2040 WRITE   3139318\n0x400E2080 WRITE   3139384\n0x400E20C0 WRITE   3139440\n0x400E2100 WRITE   3139523\n0x400E2140 WRITE   3139579\n0x400E2180 WRITE   3139642\n0x400E21C0 WRITE   3139698\n0x4016A180 WRITE   3139754\n0x4016A140 WRITE   3139756\n0x400E2200 WRITE   3139792\n0x400E2240 WRITE   3139848\n0x400E2280 WRITE   3139911\n0x400E22C0 WRITE   3139967\n0x400E2300 WRITE   3140045\n0x400E2340 WRITE   3140101\n0x400E2380 WRITE   3140164\n0x400E23C0 WRITE   3140220\n0x4016A300 WRITE   3140281\n0x4016A2C0 WRITE   3140283\n0x4016A280 WRITE   3140290\n0x4016A240 WRITE   3140292\n0x400E2400 WRITE   3140325\n0x400E2440 WRITE   3140381\n0x400E2480 WRITE   3140455\n0x400E24C0 WRITE   3140511\n0x400E2500 WRITE   3140602\n0x400E2540 WRITE   3140658\n0x400E2580 WRITE   3140729\n0x400E25C0 WRITE   3140785\n0x4016A380 WRITE   3140849\n0x4016A340 WRITE   3140851\n0x400E2600 WRITE   3140887\n0x400E2640 WRITE   3140943\n0x400E2680 WRITE   3141014\n0x400E26C0 WRITE   3141070\n0x400E2700 WRITE   3141156\n0x400E2740 WRITE   3141212\n0x400E2780 WRITE   3141283\n0x400E27C0 WRITE   3141339\n0x4016A600 WRITE   3141408\n0x4016A5C0 WRITE   3141410\n0x4016A500 WRITE   3141417\n0x4016A4C0 WRITE   3141419\n0x4016A480 WRITE   3141429\n0x4016A440 WRITE   3141431\n0x400E2800 WRITE   3141458\n0x400E2840 WRITE   3141514\n0x400E2880 WRITE   3141580\n0x400E28C0 WRITE   3141636\n0x400E2900 WRITE   3141723\n0x400E2940 WRITE   3141779\n0x400E2980 WRITE   3141842\n0x400E29C0 WRITE   3141898\n0x4016A580 WRITE   3141960\n0x4016A540 WRITE   3141962\n0x400E2A00 WRITE   3141998\n0x400E2A40 WRITE   3142054\n0x400E2A80 WRITE   3142117\n0x400E2AC0 WRITE   3142173\n0x400E2B00 WRITE   3142255\n0x400E2B40 WRITE   3142311\n0x400E2B80 WRITE   3142374\n0x400E2BC0 WRITE   3142430\n0x4016A700 WRITE   3142496\n0x4016A6C0 WRITE   3142498\n0x4016A680 WRITE   3142505\n0x4016A640 WRITE   3142507\n0x400E2C00 WRITE   3142540\n0x400E2C40 WRITE   3142596\n0x400E2C80 WRITE   3142670\n0x400E2CC0 WRITE   3142726\n0x400E2D00 WRITE   3142821\n0x400E2D40 WRITE   3142877\n0x400E2D80 WRITE   3142948\n0x400E2DC0 WRITE   3143004\n0x4016A780 WRITE   3143074\n0x4016A740 WRITE   3143076\n0x400E2E00 WRITE   3143112\n0x400E2E40 WRITE   3143168\n0x400E2E80 WRITE   3143239\n0x400E2EC0 WRITE   3143295\n0x400E2F00 WRITE   3143385\n0x400E2F40 WRITE   3143441\n0x400E2F80 WRITE   3143512\n0x400E2FC0 WRITE   3143568\n0x4016AC00 WRITE   3143648\n0x4016ABC0 WRITE   3143650\n0x4016AA00 WRITE   3143657\n0x4016A9C0 WRITE   3143659\n0x4016A900 WRITE   3143669\n0x4016A8C0 WRITE   3143671\n0x4016A880 WRITE   3143676\n0x4016A840 WRITE   3143679\n0x400E3000 WRITE   3143704\n0x400E3040 WRITE   3143788\n0x400E3080 WRITE   3143854\n0x400E30C0 WRITE   3143910\n0x400E3100 WRITE   3143993\n0x400E3140 WRITE   3144049\n0x400E3180 WRITE   3144112\n0x400E31C0 WRITE   3144168\n0x4016A980 WRITE   3144232\n0x4016A940 WRITE   3144234\n0x400E3200 WRITE   3144270\n0x400E3240 WRITE   3144326\n0x400E3280 WRITE   3144389\n0x400E32C0 WRITE   3144445\n0x400E3300 WRITE   3144523\n0x400E3340 WRITE   3144579\n0x400E3380 WRITE   3144642\n0x400E33C0 WRITE   3144698\n0x4016AB00 WRITE   3144766\n0x4016AAC0 WRITE   3144768\n0x4016AA80 WRITE   3144775\n0x4016AA40 WRITE   3144777\n0x400E3400 WRITE   3144810\n0x400E3440 WRITE   3144866\n0x400E3480 WRITE   3144940\n0x400E34C0 WRITE   3144996\n0x400E3500 WRITE   3145087\n0x400E3540 WRITE   3145143\n0x400E3580 WRITE   3145214\n0x400E35C0 WRITE   3145270\n0x4016AB80 WRITE   3145342\n0x4016AB40 WRITE   3145344\n0x400E3600 WRITE   3145380\n0x400E3640 WRITE   3145436\n0x400E3680 WRITE   3145507\n0x400E36C0 WRITE   3145563\n0x400E3700 WRITE   3145649\n0x400E3740 WRITE   3145705\n0x400E3780 WRITE   3145776\n0x400E37C0 WRITE   3145832\n0x4016AE00 WRITE   3145909\n0x4016ADC0 WRITE   3145911\n0x4016AD00 WRITE   3145918\n0x4016ACC0 WRITE   3145920\n0x4016AC80 WRITE   3145930\n0x4016AC40 WRITE   3145932\n0x400E3800 WRITE   3145959\n0x400E3840 WRITE   3146015\n0x400E3880 WRITE   3146081\n0x400E38C0 WRITE   3146137\n0x400E3900 WRITE   3146224\n0x400E3940 WRITE   3146280\n0x400E3980 WRITE   3146343\n0x400E39C0 WRITE   3146399\n0x4016AD80 WRITE   3146468\n0x4016AD40 WRITE   3146470\n0x400E3A00 WRITE   3146506\n0x400E3A40 WRITE   3146562\n0x400E3A80 WRITE   3146625\n0x400E3AC0 WRITE   3146681\n0x400E3B00 WRITE   3146763\n0x400E3B40 WRITE   3146819\n0x400E3B80 WRITE   3146882\n0x400E3BC0 WRITE   3146938\n0x4016AF00 WRITE   3147011\n0x4016AEC0 WRITE   3147013\n0x4016AE80 WRITE   3147020\n0x4016AE40 WRITE   3147022\n0x400E3C00 WRITE   3147055\n0x400E3C40 WRITE   3147111\n0x400E3C80 WRITE   3147185\n0x400E3CC0 WRITE   3147241\n0x400E3D00 WRITE   3147336\n0x400E3D40 WRITE   3147392\n0x400E3D80 WRITE   3147463\n0x400E3DC0 WRITE   3147519\n0x4016AF80 WRITE   3147596\n0x4016AF40 WRITE   3147598\n0x400E3E00 WRITE   3147634\n0x400E3E40 WRITE   3147690\n0x400E3E80 WRITE   3147761\n0x400E3EC0 WRITE   3147817\n0x400E3F00 WRITE   3147907\n0x400E3F40 WRITE   3147963\n0x400E3F80 WRITE   3148034\n0x400E3FC0 WRITE   3148090\n0x4016B800 WRITE   3148176\n0x4016B7C0 WRITE   3148178\n0x4016B400 WRITE   3148185\n0x4016B3C0 WRITE   3148187\n0x4016B200 WRITE   3148197\n0x4016B1C0 WRITE   3148199\n0x4016B100 WRITE   3148204\n0x4016B0C0 WRITE   3148207\n0x4016B080 WRITE   3148210\n0x4016B040 WRITE   3148213\n0x400E4000 WRITE   3148238\n0x400E4040 WRITE   3148322\n0x400E4080 WRITE   3148388\n0x400E40C0 WRITE   3148444\n0x400E4100 WRITE   3148527\n0x400E4140 WRITE   3148583\n0x400E4180 WRITE   3148646\n0x400E41C0 WRITE   3148702\n0x4016B180 WRITE   3148758\n0x4016B140 WRITE   3148760\n0x400E4200 WRITE   3148796\n0x400E4240 WRITE   3148852\n0x400E4280 WRITE   3148915\n0x400E42C0 WRITE   3148971\n0x400E4300 WRITE   3149049\n0x400E4340 WRITE   3149105\n0x400E4380 WRITE   3149168\n0x400E43C0 WRITE   3149224\n0x4016B300 WRITE   3149290\n0x4016B2C0 WRITE   3149292\n0x4016B280 WRITE   3149299\n0x4016B240 WRITE   3149301\n0x400E4400 WRITE   3149334\n0x400E4440 WRITE   3149390\n0x400E4480 WRITE   3149464\n0x400E44C0 WRITE   3149520\n0x400E4500 WRITE   3149611\n0x400E4540 WRITE   3149667\n0x400E4580 WRITE   3149738\n0x400E45C0 WRITE   3149794\n0x4016B380 WRITE   3149858\n0x4016B340 WRITE   3149860\n0x400E4600 WRITE   3149896\n0x400E4640 WRITE   3149952\n0x400E4680 WRITE   3150023\n0x400E46C0 WRITE   3150079\n0x400E4700 WRITE   3150165\n0x400E4740 WRITE   3150221\n0x400E4780 WRITE   3150292\n0x400E47C0 WRITE   3150348\n0x4016B600 WRITE   3150423\n0x4016B5C0 WRITE   3150425\n0x4016B500 WRITE   3150432\n0x4016B4C0 WRITE   3150434\n0x4016B480 WRITE   3150444\n0x4016B440 WRITE   3150446\n0x400E4800 WRITE   3150473\n0x400E4840 WRITE   3150529\n0x400E4880 WRITE   3150595\n0x400E48C0 WRITE   3150651\n0x400E4900 WRITE   3150738\n0x400E4940 WRITE   3150794\n0x400E4980 WRITE   3150857\n0x400E49C0 WRITE   3150913\n0x4016B580 WRITE   3150975\n0x4016B540 WRITE   3150977\n0x400E4A00 WRITE   3151013\n0x400E4A40 WRITE   3151069\n0x400E4A80 WRITE   3151132\n0x400E4AC0 WRITE   3151188\n0x400E4B00 WRITE   3151270\n0x400E4B40 WRITE   3151326\n0x400E4B80 WRITE   3151389\n0x400E4BC0 WRITE   3151445\n0x4016B700 WRITE   3151517\n0x4016B6C0 WRITE   3151519\n0x4016B680 WRITE   3151526\n0x4016B640 WRITE   3151528\n0x400E4C00 WRITE   3151561\n0x400E4C40 WRITE   3151617\n0x400E4C80 WRITE   3151691\n0x400E4CC0 WRITE   3151747\n0x400E4D00 WRITE   3151842\n0x400E4D40 WRITE   3151898\n0x400E4D80 WRITE   3151969\n0x400E4DC0 WRITE   3152025\n0x4016B780 WRITE   3152095\n0x4016B740 WRITE   3152097\n0x400E4E00 WRITE   3152133\n0x400E4E40 WRITE   3152189\n0x400E4E80 WRITE   3152260\n0x400E4EC0 WRITE   3152316\n0x400E4F00 WRITE   3152406\n0x400E4F40 WRITE   3152462\n0x400E4F80 WRITE   3152533\n0x400E4FC0 WRITE   3152589\n0x4016BC00 WRITE   3152675\n0x4016BBC0 WRITE   3152677\n0x4016BA00 WRITE   3152684\n0x4016B9C0 WRITE   3152686\n0x4016B900 WRITE   3152696\n0x4016B8C0 WRITE   3152698\n0x4016B880 WRITE   3152703\n0x4016B840 WRITE   3152706\n0x400E5000 WRITE   3152731\n0x400E5040 WRITE   3152815\n0x400E5080 WRITE   3152881\n0x400E50C0 WRITE   3152937\n0x400E5100 WRITE   3153020\n0x400E5140 WRITE   3153076\n0x400E5180 WRITE   3153139\n0x400E51C0 WRITE   3153195\n0x4016B980 WRITE   3153259\n0x4016B940 WRITE   3153261\n0x400E5200 WRITE   3153297\n0x400E5240 WRITE   3153353\n0x400E5280 WRITE   3153416\n0x400E52C0 WRITE   3153472\n0x400E5300 WRITE   3153550\n0x400E5340 WRITE   3153606\n0x400E5380 WRITE   3153669\n0x400E53C0 WRITE   3153725\n0x4016BB00 WRITE   3153799\n0x4016BAC0 WRITE   3153801\n0x4016BA80 WRITE   3153808\n0x4016BA40 WRITE   3153810\n0x400E5400 WRITE   3153843\n0x400E5440 WRITE   3153899\n0x400E5480 WRITE   3153973\n0x400E54C0 WRITE   3154029\n0x400E5500 WRITE   3154120\n0x400E5540 WRITE   3154176\n0x400E5580 WRITE   3154247\n0x400E55C0 WRITE   3154303\n0x4016BB80 WRITE   3154375\n0x4016BB40 WRITE   3154377\n0x400E5600 WRITE   3154413\n0x400E5640 WRITE   3154469\n0x400E5680 WRITE   3154540\n0x400E56C0 WRITE   3154596\n0x400E5700 WRITE   3154682\n0x400E5740 WRITE   3154738\n0x400E5780 WRITE   3154809\n0x400E57C0 WRITE   3154865\n0x4016BE00 WRITE   3154948\n0x4016BDC0 WRITE   3154950\n0x4016BD00 WRITE   3154957\n0x4016BCC0 WRITE   3154959\n0x4016BC80 WRITE   3154969\n0x4016BC40 WRITE   3154971\n0x400E5800 WRITE   3154998\n0x400E5840 WRITE   3155054\n0x400E5880 WRITE   3155120\n0x400E58C0 WRITE   3155176\n0x400E5900 WRITE   3155263\n0x400E5940 WRITE   3155319\n0x400E5980 WRITE   3155382\n0x400E59C0 WRITE   3155438\n0x4016BD80 WRITE   3155507\n0x4016BD40 WRITE   3155509\n0x400E5A00 WRITE   3155545\n0x400E5A40 WRITE   3155601\n0x400E5A80 WRITE   3155664\n0x400E5AC0 WRITE   3155720\n0x400E5B00 WRITE   3155802\n0x400E5B40 WRITE   3155858\n0x400E5B80 WRITE   3155921\n0x400E5BC0 WRITE   3155977\n0x4016BF00 WRITE   3156056\n0x4016BEC0 WRITE   3156058\n0x4016BE80 WRITE   3156065\n0x4016BE40 WRITE   3156067\n0x400E5C00 WRITE   3156100\n0x400E5C40 WRITE   3156156\n0x400E5C80 WRITE   3156230\n0x400E5CC0 WRITE   3156286\n0x400E5D00 WRITE   3156381\n0x400E5D40 WRITE   3156437\n0x400E5D80 WRITE   3156508\n0x400E5DC0 WRITE   3156564\n0x4016BF80 WRITE   3156641\n0x4016BF40 WRITE   3156643\n0x400E5E00 WRITE   3156679\n0x400E5E40 WRITE   3156735\n0x400E5E80 WRITE   3156806\n0x400E5EC0 WRITE   3156862\n0x400E5F00 WRITE   3156952\n0x400E5F40 WRITE   3157008\n0x400E5F80 WRITE   3157079\n0x400E5FC0 WRITE   3157135\n0x4016DFC0 WRITE   3157297\n0x4016E000 WRITE   3157329\n0x4016D000 WRITE   3157456\n0x4016CFC0 WRITE   3157458\n0x4016C800 WRITE   3157465\n0x4016C7C0 WRITE   3157467\n0x4016C400 WRITE   3157477\n0x4016C3C0 WRITE   3157479\n0x4016C200 WRITE   3157484\n0x4016C1C0 WRITE   3157487\n0x4016C100 WRITE   3157490\n0x4016C0C0 WRITE   3157493\n0x4016C080 WRITE   3157496\n0x4016C040 WRITE   3157499\n0x400E6000 WRITE   3157531\n0x400E6040 WRITE   3157619\n0x400E6080 WRITE   3157685\n0x400E60C0 WRITE   3157741\n0x400E6100 WRITE   3157824\n0x400E6140 WRITE   3157880\n0x400E6180 WRITE   3157943\n0x400E61C0 WRITE   3157999\n0x4016C180 WRITE   3158055\n0x4016C140 WRITE   3158057\n0x400E6200 WRITE   3158093\n0x400E6240 WRITE   3158149\n0x400E6280 WRITE   3158212\n0x400E62C0 WRITE   3158268\n0x400E6300 WRITE   3158346\n0x400E6340 WRITE   3158402\n0x400E6380 WRITE   3158465\n0x400E63C0 WRITE   3158521\n0x4016C300 WRITE   3158582\n0x4016C2C0 WRITE   3158584\n0x4016C280 WRITE   3158591\n0x4016C240 WRITE   3158593\n0x400E6400 WRITE   3158626\n0x400E6440 WRITE   3158682\n0x400E6480 WRITE   3158756\n0x400E64C0 WRITE   3158812\n0x400E6500 WRITE   3158903\n0x400E6540 WRITE   3158959\n0x400E6580 WRITE   3159030\n0x400E65C0 WRITE   3159086\n0x4016C380 WRITE   3159150\n0x4016C340 WRITE   3159152\n0x400E6600 WRITE   3159188\n0x400E6640 WRITE   3159244\n0x400E6680 WRITE   3159315\n0x400E66C0 WRITE   3159371\n0x400E6700 WRITE   3159457\n0x400E6740 WRITE   3159513\n0x400E6780 WRITE   3159584\n0x400E67C0 WRITE   3159640\n0x4016C600 WRITE   3159709\n0x4016C5C0 WRITE   3159711\n0x4016C500 WRITE   3159718\n0x4016C4C0 WRITE   3159720\n0x4016C480 WRITE   3159730\n0x4016C440 WRITE   3159732\n0x400E6800 WRITE   3159759\n0x400E6840 WRITE   3159815\n0x400E6880 WRITE   3159881\n0x400E68C0 WRITE   3159937\n0x400E6900 WRITE   3160024\n0x400E6940 WRITE   3160080\n0x400E6980 WRITE   3160143\n0x400E69C0 WRITE   3160199\n0x4016C580 WRITE   3160261\n0x4016C540 WRITE   3160263\n0x400E6A00 WRITE   3160299\n0x400E6A40 WRITE   3160355\n0x400E6A80 WRITE   3160418\n0x400E6AC0 WRITE   3160474\n0x400E6B00 WRITE   3160556\n0x400E6B40 WRITE   3160612\n0x400E6B80 WRITE   3160675\n0x400E6BC0 WRITE   3160731\n0x4016C700 WRITE   3160797\n0x4016C6C0 WRITE   3160799\n0x4016C680 WRITE   3160806\n0x4016C640 WRITE   3160808\n0x400E6C00 WRITE   3160841\n0x400E6C40 WRITE   3160897\n0x400E6C80 WRITE   3160971\n0x400E6CC0 WRITE   3161027\n0x400E6D00 WRITE   3161122\n0x400E6D40 WRITE   3161178\n0x400E6D80 WRITE   3161249\n0x400E6DC0 WRITE   3161305\n0x4016C780 WRITE   3161375\n0x4016C740 WRITE   3161377\n0x400E6E00 WRITE   3161413\n0x400E6E40 WRITE   3161469\n0x400E6E80 WRITE   3161540\n0x400E6EC0 WRITE   3161596\n0x400E6F00 WRITE   3161686\n0x400E6F40 WRITE   3161742\n0x400E6F80 WRITE   3161813\n0x400E6FC0 WRITE   3161869\n0x4016CC00 WRITE   3161949\n0x4016CBC0 WRITE   3161951\n0x4016CA00 WRITE   3161958\n0x4016C9C0 WRITE   3161960\n0x4016C900 WRITE   3161970\n0x4016C8C0 WRITE   3161972\n0x4016C880 WRITE   3161977\n0x4016C840 WRITE   3161980\n0x400E7000 WRITE   3162005\n0x400E7040 WRITE   3162089\n0x400E7080 WRITE   3162155\n0x400E70C0 WRITE   3162211\n0x400E7100 WRITE   3162294\n0x400E7140 WRITE   3162350\n0x400E7180 WRITE   3162413\n0x400E71C0 WRITE   3162469\n0x4016C980 WRITE   3162533\n0x4016C940 WRITE   3162535\n0x400E7200 WRITE   3162571\n0x400E7240 WRITE   3162627\n0x400E7280 WRITE   3162690\n0x400E72C0 WRITE   3162746\n0x400E7300 WRITE   3162824\n0x400E7340 WRITE   3162880\n0x400E7380 WRITE   3162943\n0x400E73C0 WRITE   3162999\n0x4016CB00 WRITE   3163067\n0x4016CAC0 WRITE   3163069\n0x4016CA80 WRITE   3163076\n0x4016CA40 WRITE   3163078\n0x400E7400 WRITE   3163111\n0x400E7440 WRITE   3163167\n0x400E7480 WRITE   3163241\n0x400E74C0 WRITE   3163297\n0x400E7500 WRITE   3163388\n0x400E7540 WRITE   3163444\n0x400E7580 WRITE   3163515\n0x400E75C0 WRITE   3163571\n0x4016CB80 WRITE   3163643\n0x4016CB40 WRITE   3163645\n0x400E7600 WRITE   3163681\n0x400E7640 WRITE   3163737\n0x400E7680 WRITE   3163808\n0x400E76C0 WRITE   3163864\n0x400E7700 WRITE   3163950\n0x400E7740 WRITE   3164006\n0x400E7780 WRITE   3164077\n0x400E77C0 WRITE   3164133\n0x4016CE00 WRITE   3164210\n0x4016CDC0 WRITE   3164212\n0x4016CD00 WRITE   3164219\n0x4016CCC0 WRITE   3164221\n0x4016CC80 WRITE   3164231\n0x4016CC40 WRITE   3164233\n0x400E7800 WRITE   3164260\n0x400E7840 WRITE   3164316\n0x400E7880 WRITE   3164382\n0x400E78C0 WRITE   3164438\n0x400E7900 WRITE   3164525\n0x400E7940 WRITE   3164581\n0x400E7980 WRITE   3164644\n0x400E79C0 WRITE   3164700\n0x4016CD80 WRITE   3164769\n0x4016CD40 WRITE   3164771\n0x400E7A00 WRITE   3164807\n0x400E7A40 WRITE   3164863\n0x400E7A80 WRITE   3164926\n0x400E7AC0 WRITE   3164982\n0x400E7B00 WRITE   3165064\n0x400E7B40 WRITE   3165120\n0x400E7B80 WRITE   3165183\n0x400E7BC0 WRITE   3165239\n0x4016CF00 WRITE   3165312\n0x4016CEC0 WRITE   3165314\n0x4016CE80 WRITE   3165321\n0x4016CE40 WRITE   3165323\n0x400E7C00 WRITE   3165356\n0x400E7C40 WRITE   3165412\n0x400E7C80 WRITE   3165486\n0x400E7CC0 WRITE   3165542\n0x400E7D00 WRITE   3165637\n0x400E7D40 WRITE   3165693\n0x400E7D80 WRITE   3165764\n0x400E7DC0 WRITE   3165820\n0x4016CF80 WRITE   3165897\n0x4016CF40 WRITE   3165899\n0x400E7E00 WRITE   3165935\n0x400E7E40 WRITE   3165991\n0x400E7E80 WRITE   3166062\n0x400E7EC0 WRITE   3166118\n0x400E7F00 WRITE   3166208\n0x400E7F40 WRITE   3166264\n0x400E7F80 WRITE   3166335\n0x400E7FC0 WRITE   3166391\n0x4016D800 WRITE   3166477\n0x4016D7C0 WRITE   3166479\n0x4016D400 WRITE   3166486\n0x4016D3C0 WRITE   3166488\n0x4016D200 WRITE   3166498\n0x4016D1C0 WRITE   3166500\n0x4016D100 WRITE   3166505\n0x4016D0C0 WRITE   3166508\n0x4016D080 WRITE   3166511\n0x4016D040 WRITE   3166514\n0x400E8000 WRITE   3166539\n0x400E8040 WRITE   3166623\n0x400E8080 WRITE   3166689\n0x400E80C0 WRITE   3166745\n0x400E8100 WRITE   3166828\n0x400E8140 WRITE   3166884\n0x400E8180 WRITE   3166947\n0x400E81C0 WRITE   3167003\n0x4016D180 WRITE   3167059\n0x4016D140 WRITE   3167061\n0x400E8200 WRITE   3167097\n0x400E8240 WRITE   3167153\n0x400E8280 WRITE   3167216\n0x400E82C0 WRITE   3167272\n0x400E8300 WRITE   3167350\n0x400E8340 WRITE   3167406\n0x400E8380 WRITE   3167469\n0x400E83C0 WRITE   3167525\n0x4016D300 WRITE   3167591\n0x4016D2C0 WRITE   3167593\n0x4016D280 WRITE   3167600\n0x4016D240 WRITE   3167602\n0x400E8400 WRITE   3167635\n0x400E8440 WRITE   3167691\n0x400E8480 WRITE   3167765\n0x400E84C0 WRITE   3167821\n0x400E8500 WRITE   3167912\n0x400E8540 WRITE   3167968\n0x400E8580 WRITE   3168039\n0x400E85C0 WRITE   3168095\n0x4016D380 WRITE   3168159\n0x4016D340 WRITE   3168161\n0x400E8600 WRITE   3168197\n0x400E8640 WRITE   3168253\n0x400E8680 WRITE   3168324\n0x400E86C0 WRITE   3168380\n0x400E8700 WRITE   3168466\n0x400E8740 WRITE   3168522\n0x400E8780 WRITE   3168593\n0x400E87C0 WRITE   3168649\n0x4016D600 WRITE   3168724\n0x4016D5C0 WRITE   3168726\n0x4016D500 WRITE   3168733\n0x4016D4C0 WRITE   3168735\n0x4016D480 WRITE   3168745\n0x4016D440 WRITE   3168747\n0x400E8800 WRITE   3168774\n0x400E8840 WRITE   3168830\n0x400E8880 WRITE   3168896\n0x400E88C0 WRITE   3168952\n0x400E8900 WRITE   3169039\n0x400E8940 WRITE   3169095\n0x400E8980 WRITE   3169158\n0x400E89C0 WRITE   3169214\n0x4016D580 WRITE   3169276\n0x4016D540 WRITE   3169278\n0x400E8A00 WRITE   3169314\n0x400E8A40 WRITE   3169370\n0x400E8A80 WRITE   3169433\n0x400E8AC0 WRITE   3169489\n0x400E8B00 WRITE   3169571\n0x400E8B40 WRITE   3169627\n0x400E8B80 WRITE   3169690\n0x400E8BC0 WRITE   3169746\n0x4016D700 WRITE   3169818\n0x4016D6C0 WRITE   3169820\n0x4016D680 WRITE   3169827\n0x4016D640 WRITE   3169829\n0x400E8C00 WRITE   3169862\n0x400E8C40 WRITE   3169918\n0x400E8C80 WRITE   3169992\n0x400E8CC0 WRITE   3170048\n0x400E8D00 WRITE   3170143\n0x400E8D40 WRITE   3170199\n0x400E8D80 WRITE   3170270\n0x400E8DC0 WRITE   3170326\n0x4016D780 WRITE   3170396\n0x4016D740 WRITE   3170398\n0x400E8E00 WRITE   3170434\n0x400E8E40 WRITE   3170490\n0x400E8E80 WRITE   3170561\n0x400E8EC0 WRITE   3170617\n0x400E8F00 WRITE   3170707\n0x400E8F40 WRITE   3170763\n0x400E8F80 WRITE   3170834\n0x400E8FC0 WRITE   3170890\n0x4016DC00 WRITE   3170976\n0x4016DBC0 WRITE   3170978\n0x4016DA00 WRITE   3170985\n0x4016D9C0 WRITE   3170987\n0x4016D900 WRITE   3170997\n0x4016D8C0 WRITE   3170999\n0x4016D880 WRITE   3171004\n0x4016D840 WRITE   3171007\n0x400E9000 WRITE   3171032\n0x400E9040 WRITE   3171116\n0x400E9080 WRITE   3171182\n0x400E90C0 WRITE   3171238\n0x400E9100 WRITE   3171321\n0x400E9140 WRITE   3171377\n0x400E9180 WRITE   3171440\n0x400E91C0 WRITE   3171496\n0x4016D980 WRITE   3171560\n0x4016D940 WRITE   3171562\n0x400E9200 WRITE   3171598\n0x400E9240 WRITE   3171654\n0x400E9280 WRITE   3171717\n0x400E92C0 WRITE   3171773\n0x400E9300 WRITE   3171851\n0x400E9340 WRITE   3171907\n0x400E9380 WRITE   3171970\n0x400E93C0 WRITE   3172026\n0x4016DB00 WRITE   3172100\n0x4016DAC0 WRITE   3172102\n0x4016DA80 WRITE   3172109\n0x4016DA40 WRITE   3172111\n0x400E9400 WRITE   3172144\n0x400E9440 WRITE   3172200\n0x400E9480 WRITE   3172274\n0x400E94C0 WRITE   3172330\n0x400E9500 WRITE   3172421\n0x400E9540 WRITE   3172477\n0x400E9580 WRITE   3172548\n0x400E95C0 WRITE   3172604\n0x4016DB80 WRITE   3172676\n0x4016DB40 WRITE   3172678\n0x400E9600 WRITE   3172714\n0x400E9640 WRITE   3172770\n0x400E9680 WRITE   3172841\n0x400E96C0 WRITE   3172897\n0x400E9700 WRITE   3172983\n0x400E9740 WRITE   3173039\n0x400E9780 WRITE   3173110\n0x400E97C0 WRITE   3173166\n0x4016DE00 WRITE   3173249\n0x4016DDC0 WRITE   3173251\n0x4016DD00 WRITE   3173258\n0x4016DCC0 WRITE   3173260\n0x4016DC80 WRITE   3173270\n0x4016DC40 WRITE   3173272\n0x400E9800 WRITE   3173299\n0x400E9840 WRITE   3173355\n0x400E9880 WRITE   3173421\n0x400E98C0 WRITE   3173477\n0x400E9900 WRITE   3173564\n0x400E9940 WRITE   3173620\n0x400E9980 WRITE   3173683\n0x400E99C0 WRITE   3173739\n0x4016DD80 WRITE   3173808\n0x4016DD40 WRITE   3173810\n0x400E9A00 WRITE   3173846\n0x400E9A40 WRITE   3173902\n0x400E9A80 WRITE   3173965\n0x400E9AC0 WRITE   3174021\n0x400E9B00 WRITE   3174103\n0x400E9B40 WRITE   3174159\n0x400E9B80 WRITE   3174222\n0x400E9BC0 WRITE   3174278\n0x4016DF00 WRITE   3174357\n0x4016DEC0 WRITE   3174359\n0x4016DE80 WRITE   3174366\n0x4016DE40 WRITE   3174368\n0x400E9C00 WRITE   3174401\n0x400E9C40 WRITE   3174457\n0x400E9C80 WRITE   3174531\n0x400E9CC0 WRITE   3174587\n0x400E9D00 WRITE   3174682\n0x400E9D40 WRITE   3174738\n0x400E9D80 WRITE   3174809\n0x400E9DC0 WRITE   3174865\n0x4016DF80 WRITE   3174942\n0x4016DF40 WRITE   3174944\n0x400E9E00 WRITE   3174980\n0x400E9E40 WRITE   3175036\n0x400E9E80 WRITE   3175107\n0x400E9EC0 WRITE   3175163\n0x400E9F00 WRITE   3175253\n0x400E9F40 WRITE   3175309\n0x400E9F80 WRITE   3175380\n0x400E9FC0 WRITE   3175436\n0x4016FFC0 WRITE   3175598\n0x40170000 WRITE   3175630\n0x4016F000 WRITE   3175757\n0x4016EFC0 WRITE   3175759\n0x4016E800 WRITE   3175766\n0x4016E7C0 WRITE   3175768\n0x4016E400 WRITE   3175778\n0x4016E3C0 WRITE   3175780\n0x4016E200 WRITE   3175785\n0x4016E1C0 WRITE   3175788\n0x4016E100 WRITE   3175791\n0x4016E0C0 WRITE   3175794\n0x4016E080 WRITE   3175797\n0x4016E040 WRITE   3175800\n0x400EA000 WRITE   3175832\n0x400EA040 WRITE   3175920\n0x400EA080 WRITE   3175986\n0x400EA0C0 WRITE   3176042\n0x400EA100 WRITE   3176125\n0x400EA140 WRITE   3176181\n0x400EA180 WRITE   3176244\n0x400EA1C0 WRITE   3176300\n0x4016E180 WRITE   3176356\n0x4016E140 WRITE   3176358\n0x400EA200 WRITE   3176394\n0x400EA240 WRITE   3176450\n0x400EA280 WRITE   3176513\n0x400EA2C0 WRITE   3176569\n0x400EA300 WRITE   3176647\n0x400EA340 WRITE   3176703\n0x400EA380 WRITE   3176766\n0x400EA3C0 WRITE   3176822\n0x4016E300 WRITE   3176883\n0x4016E2C0 WRITE   3176885\n0x4016E280 WRITE   3176892\n0x4016E240 WRITE   3176894\n0x400EA400 WRITE   3176927\n0x400EA440 WRITE   3176983\n0x400EA480 WRITE   3177057\n0x400EA4C0 WRITE   3177113\n0x400EA500 WRITE   3177204\n0x400EA540 WRITE   3177260\n0x400EA580 WRITE   3177331\n0x400EA5C0 WRITE   3177387\n0x4016E380 WRITE   3177451\n0x4016E340 WRITE   3177453\n0x400EA600 WRITE   3177489\n0x400EA640 WRITE   3177545\n0x400EA680 WRITE   3177616\n0x400EA6C0 WRITE   3177672\n0x400EA700 WRITE   3177758\n0x400EA740 WRITE   3177814\n0x400EA780 WRITE   3177885\n0x400EA7C0 WRITE   3177941\n0x4016E600 WRITE   3178010\n0x4016E5C0 WRITE   3178012\n0x4016E500 WRITE   3178019\n0x4016E4C0 WRITE   3178021\n0x4016E480 WRITE   3178031\n0x4016E440 WRITE   3178033\n0x400EA800 WRITE   3178060\n0x400EA840 WRITE   3178116\n0x400EA880 WRITE   3178182\n0x400EA8C0 WRITE   3178238\n0x400EA900 WRITE   3178325\n0x400EA940 WRITE   3178381\n0x400EA980 WRITE   3178444\n0x400EA9C0 WRITE   3178500\n0x4016E580 WRITE   3178562\n0x4016E540 WRITE   3178564\n0x400EAA00 WRITE   3178600\n0x400EAA40 WRITE   3178656\n0x400EAA80 WRITE   3178719\n0x400EAAC0 WRITE   3178775\n0x400EAB00 WRITE   3178857\n0x400EAB40 WRITE   3178913\n0x400EAB80 WRITE   3178976\n0x400EABC0 WRITE   3179032\n0x4016E700 WRITE   3179098\n0x4016E6C0 WRITE   3179100\n0x4016E680 WRITE   3179107\n0x4016E640 WRITE   3179109\n0x400EAC00 WRITE   3179142\n0x400EAC40 WRITE   3179198\n0x400EAC80 WRITE   3179272\n0x400EACC0 WRITE   3179328\n0x400EAD00 WRITE   3179423\n0x400EAD40 WRITE   3179479\n0x400EAD80 WRITE   3179550\n0x400EADC0 WRITE   3179606\n0x4016E780 WRITE   3179676\n0x4016E740 WRITE   3179678\n0x400EAE00 WRITE   3179714\n0x400EAE40 WRITE   3179770\n0x400EAE80 WRITE   3179841\n0x400EAEC0 WRITE   3179897\n0x400EAF00 WRITE   3179987\n0x400EAF40 WRITE   3180043\n0x400EAF80 WRITE   3180114\n0x400EAFC0 WRITE   3180170\n0x4016EC00 WRITE   3180250\n0x4016EBC0 WRITE   3180252\n0x4016EA00 WRITE   3180259\n0x4016E9C0 WRITE   3180261\n0x4016E900 WRITE   3180271\n0x4016E8C0 WRITE   3180273\n0x4016E880 WRITE   3180278\n0x4016E840 WRITE   3180281\n0x400EB000 WRITE   3180306\n0x400EB040 WRITE   3180390\n0x400EB080 WRITE   3180456\n0x400EB0C0 WRITE   3180512\n0x400EB100 WRITE   3180595\n0x400EB140 WRITE   3180651\n0x400EB180 WRITE   3180714\n0x400EB1C0 WRITE   3180770\n0x4016E980 WRITE   3180834\n0x4016E940 WRITE   3180836\n0x400EB200 WRITE   3180872\n0x400EB240 WRITE   3180928\n0x400EB280 WRITE   3180991\n0x400EB2C0 WRITE   3181047\n0x400EB300 WRITE   3181125\n0x400EB340 WRITE   3181181\n0x400EB380 WRITE   3181244\n0x400EB3C0 WRITE   3181300\n0x4016EB00 WRITE   3181368\n0x4016EAC0 WRITE   3181370\n0x4016EA80 WRITE   3181377\n0x4016EA40 WRITE   3181379\n0x400EB400 WRITE   3181412\n0x400EB440 WRITE   3181468\n0x400EB480 WRITE   3181542\n0x400EB4C0 WRITE   3181598\n0x400EB500 WRITE   3181689\n0x400EB540 WRITE   3181745\n0x400EB580 WRITE   3181816\n0x400EB5C0 WRITE   3181872\n0x4016EB80 WRITE   3181944\n0x4016EB40 WRITE   3181946\n0x400EB600 WRITE   3181982\n0x400EB640 WRITE   3182038\n0x400EB680 WRITE   3182109\n0x400EB6C0 WRITE   3182165\n0x400EB700 WRITE   3182251\n0x400EB740 WRITE   3182307\n0x400EB780 WRITE   3182378\n0x400EB7C0 WRITE   3182434\n0x4016EE00 WRITE   3182511\n0x4016EDC0 WRITE   3182513\n0x4016ED00 WRITE   3182520\n0x4016ECC0 WRITE   3182522\n0x4016EC80 WRITE   3182532\n0x4016EC40 WRITE   3182534\n0x400EB800 WRITE   3182561\n0x400EB840 WRITE   3182617\n0x400EB880 WRITE   3182683\n0x400EB8C0 WRITE   3182739\n0x400EB900 WRITE   3182826\n0x400EB940 WRITE   3182882\n0x400EB980 WRITE   3182945\n0x400EB9C0 WRITE   3183001\n0x4016ED80 WRITE   3183070\n0x4016ED40 WRITE   3183072\n0x400EBA00 WRITE   3183108\n0x400EBA40 WRITE   3183164\n0x400EBA80 WRITE   3183227\n0x400EBAC0 WRITE   3183283\n0x400EBB00 WRITE   3183365\n0x400EBB40 WRITE   3183421\n0x400EBB80 WRITE   3183484\n0x400EBBC0 WRITE   3183540\n0x4016EF00 WRITE   3183613\n0x4016EEC0 WRITE   3183615\n0x4016EE80 WRITE   3183622\n0x4016EE40 WRITE   3183624\n0x400EBC00 WRITE   3183657\n0x400EBC40 WRITE   3183713\n0x400EBC80 WRITE   3183787\n0x400EBCC0 WRITE   3183843\n0x400EBD00 WRITE   3183938\n0x400EBD40 WRITE   3183994\n0x400EBD80 WRITE   3184065\n0x400EBDC0 WRITE   3184121\n0x4016EF80 WRITE   3184198\n0x4016EF40 WRITE   3184200\n0x400EBE00 WRITE   3184236\n0x400EBE40 WRITE   3184292\n0x400EBE80 WRITE   3184363\n0x400EBEC0 WRITE   3184419\n0x400EBF00 WRITE   3184509\n0x400EBF40 WRITE   3184565\n0x400EBF80 WRITE   3184636\n0x400EBFC0 WRITE   3184692\n0x4016F800 WRITE   3184778\n0x4016F7C0 WRITE   3184780\n0x4016F400 WRITE   3184787\n0x4016F3C0 WRITE   3184789\n0x4016F200 WRITE   3184799\n0x4016F1C0 WRITE   3184801\n0x4016F100 WRITE   3184806\n0x4016F0C0 WRITE   3184809\n0x4016F080 WRITE   3184812\n0x4016F040 WRITE   3184815\n0x400EC000 WRITE   3184840\n0x400EC040 WRITE   3184924\n0x400EC080 WRITE   3184990\n0x400EC0C0 WRITE   3185046\n0x400EC100 WRITE   3185129\n0x400EC140 WRITE   3185185\n0x400EC180 WRITE   3185248\n0x400EC1C0 WRITE   3185304\n0x4016F180 WRITE   3185360\n0x4016F140 WRITE   3185362\n0x400EC200 WRITE   3185398\n0x400EC240 WRITE   3185454\n0x400EC280 WRITE   3185517\n0x400EC2C0 WRITE   3185573\n0x400EC300 WRITE   3185651\n0x400EC340 WRITE   3185707\n0x400EC380 WRITE   3185770\n0x400EC3C0 WRITE   3185826\n0x4016F300 WRITE   3185892\n0x4016F2C0 WRITE   3185894\n0x4016F280 WRITE   3185901\n0x4016F240 WRITE   3185903\n0x400EC400 WRITE   3185936\n0x400EC440 WRITE   3185992\n0x400EC480 WRITE   3186066\n0x400EC4C0 WRITE   3186122\n0x400EC500 WRITE   3186213\n0x400EC540 WRITE   3186269\n0x400EC580 WRITE   3186340\n0x400EC5C0 WRITE   3186396\n0x4016F380 WRITE   3186460\n0x4016F340 WRITE   3186462\n0x400EC600 WRITE   3186498\n0x400EC640 WRITE   3186554\n0x400EC680 WRITE   3186625\n0x400EC6C0 WRITE   3186681\n0x400EC700 WRITE   3186767\n0x400EC740 WRITE   3186823\n0x400EC780 WRITE   3186894\n0x400EC7C0 WRITE   3186950\n0x4016F600 WRITE   3187025\n0x4016F5C0 WRITE   3187027\n0x4016F500 WRITE   3187034\n0x4016F4C0 WRITE   3187036\n0x4016F480 WRITE   3187046\n0x4016F440 WRITE   3187048\n0x400EC800 WRITE   3187075\n0x400EC840 WRITE   3187131\n0x400EC880 WRITE   3187197\n0x400EC8C0 WRITE   3187253\n0x400EC900 WRITE   3187340\n0x400EC940 WRITE   3187396\n0x400EC980 WRITE   3187459\n0x400EC9C0 WRITE   3187515\n0x4016F580 WRITE   3187577\n0x4016F540 WRITE   3187579\n0x400ECA00 WRITE   3187615\n0x400ECA40 WRITE   3187671\n0x400ECA80 WRITE   3187734\n0x400ECAC0 WRITE   3187790\n0x400ECB00 WRITE   3187872\n0x400ECB40 WRITE   3187928\n0x400ECB80 WRITE   3187991\n0x400ECBC0 WRITE   3188047\n0x4016F700 WRITE   3188119\n0x4016F6C0 WRITE   3188121\n0x4016F680 WRITE   3188128\n0x4016F640 WRITE   3188130\n0x400ECC00 WRITE   3188163\n0x400ECC40 WRITE   3188219\n0x400ECC80 WRITE   3188293\n0x400ECCC0 WRITE   3188349\n0x400ECD00 WRITE   3188444\n0x400ECD40 WRITE   3188500\n0x400ECD80 WRITE   3188571\n0x400ECDC0 WRITE   3188627\n0x4016F780 WRITE   3188697\n0x4016F740 WRITE   3188699\n0x400ECE00 WRITE   3188735\n0x400ECE40 WRITE   3188791\n0x400ECE80 WRITE   3188862\n0x400ECEC0 WRITE   3188918\n0x400ECF00 WRITE   3189008\n0x400ECF40 WRITE   3189064\n0x400ECF80 WRITE   3189135\n0x400ECFC0 WRITE   3189191\n0x4016FC00 WRITE   3189277\n0x4016FBC0 WRITE   3189279\n0x4016FA00 WRITE   3189286\n0x4016F9C0 WRITE   3189288\n0x4016F900 WRITE   3189298\n0x4016F8C0 WRITE   3189300\n0x4016F880 WRITE   3189305\n0x4016F840 WRITE   3189397\n0x400ED000 WRITE   3189437\n0x400ED040 WRITE   3189505\n0x400ED080 WRITE   3189571\n0x400ED0C0 WRITE   3189627\n0x400ED100 WRITE   3189710\n0x400ED140 WRITE   3189766\n0x400ED180 WRITE   3189829\n0x400ED1C0 WRITE   3189885\n0x4016F980 WRITE   3189949\n0x4016F940 WRITE   3189951\n0x400ED200 WRITE   3189987\n0x400ED240 WRITE   3190043\n0x400ED280 WRITE   3190106\n0x400ED2C0 WRITE   3190162\n0x400ED300 WRITE   3190240\n0x400ED340 WRITE   3190296\n0x400ED380 WRITE   3190359\n0x400ED3C0 WRITE   3190415\n0x4016FB00 WRITE   3190489\n0x4016FAC0 WRITE   3190491\n0x4016FA80 WRITE   3190498\n0x4016FA40 WRITE   3190500\n0x400ED400 WRITE   3190533\n0x400ED440 WRITE   3190589\n0x400ED480 WRITE   3190663\n0x400ED4C0 WRITE   3190719\n0x400ED500 WRITE   3190810\n0x400ED540 WRITE   3190866\n0x400ED580 WRITE   3190937\n0x400ED5C0 WRITE   3190993\n0x4016FB80 WRITE   3191065\n0x4016FB40 WRITE   3191067\n0x400ED600 WRITE   3191103\n0x400ED640 WRITE   3191159\n0x400ED680 WRITE   3191230\n0x400ED6C0 WRITE   3191286\n0x400ED700 WRITE   3191372\n0x400ED740 WRITE   3191428\n0x400ED780 WRITE   3191499\n0x400ED7C0 WRITE   3191555\n0x4016FE00 WRITE   3191638\n0x4016FDC0 WRITE   3191640\n0x4016FD00 WRITE   3191647\n0x4016FCC0 WRITE   3191649\n0x4016FC80 WRITE   3191659\n0x4016FC40 WRITE   3191661\n0x400ED800 WRITE   3191688\n0x400ED840 WRITE   3191777\n0x400ED880 WRITE   3191841\n0x400ED8C0 WRITE   3191897\n0x400ED900 WRITE   3191984\n0x400ED940 WRITE   3192040\n0x400ED980 WRITE   3192103\n0x400ED9C0 WRITE   3192159\n0x4016FD80 WRITE   3192228\n0x4016FD40 WRITE   3192230\n0x400EDA00 WRITE   3192266\n0x400EDA40 WRITE   3192322\n0x400EDA80 WRITE   3192385\n0x400EDAC0 WRITE   3192441\n0x400EDB00 WRITE   3192523\n0x400EDB40 WRITE   3192579\n0x400EDB80 WRITE   3192642\n0x400EDBC0 WRITE   3192698\n0x4016FF00 WRITE   3192777\n0x4016FEC0 WRITE   3192779\n0x4016FE80 WRITE   3192786\n0x4016FE40 WRITE   3192788\n0x400EDC00 WRITE   3192821\n0x400EDC40 WRITE   3192877\n0x400EDC80 WRITE   3192951\n0x400EDCC0 WRITE   3193007\n0x400EDD00 WRITE   3193102\n0x400EDD40 WRITE   3193158\n0x400EDD80 WRITE   3193229\n0x400EDDC0 WRITE   3193285\n0x4016FF80 WRITE   3193362\n0x4016FF40 WRITE   3193364\n0x400EDE00 WRITE   3193400\n0x400EDE40 WRITE   3193456\n0x400EDE80 WRITE   3193527\n0x400EDEC0 WRITE   3193583\n0x400EDF00 WRITE   3193673\n0x400EDF40 WRITE   3193729\n0x400EDF80 WRITE   3193800\n0x400EDFC0 WRITE   3193856\n0x40171FC0 WRITE   3194018\n0x40172000 WRITE   3194050\n0x40171000 WRITE   3194193\n0x40170FC0 WRITE   3194195\n0x40170800 WRITE   3194202\n0x401707C0 WRITE   3194204\n0x40170400 WRITE   3194214\n0x401703C0 WRITE   3194216\n0x40170200 WRITE   3194221\n0x401701C0 WRITE   3194224\n0x40170100 WRITE   3194227\n0x401700C0 WRITE   3194237\n0x40170080 WRITE   3194277\n0x40170040 WRITE   3194317\n0x400EE000 WRITE   3194357\n0x400EE040 WRITE   3194436\n0x400EE080 WRITE   3194502\n0x400EE0C0 WRITE   3194558\n0x400EE100 WRITE   3194641\n0x400EE140 WRITE   3194697\n0x400EE180 WRITE   3194760\n0x400EE1C0 WRITE   3194816\n0x40170180 WRITE   3194872\n0x40170140 WRITE   3194874\n0x400EE200 WRITE   3194910\n0x400EE240 WRITE   3194966\n0x400EE280 WRITE   3195029\n0x400EE2C0 WRITE   3195085\n0x400EE300 WRITE   3195163\n0x400EE340 WRITE   3195219\n0x400EE380 WRITE   3195282\n0x400EE3C0 WRITE   3195338\n0x40170300 WRITE   3195399\n0x401702C0 WRITE   3195401\n0x40170280 WRITE   3195408\n0x40170240 WRITE   3195410\n0x400EE400 WRITE   3195443\n0x400EE440 WRITE   3195499\n0x400EE480 WRITE   3195573\n0x400EE4C0 WRITE   3195629\n0x400EE500 WRITE   3195720\n0x400EE540 WRITE   3195776\n0x400EE580 WRITE   3195847\n0x400EE5C0 WRITE   3195903\n0x40170380 WRITE   3195967\n0x40170340 WRITE   3195969\n0x400EE600 WRITE   3196005\n0x400EE640 WRITE   3196061\n0x400EE680 WRITE   3196132\n0x400EE6C0 WRITE   3196188\n0x400EE700 WRITE   3196274\n0x400EE740 WRITE   3196330\n0x400EE780 WRITE   3196401\n0x400EE7C0 WRITE   3196457\n0x40170600 WRITE   3196526\n0x401705C0 WRITE   3196528\n0x40170500 WRITE   3196535\n0x401704C0 WRITE   3196537\n0x40170480 WRITE   3196547\n0x40170440 WRITE   3196549\n0x400EE800 WRITE   3196576\n0x400EE840 WRITE   3196632\n0x400EE880 WRITE   3196698\n0x400EE8C0 WRITE   3196754\n0x400EE900 WRITE   3196841\n0x400EE940 WRITE   3196897\n0x400EE980 WRITE   3196960\n0x400EE9C0 WRITE   3197016\n0x40170580 WRITE   3197078\n0x40170540 WRITE   3197080\n0x400EEA00 WRITE   3197116\n0x400EEA40 WRITE   3197172\n0x400EEA80 WRITE   3197235\n0x400EEAC0 WRITE   3197291\n0x400EEB00 WRITE   3197373\n0x400EEB40 WRITE   3197429\n0x400EEB80 WRITE   3197492\n0x400EEBC0 WRITE   3197548\n0x40170700 WRITE   3197614\n0x401706C0 WRITE   3197616\n0x40170680 WRITE   3197623\n0x40170640 WRITE   3197625\n0x400EEC00 WRITE   3197658\n0x400EEC40 WRITE   3197714\n0x400EEC80 WRITE   3197788\n0x400EECC0 WRITE   3197844\n0x400EED00 WRITE   3197939\n0x400EED40 WRITE   3197995\n0x400EED80 WRITE   3198066\n0x400EEDC0 WRITE   3198122\n0x40170780 WRITE   3198192\n0x40170740 WRITE   3198194\n0x400EEE00 WRITE   3198230\n0x400EEE40 WRITE   3198286\n0x400EEE80 WRITE   3198357\n0x400EEEC0 WRITE   3198413\n0x400EEF00 WRITE   3198503\n0x400EEF40 WRITE   3198559\n0x400EEF80 WRITE   3198630\n0x400EEFC0 WRITE   3198686\n0x40170C00 WRITE   3198766\n0x40170BC0 WRITE   3198768\n0x40170A00 WRITE   3198775\n0x401709C0 WRITE   3198777\n0x40170900 WRITE   3198787\n0x401708C0 WRITE   3198789\n0x40170880 WRITE   3198794\n0x40170840 WRITE   3198797\n0x400EF000 WRITE   3198822\n0x400EF040 WRITE   3198906\n0x400EF080 WRITE   3198972\n0x400EF0C0 WRITE   3199028\n0x400EF100 WRITE   3199111\n0x400EF140 WRITE   3199167\n0x400EF180 WRITE   3199230\n0x400EF1C0 WRITE   3199286\n0x40170980 WRITE   3199350\n0x40170940 WRITE   3199352\n0x400EF200 WRITE   3199388\n0x400EF240 WRITE   3199444\n0x400EF280 WRITE   3199507\n0x400EF2C0 WRITE   3199563\n0x400EF300 WRITE   3199641\n0x400EF340 WRITE   3199697\n0x400EF380 WRITE   3199760\n0x400EF3C0 WRITE   3199816\n0x40170B00 WRITE   3199884\n0x40170AC0 WRITE   3199886\n0x40170A80 WRITE   3199893\n0x40170A40 WRITE   3199895\n0x400EF400 WRITE   3199928\n0x400EF440 WRITE   3199984\n0x400EF480 WRITE   3200058\n0x400EF4C0 WRITE   3200114\n0x400EF500 WRITE   3200205\n0x400EF540 WRITE   3200261\n0x400EF580 WRITE   3200332\n0x400EF5C0 WRITE   3200388\n0x40170B80 WRITE   3200460\n0x40170B40 WRITE   3200462\n0x400EF600 WRITE   3200498\n0x400EF640 WRITE   3200554\n0x400EF680 WRITE   3200625\n0x400EF6C0 WRITE   3200681\n0x400EF700 WRITE   3200767\n0x400EF740 WRITE   3200823\n0x400EF780 WRITE   3200894\n0x400EF7C0 WRITE   3200950\n0x40170E00 WRITE   3201027\n0x40170DC0 WRITE   3201029\n0x40170D00 WRITE   3201036\n0x40170CC0 WRITE   3201038\n0x40170C80 WRITE   3201048\n0x40170C40 WRITE   3201050\n0x400EF800 WRITE   3201077\n0x400EF840 WRITE   3201133\n0x400EF880 WRITE   3201199\n0x400EF8C0 WRITE   3201255\n0x400EF900 WRITE   3201342\n0x400EF940 WRITE   3201398\n0x400EF980 WRITE   3201461\n0x400EF9C0 WRITE   3201517\n0x40170D80 WRITE   3201586\n0x40170D40 WRITE   3201588\n0x400EFA00 WRITE   3201624\n0x400EFA40 WRITE   3201680\n0x400EFA80 WRITE   3201743\n0x400EFAC0 WRITE   3201799\n0x400EFB00 WRITE   3201881\n0x400EFB40 WRITE   3201937\n0x400EFB80 WRITE   3202000\n0x400EFBC0 WRITE   3202056\n0x40170F00 WRITE   3202129\n0x40170EC0 WRITE   3202131\n0x40170E80 WRITE   3202138\n0x40170E40 WRITE   3202140\n0x400EFC00 WRITE   3202173\n0x400EFC40 WRITE   3202229\n0x400EFC80 WRITE   3202303\n0x400EFCC0 WRITE   3202359\n0x400EFD00 WRITE   3202454\n0x400EFD40 WRITE   3202510\n0x400EFD80 WRITE   3202581\n0x400EFDC0 WRITE   3202637\n0x40170F80 WRITE   3202714\n0x40170F40 WRITE   3202716\n0x400EFE00 WRITE   3202752\n0x400EFE40 WRITE   3202808\n0x400EFE80 WRITE   3202879\n0x400EFEC0 WRITE   3202935\n0x400EFF00 WRITE   3203025\n0x400EFF40 WRITE   3203081\n0x400EFF80 WRITE   3203152\n0x400EFFC0 WRITE   3203208\n0x40171800 WRITE   3203294\n0x401717C0 WRITE   3203296\n0x40171400 WRITE   3203303\n0x401713C0 WRITE   3203305\n0x40171200 WRITE   3203315\n0x401711C0 WRITE   3203317\n0x40171100 WRITE   3203322\n0x401710C0 WRITE   3203325\n0x40171080 WRITE   3203328\n0x40171040 WRITE   3203331\n0x400F0000 WRITE   3203356\n0x400F0040 WRITE   3203440\n0x400F0080 WRITE   3203506\n0x400F00C0 WRITE   3203562\n0x400F0100 WRITE   3203645\n0x400F0140 WRITE   3203701\n0x400F0180 WRITE   3203764\n0x400F01C0 WRITE   3203820\n0x40171180 WRITE   3203876\n0x40171140 WRITE   3203878\n0x400F0200 WRITE   3203914\n0x400F0240 WRITE   3203970\n0x400F0280 WRITE   3204033\n0x400F02C0 WRITE   3204089\n0x400F0300 WRITE   3204167\n0x400F0340 WRITE   3204223\n0x400F0380 WRITE   3204286\n0x400F03C0 WRITE   3204342\n0x40171300 WRITE   3204408\n0x401712C0 WRITE   3204410\n0x40171280 WRITE   3204417\n0x40171240 WRITE   3204419\n0x400F0400 WRITE   3204452\n0x400F0440 WRITE   3204508\n0x400F0480 WRITE   3204582\n0x400F04C0 WRITE   3204638\n0x400F0500 WRITE   3204729\n0x400F0540 WRITE   3204785\n0x400F0580 WRITE   3204856\n0x400F05C0 WRITE   3204912\n0x40171380 WRITE   3204976\n0x40171340 WRITE   3204978\n0x400F0600 WRITE   3205014\n0x400F0640 WRITE   3205070\n0x400F0680 WRITE   3205141\n0x400F06C0 WRITE   3205197\n0x400F0700 WRITE   3205283\n0x400F0740 WRITE   3205339\n0x400F0780 WRITE   3205410\n0x400F07C0 WRITE   3205466\n0x40171600 WRITE   3205541\n0x401715C0 WRITE   3205543\n0x40171500 WRITE   3205550\n0x401714C0 WRITE   3205552\n0x40171480 WRITE   3205562\n0x40171440 WRITE   3205564\n0x400F0800 WRITE   3205591\n0x400F0840 WRITE   3205647\n0x400F0880 WRITE   3205713\n0x400F08C0 WRITE   3205769\n0x400F0900 WRITE   3205856\n0x400F0940 WRITE   3205912\n0x400F0980 WRITE   3205975\n0x400F09C0 WRITE   3206031\n0x40171580 WRITE   3206093\n0x40171540 WRITE   3206095\n0x400F0A00 WRITE   3206131\n0x400F0A40 WRITE   3206187\n0x400F0A80 WRITE   3206250\n0x400F0AC0 WRITE   3206306\n0x400F0B00 WRITE   3206388\n0x400F0B40 WRITE   3206444\n0x400F0B80 WRITE   3206507\n0x400F0BC0 WRITE   3206563\n0x40171700 WRITE   3206635\n0x401716C0 WRITE   3206637\n0x40171680 WRITE   3206644\n0x40171640 WRITE   3206646\n0x400F0C00 WRITE   3206679\n0x400F0C40 WRITE   3206735\n0x400F0C80 WRITE   3206809\n0x400F0CC0 WRITE   3206865\n0x400F0D00 WRITE   3206960\n0x400F0D40 WRITE   3207016\n0x400F0D80 WRITE   3207087\n0x400F0DC0 WRITE   3207143\n0x40171780 WRITE   3207213\n0x40171740 WRITE   3207215\n0x400F0E00 WRITE   3207251\n0x400F0E40 WRITE   3207307\n0x400F0E80 WRITE   3207378\n0x400F0EC0 WRITE   3207434\n0x400F0F00 WRITE   3207524\n0x400F0F40 WRITE   3207580\n0x400F0F80 WRITE   3207651\n0x400F0FC0 WRITE   3207707\n0x40171C00 WRITE   3207793\n0x40171BC0 WRITE   3207795\n0x40171A00 WRITE   3207802\n0x401719C0 WRITE   3207804\n0x40171900 WRITE   3207814\n0x401718C0 WRITE   3207816\n0x40171880 WRITE   3207821\n0x40171840 WRITE   3207917\n0x400F1000 WRITE   3207957\n0x400F1040 WRITE   3208025\n0x400F1080 WRITE   3208091\n0x400F10C0 WRITE   3208147\n0x400F1100 WRITE   3208230\n0x400F1140 WRITE   3208286\n0x400F1180 WRITE   3208349\n0x400F11C0 WRITE   3208405\n0x40171980 WRITE   3208469\n0x40171940 WRITE   3208471\n0x400F1200 WRITE   3208507\n0x400F1240 WRITE   3208563\n0x400F1280 WRITE   3208626\n0x400F12C0 WRITE   3208682\n0x400F1300 WRITE   3208760\n0x400F1340 WRITE   3208816\n0x400F1380 WRITE   3208879\n0x400F13C0 WRITE   3208935\n0x40171B00 WRITE   3209009\n0x40171AC0 WRITE   3209011\n0x40171A80 WRITE   3209018\n0x40171A40 WRITE   3209020\n0x400F1400 WRITE   3209053\n0x400F1440 WRITE   3209109\n0x400F1480 WRITE   3209183\n0x400F14C0 WRITE   3209239\n0x400F1500 WRITE   3209330\n0x400F1540 WRITE   3209386\n0x400F1580 WRITE   3209457\n0x400F15C0 WRITE   3209513\n0x40171B80 WRITE   3209585\n0x40171B40 WRITE   3209587\n0x400F1600 WRITE   3209623\n0x400F1640 WRITE   3209679\n0x400F1680 WRITE   3209750\n0x400F16C0 WRITE   3209806\n0x400F1700 WRITE   3209892\n0x400F1740 WRITE   3209948\n0x400F1780 WRITE   3210019\n0x400F17C0 WRITE   3210075\n0x40171E00 WRITE   3210158\n0x40171DC0 WRITE   3210160\n0x40171D00 WRITE   3210167\n0x40171CC0 WRITE   3210169\n0x40171C80 WRITE   3210179\n0x40171C40 WRITE   3210181\n0x400F1800 WRITE   3210208\n0x400F1840 WRITE   3210297\n0x400F1880 WRITE   3210361\n0x400F18C0 WRITE   3210417\n0x400F1900 WRITE   3210504\n0x400F1940 WRITE   3210560\n0x400F1980 WRITE   3210623\n0x400F19C0 WRITE   3210679\n0x40171D80 WRITE   3210748\n0x40171D40 WRITE   3210750\n0x400F1A00 WRITE   3210786\n0x400F1A40 WRITE   3210842\n0x400F1A80 WRITE   3210905\n0x400F1AC0 WRITE   3210961\n0x400F1B00 WRITE   3211043\n0x400F1B40 WRITE   3211099\n0x400F1B80 WRITE   3211162\n0x400F1BC0 WRITE   3211218\n0x40171F00 WRITE   3211297\n0x40171EC0 WRITE   3211299\n0x40171E80 WRITE   3211306\n0x40171E40 WRITE   3211308\n0x400F1C00 WRITE   3211341\n0x400F1C40 WRITE   3211397\n0x400F1C80 WRITE   3211471\n0x400F1CC0 WRITE   3211527\n0x400F1D00 WRITE   3211622\n0x400F1D40 WRITE   3211678\n0x400F1D80 WRITE   3211749\n0x400F1DC0 WRITE   3211805\n0x40171F80 WRITE   3211882\n0x40171F40 WRITE   3211884\n0x400F1E00 WRITE   3211920\n0x400F1E40 WRITE   3211976\n0x400F1E80 WRITE   3212047\n0x400F1EC0 WRITE   3212103\n0x400F1F00 WRITE   3212193\n0x400F1F40 WRITE   3212249\n0x400F1F80 WRITE   3212320\n0x400F1FC0 WRITE   3212376\n0x40173FC0 WRITE   3212538\n0x40174000 WRITE   3212570\n0x40173000 WRITE   3212697\n0x40172FC0 WRITE   3212699\n0x40172800 WRITE   3212706\n0x401727C0 WRITE   3212708\n0x40172400 WRITE   3212718\n0x401723C0 WRITE   3212720\n0x40172200 WRITE   3212725\n0x401721C0 WRITE   3212728\n0x40172100 WRITE   3212731\n0x401720C0 WRITE   3212757\n0x40172080 WRITE   3212797\n0x40172040 WRITE   3212837\n0x400F2000 WRITE   3212877\n0x400F2040 WRITE   3212967\n0x400F2080 WRITE   3213031\n0x400F20C0 WRITE   3213087\n0x400F2100 WRITE   3213170\n0x400F2140 WRITE   3213226\n0x400F2180 WRITE   3213289\n0x400F21C0 WRITE   3213345\n0x40172180 WRITE   3213401\n0x40172140 WRITE   3213403\n0x400F2200 WRITE   3213439\n0x400F2240 WRITE   3213495\n0x400F2280 WRITE   3213558\n0x400F22C0 WRITE   3213614\n0x400F2300 WRITE   3213692\n0x400F2340 WRITE   3213748\n0x400F2380 WRITE   3213811\n0x400F23C0 WRITE   3213867\n0x40172300 WRITE   3213928\n0x401722C0 WRITE   3213930\n0x40172280 WRITE   3213937\n0x40172240 WRITE   3213939\n0x400F2400 WRITE   3213972\n0x400F2440 WRITE   3214028\n0x400F2480 WRITE   3214102\n0x400F24C0 WRITE   3214158\n0x400F2500 WRITE   3214249\n0x400F2540 WRITE   3214305\n0x400F2580 WRITE   3214376\n0x400F25C0 WRITE   3214432\n0x40172380 WRITE   3214496\n0x40172340 WRITE   3214498\n0x400F2600 WRITE   3214534\n0x400F2640 WRITE   3214590\n0x400F2680 WRITE   3214661\n0x400F26C0 WRITE   3214717\n0x400F2700 WRITE   3214803\n0x400F2740 WRITE   3214859\n0x400F2780 WRITE   3214930\n0x400F27C0 WRITE   3214986\n0x40172600 WRITE   3215055\n0x401725C0 WRITE   3215057\n0x40172500 WRITE   3215064\n0x401724C0 WRITE   3215066\n0x40172480 WRITE   3215076\n0x40172440 WRITE   3215078\n0x400F2800 WRITE   3215107\n0x400F2840 WRITE   3215161\n0x400F2880 WRITE   3215247\n0x400F28C0 WRITE   3215301\n0x400F2900 WRITE   3215388\n0x400F2940 WRITE   3215444\n0x400F2980 WRITE   3215507\n0x400F29C0 WRITE   3215563\n0x40172580 WRITE   3215625\n0x40172540 WRITE   3215627\n0x400F2A00 WRITE   3215663\n0x400F2A40 WRITE   3215719\n0x400F2A80 WRITE   3215782\n0x400F2AC0 WRITE   3215838\n0x400F2B00 WRITE   3215920\n0x400F2B40 WRITE   3215976\n0x400F2B80 WRITE   3216039\n0x400F2BC0 WRITE   3216095\n0x40172700 WRITE   3216161\n0x401726C0 WRITE   3216163\n0x40172680 WRITE   3216170\n0x40172640 WRITE   3216172\n0x400F2C00 WRITE   3216205\n0x400F2C40 WRITE   3216261\n0x400F2C80 WRITE   3216335\n0x400F2CC0 WRITE   3216391\n0x400F2D00 WRITE   3216486\n0x400F2D40 WRITE   3216542\n0x400F2D80 WRITE   3216613\n0x400F2DC0 WRITE   3216669\n0x40172780 WRITE   3216739\n0x40172740 WRITE   3216741\n0x400F2E00 WRITE   3216777\n0x400F2E40 WRITE   3216833\n0x400F2E80 WRITE   3216904\n0x400F2EC0 WRITE   3216960\n0x400F2F00 WRITE   3217050\n0x400F2F40 WRITE   3217106\n0x400F2F80 WRITE   3217177\n0x400F2FC0 WRITE   3217233\n0x40172C00 WRITE   3217318\n0x40172BC0 WRITE   3217320\n0x40172A00 WRITE   3217328\n0x401729C0 WRITE   3217330\n0x40172900 WRITE   3217340\n0x401728C0 WRITE   3217342\n0x40172880 WRITE   3217367\n0x40172840 WRITE   3217417\n0x400F3000 WRITE   3217507\n0x400F3040 WRITE   3217561\n0x400F3080 WRITE   3217627\n0x400F30C0 WRITE   3217683\n0x400F3100 WRITE   3217766\n0x400F3140 WRITE   3217822\n0x400F3180 WRITE   3217885\n0x400F31C0 WRITE   3217941\n0x40172980 WRITE   3218005\n0x40172940 WRITE   3218007\n0x400F3200 WRITE   3218043\n0x400F3240 WRITE   3218099\n0x400F3280 WRITE   3218162\n0x400F32C0 WRITE   3218218\n0x400F3300 WRITE   3218296\n0x400F3340 WRITE   3218352\n0x400F3380 WRITE   3218415\n0x400F33C0 WRITE   3218471\n0x40172B00 WRITE   3218539\n0x40172AC0 WRITE   3218541\n0x40172A80 WRITE   3218548\n0x40172A40 WRITE   3218550\n0x400F3400 WRITE   3218583\n0x400F3440 WRITE   3218639\n0x400F3480 WRITE   3218713\n0x400F34C0 WRITE   3218769\n0x400F3500 WRITE   3218860\n0x400F3540 WRITE   3218916\n0x400F3580 WRITE   3218987\n0x400F35C0 WRITE   3219043\n0x40172B80 WRITE   3219115\n0x40172B40 WRITE   3219117\n0x400F3600 WRITE   3219153\n0x400F3640 WRITE   3219209\n0x400F3680 WRITE   3219280\n0x400F36C0 WRITE   3219336\n0x400F3700 WRITE   3219422\n0x400F3740 WRITE   3219478\n0x400F3780 WRITE   3219549\n0x400F37C0 WRITE   3219605\n0x40172E00 WRITE   3219682\n0x40172DC0 WRITE   3219684\n0x40172D00 WRITE   3219691\n0x40172CC0 WRITE   3219693\n0x40172C80 WRITE   3219703\n0x40172C40 WRITE   3219705\n0x400F3800 WRITE   3219732\n0x400F3840 WRITE   3219847\n0x400F3880 WRITE   3219911\n0x400F38C0 WRITE   3219967\n0x400F3900 WRITE   3220054\n0x400F3940 WRITE   3220110\n0x400F3980 WRITE   3220173\n0x400F39C0 WRITE   3220229\n0x40172D80 WRITE   3220298\n0x40172D40 WRITE   3220300\n0x400F3A00 WRITE   3220336\n0x400F3A40 WRITE   3220392\n0x400F3A80 WRITE   3220455\n0x400F3AC0 WRITE   3220511\n0x400F3B00 WRITE   3220593\n0x400F3B40 WRITE   3220649\n0x400F3B80 WRITE   3220712\n0x400F3BC0 WRITE   3220768\n0x40172F00 WRITE   3220841\n0x40172EC0 WRITE   3220843\n0x40172E80 WRITE   3220850\n0x40172E40 WRITE   3220852\n0x400F3C00 WRITE   3220885\n0x400F3C40 WRITE   3220941\n0x400F3C80 WRITE   3221015\n0x400F3CC0 WRITE   3221071\n0x400F3D00 WRITE   3221166\n0x400F3D40 WRITE   3221222\n0x400F3D80 WRITE   3221293\n0x400F3DC0 WRITE   3221349\n0x40172F80 WRITE   3221426\n0x40172F40 WRITE   3221428\n0x400F3E00 WRITE   3221464\n0x400F3E40 WRITE   3221520\n0x400F3E80 WRITE   3221591\n0x400F3EC0 WRITE   3221647\n0x400F3F00 WRITE   3221737\n0x400F3F40 WRITE   3221793\n0x400F3F80 WRITE   3221864\n0x400F3FC0 WRITE   3221920\n0x40173800 WRITE   3222006\n0x401737C0 WRITE   3222008\n0x40173400 WRITE   3222015\n0x401733C0 WRITE   3222017\n0x40173200 WRITE   3222027\n0x401731C0 WRITE   3222029\n0x40173100 WRITE   3222034\n0x401730C0 WRITE   3222147\n0x40173080 WRITE   3222187\n0x40173040 WRITE   3222227\n0x400F4000 WRITE   3222267\n0x400F4040 WRITE   3222335\n0x400F4080 WRITE   3222401\n0x400F40C0 WRITE   3222457\n0x400F4100 WRITE   3222540\n0x400F4140 WRITE   3222596\n0x400F4180 WRITE   3222659\n0x400F41C0 WRITE   3222715\n0x40173180 WRITE   3222771\n0x40173140 WRITE   3222773\n0x400F4200 WRITE   3222809\n0x400F4240 WRITE   3222865\n0x400F4280 WRITE   3222928\n0x400F42C0 WRITE   3222984\n0x400F4300 WRITE   3223062\n0x400F4340 WRITE   3223118\n0x400F4380 WRITE   3223181\n0x400F43C0 WRITE   3223237\n0x40173300 WRITE   3223303\n0x401732C0 WRITE   3223305\n0x40173280 WRITE   3223312\n0x40173240 WRITE   3223314\n0x400F4400 WRITE   3223347\n0x400F4440 WRITE   3223403\n0x400F4480 WRITE   3223477\n0x400F44C0 WRITE   3223533\n0x400F4500 WRITE   3223624\n0x400F4540 WRITE   3223680\n0x400F4580 WRITE   3223751\n0x400F45C0 WRITE   3223807\n0x40173380 WRITE   3223871\n0x40173340 WRITE   3223873\n0x400F4600 WRITE   3223909\n0x400F4640 WRITE   3223965\n0x400F4680 WRITE   3224036\n0x400F46C0 WRITE   3224092\n0x400F4700 WRITE   3224178\n0x400F4740 WRITE   3224234\n0x400F4780 WRITE   3224305\n0x400F47C0 WRITE   3224361\n0x40173600 WRITE   3224436\n0x401735C0 WRITE   3224438\n0x40173500 WRITE   3224445\n0x401734C0 WRITE   3224447\n0x40173480 WRITE   3224457\n0x40173440 WRITE   3224459\n0x400F4800 WRITE   3224486\n0x400F4840 WRITE   3224542\n0x400F4880 WRITE   3224608\n0x400F48C0 WRITE   3224664\n0x400F4900 WRITE   3224751\n0x400F4940 WRITE   3224807\n0x400F4980 WRITE   3224870\n0x400F49C0 WRITE   3224926\n0x40173580 WRITE   3224988\n0x40173540 WRITE   3224990\n0x400F4A00 WRITE   3225026\n0x400F4A40 WRITE   3225082\n0x400F4A80 WRITE   3225145\n0x400F4AC0 WRITE   3225201\n0x400F4B00 WRITE   3225283\n0x400F4B40 WRITE   3225339\n0x400F4B80 WRITE   3225402\n0x400F4BC0 WRITE   3225458\n0x40173700 WRITE   3225530\n0x401736C0 WRITE   3225532\n0x40173680 WRITE   3225539\n0x40173640 WRITE   3225541\n0x400F4C00 WRITE   3225574\n0x400F4C40 WRITE   3225630\n0x400F4C80 WRITE   3225704\n0x400F4CC0 WRITE   3225760\n0x400F4D00 WRITE   3225855\n0x400F4D40 WRITE   3225911\n0x400F4D80 WRITE   3225982\n0x400F4DC0 WRITE   3226038\n0x40173780 WRITE   3226108\n0x40173740 WRITE   3226110\n0x400F4E00 WRITE   3226146\n0x400F4E40 WRITE   3226202\n0x400F4E80 WRITE   3226273\n0x400F4EC0 WRITE   3226329\n0x400F4F00 WRITE   3226419\n0x400F4F40 WRITE   3226475\n0x400F4F80 WRITE   3226546\n0x400F4FC0 WRITE   3226602\n0x40173C00 WRITE   3226688\n0x40173BC0 WRITE   3226690\n0x40173A00 WRITE   3226697\n0x401739C0 WRITE   3226699\n0x40173900 WRITE   3226709\n0x401738C0 WRITE   3226711\n0x40173880 WRITE   3226716\n0x40173840 WRITE   3226719\n0x400F5000 WRITE   3226744\n0x400F5040 WRITE   3226828\n0x400F5080 WRITE   3226894\n0x400F50C0 WRITE   3226950\n0x400F5100 WRITE   3227033\n0x400F5140 WRITE   3227089\n0x400F5180 WRITE   3227152\n0x400F51C0 WRITE   3227208\n0x40173980 WRITE   3227272\n0x40173940 WRITE   3227274\n0x400F5200 WRITE   3227310\n0x400F5240 WRITE   3227366\n0x400F5280 WRITE   3227429\n0x400F52C0 WRITE   3227485\n0x400F5300 WRITE   3227563\n0x400F5340 WRITE   3227619\n0x400F5380 WRITE   3227682\n0x400F53C0 WRITE   3227738\n0x40173B00 WRITE   3227812\n0x40173AC0 WRITE   3227814\n0x40173A80 WRITE   3227821\n0x40173A40 WRITE   3227823\n0x400F5400 WRITE   3227856\n0x400F5440 WRITE   3227912\n0x400F5480 WRITE   3227986\n0x400F54C0 WRITE   3228042\n0x400F5500 WRITE   3228133\n0x400F5540 WRITE   3228189\n0x400F5580 WRITE   3228260\n0x400F55C0 WRITE   3228316\n0x40173B80 WRITE   3228388\n0x40173B40 WRITE   3228390\n0x400F5600 WRITE   3228426\n0x400F5640 WRITE   3228482\n0x400F5680 WRITE   3228553\n0x400F56C0 WRITE   3228609\n0x400F5700 WRITE   3228695\n0x400F5740 WRITE   3228751\n0x400F5780 WRITE   3228822\n0x400F57C0 WRITE   3228878\n0x40173E00 WRITE   3228961\n0x40173DC0 WRITE   3228963\n0x40173D00 WRITE   3228970\n0x40173CC0 WRITE   3228972\n0x40173C80 WRITE   3228982\n0x40173C40 WRITE   3228984\n0x400F5800 WRITE   3229011\n0x400F5840 WRITE   3229067\n0x400F5880 WRITE   3229133\n0x400F58C0 WRITE   3229189\n0x400F5900 WRITE   3229276\n0x400F5940 WRITE   3229332\n0x400F5980 WRITE   3229395\n0x400F59C0 WRITE   3229451\n0x40173D80 WRITE   3229520\n0x40173D40 WRITE   3229522\n0x400F5A00 WRITE   3229558\n0x400F5A40 WRITE   3229614\n0x400F5A80 WRITE   3229677\n0x400F5AC0 WRITE   3229733\n0x400F5B00 WRITE   3229815\n0x400F5B40 WRITE   3229871\n0x400F5B80 WRITE   3229934\n0x400F5BC0 WRITE   3229990\n0x40173F00 WRITE   3230069\n0x40173EC0 WRITE   3230071\n0x40173E80 WRITE   3230078\n0x40173E40 WRITE   3230080\n0x400F5C00 WRITE   3230113\n0x400F5C40 WRITE   3230169\n0x400F5C80 WRITE   3230243\n0x400F5CC0 WRITE   3230299\n0x400F5D00 WRITE   3230394\n0x400F5D40 WRITE   3230450\n0x400F5D80 WRITE   3230521\n0x400F5DC0 WRITE   3230577\n0x40173F80 WRITE   3230654\n0x40173F40 WRITE   3230656\n0x400F5E00 WRITE   3230692\n0x400F5E40 WRITE   3230748\n0x400F5E80 WRITE   3230819\n0x400F5EC0 WRITE   3230875\n0x400F5F00 WRITE   3230965\n0x400F5F40 WRITE   3231021\n0x400F5F80 WRITE   3231092\n0x400F5FC0 WRITE   3231148\n0x40175FC0 WRITE   3231310\n0x40176000 WRITE   3231342\n0x40175000 WRITE   3231469\n0x40174FC0 WRITE   3231471\n0x40174800 WRITE   3231478\n0x401747C0 WRITE   3231480\n0x40174400 WRITE   3231490\n0x401743C0 WRITE   3231492\n0x40174200 WRITE   3231497\n0x401741C0 WRITE   3231500\n0x40174100 WRITE   3231503\n0x401740C0 WRITE   3231506\n0x40174080 WRITE   3231509\n0x40174040 WRITE   3231512\n0x400F6000 WRITE   3231544\n0x400F6040 WRITE   3231632\n0x400F6080 WRITE   3231698\n0x400F60C0 WRITE   3231754\n0x400F6100 WRITE   3231837\n0x400F6140 WRITE   3231893\n0x400F6180 WRITE   3231956\n0x400F61C0 WRITE   3232012\n0x40174180 WRITE   3232068\n0x40174140 WRITE   3232070\n0x400F6200 WRITE   3232106\n0x400F6240 WRITE   3232162\n0x400F6280 WRITE   3232225\n0x400F62C0 WRITE   3232281\n0x400F6300 WRITE   3232359\n0x400F6340 WRITE   3232415\n0x400F6380 WRITE   3232478\n0x400F63C0 WRITE   3232534\n0x40174300 WRITE   3232595\n0x401742C0 WRITE   3232597\n0x40174280 WRITE   3232604\n0x40174240 WRITE   3232606\n0x400F6400 WRITE   3232639\n0x400F6440 WRITE   3232695\n0x400F6480 WRITE   3232769\n0x400F64C0 WRITE   3232825\n0x400F6500 WRITE   3232916\n0x400F6540 WRITE   3232972\n0x400F6580 WRITE   3233043\n0x400F65C0 WRITE   3233099\n0x40174380 WRITE   3233163\n0x40174340 WRITE   3233165\n0x400F6600 WRITE   3233201\n0x400F6640 WRITE   3233257\n0x400F6680 WRITE   3233328\n0x400F66C0 WRITE   3233384\n0x400F6700 WRITE   3233470\n0x400F6740 WRITE   3233526\n0x400F6780 WRITE   3233597\n0x400F67C0 WRITE   3233653\n0x40174600 WRITE   3233722\n0x401745C0 WRITE   3233724\n0x40174500 WRITE   3233731\n0x401744C0 WRITE   3233733\n0x40174480 WRITE   3233743\n0x40174440 WRITE   3233745\n0x400F6800 WRITE   3233772\n0x400F6840 WRITE   3233872\n0x400F6880 WRITE   3233936\n0x400F68C0 WRITE   3233992\n0x400F6900 WRITE   3234079\n0x400F6940 WRITE   3234135\n0x400F6980 WRITE   3234198\n0x400F69C0 WRITE   3234254\n0x40174580 WRITE   3234316\n0x40174540 WRITE   3234318\n0x400F6A00 WRITE   3234354\n0x400F6A40 WRITE   3234410\n0x400F6A80 WRITE   3234473\n0x400F6AC0 WRITE   3234529\n0x400F6B00 WRITE   3234611\n0x400F6B40 WRITE   3234667\n0x400F6B80 WRITE   3234730\n0x400F6BC0 WRITE   3234786\n0x40174700 WRITE   3234852\n0x401746C0 WRITE   3234854\n0x40174680 WRITE   3234861\n0x40174640 WRITE   3234863\n0x400F6C00 WRITE   3234896\n0x400F6C40 WRITE   3234952\n0x400F6C80 WRITE   3235026\n0x400F6CC0 WRITE   3235082\n0x400F6D00 WRITE   3235177\n0x400F6D40 WRITE   3235233\n0x400F6D80 WRITE   3235304\n0x400F6DC0 WRITE   3235360\n0x40174780 WRITE   3235430\n0x40174740 WRITE   3235432\n0x400F6E00 WRITE   3235468\n0x400F6E40 WRITE   3235524\n0x400F6E80 WRITE   3235595\n0x400F6EC0 WRITE   3235651\n0x400F6F00 WRITE   3235741\n0x400F6F40 WRITE   3235797\n0x400F6F80 WRITE   3235868\n0x400F6FC0 WRITE   3235924\n0x40174C00 WRITE   3236004\n0x40174BC0 WRITE   3236006\n0x40174A00 WRITE   3236013\n0x401749C0 WRITE   3236015\n0x40174900 WRITE   3236025\n0x401748C0 WRITE   3236027\n0x40174880 WRITE   3236032\n0x40174840 WRITE   3236172\n0x400F7000 WRITE   3236212\n0x400F7040 WRITE   3236280\n0x400F7080 WRITE   3236346\n0x400F70C0 WRITE   3236402\n0x400F7100 WRITE   3236485\n0x400F7140 WRITE   3236541\n0x400F7180 WRITE   3236604\n0x400F71C0 WRITE   3236660\n0x40174980 WRITE   3236724\n0x40174940 WRITE   3236726\n0x400F7200 WRITE   3236762\n0x400F7240 WRITE   3236818\n0x400F7280 WRITE   3236881\n0x400F72C0 WRITE   3236937\n0x400F7300 WRITE   3237015\n0x400F7340 WRITE   3237071\n0x400F7380 WRITE   3237134\n0x400F73C0 WRITE   3237190\n0x40174B00 WRITE   3237258\n0x40174AC0 WRITE   3237260\n0x40174A80 WRITE   3237267\n0x40174A40 WRITE   3237269\n0x400F7400 WRITE   3237302\n0x400F7440 WRITE   3237358\n0x400F7480 WRITE   3237432\n0x400F74C0 WRITE   3237488\n0x400F7500 WRITE   3237579\n0x400F7540 WRITE   3237635\n0x400F7580 WRITE   3237706\n0x400F75C0 WRITE   3237762\n0x40174B80 WRITE   3237834\n0x40174B40 WRITE   3237836\n0x400F7600 WRITE   3237872\n0x400F7640 WRITE   3237928\n0x400F7680 WRITE   3237999\n0x400F76C0 WRITE   3238055\n0x400F7700 WRITE   3238141\n0x400F7740 WRITE   3238197\n0x400F7780 WRITE   3238268\n0x400F77C0 WRITE   3238324\n0x40174E00 WRITE   3238401\n0x40174DC0 WRITE   3238403\n0x40174D00 WRITE   3238410\n0x40174CC0 WRITE   3238412\n0x40174C80 WRITE   3238422\n0x40174C40 WRITE   3238424\n0x400F7800 WRITE   3238451\n0x400F7840 WRITE   3238552\n0x400F7880 WRITE   3238616\n0x400F78C0 WRITE   3238672\n0x400F7900 WRITE   3238759\n0x400F7940 WRITE   3238815\n0x400F7980 WRITE   3238878\n0x400F79C0 WRITE   3238934\n0x40174D80 WRITE   3239003\n0x40174D40 WRITE   3239005\n0x400F7A00 WRITE   3239041\n0x400F7A40 WRITE   3239097\n0x400F7A80 WRITE   3239160\n0x400F7AC0 WRITE   3239216\n0x400F7B00 WRITE   3239298\n0x400F7B40 WRITE   3239354\n0x400F7B80 WRITE   3239417\n0x400F7BC0 WRITE   3239473\n0x40174F00 WRITE   3239546\n0x40174EC0 WRITE   3239548\n0x40174E80 WRITE   3239555\n0x40174E40 WRITE   3239557\n0x400F7C00 WRITE   3239590\n0x400F7C40 WRITE   3239646\n0x400F7C80 WRITE   3239720\n0x400F7CC0 WRITE   3239776\n0x400F7D00 WRITE   3239871\n0x400F7D40 WRITE   3239927\n0x400F7D80 WRITE   3239998\n0x400F7DC0 WRITE   3240054\n0x40174F80 WRITE   3240131\n0x40174F40 WRITE   3240133\n0x400F7E00 WRITE   3240169\n0x400F7E40 WRITE   3240225\n0x400F7E80 WRITE   3240296\n0x400F7EC0 WRITE   3240352\n0x400F7F00 WRITE   3240442\n0x400F7F40 WRITE   3240498\n0x400F7F80 WRITE   3240569\n0x400F7FC0 WRITE   3240625\n0x40175800 WRITE   3240711\n0x401757C0 WRITE   3240713\n0x40175400 WRITE   3240720\n0x401753C0 WRITE   3240722\n0x40175200 WRITE   3240732\n0x401751C0 WRITE   3240734\n0x40175100 WRITE   3240739\n0x401750C0 WRITE   3240852\n0x40175080 WRITE   3240892\n0x40175040 WRITE   3240932\n0x400F8000 WRITE   3240972\n0x400F8040 WRITE   3241040\n0x400F8080 WRITE   3241106\n0x400F80C0 WRITE   3241162\n0x400F8100 WRITE   3241245\n0x400F8140 WRITE   3241301\n0x400F8180 WRITE   3241364\n0x400F81C0 WRITE   3241420\n0x40175180 WRITE   3241476\n0x40175140 WRITE   3241478\n0x400F8200 WRITE   3241514\n0x400F8240 WRITE   3241570\n0x400F8280 WRITE   3241633\n0x400F82C0 WRITE   3241689\n0x400F8300 WRITE   3241767\n0x400F8340 WRITE   3241823\n0x400F8380 WRITE   3241886\n0x400F83C0 WRITE   3241942\n0x40175300 WRITE   3242008\n0x401752C0 WRITE   3242010\n0x40175280 WRITE   3242017\n0x40175240 WRITE   3242019\n0x400F8400 WRITE   3242052\n0x400F8440 WRITE   3242108\n0x400F8480 WRITE   3242182\n0x400F84C0 WRITE   3242238\n0x400F8500 WRITE   3242329\n0x400F8540 WRITE   3242385\n0x400F8580 WRITE   3242456\n0x400F85C0 WRITE   3242512\n0x40175380 WRITE   3242576\n0x40175340 WRITE   3242578\n0x400F8600 WRITE   3242614\n0x400F8640 WRITE   3242670\n0x400F8680 WRITE   3242741\n0x400F86C0 WRITE   3242797\n0x400F8700 WRITE   3242883\n0x400F8740 WRITE   3242939\n0x400F8780 WRITE   3243010\n0x400F87C0 WRITE   3243066\n0x40175600 WRITE   3243141\n0x401755C0 WRITE   3243143\n0x40175500 WRITE   3243150\n0x401754C0 WRITE   3243152\n0x40175480 WRITE   3243162\n0x40175440 WRITE   3243164\n0x400F8800 WRITE   3243191\n0x400F8840 WRITE   3243247\n0x400F8880 WRITE   3243313\n0x400F88C0 WRITE   3243369\n0x400F8900 WRITE   3243456\n0x400F8940 WRITE   3243512\n0x400F8980 WRITE   3243575\n0x400F89C0 WRITE   3243631\n0x40175580 WRITE   3243693\n0x40175540 WRITE   3243695\n0x400F8A00 WRITE   3243731\n0x400F8A40 WRITE   3243787\n0x400F8A80 WRITE   3243850\n0x400F8AC0 WRITE   3243906\n0x400F8B00 WRITE   3243988\n0x400F8B40 WRITE   3244044\n0x400F8B80 WRITE   3244107\n0x400F8BC0 WRITE   3244163\n0x40175700 WRITE   3244235\n0x401756C0 WRITE   3244237\n0x40175680 WRITE   3244244\n0x40175640 WRITE   3244246\n0x400F8C00 WRITE   3244279\n0x400F8C40 WRITE   3244335\n0x400F8C80 WRITE   3244409\n0x400F8CC0 WRITE   3244465\n0x400F8D00 WRITE   3244560\n0x400F8D40 WRITE   3244616\n0x400F8D80 WRITE   3244687\n0x400F8DC0 WRITE   3244743\n0x40175780 WRITE   3244813\n0x40175740 WRITE   3244815\n0x400F8E00 WRITE   3244851\n0x400F8E40 WRITE   3244907\n0x400F8E80 WRITE   3244978\n0x400F8EC0 WRITE   3245034\n0x400F8F00 WRITE   3245124\n0x400F8F40 WRITE   3245180\n0x400F8F80 WRITE   3245251\n0x400F8FC0 WRITE   3245307\n0x40175C00 WRITE   3245393\n0x40175BC0 WRITE   3245395\n0x40175A00 WRITE   3245402\n0x401759C0 WRITE   3245404\n0x40175900 WRITE   3245414\n0x401758C0 WRITE   3245416\n0x40175880 WRITE   3245421\n0x40175840 WRITE   3245424\n0x400F9000 WRITE   3245449\n0x400F9040 WRITE   3245533\n0x400F9080 WRITE   3245599\n0x400F90C0 WRITE   3245655\n0x400F9100 WRITE   3245738\n0x400F9140 WRITE   3245794\n0x400F9180 WRITE   3245857\n0x400F91C0 WRITE   3245913\n0x40175980 WRITE   3245977\n0x40175940 WRITE   3245979\n0x400F9200 WRITE   3246015\n0x400F9240 WRITE   3246071\n0x400F9280 WRITE   3246134\n0x400F92C0 WRITE   3246190\n0x400F9300 WRITE   3246268\n0x400F9340 WRITE   3246324\n0x400F9380 WRITE   3246387\n0x400F93C0 WRITE   3246443\n0x40175B00 WRITE   3246517\n0x40175AC0 WRITE   3246519\n0x40175A80 WRITE   3246526\n0x40175A40 WRITE   3246528\n0x400F9400 WRITE   3246561\n0x400F9440 WRITE   3246617\n0x400F9480 WRITE   3246691\n0x400F94C0 WRITE   3246747\n0x400F9500 WRITE   3246838\n0x400F9540 WRITE   3246894\n0x400F9580 WRITE   3246965\n0x400F95C0 WRITE   3247021\n0x40175B80 WRITE   3247093\n0x40175B40 WRITE   3247095\n0x400F9600 WRITE   3247131\n0x400F9640 WRITE   3247187\n0x400F9680 WRITE   3247258\n0x400F96C0 WRITE   3247314\n0x400F9700 WRITE   3247400\n0x400F9740 WRITE   3247456\n0x400F9780 WRITE   3247527\n0x400F97C0 WRITE   3247583\n0x40175E00 WRITE   3247666\n0x40175DC0 WRITE   3247668\n0x40175D00 WRITE   3247675\n0x40175CC0 WRITE   3247677\n0x40175C80 WRITE   3247687\n0x40175C40 WRITE   3247689\n0x400F9800 WRITE   3247716\n0x400F9840 WRITE   3247772\n0x400F9880 WRITE   3247838\n0x400F98C0 WRITE   3247894\n0x400F9900 WRITE   3247981\n0x400F9940 WRITE   3248037\n0x400F9980 WRITE   3248100\n0x400F99C0 WRITE   3248156\n0x40175D80 WRITE   3248225\n0x40175D40 WRITE   3248227\n0x400F9A00 WRITE   3248263\n0x400F9A40 WRITE   3248319\n0x400F9A80 WRITE   3248382\n0x400F9AC0 WRITE   3248438\n0x400F9B00 WRITE   3248520\n0x400F9B40 WRITE   3248576\n0x400F9B80 WRITE   3248639\n0x400F9BC0 WRITE   3248695\n0x40175F00 WRITE   3248774\n0x40175EC0 WRITE   3248776\n0x40175E80 WRITE   3248783\n0x40175E40 WRITE   3248785\n0x400F9C00 WRITE   3248818\n0x400F9C40 WRITE   3248874\n0x400F9C80 WRITE   3248948\n0x400F9CC0 WRITE   3249004\n0x400F9D00 WRITE   3249099\n0x400F9D40 WRITE   3249155\n0x400F9D80 WRITE   3249226\n0x400F9DC0 WRITE   3249282\n0x40175F80 WRITE   3249359\n0x40175F40 WRITE   3249361\n0x400F9E00 WRITE   3249397\n0x400F9E40 WRITE   3249453\n0x400F9E80 WRITE   3249524\n0x400F9EC0 WRITE   3249580\n0x400F9F00 WRITE   3249670\n0x400F9F40 WRITE   3249726\n0x400F9F80 WRITE   3249797\n0x400F9FC0 WRITE   3249853\n0x40177FC0 WRITE   3250015\n0x40178000 WRITE   3250047\n0x40177000 WRITE   3250190\n0x40176FC0 WRITE   3250192\n0x40176800 WRITE   3250199\n0x401767C0 WRITE   3250201\n0x40176400 WRITE   3250211\n0x401763C0 WRITE   3250213\n0x40176200 WRITE   3250218\n0x401761C0 WRITE   3250221\n0x40176100 WRITE   3250224\n0x401760C0 WRITE   3250227\n0x40176080 WRITE   3250230\n0x40176040 WRITE   3250233\n0x400FA000 WRITE   3250265\n0x400FA040 WRITE   3250353\n0x400FA080 WRITE   3250419\n0x400FA0C0 WRITE   3250475\n0x400FA100 WRITE   3250558\n0x400FA140 WRITE   3250614\n0x400FA180 WRITE   3250677\n0x400FA1C0 WRITE   3250733\n0x40176180 WRITE   3250789\n0x40176140 WRITE   3250791\n0x400FA200 WRITE   3250827\n0x400FA240 WRITE   3250883\n0x400FA280 WRITE   3250946\n0x400FA2C0 WRITE   3251002\n0x400FA300 WRITE   3251080\n0x400FA340 WRITE   3251136\n0x400FA380 WRITE   3251199\n0x400FA3C0 WRITE   3251255\n0x40176300 WRITE   3251316\n0x401762C0 WRITE   3251318\n0x40176280 WRITE   3251325\n0x40176240 WRITE   3251327\n0x400FA400 WRITE   3251360\n0x400FA440 WRITE   3251416\n0x400FA480 WRITE   3251490\n0x400FA4C0 WRITE   3251546\n0x400FA500 WRITE   3251637\n0x400FA540 WRITE   3251693\n0x400FA580 WRITE   3251764\n0x400FA5C0 WRITE   3251820\n0x40176380 WRITE   3251884\n0x40176340 WRITE   3251886\n0x400FA600 WRITE   3251922\n0x400FA640 WRITE   3251978\n0x400FA680 WRITE   3252049\n0x400FA6C0 WRITE   3252105\n0x400FA700 WRITE   3252191\n0x400FA740 WRITE   3252247\n0x400FA780 WRITE   3252318\n0x400FA7C0 WRITE   3252374\n0x40176600 WRITE   3252443\n0x401765C0 WRITE   3252445\n0x40176500 WRITE   3252452\n0x401764C0 WRITE   3252454\n0x40176480 WRITE   3252464\n0x40176440 WRITE   3252466\n0x400FA800 WRITE   3252493\n0x400FA840 WRITE   3252549\n0x400FA880 WRITE   3252615\n0x400FA8C0 WRITE   3252671\n0x400FA900 WRITE   3252758\n0x400FA940 WRITE   3252814\n0x400FA980 WRITE   3252877\n0x400FA9C0 WRITE   3252933\n0x40176580 WRITE   3252995\n0x40176540 WRITE   3252997\n0x400FAA00 WRITE   3253033\n0x400FAA40 WRITE   3253089\n0x400FAA80 WRITE   3253152\n0x400FAAC0 WRITE   3253208\n0x400FAB00 WRITE   3253290\n0x400FAB40 WRITE   3253346\n0x400FAB80 WRITE   3253409\n0x400FABC0 WRITE   3253465\n0x40176700 WRITE   3253531\n0x401766C0 WRITE   3253533\n0x40176680 WRITE   3253540\n0x40176640 WRITE   3253542\n0x400FAC00 WRITE   3253575\n0x400FAC40 WRITE   3253631\n0x400FAC80 WRITE   3253705\n0x400FACC0 WRITE   3253761\n0x400FAD00 WRITE   3253856\n0x400FAD40 WRITE   3253912\n0x400FAD80 WRITE   3253983\n0x400FADC0 WRITE   3254039\n0x40176780 WRITE   3254109\n0x40176740 WRITE   3254111\n0x400FAE00 WRITE   3254147\n0x400FAE40 WRITE   3254203\n0x400FAE80 WRITE   3254274\n0x400FAEC0 WRITE   3254330\n0x400FAF00 WRITE   3254420\n0x400FAF40 WRITE   3254476\n0x400FAF80 WRITE   3254547\n0x400FAFC0 WRITE   3254603\n0x40176C00 WRITE   3254683\n0x40176BC0 WRITE   3254685\n0x40176A00 WRITE   3254692\n0x401769C0 WRITE   3254694\n0x40176900 WRITE   3254704\n0x401768C0 WRITE   3254706\n0x40176880 WRITE   3254711\n0x40176840 WRITE   3254714\n0x400FB000 WRITE   3254739\n0x400FB040 WRITE   3254823\n0x400FB080 WRITE   3254889\n0x400FB0C0 WRITE   3254945\n0x400FB100 WRITE   3255028\n0x400FB140 WRITE   3255084\n0x400FB180 WRITE   3255147\n0x400FB1C0 WRITE   3255203\n0x40176980 WRITE   3255267\n0x40176940 WRITE   3255269\n0x400FB200 WRITE   3255305\n0x400FB240 WRITE   3255361\n0x400FB280 WRITE   3255424\n0x400FB2C0 WRITE   3255480\n0x400FB300 WRITE   3255558\n0x400FB340 WRITE   3255614\n0x400FB380 WRITE   3255677\n0x400FB3C0 WRITE   3255733\n0x40176B00 WRITE   3255801\n0x40176AC0 WRITE   3255803\n0x40176A80 WRITE   3255810\n0x40176A40 WRITE   3255812\n0x400FB400 WRITE   3255845\n0x400FB440 WRITE   3255901\n0x400FB480 WRITE   3255975\n0x400FB4C0 WRITE   3256031\n0x400FB500 WRITE   3256122\n0x400FB540 WRITE   3256178\n0x400FB580 WRITE   3256249\n0x400FB5C0 WRITE   3256305\n0x40176B80 WRITE   3256377\n0x40176B40 WRITE   3256379\n0x400FB600 WRITE   3256415\n0x400FB640 WRITE   3256471\n0x400FB680 WRITE   3256542\n0x400FB6C0 WRITE   3256598\n0x400FB700 WRITE   3256684\n0x400FB740 WRITE   3256740\n0x400FB780 WRITE   3256811\n0x400FB7C0 WRITE   3256867\n0x40176E00 WRITE   3256944\n0x40176DC0 WRITE   3256946\n0x40176D00 WRITE   3256953\n0x40176CC0 WRITE   3256955\n0x40176C80 WRITE   3256965\n0x40176C40 WRITE   3256967\n0x400FB800 WRITE   3256994\n0x400FB840 WRITE   3257050\n0x400FB880 WRITE   3257116\n0x400FB8C0 WRITE   3257172\n0x400FB900 WRITE   3257259\n0x400FB940 WRITE   3257315\n0x400FB980 WRITE   3257378\n0x400FB9C0 WRITE   3257434\n0x40176D80 WRITE   3257503\n0x40176D40 WRITE   3257505\n0x400FBA00 WRITE   3257541\n0x400FBA40 WRITE   3257597\n0x400FBA80 WRITE   3257660\n0x400FBAC0 WRITE   3257716\n0x400FBB00 WRITE   3257798\n0x400FBB40 WRITE   3257854\n0x400FBB80 WRITE   3257917\n0x400FBBC0 WRITE   3257973\n0x40176F00 WRITE   3258046\n0x40176EC0 WRITE   3258048\n0x40176E80 WRITE   3258055\n0x40176E40 WRITE   3258057\n0x400FBC00 WRITE   3258090\n0x400FBC40 WRITE   3258146\n0x400FBC80 WRITE   3258220\n0x400FBCC0 WRITE   3258276\n0x400FBD00 WRITE   3258371\n0x400FBD40 WRITE   3258427\n0x400FBD80 WRITE   3258498\n0x400FBDC0 WRITE   3258554\n0x40176F80 WRITE   3258631\n0x40176F40 WRITE   3258633\n0x400FBE00 WRITE   3258669\n0x400FBE40 WRITE   3258725\n0x400FBE80 WRITE   3258796\n0x400FBEC0 WRITE   3258852\n0x400FBF00 WRITE   3258942\n0x400FBF40 WRITE   3258998\n0x400FBF80 WRITE   3259069\n0x400FBFC0 WRITE   3259125\n0x40177800 WRITE   3259211\n0x401777C0 WRITE   3259213\n0x40177400 WRITE   3259220\n0x401773C0 WRITE   3259222\n0x40177200 WRITE   3259232\n0x401771C0 WRITE   3259234\n0x40177100 WRITE   3259239\n0x401770C0 WRITE   3259242\n0x40177080 WRITE   3259245\n0x40177040 WRITE   3259248\n0x400FC000 WRITE   3259273\n0x400FC040 WRITE   3259357\n0x400FC080 WRITE   3259423\n0x400FC0C0 WRITE   3259479\n0x400FC100 WRITE   3259562\n0x400FC140 WRITE   3259618\n0x400FC180 WRITE   3259681\n0x400FC1C0 WRITE   3259737\n0x40177180 WRITE   3259793\n0x40177140 WRITE   3259795\n0x400FC200 WRITE   3259831\n0x400FC240 WRITE   3259887\n0x400FC280 WRITE   3259950\n0x400FC2C0 WRITE   3260006\n0x400FC300 WRITE   3260084\n0x400FC340 WRITE   3260140\n0x400FC380 WRITE   3260203\n0x400FC3C0 WRITE   3260259\n0x40177300 WRITE   3260325\n0x401772C0 WRITE   3260327\n0x40177280 WRITE   3260334\n0x40177240 WRITE   3260336\n0x400FC400 WRITE   3260369\n0x400FC440 WRITE   3260425\n0x400FC480 WRITE   3260499\n0x400FC4C0 WRITE   3260555\n0x400FC500 WRITE   3260646\n0x400FC540 WRITE   3260702\n0x400FC580 WRITE   3260773\n0x400FC5C0 WRITE   3260829\n0x40177380 WRITE   3260893\n0x40177340 WRITE   3260895\n0x400FC600 WRITE   3260931\n0x400FC640 WRITE   3260987\n0x400FC680 WRITE   3261058\n0x400FC6C0 WRITE   3261114\n0x400FC700 WRITE   3261200\n0x400FC740 WRITE   3261256\n0x400FC780 WRITE   3261327\n0x400FC7C0 WRITE   3261383\n0x40177600 WRITE   3261458\n0x401775C0 WRITE   3261460\n0x40177500 WRITE   3261467\n0x401774C0 WRITE   3261469\n0x40177480 WRITE   3261479\n0x40177440 WRITE   3261481\n0x400FC800 WRITE   3261508\n0x400FC840 WRITE   3261564\n0x400FC880 WRITE   3261630\n0x400FC8C0 WRITE   3261686\n0x400FC900 WRITE   3261773\n0x400FC940 WRITE   3261829\n0x400FC980 WRITE   3261892\n0x400FC9C0 WRITE   3261948\n0x40177580 WRITE   3262010\n0x40177540 WRITE   3262012\n0x400FCA00 WRITE   3262048\n0x400FCA40 WRITE   3262104\n0x400FCA80 WRITE   3262167\n0x400FCAC0 WRITE   3262223\n0x400FCB00 WRITE   3262305\n0x400FCB40 WRITE   3262361\n0x400FCB80 WRITE   3262424\n0x400FCBC0 WRITE   3262480\n0x40177700 WRITE   3262552\n0x401776C0 WRITE   3262554\n0x40177680 WRITE   3262561\n0x40177640 WRITE   3262563\n0x400FCC00 WRITE   3262596\n0x400FCC40 WRITE   3262652\n0x400FCC80 WRITE   3262726\n0x400FCCC0 WRITE   3262782\n0x400FCD00 WRITE   3262877\n0x400FCD40 WRITE   3262933\n0x400FCD80 WRITE   3263004\n0x400FCDC0 WRITE   3263060\n0x40177780 WRITE   3263130\n0x40177740 WRITE   3263132\n0x400FCE00 WRITE   3263168\n0x400FCE40 WRITE   3263224\n0x400FCE80 WRITE   3263295\n0x400FCEC0 WRITE   3263351\n0x400FCF00 WRITE   3263441\n0x400FCF40 WRITE   3263497\n0x400FCF80 WRITE   3263568\n0x400FCFC0 WRITE   3263624\n0x40177C00 WRITE   3263710\n0x40177BC0 WRITE   3263712\n0x40177A00 WRITE   3263719\n0x401779C0 WRITE   3263721\n0x40177900 WRITE   3263731\n0x401778C0 WRITE   3263733\n0x40177880 WRITE   3263738\n0x40177840 WRITE   3263741\n0x400FD000 WRITE   3263766\n0x400FD040 WRITE   3263850\n0x400FD080 WRITE   3263916\n0x400FD0C0 WRITE   3263972\n0x400FD100 WRITE   3264055\n0x400FD140 WRITE   3264111\n0x400FD180 WRITE   3264174\n0x400FD1C0 WRITE   3264230\n0x40177980 WRITE   3264294\n0x40177940 WRITE   3264296\n0x400FD200 WRITE   3264332\n0x400FD240 WRITE   3264388\n0x400FD280 WRITE   3264451\n0x400FD2C0 WRITE   3264507\n0x400FD300 WRITE   3264585\n0x400FD340 WRITE   3264641\n0x400FD380 WRITE   3264704\n0x400FD3C0 WRITE   3264760\n0x40177B00 WRITE   3264834\n0x40177AC0 WRITE   3264836\n0x40177A80 WRITE   3264843\n0x40177A40 WRITE   3264845\n0x400FD400 WRITE   3264878\n0x400FD440 WRITE   3264934\n0x400FD480 WRITE   3265008\n0x400FD4C0 WRITE   3265064\n0x400FD500 WRITE   3265155\n0x400FD540 WRITE   3265211\n0x400FD580 WRITE   3265282\n0x400FD5C0 WRITE   3265338\n0x40177B80 WRITE   3265410\n0x40177B40 WRITE   3265412\n0x400FD600 WRITE   3265448\n0x400FD640 WRITE   3265504\n0x400FD680 WRITE   3265575\n0x400FD6C0 WRITE   3265631\n0x400FD700 WRITE   3265717\n0x400FD740 WRITE   3265773\n0x400FD780 WRITE   3265844\n0x400FD7C0 WRITE   3265900\n0x40177E00 WRITE   3265983\n0x40177DC0 WRITE   3265985\n0x40177D00 WRITE   3265992\n0x40177CC0 WRITE   3265994\n0x40177C80 WRITE   3266004\n0x40177C40 WRITE   3266006\n0x400FD800 WRITE   3266033\n0x400FD840 WRITE   3266089\n0x400FD880 WRITE   3266155\n0x400FD8C0 WRITE   3266211\n0x400FD900 WRITE   3266298\n0x400FD940 WRITE   3266354\n0x400FD980 WRITE   3266417\n0x400FD9C0 WRITE   3266473\n0x40177D80 WRITE   3266542\n0x40177D40 WRITE   3266544\n0x400FDA00 WRITE   3266580\n0x400FDA40 WRITE   3266636\n0x400FDA80 WRITE   3266699\n0x400FDAC0 WRITE   3266755\n0x400FDB00 WRITE   3266837\n0x400FDB40 WRITE   3266893\n0x400FDB80 WRITE   3266956\n0x400FDBC0 WRITE   3267012\n0x40177F00 WRITE   3267091\n0x40177EC0 WRITE   3267093\n0x40177E80 WRITE   3267100\n0x40177E40 WRITE   3267102\n0x400FDC00 WRITE   3267135\n0x400FDC40 WRITE   3267191\n0x400FDC80 WRITE   3267265\n0x400FDCC0 WRITE   3267321\n0x400FDD00 WRITE   3267416\n0x400FDD40 WRITE   3267472\n0x400FDD80 WRITE   3267543\n0x400FDDC0 WRITE   3267599\n0x40177F80 WRITE   3267676\n0x40177F40 WRITE   3267678\n0x400FDE00 WRITE   3267714\n0x400FDE40 WRITE   3267770\n0x400FDE80 WRITE   3267841\n0x400FDEC0 WRITE   3267897\n0x400FDF00 WRITE   3267987\n0x400FDF40 WRITE   3268043\n0x400FDF80 WRITE   3268114\n0x400FDFC0 WRITE   3268170\n0x40179FC0 WRITE   3268332\n0x4017A000 WRITE   3268364\n0x40179000 WRITE   3268491\n0x40178FC0 WRITE   3268493\n0x40178800 WRITE   3268500\n0x401787C0 WRITE   3268502\n0x40178400 WRITE   3268512\n0x401783C0 WRITE   3268514\n0x40178200 WRITE   3268519\n0x401781C0 WRITE   3268522\n0x40178100 WRITE   3268525\n0x401780C0 WRITE   3268528\n0x40178080 WRITE   3268531\n0x40178040 WRITE   3268534\n0x400FE000 WRITE   3268566\n0x400FE040 WRITE   3268654\n0x400FE080 WRITE   3268720\n0x400FE0C0 WRITE   3268776\n0x400FE100 WRITE   3268859\n0x400FE140 WRITE   3268915\n0x400FE180 WRITE   3268978\n0x400FE1C0 WRITE   3269034\n0x40178180 WRITE   3269090\n0x40178140 WRITE   3269092\n0x400FE200 WRITE   3269128\n0x400FE240 WRITE   3269184\n0x400FE280 WRITE   3269247\n0x400FE2C0 WRITE   3269303\n0x400FE300 WRITE   3269381\n0x400FE340 WRITE   3269437\n0x400FE380 WRITE   3269500\n0x400FE3C0 WRITE   3269556\n0x40178300 WRITE   3269617\n0x401782C0 WRITE   3269619\n0x40178280 WRITE   3269626\n0x40178240 WRITE   3269628\n0x400FE400 WRITE   3269661\n0x400FE440 WRITE   3269717\n0x400FE480 WRITE   3269791\n0x400FE4C0 WRITE   3269847\n0x400FE500 WRITE   3269938\n0x400FE540 WRITE   3269994\n0x400FE580 WRITE   3270065\n0x400FE5C0 WRITE   3270121\n0x40178380 WRITE   3270185\n0x40178340 WRITE   3270187\n0x400FE600 WRITE   3270223\n0x400FE640 WRITE   3270279\n0x400FE680 WRITE   3270350\n0x400FE6C0 WRITE   3270406\n0x400FE700 WRITE   3270492\n0x400FE740 WRITE   3270548\n0x400FE780 WRITE   3270619\n0x400FE7C0 WRITE   3270675\n0x40178600 WRITE   3270744\n0x401785C0 WRITE   3270746\n0x40178500 WRITE   3270753\n0x401784C0 WRITE   3270755\n0x40178480 WRITE   3270765\n0x40178440 WRITE   3270767\n0x400FE800 WRITE   3270794\n0x400FE840 WRITE   3270850\n0x400FE880 WRITE   3270916\n0x400FE8C0 WRITE   3270972\n0x400FE900 WRITE   3271059\n0x400FE940 WRITE   3271115\n0x400FE980 WRITE   3271178\n0x400FE9C0 WRITE   3271234\n0x40178580 WRITE   3271296\n0x40178540 WRITE   3271298\n0x400FEA00 WRITE   3271334\n0x400FEA40 WRITE   3271390\n0x400FEA80 WRITE   3271453\n0x400FEAC0 WRITE   3271509\n0x400FEB00 WRITE   3271591\n0x400FEB40 WRITE   3271647\n0x400FEB80 WRITE   3271710\n0x400FEBC0 WRITE   3271766\n0x40178700 WRITE   3271832\n0x401786C0 WRITE   3271834\n0x40178680 WRITE   3271841\n0x40178640 WRITE   3271843\n0x400FEC00 WRITE   3271876\n0x400FEC40 WRITE   3271932\n0x400FEC80 WRITE   3272006\n0x400FECC0 WRITE   3272062\n0x400FED00 WRITE   3272157\n0x400FED40 WRITE   3272213\n0x400FED80 WRITE   3272284\n0x400FEDC0 WRITE   3272340\n0x40178780 WRITE   3272410\n0x40178740 WRITE   3272412\n0x400FEE00 WRITE   3272448\n0x400FEE40 WRITE   3272504\n0x400FEE80 WRITE   3272575\n0x400FEEC0 WRITE   3272631\n0x400FEF00 WRITE   3272721\n0x400FEF40 WRITE   3272777\n0x400FEF80 WRITE   3272848\n0x400FEFC0 WRITE   3272904\n0x40178C00 WRITE   3272984\n0x40178BC0 WRITE   3272986\n0x40178A00 WRITE   3272993\n0x401789C0 WRITE   3272995\n0x40178900 WRITE   3273005\n0x401788C0 WRITE   3273007\n0x40178880 WRITE   3273012\n0x40178840 WRITE   3273015\n0x400FF000 WRITE   3273040\n0x400FF040 WRITE   3273124\n0x400FF080 WRITE   3273190\n0x400FF0C0 WRITE   3273246\n0x400FF100 WRITE   3273329\n0x400FF140 WRITE   3273385\n0x400FF180 WRITE   3273448\n0x400FF1C0 WRITE   3273504\n0x40178980 WRITE   3273568\n0x40178940 WRITE   3273570\n0x400FF200 WRITE   3273606\n0x400FF240 WRITE   3273662\n0x400FF280 WRITE   3273725\n0x400FF2C0 WRITE   3273781\n0x400FF300 WRITE   3273859\n0x400FF340 WRITE   3273915\n0x400FF380 WRITE   3273978\n0x400FF3C0 WRITE   3274034\n0x40178B00 WRITE   3274102\n0x40178AC0 WRITE   3274104\n0x40178A80 WRITE   3274111\n0x40178A40 WRITE   3274113\n0x400FF400 WRITE   3274146\n0x400FF440 WRITE   3274202\n0x400FF480 WRITE   3274276\n0x400FF4C0 WRITE   3274332\n0x400FF500 WRITE   3274423\n0x400FF540 WRITE   3274479\n0x400FF580 WRITE   3274550\n0x400FF5C0 WRITE   3274606\n0x40178B80 WRITE   3274678\n0x40178B40 WRITE   3274680\n0x400FF600 WRITE   3274716\n0x400FF640 WRITE   3274772\n0x400FF680 WRITE   3274843\n0x400FF6C0 WRITE   3274899\n0x400FF700 WRITE   3274985\n0x400FF740 WRITE   3275041\n0x400FF780 WRITE   3275112\n0x400FF7C0 WRITE   3275168\n0x40178E00 WRITE   3275245\n0x40178DC0 WRITE   3275247\n0x40178D00 WRITE   3275254\n0x40178CC0 WRITE   3275256\n0x40178C80 WRITE   3275266\n0x40178C40 WRITE   3275268\n0x400FF800 WRITE   3275295\n0x400FF840 WRITE   3275351\n0x400FF880 WRITE   3275417\n0x400FF8C0 WRITE   3275473\n0x400FF900 WRITE   3275560\n0x400FF940 WRITE   3275616\n0x400FF980 WRITE   3275679\n0x400FF9C0 WRITE   3275735\n0x40178D80 WRITE   3275804\n0x40178D40 WRITE   3275806\n0x400FFA00 WRITE   3275842\n0x400FFA40 WRITE   3275898\n0x400FFA80 WRITE   3275961\n0x400FFAC0 WRITE   3276017\n0x400FFB00 WRITE   3276099\n0x400FFB40 WRITE   3276155\n0x400FFB80 WRITE   3276218\n0x400FFBC0 WRITE   3276274\n0x40178F00 WRITE   3276347\n0x40178EC0 WRITE   3276349\n0x40178E80 WRITE   3276356\n0x40178E40 WRITE   3276358\n0x400FFC00 WRITE   3276391\n0x400FFC40 WRITE   3276447\n0x400FFC80 WRITE   3276521\n0x400FFCC0 WRITE   3276577\n0x400FFD00 WRITE   3276672\n0x400FFD40 WRITE   3276728\n0x400FFD80 WRITE   3276799\n0x400FFDC0 WRITE   3276855\n0x40178F80 WRITE   3276932\n0x40178F40 WRITE   3276934\n0x400FFE00 WRITE   3276970\n0x400FFE40 WRITE   3277026\n0x400FFE80 WRITE   3277097\n0x400FFEC0 WRITE   3277153\n0x400FFF00 WRITE   3277243\n0x400FFF40 WRITE   3277299\n0x400FFF80 WRITE   3277370\n0x400FFFC0 WRITE   3277426\n0x40179800 WRITE   3277512\n0x401797C0 WRITE   3277514\n0x40179400 WRITE   3277521\n0x401793C0 WRITE   3277523\n0x40179200 WRITE   3277533\n0x401791C0 WRITE   3277535\n0x40179100 WRITE   3277540\n0x401790C0 WRITE   3277543\n0x40179080 WRITE   3277546\n0x40179040 WRITE   3277549\n0x40100000 WRITE   3277574\n0x40100040 WRITE   3277658\n0x40100080 WRITE   3277724\n0x401000C0 WRITE   3277780\n0x40100100 WRITE   3277863\n0x40100140 WRITE   3277919\n0x40100180 WRITE   3277982\n0x401001C0 WRITE   3278038\n0x40179180 WRITE   3278094\n0x40179140 WRITE   3278096\n0x40100200 WRITE   3278132\n0x40100240 WRITE   3278188\n0x40100280 WRITE   3278251\n0x401002C0 WRITE   3278307\n0x40100300 WRITE   3278385\n0x40100340 WRITE   3278441\n0x40100380 WRITE   3278504\n0x401003C0 WRITE   3278560\n0x40179300 WRITE   3278626\n0x401792C0 WRITE   3278628\n0x40179280 WRITE   3278635\n0x40179240 WRITE   3278637\n0x40100400 WRITE   3278670\n0x40100440 WRITE   3278726\n0x40100480 WRITE   3278800\n0x401004C0 WRITE   3278856\n0x40100500 WRITE   3278947\n0x40100540 WRITE   3279003\n0x40100580 WRITE   3279074\n0x401005C0 WRITE   3279130\n0x40179380 WRITE   3279194\n0x40179340 WRITE   3279196\n0x40100600 WRITE   3279232\n0x40100640 WRITE   3279288\n0x40100680 WRITE   3279359\n0x401006C0 WRITE   3279415\n0x40100700 WRITE   3279501\n0x40100740 WRITE   3279557\n0x40100780 WRITE   3279628\n0x401007C0 WRITE   3279684\n0x40179600 WRITE   3279759\n0x401795C0 WRITE   3279761\n0x40179500 WRITE   3279768\n0x401794C0 WRITE   3279770\n0x40179480 WRITE   3279780\n0x40179440 WRITE   3279782\n0x40100800 WRITE   3279809\n0x40100840 WRITE   3279865\n0x40100880 WRITE   3279931\n0x401008C0 WRITE   3279987\n0x40100900 WRITE   3280074\n0x40100940 WRITE   3280130\n0x40100980 WRITE   3280193\n0x401009C0 WRITE   3280249\n0x40179580 WRITE   3280311\n0x40179540 WRITE   3280313\n0x40100A00 WRITE   3280349\n0x40100A40 WRITE   3280405\n0x40100A80 WRITE   3280468\n0x40100AC0 WRITE   3280524\n0x40100B00 WRITE   3280606\n0x40100B40 WRITE   3280662\n0x40100B80 WRITE   3280725\n0x40100BC0 WRITE   3280781\n0x40179700 WRITE   3280853\n0x401796C0 WRITE   3280855\n0x40179680 WRITE   3280862\n0x40179640 WRITE   3280864\n0x40100C00 WRITE   3280897\n0x40100C40 WRITE   3280953\n0x40100C80 WRITE   3281027\n0x40100CC0 WRITE   3281083\n0x40100D00 WRITE   3281178\n0x40100D40 WRITE   3281234\n0x40100D80 WRITE   3281305\n0x40100DC0 WRITE   3281361\n0x40179780 WRITE   3281431\n0x40179740 WRITE   3281433\n0x40100E00 WRITE   3281469\n0x40100E40 WRITE   3281525\n0x40100E80 WRITE   3281596\n0x40100EC0 WRITE   3281652\n0x40100F00 WRITE   3281742\n0x40100F40 WRITE   3281798\n0x40100F80 WRITE   3281869\n0x40100FC0 WRITE   3281925\n0x40179C00 WRITE   3282011\n0x40179BC0 WRITE   3282013\n0x40179A00 WRITE   3282020\n0x401799C0 WRITE   3282022\n0x40179900 WRITE   3282032\n0x401798C0 WRITE   3282034\n0x40179880 WRITE   3282039\n0x40179840 WRITE   3282042\n0x40101000 WRITE   3282067\n0x40101040 WRITE   3282151\n0x40101080 WRITE   3282217\n0x401010C0 WRITE   3282273\n0x40101100 WRITE   3282356\n0x40101140 WRITE   3282412\n0x40101180 WRITE   3282475\n0x401011C0 WRITE   3282531\n0x40179980 WRITE   3282595\n0x40179940 WRITE   3282597\n0x40101200 WRITE   3282633\n0x40101240 WRITE   3282689\n0x40101280 WRITE   3282752\n0x401012C0 WRITE   3282808\n0x40101300 WRITE   3282886\n0x40101340 WRITE   3282942\n0x40101380 WRITE   3283005\n0x401013C0 WRITE   3283061\n0x40179B00 WRITE   3283135\n0x40179AC0 WRITE   3283137\n0x40179A80 WRITE   3283144\n0x40179A40 WRITE   3283146\n0x40101400 WRITE   3283179\n0x40101440 WRITE   3283235\n0x40101480 WRITE   3283309\n0x401014C0 WRITE   3283365\n0x40101500 WRITE   3283456\n0x40101540 WRITE   3283512\n0x40101580 WRITE   3283583\n0x401015C0 WRITE   3283639\n0x40179B80 WRITE   3283711\n0x40179B40 WRITE   3283713\n0x40101600 WRITE   3283749\n0x40101640 WRITE   3283805\n0x40101680 WRITE   3283876\n0x401016C0 WRITE   3283932\n0x40101700 WRITE   3284018\n0x40101740 WRITE   3284074\n0x40101780 WRITE   3284145\n0x401017C0 WRITE   3284201\n0x40179E00 WRITE   3284284\n0x40179DC0 WRITE   3284286\n0x40179D00 WRITE   3284293\n0x40179CC0 WRITE   3284295\n0x40179C80 WRITE   3284305\n0x40179C40 WRITE   3284307\n0x40101800 WRITE   3284334\n0x40101840 WRITE   3284390\n0x40101880 WRITE   3284456\n0x401018C0 WRITE   3284512\n0x40101900 WRITE   3284599\n0x40101940 WRITE   3284655\n0x40101980 WRITE   3284718\n0x401019C0 WRITE   3284774\n0x40179D80 WRITE   3284843\n0x40179D40 WRITE   3284845\n0x40101A00 WRITE   3284881\n0x40101A40 WRITE   3284937\n0x40101A80 WRITE   3285000\n0x40101AC0 WRITE   3285056\n0x40101B00 WRITE   3285138\n0x40101B40 WRITE   3285194\n0x40101B80 WRITE   3285257\n0x40101BC0 WRITE   3285313\n0x40179F00 WRITE   3285392\n0x40179EC0 WRITE   3285394\n0x40179E80 WRITE   3285401\n0x40179E40 WRITE   3285403\n0x40101C00 WRITE   3285436\n0x40101C40 WRITE   3285492\n0x40101C80 WRITE   3285566\n0x40101CC0 WRITE   3285622\n0x40101D00 WRITE   3285717\n0x40101D40 WRITE   3285773\n0x40101D80 WRITE   3285844\n0x40101DC0 WRITE   3285900\n0x40179F80 WRITE   3285977\n0x40179F40 WRITE   3285979\n0x40101E00 WRITE   3286015\n0x40101E40 WRITE   3286071\n0x40101E80 WRITE   3286142\n0x40101EC0 WRITE   3286198\n0x40101F00 WRITE   3286288\n0x40101F40 WRITE   3286344\n0x40101F80 WRITE   3286415\n0x40101FC0 WRITE   3286471\n0x4017BFC0 WRITE   3286633\n0x4017C000 WRITE   3286665\n0x4017B000 WRITE   3286792\n0x4017AFC0 WRITE   3286794\n0x4017A800 WRITE   3286801\n0x4017A7C0 WRITE   3286803\n0x4017A400 WRITE   3286813\n0x4017A3C0 WRITE   3286815\n0x4017A200 WRITE   3286820\n0x4017A1C0 WRITE   3286823\n0x4017A100 WRITE   3286826\n0x4017A0C0 WRITE   3286829\n0x4017A080 WRITE   3286832\n0x4017A040 WRITE   3286835\n0x40102000 WRITE   3286867\n0x40102040 WRITE   3286955\n0x40102080 WRITE   3287021\n0x401020C0 WRITE   3287077\n0x40102100 WRITE   3287160\n0x40102140 WRITE   3287216\n0x40102180 WRITE   3287279\n0x401021C0 WRITE   3287335\n0x4017A180 WRITE   3287391\n0x4017A140 WRITE   3287393\n0x40102200 WRITE   3287429\n0x40102240 WRITE   3287485\n0x40102280 WRITE   3287548\n0x401022C0 WRITE   3287604\n0x40102300 WRITE   3287682\n0x40102340 WRITE   3287738\n0x40102380 WRITE   3287801\n0x401023C0 WRITE   3287857\n0x4017A300 WRITE   3287918\n0x4017A2C0 WRITE   3287920\n0x4017A280 WRITE   3287927\n0x4017A240 WRITE   3287929\n0x40102400 WRITE   3287962\n0x40102440 WRITE   3288018\n0x40102480 WRITE   3288092\n0x401024C0 WRITE   3288148\n0x40102500 WRITE   3288239\n0x40102540 WRITE   3288295\n0x40102580 WRITE   3288366\n0x401025C0 WRITE   3288422\n0x4017A380 WRITE   3288486\n0x4017A340 WRITE   3288488\n0x40102600 WRITE   3288524\n0x40102640 WRITE   3288580\n0x40102680 WRITE   3288651\n0x401026C0 WRITE   3288707\n0x40102700 WRITE   3288793\n0x40102740 WRITE   3288849\n0x40102780 WRITE   3288920\n0x401027C0 WRITE   3288976\n0x4017A600 WRITE   3289045\n0x4017A5C0 WRITE   3289047\n0x4017A500 WRITE   3289054\n0x4017A4C0 WRITE   3289056\n0x4017A480 WRITE   3289066\n0x4017A440 WRITE   3289068\n0x40102800 WRITE   3289095\n0x40102840 WRITE   3289151\n0x40102880 WRITE   3289217\n0x401028C0 WRITE   3289273\n0x40102900 WRITE   3289360\n0x40102940 WRITE   3289416\n0x40102980 WRITE   3289479\n0x401029C0 WRITE   3289535\n0x4017A580 WRITE   3289597\n0x4017A540 WRITE   3289599\n0x40102A00 WRITE   3289635\n0x40102A40 WRITE   3289691\n0x40102A80 WRITE   3289754\n0x40102AC0 WRITE   3289810\n0x40102B00 WRITE   3289892\n0x40102B40 WRITE   3289948\n0x40102B80 WRITE   3290011\n0x40102BC0 WRITE   3290067\n0x4017A700 WRITE   3290133\n0x4017A6C0 WRITE   3290135\n0x4017A680 WRITE   3290142\n0x4017A640 WRITE   3290144\n0x40102C00 WRITE   3290177\n0x40102C40 WRITE   3290233\n0x40102C80 WRITE   3290307\n0x40102CC0 WRITE   3290363\n0x40102D00 WRITE   3290458\n0x40102D40 WRITE   3290514\n0x40102D80 WRITE   3290585\n0x40102DC0 WRITE   3290641\n0x4017A780 WRITE   3290711\n0x4017A740 WRITE   3290713\n0x40102E00 WRITE   3290749\n0x40102E40 WRITE   3290805\n0x40102E80 WRITE   3290876\n0x40102EC0 WRITE   3290932\n0x40102F00 WRITE   3291022\n0x40102F40 WRITE   3291078\n0x40102F80 WRITE   3291149\n0x40102FC0 WRITE   3291205\n0x4017AC00 WRITE   3291285\n0x4017ABC0 WRITE   3291287\n0x4017AA00 WRITE   3291294\n0x4017A9C0 WRITE   3291296\n0x4017A900 WRITE   3291306\n0x4017A8C0 WRITE   3291308\n0x4017A880 WRITE   3291313\n0x4017A840 WRITE   3291316\n0x40103000 WRITE   3291341\n0x40103040 WRITE   3291425\n0x40103080 WRITE   3291491\n0x401030C0 WRITE   3291547\n0x40103100 WRITE   3291630\n0x40103140 WRITE   3291686\n0x40103180 WRITE   3291749\n0x401031C0 WRITE   3291805\n0x4017A980 WRITE   3291869\n0x4017A940 WRITE   3291871\n0x40103200 WRITE   3291907\n0x40103240 WRITE   3291963\n0x40103280 WRITE   3292026\n0x401032C0 WRITE   3292082\n0x40103300 WRITE   3292160\n0x40103340 WRITE   3292216\n0x40103380 WRITE   3292279\n0x401033C0 WRITE   3292335\n0x4017AB00 WRITE   3292403\n0x4017AAC0 WRITE   3292405\n0x4017AA80 WRITE   3292412\n0x4017AA40 WRITE   3292414\n0x40103400 WRITE   3292447\n0x40103440 WRITE   3292503\n0x40103480 WRITE   3292577\n0x401034C0 WRITE   3292633\n0x40103500 WRITE   3292724\n0x40103540 WRITE   3292780\n0x40103580 WRITE   3292851\n0x401035C0 WRITE   3292907\n0x4017AB80 WRITE   3292979\n0x4017AB40 WRITE   3292981\n0x40103600 WRITE   3293017\n0x40103640 WRITE   3293073\n0x40103680 WRITE   3293144\n0x401036C0 WRITE   3293200\n0x40103700 WRITE   3293286\n0x40103740 WRITE   3293342\n0x40103780 WRITE   3293413\n0x401037C0 WRITE   3293469\n0x4017AE00 WRITE   3293546\n0x4017ADC0 WRITE   3293548\n0x4017AD00 WRITE   3293555\n0x4017ACC0 WRITE   3293557\n0x4017AC80 WRITE   3293567\n0x4017AC40 WRITE   3293569\n0x40103800 WRITE   3293596\n0x40103840 WRITE   3293652\n0x40103880 WRITE   3293718\n0x401038C0 WRITE   3293774\n0x40103900 WRITE   3293861\n0x40103940 WRITE   3293917\n0x40103980 WRITE   3293980\n0x401039C0 WRITE   3294036\n0x4017AD80 WRITE   3294105\n0x4017AD40 WRITE   3294107\n0x40103A00 WRITE   3294143\n0x40103A40 WRITE   3294199\n0x40103A80 WRITE   3294262\n0x40103AC0 WRITE   3294318\n0x40103B00 WRITE   3294400\n0x40103B40 WRITE   3294456\n0x40103B80 WRITE   3294519\n0x40103BC0 WRITE   3294575\n0x4017AF00 WRITE   3294648\n0x4017AEC0 WRITE   3294650\n0x4017AE80 WRITE   3294657\n0x4017AE40 WRITE   3294659\n0x40103C00 WRITE   3294692\n0x40103C40 WRITE   3294748\n0x40103C80 WRITE   3294822\n0x40103CC0 WRITE   3294878\n0x40103D00 WRITE   3294973\n0x40103D40 WRITE   3295029\n0x40103D80 WRITE   3295100\n0x40103DC0 WRITE   3295156\n0x4017AF80 WRITE   3295233\n0x4017AF40 WRITE   3295235\n0x40103E00 WRITE   3295271\n0x40103E40 WRITE   3295327\n0x40103E80 WRITE   3295398\n0x40103EC0 WRITE   3295454\n0x40103F00 WRITE   3295544\n0x40103F40 WRITE   3295600\n0x40103F80 WRITE   3295671\n0x40103FC0 WRITE   3295727\n0x4017B800 WRITE   3295813\n0x4017B7C0 WRITE   3295815\n0x4017B400 WRITE   3295822\n0x4017B3C0 WRITE   3295824\n0x4017B200 WRITE   3295834\n0x4017B1C0 WRITE   3295836\n0x4017B100 WRITE   3295841\n0x4017B0C0 WRITE   3295844\n0x4017B080 WRITE   3295847\n0x4017B040 WRITE   3295850\n0x40104000 WRITE   3295875\n0x40104040 WRITE   3295959\n0x40104080 WRITE   3296025\n0x401040C0 WRITE   3296081\n0x40104100 WRITE   3296164\n0x40104140 WRITE   3296220\n0x40104180 WRITE   3296283\n0x401041C0 WRITE   3296339\n0x4017B180 WRITE   3296395\n0x4017B140 WRITE   3296397\n0x40104200 WRITE   3296433\n0x40104240 WRITE   3296489\n0x40104280 WRITE   3296552\n0x401042C0 WRITE   3296608\n0x40104300 WRITE   3296686\n0x40104340 WRITE   3296742\n0x40104380 WRITE   3296805\n0x401043C0 WRITE   3296861\n0x4017B300 WRITE   3296927\n0x4017B2C0 WRITE   3296929\n0x4017B280 WRITE   3296936\n0x4017B240 WRITE   3296938\n0x40104400 WRITE   3296971\n0x40104440 WRITE   3297027\n0x40104480 WRITE   3297101\n0x401044C0 WRITE   3297157\n0x40104500 WRITE   3297248\n0x40104540 WRITE   3297304\n0x40104580 WRITE   3297375\n0x401045C0 WRITE   3297431\n0x4017B380 WRITE   3297495\n0x4017B340 WRITE   3297497\n0x40104600 WRITE   3297533\n0x40104640 WRITE   3297589\n0x40104680 WRITE   3297660\n0x401046C0 WRITE   3297716\n0x40104700 WRITE   3297802\n0x40104740 WRITE   3297858\n0x40104780 WRITE   3297929\n0x401047C0 WRITE   3297985\n0x4017B600 WRITE   3298060\n0x4017B5C0 WRITE   3298062\n0x4017B500 WRITE   3298069\n0x4017B4C0 WRITE   3298071\n0x4017B480 WRITE   3298081\n0x4017B440 WRITE   3298083\n0x40104800 WRITE   3298110\n0x40104840 WRITE   3298166\n0x40104880 WRITE   3298232\n0x401048C0 WRITE   3298288\n0x40104900 WRITE   3298375\n0x40104940 WRITE   3298431\n0x40104980 WRITE   3298494\n0x401049C0 WRITE   3298550\n0x4017B580 WRITE   3298612\n0x4017B540 WRITE   3298614\n0x40104A00 WRITE   3298650\n0x40104A40 WRITE   3298706\n0x40104A80 WRITE   3298769\n0x40104AC0 WRITE   3298825\n0x40104B00 WRITE   3298907\n0x40104B40 WRITE   3298963\n0x40104B80 WRITE   3299026\n0x40104BC0 WRITE   3299082\n0x4017B700 WRITE   3299154\n0x4017B6C0 WRITE   3299156\n0x4017B680 WRITE   3299163\n0x4017B640 WRITE   3299165\n0x40104C00 WRITE   3299198\n0x40104C40 WRITE   3299254\n0x40104C80 WRITE   3299328\n0x40104CC0 WRITE   3299384\n0x40104D00 WRITE   3299479\n0x40104D40 WRITE   3299535\n0x40104D80 WRITE   3299606\n0x40104DC0 WRITE   3299662\n0x4017B780 WRITE   3299732\n0x4017B740 WRITE   3299734\n0x40104E00 WRITE   3299770\n0x40104E40 WRITE   3299826\n0x40104E80 WRITE   3299897\n0x40104EC0 WRITE   3299953\n0x40104F00 WRITE   3300043\n0x40104F40 WRITE   3300099\n0x40104F80 WRITE   3300170\n0x40104FC0 WRITE   3300226\n0x4017BC00 WRITE   3300312\n0x4017BBC0 WRITE   3300314\n0x4017BA00 WRITE   3300321\n0x4017B9C0 WRITE   3300323\n0x4017B900 WRITE   3300333\n0x4017B8C0 WRITE   3300335\n0x4017B880 WRITE   3300340\n0x4017B840 WRITE   3300343\n0x40105000 WRITE   3300368\n0x40105040 WRITE   3300452\n0x40105080 WRITE   3300518\n0x401050C0 WRITE   3300574\n0x40105100 WRITE   3300657\n0x40105140 WRITE   3300713\n0x40105180 WRITE   3300776\n0x401051C0 WRITE   3300832\n0x4017B980 WRITE   3300896\n0x4017B940 WRITE   3300898\n0x40105200 WRITE   3300934\n0x40105240 WRITE   3300990\n0x40105280 WRITE   3301053\n0x401052C0 WRITE   3301109\n0x40105300 WRITE   3301187\n0x40105340 WRITE   3301243\n0x40105380 WRITE   3301306\n0x401053C0 WRITE   3301362\n0x4017BB00 WRITE   3301436\n0x4017BAC0 WRITE   3301438\n0x4017BA80 WRITE   3301445\n0x4017BA40 WRITE   3301447\n0x40105400 WRITE   3301480\n0x40105440 WRITE   3301536\n0x40105480 WRITE   3301610\n0x401054C0 WRITE   3301666\n0x40105500 WRITE   3301757\n0x40105540 WRITE   3301813\n0x40105580 WRITE   3301884\n0x401055C0 WRITE   3301940\n0x4017BB80 WRITE   3302012\n0x4017BB40 WRITE   3302014\n0x40105600 WRITE   3302050\n0x40105640 WRITE   3302106\n0x40105680 WRITE   3302177\n0x401056C0 WRITE   3302233\n0x40105700 WRITE   3302319\n0x40105740 WRITE   3302375\n0x40105780 WRITE   3302446\n0x401057C0 WRITE   3302502\n0x4017BE00 WRITE   3302585\n0x4017BDC0 WRITE   3302587\n0x4017BD00 WRITE   3302594\n0x4017BCC0 WRITE   3302596\n0x4017BC80 WRITE   3302606\n0x4017BC40 WRITE   3302608\n0x40105800 WRITE   3302635\n0x40105840 WRITE   3302691\n0x40105880 WRITE   3302757\n0x401058C0 WRITE   3302813\n0x40105900 WRITE   3302900\n0x40105940 WRITE   3302956\n0x40105980 WRITE   3303019\n0x401059C0 WRITE   3303075\n0x4017BD80 WRITE   3303144\n0x4017BD40 WRITE   3303146\n0x40105A00 WRITE   3303182\n0x40105A40 WRITE   3303238\n0x40105A80 WRITE   3303301\n0x40105AC0 WRITE   3303357\n0x40105B00 WRITE   3303439\n0x40105B40 WRITE   3303495\n0x40105B80 WRITE   3303558\n0x40105BC0 WRITE   3303614\n0x4017BF00 WRITE   3303693\n0x4017BEC0 WRITE   3303695\n0x4017BE80 WRITE   3303702\n0x4017BE40 WRITE   3303704\n0x40105C00 WRITE   3303737\n0x40105C40 WRITE   3303793\n0x40105C80 WRITE   3303867\n0x40105CC0 WRITE   3303923\n0x40105D00 WRITE   3304018\n0x40105D40 WRITE   3304074\n0x40105D80 WRITE   3304145\n0x40105DC0 WRITE   3304201\n0x4017BF80 WRITE   3304278\n0x4017BF40 WRITE   3304280\n0x40105E00 WRITE   3304316\n0x40105E40 WRITE   3304372\n0x40105E80 WRITE   3304443\n0x40105EC0 WRITE   3304499\n0x40105F00 WRITE   3304589\n0x40105F40 WRITE   3304645\n0x40105F80 WRITE   3304716\n0x40105FC0 WRITE   3304772\n0x4017DFC0 WRITE   3304934\n0x4017E000 WRITE   3304966\n0x4017D000 WRITE   3305109\n0x4017CFC0 WRITE   3305111\n0x4017C800 WRITE   3305118\n0x4017C7C0 WRITE   3305120\n0x4017C400 WRITE   3305130\n0x4017C3C0 WRITE   3305132\n0x4017C200 WRITE   3305137\n0x4017C1C0 WRITE   3305140\n0x4017C100 WRITE   3305143\n0x4017C0C0 WRITE   3305146\n0x4017C080 WRITE   3305149\n0x4017C040 WRITE   3305152\n0x40106000 WRITE   3305184\n0x40106040 WRITE   3305272\n0x40106080 WRITE   3305338\n0x401060C0 WRITE   3305394\n0x40106100 WRITE   3305477\n0x40106140 WRITE   3305533\n0x40106180 WRITE   3305596\n0x401061C0 WRITE   3305652\n0x4017C180 WRITE   3305708\n0x4017C140 WRITE   3305710\n0x40106200 WRITE   3305746\n0x40106240 WRITE   3305802\n0x40106280 WRITE   3305865\n0x401062C0 WRITE   3305921\n0x40106300 WRITE   3305999\n0x40106340 WRITE   3306055\n0x40106380 WRITE   3306118\n0x401063C0 WRITE   3306174\n0x4017C300 WRITE   3306235\n0x4017C2C0 WRITE   3306237\n0x4017C280 WRITE   3306244\n0x4017C240 WRITE   3306246\n0x40106400 WRITE   3306279\n0x40106440 WRITE   3306335\n0x40106480 WRITE   3306409\n0x401064C0 WRITE   3306465\n0x40106500 WRITE   3306556\n0x40106540 WRITE   3306612\n0x40106580 WRITE   3306683\n0x401065C0 WRITE   3306739\n0x4017C380 WRITE   3306803\n0x4017C340 WRITE   3306805\n0x40106600 WRITE   3306841\n0x40106640 WRITE   3306897\n0x40106680 WRITE   3306968\n0x401066C0 WRITE   3307024\n0x40106700 WRITE   3307110\n0x40106740 WRITE   3307166\n0x40106780 WRITE   3307237\n0x401067C0 WRITE   3307293\n0x4017C600 WRITE   3307362\n0x4017C5C0 WRITE   3307364\n0x4017C500 WRITE   3307371\n0x4017C4C0 WRITE   3307373\n0x4017C480 WRITE   3307383\n0x4017C440 WRITE   3307385\n0x40106800 WRITE   3307412\n0x40106840 WRITE   3307468\n0x40106880 WRITE   3307534\n0x401068C0 WRITE   3307590\n0x40106900 WRITE   3307677\n0x40106940 WRITE   3307733\n0x40106980 WRITE   3307796\n0x401069C0 WRITE   3307852\n0x4017C580 WRITE   3307914\n0x4017C540 WRITE   3307916\n0x40106A00 WRITE   3307952\n0x40106A40 WRITE   3308008\n0x40106A80 WRITE   3308071\n0x40106AC0 WRITE   3308127\n0x40106B00 WRITE   3308209\n0x40106B40 WRITE   3308265\n0x40106B80 WRITE   3308328\n0x40106BC0 WRITE   3308384\n0x4017C700 WRITE   3308450\n0x4017C6C0 WRITE   3308452\n0x4017C680 WRITE   3308459\n0x4017C640 WRITE   3308461\n0x40106C00 WRITE   3308494\n0x40106C40 WRITE   3308550\n0x40106C80 WRITE   3308624\n0x40106CC0 WRITE   3308680\n0x40106D00 WRITE   3308775\n0x40106D40 WRITE   3308831\n0x40106D80 WRITE   3308902\n0x40106DC0 WRITE   3308958\n0x4017C780 WRITE   3309028\n0x4017C740 WRITE   3309030\n0x40106E00 WRITE   3309066\n0x40106E40 WRITE   3309122\n0x40106E80 WRITE   3309193\n0x40106EC0 WRITE   3309249\n0x40106F00 WRITE   3309339\n0x40106F40 WRITE   3309395\n0x40106F80 WRITE   3309466\n0x40106FC0 WRITE   3309522\n0x4017CC00 WRITE   3309602\n0x4017CBC0 WRITE   3309604\n0x4017CA00 WRITE   3309611\n0x4017C9C0 WRITE   3309613\n0x4017C900 WRITE   3309623\n0x4017C8C0 WRITE   3309625\n0x4017C880 WRITE   3309630\n0x4017C840 WRITE   3309633\n0x40107000 WRITE   3309658\n0x40107040 WRITE   3309742\n0x40107080 WRITE   3309808\n0x401070C0 WRITE   3309864\n0x40107100 WRITE   3309947\n0x40107140 WRITE   3310003\n0x40107180 WRITE   3310066\n0x401071C0 WRITE   3310122\n0x4017C980 WRITE   3310186\n0x4017C940 WRITE   3310188\n0x40107200 WRITE   3310224\n0x40107240 WRITE   3310280\n0x40107280 WRITE   3310343\n0x401072C0 WRITE   3310399\n0x40107300 WRITE   3310477\n0x40107340 WRITE   3310533\n0x40107380 WRITE   3310596\n0x401073C0 WRITE   3310652\n0x4017CB00 WRITE   3310720\n0x4017CAC0 WRITE   3310722\n0x4017CA80 WRITE   3310729\n0x4017CA40 WRITE   3310731\n0x40107400 WRITE   3310764\n0x40107440 WRITE   3310820\n0x40107480 WRITE   3310894\n0x401074C0 WRITE   3310950\n0x40107500 WRITE   3311041\n0x40107540 WRITE   3311097\n0x40107580 WRITE   3311168\n0x401075C0 WRITE   3311224\n0x4017CB80 WRITE   3311296\n0x4017CB40 WRITE   3311298\n0x40107600 WRITE   3311334\n0x40107640 WRITE   3311390\n0x40107680 WRITE   3311461\n0x401076C0 WRITE   3311517\n0x40107700 WRITE   3311603\n0x40107740 WRITE   3311659\n0x40107780 WRITE   3311730\n0x401077C0 WRITE   3311786\n0x4017CE00 WRITE   3311863\n0x4017CDC0 WRITE   3311865\n0x4017CD00 WRITE   3311872\n0x4017CCC0 WRITE   3311874\n0x4017CC80 WRITE   3311884\n0x4017CC40 WRITE   3311886\n0x40107800 WRITE   3311913\n0x40107840 WRITE   3311969\n0x40107880 WRITE   3312035\n0x401078C0 WRITE   3312091\n0x40107900 WRITE   3312178\n0x40107940 WRITE   3312234\n0x40107980 WRITE   3312297\n0x401079C0 WRITE   3312353\n0x4017CD80 WRITE   3312422\n0x4017CD40 WRITE   3312424\n0x40107A00 WRITE   3312460\n0x40107A40 WRITE   3312516\n0x40107A80 WRITE   3312579\n0x40107AC0 WRITE   3312635\n0x40107B00 WRITE   3312717\n0x40107B40 WRITE   3312773\n0x40107B80 WRITE   3312836\n0x40107BC0 WRITE   3312892\n0x4017CF00 WRITE   3312965\n0x4017CEC0 WRITE   3312967\n0x4017CE80 WRITE   3312974\n0x4017CE40 WRITE   3312976\n0x40107C00 WRITE   3313009\n0x40107C40 WRITE   3313065\n0x40107C80 WRITE   3313139\n0x40107CC0 WRITE   3313195\n0x40107D00 WRITE   3313290\n0x40107D40 WRITE   3313346\n0x40107D80 WRITE   3313417\n0x40107DC0 WRITE   3313473\n0x4017CF80 WRITE   3313550\n0x4017CF40 WRITE   3313552\n0x40107E00 WRITE   3313588\n0x40107E40 WRITE   3313644\n0x40107E80 WRITE   3313715\n0x40107EC0 WRITE   3313771\n0x40107F00 WRITE   3313861\n0x40107F40 WRITE   3313917\n0x40107F80 WRITE   3313988\n0x40107FC0 WRITE   3314044\n0x4017D800 WRITE   3314130\n0x4017D7C0 WRITE   3314132\n0x4017D400 WRITE   3314139\n0x4017D3C0 WRITE   3314141\n0x4017D200 WRITE   3314151\n0x4017D1C0 WRITE   3314153\n0x4017D100 WRITE   3314158\n0x4017D0C0 WRITE   3314161\n0x4017D080 WRITE   3314164\n0x4017D040 WRITE   3314167\n0x40108000 WRITE   3314192\n0x40108040 WRITE   3314276\n0x40108080 WRITE   3314342\n0x401080C0 WRITE   3314398\n0x40108100 WRITE   3314481\n0x40108140 WRITE   3314537\n0x40108180 WRITE   3314600\n0x401081C0 WRITE   3314656\n0x4017D180 WRITE   3314712\n0x4017D140 WRITE   3314714\n0x40108200 WRITE   3314750\n0x40108240 WRITE   3314806\n0x40108280 WRITE   3314869\n0x401082C0 WRITE   3314925\n0x40108300 WRITE   3315003\n0x40108340 WRITE   3315059\n0x40108380 WRITE   3315122\n0x401083C0 WRITE   3315178\n0x4017D300 WRITE   3315244\n0x4017D2C0 WRITE   3315246\n0x4017D280 WRITE   3315253\n0x4017D240 WRITE   3315255\n0x40108400 WRITE   3315288\n0x40108440 WRITE   3315344\n0x40108480 WRITE   3315418\n0x401084C0 WRITE   3315474\n0x40108500 WRITE   3315565\n0x40108540 WRITE   3315621\n0x40108580 WRITE   3315692\n0x401085C0 WRITE   3315748\n0x4017D380 WRITE   3315812\n0x4017D340 WRITE   3315814\n0x40108600 WRITE   3315850\n0x40108640 WRITE   3315906\n0x40108680 WRITE   3315977\n0x401086C0 WRITE   3316033\n0x40108700 WRITE   3316119\n0x40108740 WRITE   3316175\n0x40108780 WRITE   3316246\n0x401087C0 WRITE   3316302\n0x4017D600 WRITE   3316377\n0x4017D5C0 WRITE   3316379\n0x4017D500 WRITE   3316386\n0x4017D4C0 WRITE   3316388\n0x4017D480 WRITE   3316398\n0x4017D440 WRITE   3316400\n0x40108800 WRITE   3316427\n0x40108840 WRITE   3316483\n0x40108880 WRITE   3316549\n0x401088C0 WRITE   3316605\n0x40108900 WRITE   3316692\n0x40108940 WRITE   3316748\n0x40108980 WRITE   3316811\n0x401089C0 WRITE   3316867\n0x4017D580 WRITE   3316929\n0x4017D540 WRITE   3316931\n0x40108A00 WRITE   3316967\n0x40108A40 WRITE   3317023\n0x40108A80 WRITE   3317086\n0x40108AC0 WRITE   3317142\n0x40108B00 WRITE   3317224\n0x40108B40 WRITE   3317280\n0x40108B80 WRITE   3317343\n0x40108BC0 WRITE   3317399\n0x4017D700 WRITE   3317471\n0x4017D6C0 WRITE   3317473\n0x4017D680 WRITE   3317480\n0x4017D640 WRITE   3317482\n0x40108C00 WRITE   3317515\n0x40108C40 WRITE   3317571\n0x40108C80 WRITE   3317645\n0x40108CC0 WRITE   3317701\n0x40108D00 WRITE   3317796\n0x40108D40 WRITE   3317852\n0x40108D80 WRITE   3317923\n0x40108DC0 WRITE   3317979\n0x4017D780 WRITE   3318049\n0x4017D740 WRITE   3318051\n0x40108E00 WRITE   3318087\n0x40108E40 WRITE   3318143\n0x40108E80 WRITE   3318214\n0x40108EC0 WRITE   3318270\n0x40108F00 WRITE   3318360\n0x40108F40 WRITE   3318416\n0x40108F80 WRITE   3318487\n0x40108FC0 WRITE   3318543\n0x4017DC00 WRITE   3318629\n0x4017DBC0 WRITE   3318631\n0x4017DA00 WRITE   3318638\n0x4017D9C0 WRITE   3318640\n0x4017D900 WRITE   3318650\n0x4017D8C0 WRITE   3318652\n0x4017D880 WRITE   3318657\n0x4017D840 WRITE   3318660\n0x40109000 WRITE   3318685\n0x40109040 WRITE   3318769\n0x40109080 WRITE   3318835\n0x401090C0 WRITE   3318891\n0x40109100 WRITE   3318974\n0x40109140 WRITE   3319030\n0x40109180 WRITE   3319093\n0x401091C0 WRITE   3319149\n0x4017D980 WRITE   3319213\n0x4017D940 WRITE   3319215\n0x40109200 WRITE   3319251\n0x40109240 WRITE   3319307\n0x40109280 WRITE   3319370\n0x401092C0 WRITE   3319426\n0x40109300 WRITE   3319504\n0x40109340 WRITE   3319560\n0x40109380 WRITE   3319623\n0x401093C0 WRITE   3319679\n0x4017DB00 WRITE   3319753\n0x4017DAC0 WRITE   3319755\n0x4017DA80 WRITE   3319762\n0x4017DA40 WRITE   3319764\n0x40109400 WRITE   3319797\n0x40109440 WRITE   3319853\n0x40109480 WRITE   3319927\n0x401094C0 WRITE   3319983\n0x40109500 WRITE   3320074\n0x40109540 WRITE   3320130\n0x40109580 WRITE   3320201\n0x401095C0 WRITE   3320257\n0x4017DB80 WRITE   3320329\n0x4017DB40 WRITE   3320331\n0x40109600 WRITE   3320367\n0x40109640 WRITE   3320423\n0x40109680 WRITE   3320494\n0x401096C0 WRITE   3320550\n0x40109700 WRITE   3320636\n0x40109740 WRITE   3320692\n0x40109780 WRITE   3320763\n0x401097C0 WRITE   3320819\n0x4017DE00 WRITE   3320902\n0x4017DDC0 WRITE   3320904\n0x4017DD00 WRITE   3320911\n0x4017DCC0 WRITE   3320913\n0x4017DC80 WRITE   3320923\n0x4017DC40 WRITE   3320925\n0x40109800 WRITE   3320952\n0x40109840 WRITE   3321008\n0x40109880 WRITE   3321074\n0x401098C0 WRITE   3321130\n0x40109900 WRITE   3321217\n0x40109940 WRITE   3321273\n0x40109980 WRITE   3321336\n0x401099C0 WRITE   3321392\n0x4017DD80 WRITE   3321461\n0x4017DD40 WRITE   3321463\n0x40109A00 WRITE   3321499\n0x40109A40 WRITE   3321555\n0x40109A80 WRITE   3321618\n0x40109AC0 WRITE   3321674\n0x40109B00 WRITE   3321756\n0x40109B40 WRITE   3321812\n0x40109B80 WRITE   3321875\n0x40109BC0 WRITE   3321931\n0x4017DF00 WRITE   3322010\n0x4017DEC0 WRITE   3322012\n0x4017DE80 WRITE   3322019\n0x4017DE40 WRITE   3322021\n0x40109C00 WRITE   3322054\n0x40109C40 WRITE   3322110\n0x40109C80 WRITE   3322184\n0x40109CC0 WRITE   3322240\n0x40109D00 WRITE   3322335\n0x40109D40 WRITE   3322391\n0x40109D80 WRITE   3322462\n0x40109DC0 WRITE   3322518\n0x4017DF80 WRITE   3322595\n0x4017DF40 WRITE   3322597\n0x40109E00 WRITE   3322633\n0x40109E40 WRITE   3322689\n0x40109E80 WRITE   3322760\n0x40109EC0 WRITE   3322816\n0x40109F00 WRITE   3322906\n0x40109F40 WRITE   3322962\n0x40109F80 WRITE   3323033\n0x40109FC0 WRITE   3323089\n0x4017FFC0 WRITE   3323251\n0x40180000 WRITE   3323283\n0x4017F000 WRITE   3323410\n0x4017EFC0 WRITE   3323412\n0x4017E800 WRITE   3323419\n0x4017E7C0 WRITE   3323421\n0x4017E400 WRITE   3323431\n0x4017E3C0 WRITE   3323433\n0x4017E200 WRITE   3323438\n0x4017E1C0 WRITE   3323441\n0x4017E100 WRITE   3323444\n0x4017E0C0 WRITE   3323447\n0x4017E080 WRITE   3323450\n0x4017E040 WRITE   3323453\n0x4010A000 WRITE   3323485\n0x4010A040 WRITE   3323573\n0x4010A080 WRITE   3323639\n0x4010A0C0 WRITE   3323695\n0x4010A100 WRITE   3323778\n0x4010A140 WRITE   3323834\n0x4010A180 WRITE   3323897\n0x4010A1C0 WRITE   3323953\n0x4017E180 WRITE   3324009\n0x4017E140 WRITE   3324011\n0x4010A200 WRITE   3324047\n0x4010A240 WRITE   3324103\n0x4010A280 WRITE   3324166\n0x4010A2C0 WRITE   3324222\n0x4010A300 WRITE   3324300\n0x4010A340 WRITE   3324356\n0x4010A380 WRITE   3324419\n0x4010A3C0 WRITE   3324475\n0x4017E300 WRITE   3324536\n0x4017E2C0 WRITE   3324538\n0x4017E280 WRITE   3324545\n0x4017E240 WRITE   3324547\n0x4010A400 WRITE   3324580\n0x4010A440 WRITE   3324636\n0x4010A480 WRITE   3324710\n0x4010A4C0 WRITE   3324766\n0x4010A500 WRITE   3324857\n0x4010A540 WRITE   3324913\n0x4010A580 WRITE   3324984\n0x4010A5C0 WRITE   3325040\n0x4017E380 WRITE   3325104\n0x4017E340 WRITE   3325106\n0x4010A600 WRITE   3325142\n0x4010A640 WRITE   3325198\n0x4010A680 WRITE   3325269\n0x4010A6C0 WRITE   3325325\n0x4010A700 WRITE   3325411\n0x4010A740 WRITE   3325467\n0x4010A780 WRITE   3325538\n0x4010A7C0 WRITE   3325594\n0x4017E600 WRITE   3325663\n0x4017E5C0 WRITE   3325665\n0x4017E500 WRITE   3325672\n0x4017E4C0 WRITE   3325674\n0x4017E480 WRITE   3325684\n0x4017E440 WRITE   3325686\n0x4010A800 WRITE   3325713\n0x4010A840 WRITE   3325769\n0x4010A880 WRITE   3325835\n0x4010A8C0 WRITE   3325891\n0x4010A900 WRITE   3325978\n0x4010A940 WRITE   3326034\n0x4010A980 WRITE   3326097\n0x4010A9C0 WRITE   3326153\n0x4017E580 WRITE   3326215\n0x4017E540 WRITE   3326217\n0x4010AA00 WRITE   3326253\n0x4010AA40 WRITE   3326309\n0x4010AA80 WRITE   3326372\n0x4010AAC0 WRITE   3326428\n0x4010AB00 WRITE   3326510\n0x4010AB40 WRITE   3326566\n0x4010AB80 WRITE   3326629\n0x4010ABC0 WRITE   3326685\n0x4017E700 WRITE   3326751\n0x4017E6C0 WRITE   3326753\n0x4017E680 WRITE   3326760\n0x4017E640 WRITE   3326762\n0x4010AC00 WRITE   3326795\n0x4010AC40 WRITE   3326851\n0x4010AC80 WRITE   3326925\n0x4010ACC0 WRITE   3326981\n0x4010AD00 WRITE   3327076\n0x4010AD40 WRITE   3327132\n0x4010AD80 WRITE   3327203\n0x4010ADC0 WRITE   3327259\n0x4017E780 WRITE   3327329\n0x4017E740 WRITE   3327331\n0x4010AE00 WRITE   3327367\n0x4010AE40 WRITE   3327423\n0x4010AE80 WRITE   3327494\n0x4010AEC0 WRITE   3327550\n0x4010AF00 WRITE   3327640\n0x4010AF40 WRITE   3327696\n0x4010AF80 WRITE   3327767\n0x4010AFC0 WRITE   3327823\n0x4017EC00 WRITE   3327903\n0x4017EBC0 WRITE   3327905\n0x4017EA00 WRITE   3327912\n0x4017E9C0 WRITE   3327914\n0x4017E900 WRITE   3327924\n0x4017E8C0 WRITE   3327926\n0x4017E880 WRITE   3327931\n0x4017E840 WRITE   3327934\n0x4010B000 WRITE   3327959\n0x4010B040 WRITE   3328043\n0x4010B080 WRITE   3328109\n0x4010B0C0 WRITE   3328165\n0x4010B100 WRITE   3328248\n0x4010B140 WRITE   3328304\n0x4010B180 WRITE   3328367\n0x4010B1C0 WRITE   3328423\n0x4017E980 WRITE   3328487\n0x4017E940 WRITE   3328489\n0x4010B200 WRITE   3328525\n0x4010B240 WRITE   3328581\n0x4010B280 WRITE   3328644\n0x4010B2C0 WRITE   3328700\n0x4010B300 WRITE   3328778\n0x4010B340 WRITE   3328834\n0x4010B380 WRITE   3328897\n0x4010B3C0 WRITE   3328953\n0x4017EB00 WRITE   3329021\n0x4017EAC0 WRITE   3329023\n0x4017EA80 WRITE   3329030\n0x4017EA40 WRITE   3329032\n0x4010B400 WRITE   3329065\n0x4010B440 WRITE   3329121\n0x4010B480 WRITE   3329195\n0x4010B4C0 WRITE   3329251\n0x4010B500 WRITE   3329342\n0x4010B540 WRITE   3329398\n0x4010B580 WRITE   3329469\n0x4010B5C0 WRITE   3329525\n0x4017EB80 WRITE   3329597\n0x4017EB40 WRITE   3329599\n0x4010B600 WRITE   3329635\n0x4010B640 WRITE   3329691\n0x4010B680 WRITE   3329762\n0x4010B6C0 WRITE   3329818\n0x4010B700 WRITE   3329904\n0x4010B740 WRITE   3329960\n0x4010B780 WRITE   3330031\n0x4010B7C0 WRITE   3330087\n0x4017EE00 WRITE   3330164\n0x4017EDC0 WRITE   3330166\n0x4017ED00 WRITE   3330173\n0x4017ECC0 WRITE   3330175\n0x4017EC80 WRITE   3330185\n0x4017EC40 WRITE   3330187\n0x4010B800 WRITE   3330214\n0x4010B840 WRITE   3330270\n0x4010B880 WRITE   3330336\n0x4010B8C0 WRITE   3330392\n0x4010B900 WRITE   3330479\n0x4010B940 WRITE   3330535\n0x4010B980 WRITE   3330598\n0x4010B9C0 WRITE   3330654\n0x4017ED80 WRITE   3330723\n0x4017ED40 WRITE   3330725\n0x4010BA00 WRITE   3330761\n0x4010BA40 WRITE   3330817\n0x4010BA80 WRITE   3330880\n0x4010BAC0 WRITE   3330936\n0x4010BB00 WRITE   3331018\n0x4010BB40 WRITE   3331074\n0x4010BB80 WRITE   3331137\n0x4010BBC0 WRITE   3331193\n0x4017EF00 WRITE   3331266\n0x4017EEC0 WRITE   3331268\n0x4017EE80 WRITE   3331275\n0x4017EE40 WRITE   3331277\n0x4010BC00 WRITE   3331310\n0x4010BC40 WRITE   3331366\n0x4010BC80 WRITE   3331440\n0x4010BCC0 WRITE   3331496\n0x4010BD00 WRITE   3331591\n0x4010BD40 WRITE   3331647\n0x4010BD80 WRITE   3331718\n0x4010BDC0 WRITE   3331774\n0x4017EF80 WRITE   3331851\n0x4017EF40 WRITE   3331853\n0x4010BE00 WRITE   3331889\n0x4010BE40 WRITE   3331945\n0x4010BE80 WRITE   3332016\n0x4010BEC0 WRITE   3332072\n0x4010BF00 WRITE   3332162\n0x4010BF40 WRITE   3332218\n0x4010BF80 WRITE   3332289\n0x4010BFC0 WRITE   3332345\n0x4017F800 WRITE   3332431\n0x4017F7C0 WRITE   3332433\n0x4017F400 WRITE   3332440\n0x4017F3C0 WRITE   3332442\n0x4017F200 WRITE   3332452\n0x4017F1C0 WRITE   3332454\n0x4017F100 WRITE   3332459\n0x4017F0C0 WRITE   3332462\n0x4017F080 WRITE   3332465\n0x4017F040 WRITE   3332468\n0x4010C000 WRITE   3332493\n0x4010C040 WRITE   3332577\n0x4010C080 WRITE   3332643\n0x4010C0C0 WRITE   3332699\n0x4010C100 WRITE   3332782\n0x4010C140 WRITE   3332838\n0x4010C180 WRITE   3332901\n0x4010C1C0 WRITE   3332957\n0x4017F180 WRITE   3333013\n0x4017F140 WRITE   3333015\n0x4010C200 WRITE   3333051\n0x4010C240 WRITE   3333107\n0x4010C280 WRITE   3333170\n0x4010C2C0 WRITE   3333226\n0x4010C300 WRITE   3333304\n0x4010C340 WRITE   3333360\n0x4010C380 WRITE   3333423\n0x4010C3C0 WRITE   3333479\n0x4017F300 WRITE   3333545\n0x4017F2C0 WRITE   3333547\n0x4017F280 WRITE   3333554\n0x4017F240 WRITE   3333556\n0x4010C400 WRITE   3333589\n0x4010C440 WRITE   3333645\n0x4010C480 WRITE   3333719\n0x4010C4C0 WRITE   3333775\n0x4010C500 WRITE   3333866\n0x4010C540 WRITE   3333922\n0x4010C580 WRITE   3333993\n0x4010C5C0 WRITE   3334049\n0x4017F380 WRITE   3334113\n0x4017F340 WRITE   3334115\n0x4010C600 WRITE   3334151\n0x4010C640 WRITE   3334207\n0x4010C680 WRITE   3334278\n0x4010C6C0 WRITE   3334334\n0x4010C700 WRITE   3334420\n0x4010C740 WRITE   3334476\n0x4010C780 WRITE   3334547\n0x4010C7C0 WRITE   3334603\n0x4017F600 WRITE   3334678\n0x4017F5C0 WRITE   3334680\n0x4017F500 WRITE   3334687\n0x4017F4C0 WRITE   3334689\n0x4017F480 WRITE   3334699\n0x4017F440 WRITE   3334701\n0x4010C800 WRITE   3334728\n0x4010C840 WRITE   3334784\n0x4010C880 WRITE   3334850\n0x4010C8C0 WRITE   3334906\n0x4010C900 WRITE   3334993\n0x4010C940 WRITE   3335049\n0x4010C980 WRITE   3335112\n0x4010C9C0 WRITE   3335168\n0x4017F580 WRITE   3335230\n0x4017F540 WRITE   3335232\n0x4010CA00 WRITE   3335268\n0x4010CA40 WRITE   3335324\n0x4010CA80 WRITE   3335387\n0x4010CAC0 WRITE   3335443\n0x4010CB00 WRITE   3335525\n0x4010CB40 WRITE   3335581\n0x4010CB80 WRITE   3335644\n0x4010CBC0 WRITE   3335700\n0x4017F700 WRITE   3335772\n0x4017F6C0 WRITE   3335774\n0x4017F680 WRITE   3335781\n0x4017F640 WRITE   3335783\n0x4010CC00 WRITE   3335816\n0x4010CC40 WRITE   3335872\n0x4010CC80 WRITE   3335946\n0x4010CCC0 WRITE   3336002\n0x4010CD00 WRITE   3336097\n0x4010CD40 WRITE   3336153\n0x4010CD80 WRITE   3336224\n0x4010CDC0 WRITE   3336280\n0x4017F780 WRITE   3336350\n0x4017F740 WRITE   3336352\n0x4010CE00 WRITE   3336388\n0x4010CE40 WRITE   3336444\n0x4010CE80 WRITE   3336515\n0x4010CEC0 WRITE   3336571\n0x4010CF00 WRITE   3336661\n0x4010CF40 WRITE   3336717\n0x4010CF80 WRITE   3336788\n0x4010CFC0 WRITE   3336844\n0x4017FC00 WRITE   3336930\n0x4017FBC0 WRITE   3336932\n0x4017FA00 WRITE   3336939\n0x4017F9C0 WRITE   3336941\n0x4017F900 WRITE   3336951\n0x4017F8C0 WRITE   3336953\n0x4017F880 WRITE   3336958\n0x4017F840 WRITE   3336961\n0x4010D000 WRITE   3336986\n0x4010D040 WRITE   3337070\n0x4010D080 WRITE   3337136\n0x4010D0C0 WRITE   3337192\n0x4010D100 WRITE   3337275\n0x4010D140 WRITE   3337331\n0x4010D180 WRITE   3337394\n0x4010D1C0 WRITE   3337450\n0x4017F980 WRITE   3337514\n0x4017F940 WRITE   3337516\n0x4010D200 WRITE   3337552\n0x4010D240 WRITE   3337608\n0x4010D280 WRITE   3337671\n0x4010D2C0 WRITE   3337727\n0x4010D300 WRITE   3337805\n0x4010D340 WRITE   3337861\n0x4010D380 WRITE   3337924\n0x4010D3C0 WRITE   3337980\n0x4017FB00 WRITE   3338054\n0x4017FAC0 WRITE   3338056\n0x4017FA80 WRITE   3338063\n0x4017FA40 WRITE   3338065\n0x4010D400 WRITE   3338098\n0x4010D440 WRITE   3338154\n0x4010D480 WRITE   3338228\n0x4010D4C0 WRITE   3338284\n0x4010D500 WRITE   3338375\n0x4010D540 WRITE   3338431\n0x4010D580 WRITE   3338502\n0x4010D5C0 WRITE   3338558\n0x4017FB80 WRITE   3338630\n0x4017FB40 WRITE   3338632\n0x4010D600 WRITE   3338668\n0x4010D640 WRITE   3338724\n0x4010D680 WRITE   3338795\n0x4010D6C0 WRITE   3338851\n0x4010D700 WRITE   3338937\n0x4010D740 WRITE   3338993\n0x4010D780 WRITE   3339064\n0x4010D7C0 WRITE   3339120\n0x4017FE00 WRITE   3339203\n0x4017FDC0 WRITE   3339205\n0x4017FD00 WRITE   3339212\n0x4017FCC0 WRITE   3339214\n0x4017FC80 WRITE   3339224\n0x4017FC40 WRITE   3339226\n0x4010D800 WRITE   3339253\n0x4010D840 WRITE   3339309\n0x4010D880 WRITE   3339375\n0x4010D8C0 WRITE   3339431\n0x4010D900 WRITE   3339518\n0x4010D940 WRITE   3339574\n0x4010D980 WRITE   3339637\n0x4010D9C0 WRITE   3339693\n0x4017FD80 WRITE   3339762\n0x4017FD40 WRITE   3339764\n0x4010DA00 WRITE   3339800\n0x4010DA40 WRITE   3339856\n0x4010DA80 WRITE   3339919\n0x4010DAC0 WRITE   3339975\n0x4010DB00 WRITE   3340057\n0x4010DB40 WRITE   3340113\n0x4010DB80 WRITE   3340176\n0x4010DBC0 WRITE   3340232\n0x4017FF00 WRITE   3340311\n0x4017FEC0 WRITE   3340313\n0x4017FE80 WRITE   3340320\n0x4017FE40 WRITE   3340322\n0x4010DC00 WRITE   3340355\n0x4010DC40 WRITE   3340411\n0x4010DC80 WRITE   3340485\n0x4010DCC0 WRITE   3340541\n0x4010DD00 WRITE   3340636\n0x4010DD40 WRITE   3340692\n0x4010DD80 WRITE   3340763\n0x4010DDC0 WRITE   3340819\n0x4017FF80 WRITE   3340896\n0x4017FF40 WRITE   3340898\n0x4010DE00 WRITE   3340934\n0x4010DE40 WRITE   3340990\n0x4010DE80 WRITE   3341061\n0x4010DEC0 WRITE   3341117\n0x4010DF00 WRITE   3341207\n0x4010DF40 WRITE   3341263\n0x4010DF80 WRITE   3341334\n0x4010DFC0 WRITE   3341390\n0x40181FC0 WRITE   3341552\n0x40182000 WRITE   3341584\n0x40181000 WRITE   3341711\n0x40180FC0 WRITE   3341713\n0x40180800 WRITE   3341720\n0x401807C0 WRITE   3341722\n0x40180400 WRITE   3341732\n0x401803C0 WRITE   3341734\n0x40180200 WRITE   3341739\n0x401801C0 WRITE   3341742\n0x40180100 WRITE   3341745\n0x401800C0 WRITE   3341748\n0x40180080 WRITE   3341751\n0x40180040 WRITE   3341754\n0x4010E000 WRITE   3341786\n0x4010E040 WRITE   3341874\n0x4010E080 WRITE   3341940\n0x4010E0C0 WRITE   3341996\n0x4010E100 WRITE   3342079\n0x4010E140 WRITE   3342135\n0x4010E180 WRITE   3342198\n0x4010E1C0 WRITE   3342254\n0x40180180 WRITE   3342310\n0x40180140 WRITE   3342312\n0x4010E200 WRITE   3342348\n0x4010E240 WRITE   3342404\n0x4010E280 WRITE   3342467\n0x4010E2C0 WRITE   3342523\n0x4010E300 WRITE   3342601\n0x4010E340 WRITE   3342657\n0x4010E380 WRITE   3342720\n0x4010E3C0 WRITE   3342776\n0x40180300 WRITE   3342837\n0x401802C0 WRITE   3342839\n0x40180280 WRITE   3342846\n0x40180240 WRITE   3342848\n0x4010E400 WRITE   3342881\n0x4010E440 WRITE   3342937\n0x4010E480 WRITE   3343011\n0x4010E4C0 WRITE   3343067\n0x4010E500 WRITE   3343158\n0x4010E540 WRITE   3343214\n0x4010E580 WRITE   3343285\n0x4010E5C0 WRITE   3343341\n0x40180380 WRITE   3343405\n0x40180340 WRITE   3343407\n0x4010E600 WRITE   3343443\n0x4010E640 WRITE   3343499\n0x4010E680 WRITE   3343570\n0x4010E6C0 WRITE   3343626\n0x4010E700 WRITE   3343712\n0x4010E740 WRITE   3343768\n0x4010E780 WRITE   3343839\n0x4010E7C0 WRITE   3343895\n0x40180600 WRITE   3343964\n0x401805C0 WRITE   3343966\n0x40180500 WRITE   3343973\n0x401804C0 WRITE   3343975\n0x40180480 WRITE   3343985\n0x40180440 WRITE   3343987\n0x4010E800 WRITE   3344014\n0x4010E840 WRITE   3344070\n0x4010E880 WRITE   3344136\n0x4010E8C0 WRITE   3344192\n0x4010E900 WRITE   3344279\n0x4010E940 WRITE   3344335\n0x4010E980 WRITE   3344398\n0x4010E9C0 WRITE   3344454\n0x40180580 WRITE   3344516\n0x40180540 WRITE   3344518\n0x4010EA00 WRITE   3344554\n0x4010EA40 WRITE   3344610\n0x4010EA80 WRITE   3344673\n0x4010EAC0 WRITE   3344729\n0x4010EB00 WRITE   3344811\n0x4010EB40 WRITE   3344867\n0x4010EB80 WRITE   3344930\n0x4010EBC0 WRITE   3344986\n0x40180700 WRITE   3345052\n0x401806C0 WRITE   3345054\n0x40180680 WRITE   3345061\n0x40180640 WRITE   3345063\n0x4010EC00 WRITE   3345096\n0x4010EC40 WRITE   3345152\n0x4010EC80 WRITE   3345226\n0x4010ECC0 WRITE   3345282\n0x4010ED00 WRITE   3345377\n0x4010ED40 WRITE   3345433\n0x4010ED80 WRITE   3345504\n0x4010EDC0 WRITE   3345560\n0x40180780 WRITE   3345630\n0x40180740 WRITE   3345632\n0x4010EE00 WRITE   3345668\n0x4010EE40 WRITE   3345724\n0x4010EE80 WRITE   3345795\n0x4010EEC0 WRITE   3345851\n0x4010EF00 WRITE   3345941\n0x4010EF40 WRITE   3345997\n0x4010EF80 WRITE   3346068\n0x4010EFC0 WRITE   3346124\n0x40180C00 WRITE   3346204\n0x40180BC0 WRITE   3346206\n0x40180A00 WRITE   3346213\n0x401809C0 WRITE   3346215\n0x40180900 WRITE   3346225\n0x401808C0 WRITE   3346227\n0x40180880 WRITE   3346232\n0x40180840 WRITE   3346235\n0x4010F000 WRITE   3346260\n0x4010F040 WRITE   3346344\n0x4010F080 WRITE   3346410\n0x4010F0C0 WRITE   3346466\n0x4010F100 WRITE   3346549\n0x4010F140 WRITE   3346605\n0x4010F180 WRITE   3346668\n0x4010F1C0 WRITE   3346724\n0x40180980 WRITE   3346788\n0x40180940 WRITE   3346790\n0x4010F200 WRITE   3346826\n0x4010F240 WRITE   3346882\n0x4010F280 WRITE   3346945\n0x4010F2C0 WRITE   3347001\n0x4010F300 WRITE   3347079\n0x4010F340 WRITE   3347135\n0x4010F380 WRITE   3347198\n0x4010F3C0 WRITE   3347254\n0x40180B00 WRITE   3347322\n0x40180AC0 WRITE   3347324\n0x40180A80 WRITE   3347331\n0x40180A40 WRITE   3347333\n0x4010F400 WRITE   3347366\n0x4010F440 WRITE   3347422\n0x4010F480 WRITE   3347496\n0x4010F4C0 WRITE   3347552\n0x4010F500 WRITE   3347643\n0x4010F540 WRITE   3347699\n0x4010F580 WRITE   3347770\n0x4010F5C0 WRITE   3347826\n0x40180B80 WRITE   3347898\n0x40180B40 WRITE   3347900\n0x4010F600 WRITE   3347936\n0x4010F640 WRITE   3347992\n0x4010F680 WRITE   3348063\n0x4010F6C0 WRITE   3348119\n0x4010F700 WRITE   3348205\n0x4010F740 WRITE   3348261\n0x4010F780 WRITE   3348332\n0x4010F7C0 WRITE   3348388\n0x40180E00 WRITE   3348465\n0x40180DC0 WRITE   3348467\n0x40180D00 WRITE   3348474\n0x40180CC0 WRITE   3348476\n0x40180C80 WRITE   3348486\n0x40180C40 WRITE   3348488\n0x4010F800 WRITE   3348515\n0x4010F840 WRITE   3348571\n0x4010F880 WRITE   3348637\n0x4010F8C0 WRITE   3348693\n0x4010F900 WRITE   3348780\n0x4010F940 WRITE   3348836\n0x4010F980 WRITE   3348899\n0x4010F9C0 WRITE   3348955\n0x40180D80 WRITE   3349024\n0x40180D40 WRITE   3349026\n0x4010FA00 WRITE   3349062\n0x4010FA40 WRITE   3349118\n0x4010FA80 WRITE   3349181\n0x4010FAC0 WRITE   3349237\n0x4010FB00 WRITE   3349319\n0x4010FB40 WRITE   3349375\n0x4010FB80 WRITE   3349438\n0x4010FBC0 WRITE   3349494\n0x40180F00 WRITE   3349567\n0x40180EC0 WRITE   3349569\n0x40180E80 WRITE   3349576\n0x40180E40 WRITE   3349578\n0x4010FC00 WRITE   3349611\n0x4010FC40 WRITE   3349667\n0x4010FC80 WRITE   3349741\n0x4010FCC0 WRITE   3349797\n0x4010FD00 WRITE   3349892\n0x4010FD40 WRITE   3349948\n0x4010FD80 WRITE   3350019\n0x4010FDC0 WRITE   3350075\n0x40180F80 WRITE   3350152\n0x40180F40 WRITE   3350154\n0x4010FE00 WRITE   3350190\n0x4010FE40 WRITE   3350246\n0x4010FE80 WRITE   3350317\n0x4010FEC0 WRITE   3350373\n0x4010FF00 WRITE   3350463\n0x4010FF40 WRITE   3350519\n0x4010FF80 WRITE   3350590\n0x4010FFC0 WRITE   3350646\n0x40181800 WRITE   3350732\n0x401817C0 WRITE   3350734\n0x40181400 WRITE   3350741\n0x401813C0 WRITE   3350743\n0x40181200 WRITE   3350753\n0x401811C0 WRITE   3350755\n0x40181100 WRITE   3350760\n0x401810C0 WRITE   3350763\n0x40181080 WRITE   3350766\n0x40181040 WRITE   3350769\n0x40110000 WRITE   3350794\n0x40110040 WRITE   3350878\n0x40110080 WRITE   3350944\n0x401100C0 WRITE   3351000\n0x40110100 WRITE   3351083\n0x40110140 WRITE   3351139\n0x40110180 WRITE   3351202\n0x401101C0 WRITE   3351258\n0x40181180 WRITE   3351314\n0x40181140 WRITE   3351316\n0x40110200 WRITE   3351352\n0x40110240 WRITE   3351408\n0x40110280 WRITE   3351471\n0x401102C0 WRITE   3351527\n0x40110300 WRITE   3351605\n0x40110340 WRITE   3351661\n0x40110380 WRITE   3351724\n0x401103C0 WRITE   3351780\n0x40181300 WRITE   3351846\n0x401812C0 WRITE   3351848\n0x40181280 WRITE   3351855\n0x40181240 WRITE   3351857\n0x40110400 WRITE   3351890\n0x40110440 WRITE   3351946\n0x40110480 WRITE   3352020\n0x401104C0 WRITE   3352076\n0x40110500 WRITE   3352167\n0x40110540 WRITE   3352223\n0x40110580 WRITE   3352294\n0x401105C0 WRITE   3352350\n0x40181380 WRITE   3352414\n0x40181340 WRITE   3352416\n0x40110600 WRITE   3352452\n0x40110640 WRITE   3352508\n0x40110680 WRITE   3352579\n0x401106C0 WRITE   3352635\n0x40110700 WRITE   3352721\n0x40110740 WRITE   3352777\n0x40110780 WRITE   3352848\n0x401107C0 WRITE   3352904\n0x40181600 WRITE   3352979\n0x401815C0 WRITE   3352981\n0x40181500 WRITE   3352988\n0x401814C0 WRITE   3352990\n0x40181480 WRITE   3353000\n0x40181440 WRITE   3353002\n0x40110800 WRITE   3353029\n0x40110840 WRITE   3353085\n0x40110880 WRITE   3353151\n0x401108C0 WRITE   3353207\n0x40110900 WRITE   3353294\n0x40110940 WRITE   3353350\n0x40110980 WRITE   3353413\n0x401109C0 WRITE   3353469\n0x40181580 WRITE   3353531\n0x40181540 WRITE   3353533\n0x40110A00 WRITE   3353569\n0x40110A40 WRITE   3353625\n0x40110A80 WRITE   3353688\n0x40110AC0 WRITE   3353744\n0x40110B00 WRITE   3353826\n0x40110B40 WRITE   3353882\n0x40110B80 WRITE   3353945\n0x40110BC0 WRITE   3354001\n0x40181700 WRITE   3354073\n0x401816C0 WRITE   3354075\n0x40181680 WRITE   3354082\n0x40181640 WRITE   3354084\n0x40110C00 WRITE   3354117\n0x40110C40 WRITE   3354173\n0x40110C80 WRITE   3354247\n0x40110CC0 WRITE   3354303\n0x40110D00 WRITE   3354398\n0x40110D40 WRITE   3354454\n0x40110D80 WRITE   3354525\n0x40110DC0 WRITE   3354581\n0x40181780 WRITE   3354651\n0x40181740 WRITE   3354653\n0x40110E00 WRITE   3354689\n0x40110E40 WRITE   3354745\n0x40110E80 WRITE   3354816\n0x40110EC0 WRITE   3354872\n0x40110F00 WRITE   3354962\n0x40110F40 WRITE   3355018\n0x40110F80 WRITE   3355089\n0x40110FC0 WRITE   3355145\n0x40181C00 WRITE   3355231\n0x40181BC0 WRITE   3355233\n0x40181A00 WRITE   3355240\n0x401819C0 WRITE   3355242\n0x40181900 WRITE   3355252\n0x401818C0 WRITE   3355254\n0x40181880 WRITE   3355259\n0x40181840 WRITE   3355262\n0x40111000 WRITE   3355287\n0x40111040 WRITE   3355371\n0x40111080 WRITE   3355437\n0x401110C0 WRITE   3355493\n0x40111100 WRITE   3355576\n0x40111140 WRITE   3355632\n0x40111180 WRITE   3355695\n0x401111C0 WRITE   3355751\n0x40181980 WRITE   3355815\n0x40181940 WRITE   3355817\n0x40111200 WRITE   3355853\n0x40111240 WRITE   3355909\n0x40111280 WRITE   3355972\n0x401112C0 WRITE   3356028\n0x40111300 WRITE   3356106\n0x40111340 WRITE   3356162\n0x40111380 WRITE   3356225\n0x401113C0 WRITE   3356281\n0x40181B00 WRITE   3356355\n0x40181AC0 WRITE   3356357\n0x40181A80 WRITE   3356364\n0x40181A40 WRITE   3356366\n0x40111400 WRITE   3356399\n0x40111440 WRITE   3356455\n0x40111480 WRITE   3356529\n0x401114C0 WRITE   3356585\n0x40111500 WRITE   3356676\n0x40111540 WRITE   3356732\n0x40111580 WRITE   3356803\n0x401115C0 WRITE   3356859\n0x40181B80 WRITE   3356931\n0x40181B40 WRITE   3356933\n0x40111600 WRITE   3356969\n0x40111640 WRITE   3357025\n0x40111680 WRITE   3357096\n0x401116C0 WRITE   3357152\n0x40111700 WRITE   3357238\n0x40111740 WRITE   3357294\n0x40111780 WRITE   3357365\n0x401117C0 WRITE   3357421\n0x40181E00 WRITE   3357504\n0x40181DC0 WRITE   3357506\n0x40181D00 WRITE   3357513\n0x40181CC0 WRITE   3357515\n0x40181C80 WRITE   3357525\n0x40181C40 WRITE   3357527\n0x40111800 WRITE   3357554\n0x40111840 WRITE   3357610\n0x40111880 WRITE   3357676\n0x401118C0 WRITE   3357732\n0x40111900 WRITE   3357819\n0x40111940 WRITE   3357875\n0x40111980 WRITE   3357938\n0x401119C0 WRITE   3357994\n0x40181D80 WRITE   3358063\n0x40181D40 WRITE   3358065\n0x40111A00 WRITE   3358101\n0x40111A40 WRITE   3358157\n0x40111A80 WRITE   3358220\n0x40111AC0 WRITE   3358276\n0x40111B00 WRITE   3358358\n0x40111B40 WRITE   3358414\n0x40111B80 WRITE   3358477\n0x40111BC0 WRITE   3358533\n0x40181F00 WRITE   3358612\n0x40181EC0 WRITE   3358614\n0x40181E80 WRITE   3358621\n0x40181E40 WRITE   3358623\n0x40111C00 WRITE   3358656\n0x40111C40 WRITE   3358712\n0x40111C80 WRITE   3358786\n0x40111CC0 WRITE   3358842\n0x40111D00 WRITE   3358937\n0x40111D40 WRITE   3358993\n0x40111D80 WRITE   3359064\n0x40111DC0 WRITE   3359120\n0x40181F80 WRITE   3359197\n0x40181F40 WRITE   3359199\n0x40111E00 WRITE   3359235\n0x40111E40 WRITE   3359291\n0x40111E80 WRITE   3359362\n0x40111EC0 WRITE   3359418\n0x40111F00 WRITE   3359508\n0x40111F40 WRITE   3359564\n0x40111F80 WRITE   3359635\n0x40111FC0 WRITE   3359691\n0x40183FC0 WRITE   3359853\n0x40184000 WRITE   3359896\n0x40183000 WRITE   3360034\n0x40182FC0 WRITE   3360036\n0x40182800 WRITE   3360043\n0x401827C0 WRITE   3360045\n0x40182400 WRITE   3360055\n0x401823C0 WRITE   3360057\n0x40182200 WRITE   3360062\n0x401821C0 WRITE   3360065\n0x40182100 WRITE   3360068\n0x401820C0 WRITE   3360071\n0x40182080 WRITE   3360074\n0x40182040 WRITE   3360077\n0x40112000 WRITE   3360109\n0x40112040 WRITE   3360197\n0x40112080 WRITE   3360263\n0x401120C0 WRITE   3360319\n0x40112100 WRITE   3360402\n0x40112140 WRITE   3360458\n0x40112180 WRITE   3360521\n0x401121C0 WRITE   3360577\n0x40182180 WRITE   3360633\n0x40182140 WRITE   3360635\n0x40112200 WRITE   3360671\n0x40112240 WRITE   3360727\n0x40112280 WRITE   3360790\n0x401122C0 WRITE   3360846\n0x40112300 WRITE   3360924\n0x40112340 WRITE   3360980\n0x40112380 WRITE   3361043\n0x401123C0 WRITE   3361099\n0x40182300 WRITE   3361160\n0x401822C0 WRITE   3361162\n0x40182280 WRITE   3361169\n0x40182240 WRITE   3361171\n0x40112400 WRITE   3361204\n0x40112440 WRITE   3361260\n0x40112480 WRITE   3361334\n0x401124C0 WRITE   3361390\n0x40112500 WRITE   3361481\n0x40112540 WRITE   3361537\n0x40112580 WRITE   3361608\n0x401125C0 WRITE   3361664\n0x40182380 WRITE   3361728\n0x40182340 WRITE   3361730\n0x40112600 WRITE   3361766\n0x40112640 WRITE   3361822\n0x40112680 WRITE   3361893\n0x401126C0 WRITE   3361949\n0x40112700 WRITE   3362035\n0x40112740 WRITE   3362091\n0x40112780 WRITE   3362162\n0x401127C0 WRITE   3362218\n0x40182600 WRITE   3362287\n0x401825C0 WRITE   3362289\n0x40182500 WRITE   3362296\n0x401824C0 WRITE   3362298\n0x40182480 WRITE   3362308\n0x40182440 WRITE   3362310\n0x40112800 WRITE   3362337\n0x40112840 WRITE   3362393\n0x40112880 WRITE   3362459\n0x401128C0 WRITE   3362515\n0x40112900 WRITE   3362602\n0x40112940 WRITE   3362658\n0x40112980 WRITE   3362721\n0x401129C0 WRITE   3362777\n0x40182580 WRITE   3362839\n0x40182540 WRITE   3362841\n0x40112A00 WRITE   3362877\n0x40112A40 WRITE   3362933\n0x40112A80 WRITE   3362996\n0x40112AC0 WRITE   3363052\n0x40112B00 WRITE   3363134\n0x40112B40 WRITE   3363190\n0x40112B80 WRITE   3363253\n0x40112BC0 WRITE   3363309\n0x40182700 WRITE   3363375\n0x401826C0 WRITE   3363377\n0x40182680 WRITE   3363384\n0x40182640 WRITE   3363386\n0x40112C00 WRITE   3363419\n0x40112C40 WRITE   3363475\n0x40112C80 WRITE   3363549\n0x40112CC0 WRITE   3363605\n0x40112D00 WRITE   3363700\n0x40112D40 WRITE   3363756\n0x40112D80 WRITE   3363827\n0x40112DC0 WRITE   3363883\n0x40182780 WRITE   3363953\n0x40182740 WRITE   3363955\n0x40112E00 WRITE   3363991\n0x40112E40 WRITE   3364047\n0x40112E80 WRITE   3364118\n0x40112EC0 WRITE   3364174\n0x40112F00 WRITE   3364264\n0x40112F40 WRITE   3364320\n0x40112F80 WRITE   3364391\n0x40112FC0 WRITE   3364447\n0x40182C00 WRITE   3364527\n0x40182BC0 WRITE   3364529\n0x40182A00 WRITE   3364536\n0x401829C0 WRITE   3364538\n0x40182900 WRITE   3364548\n0x401828C0 WRITE   3364550\n0x40182880 WRITE   3364555\n0x40182840 WRITE   3364558\n0x40113000 WRITE   3364583\n0x40113040 WRITE   3364667\n0x40113080 WRITE   3364733\n0x401130C0 WRITE   3364789\n0x40113100 WRITE   3364872\n0x40113140 WRITE   3364928\n0x40113180 WRITE   3364991\n0x401131C0 WRITE   3365047\n0x40182980 WRITE   3365111\n0x40182940 WRITE   3365113\n0x40113200 WRITE   3365149\n0x40113240 WRITE   3365205\n0x40113280 WRITE   3365268\n0x401132C0 WRITE   3365324\n0x40113300 WRITE   3365402\n0x40113340 WRITE   3365458\n0x40113380 WRITE   3365521\n0x401133C0 WRITE   3365577\n0x40182B00 WRITE   3365645\n0x40182AC0 WRITE   3365647\n0x40182A80 WRITE   3365654\n0x40182A40 WRITE   3365656\n0x40113400 WRITE   3365689\n0x40113440 WRITE   3365745\n0x40113480 WRITE   3365819\n0x401134C0 WRITE   3365875\n0x40113500 WRITE   3365966\n0x40113540 WRITE   3366022\n0x40113580 WRITE   3366093\n0x401135C0 WRITE   3366149\n0x40182B80 WRITE   3366221\n0x40182B40 WRITE   3366223\n0x40113600 WRITE   3366259\n0x40113640 WRITE   3366315\n0x40113680 WRITE   3366386\n0x401136C0 WRITE   3366442\n0x40113700 WRITE   3366528\n0x40113740 WRITE   3366584\n0x40113780 WRITE   3366655\n0x401137C0 WRITE   3366711\n0x40182E00 WRITE   3366788\n0x40182DC0 WRITE   3366790\n0x40182D00 WRITE   3366797\n0x40182CC0 WRITE   3366799\n0x40182C80 WRITE   3366809\n0x40182C40 WRITE   3366811\n0x40113800 WRITE   3366838\n0x40113840 WRITE   3366894\n0x40113880 WRITE   3366960\n0x401138C0 WRITE   3367016\n0x40113900 WRITE   3367103\n0x40113940 WRITE   3367159\n0x40113980 WRITE   3367222\n0x401139C0 WRITE   3367278\n0x40182D80 WRITE   3367347\n0x40182D40 WRITE   3367349\n0x40113A00 WRITE   3367385\n0x40113A40 WRITE   3367441\n0x40113A80 WRITE   3367504\n0x40113AC0 WRITE   3367560\n0x40113B00 WRITE   3367642\n0x40113B40 WRITE   3367698\n0x40113B80 WRITE   3367761\n0x40113BC0 WRITE   3367817\n0x40182F00 WRITE   3367890\n0x40182EC0 WRITE   3367892\n0x40182E80 WRITE   3367899\n0x40182E40 WRITE   3367901\n0x40113C00 WRITE   3367934\n0x40113C40 WRITE   3367990\n0x40113C80 WRITE   3368064\n0x40113CC0 WRITE   3368120\n0x40113D00 WRITE   3368215\n0x40113D40 WRITE   3368271\n0x40113D80 WRITE   3368342\n0x40113DC0 WRITE   3368398\n0x40182F80 WRITE   3368475\n0x40182F40 WRITE   3368477\n0x40113E00 WRITE   3368513\n0x40113E40 WRITE   3368569\n0x40113E80 WRITE   3368640\n0x40113EC0 WRITE   3368696\n0x40113F00 WRITE   3368786\n0x40113F40 WRITE   3368842\n0x40113F80 WRITE   3368913\n0x40113FC0 WRITE   3368969\n0x40183800 WRITE   3369055\n0x401837C0 WRITE   3369057\n0x40183400 WRITE   3369064\n0x401833C0 WRITE   3369066\n0x40183200 WRITE   3369076\n0x401831C0 WRITE   3369078\n0x40183100 WRITE   3369083\n0x401830C0 WRITE   3369086\n0x40183080 WRITE   3369089\n0x40183040 WRITE   3369092\n0x40114000 WRITE   3369117\n0x40114040 WRITE   3369201\n0x40114080 WRITE   3369267\n0x401140C0 WRITE   3369323\n0x40114100 WRITE   3369406\n0x40114140 WRITE   3369462\n0x40114180 WRITE   3369525\n0x401141C0 WRITE   3369581\n0x40183180 WRITE   3369637\n0x40183140 WRITE   3369639\n0x40114200 WRITE   3369675\n0x40114240 WRITE   3369731\n0x40114280 WRITE   3369794\n0x401142C0 WRITE   3369850\n0x40114300 WRITE   3369928\n0x40114340 WRITE   3369984\n0x40114380 WRITE   3370047\n0x401143C0 WRITE   3370103\n0x40183300 WRITE   3370169\n0x401832C0 WRITE   3370171\n0x40183280 WRITE   3370178\n0x40183240 WRITE   3370180\n0x40114400 WRITE   3370213\n0x40114440 WRITE   3370269\n0x40114480 WRITE   3370343\n0x401144C0 WRITE   3370399\n0x40114500 WRITE   3370490\n0x40114540 WRITE   3370546\n0x40114580 WRITE   3370617\n0x401145C0 WRITE   3370673\n0x40183380 WRITE   3370737\n0x40183340 WRITE   3370739\n0x40114600 WRITE   3370775\n0x40114640 WRITE   3370831\n0x40114680 WRITE   3370902\n0x401146C0 WRITE   3370958\n0x40114700 WRITE   3371044\n0x40114740 WRITE   3371100\n0x40114780 WRITE   3371171\n0x401147C0 WRITE   3371227\n0x40183600 WRITE   3371302\n0x401835C0 WRITE   3371304\n0x40183500 WRITE   3371311\n0x401834C0 WRITE   3371313\n0x40183480 WRITE   3371323\n0x40183440 WRITE   3371325\n0x40114800 WRITE   3371352\n0x40114840 WRITE   3371408\n0x40114880 WRITE   3371474\n0x401148C0 WRITE   3371530\n0x40114900 WRITE   3371617\n0x40114940 WRITE   3371673\n0x40114980 WRITE   3371736\n0x401149C0 WRITE   3371792\n0x40183580 WRITE   3371854\n0x40183540 WRITE   3371856\n0x40114A00 WRITE   3371892\n0x40114A40 WRITE   3371948\n0x40114A80 WRITE   3372011\n0x40114AC0 WRITE   3372067\n0x40114B00 WRITE   3372149\n0x40114B40 WRITE   3372205\n0x40114B80 WRITE   3372268\n0x40114BC0 WRITE   3372324\n0x40183700 WRITE   3372396\n0x401836C0 WRITE   3372398\n0x40183680 WRITE   3372405\n0x40183640 WRITE   3372407\n0x40114C00 WRITE   3372440\n0x40114C40 WRITE   3372496\n0x40114C80 WRITE   3372570\n0x40114CC0 WRITE   3372626\n0x40114D00 WRITE   3372721\n0x40114D40 WRITE   3372777\n0x40114D80 WRITE   3372848\n0x40114DC0 WRITE   3372904\n0x40183780 WRITE   3372974\n0x40183740 WRITE   3372976\n0x40114E00 WRITE   3373012\n0x40114E40 WRITE   3373068\n0x40114E80 WRITE   3373139\n0x40114EC0 WRITE   3373195\n0x40114F00 WRITE   3373285\n0x40114F40 WRITE   3373341\n0x40114F80 WRITE   3373412\n0x40114FC0 WRITE   3373468\n0x40183C00 WRITE   3373554\n0x40183BC0 WRITE   3373556\n0x40183A00 WRITE   3373563\n0x401839C0 WRITE   3373565\n0x40183900 WRITE   3373575\n0x401838C0 WRITE   3373577\n0x40183880 WRITE   3373582\n0x40183840 WRITE   3373585\n0x40115000 WRITE   3373610\n0x40115040 WRITE   3373694\n0x40115080 WRITE   3373760\n0x401150C0 WRITE   3373816\n0x40115100 WRITE   3373899\n0x40115140 WRITE   3373955\n0x40115180 WRITE   3374018\n0x401151C0 WRITE   3374074\n0x40183980 WRITE   3374138\n0x40183940 WRITE   3374140\n0x40115200 WRITE   3374176\n0x40115240 WRITE   3374232\n0x40115280 WRITE   3374295\n0x401152C0 WRITE   3374351\n0x40115300 WRITE   3374429\n0x40115340 WRITE   3374485\n0x40115380 WRITE   3374548\n0x401153C0 WRITE   3374604\n0x40183B00 WRITE   3374678\n0x40183AC0 WRITE   3374680\n0x40183A80 WRITE   3374687\n0x40183A40 WRITE   3374689\n0x40115400 WRITE   3374722\n0x40115440 WRITE   3374778\n0x40115480 WRITE   3374852\n0x401154C0 WRITE   3374908\n0x40115500 WRITE   3374999\n0x40115540 WRITE   3375055\n0x40115580 WRITE   3375126\n0x401155C0 WRITE   3375182\n0x40183B80 WRITE   3375254\n0x40183B40 WRITE   3375256\n0x40115600 WRITE   3375292\n0x40115640 WRITE   3375348\n0x40115680 WRITE   3375419\n0x401156C0 WRITE   3375475\n0x40115700 WRITE   3375561\n0x40115740 WRITE   3375617\n0x40115780 WRITE   3375688\n0x401157C0 WRITE   3375744\n0x40183E00 WRITE   3375827\n0x40183DC0 WRITE   3375829\n0x40183D00 WRITE   3375836\n0x40183CC0 WRITE   3375838\n0x40183C80 WRITE   3375848\n0x40183C40 WRITE   3375850\n0x40115800 WRITE   3375877\n0x40115840 WRITE   3375933\n0x40115880 WRITE   3375999\n0x401158C0 WRITE   3376055\n0x40115900 WRITE   3376142\n0x40115940 WRITE   3376198\n0x40115980 WRITE   3376261\n0x401159C0 WRITE   3376317\n0x40183D80 WRITE   3376386\n0x40183D40 WRITE   3376388\n0x40115A00 WRITE   3376424\n0x40115A40 WRITE   3376480\n0x40115A80 WRITE   3376543\n0x40115AC0 WRITE   3376599\n0x40115B00 WRITE   3376681\n0x40115B40 WRITE   3376737\n0x40115B80 WRITE   3376800\n0x40115BC0 WRITE   3376856\n0x40183F00 WRITE   3376935\n0x40183EC0 WRITE   3376937\n0x40183E80 WRITE   3376944\n0x40183E40 WRITE   3376946\n0x40115C00 WRITE   3376979\n0x40115C40 WRITE   3377035\n0x40115C80 WRITE   3377109\n0x40115CC0 WRITE   3377165\n0x40115D00 WRITE   3377260\n0x40115D40 WRITE   3377316\n0x40115D80 WRITE   3377387\n0x40115DC0 WRITE   3377443\n0x40183F80 WRITE   3377520\n0x40183F40 WRITE   3377522\n0x40115E00 WRITE   3377558\n0x40115E40 WRITE   3377614\n0x40115E80 WRITE   3377685\n0x40115EC0 WRITE   3377741\n0x40115F00 WRITE   3377831\n0x40115F40 WRITE   3377887\n0x40115F80 WRITE   3377958\n0x40115FC0 WRITE   3378014\n0x40184880 WRITE   3378343\n0x40185FC0 WRITE   3378461\n0x40186000 WRITE   3378495\n0x40185000 WRITE   3378614\n0x40184FC0 WRITE   3378616\n0x40184800 WRITE   3378623\n0x401847C0 WRITE   3378625\n0x40184400 WRITE   3378635\n0x401843C0 WRITE   3378637\n0x40184200 WRITE   3378642\n0x401841C0 WRITE   3378645\n0x40184100 WRITE   3378653\n0x401840C0 WRITE   3378656\n0x40184080 WRITE   3378659\n0x40184040 WRITE   3378661\n0x40116000 WRITE   3378693\n0x40116040 WRITE   3378781\n0x40116080 WRITE   3378847\n0x401160C0 WRITE   3378903\n0x40116100 WRITE   3378986\n0x40116140 WRITE   3379042\n0x40116180 WRITE   3379105\n0x401161C0 WRITE   3379161\n0x40184180 WRITE   3379217\n0x40184140 WRITE   3379219\n0x40116200 WRITE   3379255\n0x40116240 WRITE   3379311\n0x40116280 WRITE   3379374\n0x401162C0 WRITE   3379430\n0x40116300 WRITE   3379508\n0x40116340 WRITE   3379564\n0x40116380 WRITE   3379627\n0x401163C0 WRITE   3379683\n0x40184300 WRITE   3379744\n0x401842C0 WRITE   3379746\n0x40184280 WRITE   3379753\n0x40184240 WRITE   3379755\n0x40116400 WRITE   3379788\n0x40116440 WRITE   3379844\n0x40116480 WRITE   3379918\n0x401164C0 WRITE   3379974\n0x40116500 WRITE   3380065\n0x40116540 WRITE   3380121\n0x40116580 WRITE   3380192\n0x401165C0 WRITE   3380248\n0x40184380 WRITE   3380312\n0x40184340 WRITE   3380314\n0x40116600 WRITE   3380350\n0x40116640 WRITE   3380406\n0x40116680 WRITE   3380477\n0x401166C0 WRITE   3380533\n0x40116700 WRITE   3380619\n0x40116740 WRITE   3380675\n0x40116780 WRITE   3380746\n0x401167C0 WRITE   3380802\n0x40184600 WRITE   3380871\n0x401845C0 WRITE   3380873\n0x40184500 WRITE   3380880\n0x401844C0 WRITE   3380882\n0x40184480 WRITE   3380892\n0x40184440 WRITE   3380894\n0x40116800 WRITE   3380921\n0x40116840 WRITE   3380977\n0x40116880 WRITE   3381043\n0x401168C0 WRITE   3381099\n0x40116900 WRITE   3381186\n0x40116940 WRITE   3381242\n0x40116980 WRITE   3381305\n0x401169C0 WRITE   3381361\n0x40184580 WRITE   3381423\n0x40184540 WRITE   3381425\n0x40116A00 WRITE   3381461\n0x40116A40 WRITE   3381517\n0x40116A80 WRITE   3381580\n0x40116AC0 WRITE   3381636\n0x40116B00 WRITE   3381718\n0x40116B40 WRITE   3381774\n0x40116B80 WRITE   3381837\n0x40116BC0 WRITE   3381893\n0x40184700 WRITE   3381959\n0x401846C0 WRITE   3381961\n0x40184680 WRITE   3381968\n0x40184640 WRITE   3381970\n0x40116C00 WRITE   3382003\n0x40116C40 WRITE   3382059\n0x40116C80 WRITE   3382133\n0x40116CC0 WRITE   3382189\n0x40116D00 WRITE   3382284\n0x40116D40 WRITE   3382340\n0x40116D80 WRITE   3382411\n0x40116DC0 WRITE   3382467\n0x40184780 WRITE   3382537\n0x40184740 WRITE   3382539\n0x40116E00 WRITE   3382575\n0x40116E40 WRITE   3382631\n0x40116E80 WRITE   3382702\n0x40116EC0 WRITE   3382758\n0x40116F00 WRITE   3382848\n0x40116F40 WRITE   3382904\n0x40116F80 WRITE   3382975\n0x40116FC0 WRITE   3383031\n0x40184C00 WRITE   3383111\n0x40184BC0 WRITE   3383113\n0x40184A00 WRITE   3383120\n0x401849C0 WRITE   3383122\n0x40184900 WRITE   3383132\n0x401848C0 WRITE   3383134\n0x40184840 WRITE   3383142\n0x40117000 WRITE   3383167\n0x40117040 WRITE   3383251\n0x40117080 WRITE   3383317\n0x401170C0 WRITE   3383373\n0x40117100 WRITE   3383456\n0x40117140 WRITE   3383512\n0x40117180 WRITE   3383575\n0x401171C0 WRITE   3383631\n0x40184980 WRITE   3383695\n0x40184940 WRITE   3383697\n0x40117200 WRITE   3383733\n0x40117240 WRITE   3383789\n0x40117280 WRITE   3383852\n0x401172C0 WRITE   3383908\n0x40117300 WRITE   3383986\n0x40117340 WRITE   3384042\n0x40117380 WRITE   3384105\n0x401173C0 WRITE   3384161\n0x40184B00 WRITE   3384229\n0x40184AC0 WRITE   3384231\n0x40184A80 WRITE   3384238\n0x40184A40 WRITE   3384240\n0x40117400 WRITE   3384273\n0x40117440 WRITE   3384329\n0x40117480 WRITE   3384403\n0x401174C0 WRITE   3384459\n0x40117500 WRITE   3384550\n0x40117540 WRITE   3384606\n0x40117580 WRITE   3384677\n0x401175C0 WRITE   3384733\n0x40184B80 WRITE   3384805\n0x40184B40 WRITE   3384807\n0x40117600 WRITE   3384843\n0x40117640 WRITE   3384899\n0x40117680 WRITE   3384970\n0x401176C0 WRITE   3385026\n0x40117700 WRITE   3385112\n0x40117740 WRITE   3385168\n0x40117780 WRITE   3385239\n0x401177C0 WRITE   3385295\n0x40184E00 WRITE   3385372\n0x40184DC0 WRITE   3385374\n0x40184D00 WRITE   3385381\n0x40184CC0 WRITE   3385383\n0x40184C80 WRITE   3385393\n0x40184C40 WRITE   3385395\n0x40117800 WRITE   3385422\n0x40117840 WRITE   3385478\n0x40117880 WRITE   3385544\n0x401178C0 WRITE   3385600\n0x40117900 WRITE   3385687\n0x40117940 WRITE   3385743\n0x40117980 WRITE   3385806\n0x401179C0 WRITE   3385862\n0x40184D80 WRITE   3385931\n0x40184D40 WRITE   3385933\n0x40117A00 WRITE   3385969\n0x40117A40 WRITE   3386025\n0x40117A80 WRITE   3386088\n0x40117AC0 WRITE   3386144\n0x40117B00 WRITE   3386226\n0x40117B40 WRITE   3386282\n0x40117B80 WRITE   3386345\n0x40117BC0 WRITE   3386401\n0x40184F00 WRITE   3386474\n0x40184EC0 WRITE   3386476\n0x40184E80 WRITE   3386483\n0x40184E40 WRITE   3386485\n0x40117C00 WRITE   3386518\n0x40117C40 WRITE   3386574\n0x40117C80 WRITE   3386648\n0x40117CC0 WRITE   3386704\n0x40117D00 WRITE   3386799\n0x40117D40 WRITE   3386855\n0x40117D80 WRITE   3386926\n0x40117DC0 WRITE   3386982\n0x40184F80 WRITE   3387059\n0x40184F40 WRITE   3387061\n0x40117E00 WRITE   3387097\n0x40117E40 WRITE   3387153\n0x40117E80 WRITE   3387224\n0x40117EC0 WRITE   3387280\n0x40117F00 WRITE   3387370\n0x40117F40 WRITE   3387426\n0x40117F80 WRITE   3387497\n0x40117FC0 WRITE   3387553\n0x40185800 WRITE   3387639\n0x401857C0 WRITE   3387641\n0x40185400 WRITE   3387648\n0x401853C0 WRITE   3387650\n0x40185200 WRITE   3387660\n0x401851C0 WRITE   3387662\n0x40185100 WRITE   3387667\n0x401850C0 WRITE   3387670\n0x40185080 WRITE   3387673\n0x40185040 WRITE   3387676\n0x40118000 WRITE   3387701\n0x40118040 WRITE   3387785\n0x40118080 WRITE   3387851\n0x401180C0 WRITE   3387907\n0x40118100 WRITE   3387990\n0x40118140 WRITE   3388046\n0x40118180 WRITE   3388109\n0x401181C0 WRITE   3388165\n0x40185180 WRITE   3388221\n0x40185140 WRITE   3388223\n0x40118200 WRITE   3388259\n0x40118240 WRITE   3388315\n0x40118280 WRITE   3388378\n0x401182C0 WRITE   3388434\n0x40118300 WRITE   3388512\n0x40118340 WRITE   3388568\n0x40118380 WRITE   3388631\n0x401183C0 WRITE   3388687\n0x40185300 WRITE   3388753\n0x401852C0 WRITE   3388755\n0x40185280 WRITE   3388762\n0x40185240 WRITE   3388764\n0x40118400 WRITE   3388797\n0x40118440 WRITE   3388853\n0x40118480 WRITE   3388927\n0x401184C0 WRITE   3388983\n0x40118500 WRITE   3389074\n0x40118540 WRITE   3389130\n0x40118580 WRITE   3389201\n0x401185C0 WRITE   3389257\n0x40185380 WRITE   3389321\n0x40185340 WRITE   3389323\n0x40118600 WRITE   3389359\n0x40118640 WRITE   3389415\n0x40118680 WRITE   3389486\n0x401186C0 WRITE   3389542\n0x40118700 WRITE   3389628\n0x40118740 WRITE   3389684\n0x40118780 WRITE   3389755\n0x401187C0 WRITE   3389811\n0x40185600 WRITE   3389886\n0x401855C0 WRITE   3389888\n0x40185500 WRITE   3389895\n0x401854C0 WRITE   3389897\n0x40185480 WRITE   3389907\n0x40185440 WRITE   3389909\n0x40118800 WRITE   3389936\n0x40118840 WRITE   3389992\n0x40118880 WRITE   3390058\n0x401188C0 WRITE   3390114\n0x40118900 WRITE   3390201\n0x40118940 WRITE   3390257\n0x40118980 WRITE   3390320\n0x401189C0 WRITE   3390376\n0x40185580 WRITE   3390438\n0x40185540 WRITE   3390440\n0x40118A00 WRITE   3390476\n0x40118A40 WRITE   3390532\n0x40118A80 WRITE   3390595\n0x40118AC0 WRITE   3390651\n0x40118B00 WRITE   3390733\n0x40118B40 WRITE   3390789\n0x40118B80 WRITE   3390852\n0x40118BC0 WRITE   3390908\n0x40185700 WRITE   3390980\n0x401856C0 WRITE   3390982\n0x40185680 WRITE   3390989\n0x40185640 WRITE   3390991\n0x40118C00 WRITE   3391024\n0x40118C40 WRITE   3391080\n0x40118C80 WRITE   3391154\n0x40118CC0 WRITE   3391210\n0x40118D00 WRITE   3391305\n0x40118D40 WRITE   3391361\n0x40118D80 WRITE   3391432\n0x40118DC0 WRITE   3391488\n0x40185780 WRITE   3391558\n0x40185740 WRITE   3391560\n0x40118E00 WRITE   3391596\n0x40118E40 WRITE   3391652\n0x40118E80 WRITE   3391723\n0x40118EC0 WRITE   3391779\n0x40118F00 WRITE   3391869\n0x40118F40 WRITE   3391925\n0x40118F80 WRITE   3391996\n0x40118FC0 WRITE   3392052\n0x40185C00 WRITE   3392138\n0x40185BC0 WRITE   3392140\n0x40185A00 WRITE   3392147\n0x401859C0 WRITE   3392149\n0x40185900 WRITE   3392159\n0x401858C0 WRITE   3392161\n0x40185880 WRITE   3392166\n0x40185840 WRITE   3392169\n0x40119000 WRITE   3392194\n0x40119040 WRITE   3392278\n0x40119080 WRITE   3392344\n0x401190C0 WRITE   3392400\n0x40119100 WRITE   3392483\n0x40119140 WRITE   3392539\n0x40119180 WRITE   3392602\n0x401191C0 WRITE   3392658\n0x40185980 WRITE   3392722\n0x40185940 WRITE   3392724\n0x40119200 WRITE   3392760\n0x40119240 WRITE   3392816\n0x40119280 WRITE   3392879\n0x401192C0 WRITE   3392935\n0x40119300 WRITE   3393013\n0x40119340 WRITE   3393069\n0x40119380 WRITE   3393132\n0x401193C0 WRITE   3393188\n0x40185B00 WRITE   3393262\n0x40185AC0 WRITE   3393264\n0x40185A80 WRITE   3393271\n0x40185A40 WRITE   3393273\n0x40119400 WRITE   3393306\n0x40119440 WRITE   3393362\n0x40119480 WRITE   3393436\n0x401194C0 WRITE   3393492\n0x40119500 WRITE   3393583\n0x40119540 WRITE   3393639\n0x40119580 WRITE   3393710\n0x401195C0 WRITE   3393766\n0x40185B80 WRITE   3393838\n0x40185B40 WRITE   3393840\n0x40119600 WRITE   3393876\n0x40119640 WRITE   3393932\n0x40119680 WRITE   3394003\n0x401196C0 WRITE   3394059\n0x40119700 WRITE   3394145\n0x40119740 WRITE   3394201\n0x40119780 WRITE   3394272\n0x401197C0 WRITE   3394328\n0x40185E00 WRITE   3394411\n0x40185DC0 WRITE   3394413\n0x40185D00 WRITE   3394420\n0x40185CC0 WRITE   3394422\n0x40185C80 WRITE   3394432\n0x40185C40 WRITE   3394434\n0x40119800 WRITE   3394461\n0x40119840 WRITE   3394517\n0x40119880 WRITE   3394583\n0x401198C0 WRITE   3394639\n0x40119900 WRITE   3394726\n0x40119940 WRITE   3394782\n0x40119980 WRITE   3394845\n0x401199C0 WRITE   3394901\n0x40185D80 WRITE   3394970\n0x40185D40 WRITE   3394972\n0x40119A00 WRITE   3395008\n0x40119A40 WRITE   3395064\n0x40119A80 WRITE   3395127\n0x40119AC0 WRITE   3395183\n0x40119B00 WRITE   3395265\n0x40119B40 WRITE   3395321\n0x40119B80 WRITE   3395384\n0x40119BC0 WRITE   3395440\n0x40185F00 WRITE   3395519\n0x40185EC0 WRITE   3395521\n0x40185E80 WRITE   3395528\n0x40185E40 WRITE   3395530\n0x40119C00 WRITE   3395563\n0x40119C40 WRITE   3395619\n0x40119C80 WRITE   3395693\n0x40119CC0 WRITE   3395749\n0x40119D00 WRITE   3395844\n0x40119D40 WRITE   3395900\n0x40119D80 WRITE   3395971\n0x40119DC0 WRITE   3396027\n0x40185F80 WRITE   3396104\n0x40185F40 WRITE   3396106\n0x40119E00 WRITE   3396142\n0x40119E40 WRITE   3396198\n0x40119E80 WRITE   3396269\n0x40119EC0 WRITE   3396325\n0x40119F00 WRITE   3396415\n0x40119F40 WRITE   3396471\n0x40119F80 WRITE   3396542\n0x40119FC0 WRITE   3396598\n0x40187FC0 WRITE   3396760\n0x40188000 WRITE   3396792\n0x40187000 WRITE   3396919\n0x40186FC0 WRITE   3396921\n0x40186800 WRITE   3396928\n0x401867C0 WRITE   3396930\n0x40186400 WRITE   3396940\n0x401863C0 WRITE   3396942\n0x40186200 WRITE   3396947\n0x401861C0 WRITE   3396950\n0x40186100 WRITE   3396953\n0x401860C0 WRITE   3396956\n0x40186080 WRITE   3396959\n0x40186040 WRITE   3396962\n0x4011A000 WRITE   3396994\n0x4011A040 WRITE   3397082\n0x4011A080 WRITE   3397148\n0x4011A0C0 WRITE   3397204\n0x4011A100 WRITE   3397287\n0x4011A140 WRITE   3397343\n0x4011A180 WRITE   3397406\n0x4011A1C0 WRITE   3397462\n0x40186180 WRITE   3397518\n0x40186140 WRITE   3397520\n0x4011A200 WRITE   3397556\n0x4011A240 WRITE   3397612\n0x4011A280 WRITE   3397675\n0x4011A2C0 WRITE   3397731\n0x4011A300 WRITE   3397809\n0x4011A340 WRITE   3397865\n0x4011A380 WRITE   3397928\n0x4011A3C0 WRITE   3397984\n0x40186300 WRITE   3398045\n0x401862C0 WRITE   3398047\n0x40186280 WRITE   3398054\n0x40186240 WRITE   3398056\n0x4011A400 WRITE   3398089\n0x4011A440 WRITE   3398145\n0x4011A480 WRITE   3398219\n0x4011A4C0 WRITE   3398275\n0x4011A500 WRITE   3398366\n0x4011A540 WRITE   3398422\n0x4011A580 WRITE   3398493\n0x4011A5C0 WRITE   3398549\n0x40186380 WRITE   3398613\n0x40186340 WRITE   3398615\n0x4011A600 WRITE   3398651\n0x4011A640 WRITE   3398707\n0x4011A680 WRITE   3398778\n0x4011A6C0 WRITE   3398834\n0x4011A700 WRITE   3398920\n0x4011A740 WRITE   3398976\n0x4011A780 WRITE   3399047\n0x4011A7C0 WRITE   3399103\n0x40186600 WRITE   3399172\n0x401865C0 WRITE   3399174\n0x40186500 WRITE   3399181\n0x401864C0 WRITE   3399183\n0x40186480 WRITE   3399193\n0x40186440 WRITE   3399195\n0x4011A800 WRITE   3399222\n0x4011A840 WRITE   3399278\n0x4011A880 WRITE   3399344\n0x4011A8C0 WRITE   3399400\n0x4011A900 WRITE   3399487\n0x4011A940 WRITE   3399543\n0x4011A980 WRITE   3399606\n0x4011A9C0 WRITE   3399662\n0x40186580 WRITE   3399724\n0x40186540 WRITE   3399726\n0x4011AA00 WRITE   3399762\n0x4011AA40 WRITE   3399818\n0x4011AA80 WRITE   3399881\n0x4011AAC0 WRITE   3399937\n0x4011AB00 WRITE   3400019\n0x4011AB40 WRITE   3400075\n0x4011AB80 WRITE   3400138\n0x4011ABC0 WRITE   3400194\n0x40186700 WRITE   3400260\n0x401866C0 WRITE   3400262\n0x40186680 WRITE   3400269\n0x40186640 WRITE   3400271\n0x4011AC00 WRITE   3400304\n0x4011AC40 WRITE   3400360\n0x4011AC80 WRITE   3400434\n0x4011ACC0 WRITE   3400490\n0x4011AD00 WRITE   3400585\n0x4011AD40 WRITE   3400641\n0x4011AD80 WRITE   3400712\n0x4011ADC0 WRITE   3400768\n0x40186780 WRITE   3400838\n0x40186740 WRITE   3400840\n0x4011AE00 WRITE   3400876\n0x4011AE40 WRITE   3400932\n0x4011AE80 WRITE   3401003\n0x4011AEC0 WRITE   3401059\n0x4011AF00 WRITE   3401149\n0x4011AF40 WRITE   3401205\n0x4011AF80 WRITE   3401276\n0x4011AFC0 WRITE   3401332\n0x40186C00 WRITE   3401412\n0x40186BC0 WRITE   3401414\n0x40186A00 WRITE   3401421\n0x401869C0 WRITE   3401423\n0x40186900 WRITE   3401433\n0x401868C0 WRITE   3401435\n0x40186880 WRITE   3401440\n0x40186840 WRITE   3401443\n0x4011B000 WRITE   3401468\n0x4011B040 WRITE   3401552\n0x4011B080 WRITE   3401618\n0x4011B0C0 WRITE   3401674\n0x4011B100 WRITE   3401757\n0x4011B140 WRITE   3401813\n0x4011B180 WRITE   3401876\n0x4011B1C0 WRITE   3401932\n0x40186980 WRITE   3401996\n0x40186940 WRITE   3401998\n0x4011B200 WRITE   3402034\n0x4011B240 WRITE   3402090\n0x4011B280 WRITE   3402153\n0x4011B2C0 WRITE   3402209\n0x4011B300 WRITE   3402287\n0x4011B340 WRITE   3402343\n0x4011B380 WRITE   3402406\n0x4011B3C0 WRITE   3402462\n0x40186B00 WRITE   3402530\n0x40186AC0 WRITE   3402532\n0x40186A80 WRITE   3402539\n0x40186A40 WRITE   3402541\n0x4011B400 WRITE   3402574\n0x4011B440 WRITE   3402630\n0x4011B480 WRITE   3402704\n0x4011B4C0 WRITE   3402760\n0x4011B500 WRITE   3402851\n0x4011B540 WRITE   3402907\n0x4011B580 WRITE   3402978\n0x4011B5C0 WRITE   3403034\n0x40186B80 WRITE   3403106\n0x40186B40 WRITE   3403108\n0x4011B600 WRITE   3403144\n0x4011B640 WRITE   3403200\n0x4011B680 WRITE   3403271\n0x4011B6C0 WRITE   3403327\n0x4011B700 WRITE   3403413\n0x4011B740 WRITE   3403469\n0x4011B780 WRITE   3403540\n0x4011B7C0 WRITE   3403596\n0x40186E00 WRITE   3403673\n0x40186DC0 WRITE   3403675\n0x40186D00 WRITE   3403682\n0x40186CC0 WRITE   3403684\n0x40186C80 WRITE   3403694\n0x40186C40 WRITE   3403696\n0x4011B800 WRITE   3403723\n0x4011B840 WRITE   3403779\n0x4011B880 WRITE   3403845\n0x4011B8C0 WRITE   3403901\n0x4011B900 WRITE   3403988\n0x4011B940 WRITE   3404044\n0x4011B980 WRITE   3404107\n0x4011B9C0 WRITE   3404163\n0x40186D80 WRITE   3404232\n0x40186D40 WRITE   3404234\n0x4011BA00 WRITE   3404270\n0x4011BA40 WRITE   3404326\n0x4011BA80 WRITE   3404389\n0x4011BAC0 WRITE   3404445\n0x4011BB00 WRITE   3404527\n0x4011BB40 WRITE   3404583\n0x4011BB80 WRITE   3404646\n0x4011BBC0 WRITE   3404702\n0x40186F00 WRITE   3404775\n0x40186EC0 WRITE   3404777\n0x40186E80 WRITE   3404784\n0x40186E40 WRITE   3404786\n0x4011BC00 WRITE   3404819\n0x4011BC40 WRITE   3404875\n0x4011BC80 WRITE   3404949\n0x4011BCC0 WRITE   3405005\n0x4011BD00 WRITE   3405100\n0x4011BD40 WRITE   3405156\n0x4011BD80 WRITE   3405227\n0x4011BDC0 WRITE   3405283\n0x40186F80 WRITE   3405360\n0x40186F40 WRITE   3405362\n0x4011BE00 WRITE   3405398\n0x4011BE40 WRITE   3405454\n0x4011BE80 WRITE   3405525\n0x4011BEC0 WRITE   3405581\n0x4011BF00 WRITE   3405671\n0x4011BF40 WRITE   3405727\n0x4011BF80 WRITE   3405798\n0x4011BFC0 WRITE   3405854\n0x40187800 WRITE   3405940\n0x401877C0 WRITE   3405942\n0x40187400 WRITE   3405949\n0x401873C0 WRITE   3405951\n0x40187200 WRITE   3405961\n0x401871C0 WRITE   3405963\n0x40187100 WRITE   3405968\n0x401870C0 WRITE   3405971\n0x40187080 WRITE   3405974\n0x40187040 WRITE   3405977\n0x4011C000 WRITE   3406002\n0x4011C040 WRITE   3406086\n0x4011C080 WRITE   3406152\n0x4011C0C0 WRITE   3406208\n0x4011C100 WRITE   3406291\n0x4011C140 WRITE   3406347\n0x4011C180 WRITE   3406410\n0x4011C1C0 WRITE   3406466\n0x40187180 WRITE   3406522\n0x40187140 WRITE   3406524\n0x4011C200 WRITE   3406560\n0x4011C240 WRITE   3406616\n0x4011C280 WRITE   3406679\n0x4011C2C0 WRITE   3406735\n0x4011C300 WRITE   3406813\n0x4011C340 WRITE   3406869\n0x4011C380 WRITE   3406932\n0x4011C3C0 WRITE   3406988\n0x40187300 WRITE   3407054\n0x401872C0 WRITE   3407056\n0x40187280 WRITE   3407063\n0x40187240 WRITE   3407065\n0x4011C400 WRITE   3407098\n0x4011C440 WRITE   3407154\n0x4011C480 WRITE   3407228\n0x4011C4C0 WRITE   3407284\n0x4011C500 WRITE   3407375\n0x4011C540 WRITE   3407431\n0x4011C580 WRITE   3407502\n0x4011C5C0 WRITE   3407558\n0x40187380 WRITE   3407622\n0x40187340 WRITE   3407624\n0x4011C600 WRITE   3407660\n0x4011C640 WRITE   3407716\n0x4011C680 WRITE   3407787\n0x4011C6C0 WRITE   3407843\n0x4011C700 WRITE   3407929\n0x4011C740 WRITE   3407985\n0x4011C780 WRITE   3408056\n0x4011C7C0 WRITE   3408112\n0x40187600 WRITE   3408187\n0x401875C0 WRITE   3408189\n0x40187500 WRITE   3408196\n0x401874C0 WRITE   3408198\n0x40187480 WRITE   3408208\n0x40187440 WRITE   3408210\n0x4011C800 WRITE   3408237\n0x4011C840 WRITE   3408293\n0x4011C880 WRITE   3408359\n0x4011C8C0 WRITE   3408415\n0x4011C900 WRITE   3408502\n0x4011C940 WRITE   3408558\n0x4011C980 WRITE   3408621\n0x4011C9C0 WRITE   3408677\n0x40187580 WRITE   3408739\n0x40187540 WRITE   3408741\n0x4011CA00 WRITE   3408777\n0x4011CA40 WRITE   3408833\n0x4011CA80 WRITE   3408896\n0x4011CAC0 WRITE   3408952\n0x4011CB00 WRITE   3409034\n0x4011CB40 WRITE   3409090\n0x4011CB80 WRITE   3409153\n0x4011CBC0 WRITE   3409209\n0x40187700 WRITE   3409281\n0x401876C0 WRITE   3409283\n0x40187680 WRITE   3409290\n0x40187640 WRITE   3409292\n0x4011CC00 WRITE   3409325\n0x4011CC40 WRITE   3409381\n0x4011CC80 WRITE   3409455\n0x4011CCC0 WRITE   3409511\n0x4011CD00 WRITE   3409606\n0x4011CD40 WRITE   3409662\n0x4011CD80 WRITE   3409733\n0x4011CDC0 WRITE   3409789\n0x40187780 WRITE   3409859\n0x40187740 WRITE   3409861\n0x4011CE00 WRITE   3409897\n0x4011CE40 WRITE   3409953\n0x4011CE80 WRITE   3410024\n0x4011CEC0 WRITE   3410080\n0x4011CF00 WRITE   3410170\n0x4011CF40 WRITE   3410226\n0x4011CF80 WRITE   3410297\n0x4011CFC0 WRITE   3410353\n0x40187C00 WRITE   3410439\n0x40187BC0 WRITE   3410441\n0x40187A00 WRITE   3410448\n0x401879C0 WRITE   3410450\n0x40187900 WRITE   3410460\n0x401878C0 WRITE   3410462\n0x40187880 WRITE   3410467\n0x40187840 WRITE   3410470\n0x4011D000 WRITE   3410495\n0x4011D040 WRITE   3410579\n0x4011D080 WRITE   3410645\n0x4011D0C0 WRITE   3410701\n0x4011D100 WRITE   3410784\n0x4011D140 WRITE   3410840\n0x4011D180 WRITE   3410903\n0x4011D1C0 WRITE   3410959\n0x40187980 WRITE   3411023\n0x40187940 WRITE   3411025\n0x4011D200 WRITE   3411061\n0x4011D240 WRITE   3411117\n0x4011D280 WRITE   3411180\n0x4011D2C0 WRITE   3411236\n0x4011D300 WRITE   3411314\n0x4011D340 WRITE   3411370\n0x4011D380 WRITE   3411433\n0x4011D3C0 WRITE   3411489\n0x40187B00 WRITE   3411563\n0x40187AC0 WRITE   3411565\n0x40187A80 WRITE   3411572\n0x40187A40 WRITE   3411574\n0x4011D400 WRITE   3411607\n0x4011D440 WRITE   3411663\n0x4011D480 WRITE   3411737\n0x4011D4C0 WRITE   3411793\n0x4011D500 WRITE   3411884\n0x4011D540 WRITE   3411940\n0x4011D580 WRITE   3412011\n0x4011D5C0 WRITE   3412067\n0x40187B80 WRITE   3412139\n0x40187B40 WRITE   3412141\n0x4011D600 WRITE   3412177\n0x4011D640 WRITE   3412233\n0x4011D680 WRITE   3412304\n0x4011D6C0 WRITE   3412360\n0x4011D700 WRITE   3412446\n0x4011D740 WRITE   3412502\n0x4011D780 WRITE   3412573\n0x4011D7C0 WRITE   3412629\n0x40187E00 WRITE   3412712\n0x40187DC0 WRITE   3412714\n0x40187D00 WRITE   3412721\n0x40187CC0 WRITE   3412723\n0x40187C80 WRITE   3412733\n0x40187C40 WRITE   3412735\n0x4011D800 WRITE   3412762\n0x4011D840 WRITE   3412818\n0x4011D880 WRITE   3412884\n0x4011D8C0 WRITE   3412940\n0x4011D900 WRITE   3413027\n0x4011D940 WRITE   3413083\n0x4011D980 WRITE   3413146\n0x4011D9C0 WRITE   3413202\n0x40187D80 WRITE   3413271\n0x40187D40 WRITE   3413273\n0x4011DA00 WRITE   3413309\n0x4011DA40 WRITE   3413365\n0x4011DA80 WRITE   3413428\n0x4011DAC0 WRITE   3413484\n0x4011DB00 WRITE   3413566\n0x4011DB40 WRITE   3413622\n0x4011DB80 WRITE   3413685\n0x4011DBC0 WRITE   3413741\n0x40187F00 WRITE   3413820\n0x40187EC0 WRITE   3413822\n0x40187E80 WRITE   3413829\n0x40187E40 WRITE   3413831\n0x4011DC00 WRITE   3413864\n0x4011DC40 WRITE   3413920\n0x4011DC80 WRITE   3413994\n0x4011DCC0 WRITE   3414050\n0x4011DD00 WRITE   3414145\n0x4011DD40 WRITE   3414201\n0x4011DD80 WRITE   3414272\n0x4011DDC0 WRITE   3414328\n0x40187F80 WRITE   3414405\n0x40187F40 WRITE   3414407\n0x4011DE00 WRITE   3414443\n0x4011DE40 WRITE   3414499\n0x4011DE80 WRITE   3414570\n0x4011DEC0 WRITE   3414626\n0x4011DF00 WRITE   3414716\n0x4011DF40 WRITE   3414772\n0x4011DF80 WRITE   3414843\n0x4011DFC0 WRITE   3414899\n0x40189FC0 WRITE   3415061\n0x4018A000 WRITE   3415093\n0x40189000 WRITE   3415236\n0x40188FC0 WRITE   3415238\n0x40188800 WRITE   3415245\n0x401887C0 WRITE   3415247\n0x40188400 WRITE   3415257\n0x401883C0 WRITE   3415259\n0x40188200 WRITE   3415264\n0x401881C0 WRITE   3415267\n0x40188100 WRITE   3415270\n0x401880C0 WRITE   3415273\n0x40188080 WRITE   3415276\n0x40188040 WRITE   3415279\n0x4011E000 WRITE   3415311\n0x4011E040 WRITE   3415399\n0x4011E080 WRITE   3415465\n0x4011E0C0 WRITE   3415521\n0x4011E100 WRITE   3415604\n0x4011E140 WRITE   3415660\n0x4011E180 WRITE   3415723\n0x4011E1C0 WRITE   3415779\n0x40188180 WRITE   3415835\n0x40188140 WRITE   3415837\n0x4011E200 WRITE   3415873\n0x4011E240 WRITE   3415929\n0x4011E280 WRITE   3415992\n0x4011E2C0 WRITE   3416048\n0x4011E300 WRITE   3416126\n0x4011E340 WRITE   3416182\n0x4011E380 WRITE   3416245\n0x4011E3C0 WRITE   3416301\n0x40188300 WRITE   3416362\n0x401882C0 WRITE   3416364\n0x40188280 WRITE   3416371\n0x40188240 WRITE   3416373\n0x4011E400 WRITE   3416406\n0x4011E440 WRITE   3416462\n0x4011E480 WRITE   3416536\n0x4011E4C0 WRITE   3416592\n0x4011E500 WRITE   3416683\n0x4011E540 WRITE   3416739\n0x4011E580 WRITE   3416810\n0x4011E5C0 WRITE   3416866\n0x40188380 WRITE   3416930\n0x40188340 WRITE   3416932\n0x4011E600 WRITE   3416968\n0x4011E640 WRITE   3417024\n0x4011E680 WRITE   3417095\n0x4011E6C0 WRITE   3417151\n0x4011E700 WRITE   3417237\n0x4011E740 WRITE   3417293\n0x4011E780 WRITE   3417364\n0x4011E7C0 WRITE   3417420\n0x40188600 WRITE   3417489\n0x401885C0 WRITE   3417491\n0x40188500 WRITE   3417498\n0x401884C0 WRITE   3417500\n0x40188480 WRITE   3417510\n0x40188440 WRITE   3417512\n0x4011E800 WRITE   3417539\n0x4011E840 WRITE   3417595\n0x4011E880 WRITE   3417661\n0x4011E8C0 WRITE   3417717\n0x4011E900 WRITE   3417804\n0x4011E940 WRITE   3417860\n0x4011E980 WRITE   3417923\n0x4011E9C0 WRITE   3417979\n0x40188580 WRITE   3418041\n0x40188540 WRITE   3418043\n0x4011EA00 WRITE   3418079\n0x4011EA40 WRITE   3418135\n0x4011EA80 WRITE   3418198\n0x4011EAC0 WRITE   3418254\n0x4011EB00 WRITE   3418336\n0x4011EB40 WRITE   3418392\n0x4011EB80 WRITE   3418455\n0x4011EBC0 WRITE   3418511\n0x40188700 WRITE   3418577\n0x401886C0 WRITE   3418579\n0x40188680 WRITE   3418586\n0x40188640 WRITE   3418588\n0x4011EC00 WRITE   3418621\n0x4011EC40 WRITE   3418677\n0x4011EC80 WRITE   3418751\n0x4011ECC0 WRITE   3418807\n0x4011ED00 WRITE   3418902\n0x4011ED40 WRITE   3418958\n0x4011ED80 WRITE   3419029\n0x4011EDC0 WRITE   3419085\n0x40188780 WRITE   3419155\n0x40188740 WRITE   3419157\n0x4011EE00 WRITE   3419193\n0x4011EE40 WRITE   3419249\n0x4011EE80 WRITE   3419320\n0x4011EEC0 WRITE   3419376\n0x4011EF00 WRITE   3419466\n0x4011EF40 WRITE   3419522\n0x4011EF80 WRITE   3419593\n0x4011EFC0 WRITE   3419649\n0x40188C00 WRITE   3419729\n0x40188BC0 WRITE   3419731\n0x40188A00 WRITE   3419738\n0x401889C0 WRITE   3419740\n0x40188900 WRITE   3419750\n0x401888C0 WRITE   3419752\n0x40188880 WRITE   3419757\n0x40188840 WRITE   3419760\n0x4011F000 WRITE   3419785\n0x4011F040 WRITE   3419869\n0x4011F080 WRITE   3419935\n0x4011F0C0 WRITE   3419991\n0x4011F100 WRITE   3420074\n0x4011F140 WRITE   3420130\n0x4011F180 WRITE   3420193\n0x4011F1C0 WRITE   3420249\n0x40188980 WRITE   3420313\n0x40188940 WRITE   3420315\n0x4011F200 WRITE   3420351\n0x4011F240 WRITE   3420407\n0x4011F280 WRITE   3420470\n0x4011F2C0 WRITE   3420526\n0x4011F300 WRITE   3420604\n0x4011F340 WRITE   3420660\n0x4011F380 WRITE   3420723\n0x4011F3C0 WRITE   3420779\n0x40188B00 WRITE   3420847\n0x40188AC0 WRITE   3420849\n0x40188A80 WRITE   3420856\n0x40188A40 WRITE   3420858\n0x4011F400 WRITE   3420891\n0x4011F440 WRITE   3420947\n0x4011F480 WRITE   3421021\n0x4011F4C0 WRITE   3421077\n0x4011F500 WRITE   3421168\n0x4011F540 WRITE   3421224\n0x4011F580 WRITE   3421295\n0x4011F5C0 WRITE   3421351\n0x40188B80 WRITE   3421423\n0x40188B40 WRITE   3421425\n0x4011F600 WRITE   3421461\n0x4011F640 WRITE   3421517\n0x4011F680 WRITE   3421588\n0x4011F6C0 WRITE   3421644\n0x4011F700 WRITE   3421730\n0x4011F740 WRITE   3421786\n0x4011F780 WRITE   3421857\n0x4011F7C0 WRITE   3421913\n0x40188E00 WRITE   3421990\n0x40188DC0 WRITE   3421992\n0x40188D00 WRITE   3421999\n0x40188CC0 WRITE   3422001\n0x40188C80 WRITE   3422011\n0x40188C40 WRITE   3422013\n0x4011F800 WRITE   3422040\n0x4011F840 WRITE   3422096\n0x4011F880 WRITE   3422162\n0x4011F8C0 WRITE   3422218\n0x4011F900 WRITE   3422305\n0x4011F940 WRITE   3422361\n0x4011F980 WRITE   3422424\n0x4011F9C0 WRITE   3422480\n0x40188D80 WRITE   3422549\n0x40188D40 WRITE   3422551\n0x4011FA00 WRITE   3422587\n0x4011FA40 WRITE   3422643\n0x4011FA80 WRITE   3422706\n0x4011FAC0 WRITE   3422762\n0x4011FB00 WRITE   3422844\n0x4011FB40 WRITE   3422900\n0x4011FB80 WRITE   3422963\n0x4011FBC0 WRITE   3423019\n0x40188F00 WRITE   3423092\n0x40188EC0 WRITE   3423094\n0x40188E80 WRITE   3423101\n0x40188E40 WRITE   3423103\n0x4011FC00 WRITE   3423136\n0x4011FC40 WRITE   3423192\n0x4011FC80 WRITE   3423266\n0x4011FCC0 WRITE   3423322\n0x4011FD00 WRITE   3423417\n0x4011FD40 WRITE   3423473\n0x4011FD80 WRITE   3423544\n0x4011FDC0 WRITE   3423600\n0x40188F80 WRITE   3423677\n0x40188F40 WRITE   3423679\n0x4011FE00 WRITE   3423715\n0x4011FE40 WRITE   3423771\n0x4011FE80 WRITE   3423842\n0x4011FEC0 WRITE   3423898\n0x4011FF00 WRITE   3423988\n0x4011FF40 WRITE   3424044\n0x4011FF80 WRITE   3424115\n0x4011FFC0 WRITE   3424171\n0x40189800 WRITE   3424257\n0x401897C0 WRITE   3424259\n0x40189400 WRITE   3424266\n0x401893C0 WRITE   3424268\n0x40189200 WRITE   3424278\n0x401891C0 WRITE   3424280\n0x40189100 WRITE   3424285\n0x401890C0 WRITE   3424288\n0x40189080 WRITE   3424291\n0x40189040 WRITE   3424294\n0x40120000 WRITE   3424319\n0x40120040 WRITE   3424403\n0x40120080 WRITE   3424469\n0x401200C0 WRITE   3424525\n0x40120100 WRITE   3424608\n0x40120140 WRITE   3424664\n0x40120180 WRITE   3424727\n0x401201C0 WRITE   3424783\n0x40189180 WRITE   3424839\n0x40189140 WRITE   3424841\n0x40120200 WRITE   3424877\n0x40120240 WRITE   3424933\n0x40120280 WRITE   3424996\n0x401202C0 WRITE   3425052\n0x40120300 WRITE   3425130\n0x40120340 WRITE   3425186\n0x40120380 WRITE   3425249\n0x401203C0 WRITE   3425305\n0x40189300 WRITE   3425371\n0x401892C0 WRITE   3425373\n0x40189280 WRITE   3425380\n0x40189240 WRITE   3425382\n0x40120400 WRITE   3425415\n0x40120440 WRITE   3425471\n0x40120480 WRITE   3425545\n0x401204C0 WRITE   3425601\n0x40120500 WRITE   3425692\n0x40120540 WRITE   3425748\n0x40120580 WRITE   3425819\n0x401205C0 WRITE   3425875\n0x40189380 WRITE   3425939\n0x40189340 WRITE   3425941\n0x40120600 WRITE   3425977\n0x40120640 WRITE   3426033\n0x40120680 WRITE   3426104\n0x401206C0 WRITE   3426160\n0x40120700 WRITE   3426246\n0x40120740 WRITE   3426302\n0x40120780 WRITE   3426373\n0x401207C0 WRITE   3426429\n0x40189600 WRITE   3426504\n0x401895C0 WRITE   3426506\n0x40189500 WRITE   3426513\n0x401894C0 WRITE   3426515\n0x40189480 WRITE   3426525\n0x40189440 WRITE   3426527\n0x40120800 WRITE   3426554\n0x40120840 WRITE   3426610\n0x40120880 WRITE   3426676\n0x401208C0 WRITE   3426732\n0x40120900 WRITE   3426819\n0x40120940 WRITE   3426875\n0x40120980 WRITE   3426938\n0x401209C0 WRITE   3426994\n0x40189580 WRITE   3427056\n0x40189540 WRITE   3427058\n0x40120A00 WRITE   3427094\n0x40120A40 WRITE   3427150\n0x40120A80 WRITE   3427213\n0x40120AC0 WRITE   3427269\n0x40120B00 WRITE   3427351\n0x40120B40 WRITE   3427407\n0x40120B80 WRITE   3427470\n0x40120BC0 WRITE   3427526\n0x40189700 WRITE   3427598\n0x401896C0 WRITE   3427600\n0x40189680 WRITE   3427607\n0x40189640 WRITE   3427609\n0x40120C00 WRITE   3427642\n0x40120C40 WRITE   3427698\n0x40120C80 WRITE   3427772\n0x40120CC0 WRITE   3427828\n0x40120D00 WRITE   3427923\n0x40120D40 WRITE   3427979\n0x40120D80 WRITE   3428050\n0x40120DC0 WRITE   3428106\n0x40189780 WRITE   3428176\n0x40189740 WRITE   3428178\n0x40120E00 WRITE   3428214\n0x40120E40 WRITE   3428270\n0x40120E80 WRITE   3428341\n0x40120EC0 WRITE   3428397\n0x40120F00 WRITE   3428487\n0x40120F40 WRITE   3428543\n0x40120F80 WRITE   3428614\n0x40120FC0 WRITE   3428670\n0x40189C00 WRITE   3428756\n0x40189BC0 WRITE   3428758\n0x40189A00 WRITE   3428765\n0x401899C0 WRITE   3428767\n0x40189900 WRITE   3428777\n0x401898C0 WRITE   3428779\n0x40189880 WRITE   3428784\n0x40189840 WRITE   3428787\n0x40121000 WRITE   3428812\n0x40121040 WRITE   3428896\n0x40121080 WRITE   3428962\n0x401210C0 WRITE   3429018\n0x40121100 WRITE   3429101\n0x40121140 WRITE   3429157\n0x40121180 WRITE   3429220\n0x401211C0 WRITE   3429276\n0x40189980 WRITE   3429340\n0x40189940 WRITE   3429342\n0x40121200 WRITE   3429378\n0x40121240 WRITE   3429434\n0x40121280 WRITE   3429497\n0x401212C0 WRITE   3429553\n0x40121300 WRITE   3429631\n0x40121340 WRITE   3429687\n0x40121380 WRITE   3429750\n0x401213C0 WRITE   3429806\n0x40189B00 WRITE   3429880\n0x40189AC0 WRITE   3429882\n0x40189A80 WRITE   3429889\n0x40189A40 WRITE   3429891\n0x40121400 WRITE   3429924\n0x40121440 WRITE   3429980\n0x40121480 WRITE   3430054\n0x401214C0 WRITE   3430110\n0x40121500 WRITE   3430201\n0x40121540 WRITE   3430257\n0x40121580 WRITE   3430328\n0x401215C0 WRITE   3430384\n0x40189B80 WRITE   3430456\n0x40189B40 WRITE   3430458\n0x40121600 WRITE   3430494\n0x40121640 WRITE   3430550\n0x40121680 WRITE   3430621\n0x401216C0 WRITE   3430677\n0x40121700 WRITE   3430763\n0x40121740 WRITE   3430819\n0x40121780 WRITE   3430890\n0x401217C0 WRITE   3430946\n0x40189E00 WRITE   3431029\n0x40189DC0 WRITE   3431031\n0x40189D00 WRITE   3431038\n0x40189CC0 WRITE   3431040\n0x40189C80 WRITE   3431050\n0x40189C40 WRITE   3431052\n0x40121800 WRITE   3431079\n0x40121840 WRITE   3431135\n0x40121880 WRITE   3431201\n0x401218C0 WRITE   3431257\n0x40121900 WRITE   3431344\n0x40121940 WRITE   3431400\n0x40121980 WRITE   3431463\n0x401219C0 WRITE   3431519\n0x40189D80 WRITE   3431588\n0x40189D40 WRITE   3431590\n0x40121A00 WRITE   3431626\n0x40121A40 WRITE   3431682\n0x40121A80 WRITE   3431745\n0x40121AC0 WRITE   3431801\n0x40121B00 WRITE   3431883\n0x40121B40 WRITE   3431939\n0x40121B80 WRITE   3432002\n0x40121BC0 WRITE   3432058\n0x40189F00 WRITE   3432137\n0x40189EC0 WRITE   3432139\n0x40189E80 WRITE   3432146\n0x40189E40 WRITE   3432148\n0x40121C00 WRITE   3432181\n0x40121C40 WRITE   3432237\n0x40121C80 WRITE   3432311\n0x40121CC0 WRITE   3432367\n0x40121D00 WRITE   3432462\n0x40121D40 WRITE   3432518\n0x40121D80 WRITE   3432589\n0x40121DC0 WRITE   3432645\n0x40189F80 WRITE   3432722\n0x40189F40 WRITE   3432724\n0x40121E00 WRITE   3432760\n0x40121E40 WRITE   3432816\n0x40121E80 WRITE   3432887\n0x40121EC0 WRITE   3432943\n0x40121F00 WRITE   3433033\n0x40121F40 WRITE   3433089\n0x40121F80 WRITE   3433160\n0x40121FC0 WRITE   3433216\n0x4018BFC0 WRITE   3433378\n0x4018C000 WRITE   3433410\n0x4018B000 WRITE   3433537\n0x4018AFC0 WRITE   3433539\n0x4018A800 WRITE   3433546\n0x4018A7C0 WRITE   3433548\n0x4018A400 WRITE   3433558\n0x4018A3C0 WRITE   3433560\n0x4018A200 WRITE   3433565\n0x4018A1C0 WRITE   3433568\n0x4018A100 WRITE   3433571\n0x4018A0C0 WRITE   3433574\n0x4018A080 WRITE   3433577\n0x4018A040 WRITE   3433580\n0x40122000 WRITE   3433612\n0x40122040 WRITE   3433700\n0x40122080 WRITE   3433766\n0x401220C0 WRITE   3433822\n0x40122100 WRITE   3433905\n0x40122140 WRITE   3433961\n0x40122180 WRITE   3434024\n0x401221C0 WRITE   3434080\n0x4018A180 WRITE   3434136\n0x4018A140 WRITE   3434138\n0x40122200 WRITE   3434174\n0x40122240 WRITE   3434230\n0x40122280 WRITE   3434293\n0x401222C0 WRITE   3434349\n0x40122300 WRITE   3434427\n0x40122340 WRITE   3434483\n0x40122380 WRITE   3434546\n0x401223C0 WRITE   3434602\n0x4018A300 WRITE   3434663\n0x4018A2C0 WRITE   3434665\n0x4018A280 WRITE   3434672\n0x4018A240 WRITE   3434674\n0x40122400 WRITE   3434707\n0x40122440 WRITE   3434763\n0x40122480 WRITE   3434837\n0x401224C0 WRITE   3434893\n0x40122500 WRITE   3434984\n0x40122540 WRITE   3435040\n0x40122580 WRITE   3435111\n0x401225C0 WRITE   3435167\n0x4018A380 WRITE   3435231\n0x4018A340 WRITE   3435233\n0x40122600 WRITE   3435269\n0x40122640 WRITE   3435325\n0x40122680 WRITE   3435396\n0x401226C0 WRITE   3435452\n0x40122700 WRITE   3435538\n0x40122740 WRITE   3435594\n0x40122780 WRITE   3435665\n0x401227C0 WRITE   3435721\n0x4018A600 WRITE   3435790\n0x4018A5C0 WRITE   3435792\n0x4018A500 WRITE   3435799\n0x4018A4C0 WRITE   3435801\n0x4018A480 WRITE   3435811\n0x4018A440 WRITE   3435813\n0x40122800 WRITE   3435840\n0x40122840 WRITE   3435896\n0x40122880 WRITE   3435962\n0x401228C0 WRITE   3436018\n0x40122900 WRITE   3436105\n0x40122940 WRITE   3436161\n0x40122980 WRITE   3436224\n0x401229C0 WRITE   3436280\n0x4018A580 WRITE   3436342\n0x4018A540 WRITE   3436344\n0x40122A00 WRITE   3436380\n0x40122A40 WRITE   3436436\n0x40122A80 WRITE   3436499\n0x40122AC0 WRITE   3436555\n0x40122B00 WRITE   3436637\n0x40122B40 WRITE   3436693\n0x40122B80 WRITE   3436756\n0x40122BC0 WRITE   3436812\n0x4018A700 WRITE   3436878\n0x4018A6C0 WRITE   3436880\n0x4018A680 WRITE   3436887\n0x4018A640 WRITE   3436889\n0x40122C00 WRITE   3436922\n0x40122C40 WRITE   3436978\n0x40122C80 WRITE   3437052\n0x40122CC0 WRITE   3437108\n0x40122D00 WRITE   3437203\n0x40122D40 WRITE   3437259\n0x40122D80 WRITE   3437330\n0x40122DC0 WRITE   3437386\n0x4018A780 WRITE   3437456\n0x4018A740 WRITE   3437458\n0x40122E00 WRITE   3437494\n0x40122E40 WRITE   3437550\n0x40122E80 WRITE   3437621\n0x40122EC0 WRITE   3437677\n0x40122F00 WRITE   3437767\n0x40122F40 WRITE   3437823\n0x40122F80 WRITE   3437894\n0x40122FC0 WRITE   3437950\n0x4018AC00 WRITE   3438030\n0x4018ABC0 WRITE   3438032\n0x4018AA00 WRITE   3438039\n0x4018A9C0 WRITE   3438041\n0x4018A900 WRITE   3438051\n0x4018A8C0 WRITE   3438053\n0x4018A880 WRITE   3438058\n0x4018A840 WRITE   3438061\n0x40123000 WRITE   3438086\n0x40123040 WRITE   3438170\n0x40123080 WRITE   3438236\n0x401230C0 WRITE   3438292\n0x40123100 WRITE   3438375\n0x40123140 WRITE   3438431\n0x40123180 WRITE   3438494\n0x401231C0 WRITE   3438550\n0x4018A980 WRITE   3438614\n0x4018A940 WRITE   3438616\n0x40123200 WRITE   3438652\n0x40123240 WRITE   3438708\n0x40123280 WRITE   3438771\n0x401232C0 WRITE   3438827\n0x40123300 WRITE   3438905\n0x40123340 WRITE   3438961\n0x40123380 WRITE   3439024\n0x401233C0 WRITE   3439080\n0x4018AB00 WRITE   3439148\n0x4018AAC0 WRITE   3439150\n0x4018AA80 WRITE   3439157\n0x4018AA40 WRITE   3439159\n0x40123400 WRITE   3439192\n0x40123440 WRITE   3439248\n0x40123480 WRITE   3439322\n0x401234C0 WRITE   3439378\n0x40123500 WRITE   3439469\n0x40123540 WRITE   3439525\n0x40123580 WRITE   3439596\n0x401235C0 WRITE   3439652\n0x4018AB80 WRITE   3439724\n0x4018AB40 WRITE   3439726\n0x40123600 WRITE   3439762\n0x40123640 WRITE   3439818\n0x40123680 WRITE   3439889\n0x401236C0 WRITE   3439945\n0x40123700 WRITE   3440031\n0x40123740 WRITE   3440087\n0x40123780 WRITE   3440158\n0x401237C0 WRITE   3440214\n0x4018AE00 WRITE   3440291\n0x4018ADC0 WRITE   3440293\n0x4018AD00 WRITE   3440300\n0x4018ACC0 WRITE   3440302\n0x4018AC80 WRITE   3440312\n0x4018AC40 WRITE   3440314\n0x40123800 WRITE   3440341\n0x40123840 WRITE   3440397\n0x40123880 WRITE   3440463\n0x401238C0 WRITE   3440519\n0x40123900 WRITE   3440606\n0x40123940 WRITE   3440662\n0x40123980 WRITE   3440725\n0x401239C0 WRITE   3440781\n0x4018AD80 WRITE   3440850\n0x4018AD40 WRITE   3440852\n0x40123A00 WRITE   3440888\n0x40123A40 WRITE   3440944\n0x40123A80 WRITE   3441007\n0x40123AC0 WRITE   3441063\n0x40123B00 WRITE   3441145\n0x40123B40 WRITE   3441201\n0x40123B80 WRITE   3441264\n0x40123BC0 WRITE   3441320\n0x4018AF00 WRITE   3441393\n0x4018AEC0 WRITE   3441395\n0x4018AE80 WRITE   3441402\n0x4018AE40 WRITE   3441404\n0x40123C00 WRITE   3441437\n0x40123C40 WRITE   3441493\n0x40123C80 WRITE   3441567\n0x40123CC0 WRITE   3441623\n0x40123D00 WRITE   3441718\n0x40123D40 WRITE   3441774\n0x40123D80 WRITE   3441845\n0x40123DC0 WRITE   3441901\n0x4018AF80 WRITE   3441978\n0x4018AF40 WRITE   3441980\n0x40123E00 WRITE   3442016\n0x40123E40 WRITE   3442072\n0x40123E80 WRITE   3442143\n0x40123EC0 WRITE   3442199\n0x40123F00 WRITE   3442289\n0x40123F40 WRITE   3442345\n0x40123F80 WRITE   3442416\n0x40123FC0 WRITE   3442472\n0x4018B800 WRITE   3442558\n0x4018B7C0 WRITE   3442560\n0x4018B400 WRITE   3442567\n0x4018B3C0 WRITE   3442569\n0x4018B200 WRITE   3442579\n0x4018B1C0 WRITE   3442581\n0x4018B100 WRITE   3442586\n0x4018B0C0 WRITE   3442589\n0x4018B080 WRITE   3442592\n0x4018B040 WRITE   3442595\n0x40124000 WRITE   3442620\n0x40124040 WRITE   3442704\n0x40124080 WRITE   3442770\n0x401240C0 WRITE   3442826\n0x40124100 WRITE   3442909\n0x40124140 WRITE   3442965\n0x40124180 WRITE   3443028\n0x401241C0 WRITE   3443084\n0x4018B180 WRITE   3443140\n0x4018B140 WRITE   3443142\n0x40124200 WRITE   3443178\n0x40124240 WRITE   3443234\n0x40124280 WRITE   3443297\n0x401242C0 WRITE   3443353\n0x40124300 WRITE   3443431\n0x40124340 WRITE   3443487\n0x40124380 WRITE   3443550\n0x401243C0 WRITE   3443606\n0x4018B300 WRITE   3443672\n0x4018B2C0 WRITE   3443674\n0x4018B280 WRITE   3443681\n0x4018B240 WRITE   3443683\n0x40124400 WRITE   3443716\n0x40124440 WRITE   3443772\n0x40124480 WRITE   3443846\n0x401244C0 WRITE   3443902\n0x40124500 WRITE   3443993\n0x40124540 WRITE   3444049\n0x40124580 WRITE   3444120\n0x401245C0 WRITE   3444176\n0x4018B380 WRITE   3444240\n0x4018B340 WRITE   3444242\n0x40124600 WRITE   3444278\n0x40124640 WRITE   3444334\n0x40124680 WRITE   3444405\n0x401246C0 WRITE   3444461\n0x40124700 WRITE   3444547\n0x40124740 WRITE   3444603\n0x40124780 WRITE   3444674\n0x401247C0 WRITE   3444730\n0x4018B600 WRITE   3444805\n0x4018B5C0 WRITE   3444807\n0x4018B500 WRITE   3444814\n0x4018B4C0 WRITE   3444816\n0x4018B480 WRITE   3444826\n0x4018B440 WRITE   3444828\n0x40124800 WRITE   3444855\n0x40124840 WRITE   3444911\n0x40124880 WRITE   3444977\n0x401248C0 WRITE   3445033\n0x40124900 WRITE   3445120\n0x40124940 WRITE   3445176\n0x40124980 WRITE   3445239\n0x401249C0 WRITE   3445295\n0x4018B580 WRITE   3445357\n0x4018B540 WRITE   3445359\n0x40124A00 WRITE   3445395\n0x40124A40 WRITE   3445451\n0x40124A80 WRITE   3445514\n0x40124AC0 WRITE   3445570\n0x40124B00 WRITE   3445652\n0x40124B40 WRITE   3445708\n0x40124B80 WRITE   3445771\n0x40124BC0 WRITE   3445827\n0x4018B700 WRITE   3445899\n0x4018B6C0 WRITE   3445901\n0x4018B680 WRITE   3445908\n0x4018B640 WRITE   3445910\n0x40124C00 WRITE   3445943\n0x40124C40 WRITE   3445999\n0x40124C80 WRITE   3446073\n0x40124CC0 WRITE   3446129\n0x40124D00 WRITE   3446224\n0x40124D40 WRITE   3446280\n0x40124D80 WRITE   3446351\n0x40124DC0 WRITE   3446407\n0x4018B780 WRITE   3446477\n0x4018B740 WRITE   3446479\n0x40124E00 WRITE   3446515\n0x40124E40 WRITE   3446571\n0x40124E80 WRITE   3446642\n0x40124EC0 WRITE   3446698\n0x40124F00 WRITE   3446788\n0x40124F40 WRITE   3446844\n0x40124F80 WRITE   3446915\n0x40124FC0 WRITE   3446971\n0x4018BC00 WRITE   3447057\n0x4018BBC0 WRITE   3447059\n0x4018BA00 WRITE   3447066\n0x4018B9C0 WRITE   3447068\n0x4018B900 WRITE   3447078\n0x4018B8C0 WRITE   3447080\n0x4018B880 WRITE   3447085\n0x4018B840 WRITE   3447088\n0x40125000 WRITE   3447113\n0x40125040 WRITE   3447197\n0x40125080 WRITE   3447263\n0x401250C0 WRITE   3447319\n0x40125100 WRITE   3447402\n0x40125140 WRITE   3447458\n0x40125180 WRITE   3447521\n0x401251C0 WRITE   3447577\n0x4018B980 WRITE   3447641\n0x4018B940 WRITE   3447643\n0x40125200 WRITE   3447679\n0x40125240 WRITE   3447735\n0x40125280 WRITE   3447798\n0x401252C0 WRITE   3447854\n0x40125300 WRITE   3447932\n0x40125340 WRITE   3447988\n0x40125380 WRITE   3448051\n0x401253C0 WRITE   3448107\n0x4018BB00 WRITE   3448181\n0x4018BAC0 WRITE   3448183\n0x4018BA80 WRITE   3448190\n0x4018BA40 WRITE   3448192\n0x40125400 WRITE   3448225\n0x40125440 WRITE   3448281\n0x40125480 WRITE   3448355\n0x401254C0 WRITE   3448411\n0x40125500 WRITE   3448502\n0x40125540 WRITE   3448558\n0x40125580 WRITE   3448629\n0x401255C0 WRITE   3448685\n0x4018BB80 WRITE   3448757\n0x4018BB40 WRITE   3448759\n0x40125600 WRITE   3448795\n0x40125640 WRITE   3448851\n0x40125680 WRITE   3448922\n0x401256C0 WRITE   3448978\n0x40125700 WRITE   3449064\n0x40125740 WRITE   3449120\n0x40125780 WRITE   3449191\n0x401257C0 WRITE   3449247\n0x4018BE00 WRITE   3449330\n0x4018BDC0 WRITE   3449332\n0x4018BD00 WRITE   3449339\n0x4018BCC0 WRITE   3449341\n0x4018BC80 WRITE   3449351\n0x4018BC40 WRITE   3449353\n0x40125800 WRITE   3449380\n0x40125840 WRITE   3449436\n0x40125880 WRITE   3449502\n0x401258C0 WRITE   3449558\n0x40125900 WRITE   3449645\n0x40125940 WRITE   3449701\n0x40125980 WRITE   3449764\n0x401259C0 WRITE   3449820\n0x4018BD80 WRITE   3449889\n0x4018BD40 WRITE   3449891\n0x40125A00 WRITE   3449927\n0x40125A40 WRITE   3449983\n0x40125A80 WRITE   3450046\n0x40125AC0 WRITE   3450102\n0x40125B00 WRITE   3450184\n0x40125B40 WRITE   3450240\n0x40125B80 WRITE   3450303\n0x40125BC0 WRITE   3450359\n0x4018BF00 WRITE   3450438\n0x4018BEC0 WRITE   3450440\n0x4018BE80 WRITE   3450447\n0x4018BE40 WRITE   3450449\n0x40125C00 WRITE   3450482\n0x40125C40 WRITE   3450538\n0x40125C80 WRITE   3450612\n0x40125CC0 WRITE   3450668\n0x40125D00 WRITE   3450763\n0x40125D40 WRITE   3450819\n0x40125D80 WRITE   3450890\n0x40125DC0 WRITE   3450946\n0x4018BF80 WRITE   3451023\n0x4018BF40 WRITE   3451025\n0x40125E00 WRITE   3451061\n0x40125E40 WRITE   3451117\n0x40125E80 WRITE   3451188\n0x40125EC0 WRITE   3451244\n0x40125F00 WRITE   3451334\n0x40125F40 WRITE   3451390\n0x40125F80 WRITE   3451461\n0x40125FC0 WRITE   3451517\n0x4018DFC0 WRITE   3451679\n0x4018E000 WRITE   3451711\n0x4018D000 WRITE   3451838\n0x4018CFC0 WRITE   3451840\n0x4018C800 WRITE   3451847\n0x4018C7C0 WRITE   3451849\n0x4018C400 WRITE   3451859\n0x4018C3C0 WRITE   3451861\n0x4018C200 WRITE   3451866\n0x4018C1C0 WRITE   3451869\n0x4018C100 WRITE   3451872\n0x4018C0C0 WRITE   3451875\n0x4018C080 WRITE   3451878\n0x4018C040 WRITE   3451881\n0x40126000 WRITE   3451913\n0x40126040 WRITE   3452001\n0x40126080 WRITE   3452067\n0x401260C0 WRITE   3452123\n0x40126100 WRITE   3452206\n0x40126140 WRITE   3452262\n0x40126180 WRITE   3452325\n0x401261C0 WRITE   3452381\n0x4018C180 WRITE   3452437\n0x4018C140 WRITE   3452439\n0x40126200 WRITE   3452475\n0x40126240 WRITE   3452531\n0x40126280 WRITE   3452594\n0x401262C0 WRITE   3452650\n0x40126300 WRITE   3452728\n0x40126340 WRITE   3452784\n0x40126380 WRITE   3452847\n0x401263C0 WRITE   3452903\n0x4018C300 WRITE   3452964\n0x4018C2C0 WRITE   3452966\n0x4018C280 WRITE   3452973\n0x4018C240 WRITE   3452975\n0x40126400 WRITE   3453008\n0x40126440 WRITE   3453064\n0x40126480 WRITE   3453138\n0x401264C0 WRITE   3453194\n0x40126500 WRITE   3453285\n0x40126540 WRITE   3453341\n0x40126580 WRITE   3453412\n0x401265C0 WRITE   3453468\n0x4018C380 WRITE   3453532\n0x4018C340 WRITE   3453534\n0x40126600 WRITE   3453570\n0x40126640 WRITE   3453626\n0x40126680 WRITE   3453697\n0x401266C0 WRITE   3453753\n0x40126700 WRITE   3453839\n0x40126740 WRITE   3453895\n0x40126780 WRITE   3453966\n0x401267C0 WRITE   3454022\n0x4018C600 WRITE   3454091\n0x4018C5C0 WRITE   3454093\n0x4018C500 WRITE   3454100\n0x4018C4C0 WRITE   3454102\n0x4018C480 WRITE   3454112\n0x4018C440 WRITE   3454114\n0x40126800 WRITE   3454141\n0x40126840 WRITE   3454197\n0x40126880 WRITE   3454263\n0x401268C0 WRITE   3454319\n0x40126900 WRITE   3454406\n0x40126940 WRITE   3454462\n0x40126980 WRITE   3454525\n0x401269C0 WRITE   3454581\n0x4018C580 WRITE   3454643\n0x4018C540 WRITE   3454645\n0x40126A00 WRITE   3454681\n0x40126A40 WRITE   3454737\n0x40126A80 WRITE   3454800\n0x40126AC0 WRITE   3454856\n0x40126B00 WRITE   3454938\n0x40126B40 WRITE   3454994\n0x40126B80 WRITE   3455057\n0x40126BC0 WRITE   3455113\n0x4018C700 WRITE   3455179\n0x4018C6C0 WRITE   3455181\n0x4018C680 WRITE   3455188\n0x4018C640 WRITE   3455190\n0x40126C00 WRITE   3455223\n0x40126C40 WRITE   3455279\n0x40126C80 WRITE   3455353\n0x40126CC0 WRITE   3455409\n0x40126D00 WRITE   3455504\n0x40126D40 WRITE   3455560\n0x40126D80 WRITE   3455631\n0x40126DC0 WRITE   3455687\n0x4018C780 WRITE   3455757\n0x4018C740 WRITE   3455759\n0x40126E00 WRITE   3455795\n0x40126E40 WRITE   3455851\n0x40126E80 WRITE   3455922\n0x40126EC0 WRITE   3455978\n0x40126F00 WRITE   3456068\n0x40126F40 WRITE   3456124\n0x40126F80 WRITE   3456195\n0x40126FC0 WRITE   3456251\n0x4018CC00 WRITE   3456331\n0x4018CBC0 WRITE   3456333\n0x4018CA00 WRITE   3456340\n0x4018C9C0 WRITE   3456342\n0x4018C900 WRITE   3456352\n0x4018C8C0 WRITE   3456354\n0x4018C880 WRITE   3456359\n0x4018C840 WRITE   3456362\n0x40127000 WRITE   3456387\n0x40127040 WRITE   3456471\n0x40127080 WRITE   3456537\n0x401270C0 WRITE   3456593\n0x40127100 WRITE   3456676\n0x40127140 WRITE   3456732\n0x40127180 WRITE   3456795\n0x401271C0 WRITE   3456851\n0x4018C980 WRITE   3456915\n0x4018C940 WRITE   3456917\n0x40127200 WRITE   3456953\n0x40127240 WRITE   3457009\n0x40127280 WRITE   3457072\n0x401272C0 WRITE   3457128\n0x40127300 WRITE   3457206\n0x40127340 WRITE   3457262\n0x40127380 WRITE   3457325\n0x401273C0 WRITE   3457381\n0x4018CB00 WRITE   3457449\n0x4018CAC0 WRITE   3457451\n0x4018CA80 WRITE   3457458\n0x4018CA40 WRITE   3457460\n0x40127400 WRITE   3457493\n0x40127440 WRITE   3457549\n0x40127480 WRITE   3457623\n0x401274C0 WRITE   3457679\n0x40127500 WRITE   3457770\n0x40127540 WRITE   3457826\n0x40127580 WRITE   3457897\n0x401275C0 WRITE   3457953\n0x4018CB80 WRITE   3458025\n0x4018CB40 WRITE   3458027\n0x40127600 WRITE   3458063\n0x40127640 WRITE   3458119\n0x40127680 WRITE   3458190\n0x401276C0 WRITE   3458246\n0x40127700 WRITE   3458332\n0x40127740 WRITE   3458388\n0x40127780 WRITE   3458459\n0x401277C0 WRITE   3458515\n0x4018CE00 WRITE   3458592\n0x4018CDC0 WRITE   3458594\n0x4018CD00 WRITE   3458601\n0x4018CCC0 WRITE   3458603\n0x4018CC80 WRITE   3458613\n0x4018CC40 WRITE   3458615\n0x40127800 WRITE   3458642\n0x40127840 WRITE   3458698\n0x40127880 WRITE   3458764\n0x401278C0 WRITE   3458820\n0x40127900 WRITE   3458907\n0x40127940 WRITE   3458963\n0x40127980 WRITE   3459026\n0x401279C0 WRITE   3459082\n0x4018CD80 WRITE   3459151\n0x4018CD40 WRITE   3459153\n0x40127A00 WRITE   3459189\n0x40127A40 WRITE   3459245\n0x40127A80 WRITE   3459308\n0x40127AC0 WRITE   3459364\n0x40127B00 WRITE   3459446\n0x40127B40 WRITE   3459502\n0x40127B80 WRITE   3459565\n0x40127BC0 WRITE   3459621\n0x4018CF00 WRITE   3459694\n0x4018CEC0 WRITE   3459696\n0x4018CE80 WRITE   3459703\n0x4018CE40 WRITE   3459705\n0x40127C00 WRITE   3459738\n0x40127C40 WRITE   3459794\n0x40127C80 WRITE   3459868\n0x40127CC0 WRITE   3459924\n0x40127D00 WRITE   3460019\n0x40127D40 WRITE   3460075\n0x40127D80 WRITE   3460146\n0x40127DC0 WRITE   3460202\n0x4018CF80 WRITE   3460279\n0x4018CF40 WRITE   3460281\n0x40127E00 WRITE   3460317\n0x40127E40 WRITE   3460373\n0x40127E80 WRITE   3460444\n0x40127EC0 WRITE   3460500\n0x40127F00 WRITE   3460590\n0x40127F40 WRITE   3460646\n0x40127F80 WRITE   3460717\n0x40127FC0 WRITE   3460773\n0x4018D800 WRITE   3460859\n0x4018D7C0 WRITE   3460861\n0x4018D400 WRITE   3460868\n0x4018D3C0 WRITE   3460870\n0x4018D200 WRITE   3460880\n0x4018D1C0 WRITE   3460882\n0x4018D100 WRITE   3460887\n0x4018D0C0 WRITE   3460890\n0x4018D080 WRITE   3460893\n0x4018D040 WRITE   3460896\n0x40128000 WRITE   3460921\n0x40128040 WRITE   3461005\n0x40128080 WRITE   3461071\n0x401280C0 WRITE   3461127\n0x40128100 WRITE   3461210\n0x40128140 WRITE   3461266\n0x40128180 WRITE   3461329\n0x401281C0 WRITE   3461385\n0x4018D180 WRITE   3461441\n0x4018D140 WRITE   3461443\n0x40128200 WRITE   3461479\n0x40128240 WRITE   3461535\n0x40128280 WRITE   3461598\n0x401282C0 WRITE   3461654\n0x40128300 WRITE   3461732\n0x40128340 WRITE   3461788\n0x40128380 WRITE   3461851\n0x401283C0 WRITE   3461907\n0x4018D300 WRITE   3461973\n0x4018D2C0 WRITE   3461975\n0x4018D280 WRITE   3461982\n0x4018D240 WRITE   3461984\n0x40128400 WRITE   3462017\n0x40128440 WRITE   3462073\n0x40128480 WRITE   3462147\n0x401284C0 WRITE   3462203\n0x40128500 WRITE   3462294\n0x40128540 WRITE   3462350\n0x40128580 WRITE   3462421\n0x401285C0 WRITE   3462477\n0x4018D380 WRITE   3462541\n0x4018D340 WRITE   3462543\n0x40128600 WRITE   3462579\n0x40128640 WRITE   3462635\n0x40128680 WRITE   3462706\n0x401286C0 WRITE   3462762\n0x40128700 WRITE   3462848\n0x40128740 WRITE   3462904\n0x40128780 WRITE   3462975\n0x401287C0 WRITE   3463031\n0x4018D600 WRITE   3463106\n0x4018D5C0 WRITE   3463108\n0x4018D500 WRITE   3463115\n0x4018D4C0 WRITE   3463117\n0x4018D480 WRITE   3463127\n0x4018D440 WRITE   3463129\n0x40128800 WRITE   3463156\n0x40128840 WRITE   3463212\n0x40128880 WRITE   3463278\n0x401288C0 WRITE   3463334\n0x40128900 WRITE   3463421\n0x40128940 WRITE   3463477\n0x40128980 WRITE   3463540\n0x401289C0 WRITE   3463596\n0x4018D580 WRITE   3463658\n0x4018D540 WRITE   3463660\n0x40128A00 WRITE   3463696\n0x40128A40 WRITE   3463752\n0x40128A80 WRITE   3463815\n0x40128AC0 WRITE   3463871\n0x40128B00 WRITE   3463953\n0x40128B40 WRITE   3464009\n0x40128B80 WRITE   3464072\n0x40128BC0 WRITE   3464128\n0x4018D700 WRITE   3464200\n0x4018D6C0 WRITE   3464202\n0x4018D680 WRITE   3464209\n0x4018D640 WRITE   3464211\n0x40128C00 WRITE   3464244\n0x40128C40 WRITE   3464300\n0x40128C80 WRITE   3464374\n0x40128CC0 WRITE   3464430\n0x40128D00 WRITE   3464525\n0x40128D40 WRITE   3464581\n0x40128D80 WRITE   3464652\n0x40128DC0 WRITE   3464708\n0x4018D780 WRITE   3464778\n0x4018D740 WRITE   3464780\n0x40128E00 WRITE   3464816\n0x40128E40 WRITE   3464872\n0x40128E80 WRITE   3464943\n0x40128EC0 WRITE   3464999\n0x40128F00 WRITE   3465089\n0x40128F40 WRITE   3465145\n0x40128F80 WRITE   3465216\n0x40128FC0 WRITE   3465272\n0x4018DC00 WRITE   3465358\n0x4018DBC0 WRITE   3465360\n0x4018DA00 WRITE   3465367\n0x4018D9C0 WRITE   3465369\n0x4018D900 WRITE   3465379\n0x4018D8C0 WRITE   3465381\n0x4018D880 WRITE   3465386\n0x4018D840 WRITE   3465389\n0x40129000 WRITE   3465414\n0x40129040 WRITE   3465498\n0x40129080 WRITE   3465564\n0x401290C0 WRITE   3465620\n0x40129100 WRITE   3465703\n0x40129140 WRITE   3465759\n0x40129180 WRITE   3465822\n0x401291C0 WRITE   3465878\n0x4018D980 WRITE   3465942\n0x4018D940 WRITE   3465944\n0x40129200 WRITE   3465980\n0x40129240 WRITE   3466036\n0x40129280 WRITE   3466099\n0x401292C0 WRITE   3466155\n0x40129300 WRITE   3466233\n0x40129340 WRITE   3466289\n0x40129380 WRITE   3466352\n0x401293C0 WRITE   3466408\n0x4018DB00 WRITE   3466482\n0x4018DAC0 WRITE   3466484\n0x4018DA80 WRITE   3466491\n0x4018DA40 WRITE   3466493\n0x40129400 WRITE   3466526\n0x40129440 WRITE   3466582\n0x40129480 WRITE   3466656\n0x401294C0 WRITE   3466712\n0x40129500 WRITE   3466803\n0x40129540 WRITE   3466859\n0x40129580 WRITE   3466930\n0x401295C0 WRITE   3466986\n0x4018DB80 WRITE   3467058\n0x4018DB40 WRITE   3467060\n0x40129600 WRITE   3467096\n0x40129640 WRITE   3467152\n0x40129680 WRITE   3467223\n0x401296C0 WRITE   3467279\n0x40129700 WRITE   3467365\n0x40129740 WRITE   3467421\n0x40129780 WRITE   3467492\n0x401297C0 WRITE   3467548\n0x4018DE00 WRITE   3467631\n0x4018DDC0 WRITE   3467633\n0x4018DD00 WRITE   3467640\n0x4018DCC0 WRITE   3467642\n0x4018DC80 WRITE   3467652\n0x4018DC40 WRITE   3467654\n0x40129800 WRITE   3467681\n0x40129840 WRITE   3467737\n0x40129880 WRITE   3467803\n0x401298C0 WRITE   3467859\n0x40129900 WRITE   3467946\n0x40129940 WRITE   3468002\n0x40129980 WRITE   3468065\n0x401299C0 WRITE   3468121\n0x4018DD80 WRITE   3468190\n0x4018DD40 WRITE   3468192\n0x40129A00 WRITE   3468228\n0x40129A40 WRITE   3468284\n0x40129A80 WRITE   3468347\n0x40129AC0 WRITE   3468403\n0x40129B00 WRITE   3468485\n0x40129B40 WRITE   3468541\n0x40129B80 WRITE   3468604\n0x40129BC0 WRITE   3468660\n0x4018DF00 WRITE   3468739\n0x4018DEC0 WRITE   3468741\n0x4018DE80 WRITE   3468748\n0x4018DE40 WRITE   3468750\n0x40129C00 WRITE   3468783\n0x40129C40 WRITE   3468839\n0x40129C80 WRITE   3468913\n0x40129CC0 WRITE   3468969\n0x40129D00 WRITE   3469064\n0x40129D40 WRITE   3469120\n0x40129D80 WRITE   3469191\n0x40129DC0 WRITE   3469247\n0x4018DF80 WRITE   3469324\n0x4018DF40 WRITE   3469326\n0x40129E00 WRITE   3469362\n0x40129E40 WRITE   3469418\n0x40129E80 WRITE   3469489\n0x40129EC0 WRITE   3469545\n0x40129F00 WRITE   3469635\n0x40129F40 WRITE   3469691\n0x40129F80 WRITE   3469762\n0x40129FC0 WRITE   3469818\n0x4018FFC0 WRITE   3469980\n0x40190000 WRITE   3470012\n0x4018F000 WRITE   3470155\n0x4018EFC0 WRITE   3470157\n0x4018E800 WRITE   3470164\n0x4018E7C0 WRITE   3470166\n0x4018E400 WRITE   3470176\n0x4018E3C0 WRITE   3470178\n0x4018E200 WRITE   3470183\n0x4018E1C0 WRITE   3470186\n0x4018E100 WRITE   3470189\n0x4018E0C0 WRITE   3470192\n0x4018E080 WRITE   3470195\n0x4018E040 WRITE   3470198\n0x4012A000 WRITE   3470230\n0x4012A040 WRITE   3470318\n0x4012A080 WRITE   3470384\n0x4012A0C0 WRITE   3470440\n0x4012A100 WRITE   3470523\n0x4012A140 WRITE   3470579\n0x4012A180 WRITE   3470642\n0x4012A1C0 WRITE   3470698\n0x4018E180 WRITE   3470754\n0x4018E140 WRITE   3470756\n0x4012A200 WRITE   3470792\n0x4012A240 WRITE   3470848\n0x4012A280 WRITE   3470911\n0x4012A2C0 WRITE   3470967\n0x4012A300 WRITE   3471045\n0x4012A340 WRITE   3471101\n0x4012A380 WRITE   3471164\n0x4012A3C0 WRITE   3471220\n0x4018E300 WRITE   3471281\n0x4018E2C0 WRITE   3471283\n0x4018E280 WRITE   3471290\n0x4018E240 WRITE   3471292\n0x4012A400 WRITE   3471325\n0x4012A440 WRITE   3471381\n0x4012A480 WRITE   3471455\n0x4012A4C0 WRITE   3471511\n0x4012A500 WRITE   3471602\n0x4012A540 WRITE   3471658\n0x4012A580 WRITE   3471729\n0x4012A5C0 WRITE   3471785\n0x4018E380 WRITE   3471849\n0x4018E340 WRITE   3471851\n0x4012A600 WRITE   3471887\n0x4012A640 WRITE   3471943\n0x4012A680 WRITE   3472014\n0x4012A6C0 WRITE   3472070\n0x4012A700 WRITE   3472156\n0x4012A740 WRITE   3472212\n0x4012A780 WRITE   3472283\n0x4012A7C0 WRITE   3472339\n0x4018E600 WRITE   3472408\n0x4018E5C0 WRITE   3472410\n0x4018E500 WRITE   3472417\n0x4018E4C0 WRITE   3472419\n0x4018E480 WRITE   3472429\n0x4018E440 WRITE   3472431\n0x4012A800 WRITE   3472458\n0x4012A840 WRITE   3472514\n0x4012A880 WRITE   3472580\n0x4012A8C0 WRITE   3472636\n0x4012A900 WRITE   3472723\n0x4012A940 WRITE   3472779\n0x4012A980 WRITE   3472842\n0x4012A9C0 WRITE   3472898\n0x4018E580 WRITE   3472960\n0x4018E540 WRITE   3472962\n0x4012AA00 WRITE   3472998\n0x4012AA40 WRITE   3473054\n0x4012AA80 WRITE   3473117\n0x4012AAC0 WRITE   3473173\n0x4012AB00 WRITE   3473255\n0x4012AB40 WRITE   3473311\n0x4012AB80 WRITE   3473374\n0x4012ABC0 WRITE   3473430\n0x4018E700 WRITE   3473496\n0x4018E6C0 WRITE   3473498\n0x4018E680 WRITE   3473505\n0x4018E640 WRITE   3473507\n0x4012AC00 WRITE   3473540\n0x4012AC40 WRITE   3473596\n0x4012AC80 WRITE   3473670\n0x4012ACC0 WRITE   3473726\n0x4012AD00 WRITE   3473821\n0x4012AD40 WRITE   3473877\n0x4012AD80 WRITE   3473948\n0x4012ADC0 WRITE   3474004\n0x4018E780 WRITE   3474074\n0x4018E740 WRITE   3474076\n0x4012AE00 WRITE   3474112\n0x4012AE40 WRITE   3474168\n0x4012AE80 WRITE   3474239\n0x4012AEC0 WRITE   3474295\n0x4012AF00 WRITE   3474385\n0x4012AF40 WRITE   3474441\n0x4012AF80 WRITE   3474512\n0x4012AFC0 WRITE   3474568\n0x4018EC00 WRITE   3474648\n0x4018EBC0 WRITE   3474650\n0x4018EA00 WRITE   3474657\n0x4018E9C0 WRITE   3474659\n0x4018E900 WRITE   3474669\n0x4018E8C0 WRITE   3474671\n0x4018E880 WRITE   3474676\n0x4018E840 WRITE   3474679\n0x4012B000 WRITE   3474704\n0x4012B040 WRITE   3474788\n0x4012B080 WRITE   3474854\n0x4012B0C0 WRITE   3474910\n0x4012B100 WRITE   3474993\n0x4012B140 WRITE   3475049\n0x4012B180 WRITE   3475112\n0x4012B1C0 WRITE   3475168\n0x4018E980 WRITE   3475232\n0x4018E940 WRITE   3475234\n0x4012B200 WRITE   3475270\n0x4012B240 WRITE   3475326\n0x4012B280 WRITE   3475389\n0x4012B2C0 WRITE   3475445\n0x4012B300 WRITE   3475523\n0x4012B340 WRITE   3475579\n0x4012B380 WRITE   3475642\n0x4012B3C0 WRITE   3475698\n0x4018EB00 WRITE   3475766\n0x4018EAC0 WRITE   3475768\n0x4018EA80 WRITE   3475775\n0x4018EA40 WRITE   3475777\n0x4012B400 WRITE   3475810\n0x4012B440 WRITE   3475866\n0x4012B480 WRITE   3475940\n0x4012B4C0 WRITE   3475996\n0x4012B500 WRITE   3476087\n0x4012B540 WRITE   3476143\n0x4012B580 WRITE   3476214\n0x4012B5C0 WRITE   3476270\n0x4018EB80 WRITE   3476342\n0x4018EB40 WRITE   3476344\n0x4012B600 WRITE   3476380\n0x4012B640 WRITE   3476436\n0x4012B680 WRITE   3476507\n0x4012B6C0 WRITE   3476563\n0x4012B700 WRITE   3476649\n0x4012B740 WRITE   3476705\n0x4012B780 WRITE   3476776\n0x4012B7C0 WRITE   3476832\n0x4018EE00 WRITE   3476909\n0x4018EDC0 WRITE   3476911\n0x4018ED00 WRITE   3476918\n0x4018ECC0 WRITE   3476920\n0x4018EC80 WRITE   3476930\n0x4018EC40 WRITE   3476932\n0x4012B800 WRITE   3476959\n0x4012B840 WRITE   3477015\n0x4012B880 WRITE   3477081\n0x4012B8C0 WRITE   3477137\n0x4012B900 WRITE   3477224\n0x4012B940 WRITE   3477280\n0x4012B980 WRITE   3477343\n0x4012B9C0 WRITE   3477399\n0x4018ED80 WRITE   3477468\n0x4018ED40 WRITE   3477470\n0x4012BA00 WRITE   3477506\n0x4012BA40 WRITE   3477562\n0x4012BA80 WRITE   3477625\n0x4012BAC0 WRITE   3477681\n0x4012BB00 WRITE   3477763\n0x4012BB40 WRITE   3477819\n0x4012BB80 WRITE   3477882\n0x4012BBC0 WRITE   3477938\n0x4018EF00 WRITE   3478011\n0x4018EEC0 WRITE   3478013\n0x4018EE80 WRITE   3478020\n0x4018EE40 WRITE   3478022\n0x4012BC00 WRITE   3478055\n0x4012BC40 WRITE   3478111\n0x4012BC80 WRITE   3478185\n0x4012BCC0 WRITE   3478241\n0x4012BD00 WRITE   3478336\n0x4012BD40 WRITE   3478392\n0x4012BD80 WRITE   3478463\n0x4012BDC0 WRITE   3478519\n0x4018EF80 WRITE   3478596\n0x4018EF40 WRITE   3478598\n0x4012BE00 WRITE   3478634\n0x4012BE40 WRITE   3478690\n0x4012BE80 WRITE   3478761\n0x4012BEC0 WRITE   3478817\n0x4012BF00 WRITE   3478907\n0x4012BF40 WRITE   3478963\n0x4012BF80 WRITE   3479034\n0x4012BFC0 WRITE   3479090\n0x4018F800 WRITE   3479176\n0x4018F7C0 WRITE   3479178\n0x4018F400 WRITE   3479185\n0x4018F3C0 WRITE   3479187\n0x4018F200 WRITE   3479197\n0x4018F1C0 WRITE   3479199\n0x4018F100 WRITE   3479204\n0x4018F0C0 WRITE   3479207\n0x4018F080 WRITE   3479210\n0x4018F040 WRITE   3479213\n0x4012C000 WRITE   3479238\n0x4012C040 WRITE   3479322\n0x4012C080 WRITE   3479388\n0x4012C0C0 WRITE   3479444\n0x4012C100 WRITE   3479527\n0x4012C140 WRITE   3479583\n0x4012C180 WRITE   3479646\n0x4012C1C0 WRITE   3479702\n0x4018F180 WRITE   3479758\n0x4018F140 WRITE   3479760\n0x4012C200 WRITE   3479796\n0x4012C240 WRITE   3479852\n0x4012C280 WRITE   3479915\n0x4012C2C0 WRITE   3479971\n0x4012C300 WRITE   3480049\n0x4012C340 WRITE   3480105\n0x4012C380 WRITE   3480168\n0x4012C3C0 WRITE   3480224\n0x4018F300 WRITE   3480290\n0x4018F2C0 WRITE   3480292\n0x4018F280 WRITE   3480299\n0x4018F240 WRITE   3480301\n0x4012C400 WRITE   3480334\n0x4012C440 WRITE   3480390\n0x4012C480 WRITE   3480464\n0x4012C4C0 WRITE   3480520\n0x4012C500 WRITE   3480611\n0x4012C540 WRITE   3480667\n0x4012C580 WRITE   3480738\n0x4012C5C0 WRITE   3480794\n0x4018F380 WRITE   3480858\n0x4018F340 WRITE   3480860\n0x4012C600 WRITE   3480896\n0x4012C640 WRITE   3480952\n0x4012C680 WRITE   3481023\n0x4012C6C0 WRITE   3481079\n0x4012C700 WRITE   3481165\n0x4012C740 WRITE   3481221\n0x4012C780 WRITE   3481292\n0x4012C7C0 WRITE   3481348\n0x4018F600 WRITE   3481423\n0x4018F5C0 WRITE   3481425\n0x4018F500 WRITE   3481432\n0x4018F4C0 WRITE   3481434\n0x4018F480 WRITE   3481444\n0x4018F440 WRITE   3481446\n0x4012C800 WRITE   3481473\n0x4012C840 WRITE   3481529\n0x4012C880 WRITE   3481595\n0x4012C8C0 WRITE   3481651\n0x4012C900 WRITE   3481738\n0x4012C940 WRITE   3481794\n0x4012C980 WRITE   3481857\n0x4012C9C0 WRITE   3481913\n0x4018F580 WRITE   3481975\n0x4018F540 WRITE   3481977\n0x4012CA00 WRITE   3482013\n0x4012CA40 WRITE   3482069\n0x4012CA80 WRITE   3482132\n0x4012CAC0 WRITE   3482188\n0x4012CB00 WRITE   3482270\n0x4012CB40 WRITE   3482326\n0x4012CB80 WRITE   3482389\n0x4012CBC0 WRITE   3482445\n0x4018F700 WRITE   3482517\n0x4018F6C0 WRITE   3482519\n0x4018F680 WRITE   3482526\n0x4018F640 WRITE   3482528\n0x4012CC00 WRITE   3482561\n0x4012CC40 WRITE   3482617\n0x4012CC80 WRITE   3482691\n0x4012CCC0 WRITE   3482747\n0x4012CD00 WRITE   3482842\n0x4012CD40 WRITE   3482898\n0x4012CD80 WRITE   3482969\n0x4012CDC0 WRITE   3483025\n0x4018F780 WRITE   3483095\n0x4018F740 WRITE   3483097\n0x4012CE00 WRITE   3483133\n0x4012CE40 WRITE   3483189\n0x4012CE80 WRITE   3483260\n0x4012CEC0 WRITE   3483316\n0x4012CF00 WRITE   3483406\n0x4012CF40 WRITE   3483462\n0x4012CF80 WRITE   3483533\n0x4012CFC0 WRITE   3483589\n0x4018FC00 WRITE   3483675\n0x4018FBC0 WRITE   3483677\n0x4018FA00 WRITE   3483684\n0x4018F9C0 WRITE   3483686\n0x4018F900 WRITE   3483696\n0x4018F8C0 WRITE   3483698\n0x4018F880 WRITE   3483703\n0x4018F840 WRITE   3483706\n0x4012D000 WRITE   3483731\n0x4012D040 WRITE   3483815\n0x4012D080 WRITE   3483881\n0x4012D0C0 WRITE   3483937\n0x4012D100 WRITE   3484020\n0x4012D140 WRITE   3484076\n0x4012D180 WRITE   3484139\n0x4012D1C0 WRITE   3484195\n0x4018F980 WRITE   3484259\n0x4018F940 WRITE   3484261\n0x4012D200 WRITE   3484297\n0x4012D240 WRITE   3484353\n0x4012D280 WRITE   3484416\n0x4012D2C0 WRITE   3484472\n0x4012D300 WRITE   3484550\n0x4012D340 WRITE   3484606\n0x4012D380 WRITE   3484669\n0x4012D3C0 WRITE   3484725\n0x4018FB00 WRITE   3484799\n0x4018FAC0 WRITE   3484801\n0x4018FA80 WRITE   3484808\n0x4018FA40 WRITE   3484810\n0x4012D400 WRITE   3484843\n0x4012D440 WRITE   3484899\n0x4012D480 WRITE   3484973\n0x4012D4C0 WRITE   3485029\n0x4012D500 WRITE   3485120\n0x4012D540 WRITE   3485176\n0x4012D580 WRITE   3485247\n0x4012D5C0 WRITE   3485303\n0x4018FB80 WRITE   3485375\n0x4018FB40 WRITE   3485377\n0x4012D600 WRITE   3485413\n0x4012D640 WRITE   3485469\n0x4012D680 WRITE   3485540\n0x4012D6C0 WRITE   3485596\n0x4012D700 WRITE   3485682\n0x4012D740 WRITE   3485738\n0x4012D780 WRITE   3485809\n0x4012D7C0 WRITE   3485865\n0x4018FE00 WRITE   3485948\n0x4018FDC0 WRITE   3485950\n0x4018FD00 WRITE   3485957\n0x4018FCC0 WRITE   3485959\n0x4018FC80 WRITE   3485969\n0x4018FC40 WRITE   3485971\n0x4012D800 WRITE   3485998\n0x4012D840 WRITE   3486054\n0x4012D880 WRITE   3486120\n0x4012D8C0 WRITE   3486176\n0x4012D900 WRITE   3486263\n0x4012D940 WRITE   3486319\n0x4012D980 WRITE   3486382\n0x4012D9C0 WRITE   3486438\n0x4018FD80 WRITE   3486507\n0x4018FD40 WRITE   3486509\n0x4012DA00 WRITE   3486545\n0x4012DA40 WRITE   3486601\n0x4012DA80 WRITE   3486664\n0x4012DAC0 WRITE   3486720\n0x4012DB00 WRITE   3486802\n0x4012DB40 WRITE   3486858\n0x4012DB80 WRITE   3486921\n0x4012DBC0 WRITE   3486977\n0x4018FF00 WRITE   3487056\n0x4018FEC0 WRITE   3487058\n0x4018FE80 WRITE   3487065\n0x4018FE40 WRITE   3487067\n0x4012DC00 WRITE   3487100\n0x4012DC40 WRITE   3487156\n0x4012DC80 WRITE   3487230\n0x4012DCC0 WRITE   3487286\n0x4012DD00 WRITE   3487381\n0x4012DD40 WRITE   3487437\n0x4012DD80 WRITE   3487508\n0x4012DDC0 WRITE   3487564\n0x4018FF80 WRITE   3487641\n0x4018FF40 WRITE   3487643\n0x4012DE00 WRITE   3487679\n0x4012DE40 WRITE   3487735\n0x4012DE80 WRITE   3487806\n0x4012DEC0 WRITE   3487862\n0x4012DF00 WRITE   3487952\n0x4012DF40 WRITE   3488008\n0x4012DF80 WRITE   3488079\n0x4012DFC0 WRITE   3488135\n0x40191FC0 WRITE   3488297\n0x40192000 WRITE   3488329\n0x40191000 WRITE   3488456\n0x40190FC0 WRITE   3488458\n0x40190800 WRITE   3488465\n0x401907C0 WRITE   3488467\n0x40190400 WRITE   3488477\n0x401903C0 WRITE   3488479\n0x40190200 WRITE   3488484\n0x401901C0 WRITE   3488487\n0x40190100 WRITE   3488490\n0x401900C0 WRITE   3488493\n0x40190080 WRITE   3488496\n0x40190040 WRITE   3488499\n0x4012E000 WRITE   3488531\n0x4012E040 WRITE   3488619\n0x4012E080 WRITE   3488685\n0x4012E0C0 WRITE   3488741\n0x4012E100 WRITE   3488824\n0x4012E140 WRITE   3488880\n0x4012E180 WRITE   3488943\n0x4012E1C0 WRITE   3488999\n0x40190180 WRITE   3489055\n0x40190140 WRITE   3489057\n0x4012E200 WRITE   3489093\n0x4012E240 WRITE   3489149\n0x4012E280 WRITE   3489212\n0x4012E2C0 WRITE   3489268\n0x4012E300 WRITE   3489346\n0x4012E340 WRITE   3489402\n0x4012E380 WRITE   3489465\n0x4012E3C0 WRITE   3489521\n0x40190300 WRITE   3489582\n0x401902C0 WRITE   3489584\n0x40190280 WRITE   3489591\n0x40190240 WRITE   3489593\n0x4012E400 WRITE   3489626\n0x4012E440 WRITE   3489682\n0x4012E480 WRITE   3489756\n0x4012E4C0 WRITE   3489812\n0x4012E500 WRITE   3489903\n0x4012E540 WRITE   3489959\n0x4012E580 WRITE   3490030\n0x4012E5C0 WRITE   3490086\n0x40190380 WRITE   3490150\n0x40190340 WRITE   3490152\n0x4012E600 WRITE   3490188\n0x4012E640 WRITE   3490244\n0x4012E680 WRITE   3490315\n0x4012E6C0 WRITE   3490371\n0x4012E700 WRITE   3490457\n0x4012E740 WRITE   3490513\n0x4012E780 WRITE   3490584\n0x4012E7C0 WRITE   3490640\n0x40190600 WRITE   3490709\n0x401905C0 WRITE   3490711\n0x40190500 WRITE   3490718\n0x401904C0 WRITE   3490720\n0x40190480 WRITE   3490730\n0x40190440 WRITE   3490732\n0x4012E800 WRITE   3490759\n0x4012E840 WRITE   3490815\n0x4012E880 WRITE   3490881\n0x4012E8C0 WRITE   3490937\n0x4012E900 WRITE   3491024\n0x4012E940 WRITE   3491080\n0x4012E980 WRITE   3491143\n0x4012E9C0 WRITE   3491199\n0x40190580 WRITE   3491261\n0x40190540 WRITE   3491263\n0x4012EA00 WRITE   3491299\n0x4012EA40 WRITE   3491355\n0x4012EA80 WRITE   3491418\n0x4012EAC0 WRITE   3491474\n0x4012EB00 WRITE   3491556\n0x4012EB40 WRITE   3491612\n0x4012EB80 WRITE   3491675\n0x4012EBC0 WRITE   3491731\n0x40190700 WRITE   3491797\n0x401906C0 WRITE   3491799\n0x40190680 WRITE   3491806\n0x40190640 WRITE   3491808\n0x4012EC00 WRITE   3491841\n0x4012EC40 WRITE   3491897\n0x4012EC80 WRITE   3491971\n0x4012ECC0 WRITE   3492027\n0x4012ED00 WRITE   3492122\n0x4012ED40 WRITE   3492178\n0x4012ED80 WRITE   3492249\n0x4012EDC0 WRITE   3492305\n0x40190780 WRITE   3492375\n0x40190740 WRITE   3492377\n0x4012EE00 WRITE   3492413\n0x4012EE40 WRITE   3492469\n0x4012EE80 WRITE   3492540\n0x4012EEC0 WRITE   3492596\n0x4012EF00 WRITE   3492686\n0x4012EF40 WRITE   3492742\n0x4012EF80 WRITE   3492813\n0x4012EFC0 WRITE   3492869\n0x40190C00 WRITE   3492949\n0x40190BC0 WRITE   3492951\n0x40190A00 WRITE   3492958\n0x401909C0 WRITE   3492960\n0x40190900 WRITE   3492970\n0x401908C0 WRITE   3492972\n0x40190880 WRITE   3492977\n0x40190840 WRITE   3492980\n0x4012F000 WRITE   3493005\n0x4012F040 WRITE   3493089\n0x4012F080 WRITE   3493155\n0x4012F0C0 WRITE   3493211\n0x4012F100 WRITE   3493294\n0x4012F140 WRITE   3493350\n0x4012F180 WRITE   3493413\n0x4012F1C0 WRITE   3493469\n0x40190980 WRITE   3493533\n0x40190940 WRITE   3493535\n0x4012F200 WRITE   3493571\n0x4012F240 WRITE   3493627\n0x4012F280 WRITE   3493690\n0x4012F2C0 WRITE   3493746\n0x4012F300 WRITE   3493824\n0x4012F340 WRITE   3493880\n0x4012F380 WRITE   3493943\n0x4012F3C0 WRITE   3493999\n0x40190B00 WRITE   3494067\n0x40190AC0 WRITE   3494069\n0x40190A80 WRITE   3494076\n0x40190A40 WRITE   3494078\n0x4012F400 WRITE   3494111\n0x4012F440 WRITE   3494167\n0x4012F480 WRITE   3494241\n0x4012F4C0 WRITE   3494297\n0x4012F500 WRITE   3494388\n0x4012F540 WRITE   3494444\n0x4012F580 WRITE   3494515\n0x4012F5C0 WRITE   3494571\n0x40190B80 WRITE   3494643\n0x40190B40 WRITE   3494645\n0x4012F600 WRITE   3494681\n0x4012F640 WRITE   3494737\n0x4012F680 WRITE   3494808\n0x4012F6C0 WRITE   3494864\n0x4012F700 WRITE   3494950\n0x4012F740 WRITE   3495006\n0x4012F780 WRITE   3495077\n0x4012F7C0 WRITE   3495133\n0x40190E00 WRITE   3495210\n0x40190DC0 WRITE   3495212\n0x40190D00 WRITE   3495219\n0x40190CC0 WRITE   3495221\n0x40190C80 WRITE   3495231\n0x40190C40 WRITE   3495233\n0x4012F800 WRITE   3495260\n0x4012F840 WRITE   3495316\n0x4012F880 WRITE   3495382\n0x4012F8C0 WRITE   3495438\n0x4012F900 WRITE   3495525\n0x4012F940 WRITE   3495581\n0x4012F980 WRITE   3495644\n0x4012F9C0 WRITE   3495700\n0x40190D80 WRITE   3495769\n0x40190D40 WRITE   3495771\n0x4012FA00 WRITE   3495807\n0x4012FA40 WRITE   3495863\n0x4012FA80 WRITE   3495926\n0x4012FAC0 WRITE   3495982\n0x4012FB00 WRITE   3496064\n0x4012FB40 WRITE   3496120\n0x4012FB80 WRITE   3496183\n0x4012FBC0 WRITE   3496239\n0x40190F00 WRITE   3496312\n0x40190EC0 WRITE   3496314\n0x40190E80 WRITE   3496321\n0x40190E40 WRITE   3496323\n0x4012FC00 WRITE   3496356\n0x4012FC40 WRITE   3496412\n0x4012FC80 WRITE   3496486\n0x4012FCC0 WRITE   3496542\n0x4012FD00 WRITE   3496637\n0x4012FD40 WRITE   3496693\n0x4012FD80 WRITE   3496764\n0x4012FDC0 WRITE   3496820\n0x40190F80 WRITE   3496897\n0x40190F40 WRITE   3496899\n0x4012FE00 WRITE   3496935\n0x4012FE40 WRITE   3496991\n0x4012FE80 WRITE   3497062\n0x4012FEC0 WRITE   3497118\n0x4012FF00 WRITE   3497208\n0x4012FF40 WRITE   3497264\n0x4012FF80 WRITE   3497335\n0x4012FFC0 WRITE   3497391\n0x40191800 WRITE   3497477\n0x401917C0 WRITE   3497479\n0x40191400 WRITE   3497486\n0x401913C0 WRITE   3497488\n0x40191200 WRITE   3497498\n0x401911C0 WRITE   3497500\n0x40191100 WRITE   3497505\n0x401910C0 WRITE   3497508\n0x40191080 WRITE   3497511\n0x40191040 WRITE   3497514\n0x40130000 WRITE   3497539\n0x40130040 WRITE   3497623\n0x40130080 WRITE   3497689\n0x401300C0 WRITE   3497745\n0x40130100 WRITE   3497828\n0x40130140 WRITE   3497884\n0x40130180 WRITE   3497947\n0x401301C0 WRITE   3498003\n0x40191180 WRITE   3498059\n0x40191140 WRITE   3498061\n0x40130200 WRITE   3498097\n0x40130240 WRITE   3498153\n0x40130280 WRITE   3498216\n0x401302C0 WRITE   3498272\n0x40130300 WRITE   3498350\n0x40130340 WRITE   3498406\n0x40130380 WRITE   3498469\n0x401303C0 WRITE   3498525\n0x40191300 WRITE   3498591\n0x401912C0 WRITE   3498593\n0x40191280 WRITE   3498600\n0x40191240 WRITE   3498602\n0x40130400 WRITE   3498635\n0x40130440 WRITE   3498691\n0x40130480 WRITE   3498765\n0x401304C0 WRITE   3498821\n0x40130500 WRITE   3498912\n0x40130540 WRITE   3498968\n0x40130580 WRITE   3499039\n0x401305C0 WRITE   3499095\n0x40191380 WRITE   3499159\n0x40191340 WRITE   3499161\n0x40130600 WRITE   3499197\n0x40130640 WRITE   3499253\n0x40130680 WRITE   3499324\n0x401306C0 WRITE   3499380\n0x40130700 WRITE   3499466\n0x40130740 WRITE   3499522\n0x40130780 WRITE   3499593\n0x401307C0 WRITE   3499649\n0x40191600 WRITE   3499724\n0x401915C0 WRITE   3499726\n0x40191500 WRITE   3499733\n0x401914C0 WRITE   3499735\n0x40191480 WRITE   3499745\n0x40191440 WRITE   3499747\n0x40130800 WRITE   3499774\n0x40130840 WRITE   3499830\n0x40130880 WRITE   3499896\n0x401308C0 WRITE   3499952\n0x40130900 WRITE   3500039\n0x40130940 WRITE   3500095\n0x40130980 WRITE   3500158\n0x401309C0 WRITE   3500214\n0x40191580 WRITE   3500276\n0x40191540 WRITE   3500278\n0x40130A00 WRITE   3500314\n0x40130A40 WRITE   3500370\n0x40130A80 WRITE   3500433\n0x40130AC0 WRITE   3500489\n0x40130B00 WRITE   3500571\n0x40130B40 WRITE   3500627\n0x40130B80 WRITE   3500690\n0x40130BC0 WRITE   3500746\n0x40191700 WRITE   3500818\n0x401916C0 WRITE   3500820\n0x40191680 WRITE   3500827\n0x40191640 WRITE   3500829\n0x40130C00 WRITE   3500862\n0x40130C40 WRITE   3500918\n0x40130C80 WRITE   3500992\n0x40130CC0 WRITE   3501048\n0x40130D00 WRITE   3501143\n0x40130D40 WRITE   3501199\n0x40130D80 WRITE   3501270\n0x40130DC0 WRITE   3501326\n0x40191780 WRITE   3501396\n0x40191740 WRITE   3501398\n0x40130E00 WRITE   3501434\n0x40130E40 WRITE   3501490\n0x40130E80 WRITE   3501561\n0x40130EC0 WRITE   3501617\n0x40130F00 WRITE   3501707\n0x40130F40 WRITE   3501763\n0x40130F80 WRITE   3501834\n0x40130FC0 WRITE   3501890\n0x40191C00 WRITE   3501976\n0x40191BC0 WRITE   3501978\n0x40191A00 WRITE   3501985\n0x401919C0 WRITE   3501987\n0x40191900 WRITE   3501997\n0x401918C0 WRITE   3501999\n0x40191880 WRITE   3502004\n0x40191840 WRITE   3502007\n0x40131000 WRITE   3502032\n0x40131040 WRITE   3502116\n0x40131080 WRITE   3502182\n0x401310C0 WRITE   3502238\n0x40131100 WRITE   3502321\n0x40131140 WRITE   3502377\n0x40131180 WRITE   3502440\n0x401311C0 WRITE   3502496\n0x40191980 WRITE   3502560\n0x40191940 WRITE   3502562\n0x40131200 WRITE   3502598\n0x40131240 WRITE   3502654\n0x40131280 WRITE   3502717\n0x401312C0 WRITE   3502773\n0x40131300 WRITE   3502851\n0x40131340 WRITE   3502907\n0x40131380 WRITE   3502970\n0x401313C0 WRITE   3503026\n0x40191B00 WRITE   3503100\n0x40191AC0 WRITE   3503102\n0x40191A80 WRITE   3503109\n0x40191A40 WRITE   3503111\n0x40131400 WRITE   3503144\n0x40131440 WRITE   3503200\n0x40131480 WRITE   3503274\n0x401314C0 WRITE   3503330\n0x40131500 WRITE   3503421\n0x40131540 WRITE   3503477\n0x40131580 WRITE   3503548\n0x401315C0 WRITE   3503604\n0x40191B80 WRITE   3503676\n0x40191B40 WRITE   3503678\n0x40131600 WRITE   3503714\n0x40131640 WRITE   3503770\n0x40131680 WRITE   3503841\n0x401316C0 WRITE   3503897\n0x40131700 WRITE   3503983\n0x40131740 WRITE   3504039\n0x40131780 WRITE   3504110\n0x401317C0 WRITE   3504166\n0x40191E00 WRITE   3504249\n0x40191DC0 WRITE   3504251\n0x40191D00 WRITE   3504258\n0x40191CC0 WRITE   3504260\n0x40191C80 WRITE   3504270\n0x40191C40 WRITE   3504272\n0x40131800 WRITE   3504299\n0x40131840 WRITE   3504355\n0x40131880 WRITE   3504421\n0x401318C0 WRITE   3504477\n0x40131900 WRITE   3504564\n0x40131940 WRITE   3504620\n0x40131980 WRITE   3504683\n0x401319C0 WRITE   3504739\n0x40191D80 WRITE   3504808\n0x40191D40 WRITE   3504810\n0x40131A00 WRITE   3504846\n0x40131A40 WRITE   3504902\n0x40131A80 WRITE   3504965\n0x40131AC0 WRITE   3505021\n0x40131B00 WRITE   3505103\n0x40131B40 WRITE   3505159\n0x40131B80 WRITE   3505222\n0x40131BC0 WRITE   3505278\n0x40191F00 WRITE   3505357\n0x40191EC0 WRITE   3505359\n0x40191E80 WRITE   3505366\n0x40191E40 WRITE   3505368\n0x40131C00 WRITE   3505401\n0x40131C40 WRITE   3505457\n0x40131C80 WRITE   3505531\n0x40131CC0 WRITE   3505587\n0x40131D00 WRITE   3505682\n0x40131D40 WRITE   3505738\n0x40131D80 WRITE   3505809\n0x40131DC0 WRITE   3505865\n0x40191F80 WRITE   3505942\n0x40191F40 WRITE   3505944\n0x40131E00 WRITE   3505980\n0x40131E40 WRITE   3506036\n0x40131E80 WRITE   3506107\n0x40131EC0 WRITE   3506163\n0x40131F00 WRITE   3506253\n0x40131F40 WRITE   3506309\n0x40131F80 WRITE   3506380\n0x40131FC0 WRITE   3506436\n0x40193FC0 WRITE   3506598\n0x40194000 WRITE   3506630\n0x40193000 WRITE   3506757\n0x40192FC0 WRITE   3506759\n0x40192800 WRITE   3506766\n0x401927C0 WRITE   3506768\n0x40192400 WRITE   3506778\n0x401923C0 WRITE   3506780\n0x40192200 WRITE   3506785\n0x401921C0 WRITE   3506788\n0x40192100 WRITE   3506791\n0x401920C0 WRITE   3506794\n0x40192080 WRITE   3506797\n0x40192040 WRITE   3506800\n0x40132000 WRITE   3506832\n0x40132040 WRITE   3506920\n0x40132080 WRITE   3506986\n0x401320C0 WRITE   3507042\n0x40132100 WRITE   3507125\n0x40132140 WRITE   3507181\n0x40132180 WRITE   3507244\n0x401321C0 WRITE   3507300\n0x40192180 WRITE   3507356\n0x40192140 WRITE   3507358\n0x40132200 WRITE   3507394\n0x40132240 WRITE   3507450\n0x40132280 WRITE   3507513\n0x401322C0 WRITE   3507569\n0x40132300 WRITE   3507647\n0x40132340 WRITE   3507703\n0x40132380 WRITE   3507766\n0x401323C0 WRITE   3507822\n0x40192300 WRITE   3507883\n0x401922C0 WRITE   3507885\n0x40192280 WRITE   3507892\n0x40192240 WRITE   3507894\n0x40132400 WRITE   3507927\n0x40132440 WRITE   3507983\n0x40132480 WRITE   3508057\n0x401324C0 WRITE   3508113\n0x40132500 WRITE   3508204\n0x40132540 WRITE   3508260\n0x40132580 WRITE   3508331\n0x401325C0 WRITE   3508387\n0x40192380 WRITE   3508451\n0x40192340 WRITE   3508453\n0x40132600 WRITE   3508489\n0x40132640 WRITE   3508545\n0x40132680 WRITE   3508616\n0x401326C0 WRITE   3508672\n0x40132700 WRITE   3508758\n0x40132740 WRITE   3508814\n0x40132780 WRITE   3508885\n0x401327C0 WRITE   3508941\n0x40192600 WRITE   3509010\n0x401925C0 WRITE   3509012\n0x40192500 WRITE   3509019\n0x401924C0 WRITE   3509021\n0x40192480 WRITE   3509031\n0x40192440 WRITE   3509033\n0x40132800 WRITE   3509060\n0x40132840 WRITE   3509116\n0x40132880 WRITE   3509182\n0x401328C0 WRITE   3509238\n0x40132900 WRITE   3509325\n0x40132940 WRITE   3509381\n0x40132980 WRITE   3509444\n0x401329C0 WRITE   3509500\n0x40192580 WRITE   3509562\n0x40192540 WRITE   3509564\n0x40132A00 WRITE   3509600\n0x40132A40 WRITE   3509656\n0x40132A80 WRITE   3509719\n0x40132AC0 WRITE   3509775\n0x40132B00 WRITE   3509857\n0x40132B40 WRITE   3509913\n0x40132B80 WRITE   3509976\n0x40132BC0 WRITE   3510032\n0x40192700 WRITE   3510098\n0x401926C0 WRITE   3510100\n0x40192680 WRITE   3510107\n0x40192640 WRITE   3510109\n0x40132C00 WRITE   3510142\n0x40132C40 WRITE   3510198\n0x40132C80 WRITE   3510272\n0x40132CC0 WRITE   3510328\n0x40132D00 WRITE   3510423\n0x40132D40 WRITE   3510479\n0x40132D80 WRITE   3510550\n0x40132DC0 WRITE   3510606\n0x40192780 WRITE   3510676\n0x40192740 WRITE   3510678\n0x40132E00 WRITE   3510714\n0x40132E40 WRITE   3510770\n0x40132E80 WRITE   3510841\n0x40132EC0 WRITE   3510897\n0x40132F00 WRITE   3510987\n0x40132F40 WRITE   3511043\n0x40132F80 WRITE   3511114\n0x40132FC0 WRITE   3511170\n0x40192C00 WRITE   3511250\n0x40192BC0 WRITE   3511252\n0x40192A00 WRITE   3511259\n0x401929C0 WRITE   3511261\n0x40192900 WRITE   3511271\n0x401928C0 WRITE   3511273\n0x40192880 WRITE   3511278\n0x40192840 WRITE   3511281\n0x40133000 WRITE   3511306\n0x40133040 WRITE   3511390\n0x40133080 WRITE   3511456\n0x401330C0 WRITE   3511512\n0x40133100 WRITE   3511595\n0x40133140 WRITE   3511651\n0x40133180 WRITE   3511714\n0x401331C0 WRITE   3511770\n0x40192980 WRITE   3511834\n0x40192940 WRITE   3511836\n0x40133200 WRITE   3511872\n0x40133240 WRITE   3511928\n0x40133280 WRITE   3511991\n0x401332C0 WRITE   3512047\n0x40133300 WRITE   3512125\n0x40133340 WRITE   3512181\n0x40133380 WRITE   3512244\n0x401333C0 WRITE   3512300\n0x40192B00 WRITE   3512368\n0x40192AC0 WRITE   3512370\n0x40192A80 WRITE   3512377\n0x40192A40 WRITE   3512379\n0x40133400 WRITE   3512412\n0x40133440 WRITE   3512468\n0x40133480 WRITE   3512542\n0x401334C0 WRITE   3512598\n0x40133500 WRITE   3512689\n0x40133540 WRITE   3512745\n0x40133580 WRITE   3512816\n0x401335C0 WRITE   3512872\n0x40192B80 WRITE   3512944\n0x40192B40 WRITE   3512946\n0x40133600 WRITE   3512982\n0x40133640 WRITE   3513038\n0x40133680 WRITE   3513109\n0x401336C0 WRITE   3513165\n0x40133700 WRITE   3513251\n0x40133740 WRITE   3513307\n0x40133780 WRITE   3513378\n0x401337C0 WRITE   3513434\n0x40192E00 WRITE   3513511\n0x40192DC0 WRITE   3513513\n0x40192D00 WRITE   3513520\n0x40192CC0 WRITE   3513522\n0x40192C80 WRITE   3513532\n0x40192C40 WRITE   3513534\n0x40133800 WRITE   3513561\n0x40133840 WRITE   3513617\n0x40133880 WRITE   3513683\n0x401338C0 WRITE   3513739\n0x40133900 WRITE   3513826\n0x40133940 WRITE   3513882\n0x40133980 WRITE   3513945\n0x401339C0 WRITE   3514001\n0x40192D80 WRITE   3514070\n0x40192D40 WRITE   3514072\n0x40133A00 WRITE   3514108\n0x40133A40 WRITE   3514164\n0x40133A80 WRITE   3514227\n0x40133AC0 WRITE   3514283\n0x40133B00 WRITE   3514365\n0x40133B40 WRITE   3514421\n0x40133B80 WRITE   3514484\n0x40133BC0 WRITE   3514540\n0x40192F00 WRITE   3514613\n0x40192EC0 WRITE   3514615\n0x40192E80 WRITE   3514622\n0x40192E40 WRITE   3514624\n0x40133C00 WRITE   3514657\n0x40133C40 WRITE   3514713\n0x40133C80 WRITE   3514787\n0x40133CC0 WRITE   3514843\n0x40133D00 WRITE   3514938\n0x40133D40 WRITE   3514994\n0x40133D80 WRITE   3515065\n0x40133DC0 WRITE   3515121\n0x40192F80 WRITE   3515198\n0x40192F40 WRITE   3515200\n0x40133E00 WRITE   3515236\n0x40133E40 WRITE   3515292\n0x40133E80 WRITE   3515363\n0x40133EC0 WRITE   3515419\n0x40133F00 WRITE   3515509\n0x40133F40 WRITE   3515565\n0x40133F80 WRITE   3515636\n0x40133FC0 WRITE   3515692\n0x40193800 WRITE   3515778\n0x401937C0 WRITE   3515780\n0x40193400 WRITE   3515787\n0x401933C0 WRITE   3515789\n0x40193200 WRITE   3515799\n0x401931C0 WRITE   3515801\n0x40193100 WRITE   3515806\n0x401930C0 WRITE   3515809\n0x40193080 WRITE   3515812\n0x40193040 WRITE   3515815\n0x40134000 WRITE   3515840\n0x40134040 WRITE   3515924\n0x40134080 WRITE   3515990\n0x401340C0 WRITE   3516046\n0x40134100 WRITE   3516129\n0x40134140 WRITE   3516185\n0x40134180 WRITE   3516248\n0x401341C0 WRITE   3516304\n0x40193180 WRITE   3516360\n0x40193140 WRITE   3516362\n0x40134200 WRITE   3516398\n0x40134240 WRITE   3516454\n0x40134280 WRITE   3516517\n0x401342C0 WRITE   3516573\n0x40134300 WRITE   3516651\n0x40134340 WRITE   3516707\n0x40134380 WRITE   3516770\n0x401343C0 WRITE   3516826\n0x40193300 WRITE   3516892\n0x401932C0 WRITE   3516894\n0x40193280 WRITE   3516901\n0x40193240 WRITE   3516903\n0x40134400 WRITE   3516936\n0x40134440 WRITE   3516992\n0x40134480 WRITE   3517066\n0x401344C0 WRITE   3517122\n0x40134500 WRITE   3517213\n0x40134540 WRITE   3517269\n0x40134580 WRITE   3517340\n0x401345C0 WRITE   3517396\n0x40193380 WRITE   3517460\n0x40193340 WRITE   3517462\n0x40134600 WRITE   3517498\n0x40134640 WRITE   3517554\n0x40134680 WRITE   3517625\n0x401346C0 WRITE   3517681\n0x40134700 WRITE   3517767\n0x40134740 WRITE   3517823\n0x40134780 WRITE   3517894\n0x401347C0 WRITE   3517950\n0x40193600 WRITE   3518025\n0x401935C0 WRITE   3518027\n0x40193500 WRITE   3518034\n0x401934C0 WRITE   3518036\n0x40193480 WRITE   3518046\n0x40193440 WRITE   3518048\n0x40134800 WRITE   3518075\n0x40134840 WRITE   3518131\n0x40134880 WRITE   3518197\n0x401348C0 WRITE   3518253\n0x40134900 WRITE   3518340\n0x40134940 WRITE   3518396\n0x40134980 WRITE   3518459\n0x401349C0 WRITE   3518515\n0x40193580 WRITE   3518577\n0x40193540 WRITE   3518579\n0x40134A00 WRITE   3518615\n0x40134A40 WRITE   3518671\n0x40134A80 WRITE   3518734\n0x40134AC0 WRITE   3518790\n0x40134B00 WRITE   3518872\n0x40134B40 WRITE   3518928\n0x40134B80 WRITE   3518991\n0x40134BC0 WRITE   3519047\n0x40193700 WRITE   3519119\n0x401936C0 WRITE   3519121\n0x40193680 WRITE   3519128\n0x40193640 WRITE   3519130\n0x40134C00 WRITE   3519163\n0x40134C40 WRITE   3519219\n0x40134C80 WRITE   3519293\n0x40134CC0 WRITE   3519349\n0x40134D00 WRITE   3519444\n0x40134D40 WRITE   3519500\n0x40134D80 WRITE   3519571\n0x40134DC0 WRITE   3519627\n0x40193780 WRITE   3519697\n0x40193740 WRITE   3519699\n0x40134E00 WRITE   3519735\n0x40134E40 WRITE   3519791\n0x40134E80 WRITE   3519862\n0x40134EC0 WRITE   3519918\n0x40134F00 WRITE   3520008\n0x40134F40 WRITE   3520064\n0x40134F80 WRITE   3520135\n0x40134FC0 WRITE   3520191\n0x40193C00 WRITE   3520277\n0x40193BC0 WRITE   3520279\n0x40193A00 WRITE   3520286\n0x401939C0 WRITE   3520288\n0x40193900 WRITE   3520298\n0x401938C0 WRITE   3520300\n0x40193880 WRITE   3520305\n0x40193840 WRITE   3520308\n0x40135000 WRITE   3520333\n0x40135040 WRITE   3520417\n0x40135080 WRITE   3520483\n0x401350C0 WRITE   3520539\n0x40135100 WRITE   3520622\n0x40135140 WRITE   3520678\n0x40135180 WRITE   3520741\n0x401351C0 WRITE   3520797\n0x40193980 WRITE   3520861\n0x40193940 WRITE   3520863\n0x40135200 WRITE   3520899\n0x40135240 WRITE   3520955\n0x40135280 WRITE   3521018\n0x401352C0 WRITE   3521074\n0x40135300 WRITE   3521152\n0x40135340 WRITE   3521208\n0x40135380 WRITE   3521271\n0x401353C0 WRITE   3521327\n0x40193B00 WRITE   3521401\n0x40193AC0 WRITE   3521403\n0x40193A80 WRITE   3521410\n0x40193A40 WRITE   3521412\n0x40135400 WRITE   3521445\n0x40135440 WRITE   3521501\n0x40135480 WRITE   3521575\n0x401354C0 WRITE   3521631\n0x40135500 WRITE   3521722\n0x40135540 WRITE   3521778\n0x40135580 WRITE   3521849\n0x401355C0 WRITE   3521905\n0x40193B80 WRITE   3521977\n0x40193B40 WRITE   3521979\n0x40135600 WRITE   3522015\n0x40135640 WRITE   3522071\n0x40135680 WRITE   3522142\n0x401356C0 WRITE   3522198\n0x40135700 WRITE   3522284\n0x40135740 WRITE   3522340\n0x40135780 WRITE   3522411\n0x401357C0 WRITE   3522467\n0x40193E00 WRITE   3522550\n0x40193DC0 WRITE   3522552\n0x40193D00 WRITE   3522559\n0x40193CC0 WRITE   3522561\n0x40193C80 WRITE   3522571\n0x40193C40 WRITE   3522573\n0x40135800 WRITE   3522600\n0x40135840 WRITE   3522656\n0x40135880 WRITE   3522722\n0x401358C0 WRITE   3522778\n0x40135900 WRITE   3522865\n0x40135940 WRITE   3522921\n0x40135980 WRITE   3522984\n0x401359C0 WRITE   3523040\n0x40193D80 WRITE   3523109\n0x40193D40 WRITE   3523111\n0x40135A00 WRITE   3523147\n0x40135A40 WRITE   3523203\n0x40135A80 WRITE   3523266\n0x40135AC0 WRITE   3523322\n0x40135B00 WRITE   3523404\n0x40135B40 WRITE   3523460\n0x40135B80 WRITE   3523523\n0x40135BC0 WRITE   3523579\n0x40193F00 WRITE   3523658\n0x40193EC0 WRITE   3523660\n0x40193E80 WRITE   3523667\n0x40193E40 WRITE   3523669\n0x40135C00 WRITE   3523702\n0x40135C40 WRITE   3523758\n0x40135C80 WRITE   3523832\n0x40135CC0 WRITE   3523888\n0x40135D00 WRITE   3523983\n0x40135D40 WRITE   3524039\n0x40135D80 WRITE   3524110\n0x40135DC0 WRITE   3524166\n0x40193F80 WRITE   3524243\n0x40193F40 WRITE   3524245\n0x40135E00 WRITE   3524281\n0x40135E40 WRITE   3524337\n0x40135E80 WRITE   3524408\n0x40135EC0 WRITE   3524464\n0x40135F00 WRITE   3524554\n0x40135F40 WRITE   3524610\n0x40135F80 WRITE   3524681\n0x40135FC0 WRITE   3524737\n0x40195FC0 WRITE   3524899\n0x40196000 WRITE   3524931\n0x40195000 WRITE   3525091\n0x40194FC0 WRITE   3525093\n0x40194800 WRITE   3525100\n0x401947C0 WRITE   3525102\n0x40194400 WRITE   3525112\n0x401943C0 WRITE   3525114\n0x40194200 WRITE   3525119\n0x401941C0 WRITE   3525122\n0x40194100 WRITE   3525125\n0x401940C0 WRITE   3525128\n0x40194080 WRITE   3525131\n0x40194040 WRITE   3525134\n0x40136000 WRITE   3525166\n0x40136040 WRITE   3525254\n0x40136080 WRITE   3525320\n0x401360C0 WRITE   3525376\n0x40136100 WRITE   3525459\n0x40136140 WRITE   3525515\n0x40136180 WRITE   3525578\n0x401361C0 WRITE   3525634\n0x40194180 WRITE   3525690\n0x40194140 WRITE   3525692\n0x40136200 WRITE   3525728\n0x40136240 WRITE   3525784\n0x40136280 WRITE   3525847\n0x401362C0 WRITE   3525903\n0x40136300 WRITE   3525981\n0x40136340 WRITE   3526037\n0x40136380 WRITE   3526100\n0x401363C0 WRITE   3526156\n0x40194300 WRITE   3526217\n0x401942C0 WRITE   3526219\n0x40194280 WRITE   3526226\n0x40194240 WRITE   3526228\n0x40136400 WRITE   3526261\n0x40136440 WRITE   3526317\n0x40136480 WRITE   3526391\n0x401364C0 WRITE   3526447\n0x40136500 WRITE   3526538\n0x40136540 WRITE   3526594\n0x40136580 WRITE   3526665\n0x401365C0 WRITE   3526721\n0x40194380 WRITE   3526785\n0x40194340 WRITE   3526787\n0x40136600 WRITE   3526823\n0x40136640 WRITE   3526879\n0x40136680 WRITE   3526950\n0x401366C0 WRITE   3527006\n0x40136700 WRITE   3527092\n0x40136740 WRITE   3527148\n0x40136780 WRITE   3527219\n0x401367C0 WRITE   3527275\n0x40194600 WRITE   3527344\n0x401945C0 WRITE   3527346\n0x40194500 WRITE   3527353\n0x401944C0 WRITE   3527355\n0x40194480 WRITE   3527365\n0x40194440 WRITE   3527367\n0x40136800 WRITE   3527394\n0x40136840 WRITE   3527450\n0x40136880 WRITE   3527516\n0x401368C0 WRITE   3527572\n0x40136900 WRITE   3527659\n0x40136940 WRITE   3527715\n0x40136980 WRITE   3527778\n0x401369C0 WRITE   3527834\n0x40194580 WRITE   3527896\n0x40194540 WRITE   3527898\n0x40136A00 WRITE   3527934\n0x40136A40 WRITE   3527990\n0x40136A80 WRITE   3528053\n0x40136AC0 WRITE   3528109\n0x40136B00 WRITE   3528191\n0x40136B40 WRITE   3528247\n0x40136B80 WRITE   3528310\n0x40136BC0 WRITE   3528366\n0x40194700 WRITE   3528432\n0x401946C0 WRITE   3528434\n0x40194680 WRITE   3528441\n0x40194640 WRITE   3528443\n0x40136C00 WRITE   3528476\n0x40136C40 WRITE   3528532\n0x40136C80 WRITE   3528606\n0x40136CC0 WRITE   3528662\n0x40136D00 WRITE   3528757\n0x40136D40 WRITE   3528813\n0x40136D80 WRITE   3528884\n0x40136DC0 WRITE   3528940\n0x40194780 WRITE   3529010\n0x40194740 WRITE   3529012\n0x40136E00 WRITE   3529048\n0x40136E40 WRITE   3529104\n0x40136E80 WRITE   3529175\n0x40136EC0 WRITE   3529231\n0x40136F00 WRITE   3529321\n0x40136F40 WRITE   3529377\n0x40136F80 WRITE   3529448\n0x40136FC0 WRITE   3529504\n0x40194C00 WRITE   3529584\n0x40194BC0 WRITE   3529586\n0x40194A00 WRITE   3529593\n0x401949C0 WRITE   3529595\n0x40194900 WRITE   3529605\n0x401948C0 WRITE   3529607\n0x40194880 WRITE   3529612\n0x40194840 WRITE   3529615\n0x40137000 WRITE   3529640\n0x40137040 WRITE   3529724\n0x40137080 WRITE   3529790\n0x401370C0 WRITE   3529846\n0x40137100 WRITE   3529929\n0x40137140 WRITE   3529985\n0x40137180 WRITE   3530048\n0x401371C0 WRITE   3530104\n0x40194980 WRITE   3530168\n0x40194940 WRITE   3530170\n0x40137200 WRITE   3530206\n0x40137240 WRITE   3530262\n0x40137280 WRITE   3530325\n0x401372C0 WRITE   3530381\n0x40137300 WRITE   3530459\n0x40137340 WRITE   3530515\n0x40137380 WRITE   3530578\n0x401373C0 WRITE   3530634\n0x40194B00 WRITE   3530702\n0x40194AC0 WRITE   3530704\n0x40194A80 WRITE   3530711\n0x40194A40 WRITE   3530713\n0x40137400 WRITE   3530746\n0x40137440 WRITE   3530802\n0x40137480 WRITE   3530876\n0x401374C0 WRITE   3530932\n0x40137500 WRITE   3531023\n0x40137540 WRITE   3531079\n0x40137580 WRITE   3531150\n0x401375C0 WRITE   3531206\n0x40194B80 WRITE   3531278\n0x40194B40 WRITE   3531280\n0x40137600 WRITE   3531316\n0x40137640 WRITE   3531372\n0x40137680 WRITE   3531443\n0x401376C0 WRITE   3531499\n0x40137700 WRITE   3531585\n0x40137740 WRITE   3531641\n0x40137780 WRITE   3531712\n0x401377C0 WRITE   3531768\n0x40194E00 WRITE   3531845\n0x40194DC0 WRITE   3531847\n0x40194D00 WRITE   3531854\n0x40194CC0 WRITE   3531856\n0x40194C80 WRITE   3531866\n0x40194C40 WRITE   3531868\n0x40137800 WRITE   3531895\n0x40137840 WRITE   3531951\n0x40137880 WRITE   3532017\n0x401378C0 WRITE   3532073\n0x40137900 WRITE   3532160\n0x40137940 WRITE   3532216\n0x40137980 WRITE   3532279\n0x401379C0 WRITE   3532335\n0x40194D80 WRITE   3532404\n0x40194D40 WRITE   3532406\n0x40137A00 WRITE   3532442\n0x40137A40 WRITE   3532498\n0x40137A80 WRITE   3532561\n0x40137AC0 WRITE   3532617\n0x40137B00 WRITE   3532699\n0x40137B40 WRITE   3532755\n0x40137B80 WRITE   3532818\n0x40137BC0 WRITE   3532874\n0x40194F00 WRITE   3532947\n0x40194EC0 WRITE   3532949\n0x40194E80 WRITE   3532956\n0x40194E40 WRITE   3532958\n0x40137C00 WRITE   3532991\n0x40137C40 WRITE   3533047\n0x40137C80 WRITE   3533121\n0x40137CC0 WRITE   3533177\n0x40137D00 WRITE   3533272\n0x40137D40 WRITE   3533328\n0x40137D80 WRITE   3533399\n0x40137DC0 WRITE   3533455\n0x40194F80 WRITE   3533532\n0x40194F40 WRITE   3533534\n0x40137E00 WRITE   3533570\n0x40137E40 WRITE   3533626\n0x40137E80 WRITE   3533697\n0x40137EC0 WRITE   3533753\n0x40137F00 WRITE   3533843\n0x40137F40 WRITE   3533899\n0x40137F80 WRITE   3533970\n0x40137FC0 WRITE   3534026\n0x40195800 WRITE   3534112\n0x401957C0 WRITE   3534114\n0x40195400 WRITE   3534121\n0x401953C0 WRITE   3534123\n0x40195200 WRITE   3534133\n0x401951C0 WRITE   3534135\n0x40195100 WRITE   3534140\n0x401950C0 WRITE   3534143\n0x40195080 WRITE   3534146\n0x40195040 WRITE   3534149\n0x40138000 WRITE   3534174\n0x40138040 WRITE   3534258\n0x40138080 WRITE   3534324\n0x401380C0 WRITE   3534380\n0x40138100 WRITE   3534463\n0x40138140 WRITE   3534519\n0x40138180 WRITE   3534582\n0x401381C0 WRITE   3534638\n0x40195180 WRITE   3534694\n0x40195140 WRITE   3534696\n0x40138200 WRITE   3534732\n0x40138240 WRITE   3534788\n0x40138280 WRITE   3534851\n0x401382C0 WRITE   3534907\n0x40138300 WRITE   3534985\n0x40138340 WRITE   3535041\n0x40138380 WRITE   3535104\n0x401383C0 WRITE   3535160\n0x40195300 WRITE   3535226\n0x401952C0 WRITE   3535228\n0x40195280 WRITE   3535235\n0x40195240 WRITE   3535237\n0x40138400 WRITE   3535270\n0x40138440 WRITE   3535326\n0x40138480 WRITE   3535400\n0x401384C0 WRITE   3535456\n0x40138500 WRITE   3535547\n0x40138540 WRITE   3535603\n0x40138580 WRITE   3535674\n0x401385C0 WRITE   3535730\n0x40195380 WRITE   3535794\n0x40195340 WRITE   3535796\n0x40138600 WRITE   3535832\n0x40138640 WRITE   3535888\n0x40138680 WRITE   3535959\n0x401386C0 WRITE   3536015\n0x40138700 WRITE   3536101\n0x40138740 WRITE   3536157\n0x40138780 WRITE   3536228\n0x401387C0 WRITE   3536284\n0x40195600 WRITE   3536359\n0x401955C0 WRITE   3536361\n0x40195500 WRITE   3536368\n0x401954C0 WRITE   3536370\n0x40195480 WRITE   3536380\n0x40195440 WRITE   3536382\n0x40138800 WRITE   3536409\n0x40138840 WRITE   3536465\n0x40138880 WRITE   3536531\n0x401388C0 WRITE   3536587\n0x40138900 WRITE   3536674\n0x40138940 WRITE   3536730\n0x40138980 WRITE   3536793\n0x401389C0 WRITE   3536849\n0x40195580 WRITE   3536911\n0x40195540 WRITE   3536913\n0x40138A00 WRITE   3536949\n0x40138A40 WRITE   3537005\n0x40138A80 WRITE   3537068\n0x40138AC0 WRITE   3537124\n0x40138B00 WRITE   3537206\n0x40138B40 WRITE   3537262\n0x40138B80 WRITE   3537325\n0x40138BC0 WRITE   3537381\n0x40195700 WRITE   3537453\n0x401956C0 WRITE   3537455\n0x40195680 WRITE   3537462\n0x40195640 WRITE   3537464\n0x40138C00 WRITE   3537497\n0x40138C40 WRITE   3537553\n0x40138C80 WRITE   3537627\n0x40138CC0 WRITE   3537683\n0x40138D00 WRITE   3537778\n0x40138D40 WRITE   3537834\n0x40138D80 WRITE   3537905\n0x40138DC0 WRITE   3537961\n0x40195780 WRITE   3538031\n0x40195740 WRITE   3538033\n0x40138E00 WRITE   3538069\n0x40138E40 WRITE   3538125\n0x40138E80 WRITE   3538196\n0x40138EC0 WRITE   3538252\n0x40138F00 WRITE   3538342\n0x40138F40 WRITE   3538398\n0x40138F80 WRITE   3538469\n0x40138FC0 WRITE   3538525\n0x40195C00 WRITE   3538611\n0x40195BC0 WRITE   3538613\n0x40195A00 WRITE   3538620\n0x401959C0 WRITE   3538622\n0x40195900 WRITE   3538632\n0x401958C0 WRITE   3538634\n0x40195880 WRITE   3538639\n0x40195840 WRITE   3538642\n0x40139000 WRITE   3538667\n0x40139040 WRITE   3538751\n0x40139080 WRITE   3538817\n0x401390C0 WRITE   3538873\n0x40139100 WRITE   3538956\n0x40139140 WRITE   3539012\n0x40139180 WRITE   3539075\n0x401391C0 WRITE   3539131\n0x40195980 WRITE   3539195\n0x40195940 WRITE   3539197\n0x40139200 WRITE   3539233\n0x40139240 WRITE   3539289\n0x40139280 WRITE   3539352\n0x401392C0 WRITE   3539408\n0x40139300 WRITE   3539486\n0x40139340 WRITE   3539542\n0x40139380 WRITE   3539605\n0x401393C0 WRITE   3539661\n0x40195B00 WRITE   3539735\n0x40195AC0 WRITE   3539737\n0x40195A80 WRITE   3539744\n0x40195A40 WRITE   3539746\n0x40139400 WRITE   3539779\n0x40139440 WRITE   3539835\n0x40139480 WRITE   3539909\n0x401394C0 WRITE   3539965\n0x40139500 WRITE   3540056\n0x40139540 WRITE   3540112\n0x40139580 WRITE   3540183\n0x401395C0 WRITE   3540239\n0x40195B80 WRITE   3540311\n0x40195B40 WRITE   3540313\n0x40139600 WRITE   3540349\n0x40139640 WRITE   3540405\n0x40139680 WRITE   3540476\n0x401396C0 WRITE   3540532\n0x40139700 WRITE   3540618\n0x40139740 WRITE   3540674\n0x40139780 WRITE   3540745\n0x401397C0 WRITE   3540801\n0x40195E00 WRITE   3540884\n0x40195DC0 WRITE   3540886\n0x40195D00 WRITE   3540893\n0x40195CC0 WRITE   3540895\n0x40195C80 WRITE   3540905\n0x40195C40 WRITE   3540907\n0x40139800 WRITE   3540934\n0x40139840 WRITE   3540990\n0x40139880 WRITE   3541056\n0x401398C0 WRITE   3541112\n0x40139900 WRITE   3541199\n0x40139940 WRITE   3541255\n0x40139980 WRITE   3541318\n0x401399C0 WRITE   3541374\n0x40195D80 WRITE   3541443\n0x40195D40 WRITE   3541445\n0x40139A00 WRITE   3541481\n0x40139A40 WRITE   3541537\n0x40139A80 WRITE   3541600\n0x40139AC0 WRITE   3541656\n0x40139B00 WRITE   3541738\n0x40139B40 WRITE   3541794\n0x40139B80 WRITE   3541857\n0x40139BC0 WRITE   3541913\n0x40195F00 WRITE   3541992\n0x40195EC0 WRITE   3541994\n0x40195E80 WRITE   3542001\n0x40195E40 WRITE   3542003\n0x40139C00 WRITE   3542036\n0x40139C40 WRITE   3542092\n0x40139C80 WRITE   3542166\n0x40139CC0 WRITE   3542222\n0x40139D00 WRITE   3542317\n0x40139D40 WRITE   3542373\n0x40139D80 WRITE   3542444\n0x40139DC0 WRITE   3542500\n0x40195F80 WRITE   3542577\n0x40195F40 WRITE   3542579\n0x40139E00 WRITE   3542615\n0x40139E40 WRITE   3542671\n0x40139E80 WRITE   3542742\n0x40139EC0 WRITE   3542798\n0x40139F00 WRITE   3542888\n0x40139F40 WRITE   3542944\n0x40139F80 WRITE   3543015\n0x40139FC0 WRITE   3543071\n0x40197FC0 WRITE   3543233\n0x40198000 WRITE   3543265\n0x40197000 WRITE   3543392\n0x40196FC0 WRITE   3543394\n0x40196800 WRITE   3543401\n0x401967C0 WRITE   3543403\n0x40196400 WRITE   3543413\n0x401963C0 WRITE   3543415\n0x40196200 WRITE   3543420\n0x401961C0 WRITE   3543423\n0x40196100 WRITE   3543426\n0x401960C0 WRITE   3543429\n0x40196080 WRITE   3543432\n0x40196040 WRITE   3543435\n0x4013A000 WRITE   3543467\n0x4013A040 WRITE   3543555\n0x4013A080 WRITE   3543621\n0x4013A0C0 WRITE   3543677\n0x4013A100 WRITE   3543760\n0x4013A140 WRITE   3543816\n0x4013A180 WRITE   3543879\n0x4013A1C0 WRITE   3543935\n0x40196180 WRITE   3543991\n0x40196140 WRITE   3543993\n0x4013A200 WRITE   3544029\n0x4013A240 WRITE   3544085\n0x4013A280 WRITE   3544148\n0x4013A2C0 WRITE   3544204\n0x4013A300 WRITE   3544282\n0x4013A340 WRITE   3544338\n0x4013A380 WRITE   3544401\n0x4013A3C0 WRITE   3544457\n0x40196300 WRITE   3544518\n0x401962C0 WRITE   3544520\n0x40196280 WRITE   3544527\n0x40196240 WRITE   3544529\n0x4013A400 WRITE   3544562\n0x4013A440 WRITE   3544618\n0x4013A480 WRITE   3544692\n0x4013A4C0 WRITE   3544748\n0x4013A500 WRITE   3544839\n0x4013A540 WRITE   3544895\n0x4013A580 WRITE   3544966\n0x4013A5C0 WRITE   3545022\n0x40196380 WRITE   3545086\n0x40196340 WRITE   3545088\n0x4013A600 WRITE   3545124\n0x4013A640 WRITE   3545180\n0x4013A680 WRITE   3545251\n0x4013A6C0 WRITE   3545307\n0x4013A700 WRITE   3545393\n0x4013A740 WRITE   3545449\n0x4013A780 WRITE   3545520\n0x4013A7C0 WRITE   3545576\n0x40196600 WRITE   3545645\n0x401965C0 WRITE   3545647\n0x40196500 WRITE   3545654\n0x401964C0 WRITE   3545656\n0x40196480 WRITE   3545666\n0x40196440 WRITE   3545668\n0x4013A800 WRITE   3545695\n0x4013A840 WRITE   3545751\n0x4013A880 WRITE   3545817\n0x4013A8C0 WRITE   3545873\n0x4013A900 WRITE   3545960\n0x4013A940 WRITE   3546016\n0x4013A980 WRITE   3546079\n0x4013A9C0 WRITE   3546135\n0x40196580 WRITE   3546197\n0x40196540 WRITE   3546199\n0x4013AA00 WRITE   3546235\n0x4013AA40 WRITE   3546291\n0x4013AA80 WRITE   3546354\n0x4013AAC0 WRITE   3546410\n0x4013AB00 WRITE   3546492\n0x4013AB40 WRITE   3546548\n0x4013AB80 WRITE   3546611\n0x4013ABC0 WRITE   3546667\n0x40196700 WRITE   3546733\n0x401966C0 WRITE   3546735\n0x40196680 WRITE   3546742\n0x40196640 WRITE   3546744\n0x4013AC00 WRITE   3546777\n0x4013AC40 WRITE   3546833\n0x4013AC80 WRITE   3546907\n0x4013ACC0 WRITE   3546963\n0x4013AD00 WRITE   3547058\n0x4013AD40 WRITE   3547114\n0x4013AD80 WRITE   3547185\n0x4013ADC0 WRITE   3547241\n0x40196780 WRITE   3547311\n0x40196740 WRITE   3547313\n0x4013AE00 WRITE   3547349\n0x4013AE40 WRITE   3547405\n0x4013AE80 WRITE   3547476\n0x4013AEC0 WRITE   3547532\n0x4013AF00 WRITE   3547622\n0x4013AF40 WRITE   3547678\n0x4013AF80 WRITE   3547749\n0x4013AFC0 WRITE   3547805\n0x40196C00 WRITE   3547885\n0x40196BC0 WRITE   3547887\n0x40196A00 WRITE   3547894\n0x401969C0 WRITE   3547896\n0x40196900 WRITE   3547906\n0x401968C0 WRITE   3547908\n0x40196880 WRITE   3547913\n0x40196840 WRITE   3547916\n0x4013B000 WRITE   3547941\n0x4013B040 WRITE   3548025\n0x4013B080 WRITE   3548091\n0x4013B0C0 WRITE   3548147\n0x4013B100 WRITE   3548230\n0x4013B140 WRITE   3548286\n0x4013B180 WRITE   3548349\n0x4013B1C0 WRITE   3548405\n0x40196980 WRITE   3548469\n0x40196940 WRITE   3548471\n0x4013B200 WRITE   3548507\n0x4013B240 WRITE   3548563\n0x4013B280 WRITE   3548626\n0x4013B2C0 WRITE   3548682\n0x4013B300 WRITE   3548760\n0x4013B340 WRITE   3548816\n0x4013B380 WRITE   3548879\n0x4013B3C0 WRITE   3548935\n0x40196B00 WRITE   3549003\n0x40196AC0 WRITE   3549005\n0x40196A80 WRITE   3549012\n0x40196A40 WRITE   3549014\n0x4013B400 WRITE   3549047\n0x4013B440 WRITE   3549103\n0x4013B480 WRITE   3549177\n0x4013B4C0 WRITE   3549233\n0x4013B500 WRITE   3549324\n0x4013B540 WRITE   3549380\n0x4013B580 WRITE   3549451\n0x4013B5C0 WRITE   3549507\n0x40196B80 WRITE   3549579\n0x40196B40 WRITE   3549581\n0x4013B600 WRITE   3549617\n0x4013B640 WRITE   3549673\n0x4013B680 WRITE   3549744\n0x4013B6C0 WRITE   3549800\n0x4013B700 WRITE   3549886\n0x4013B740 WRITE   3549942\n0x4013B780 WRITE   3550013\n0x4013B7C0 WRITE   3550069\n0x40196E00 WRITE   3550146\n0x40196DC0 WRITE   3550148\n0x40196D00 WRITE   3550155\n0x40196CC0 WRITE   3550157\n0x40196C80 WRITE   3550167\n0x40196C40 WRITE   3550169\n0x4013B800 WRITE   3550196\n0x4013B840 WRITE   3550252\n0x4013B880 WRITE   3550318\n0x4013B8C0 WRITE   3550374\n0x4013B900 WRITE   3550461\n0x4013B940 WRITE   3550517\n0x4013B980 WRITE   3550580\n0x4013B9C0 WRITE   3550636\n0x40196D80 WRITE   3550705\n0x40196D40 WRITE   3550707\n0x4013BA00 WRITE   3550743\n0x4013BA40 WRITE   3550799\n0x4013BA80 WRITE   3550862\n0x4013BAC0 WRITE   3550918\n0x4013BB00 WRITE   3551000\n0x4013BB40 WRITE   3551056\n0x4013BB80 WRITE   3551119\n0x4013BBC0 WRITE   3551175\n0x40196F00 WRITE   3551248\n0x40196EC0 WRITE   3551250\n0x40196E80 WRITE   3551257\n0x40196E40 WRITE   3551259\n0x4013BC00 WRITE   3551292\n0x4013BC40 WRITE   3551348\n0x4013BC80 WRITE   3551422\n0x4013BCC0 WRITE   3551478\n0x4013BD00 WRITE   3551573\n0x4013BD40 WRITE   3551629\n0x4013BD80 WRITE   3551700\n0x4013BDC0 WRITE   3551756\n0x40196F80 WRITE   3551833\n0x40196F40 WRITE   3551835\n0x4013BE00 WRITE   3551871\n0x4013BE40 WRITE   3551927\n0x4013BE80 WRITE   3551998\n0x4013BEC0 WRITE   3552054\n0x4013BF00 WRITE   3552144\n0x4013BF40 WRITE   3552200\n0x4013BF80 WRITE   3552271\n0x4013BFC0 WRITE   3552327\n0x40197800 WRITE   3552413\n0x401977C0 WRITE   3552415\n0x40197400 WRITE   3552422\n0x401973C0 WRITE   3552424\n0x40197200 WRITE   3552434\n0x401971C0 WRITE   3552436\n0x40197100 WRITE   3552441\n0x401970C0 WRITE   3552444\n0x40197080 WRITE   3552447\n0x40197040 WRITE   3552450\n0x4013C000 WRITE   3552475\n0x4013C040 WRITE   3552559\n0x4013C080 WRITE   3552625\n0x4013C0C0 WRITE   3552681\n0x4013C100 WRITE   3552764\n0x4013C140 WRITE   3552820\n0x4013C180 WRITE   3552883\n0x4013C1C0 WRITE   3552939\n0x40197180 WRITE   3552995\n0x40197140 WRITE   3552997\n0x4013C200 WRITE   3553033\n0x4013C240 WRITE   3553089\n0x4013C280 WRITE   3553152\n0x4013C2C0 WRITE   3553208\n0x4013C300 WRITE   3553286\n0x4013C340 WRITE   3553342\n0x4013C380 WRITE   3553405\n0x4013C3C0 WRITE   3553461\n0x40197300 WRITE   3553527\n0x401972C0 WRITE   3553529\n0x40197280 WRITE   3553536\n0x40197240 WRITE   3553538\n0x4013C400 WRITE   3553571\n0x4013C440 WRITE   3553627\n0x4013C480 WRITE   3553701\n0x4013C4C0 WRITE   3553757\n0x4013C500 WRITE   3553848\n0x4013C540 WRITE   3553904\n0x4013C580 WRITE   3553975\n0x4013C5C0 WRITE   3554031\n0x40197380 WRITE   3554095\n0x40197340 WRITE   3554097\n0x4013C600 WRITE   3554133\n0x4013C640 WRITE   3554189\n0x4013C680 WRITE   3554260\n0x4013C6C0 WRITE   3554316\n0x4013C700 WRITE   3554402\n0x4013C740 WRITE   3554458\n0x4013C780 WRITE   3554529\n0x4013C7C0 WRITE   3554585\n0x40197600 WRITE   3554660\n0x401975C0 WRITE   3554662\n0x40197500 WRITE   3554669\n0x401974C0 WRITE   3554671\n0x40197480 WRITE   3554681\n0x40197440 WRITE   3554683\n0x4013C800 WRITE   3554710\n0x4013C840 WRITE   3554766\n0x4013C880 WRITE   3554832\n0x4013C8C0 WRITE   3554888\n0x4013C900 WRITE   3554975\n0x4013C940 WRITE   3555031\n0x4013C980 WRITE   3555094\n0x4013C9C0 WRITE   3555150\n0x40197580 WRITE   3555212\n0x40197540 WRITE   3555214\n0x4013CA00 WRITE   3555250\n0x4013CA40 WRITE   3555306\n0x4013CA80 WRITE   3555369\n0x4013CAC0 WRITE   3555425\n0x4013CB00 WRITE   3555507\n0x4013CB40 WRITE   3555563\n0x4013CB80 WRITE   3555626\n0x4013CBC0 WRITE   3555682\n0x40197700 WRITE   3555754\n0x401976C0 WRITE   3555756\n0x40197680 WRITE   3555763\n0x40197640 WRITE   3555765\n0x4013CC00 WRITE   3555798\n0x4013CC40 WRITE   3555854\n0x4013CC80 WRITE   3555928\n0x4013CCC0 WRITE   3555984\n0x4013CD00 WRITE   3556079\n0x4013CD40 WRITE   3556135\n0x4013CD80 WRITE   3556206\n0x4013CDC0 WRITE   3556262\n0x40197780 WRITE   3556332\n0x40197740 WRITE   3556334\n0x4013CE00 WRITE   3556370\n0x4013CE40 WRITE   3556426\n0x4013CE80 WRITE   3556497\n0x4013CEC0 WRITE   3556553\n0x4013CF00 WRITE   3556643\n0x4013CF40 WRITE   3556699\n0x4013CF80 WRITE   3556770\n0x4013CFC0 WRITE   3556826\n0x40197C00 WRITE   3556912\n0x40197BC0 WRITE   3556914\n0x40197A00 WRITE   3556921\n0x401979C0 WRITE   3556923\n0x40197900 WRITE   3556933\n0x401978C0 WRITE   3556935\n0x40197880 WRITE   3556940\n0x40197840 WRITE   3556943\n0x4013D000 WRITE   3556968\n0x4013D040 WRITE   3557052\n0x4013D080 WRITE   3557118\n0x4013D0C0 WRITE   3557174\n0x4013D100 WRITE   3557257\n0x4013D140 WRITE   3557313\n0x4013D180 WRITE   3557376\n0x4013D1C0 WRITE   3557432\n0x40197980 WRITE   3557496\n0x40197940 WRITE   3557498\n0x4013D200 WRITE   3557534\n0x4013D240 WRITE   3557590\n0x4013D280 WRITE   3557653\n0x4013D2C0 WRITE   3557709\n0x4013D300 WRITE   3557787\n0x4013D340 WRITE   3557843\n0x4013D380 WRITE   3557906\n0x4013D3C0 WRITE   3557962\n0x40197B00 WRITE   3558036\n0x40197AC0 WRITE   3558038\n0x40197A80 WRITE   3558045\n0x40197A40 WRITE   3558047\n0x4013D400 WRITE   3558080\n0x4013D440 WRITE   3558136\n0x4013D480 WRITE   3558210\n0x4013D4C0 WRITE   3558266\n0x4013D500 WRITE   3558357\n0x4013D540 WRITE   3558413\n0x4013D580 WRITE   3558484\n0x4013D5C0 WRITE   3558540\n0x40197B80 WRITE   3558612\n0x40197B40 WRITE   3558614\n0x4013D600 WRITE   3558650\n0x4013D640 WRITE   3558706\n0x4013D680 WRITE   3558777\n0x4013D6C0 WRITE   3558833\n0x4013D700 WRITE   3558919\n0x4013D740 WRITE   3558975\n0x4013D780 WRITE   3559046\n0x4013D7C0 WRITE   3559102\n0x40197E00 WRITE   3559185\n0x40197DC0 WRITE   3559187\n0x40197D00 WRITE   3559194\n0x40197CC0 WRITE   3559196\n0x40197C80 WRITE   3559206\n0x40197C40 WRITE   3559208\n0x4013D800 WRITE   3559235\n0x4013D840 WRITE   3559291\n0x4013D880 WRITE   3559357\n0x4013D8C0 WRITE   3559413\n0x4013D900 WRITE   3559500\n0x4013D940 WRITE   3559556\n0x4013D980 WRITE   3559619\n0x4013D9C0 WRITE   3559675\n0x40197D80 WRITE   3559744\n0x40197D40 WRITE   3559746\n0x4013DA00 WRITE   3559782\n0x4013DA40 WRITE   3559838\n0x4013DA80 WRITE   3559901\n0x4013DAC0 WRITE   3559957\n0x4013DB00 WRITE   3560039\n0x4013DB40 WRITE   3560095\n0x4013DB80 WRITE   3560158\n0x4013DBC0 WRITE   3560214\n0x40197F00 WRITE   3560293\n0x40197EC0 WRITE   3560295\n0x40197E80 WRITE   3560302\n0x40197E40 WRITE   3560304\n0x4013DC00 WRITE   3560337\n0x4013DC40 WRITE   3560393\n0x4013DC80 WRITE   3560467\n0x4013DCC0 WRITE   3560523\n0x4013DD00 WRITE   3560618\n0x4013DD40 WRITE   3560674\n0x4013DD80 WRITE   3560745\n0x4013DDC0 WRITE   3560801\n0x40197F80 WRITE   3560878\n0x40197F40 WRITE   3560880\n0x4013DE00 WRITE   3560916\n0x4013DE40 WRITE   3560972\n0x4013DE80 WRITE   3561043\n0x4013DEC0 WRITE   3561099\n0x4013DF00 WRITE   3561189\n0x4013DF40 WRITE   3561245\n0x4013DF80 WRITE   3561316\n0x4013DFC0 WRITE   3561372\n0x40199FC0 WRITE   3561534\n0x4019A000 WRITE   3561566\n0x40199000 WRITE   3561693\n0x40198FC0 WRITE   3561695\n0x40198800 WRITE   3561702\n0x401987C0 WRITE   3561704\n0x40198400 WRITE   3561714\n0x401983C0 WRITE   3561716\n0x40198200 WRITE   3561721\n0x401981C0 WRITE   3561724\n0x40198100 WRITE   3561727\n0x401980C0 WRITE   3561730\n0x40198080 WRITE   3561733\n0x40198040 WRITE   3561736\n0x4013E000 WRITE   3561768\n0x4013E040 WRITE   3561856\n0x4013E080 WRITE   3561922\n0x4013E0C0 WRITE   3561978\n0x4013E100 WRITE   3562061\n0x4013E140 WRITE   3562117\n0x4013E180 WRITE   3562180\n0x4013E1C0 WRITE   3562236\n0x40198180 WRITE   3562292\n0x40198140 WRITE   3562294\n0x4013E200 WRITE   3562330\n0x4013E240 WRITE   3562386\n0x4013E280 WRITE   3562449\n0x4013E2C0 WRITE   3562505\n0x4013E300 WRITE   3562583\n0x4013E340 WRITE   3562639\n0x4013E380 WRITE   3562702\n0x4013E3C0 WRITE   3562758\n0x40198300 WRITE   3562819\n0x401982C0 WRITE   3562821\n0x40198280 WRITE   3562828\n0x40198240 WRITE   3562830\n0x4013E400 WRITE   3562863\n0x4013E440 WRITE   3562919\n0x4013E480 WRITE   3562993\n0x4013E4C0 WRITE   3563049\n0x4013E500 WRITE   3563140\n0x4013E540 WRITE   3563196\n0x4013E580 WRITE   3563267\n0x4013E5C0 WRITE   3563323\n0x40198380 WRITE   3563387\n0x40198340 WRITE   3563389\n0x4013E600 WRITE   3563425\n0x4013E640 WRITE   3563481\n0x4013E680 WRITE   3563552\n0x4013E6C0 WRITE   3563608\n0x4013E700 WRITE   3563694\n0x4013E740 WRITE   3563750\n0x4013E780 WRITE   3563821\n0x4013E7C0 WRITE   3563877\n0x40198600 WRITE   3563946\n0x401985C0 WRITE   3563948\n0x40198500 WRITE   3563955\n0x401984C0 WRITE   3563957\n0x40198480 WRITE   3563967\n0x40198440 WRITE   3563969\n0x4013E800 WRITE   3563996\n0x4013E840 WRITE   3564052\n0x4013E880 WRITE   3564118\n0x4013E8C0 WRITE   3564174\n0x4013E900 WRITE   3564261\n0x4013E940 WRITE   3564317\n0x4013E980 WRITE   3564380\n0x4013E9C0 WRITE   3564436\n0x40198580 WRITE   3564498\n0x40198540 WRITE   3564500\n0x4013EA00 WRITE   3564536\n0x4013EA40 WRITE   3564592\n0x4013EA80 WRITE   3564655\n0x4013EAC0 WRITE   3564711\n0x4013EB00 WRITE   3564793\n0x4013EB40 WRITE   3564849\n0x4013EB80 WRITE   3564912\n0x4013EBC0 WRITE   3564968\n0x40198700 WRITE   3565034\n0x401986C0 WRITE   3565036\n0x40198680 WRITE   3565043\n0x40198640 WRITE   3565045\n0x4013EC00 WRITE   3565078\n0x4013EC40 WRITE   3565134\n0x4013EC80 WRITE   3565208\n0x4013ECC0 WRITE   3565264\n0x4013ED00 WRITE   3565359\n0x4013ED40 WRITE   3565415\n0x4013ED80 WRITE   3565486\n0x4013EDC0 WRITE   3565542\n0x40198780 WRITE   3565612\n0x40198740 WRITE   3565614\n0x4013EE00 WRITE   3565650\n0x4013EE40 WRITE   3565706\n0x4013EE80 WRITE   3565777\n0x4013EEC0 WRITE   3565833\n0x4013EF00 WRITE   3565923\n0x4013EF40 WRITE   3565979\n0x4013EF80 WRITE   3566050\n0x4013EFC0 WRITE   3566106\n0x40198C00 WRITE   3566186\n0x40198BC0 WRITE   3566188\n0x40198A00 WRITE   3566195\n0x401989C0 WRITE   3566197\n0x40198900 WRITE   3566207\n0x401988C0 WRITE   3566209\n0x40198880 WRITE   3566214\n0x40198840 WRITE   3566217\n0x4013F000 WRITE   3566242\n0x4013F040 WRITE   3566326\n0x4013F080 WRITE   3566392\n0x4013F0C0 WRITE   3566448\n0x4013F100 WRITE   3566531\n0x4013F140 WRITE   3566587\n0x4013F180 WRITE   3566650\n0x4013F1C0 WRITE   3566706\n0x40198980 WRITE   3566770\n0x40198940 WRITE   3566772\n0x4013F200 WRITE   3566808\n0x4013F240 WRITE   3566864\n0x4013F280 WRITE   3566927\n0x4013F2C0 WRITE   3566983\n0x4013F300 WRITE   3567061\n0x4013F340 WRITE   3567117\n0x4013F380 WRITE   3567180\n0x4013F3C0 WRITE   3567236\n0x40198B00 WRITE   3567304\n0x40198AC0 WRITE   3567306\n0x40198A80 WRITE   3567313\n0x40198A40 WRITE   3567315\n0x4013F400 WRITE   3567348\n0x4013F440 WRITE   3567404\n0x4013F480 WRITE   3567478\n0x4013F4C0 WRITE   3567534\n0x4013F500 WRITE   3567625\n0x4013F540 WRITE   3567681\n0x4013F580 WRITE   3567752\n0x4013F5C0 WRITE   3567808\n0x40198B80 WRITE   3567880\n0x40198B40 WRITE   3567882\n0x4013F600 WRITE   3567918\n0x4013F640 WRITE   3567974\n0x4013F680 WRITE   3568045\n0x4013F6C0 WRITE   3568101\n0x4013F700 WRITE   3568187\n0x4013F740 WRITE   3568243\n0x4013F780 WRITE   3568314\n0x4013F7C0 WRITE   3568370\n0x40198E00 WRITE   3568447\n0x40198DC0 WRITE   3568449\n0x40198D00 WRITE   3568456\n0x40198CC0 WRITE   3568458\n0x40198C80 WRITE   3568468\n0x40198C40 WRITE   3568470\n0x4013F800 WRITE   3568497\n0x4013F840 WRITE   3568553\n0x4013F880 WRITE   3568619\n0x4013F8C0 WRITE   3568675\n0x4013F900 WRITE   3568762\n0x4013F940 WRITE   3568818\n0x4013F980 WRITE   3568881\n0x4013F9C0 WRITE   3568937\n0x40198D80 WRITE   3569006\n0x40198D40 WRITE   3569008\n0x4013FA00 WRITE   3569044\n0x4013FA40 WRITE   3569100\n0x4013FA80 WRITE   3569163\n0x4013FAC0 WRITE   3569219\n0x4013FB00 WRITE   3569301\n0x4013FB40 WRITE   3569357\n0x4013FB80 WRITE   3569420\n0x4013FBC0 WRITE   3569476\n0x40198F00 WRITE   3569549\n0x40198EC0 WRITE   3569551\n0x40198E80 WRITE   3569558\n0x40198E40 WRITE   3569560\n0x4013FC00 WRITE   3569593\n0x4013FC40 WRITE   3569649\n0x4013FC80 WRITE   3569723\n0x4013FCC0 WRITE   3569779\n0x4013FD00 WRITE   3569874\n0x4013FD40 WRITE   3569930\n0x4013FD80 WRITE   3570001\n0x4013FDC0 WRITE   3570057\n0x40198F80 WRITE   3570134\n0x40198F40 WRITE   3570136\n0x4013FE00 WRITE   3570172\n0x4013FE40 WRITE   3570228\n0x4013FE80 WRITE   3570299\n0x4013FEC0 WRITE   3570355\n0x4013FF00 WRITE   3570445\n0x4013FF40 WRITE   3570501\n0x4013FF80 WRITE   3570572\n0x4013FFC0 WRITE   3570628\n0x40199800 WRITE   3570714\n0x401997C0 WRITE   3570716\n0x40199400 WRITE   3570723\n0x401993C0 WRITE   3570725\n0x40199200 WRITE   3570735\n0x401991C0 WRITE   3570737\n0x40199100 WRITE   3570742\n0x401990C0 WRITE   3570745\n0x40199080 WRITE   3570748\n0x40199040 WRITE   3570751\n0x40140000 WRITE   3570776\n0x40140040 WRITE   3570860\n0x40140080 WRITE   3570926\n0x401400C0 WRITE   3570982\n0x40140100 WRITE   3571065\n0x40140140 WRITE   3571121\n0x40140180 WRITE   3571184\n0x401401C0 WRITE   3571240\n0x40199180 WRITE   3571296\n0x40199140 WRITE   3571298\n0x40140200 WRITE   3571334\n0x40140240 WRITE   3571390\n0x40140280 WRITE   3571453\n0x401402C0 WRITE   3571509\n0x40140300 WRITE   3571587\n0x40140340 WRITE   3571643\n0x40140380 WRITE   3571706\n0x401403C0 WRITE   3571762\n0x40199300 WRITE   3571828\n0x401992C0 WRITE   3571830\n0x40199280 WRITE   3571837\n0x40199240 WRITE   3571839\n0x40140400 WRITE   3571872\n0x40140440 WRITE   3571928\n0x40140480 WRITE   3572002\n0x401404C0 WRITE   3572058\n0x40140500 WRITE   3572149\n0x40140540 WRITE   3572205\n0x40140580 WRITE   3572276\n0x401405C0 WRITE   3572332\n0x40199380 WRITE   3572396\n0x40199340 WRITE   3572398\n0x40140600 WRITE   3572434\n0x40140640 WRITE   3572490\n0x40140680 WRITE   3572561\n0x401406C0 WRITE   3572617\n0x40140700 WRITE   3572703\n0x40140740 WRITE   3572759\n0x40140780 WRITE   3572830\n0x401407C0 WRITE   3572886\n0x40199600 WRITE   3572961\n0x401995C0 WRITE   3572963\n0x40199500 WRITE   3572970\n0x401994C0 WRITE   3572972\n0x40199480 WRITE   3572982\n0x40199440 WRITE   3572984\n0x40140800 WRITE   3573011\n0x40140840 WRITE   3573067\n0x40140880 WRITE   3573133\n0x401408C0 WRITE   3573189\n0x40140900 WRITE   3573276\n0x40140940 WRITE   3573332\n0x40140980 WRITE   3573395\n0x401409C0 WRITE   3573451\n0x40199580 WRITE   3573513\n0x40199540 WRITE   3573515\n0x40140A00 WRITE   3573551\n0x40140A40 WRITE   3573607\n0x40140A80 WRITE   3573670\n0x40140AC0 WRITE   3573726\n0x40140B00 WRITE   3573808\n0x40140B40 WRITE   3573864\n0x40140B80 WRITE   3573927\n0x40140BC0 WRITE   3573983\n0x40199700 WRITE   3574055\n0x401996C0 WRITE   3574057\n0x40199680 WRITE   3574064\n0x40199640 WRITE   3574066\n0x40140C00 WRITE   3574099\n0x40140C40 WRITE   3574155\n0x40140C80 WRITE   3574229\n0x40140CC0 WRITE   3574285\n0x40140D00 WRITE   3574380\n0x40140D40 WRITE   3574436\n0x40140D80 WRITE   3574507\n0x40140DC0 WRITE   3574563\n0x40199780 WRITE   3574633\n0x40199740 WRITE   3574635\n0x40140E00 WRITE   3574671\n0x40140E40 WRITE   3574727\n0x40140E80 WRITE   3574798\n0x40140EC0 WRITE   3574854\n0x40140F00 WRITE   3574944\n0x40140F40 WRITE   3575000\n0x40140F80 WRITE   3575071\n0x40140FC0 WRITE   3575127\n0x40199C00 WRITE   3575213\n0x40199BC0 WRITE   3575215\n0x40199A00 WRITE   3575222\n0x401999C0 WRITE   3575224\n0x40199900 WRITE   3575234\n0x401998C0 WRITE   3575236\n0x40199880 WRITE   3575241\n0x40199840 WRITE   3575244\n0x40141000 WRITE   3575269\n0x40141040 WRITE   3575353\n0x40141080 WRITE   3575419\n0x401410C0 WRITE   3575475\n0x40141100 WRITE   3575558\n0x40141140 WRITE   3575614\n0x40141180 WRITE   3575677\n0x401411C0 WRITE   3575733\n0x40199980 WRITE   3575797\n0x40199940 WRITE   3575799\n0x40141200 WRITE   3575835\n0x40141240 WRITE   3575891\n0x40141280 WRITE   3575954\n0x401412C0 WRITE   3576010\n0x40141300 WRITE   3576088\n0x40141340 WRITE   3576144\n0x40141380 WRITE   3576207\n0x401413C0 WRITE   3576263\n0x40199B00 WRITE   3576337\n0x40199AC0 WRITE   3576339\n0x40199A80 WRITE   3576346\n0x40199A40 WRITE   3576348\n0x40141400 WRITE   3576381\n0x40141440 WRITE   3576437\n0x40141480 WRITE   3576511\n0x401414C0 WRITE   3576567\n0x40141500 WRITE   3576658\n0x40141540 WRITE   3576714\n0x40141580 WRITE   3576785\n0x401415C0 WRITE   3576841\n0x40199B80 WRITE   3576913\n0x40199B40 WRITE   3576915\n0x40141600 WRITE   3576951\n0x40141640 WRITE   3577007\n0x40141680 WRITE   3577078\n0x401416C0 WRITE   3577134\n0x40141700 WRITE   3577220\n0x40141740 WRITE   3577276\n0x40141780 WRITE   3577347\n0x401417C0 WRITE   3577403\n0x40199E00 WRITE   3577486\n0x40199DC0 WRITE   3577488\n0x40199D00 WRITE   3577495\n0x40199CC0 WRITE   3577497\n0x40199C80 WRITE   3577507\n0x40199C40 WRITE   3577509\n0x40141800 WRITE   3577536\n0x40141840 WRITE   3577592\n0x40141880 WRITE   3577658\n0x401418C0 WRITE   3577714\n0x40141900 WRITE   3577801\n0x40141940 WRITE   3577857\n0x40141980 WRITE   3577920\n0x401419C0 WRITE   3577976\n0x40199D80 WRITE   3578045\n0x40199D40 WRITE   3578047\n0x40141A00 WRITE   3578083\n0x40141A40 WRITE   3578139\n0x40141A80 WRITE   3578202\n0x40141AC0 WRITE   3578258\n0x40141B00 WRITE   3578340\n0x40141B40 WRITE   3578396\n0x40141B80 WRITE   3578459\n0x40141BC0 WRITE   3578515\n0x40199F00 WRITE   3578594\n0x40199EC0 WRITE   3578596\n0x40199E80 WRITE   3578603\n0x40199E40 WRITE   3578605\n0x40141C00 WRITE   3578638\n0x40141C40 WRITE   3578694\n0x40141C80 WRITE   3578768\n0x40141CC0 WRITE   3578824\n0x40141D00 WRITE   3578919\n0x40141D40 WRITE   3578975\n0x40141D80 WRITE   3579046\n0x40141DC0 WRITE   3579102\n0x40199F80 WRITE   3579179\n0x40199F40 WRITE   3579181\n0x40141E00 WRITE   3579217\n0x40141E40 WRITE   3579273\n0x40141E80 WRITE   3579344\n0x40141EC0 WRITE   3579400\n0x40141F00 WRITE   3579490\n0x40141F40 WRITE   3579546\n0x40141F80 WRITE   3579617\n0x40141FC0 WRITE   3579673\n0x4019BFC0 WRITE   3579835\n0x4019C000 WRITE   3579867\n0x4019B000 WRITE   3580027\n0x4019AFC0 WRITE   3580029\n0x4019A800 WRITE   3580036\n0x4019A7C0 WRITE   3580038\n0x4019A400 WRITE   3580048\n0x4019A3C0 WRITE   3580050\n0x4019A200 WRITE   3580055\n0x4019A1C0 WRITE   3580058\n0x4019A100 WRITE   3580061\n0x4019A0C0 WRITE   3580064\n0x4019A080 WRITE   3580067\n0x4019A040 WRITE   3580070\n0x40142000 WRITE   3580102\n0x40142040 WRITE   3580190\n0x40142080 WRITE   3580256\n0x401420C0 WRITE   3580312\n0x40142100 WRITE   3580395\n0x40142140 WRITE   3580451\n0x40142180 WRITE   3580514\n0x401421C0 WRITE   3580570\n0x4019A180 WRITE   3580626\n0x4019A140 WRITE   3580628\n0x40142200 WRITE   3580664\n0x40142240 WRITE   3580720\n0x40142280 WRITE   3580783\n0x401422C0 WRITE   3580839\n0x40142300 WRITE   3580917\n0x40142340 WRITE   3580973\n0x40142380 WRITE   3581036\n0x401423C0 WRITE   3581092\n0x4019A300 WRITE   3581153\n0x4019A2C0 WRITE   3581155\n0x4019A280 WRITE   3581162\n0x4019A240 WRITE   3581164\n0x40142400 WRITE   3581197\n0x40142440 WRITE   3581253\n0x40142480 WRITE   3581327\n0x401424C0 WRITE   3581383\n0x40142500 WRITE   3581474\n0x40142540 WRITE   3581530\n0x40142580 WRITE   3581601\n0x401425C0 WRITE   3581657\n0x4019A380 WRITE   3581721\n0x4019A340 WRITE   3581723\n0x40142600 WRITE   3581759\n0x40142640 WRITE   3581815\n0x40142680 WRITE   3581886\n0x401426C0 WRITE   3581942\n0x40142700 WRITE   3582028\n0x40142740 WRITE   3582084\n0x40142780 WRITE   3582155\n0x401427C0 WRITE   3582211\n0x4019A600 WRITE   3582280\n0x4019A5C0 WRITE   3582282\n0x4019A500 WRITE   3582289\n0x4019A4C0 WRITE   3582291\n0x4019A480 WRITE   3582301\n0x4019A440 WRITE   3582303\n0x40142800 WRITE   3582330\n0x40142840 WRITE   3582386\n0x40142880 WRITE   3582452\n0x401428C0 WRITE   3582508\n0x40142900 WRITE   3582595\n0x40142940 WRITE   3582651\n0x40142980 WRITE   3582714\n0x401429C0 WRITE   3582770\n0x4019A580 WRITE   3582832\n0x4019A540 WRITE   3582834\n0x40142A00 WRITE   3582870\n0x40142A40 WRITE   3582926\n0x40142A80 WRITE   3582989\n0x40142AC0 WRITE   3583045\n0x40142B00 WRITE   3583127\n0x40142B40 WRITE   3583183\n0x40142B80 WRITE   3583246\n0x40142BC0 WRITE   3583302\n0x4019A700 WRITE   3583368\n0x4019A6C0 WRITE   3583370\n0x4019A680 WRITE   3583377\n0x4019A640 WRITE   3583379\n0x40142C00 WRITE   3583412\n0x40142C40 WRITE   3583468\n0x40142C80 WRITE   3583542\n0x40142CC0 WRITE   3583598\n0x40142D00 WRITE   3583693\n0x40142D40 WRITE   3583749\n0x40142D80 WRITE   3583820\n0x40142DC0 WRITE   3583876\n0x4019A780 WRITE   3583946\n0x4019A740 WRITE   3583948\n0x40142E00 WRITE   3583984\n0x40142E40 WRITE   3584040\n0x40142E80 WRITE   3584111\n0x40142EC0 WRITE   3584167\n0x40142F00 WRITE   3584257\n0x40142F40 WRITE   3584313\n0x40142F80 WRITE   3584384\n0x40142FC0 WRITE   3584440\n0x4019AC00 WRITE   3584520\n0x4019ABC0 WRITE   3584522\n0x4019AA00 WRITE   3584529\n0x4019A9C0 WRITE   3584531\n0x4019A900 WRITE   3584541\n0x4019A8C0 WRITE   3584543\n0x4019A880 WRITE   3584548\n0x4019A840 WRITE   3584551\n0x40143000 WRITE   3584576\n0x40143040 WRITE   3584660\n0x40143080 WRITE   3584726\n0x401430C0 WRITE   3584782\n0x40143100 WRITE   3584865\n0x40143140 WRITE   3584921\n0x40143180 WRITE   3584984\n0x401431C0 WRITE   3585040\n0x4019A980 WRITE   3585104\n0x4019A940 WRITE   3585106\n0x40143200 WRITE   3585142\n0x40143240 WRITE   3585198\n0x40143280 WRITE   3585261\n0x401432C0 WRITE   3585317\n0x40143300 WRITE   3585395\n0x40143340 WRITE   3585451\n0x40143380 WRITE   3585514\n0x401433C0 WRITE   3585570\n0x4019AB00 WRITE   3585638\n0x4019AAC0 WRITE   3585640\n0x4019AA80 WRITE   3585647\n0x4019AA40 WRITE   3585649\n0x40143400 WRITE   3585682\n0x40143440 WRITE   3585738\n0x40143480 WRITE   3585812\n0x401434C0 WRITE   3585868\n0x40143500 WRITE   3585959\n0x40143540 WRITE   3586015\n0x40143580 WRITE   3586086\n0x401435C0 WRITE   3586142\n0x4019AB80 WRITE   3586214\n0x4019AB40 WRITE   3586216\n0x40143600 WRITE   3586252\n0x40143640 WRITE   3586308\n0x40143680 WRITE   3586379\n0x401436C0 WRITE   3586435\n0x40143700 WRITE   3586521\n0x40143740 WRITE   3586577\n0x40143780 WRITE   3586648\n0x401437C0 WRITE   3586704\n0x4019AE00 WRITE   3586781\n0x4019ADC0 WRITE   3586783\n0x4019AD00 WRITE   3586790\n0x4019ACC0 WRITE   3586792\n0x4019AC80 WRITE   3586802\n0x4019AC40 WRITE   3586804\n0x40143800 WRITE   3586831\n0x40143840 WRITE   3586887\n0x40143880 WRITE   3586953\n0x401438C0 WRITE   3587009\n0x40143900 WRITE   3587096\n0x40143940 WRITE   3587152\n0x40143980 WRITE   3587215\n0x401439C0 WRITE   3587271\n0x4019AD80 WRITE   3587340\n0x4019AD40 WRITE   3587342\n0x40143A00 WRITE   3587378\n0x40143A40 WRITE   3587434\n0x40143A80 WRITE   3587497\n0x40143AC0 WRITE   3587553\n0x40143B00 WRITE   3587635\n0x40143B40 WRITE   3587691\n0x40143B80 WRITE   3587754\n0x40143BC0 WRITE   3587810\n0x4019AF00 WRITE   3587883\n0x4019AEC0 WRITE   3587885\n0x4019AE80 WRITE   3587892\n0x4019AE40 WRITE   3587894\n0x40143C00 WRITE   3587927\n0x40143C40 WRITE   3587983\n0x40143C80 WRITE   3588057\n0x40143CC0 WRITE   3588113\n0x40143D00 WRITE   3588208\n0x40143D40 WRITE   3588264\n0x40143D80 WRITE   3588335\n0x40143DC0 WRITE   3588391\n0x4019AF80 WRITE   3588468\n0x4019AF40 WRITE   3588470\n0x40143E00 WRITE   3588506\n0x40143E40 WRITE   3588562\n0x40143E80 WRITE   3588633\n0x40143EC0 WRITE   3588689\n0x40143F00 WRITE   3588779\n0x40143F40 WRITE   3588835\n0x40143F80 WRITE   3588906\n0x40143FC0 WRITE   3588962\n0x4019B800 WRITE   3589048\n0x4019B7C0 WRITE   3589050\n0x4019B400 WRITE   3589057\n0x4019B3C0 WRITE   3589059\n0x4019B200 WRITE   3589069\n0x4019B1C0 WRITE   3589071\n0x4019B100 WRITE   3589076\n0x4019B0C0 WRITE   3589079\n0x4019B080 WRITE   3589082\n0x4019B040 WRITE   3589085\n0x40144000 WRITE   3589110\n0x40144040 WRITE   3589194\n0x40144080 WRITE   3589260\n0x401440C0 WRITE   3589316\n0x40144100 WRITE   3589399\n0x40144140 WRITE   3589455\n0x40144180 WRITE   3589518\n0x401441C0 WRITE   3589574\n0x4019B180 WRITE   3589630\n0x4019B140 WRITE   3589632\n0x40144200 WRITE   3589668\n0x40144240 WRITE   3589724\n0x40144280 WRITE   3589787\n0x401442C0 WRITE   3589843\n0x40144300 WRITE   3589921\n0x40144340 WRITE   3589977\n0x40144380 WRITE   3590040\n0x401443C0 WRITE   3590096\n0x4019B300 WRITE   3590162\n0x4019B2C0 WRITE   3590164\n0x4019B280 WRITE   3590171\n0x4019B240 WRITE   3590173\n0x40144400 WRITE   3590206\n0x40144440 WRITE   3590262\n0x40144480 WRITE   3590336\n0x401444C0 WRITE   3590392\n0x40144500 WRITE   3590483\n0x40144540 WRITE   3590539\n0x40144580 WRITE   3590610\n0x401445C0 WRITE   3590666\n0x4019B380 WRITE   3590730\n0x4019B340 WRITE   3590732\n0x40144600 WRITE   3590768\n0x40144640 WRITE   3590824\n0x40144680 WRITE   3590895\n0x401446C0 WRITE   3590951\n0x40144700 WRITE   3591037\n0x40144740 WRITE   3591093\n0x40144780 WRITE   3591164\n0x401447C0 WRITE   3591220\n0x4019B600 WRITE   3591295\n0x4019B5C0 WRITE   3591297\n0x4019B500 WRITE   3591304\n0x4019B4C0 WRITE   3591306\n0x4019B480 WRITE   3591316\n0x4019B440 WRITE   3591318\n0x40144800 WRITE   3591345\n0x40144840 WRITE   3591401\n0x40144880 WRITE   3591467\n0x401448C0 WRITE   3591523\n0x40144900 WRITE   3591610\n0x40144940 WRITE   3591666\n0x40144980 WRITE   3591729\n0x401449C0 WRITE   3591785\n0x4019B580 WRITE   3591847\n0x4019B540 WRITE   3591849\n0x40144A00 WRITE   3591885\n0x40144A40 WRITE   3591941\n0x40144A80 WRITE   3592004\n0x40144AC0 WRITE   3592060\n0x40144B00 WRITE   3592142\n0x40144B40 WRITE   3592198\n0x40144B80 WRITE   3592261\n0x40144BC0 WRITE   3592317\n0x4019B700 WRITE   3592389\n0x4019B6C0 WRITE   3592391\n0x4019B680 WRITE   3592398\n0x4019B640 WRITE   3592400\n0x40144C00 WRITE   3592433\n0x40144C40 WRITE   3592489\n0x40144C80 WRITE   3592563\n0x40144CC0 WRITE   3592619\n0x40144D00 WRITE   3592714\n0x40144D40 WRITE   3592770\n0x40144D80 WRITE   3592841\n0x40144DC0 WRITE   3592897\n0x4019B780 WRITE   3592967\n0x4019B740 WRITE   3592969\n0x40144E00 WRITE   3593005\n0x40144E40 WRITE   3593061\n0x40144E80 WRITE   3593132\n0x40144EC0 WRITE   3593188\n0x40144F00 WRITE   3593278\n0x40144F40 WRITE   3593334\n0x40144F80 WRITE   3593405\n0x40144FC0 WRITE   3593461\n0x4019BC00 WRITE   3593547\n0x4019BBC0 WRITE   3593549\n0x4019BA00 WRITE   3593556\n0x4019B9C0 WRITE   3593558\n0x4019B900 WRITE   3593568\n0x4019B8C0 WRITE   3593570\n0x4019B880 WRITE   3593575\n0x4019B840 WRITE   3593578\n0x40145000 WRITE   3593603\n0x40145040 WRITE   3593687\n0x40145080 WRITE   3593753\n0x401450C0 WRITE   3593809\n0x40145100 WRITE   3593892\n0x40145140 WRITE   3593948\n0x40145180 WRITE   3594011\n0x401451C0 WRITE   3594067\n0x4019B980 WRITE   3594131\n0x4019B940 WRITE   3594133\n0x40145200 WRITE   3594169\n0x40145240 WRITE   3594225\n0x40145280 WRITE   3594288\n0x401452C0 WRITE   3594344\n0x40145300 WRITE   3594422\n0x40145340 WRITE   3594478\n0x40145380 WRITE   3594541\n0x401453C0 WRITE   3594597\n0x4019BB00 WRITE   3594671\n0x4019BAC0 WRITE   3594673\n0x4019BA80 WRITE   3594680\n0x4019BA40 WRITE   3594682\n0x40145400 WRITE   3594715\n0x40145440 WRITE   3594771\n0x40145480 WRITE   3594845\n0x401454C0 WRITE   3594901\n0x40145500 WRITE   3594992\n0x40145540 WRITE   3595048\n0x40145580 WRITE   3595119\n0x401455C0 WRITE   3595175\n0x4019BB80 WRITE   3595247\n0x4019BB40 WRITE   3595249\n0x40145600 WRITE   3595285\n0x40145640 WRITE   3595341\n0x40145680 WRITE   3595412\n0x401456C0 WRITE   3595468\n0x40145700 WRITE   3595554\n0x40145740 WRITE   3595610\n0x40145780 WRITE   3595681\n0x401457C0 WRITE   3595737\n0x4019BE00 WRITE   3595820\n0x4019BDC0 WRITE   3595822\n0x4019BD00 WRITE   3595829\n0x4019BCC0 WRITE   3595831\n0x4019BC80 WRITE   3595841\n0x4019BC40 WRITE   3595843\n0x40145800 WRITE   3595870\n0x40145840 WRITE   3595926\n0x40145880 WRITE   3595992\n0x401458C0 WRITE   3596048\n0x40145900 WRITE   3596135\n0x40145940 WRITE   3596191\n0x40145980 WRITE   3596254\n0x401459C0 WRITE   3596310\n0x4019BD80 WRITE   3596379\n0x4019BD40 WRITE   3596381\n0x40145A00 WRITE   3596417\n0x40145A40 WRITE   3596473\n0x40145A80 WRITE   3596536\n0x40145AC0 WRITE   3596592\n0x40145B00 WRITE   3596674\n0x40145B40 WRITE   3596730\n0x40145B80 WRITE   3596793\n0x40145BC0 WRITE   3596849\n0x4019BF00 WRITE   3596928\n0x4019BEC0 WRITE   3596930\n0x4019BE80 WRITE   3596937\n0x4019BE40 WRITE   3596939\n0x40145C00 WRITE   3596972\n0x40145C40 WRITE   3597028\n0x40145C80 WRITE   3597102\n0x40145CC0 WRITE   3597158\n0x40145D00 WRITE   3597253\n0x40145D40 WRITE   3597309\n0x40145D80 WRITE   3597380\n0x40145DC0 WRITE   3597436\n0x4019BF80 WRITE   3597513\n0x4019BF40 WRITE   3597515\n0x40145E00 WRITE   3597551\n0x40145E40 WRITE   3597607\n0x40145E80 WRITE   3597678\n0x40145EC0 WRITE   3597734\n0x40145F00 WRITE   3597824\n0x40145F40 WRITE   3597880\n0x40145F80 WRITE   3597951\n0x40145FC0 WRITE   3598007\n0x4019DFC0 WRITE   3598169\n0x4019E000 WRITE   3598201\n0x4019D000 WRITE   3598328\n0x4019CFC0 WRITE   3598330\n0x4019C800 WRITE   3598337\n0x4019C7C0 WRITE   3598339\n0x4019C400 WRITE   3598349\n0x4019C3C0 WRITE   3598351\n0x4019C200 WRITE   3598356\n0x4019C1C0 WRITE   3598359\n0x4019C100 WRITE   3598362\n0x4019C0C0 WRITE   3598365\n0x4019C080 WRITE   3598368\n0x4019C040 WRITE   3598371\n0x40146000 WRITE   3598403\n0x40146040 WRITE   3598491\n0x40146080 WRITE   3598557\n0x401460C0 WRITE   3598613\n0x40146100 WRITE   3598696\n0x40146140 WRITE   3598752\n0x40146180 WRITE   3598815\n0x401461C0 WRITE   3598871\n0x4019C180 WRITE   3598927\n0x4019C140 WRITE   3598929\n0x40146200 WRITE   3598965\n0x40146240 WRITE   3599021\n0x40146280 WRITE   3599084\n0x401462C0 WRITE   3599140\n0x40146300 WRITE   3599218\n0x40146340 WRITE   3599274\n0x40146380 WRITE   3599337\n0x401463C0 WRITE   3599393\n0x4019C300 WRITE   3599454\n0x4019C2C0 WRITE   3599456\n0x4019C280 WRITE   3599463\n0x4019C240 WRITE   3599465\n0x40146400 WRITE   3599498\n0x40146440 WRITE   3599554\n0x40146480 WRITE   3599628\n0x401464C0 WRITE   3599684\n0x40146500 WRITE   3599775\n0x40146540 WRITE   3599831\n0x40146580 WRITE   3599902\n0x401465C0 WRITE   3599958\n0x4019C380 WRITE   3600022\n0x4019C340 WRITE   3600024\n0x40146600 WRITE   3600060\n0x40146640 WRITE   3600116\n0x40146680 WRITE   3600187\n0x401466C0 WRITE   3600243\n0x40146700 WRITE   3600329\n0x40146740 WRITE   3600385\n0x40146780 WRITE   3600456\n0x401467C0 WRITE   3600512\n0x4019C600 WRITE   3600581\n0x4019C5C0 WRITE   3600583\n0x4019C500 WRITE   3600590\n0x4019C4C0 WRITE   3600592\n0x4019C480 WRITE   3600602\n0x4019C440 WRITE   3600604\n0x40146800 WRITE   3600631\n0x40146840 WRITE   3600687\n0x40146880 WRITE   3600753\n0x401468C0 WRITE   3600809\n0x40146900 WRITE   3600896\n0x40146940 WRITE   3600952\n0x40146980 WRITE   3601015\n0x401469C0 WRITE   3601071\n0x4019C580 WRITE   3601133\n0x4019C540 WRITE   3601135\n0x40146A00 WRITE   3601171\n0x40146A40 WRITE   3601227\n0x40146A80 WRITE   3601290\n0x40146AC0 WRITE   3601346\n0x40146B00 WRITE   3601428\n0x40146B40 WRITE   3601484\n0x40146B80 WRITE   3601547\n0x40146BC0 WRITE   3601603\n0x4019C700 WRITE   3601669\n0x4019C6C0 WRITE   3601671\n0x4019C680 WRITE   3601678\n0x4019C640 WRITE   3601680\n0x40146C00 WRITE   3601713\n0x40146C40 WRITE   3601769\n0x40146C80 WRITE   3601843\n0x40146CC0 WRITE   3601899\n0x40146D00 WRITE   3601994\n0x40146D40 WRITE   3602050\n0x40146D80 WRITE   3602121\n0x40146DC0 WRITE   3602177\n0x4019C780 WRITE   3602247\n0x4019C740 WRITE   3602249\n0x40146E00 WRITE   3602285\n0x40146E40 WRITE   3602341\n0x40146E80 WRITE   3602412\n0x40146EC0 WRITE   3602468\n0x40146F00 WRITE   3602558\n0x40146F40 WRITE   3602614\n0x40146F80 WRITE   3602685\n0x40146FC0 WRITE   3602741\n0x4019CC00 WRITE   3602821\n0x4019CBC0 WRITE   3602823\n0x4019CA00 WRITE   3602830\n0x4019C9C0 WRITE   3602832\n0x4019C900 WRITE   3602842\n0x4019C8C0 WRITE   3602844\n0x4019C880 WRITE   3602849\n0x4019C840 WRITE   3602852\n0x40147000 WRITE   3602877\n0x40147040 WRITE   3602961\n0x40147080 WRITE   3603027\n0x401470C0 WRITE   3603083\n0x40147100 WRITE   3603166\n0x40147140 WRITE   3603222\n0x40147180 WRITE   3603285\n0x401471C0 WRITE   3603341\n0x4019C980 WRITE   3603405\n0x4019C940 WRITE   3603407\n0x40147200 WRITE   3603443\n0x40147240 WRITE   3603499\n0x40147280 WRITE   3603562\n0x401472C0 WRITE   3603618\n0x40147300 WRITE   3603696\n0x40147340 WRITE   3603752\n0x40147380 WRITE   3603815\n0x401473C0 WRITE   3603871\n0x4019CB00 WRITE   3603939\n0x4019CAC0 WRITE   3603941\n0x4019CA80 WRITE   3603948\n0x4019CA40 WRITE   3603950\n0x40147400 WRITE   3603983\n0x40147440 WRITE   3604039\n0x40147480 WRITE   3604113\n0x401474C0 WRITE   3604169\n0x40147500 WRITE   3604260\n0x40147540 WRITE   3604316\n0x40147580 WRITE   3604387\n0x401475C0 WRITE   3604443\n0x4019CB80 WRITE   3604515\n0x4019CB40 WRITE   3604517\n0x40147600 WRITE   3604553\n0x40147640 WRITE   3604609\n0x40147680 WRITE   3604680\n0x401476C0 WRITE   3604736\n0x40147700 WRITE   3604822\n0x40147740 WRITE   3604878\n0x40147780 WRITE   3604949\n0x401477C0 WRITE   3605005\n0x4019CE00 WRITE   3605082\n0x4019CDC0 WRITE   3605084\n0x4019CD00 WRITE   3605091\n0x4019CCC0 WRITE   3605093\n0x4019CC80 WRITE   3605103\n0x4019CC40 WRITE   3605105\n0x40147800 WRITE   3605132\n0x40147840 WRITE   3605188\n0x40147880 WRITE   3605254\n0x401478C0 WRITE   3605310\n0x40147900 WRITE   3605397\n0x40147940 WRITE   3605453\n0x40147980 WRITE   3605516\n0x401479C0 WRITE   3605572\n0x4019CD80 WRITE   3605641\n0x4019CD40 WRITE   3605643\n0x40147A00 WRITE   3605679\n0x40147A40 WRITE   3605735\n0x40147A80 WRITE   3605798\n0x40147AC0 WRITE   3605854\n0x40147B00 WRITE   3605936\n0x40147B40 WRITE   3605992\n0x40147B80 WRITE   3606055\n0x40147BC0 WRITE   3606111\n0x4019CF00 WRITE   3606184\n0x4019CEC0 WRITE   3606186\n0x4019CE80 WRITE   3606193\n0x4019CE40 WRITE   3606195\n0x40147C00 WRITE   3606228\n0x40147C40 WRITE   3606284\n0x40147C80 WRITE   3606358\n0x40147CC0 WRITE   3606414\n0x40147D00 WRITE   3606509\n0x40147D40 WRITE   3606565\n0x40147D80 WRITE   3606636\n0x40147DC0 WRITE   3606692\n0x4019CF80 WRITE   3606769\n0x4019CF40 WRITE   3606771\n0x40147E00 WRITE   3606807\n0x40147E40 WRITE   3606863\n0x40147E80 WRITE   3606934\n0x40147EC0 WRITE   3606990\n0x40147F00 WRITE   3607080\n0x40147F40 WRITE   3607136\n0x40147F80 WRITE   3607207\n0x40147FC0 WRITE   3607263\n0x4019D800 WRITE   3607349\n0x4019D7C0 WRITE   3607351\n0x4019D400 WRITE   3607358\n0x4019D3C0 WRITE   3607360\n0x4019D200 WRITE   3607370\n0x4019D1C0 WRITE   3607372\n0x4019D100 WRITE   3607377\n0x4019D0C0 WRITE   3607380\n0x4019D080 WRITE   3607383\n0x4019D040 WRITE   3607386\n0x40148000 WRITE   3607411\n0x40148040 WRITE   3607495\n0x40148080 WRITE   3607561\n0x401480C0 WRITE   3607617\n0x40148100 WRITE   3607700\n0x40148140 WRITE   3607756\n0x40148180 WRITE   3607819\n0x401481C0 WRITE   3607875\n0x4019D180 WRITE   3607931\n0x4019D140 WRITE   3607933\n0x40148200 WRITE   3607969\n0x40148240 WRITE   3608025\n0x40148280 WRITE   3608088\n0x401482C0 WRITE   3608144\n0x40148300 WRITE   3608222\n0x40148340 WRITE   3608278\n0x40148380 WRITE   3608341\n0x401483C0 WRITE   3608397\n0x4019D300 WRITE   3608463\n0x4019D2C0 WRITE   3608465\n0x4019D280 WRITE   3608472\n0x4019D240 WRITE   3608474\n0x40148400 WRITE   3608507\n0x40148440 WRITE   3608563\n0x40148480 WRITE   3608637\n0x401484C0 WRITE   3608693\n0x40148500 WRITE   3608784\n0x40148540 WRITE   3608840\n0x40148580 WRITE   3608911\n0x401485C0 WRITE   3608967\n0x4019D380 WRITE   3609031\n0x4019D340 WRITE   3609033\n0x40148600 WRITE   3609069\n0x40148640 WRITE   3609125\n0x40148680 WRITE   3609196\n0x401486C0 WRITE   3609252\n0x40148700 WRITE   3609338\n0x40148740 WRITE   3609394\n0x40148780 WRITE   3609465\n0x401487C0 WRITE   3609521\n0x4019D600 WRITE   3609596\n0x4019D5C0 WRITE   3609598\n0x4019D500 WRITE   3609605\n0x4019D4C0 WRITE   3609607\n0x4019D480 WRITE   3609617\n0x4019D440 WRITE   3609619\n0x40148800 WRITE   3609646\n0x40148840 WRITE   3609702\n0x40148880 WRITE   3609768\n0x401488C0 WRITE   3609824\n0x40148900 WRITE   3609911\n0x40148940 WRITE   3609967\n0x40148980 WRITE   3610030\n0x401489C0 WRITE   3610086\n0x4019D580 WRITE   3610148\n0x4019D540 WRITE   3610150\n0x40148A00 WRITE   3610186\n0x40148A40 WRITE   3610242\n0x40148A80 WRITE   3610305\n0x40148AC0 WRITE   3610361\n0x40148B00 WRITE   3610443\n0x40148B40 WRITE   3610499\n0x40148B80 WRITE   3610562\n0x40148BC0 WRITE   3610618\n0x4019D700 WRITE   3610690\n0x4019D6C0 WRITE   3610692\n0x4019D680 WRITE   3610699\n0x4019D640 WRITE   3610701\n0x40148C00 WRITE   3610734\n0x40148C40 WRITE   3610790\n0x40148C80 WRITE   3610864\n0x40148CC0 WRITE   3610920\n0x40148D00 WRITE   3611015\n0x40148D40 WRITE   3611071\n0x40148D80 WRITE   3611142\n0x40148DC0 WRITE   3611198\n0x4019D780 WRITE   3611268\n0x4019D740 WRITE   3611270\n0x40148E00 WRITE   3611306\n0x40148E40 WRITE   3611362\n0x40148E80 WRITE   3611433\n0x40148EC0 WRITE   3611489\n0x40148F00 WRITE   3611579\n0x40148F40 WRITE   3611635\n0x40148F80 WRITE   3611706\n0x40148FC0 WRITE   3611762\n0x4019DC00 WRITE   3611848\n0x4019DBC0 WRITE   3611850\n0x4019DA00 WRITE   3611857\n0x4019D9C0 WRITE   3611859\n0x4019D900 WRITE   3611869\n0x4019D8C0 WRITE   3611871\n0x4019D880 WRITE   3611876\n0x4019D840 WRITE   3611879\n0x40149000 WRITE   3611904\n0x40149040 WRITE   3611988\n0x40149080 WRITE   3612054\n0x401490C0 WRITE   3612110\n0x40149100 WRITE   3612193\n0x40149140 WRITE   3612249\n0x40149180 WRITE   3612312\n0x401491C0 WRITE   3612368\n0x4019D980 WRITE   3612432\n0x4019D940 WRITE   3612434\n0x40149200 WRITE   3612470\n0x40149240 WRITE   3612526\n0x40149280 WRITE   3612589\n0x401492C0 WRITE   3612645\n0x40149300 WRITE   3612723\n0x40149340 WRITE   3612779\n0x40149380 WRITE   3612842\n0x401493C0 WRITE   3612898\n0x4019DB00 WRITE   3612972\n0x4019DAC0 WRITE   3612974\n0x4019DA80 WRITE   3612981\n0x4019DA40 WRITE   3612983\n0x40149400 WRITE   3613016\n0x40149440 WRITE   3613072\n0x40149480 WRITE   3613146\n0x401494C0 WRITE   3613202\n0x40149500 WRITE   3613293\n0x40149540 WRITE   3613349\n0x40149580 WRITE   3613420\n0x401495C0 WRITE   3613476\n0x4019DB80 WRITE   3613548\n0x4019DB40 WRITE   3613550\n0x40149600 WRITE   3613586\n0x40149640 WRITE   3613642\n0x40149680 WRITE   3613713\n0x401496C0 WRITE   3613769\n0x40149700 WRITE   3613855\n0x40149740 WRITE   3613911\n0x40149780 WRITE   3613982\n0x401497C0 WRITE   3614038\n0x4019DE00 WRITE   3614121\n0x4019DDC0 WRITE   3614123\n0x4019DD00 WRITE   3614130\n0x4019DCC0 WRITE   3614132\n0x4019DC80 WRITE   3614142\n0x4019DC40 WRITE   3614144\n0x40149800 WRITE   3614171\n0x40149840 WRITE   3614227\n0x40149880 WRITE   3614293\n0x401498C0 WRITE   3614349\n0x40149900 WRITE   3614436\n0x40149940 WRITE   3614492\n0x40149980 WRITE   3614555\n0x401499C0 WRITE   3614611\n0x4019DD80 WRITE   3614680\n0x4019DD40 WRITE   3614682\n0x40149A00 WRITE   3614718\n0x40149A40 WRITE   3614774\n0x40149A80 WRITE   3614837\n0x40149AC0 WRITE   3614893\n0x40149B00 WRITE   3614975\n0x40149B40 WRITE   3615031\n0x40149B80 WRITE   3615094\n0x40149BC0 WRITE   3615150\n0x4019DF00 WRITE   3615229\n0x4019DEC0 WRITE   3615231\n0x4019DE80 WRITE   3615238\n0x4019DE40 WRITE   3615240\n0x40149C00 WRITE   3615273\n0x40149C40 WRITE   3615329\n0x40149C80 WRITE   3615403\n0x40149CC0 WRITE   3615459\n0x40149D00 WRITE   3615554\n0x40149D40 WRITE   3615610\n0x40149D80 WRITE   3615681\n0x40149DC0 WRITE   3615737\n0x4019DF80 WRITE   3615814\n0x4019DF40 WRITE   3615816\n0x40149E00 WRITE   3615852\n0x40149E40 WRITE   3615908\n0x40149E80 WRITE   3615979\n0x40149EC0 WRITE   3616035\n0x40149F00 WRITE   3616125\n0x40149F40 WRITE   3616181\n0x40149F80 WRITE   3616252\n0x40149FC0 WRITE   3616308\n0x4019FFC0 WRITE   3616470\n0x401A0000 WRITE   3616502\n0x4019F000 WRITE   3616629\n0x4019EFC0 WRITE   3616631\n0x4019E800 WRITE   3616638\n0x4019E7C0 WRITE   3616640\n0x4019E400 WRITE   3616650\n0x4019E3C0 WRITE   3616652\n0x4019E200 WRITE   3616657\n0x4019E1C0 WRITE   3616660\n0x4019E100 WRITE   3616663\n0x4019E0C0 WRITE   3616666\n0x4019E080 WRITE   3616669\n0x4019E040 WRITE   3616672\n0x4014A000 WRITE   3616704\n0x4014A040 WRITE   3616792\n0x4014A080 WRITE   3616858\n0x4014A0C0 WRITE   3616914\n0x4014A100 WRITE   3616997\n0x4014A140 WRITE   3617053\n0x4014A180 WRITE   3617116\n0x4014A1C0 WRITE   3617172\n0x4019E180 WRITE   3617228\n0x4019E140 WRITE   3617230\n0x4014A200 WRITE   3617266\n0x4014A240 WRITE   3617322\n0x4014A280 WRITE   3617385\n0x4014A2C0 WRITE   3617441\n0x4014A300 WRITE   3617519\n0x4014A340 WRITE   3617575\n0x4014A380 WRITE   3617638\n0x4014A3C0 WRITE   3617694\n0x4019E300 WRITE   3617755\n0x4019E2C0 WRITE   3617757\n0x4019E280 WRITE   3617764\n0x4019E240 WRITE   3617766\n0x4014A400 WRITE   3617799\n0x4014A440 WRITE   3617855\n0x4014A480 WRITE   3617929\n0x4014A4C0 WRITE   3617985\n0x4014A500 WRITE   3618076\n0x4014A540 WRITE   3618132\n0x4014A580 WRITE   3618203\n0x4014A5C0 WRITE   3618259\n0x4019E380 WRITE   3618323\n0x4019E340 WRITE   3618325\n0x4014A600 WRITE   3618361\n0x4014A640 WRITE   3618417\n0x4014A680 WRITE   3618488\n0x4014A6C0 WRITE   3618544\n0x4014A700 WRITE   3618630\n0x4014A740 WRITE   3618686\n0x4014A780 WRITE   3618757\n0x4014A7C0 WRITE   3618813\n0x4019E600 WRITE   3618882\n0x4019E5C0 WRITE   3618884\n0x4019E500 WRITE   3618891\n0x4019E4C0 WRITE   3618893\n0x4019E480 WRITE   3618903\n0x4019E440 WRITE   3618905\n0x4014A800 WRITE   3618932\n0x4014A840 WRITE   3618988\n0x4014A880 WRITE   3619054\n0x4014A8C0 WRITE   3619110\n0x4014A900 WRITE   3619197\n0x4014A940 WRITE   3619253\n0x4014A980 WRITE   3619316\n0x4014A9C0 WRITE   3619372\n0x4019E580 WRITE   3619434\n0x4019E540 WRITE   3619436\n0x4014AA00 WRITE   3619472\n0x4014AA40 WRITE   3619528\n0x4014AA80 WRITE   3619591\n0x4014AAC0 WRITE   3619647\n0x4014AB00 WRITE   3619729\n0x4014AB40 WRITE   3619785\n0x4014AB80 WRITE   3619848\n0x4014ABC0 WRITE   3619904\n0x4019E700 WRITE   3619970\n0x4019E6C0 WRITE   3619972\n0x4019E680 WRITE   3619979\n0x4019E640 WRITE   3619981\n0x4014AC00 WRITE   3620014\n0x4014AC40 WRITE   3620070\n0x4014AC80 WRITE   3620144\n0x4014ACC0 WRITE   3620200\n0x4014AD00 WRITE   3620295\n0x4014AD40 WRITE   3620351\n0x4014AD80 WRITE   3620422\n0x4014ADC0 WRITE   3620478\n0x4019E780 WRITE   3620548\n0x4019E740 WRITE   3620550\n0x4014AE00 WRITE   3620586\n0x4014AE40 WRITE   3620642\n0x4014AE80 WRITE   3620713\n0x4014AEC0 WRITE   3620769\n0x4014AF00 WRITE   3620859\n0x4014AF40 WRITE   3620915\n0x4014AF80 WRITE   3620986\n0x4014AFC0 WRITE   3621042\n0x4019EC00 WRITE   3621122\n0x4019EBC0 WRITE   3621124\n0x4019EA00 WRITE   3621131\n0x4019E9C0 WRITE   3621133\n0x4019E900 WRITE   3621143\n0x4019E8C0 WRITE   3621145\n0x4019E880 WRITE   3621150\n0x4019E840 WRITE   3621153\n0x4014B000 WRITE   3621178\n0x4014B040 WRITE   3621262\n0x4014B080 WRITE   3621328\n0x4014B0C0 WRITE   3621384\n0x4014B100 WRITE   3621467\n0x4014B140 WRITE   3621523\n0x4014B180 WRITE   3621586\n0x4014B1C0 WRITE   3621642\n0x4019E980 WRITE   3621706\n0x4019E940 WRITE   3621708\n0x4014B200 WRITE   3621744\n0x4014B240 WRITE   3621800\n0x4014B280 WRITE   3621863\n0x4014B2C0 WRITE   3621919\n0x4014B300 WRITE   3621997\n0x4014B340 WRITE   3622053\n0x4014B380 WRITE   3622116\n0x4014B3C0 WRITE   3622172\n0x4019EB00 WRITE   3622240\n0x4019EAC0 WRITE   3622242\n0x4019EA80 WRITE   3622249\n0x4019EA40 WRITE   3622251\n0x4014B400 WRITE   3622284\n0x4014B440 WRITE   3622340\n0x4014B480 WRITE   3622414\n0x4014B4C0 WRITE   3622470\n0x4014B500 WRITE   3622561\n0x4014B540 WRITE   3622617\n0x4014B580 WRITE   3622688\n0x4014B5C0 WRITE   3622744\n0x4019EB80 WRITE   3622816\n0x4019EB40 WRITE   3622818\n0x4014B600 WRITE   3622854\n0x4014B640 WRITE   3622910\n0x4014B680 WRITE   3622981\n0x4014B6C0 WRITE   3623037\n0x4014B700 WRITE   3623123\n0x4014B740 WRITE   3623179\n0x4014B780 WRITE   3623250\n0x4014B7C0 WRITE   3623306\n0x4019EE00 WRITE   3623383\n0x4019EDC0 WRITE   3623385\n0x4019ED00 WRITE   3623392\n0x4019ECC0 WRITE   3623394\n0x4019EC80 WRITE   3623404\n0x4019EC40 WRITE   3623406\n0x4014B800 WRITE   3623433\n0x4014B840 WRITE   3623489\n0x4014B880 WRITE   3623555\n0x4014B8C0 WRITE   3623611\n0x4014B900 WRITE   3623698\n0x4014B940 WRITE   3623754\n0x4014B980 WRITE   3623817\n0x4014B9C0 WRITE   3623873\n0x4019ED80 WRITE   3623942\n0x4019ED40 WRITE   3623944\n0x4014BA00 WRITE   3623980\n0x4014BA40 WRITE   3624036\n0x4014BA80 WRITE   3624099\n0x4014BAC0 WRITE   3624155\n0x4014BB00 WRITE   3624237\n0x4014BB40 WRITE   3624293\n0x4014BB80 WRITE   3624356\n0x4014BBC0 WRITE   3624412\n0x4019EF00 WRITE   3624485\n0x4019EEC0 WRITE   3624487\n0x4019EE80 WRITE   3624494\n0x4019EE40 WRITE   3624496\n0x4014BC00 WRITE   3624529\n0x4014BC40 WRITE   3624585\n0x4014BC80 WRITE   3624659\n0x4014BCC0 WRITE   3624715\n0x4014BD00 WRITE   3624810\n0x4014BD40 WRITE   3624866\n0x4014BD80 WRITE   3624937\n0x4014BDC0 WRITE   3624993\n0x4019EF80 WRITE   3625070\n0x4019EF40 WRITE   3625072\n0x4014BE00 WRITE   3625108\n0x4014BE40 WRITE   3625164\n0x4014BE80 WRITE   3625235\n0x4014BEC0 WRITE   3625291\n0x4014BF00 WRITE   3625381\n0x4014BF40 WRITE   3625437\n0x4014BF80 WRITE   3625508\n0x4014BFC0 WRITE   3625564\n0x4019F800 WRITE   3625650\n0x4019F7C0 WRITE   3625652\n0x4019F400 WRITE   3625659\n0x4019F3C0 WRITE   3625661\n0x4019F200 WRITE   3625671\n0x4019F1C0 WRITE   3625673\n0x4019F100 WRITE   3625678\n0x4019F0C0 WRITE   3625681\n0x4019F080 WRITE   3625684\n0x4019F040 WRITE   3625687\n0x4014C000 WRITE   3625712\n0x4014C040 WRITE   3625796\n0x4014C080 WRITE   3625862\n0x4014C0C0 WRITE   3625918\n0x4014C100 WRITE   3626001\n0x4014C140 WRITE   3626057\n0x4014C180 WRITE   3626120\n0x4014C1C0 WRITE   3626176\n0x4019F180 WRITE   3626232\n0x4019F140 WRITE   3626234\n0x4014C200 WRITE   3626270\n0x4014C240 WRITE   3626326\n0x4014C280 WRITE   3626389\n0x4014C2C0 WRITE   3626445\n0x4014C300 WRITE   3626523\n0x4014C340 WRITE   3626579\n0x4014C380 WRITE   3626642\n0x4014C3C0 WRITE   3626698\n0x4019F300 WRITE   3626764\n0x4019F2C0 WRITE   3626766\n0x4019F280 WRITE   3626773\n0x4019F240 WRITE   3626775\n0x4014C400 WRITE   3626808\n0x4014C440 WRITE   3626864\n0x4014C480 WRITE   3626938\n0x4014C4C0 WRITE   3626994\n0x4014C500 WRITE   3627085\n0x4014C540 WRITE   3627141\n0x4014C580 WRITE   3627212\n0x4014C5C0 WRITE   3627268\n0x4019F380 WRITE   3627332\n0x4019F340 WRITE   3627334\n0x4014C600 WRITE   3627370\n0x4014C640 WRITE   3627426\n0x4014C680 WRITE   3627497\n0x4014C6C0 WRITE   3627553\n0x4014C700 WRITE   3627639\n0x4014C740 WRITE   3627695\n0x4014C780 WRITE   3627766\n0x4014C7C0 WRITE   3627822\n0x4019F600 WRITE   3627897\n0x4019F5C0 WRITE   3627899\n0x4019F500 WRITE   3627906\n0x4019F4C0 WRITE   3627908\n0x4019F480 WRITE   3627918\n0x4019F440 WRITE   3627920\n0x4014C800 WRITE   3627947\n0x4014C840 WRITE   3628003\n0x4014C880 WRITE   3628069\n0x4014C8C0 WRITE   3628125\n0x4014C900 WRITE   3628212\n0x4014C940 WRITE   3628268\n0x4014C980 WRITE   3628331\n0x4014C9C0 WRITE   3628387\n0x4019F580 WRITE   3628449\n0x4019F540 WRITE   3628451\n0x4014CA00 WRITE   3628487\n0x4014CA40 WRITE   3628543\n0x4014CA80 WRITE   3628606\n0x4014CAC0 WRITE   3628662\n0x4014CB00 WRITE   3628744\n0x4014CB40 WRITE   3628800\n0x4014CB80 WRITE   3628863\n0x4014CBC0 WRITE   3628919\n0x4019F700 WRITE   3628991\n0x4019F6C0 WRITE   3628993\n0x4019F680 WRITE   3629000\n0x4019F640 WRITE   3629002\n0x4014CC00 WRITE   3629035\n0x4014CC40 WRITE   3629091\n0x4014CC80 WRITE   3629165\n0x4014CCC0 WRITE   3629221\n0x4014CD00 WRITE   3629316\n0x4014CD40 WRITE   3629372\n0x4014CD80 WRITE   3629443\n0x4014CDC0 WRITE   3629499\n0x4019F780 WRITE   3629569\n0x4019F740 WRITE   3629571\n0x4014CE00 WRITE   3629607\n0x4014CE40 WRITE   3629663\n0x4014CE80 WRITE   3629734\n0x4014CEC0 WRITE   3629790\n0x4014CF00 WRITE   3629880\n0x4014CF40 WRITE   3629936\n0x4014CF80 WRITE   3630007\n0x4014CFC0 WRITE   3630063\n0x4019FC00 WRITE   3630149\n0x4019FBC0 WRITE   3630151\n0x4019FA00 WRITE   3630158\n0x4019F9C0 WRITE   3630160\n0x4019F900 WRITE   3630170\n0x4019F8C0 WRITE   3630172\n0x4019F880 WRITE   3630177\n0x4019F840 WRITE   3630180\n0x4014D000 WRITE   3630205\n0x4014D040 WRITE   3630289\n0x4014D080 WRITE   3630355\n0x4014D0C0 WRITE   3630411\n0x4014D100 WRITE   3630494\n0x4014D140 WRITE   3630550\n0x4014D180 WRITE   3630613\n0x4014D1C0 WRITE   3630669\n0x4019F980 WRITE   3630733\n0x4019F940 WRITE   3630735\n0x4014D200 WRITE   3630771\n0x4014D240 WRITE   3630827\n0x4014D280 WRITE   3630890\n0x4014D2C0 WRITE   3630946\n0x4014D300 WRITE   3631024\n0x4014D340 WRITE   3631080\n0x4014D380 WRITE   3631143\n0x4014D3C0 WRITE   3631199\n0x4019FB00 WRITE   3631273\n0x4019FAC0 WRITE   3631275\n0x4019FA80 WRITE   3631282\n0x4019FA40 WRITE   3631284\n0x4014D400 WRITE   3631317\n0x4014D440 WRITE   3631373\n0x4014D480 WRITE   3631447\n0x4014D4C0 WRITE   3631503\n0x4014D500 WRITE   3631594\n0x4014D540 WRITE   3631650\n0x4014D580 WRITE   3631721\n0x4014D5C0 WRITE   3631777\n0x4019FB80 WRITE   3631849\n0x4019FB40 WRITE   3631851\n0x4014D600 WRITE   3631887\n0x4014D640 WRITE   3631943\n0x4014D680 WRITE   3632014\n0x4014D6C0 WRITE   3632070\n0x4014D700 WRITE   3632156\n0x4014D740 WRITE   3632212\n0x4014D780 WRITE   3632283\n0x4014D7C0 WRITE   3632339\n0x4019FE00 WRITE   3632422\n0x4019FDC0 WRITE   3632424\n0x4019FD00 WRITE   3632431\n0x4019FCC0 WRITE   3632433\n0x4019FC80 WRITE   3632443\n0x4019FC40 WRITE   3632445\n0x4014D800 WRITE   3632472\n0x4014D840 WRITE   3632528\n0x4014D880 WRITE   3632594\n0x4014D8C0 WRITE   3632650\n0x4014D900 WRITE   3632737\n0x4014D940 WRITE   3632793\n0x4014D980 WRITE   3632856\n0x4014D9C0 WRITE   3632912\n0x4019FD80 WRITE   3632981\n0x4019FD40 WRITE   3632983\n0x4014DA00 WRITE   3633019\n0x4014DA40 WRITE   3633075\n0x4014DA80 WRITE   3633138\n0x4014DAC0 WRITE   3633194\n0x4014DB00 WRITE   3633276\n0x4014DB40 WRITE   3633332\n0x4014DB80 WRITE   3633395\n0x4014DBC0 WRITE   3633451\n0x4019FF00 WRITE   3633530\n0x4019FEC0 WRITE   3633532\n0x4019FE80 WRITE   3633539\n0x4019FE40 WRITE   3633541\n0x4014DC00 WRITE   3633574\n0x4014DC40 WRITE   3633630\n0x4014DC80 WRITE   3633704\n0x4014DCC0 WRITE   3633760\n0x4014DD00 WRITE   3633855\n0x4014DD40 WRITE   3633911\n0x4014DD80 WRITE   3633982\n0x4014DDC0 WRITE   3634038\n0x4019FF80 WRITE   3634115\n0x4019FF40 WRITE   3634117\n0x4014DE00 WRITE   3634153\n0x4014DE40 WRITE   3634209\n0x4014DE80 WRITE   3634280\n0x4014DEC0 WRITE   3634336\n0x4014DF00 WRITE   3634426\n0x4014DF40 WRITE   3634482\n0x4014DF80 WRITE   3634553\n0x4014DFC0 WRITE   3634609\n0x401A1FC0 WRITE   3634771\n0x401A2000 WRITE   3634803\n0x401A1000 WRITE   3634953\n0x401A0FC0 WRITE   3634955\n0x401A0800 WRITE   3634962\n0x401A07C0 WRITE   3634964\n0x401A0400 WRITE   3634974\n0x401A03C0 WRITE   3634976\n0x401A0200 WRITE   3634981\n0x401A01C0 WRITE   3634984\n0x401A0100 WRITE   3634987\n0x401A00C0 WRITE   3634990\n0x401A0080 WRITE   3634993\n0x401A0040 WRITE   3634996\n0x4014E000 WRITE   3635028\n0x4014E040 WRITE   3635116\n0x4014E080 WRITE   3635182\n0x4014E0C0 WRITE   3635238\n0x4014E100 WRITE   3635321\n0x4014E140 WRITE   3635377\n0x4014E180 WRITE   3635440\n0x4014E1C0 WRITE   3635496\n0x401A0180 WRITE   3635552\n0x401A0140 WRITE   3635554\n0x4014E200 WRITE   3635590\n0x4014E240 WRITE   3635646\n0x4014E280 WRITE   3635709\n0x4014E2C0 WRITE   3635765\n0x4014E300 WRITE   3635843\n0x4014E340 WRITE   3635899\n0x4014E380 WRITE   3635962\n0x4014E3C0 WRITE   3636018\n0x401A0300 WRITE   3636079\n0x401A02C0 WRITE   3636081\n0x401A0280 WRITE   3636088\n0x401A0240 WRITE   3636090\n0x4014E400 WRITE   3636123\n0x4014E440 WRITE   3636179\n0x4014E480 WRITE   3636253\n0x4014E4C0 WRITE   3636309\n0x4014E500 WRITE   3636400\n0x4014E540 WRITE   3636456\n0x4014E580 WRITE   3636527\n0x4014E5C0 WRITE   3636583\n0x401A0380 WRITE   3636647\n0x401A0340 WRITE   3636649\n0x4014E600 WRITE   3636685\n0x4014E640 WRITE   3636741\n0x4014E680 WRITE   3636812\n0x4014E6C0 WRITE   3636868\n0x4014E700 WRITE   3636954\n0x4014E740 WRITE   3637010\n0x4014E780 WRITE   3637081\n0x4014E7C0 WRITE   3637137\n0x401A0600 WRITE   3637206\n0x401A05C0 WRITE   3637208\n0x401A0500 WRITE   3637215\n0x401A04C0 WRITE   3637217\n0x401A0480 WRITE   3637227\n0x401A0440 WRITE   3637229\n0x4014E800 WRITE   3637256\n0x4014E840 WRITE   3637312\n0x4014E880 WRITE   3637378\n0x4014E8C0 WRITE   3637434\n0x4014E900 WRITE   3637521\n0x4014E940 WRITE   3637577\n0x4014E980 WRITE   3637640\n0x4014E9C0 WRITE   3637696\n0x401A0580 WRITE   3637758\n0x401A0540 WRITE   3637760\n0x4014EA00 WRITE   3637796\n0x4014EA40 WRITE   3637852\n0x4014EA80 WRITE   3637915\n0x4014EAC0 WRITE   3637971\n0x4014EB00 WRITE   3638053\n0x4014EB40 WRITE   3638109\n0x4014EB80 WRITE   3638172\n0x4014EBC0 WRITE   3638228\n0x401A0700 WRITE   3638294\n0x401A06C0 WRITE   3638296\n0x401A0680 WRITE   3638303\n0x401A0640 WRITE   3638305\n0x4014EC00 WRITE   3638338\n0x4014EC40 WRITE   3638394\n0x4014EC80 WRITE   3638468\n0x4014ECC0 WRITE   3638524\n0x4014ED00 WRITE   3638619\n0x4014ED40 WRITE   3638675\n0x4014ED80 WRITE   3638746\n0x4014EDC0 WRITE   3638802\n0x401A0780 WRITE   3638872\n0x401A0740 WRITE   3638874\n0x4014EE00 WRITE   3638910\n0x4014EE40 WRITE   3638966\n0x4014EE80 WRITE   3639037\n0x4014EEC0 WRITE   3639093\n0x4014EF00 WRITE   3639183\n0x4014EF40 WRITE   3639239\n0x4014EF80 WRITE   3639310\n0x4014EFC0 WRITE   3639366\n0x401A0C00 WRITE   3639446\n0x401A0BC0 WRITE   3639448\n0x401A0A00 WRITE   3639455\n0x401A09C0 WRITE   3639457\n0x401A0900 WRITE   3639467\n0x401A08C0 WRITE   3639469\n0x401A0880 WRITE   3639474\n0x401A0840 WRITE   3639477\n0x4014F000 WRITE   3639502\n0x4014F040 WRITE   3639586\n0x4014F080 WRITE   3639652\n0x4014F0C0 WRITE   3639708\n0x4014F100 WRITE   3639791\n0x4014F140 WRITE   3639847\n0x4014F180 WRITE   3639910\n0x4014F1C0 WRITE   3639966\n0x401A0980 WRITE   3640030\n0x401A0940 WRITE   3640032\n0x4014F200 WRITE   3640068\n0x4014F240 WRITE   3640124\n0x4014F280 WRITE   3640187\n0x4014F2C0 WRITE   3640243\n0x4014F300 WRITE   3640321\n0x4014F340 WRITE   3640377\n0x4014F380 WRITE   3640440\n0x4014F3C0 WRITE   3640496\n0x401A0B00 WRITE   3640564\n0x401A0AC0 WRITE   3640566\n0x401A0A80 WRITE   3640573\n0x401A0A40 WRITE   3640575\n0x4014F400 WRITE   3640608\n0x4014F440 WRITE   3640664\n0x4014F480 WRITE   3640738\n0x4014F4C0 WRITE   3640794\n0x4014F500 WRITE   3640885\n0x4014F540 WRITE   3640941\n0x4014F580 WRITE   3641012\n0x4014F5C0 WRITE   3641068\n0x401A0B80 WRITE   3641140\n0x401A0B40 WRITE   3641142\n0x4014F600 WRITE   3641178\n0x4014F640 WRITE   3641234\n0x4014F680 WRITE   3641305\n0x4014F6C0 WRITE   3641361\n0x4014F700 WRITE   3641447\n0x4014F740 WRITE   3641503\n0x4014F780 WRITE   3641574\n0x4014F7C0 WRITE   3641630\n0x401A0E00 WRITE   3641707\n0x401A0DC0 WRITE   3641709\n0x401A0D00 WRITE   3641716\n0x401A0CC0 WRITE   3641718\n0x401A0C80 WRITE   3641728\n0x401A0C40 WRITE   3641730\n0x4014F800 WRITE   3641757\n0x4014F840 WRITE   3641813\n0x4014F880 WRITE   3641879\n0x4014F8C0 WRITE   3641935\n0x4014F900 WRITE   3642022\n0x4014F940 WRITE   3642078\n0x4014F980 WRITE   3642141\n0x4014F9C0 WRITE   3642197\n0x401A0D80 WRITE   3642266\n0x401A0D40 WRITE   3642268\n0x4014FA00 WRITE   3642304\n0x4014FA40 WRITE   3642360\n0x4014FA80 WRITE   3642423\n0x4014FAC0 WRITE   3642479\n0x4014FB00 WRITE   3642561\n0x4014FB40 WRITE   3642617\n0x4014FB80 WRITE   3642680\n0x4014FBC0 WRITE   3642736\n0x401A0F00 WRITE   3642809\n0x401A0EC0 WRITE   3642811\n0x401A0E80 WRITE   3642818\n0x401A0E40 WRITE   3642820\n0x4014FC00 WRITE   3642853\n0x4014FC40 WRITE   3642909\n0x4014FC80 WRITE   3642983\n0x4014FCC0 WRITE   3643039\n0x4014FD00 WRITE   3643134\n0x4014FD40 WRITE   3643190\n0x4014FD80 WRITE   3643261\n0x4014FDC0 WRITE   3643317\n0x401A0F80 WRITE   3643394\n0x401A0F40 WRITE   3643396\n0x4014FE00 WRITE   3643432\n0x4014FE40 WRITE   3643488\n0x4014FE80 WRITE   3643559\n0x4014FEC0 WRITE   3643615\n0x4014FF00 WRITE   3643705\n0x4014FF40 WRITE   3643761\n0x4014FF80 WRITE   3643832\n0x4014FFC0 WRITE   3643888\n0x401A1800 WRITE   3643974\n0x401A17C0 WRITE   3643976\n0x401A1400 WRITE   3643983\n0x401A13C0 WRITE   3643985\n0x401A1200 WRITE   3643995\n0x401A11C0 WRITE   3643997\n0x401A1100 WRITE   3644002\n0x401A10C0 WRITE   3644005\n0x401A1080 WRITE   3644008\n0x401A1040 WRITE   3644011\n0x40150000 WRITE   3644036\n0x40150040 WRITE   3644120\n0x40150080 WRITE   3644186\n0x401500C0 WRITE   3644242\n0x40150100 WRITE   3644325\n0x40150140 WRITE   3644381\n0x40150180 WRITE   3644444\n0x401501C0 WRITE   3644500\n0x401A1180 WRITE   3644556\n0x401A1140 WRITE   3644558\n0x40150200 WRITE   3644594\n0x40150240 WRITE   3644650\n0x40150280 WRITE   3644713\n0x401502C0 WRITE   3644769\n0x40150300 WRITE   3644847\n0x40150340 WRITE   3644903\n0x40150380 WRITE   3644966\n0x401503C0 WRITE   3645022\n0x401A1300 WRITE   3645088\n0x401A12C0 WRITE   3645090\n0x401A1280 WRITE   3645097\n0x401A1240 WRITE   3645099\n0x40150400 WRITE   3645132\n0x40150440 WRITE   3645188\n0x40150480 WRITE   3645262\n0x401504C0 WRITE   3645318\n0x40150500 WRITE   3645409\n0x40150540 WRITE   3645465\n0x40150580 WRITE   3645536\n0x401505C0 WRITE   3645592\n0x401A1380 WRITE   3645656\n0x401A1340 WRITE   3645658\n0x40150600 WRITE   3645694\n0x40150640 WRITE   3645750\n0x40150680 WRITE   3645821\n0x401506C0 WRITE   3645877\n0x40150700 WRITE   3645963\n0x40150740 WRITE   3646019\n0x40150780 WRITE   3646090\n0x401507C0 WRITE   3646146\n0x401A1600 WRITE   3646221\n0x401A15C0 WRITE   3646223\n0x401A1500 WRITE   3646230\n0x401A14C0 WRITE   3646232\n0x401A1480 WRITE   3646242\n0x401A1440 WRITE   3646244\n0x40150800 WRITE   3646271\n0x40150840 WRITE   3646327\n0x40150880 WRITE   3646393\n0x401508C0 WRITE   3646449\n0x40150900 WRITE   3646536\n0x40150940 WRITE   3646592\n0x40150980 WRITE   3646655\n0x401509C0 WRITE   3646711\n0x401A1580 WRITE   3646773\n0x401A1540 WRITE   3646775\n0x40150A00 WRITE   3646811\n0x40150A40 WRITE   3646867\n0x40150A80 WRITE   3646930\n0x40150AC0 WRITE   3646986\n0x40150B00 WRITE   3647068\n0x40150B40 WRITE   3647124\n0x40150B80 WRITE   3647187\n0x40150BC0 WRITE   3647243\n0x401A1700 WRITE   3647315\n0x401A16C0 WRITE   3647317\n0x401A1680 WRITE   3647324\n0x401A1640 WRITE   3647326\n0x40150C00 WRITE   3647359\n0x40150C40 WRITE   3647415\n0x40150C80 WRITE   3647489\n0x40150CC0 WRITE   3647545\n0x40150D00 WRITE   3647640\n0x40150D40 WRITE   3647696\n0x40150D80 WRITE   3647767\n0x40150DC0 WRITE   3647823\n0x401A1780 WRITE   3647893\n0x401A1740 WRITE   3647895\n0x40150E00 WRITE   3647931\n0x40150E40 WRITE   3647987\n0x40150E80 WRITE   3648058\n0x40150EC0 WRITE   3648114\n0x40150F00 WRITE   3648204\n0x40150F40 WRITE   3648260\n0x40150F80 WRITE   3648331\n0x40150FC0 WRITE   3648387\n0x401A1C00 WRITE   3648473\n0x401A1BC0 WRITE   3648475\n0x401A1A00 WRITE   3648482\n0x401A19C0 WRITE   3648484\n0x401A1900 WRITE   3648494\n0x401A18C0 WRITE   3648496\n0x401A1880 WRITE   3648501\n0x401A1840 WRITE   3648504\n0x40151000 WRITE   3648529\n0x40151040 WRITE   3648613\n0x40151080 WRITE   3648679\n0x401510C0 WRITE   3648735\n0x40151100 WRITE   3648818\n0x40151140 WRITE   3648874\n0x40151180 WRITE   3648937\n0x401511C0 WRITE   3648993\n0x401A1980 WRITE   3649057\n0x401A1940 WRITE   3649059\n0x40151200 WRITE   3649095\n0x40151240 WRITE   3649151\n0x40151280 WRITE   3649214\n0x401512C0 WRITE   3649270\n0x40151300 WRITE   3649348\n0x40151340 WRITE   3649404\n0x40151380 WRITE   3649467\n0x401513C0 WRITE   3649523\n0x401A1B00 WRITE   3649597\n0x401A1AC0 WRITE   3649599\n0x401A1A80 WRITE   3649606\n0x401A1A40 WRITE   3649608\n0x40151400 WRITE   3649641\n0x40151440 WRITE   3649697\n0x40151480 WRITE   3649771\n0x401514C0 WRITE   3649827\n0x40151500 WRITE   3649918\n0x40151540 WRITE   3649974\n0x40151580 WRITE   3650045\n0x401515C0 WRITE   3650101\n0x401A1B80 WRITE   3650173\n0x401A1B40 WRITE   3650175\n0x40151600 WRITE   3650211\n0x40151640 WRITE   3650267\n0x40151680 WRITE   3650338\n0x401516C0 WRITE   3650394\n0x40151700 WRITE   3650480\n0x40151740 WRITE   3650536\n0x40151780 WRITE   3650607\n0x401517C0 WRITE   3650663\n0x401A1E00 WRITE   3650746\n0x401A1DC0 WRITE   3650748\n0x401A1D00 WRITE   3650755\n0x401A1CC0 WRITE   3650757\n0x401A1C80 WRITE   3650767\n0x401A1C40 WRITE   3650769\n0x40151800 WRITE   3650796\n0x40151840 WRITE   3650852\n0x40151880 WRITE   3650918\n0x401518C0 WRITE   3650974\n0x40151900 WRITE   3651061\n0x40151940 WRITE   3651117\n0x40151980 WRITE   3651180\n0x401519C0 WRITE   3651236\n0x401A1D80 WRITE   3651305\n0x401A1D40 WRITE   3651307\n0x40151A00 WRITE   3651343\n0x40151A40 WRITE   3651399\n0x40151A80 WRITE   3651462\n0x40151AC0 WRITE   3651518\n0x40151B00 WRITE   3651600\n0x40151B40 WRITE   3651656\n0x40151B80 WRITE   3651719\n0x40151BC0 WRITE   3651775\n0x401A1F00 WRITE   3651854\n0x401A1EC0 WRITE   3651856\n0x401A1E80 WRITE   3651863\n0x401A1E40 WRITE   3651865\n0x40151C00 WRITE   3651898\n0x40151C40 WRITE   3651954\n0x40151C80 WRITE   3652028\n0x40151CC0 WRITE   3652084\n0x40151D00 WRITE   3652179\n0x40151D40 WRITE   3652235\n0x40151D80 WRITE   3652306\n0x40151DC0 WRITE   3652362\n0x401A1F80 WRITE   3652439\n0x401A1F40 WRITE   3652441\n0x40151E00 WRITE   3652477\n0x40151E40 WRITE   3652533\n0x40151E80 WRITE   3652604\n0x40151EC0 WRITE   3652660\n0x40151F00 WRITE   3652750\n0x40151F40 WRITE   3652806\n0x40151F80 WRITE   3652877\n0x40151FC0 WRITE   3652933\n0x401A3FC0 WRITE   3653095\n0x401A4000 WRITE   3653127\n0x401A3000 WRITE   3653254\n0x401A2FC0 WRITE   3653256\n0x401A2800 WRITE   3653263\n0x401A27C0 WRITE   3653265\n0x401A2400 WRITE   3653275\n0x401A23C0 WRITE   3653277\n0x401A2200 WRITE   3653282\n0x401A21C0 WRITE   3653285\n0x401A2100 WRITE   3653288\n0x401A20C0 WRITE   3653291\n0x401A2080 WRITE   3653294\n0x401A2040 WRITE   3653297\n0x40152000 WRITE   3653329\n0x40152040 WRITE   3653417\n0x40152080 WRITE   3653483\n0x401520C0 WRITE   3653539\n0x40152100 WRITE   3653622\n0x40152140 WRITE   3653678\n0x40152180 WRITE   3653741\n0x401521C0 WRITE   3653797\n0x401A2180 WRITE   3653853\n0x401A2140 WRITE   3653855\n0x40152200 WRITE   3653891\n0x40152240 WRITE   3653947\n0x40152280 WRITE   3654010\n0x401522C0 WRITE   3654066\n0x40152300 WRITE   3654144\n0x40152340 WRITE   3654200\n0x40152380 WRITE   3654263\n0x401523C0 WRITE   3654319\n0x401A2300 WRITE   3654380\n0x401A22C0 WRITE   3654382\n0x401A2280 WRITE   3654389\n0x401A2240 WRITE   3654391\n0x40152400 WRITE   3654424\n0x40152440 WRITE   3654480\n0x40152480 WRITE   3654554\n0x401524C0 WRITE   3654610\n0x40152500 WRITE   3654701\n0x40152540 WRITE   3654757\n0x40152580 WRITE   3654828\n0x401525C0 WRITE   3654884\n0x401A2380 WRITE   3654948\n0x401A2340 WRITE   3654950\n0x40152600 WRITE   3654986\n0x40152640 WRITE   3655042\n0x40152680 WRITE   3655113\n0x401526C0 WRITE   3655169\n0x40152700 WRITE   3655255\n0x40152740 WRITE   3655311\n0x40152780 WRITE   3655382\n0x401527C0 WRITE   3655438\n0x401A2600 WRITE   3655507\n0x401A25C0 WRITE   3655509\n0x401A2500 WRITE   3655516\n0x401A24C0 WRITE   3655518\n0x401A2480 WRITE   3655528\n0x401A2440 WRITE   3655530\n0x40152800 WRITE   3655557\n0x40152840 WRITE   3655613\n0x40152880 WRITE   3655679\n0x401528C0 WRITE   3655735\n0x40152900 WRITE   3655822\n0x40152940 WRITE   3655878\n0x40152980 WRITE   3655941\n0x401529C0 WRITE   3655997\n0x401A2580 WRITE   3656059\n0x401A2540 WRITE   3656061\n0x40152A00 WRITE   3656097\n0x40152A40 WRITE   3656153\n0x40152A80 WRITE   3656216\n0x40152AC0 WRITE   3656272\n0x40152B00 WRITE   3656354\n0x40152B40 WRITE   3656410\n0x40152B80 WRITE   3656473\n0x40152BC0 WRITE   3656529\n0x401A2700 WRITE   3656595\n0x401A26C0 WRITE   3656597\n0x401A2680 WRITE   3656604\n0x401A2640 WRITE   3656606\n0x40152C00 WRITE   3656639\n0x40152C40 WRITE   3656695\n0x40152C80 WRITE   3656769\n0x40152CC0 WRITE   3656825\n0x40152D00 WRITE   3656920\n0x40152D40 WRITE   3656976\n0x40152D80 WRITE   3657047\n0x40152DC0 WRITE   3657103\n0x401A2780 WRITE   3657173\n0x401A2740 WRITE   3657175\n0x40152E00 WRITE   3657211\n0x40152E40 WRITE   3657267\n0x40152E80 WRITE   3657338\n0x40152EC0 WRITE   3657394\n0x40152F00 WRITE   3657484\n0x40152F40 WRITE   3657540\n0x40152F80 WRITE   3657611\n0x40152FC0 WRITE   3657667\n0x401A2C00 WRITE   3657747\n0x401A2BC0 WRITE   3657749\n0x401A2A00 WRITE   3657756\n0x401A29C0 WRITE   3657758\n0x401A2900 WRITE   3657768\n0x401A28C0 WRITE   3657770\n0x401A2880 WRITE   3657775\n0x401A2840 WRITE   3657778\n0x40153000 WRITE   3657803\n0x40153040 WRITE   3657887\n0x40153080 WRITE   3657953\n0x401530C0 WRITE   3658009\n0x40153100 WRITE   3658092\n0x40153140 WRITE   3658148\n0x40153180 WRITE   3658211\n0x401531C0 WRITE   3658267\n0x401A2980 WRITE   3658331\n0x401A2940 WRITE   3658333\n0x40153200 WRITE   3658369\n0x40153240 WRITE   3658425\n0x40153280 WRITE   3658488\n0x401532C0 WRITE   3658544\n0x40153300 WRITE   3658622\n0x40153340 WRITE   3658678\n0x40153380 WRITE   3658741\n0x401533C0 WRITE   3658797\n0x401A2B00 WRITE   3658865\n0x401A2AC0 WRITE   3658867\n0x401A2A80 WRITE   3658874\n0x401A2A40 WRITE   3658876\n0x40153400 WRITE   3658909\n0x40153440 WRITE   3658965\n0x40153480 WRITE   3659039\n0x401534C0 WRITE   3659095\n0x40153500 WRITE   3659186\n0x40153540 WRITE   3659242\n0x40153580 WRITE   3659313\n0x401535C0 WRITE   3659369\n0x401A2B80 WRITE   3659441\n0x401A2B40 WRITE   3659443\n0x40153600 WRITE   3659479\n0x40153640 WRITE   3659535\n0x40153680 WRITE   3659606\n0x401536C0 WRITE   3659662\n0x40153700 WRITE   3659748\n0x40153740 WRITE   3659804\n0x40153780 WRITE   3659875\n0x401537C0 WRITE   3659931\n0x401A2E00 WRITE   3660008\n0x401A2DC0 WRITE   3660010\n0x401A2D00 WRITE   3660017\n0x401A2CC0 WRITE   3660019\n0x401A2C80 WRITE   3660029\n0x401A2C40 WRITE   3660031\n0x40153800 WRITE   3660058\n0x40153840 WRITE   3660114\n0x40153880 WRITE   3660180\n0x401538C0 WRITE   3660236\n0x40153900 WRITE   3660323\n0x40153940 WRITE   3660379\n0x40153980 WRITE   3660442\n0x401539C0 WRITE   3660498\n0x401A2D80 WRITE   3660567\n0x401A2D40 WRITE   3660569\n0x40153A00 WRITE   3660605\n0x40153A40 WRITE   3660661\n0x40153A80 WRITE   3660724\n0x40153AC0 WRITE   3660780\n0x40153B00 WRITE   3660862\n0x40153B40 WRITE   3660918\n0x40153B80 WRITE   3660981\n0x40153BC0 WRITE   3661037\n0x401A2F00 WRITE   3661110\n0x401A2EC0 WRITE   3661112\n0x401A2E80 WRITE   3661119\n0x401A2E40 WRITE   3661121\n0x40153C00 WRITE   3661154\n0x40153C40 WRITE   3661210\n0x40153C80 WRITE   3661284\n0x40153CC0 WRITE   3661340\n0x40153D00 WRITE   3661435\n0x40153D40 WRITE   3661491\n0x40153D80 WRITE   3661562\n0x40153DC0 WRITE   3661618\n0x401A2F80 WRITE   3661695\n0x401A2F40 WRITE   3661697\n0x40153E00 WRITE   3661733\n0x40153E40 WRITE   3661789\n0x40153E80 WRITE   3661860\n0x40153EC0 WRITE   3661916\n0x40153F00 WRITE   3662006\n0x40153F40 WRITE   3662062\n0x40153F80 WRITE   3662133\n0x40153FC0 WRITE   3662189\n0x401A3800 WRITE   3662275\n0x401A37C0 WRITE   3662277\n0x401A3400 WRITE   3662284\n0x401A33C0 WRITE   3662286\n0x401A3200 WRITE   3662296\n0x401A31C0 WRITE   3662298\n0x401A3100 WRITE   3662303\n0x401A30C0 WRITE   3662306\n0x401A3080 WRITE   3662309\n0x401A3040 WRITE   3662312\n0x40154000 WRITE   3662337\n0x40154040 WRITE   3662393\n0x40154080 WRITE   3662459\n0x401540C0 WRITE   3662515\n0x40154100 WRITE   3662598\n0x40154140 WRITE   3662654\n0x40154180 WRITE   3662717\n0x401541C0 WRITE   3662773\n0x401A3180 WRITE   3662829\n0x401A3140 WRITE   3662831\n0x40154200 WRITE   3662867\n0x40154240 WRITE   3662923\n0x40154280 WRITE   3662986\n0x401542C0 WRITE   3663042\n0x40154300 WRITE   3663120\n0x40154340 WRITE   3663176\n0x40154380 WRITE   3663239\n0x401543C0 WRITE   3663295\n0x40000A40 READ    3663348\n0x400008C0 READ    3663350\n0x40000D40 READ    3663351\n0x40000BC0 READ    3663352\n0x401A57C0 WRITE   3663716\n0x401A5800 WRITE   3663749\n0x401A4C00 WRITE   3663852\n0x401A4BC0 WRITE   3663854\n0x401A4600 WRITE   3663863\n0x401A45C0 WRITE   3663865\n0x401A4300 WRITE   3663874\n0x401A42C0 WRITE   3663877\n0x401A4180 WRITE   3663885\n0x401A4140 WRITE   3663887\n0x40000D80 READ    3663888\n0x401A40C0 WRITE   3664000\n0x40000C00 READ    3664001\n0x401A4080 WRITE   3664003\n0x401A4040 WRITE   3664100\n0x40000A80 READ    3664101\n0x40000900 READ    3664201\n0x2000E180 READ  3664304\n0x2000E1C0 READ  3664489\n0x20010DC0 READ  3664595\n0x40001440 READ    3664811\n0x401A7FC0 WRITE   3664940\n0x401A8000 WRITE   3664974\n0x40001480 READ    3665016\n0x20010E00 READ  3665151\n0x20010E40 READ  3665236\n0x20010E80 READ  3665347\n0x20010EC0 READ  3665436\n0x20010F00 READ  3665522\n0x20010F40 READ  3665612\n0x401A5840 READ    3666040\n0x401A5880 READ    3666463\n0x401A58C0 READ    3666883\n0x401A5900 READ    3667303\n0x401A5940 READ    3667723\n0x401A5980 READ    3668143\n0x401A59C0 READ    3668563\n0x401A5A00 READ    3668983\n0x401A5A40 READ    3669403\n0x401A5A80 READ    3669823\n0x401A5AC0 READ    3670243\n0x401A5B00 READ    3670663\n0x401A5B40 READ    3671083\n0x401A5B80 READ    3671503\n0x401A5BC0 READ    3671923\n0x401A5C00 READ    3672343\n0x401A5C40 READ    3672763\n0x401A5C80 READ    3673183\n0x401A5CC0 READ    3673603\n0x401A5D00 READ    3674023\n0x401A5D40 READ    3674443\n0x401A5D80 READ    3674863\n0x401A5DC0 READ    3675283\n0x401A5E00 READ    3675703\n0x401A5E40 READ    3676123\n0x401A5E80 READ    3676543\n0x401A5EC0 READ    3676963\n0x401A5F00 READ    3677383\n0x401A5F40 READ    3677803\n0x401A5F80 READ    3678223\n0x401A5FC0 READ    3678643\n0x401A6000 READ    3679093\n0x401A6040 READ    3679513\n0x401A6080 READ    3679933\n0x401A60C0 READ    3680353\n0x401A6100 READ    3680773\n0x401A6140 READ    3681193\n0x401A6180 READ    3681613\n0x401A61C0 READ    3682033\n0x401A6200 READ    3682453\n0x401A6240 READ    3682873\n0x401A6280 READ    3683293\n0x401A62C0 READ    3683713\n0x401A6300 READ    3684133\n0x401A6340 READ    3684553\n0x401A6380 READ    3684973\n0x401A63C0 READ    3685393\n0x401A6400 READ    3685813\n0x401A6440 READ    3686233\n0x401A6480 READ    3686653\n0x401A64C0 READ    3687073\n0x401A6500 READ    3687493\n0x401A6540 READ    3687913\n0x401A6580 READ    3688333\n0x401A65C0 READ    3688753\n0x401A6600 READ    3689173\n0x401A6640 READ    3689593\n0x401A6680 READ    3690013\n0x401A66C0 READ    3690433\n0x401A6700 READ    3690853\n0x401A6740 READ    3691273\n0x401A6780 READ    3691693\n0x401A67C0 READ    3692113\n0x401A6800 READ    3692533\n0x401A6840 READ    3692953\n0x401A6880 READ    3693373\n0x401A68C0 READ    3693793\n0x401A6900 READ    3694213\n0x401A6940 READ    3694633\n0x401A6980 READ    3695053\n0x401A69C0 READ    3695473\n0x401A6A00 READ    3695893\n0x401A6A40 READ    3696313\n0x401A6A80 READ    3696733\n0x401A6AC0 READ    3697153\n0x401A6B00 READ    3697573\n0x401A6B40 READ    3697993\n0x401A6B80 READ    3698413\n0x401A6BC0 READ    3698833\n0x401A6C00 READ    3699253\n0x401A6C40 READ    3699673\n0x401A6C80 READ    3700093\n0x401A6CC0 READ    3700513\n0x401A6D00 READ    3700933\n0x401A6D40 READ    3701353\n0x401A6D80 READ    3701773\n0x401A6DC0 READ    3702193\n0x401A6E00 READ    3702613\n0x401A6E40 READ    3703033\n0x401A6E80 READ    3703453\n0x401A6EC0 READ    3703873\n0x401A6F00 READ    3704293\n0x401A6F40 READ    3704713\n0x401A6F80 READ    3705133\n0x401A6FC0 READ    3705553\n0x401A7000 READ    3706003\n0x401A7040 READ    3706423\n0x401A7080 READ    3706843\n0x401A70C0 READ    3707263\n0x401A7100 READ    3707683\n0x401A7140 READ    3708103\n0x401A7180 READ    3708523\n0x401A71C0 READ    3708943\n0x401A7200 READ    3709363\n0x401A7240 READ    3709783\n0x401A7280 READ    3710203\n0x401A72C0 READ    3710623\n0x401A7300 READ    3711043\n0x401A7340 READ    3711463\n0x401A7380 READ    3711883\n0x401A73C0 READ    3712303\n0x401A7400 READ    3712723\n0x401A7440 READ    3713143\n0x401A7480 READ    3713563\n0x401A74C0 READ    3713983\n0x401A7500 READ    3714403\n0x401A7540 READ    3714823\n0x401A7580 READ    3715243\n0x401A75C0 READ    3715663\n0x401A7600 READ    3716083\n0x401A7640 READ    3716503\n0x401A7680 READ    3716923\n0x401A76C0 READ    3717343\n0x401A7700 READ    3717763\n0x401A7740 READ    3718183\n0x401A7780 READ    3718603\n0x401A77C0 READ    3719023\n0x401A7800 READ    3719443\n0x401A7840 READ    3719863\n0x401A7880 READ    3720283\n0x401A78C0 READ    3720703\n0x401A7900 READ    3721123\n0x401A7940 READ    3721543\n0x401A7980 READ    3721963\n0x401A79C0 READ    3722383\n0x401A7A00 READ    3722803\n0x401A7A40 READ    3723223\n0x401A7A80 READ    3723643\n0x401A7AC0 READ    3724063\n0x401A7B00 READ    3724483\n0x401A7B40 READ    3724903\n0x401A7B80 READ    3725323\n0x401A7BC0 READ    3725743\n0x401A7C00 READ    3726163\n0x401A7C40 READ    3726583\n0x401A7C80 READ    3727003\n0x401A7CC0 READ    3727423\n0x401A7D00 READ    3727843\n0x401A7D40 READ    3728263\n0x401A7D80 READ    3728683\n0x401A7DC0 READ    3729103\n0x401A7E00 READ    3729523\n0x401A7E40 READ    3729943\n0x401A7E80 READ    3730363\n0x401A7EC0 READ    3730783\n0x401A7F00 READ    3731203\n0x20017140 READ  3731367\n0x20016F00 READ  3731611\n0x20016F40 READ  3731705\n0x40009CC0 READ    3731706\n0x20010F80 READ  3731786\n0x20017180 READ  3731863\n0x200107C0 READ  3731991\n0x20010800 READ  3732081\n0x20016F80 READ  3732269\n0x20017040 READ  3732361\n0x20017080 READ  3732446\n0x401AA880 WRITE   3732803\n0x401BB880 WRITE   3732985\n0x401CF100 WRITE   3733177\n0x401CF140 WRITE   3733210\n0x20010840 READ  3733250\n0x20010880 READ  3733328\n0x401A3300 WRITE   3733562\n0x401A32C0 WRITE   3733564\n0x401A3280 WRITE   3733571\n0x401A3240 WRITE   3733574\n0x200108C0 READ  3733600\n0x20010900 READ  3733769\n0x401A3380 WRITE   3734292\n0x401A3340 WRITE   3734294\n0x401BB8C0 WRITE   3734378\n0x401A3600 WRITE   3734796\n0x401A35C0 WRITE   3734798\n0x401A3500 WRITE   3734806\n0x401A34C0 WRITE   3734808\n0x401A3480 WRITE   3734818\n0x401A3440 WRITE   3734820\n0x401A8040 WRITE   3734847\n0x401A3580 WRITE   3735288\n0x401A3540 WRITE   3735290\n0x401BB900 WRITE   3735374\n0x401A3700 WRITE   3735762\n0x401A36C0 WRITE   3735764\n0x401A3680 WRITE   3735771\n0x401A3640 WRITE   3735773\n0x401A8080 WRITE   3735806\n0x401A3780 WRITE   3736279\n0x401A3740 WRITE   3736281\n0x401BB940 WRITE   3736365\n0x401A3C00 WRITE   3736798\n0x401A3BC0 WRITE   3736800\n0x401A3A00 WRITE   3736808\n0x401A39C0 WRITE   3736810\n0x401A3900 WRITE   3736820\n0x401A38C0 WRITE   3736822\n0x401A3880 WRITE   3736827\n0x401A3840 WRITE   3736830\n0x401A80C0 WRITE   3736855\n0x401A3980 WRITE   3737294\n0x401A3940 WRITE   3737296\n0x401BB980 WRITE   3737380\n0x401A3B00 WRITE   3737766\n0x401A3AC0 WRITE   3737768\n0x401A3A80 WRITE   3737775\n0x401A3A40 WRITE   3737777\n0x401A8100 WRITE   3737810\n0x401A3B80 WRITE   3738281\n0x401A3B40 WRITE   3738283\n0x401BB9C0 WRITE   3738367\n0x401A3E00 WRITE   3738786\n0x401A3DC0 WRITE   3738788\n0x401A3D00 WRITE   3738795\n0x401A3CC0 WRITE   3738797\n0x401A3C80 WRITE   3738807\n0x401A3C40 WRITE   3738809\n0x401A8140 WRITE   3738836\n0x401A3D80 WRITE   3739284\n0x401A3D40 WRITE   3739286\n0x401BBA00 WRITE   3739370\n0x401A3F00 WRITE   3739765\n0x401A3EC0 WRITE   3739767\n0x401A3E80 WRITE   3739774\n0x401A3E40 WRITE   3739776\n0x401A8180 WRITE   3739809\n0x401A3F80 WRITE   3740289\n0x401A3F40 WRITE   3740291\n0x401BBA40 WRITE   3740375\n0x401D1FC0 WRITE   3740885\n0x401D2000 WRITE   3740920\n0x401CFFC0 WRITE   3740939\n0x401D0000 WRITE   3741007\n0x401D1000 WRITE   3741075\n0x401D0FC0 WRITE   3741077\n0x401D0800 WRITE   3741086\n0x401D07C0 WRITE   3741088\n0x401D0400 WRITE   3741096\n0x401D03C0 WRITE   3741098\n0x401D0200 WRITE   3741103\n0x401D01C0 WRITE   3741106\n0x401D0100 WRITE   3741109\n0x401D00C0 WRITE   3741112\n0x401D0080 WRITE   3741115\n0x401D0040 WRITE   3741118\n0x401A81C0 WRITE   3741151\n0x401D0180 WRITE   3741581\n0x401D0140 WRITE   3741583\n0x401BBA80 WRITE   3741667\n0x401D0300 WRITE   3742046\n0x401D02C0 WRITE   3742048\n0x401D0280 WRITE   3742055\n0x401D0240 WRITE   3742057\n0x401A8200 WRITE   3742090\n0x401D0380 WRITE   3742553\n0x401D0340 WRITE   3742555\n0x401BBAC0 WRITE   3742639\n0x401D0600 WRITE   3743050\n0x401D05C0 WRITE   3743052\n0x401D0500 WRITE   3743059\n0x401D04C0 WRITE   3743061\n0x401D0480 WRITE   3743071\n0x401D0440 WRITE   3743073\n0x401A8240 WRITE   3743100\n0x401D0580 WRITE   3743541\n0x401D0540 WRITE   3743543\n0x401BBB00 WRITE   3743627\n0x401D0700 WRITE   3744015\n0x401D06C0 WRITE   3744017\n0x401D0680 WRITE   3744024\n0x401D0640 WRITE   3744026\n0x401A8280 WRITE   3744059\n0x401D0780 WRITE   3744532\n0x401D0740 WRITE   3744534\n0x401BBB40 WRITE   3744618\n0x401D0C00 WRITE   3745044\n0x401D0BC0 WRITE   3745046\n0x401D0A00 WRITE   3745053\n0x401D09C0 WRITE   3745055\n0x401D0900 WRITE   3745065\n0x401D08C0 WRITE   3745067\n0x401D0880 WRITE   3745072\n0x401D0840 WRITE   3745075\n0x401A82C0 WRITE   3745100\n0x401D0980 WRITE   3745539\n0x401D0940 WRITE   3745541\n0x401BBB80 WRITE   3745625\n0x401D0B00 WRITE   3746011\n0x401D0AC0 WRITE   3746013\n0x401D0A80 WRITE   3746020\n0x401D0A40 WRITE   3746022\n0x401A8300 WRITE   3746055\n0x401D0B80 WRITE   3746526\n0x401D0B40 WRITE   3746528\n0x401BBBC0 WRITE   3746612\n0x401D0E00 WRITE   3747031\n0x401D0DC0 WRITE   3747033\n0x401D0D00 WRITE   3747040\n0x401D0CC0 WRITE   3747042\n0x401D0C80 WRITE   3747052\n0x401D0C40 WRITE   3747054\n0x401A8340 WRITE   3747081\n0x401D0D80 WRITE   3747529\n0x401D0D40 WRITE   3747531\n0x401BBC00 WRITE   3747615\n0x401D0F00 WRITE   3748010\n0x401D0EC0 WRITE   3748012\n0x401D0E80 WRITE   3748019\n0x401D0E40 WRITE   3748021\n0x401A8380 WRITE   3748054\n0x401D0F80 WRITE   3748534\n0x401D0F40 WRITE   3748536\n0x401BBC40 WRITE   3748620\n0x401D1800 WRITE   3749052\n0x401D17C0 WRITE   3749054\n0x401D1400 WRITE   3749061\n0x401D13C0 WRITE   3749063\n0x401D1200 WRITE   3749073\n0x401D11C0 WRITE   3749075\n0x401D1100 WRITE   3749080\n0x401D10C0 WRITE   3749083\n0x401D1080 WRITE   3749086\n0x401D1040 WRITE   3749089\n0x401A83C0 WRITE   3749114\n0x401D1180 WRITE   3749545\n0x401D1140 WRITE   3749547\n0x401BBC80 WRITE   3749631\n0x401D1300 WRITE   3750015\n0x401D12C0 WRITE   3750017\n0x401D1280 WRITE   3750024\n0x401D1240 WRITE   3750026\n0x401A8400 WRITE   3750059\n0x401D1380 WRITE   3750522\n0x401D1340 WRITE   3750524\n0x401BBCC0 WRITE   3750608\n0x401D1600 WRITE   3751025\n0x401D15C0 WRITE   3751027\n0x401D1500 WRITE   3751034\n0x401D14C0 WRITE   3751036\n0x401D1480 WRITE   3751046\n0x401D1440 WRITE   3751048\n0x401A8440 WRITE   3751075\n0x401D1580 WRITE   3751516\n0x401D1540 WRITE   3751518\n0x401BBD00 WRITE   3751602\n0x401D1700 WRITE   3751996\n0x401D16C0 WRITE   3751998\n0x401D1680 WRITE   3752005\n0x401D1640 WRITE   3752007\n0x401A8480 WRITE   3752040\n0x401D1780 WRITE   3752513\n0x401D1740 WRITE   3752515\n0x401BBD40 WRITE   3752599\n0x401D1C00 WRITE   3753031\n0x401D1BC0 WRITE   3753033\n0x401D1A00 WRITE   3753040\n0x401D19C0 WRITE   3753042\n0x401D1900 WRITE   3753052\n0x401D18C0 WRITE   3753054\n0x401D1880 WRITE   3753059\n0x401D1840 WRITE   3753062\n0x401A84C0 WRITE   3753087\n0x401D1980 WRITE   3753526\n0x401D1940 WRITE   3753528\n0x401BBD80 WRITE   3753612\n0x401D1B00 WRITE   3754004\n0x401D1AC0 WRITE   3754006\n0x401D1A80 WRITE   3754013\n0x401D1A40 WRITE   3754015\n0x401A8500 WRITE   3754048\n0x401D1B80 WRITE   3754519\n0x401D1B40 WRITE   3754521\n0x401BBDC0 WRITE   3754605\n0x401D1E00 WRITE   3755030\n0x401D1DC0 WRITE   3755032\n0x401D1D00 WRITE   3755039\n0x401D1CC0 WRITE   3755041\n0x401D1C80 WRITE   3755051\n0x401D1C40 WRITE   3755053\n0x401A8540 WRITE   3755080\n0x401D1D80 WRITE   3755528\n0x401D1D40 WRITE   3755530\n0x401BBE00 WRITE   3755614\n0x401D1F00 WRITE   3756015\n0x401D1EC0 WRITE   3756017\n0x401D1E80 WRITE   3756024\n0x401D1E40 WRITE   3756026\n0x401A8580 WRITE   3756059\n0x401D1F80 WRITE   3756539\n0x401D1F40 WRITE   3756541\n0x401BBE40 WRITE   3756625\n0x401D3FC0 WRITE   3757109\n0x401D4000 WRITE   3757166\n0x401D3000 WRITE   3757278\n0x401D2FC0 WRITE   3757280\n0x401D2800 WRITE   3757287\n0x401D27C0 WRITE   3757289\n0x401D2400 WRITE   3757299\n0x401D23C0 WRITE   3757301\n0x401D2200 WRITE   3757306\n0x401D21C0 WRITE   3757309\n0x401D2100 WRITE   3757312\n0x401D20C0 WRITE   3757315\n0x401D2080 WRITE   3757318\n0x401D2040 WRITE   3757321\n0x401A85C0 WRITE   3757354\n0x401D2180 WRITE   3757784\n0x401D2140 WRITE   3757786\n0x401BBE80 WRITE   3757870\n0x401D2300 WRITE   3758249\n0x401D22C0 WRITE   3758251\n0x401D2280 WRITE   3758258\n0x401D2240 WRITE   3758260\n0x401A8600 WRITE   3758293\n0x401D2380 WRITE   3758756\n0x401D2340 WRITE   3758758\n0x401BBEC0 WRITE   3758842\n0x401D2600 WRITE   3759253\n0x401D25C0 WRITE   3759255\n0x401D2500 WRITE   3759262\n0x401D24C0 WRITE   3759264\n0x401D2480 WRITE   3759274\n0x401D2440 WRITE   3759276\n0x401A8640 WRITE   3759303\n0x401D2580 WRITE   3759744\n0x401D2540 WRITE   3759746\n0x401BBF00 WRITE   3759830\n0x401D2700 WRITE   3760218\n0x401D26C0 WRITE   3760220\n0x401D2680 WRITE   3760227\n0x401D2640 WRITE   3760229\n0x401A8680 WRITE   3760262\n0x401D2780 WRITE   3760735\n0x401D2740 WRITE   3760737\n0x401BBF40 WRITE   3760821\n0x401D2C00 WRITE   3761247\n0x401D2BC0 WRITE   3761249\n0x401D2A00 WRITE   3761256\n0x401D29C0 WRITE   3761258\n0x401D2900 WRITE   3761268\n0x401D28C0 WRITE   3761270\n0x401D2880 WRITE   3761275\n0x401D2840 WRITE   3761278\n0x401A86C0 WRITE   3761303\n0x401D2980 WRITE   3761742\n0x401D2940 WRITE   3761744\n0x401BBF80 WRITE   3761828\n0x401D2B00 WRITE   3762214\n0x401D2AC0 WRITE   3762216\n0x401D2A80 WRITE   3762223\n0x401D2A40 WRITE   3762225\n0x401A8700 WRITE   3762258\n0x401D2B80 WRITE   3762729\n0x401D2B40 WRITE   3762731\n0x401BBFC0 WRITE   3762815\n0x401D2E00 WRITE   3763234\n0x401D2DC0 WRITE   3763236\n0x401D2D00 WRITE   3763243\n0x401D2CC0 WRITE   3763245\n0x401D2C80 WRITE   3763255\n0x401D2C40 WRITE   3763257\n0x401A8740 WRITE   3763284\n0x401D2D80 WRITE   3763732\n0x401D2D40 WRITE   3763734\n0x401BC000 WRITE   3763818\n0x401D2F00 WRITE   3764213\n0x401D2EC0 WRITE   3764215\n0x401D2E80 WRITE   3764222\n0x401D2E40 WRITE   3764224\n0x401A8780 WRITE   3764257\n0x401D2F80 WRITE   3764737\n0x401D2F40 WRITE   3764739\n0x401BC040 WRITE   3764823\n0x401D3800 WRITE   3765255\n0x401D37C0 WRITE   3765257\n0x401D3400 WRITE   3765264\n0x401D33C0 WRITE   3765266\n0x401D3200 WRITE   3765276\n0x401D31C0 WRITE   3765278\n0x401D3100 WRITE   3765283\n0x401D30C0 WRITE   3765286\n0x401D3080 WRITE   3765289\n0x401D3040 WRITE   3765292\n0x401A87C0 WRITE   3765317\n0x401D3180 WRITE   3765748\n0x401D3140 WRITE   3765750\n0x401BC080 WRITE   3765834\n0x401D3300 WRITE   3766218\n0x401D32C0 WRITE   3766220\n0x401D3280 WRITE   3766227\n0x401D3240 WRITE   3766229\n0x401A8800 WRITE   3766262\n0x401D3380 WRITE   3766725\n0x401D3340 WRITE   3766727\n0x401BC0C0 WRITE   3766811\n0x401D3600 WRITE   3767228\n0x401D35C0 WRITE   3767230\n0x401D3500 WRITE   3767237\n0x401D34C0 WRITE   3767239\n0x401D3480 WRITE   3767249\n0x401D3440 WRITE   3767251\n0x401A8840 WRITE   3767278\n0x401D3580 WRITE   3767719\n0x401D3540 WRITE   3767721\n0x401BC100 WRITE   3767805\n0x401D3700 WRITE   3768199\n0x401D36C0 WRITE   3768201\n0x401D3680 WRITE   3768208\n0x401D3640 WRITE   3768210\n0x401A8880 WRITE   3768243\n0x401D3780 WRITE   3768716\n0x401D3740 WRITE   3768718\n0x401BC140 WRITE   3768802\n0x401D3C00 WRITE   3769234\n0x401D3BC0 WRITE   3769236\n0x401D3A00 WRITE   3769243\n0x401D39C0 WRITE   3769245\n0x401D3900 WRITE   3769255\n0x401D38C0 WRITE   3769257\n0x401D3880 WRITE   3769262\n0x401D3840 WRITE   3769265\n0x401A88C0 WRITE   3769290\n0x401D3980 WRITE   3769729\n0x401D3940 WRITE   3769731\n0x401BC180 WRITE   3769815\n0x401D3B00 WRITE   3770207\n0x401D3AC0 WRITE   3770209\n0x401D3A80 WRITE   3770216\n0x401D3A40 WRITE   3770218\n0x401A8900 WRITE   3770251\n0x401D3B80 WRITE   3770722\n0x401D3B40 WRITE   3770724\n0x401BC1C0 WRITE   3770808\n0x401D3E00 WRITE   3771233\n0x401D3DC0 WRITE   3771235\n0x401D3D00 WRITE   3771242\n0x401D3CC0 WRITE   3771244\n0x401D3C80 WRITE   3771254\n0x401D3C40 WRITE   3771256\n0x401A8940 WRITE   3771283\n0x401D3D80 WRITE   3771731\n0x401D3D40 WRITE   3771733\n0x401BC200 WRITE   3771817\n0x401D3F00 WRITE   3772218\n0x401D3EC0 WRITE   3772220\n0x401D3E80 WRITE   3772227\n0x401D3E40 WRITE   3772229\n0x401A8980 WRITE   3772262\n0x401D3F80 WRITE   3772742\n0x401D3F40 WRITE   3772744\n0x401BC240 WRITE   3772828\n0x401D4880 WRITE   3773455\n0x401D5FC0 WRITE   3773604\n0x401D6000 WRITE   3773638\n0x401D5000 WRITE   3773754\n0x401D4FC0 WRITE   3773756\n0x401D4800 WRITE   3773763\n0x401D47C0 WRITE   3773765\n0x401D4400 WRITE   3773775\n0x401D43C0 WRITE   3773777\n0x401D4200 WRITE   3773782\n0x401D41C0 WRITE   3773785\n0x401D4100 WRITE   3773788\n0x401D40C0 WRITE   3773791\n0x401D4080 WRITE   3773794\n0x401D4040 WRITE   3773797\n0x401A89C0 WRITE   3773830\n0x401D4180 WRITE   3774265\n0x401D4140 WRITE   3774267\n0x401BC280 WRITE   3774351\n0x401D4300 WRITE   3774730\n0x401D42C0 WRITE   3774732\n0x401D4280 WRITE   3774739\n0x401D4240 WRITE   3774741\n0x401A8A00 WRITE   3774774\n0x401D4380 WRITE   3775237\n0x401D4340 WRITE   3775239\n0x401BC2C0 WRITE   3775323\n0x401D4600 WRITE   3775734\n0x401D45C0 WRITE   3775736\n0x401D4500 WRITE   3775743\n0x401D44C0 WRITE   3775745\n0x401D4480 WRITE   3775755\n0x401D4440 WRITE   3775757\n0x401A8A40 WRITE   3775784\n0x401D4580 WRITE   3776225\n0x401D4540 WRITE   3776227\n0x401BC300 WRITE   3776311\n0x401D4700 WRITE   3776699\n0x401D46C0 WRITE   3776701\n0x401D4680 WRITE   3776708\n0x401D4640 WRITE   3776710\n0x401A8A80 WRITE   3776743\n0x401D4780 WRITE   3777216\n0x401D4740 WRITE   3777218\n0x401BC340 WRITE   3777302\n0x401D4C00 WRITE   3777728\n0x401D4BC0 WRITE   3777730\n0x401D4A00 WRITE   3777737\n0x401D49C0 WRITE   3777739\n0x401D4900 WRITE   3777749\n0x401D48C0 WRITE   3777751\n0x401D4840 WRITE   3777759\n0x401A8AC0 WRITE   3777784\n0x401D4980 WRITE   3778223\n0x401D4940 WRITE   3778225\n0x401BC380 WRITE   3778309\n0x401D4B00 WRITE   3778695\n0x401D4AC0 WRITE   3778697\n0x401D4A80 WRITE   3778704\n0x401D4A40 WRITE   3778706\n0x401A8B00 WRITE   3778739\n0x401D4B80 WRITE   3779210\n0x401D4B40 WRITE   3779212\n0x401BC3C0 WRITE   3779296\n0x401D4E00 WRITE   3779715\n0x401D4DC0 WRITE   3779717\n0x401D4D00 WRITE   3779724\n0x401D4CC0 WRITE   3779726\n0x401D4C80 WRITE   3779736\n0x401D4C40 WRITE   3779738\n0x401A8B40 WRITE   3779765\n0x401D4D80 WRITE   3780213\n0x401D4D40 WRITE   3780215\n0x401BC400 WRITE   3780299\n0x401D4F00 WRITE   3780694\n0x401D4EC0 WRITE   3780696\n0x401D4E80 WRITE   3780703\n0x401D4E40 WRITE   3780705\n0x401A8B80 WRITE   3780738\n0x401D4F80 WRITE   3781218\n0x401D4F40 WRITE   3781220\n0x401BC440 WRITE   3781304\n0x401D5800 WRITE   3781736\n0x401D57C0 WRITE   3781738\n0x401D5400 WRITE   3781745\n0x401D53C0 WRITE   3781747\n0x401D5200 WRITE   3781757\n0x401D51C0 WRITE   3781759\n0x401D5100 WRITE   3781764\n0x401D50C0 WRITE   3781767\n0x401D5080 WRITE   3781770\n0x401D5040 WRITE   3781773\n0x401A8BC0 WRITE   3781798\n0x401D5180 WRITE   3782229\n0x401D5140 WRITE   3782231\n0x401BC480 WRITE   3782315\n0x401D5300 WRITE   3782699\n0x401D52C0 WRITE   3782701\n0x401D5280 WRITE   3782708\n0x401D5240 WRITE   3782710\n0x401A8C00 WRITE   3782743\n0x401D5380 WRITE   3783206\n0x401D5340 WRITE   3783208\n0x401BC4C0 WRITE   3783292\n0x401D5600 WRITE   3783709\n0x401D55C0 WRITE   3783711\n0x401D5500 WRITE   3783718\n0x401D54C0 WRITE   3783720\n0x401D5480 WRITE   3783730\n0x401D5440 WRITE   3783732\n0x401A8C40 WRITE   3783759\n0x401D5580 WRITE   3784200\n0x401D5540 WRITE   3784202\n0x401BC500 WRITE   3784286\n0x401D5700 WRITE   3784680\n0x401D56C0 WRITE   3784682\n0x401D5680 WRITE   3784689\n0x401D5640 WRITE   3784691\n0x401A8C80 WRITE   3784724\n0x401D5780 WRITE   3785197\n0x401D5740 WRITE   3785199\n0x401BC540 WRITE   3785283\n0x401D5C00 WRITE   3785715\n0x401D5BC0 WRITE   3785717\n0x401D5A00 WRITE   3785724\n0x401D59C0 WRITE   3785726\n0x401D5900 WRITE   3785736\n0x401D58C0 WRITE   3785738\n0x401D5880 WRITE   3785743\n0x401D5840 WRITE   3785746\n0x401A8CC0 WRITE   3785771\n0x401D5980 WRITE   3786210\n0x401D5940 WRITE   3786212\n0x401BC580 WRITE   3786296\n0x401D5B00 WRITE   3786688\n0x401D5AC0 WRITE   3786690\n0x401D5A80 WRITE   3786697\n0x401D5A40 WRITE   3786699\n0x401A8D00 WRITE   3786732\n0x401D5B80 WRITE   3787203\n0x401D5B40 WRITE   3787205\n0x401BC5C0 WRITE   3787289\n0x401D5E00 WRITE   3787714\n0x401D5DC0 WRITE   3787716\n0x401D5D00 WRITE   3787723\n0x401D5CC0 WRITE   3787725\n0x401D5C80 WRITE   3787735\n0x401D5C40 WRITE   3787737\n0x401A8D40 WRITE   3787764\n0x401D5D80 WRITE   3788212\n0x401D5D40 WRITE   3788214\n0x401BC600 WRITE   3788298\n0x401D5F00 WRITE   3788699\n0x401D5EC0 WRITE   3788701\n0x401D5E80 WRITE   3788708\n0x401D5E40 WRITE   3788710\n0x401A8D80 WRITE   3788743\n0x401D5F80 WRITE   3789223\n0x401D5F40 WRITE   3789225\n0x401BC640 WRITE   3789309\n0x401D7FC0 WRITE   3789798\n0x401D8000 WRITE   3789830\n0x401D7000 WRITE   3789944\n0x401D6FC0 WRITE   3789946\n0x401D6800 WRITE   3789953\n0x401D67C0 WRITE   3789955\n0x401D6400 WRITE   3789965\n0x401D63C0 WRITE   3789967\n0x401D6200 WRITE   3789972\n0x401D61C0 WRITE   3789975\n0x401D6100 WRITE   3789978\n0x401D60C0 WRITE   3789981\n0x401D6080 WRITE   3789984\n0x401D6040 WRITE   3789987\n0x401A8DC0 WRITE   3790020\n0x401D6180 WRITE   3790450\n0x401D6140 WRITE   3790452\n0x401BC680 WRITE   3790536\n0x401D6300 WRITE   3790915\n0x401D62C0 WRITE   3790917\n0x401D6280 WRITE   3790924\n0x401D6240 WRITE   3790926\n0x401A8E00 WRITE   3790959\n0x401D6380 WRITE   3791422\n0x401D6340 WRITE   3791424\n0x401BC6C0 WRITE   3791508\n0x401D6600 WRITE   3791919\n0x401D65C0 WRITE   3791921\n0x401D6500 WRITE   3791928\n0x401D64C0 WRITE   3791930\n0x401D6480 WRITE   3791940\n0x401D6440 WRITE   3791942\n0x401A8E40 WRITE   3791969\n0x401D6580 WRITE   3792410\n0x401D6540 WRITE   3792412\n0x401BC700 WRITE   3792496\n0x401D6700 WRITE   3792884\n0x401D66C0 WRITE   3792886\n0x401D6680 WRITE   3792893\n0x401D6640 WRITE   3792895\n0x401A8E80 WRITE   3792928\n0x401D6780 WRITE   3793401\n0x401D6740 WRITE   3793403\n0x401BC740 WRITE   3793487\n0x401D6C00 WRITE   3793913\n0x401D6BC0 WRITE   3793915\n0x401D6A00 WRITE   3793922\n0x401D69C0 WRITE   3793924\n0x401D6900 WRITE   3793934\n0x401D68C0 WRITE   3793936\n0x401D6880 WRITE   3793941\n0x401D6840 WRITE   3793944\n0x401A8EC0 WRITE   3793969\n0x401D6980 WRITE   3794408\n0x401D6940 WRITE   3794410\n0x401BC780 WRITE   3794494\n0x401D6B00 WRITE   3794880\n0x401D6AC0 WRITE   3794882\n0x401D6A80 WRITE   3794889\n0x401D6A40 WRITE   3794891\n0x401A8F00 WRITE   3794924\n0x401D6B80 WRITE   3795395\n0x401D6B40 WRITE   3795397\n0x401BC7C0 WRITE   3795481\n0x401D6E00 WRITE   3795900\n0x401D6DC0 WRITE   3795902\n0x401D6D00 WRITE   3795909\n0x401D6CC0 WRITE   3795911\n0x401D6C80 WRITE   3795921\n0x401D6C40 WRITE   3795923\n0x401A8F40 WRITE   3795950\n0x401D6D80 WRITE   3796398\n0x401D6D40 WRITE   3796400\n0x401BC800 WRITE   3796484\n0x401D6F00 WRITE   3796879\n0x401D6EC0 WRITE   3796881\n0x401D6E80 WRITE   3796888\n0x401D6E40 WRITE   3796890\n0x401A8F80 WRITE   3796923\n0x401D6F80 WRITE   3797403\n0x401D6F40 WRITE   3797405\n0x401BC840 WRITE   3797489\n0x401D7800 WRITE   3797921\n0x401D77C0 WRITE   3797923\n0x401D7400 WRITE   3797930\n0x401D73C0 WRITE   3797932\n0x401D7200 WRITE   3797942\n0x401D71C0 WRITE   3797944\n0x401D7100 WRITE   3797949\n0x401D70C0 WRITE   3797952\n0x401D7080 WRITE   3797955\n0x401D7040 WRITE   3797958\n0x401A8FC0 WRITE   3797983\n0x401D7180 WRITE   3798414\n0x401D7140 WRITE   3798416\n0x401BC880 WRITE   3798500\n0x401D7300 WRITE   3798884\n0x401D72C0 WRITE   3798886\n0x401D7280 WRITE   3798893\n0x401D7240 WRITE   3798895\n0x401A9000 WRITE   3798928\n0x401D7380 WRITE   3799391\n0x401D7340 WRITE   3799393\n0x401BC8C0 WRITE   3799477\n0x401D7600 WRITE   3799894\n0x401D75C0 WRITE   3799896\n0x401D7500 WRITE   3799903\n0x401D74C0 WRITE   3799905\n0x401D7480 WRITE   3799915\n0x401D7440 WRITE   3799917\n0x401A9040 WRITE   3799944\n0x401D7580 WRITE   3800385\n0x401D7540 WRITE   3800387\n0x401BC900 WRITE   3800471\n0x401D7700 WRITE   3800865\n0x401D76C0 WRITE   3800867\n0x401D7680 WRITE   3800874\n0x401D7640 WRITE   3800876\n0x401A9080 WRITE   3800909\n0x401D7780 WRITE   3801382\n0x401D7740 WRITE   3801384\n0x401BC940 WRITE   3801468\n0x401D7C00 WRITE   3801900\n0x401D7BC0 WRITE   3801902\n0x401D7A00 WRITE   3801909\n0x401D79C0 WRITE   3801911\n0x401D7900 WRITE   3801921\n0x401D78C0 WRITE   3801923\n0x401D7880 WRITE   3801928\n0x401D7840 WRITE   3801931\n0x401A90C0 WRITE   3801956\n0x401D7980 WRITE   3802395\n0x401D7940 WRITE   3802397\n0x401BC980 WRITE   3802481\n0x401D7B00 WRITE   3802873\n0x401D7AC0 WRITE   3802875\n0x401D7A80 WRITE   3802882\n0x401D7A40 WRITE   3802884\n0x401A9100 WRITE   3802917\n0x401D7B80 WRITE   3803388\n0x401D7B40 WRITE   3803390\n0x401BC9C0 WRITE   3803474\n0x401D7E00 WRITE   3803899\n0x401D7DC0 WRITE   3803901\n0x401D7D00 WRITE   3803908\n0x401D7CC0 WRITE   3803910\n0x401D7C80 WRITE   3803920\n0x401D7C40 WRITE   3803922\n0x401A9140 WRITE   3803949\n0x401D7D80 WRITE   3804397\n0x401D7D40 WRITE   3804399\n0x401BCA00 WRITE   3804483\n0x401D7F00 WRITE   3804884\n0x401D7EC0 WRITE   3804886\n0x401D7E80 WRITE   3804893\n0x401D7E40 WRITE   3804895\n0x401A9180 WRITE   3804928\n0x401D7F80 WRITE   3805408\n0x401D7F40 WRITE   3805410\n0x401BCA40 WRITE   3805494\n0x401D9FC0 WRITE   3805978\n0x401DA000 WRITE   3806012\n0x401D9000 WRITE   3806126\n0x401D8FC0 WRITE   3806128\n0x401D8800 WRITE   3806135\n0x401D87C0 WRITE   3806137\n0x401D8400 WRITE   3806147\n0x401D83C0 WRITE   3806149\n0x401D8200 WRITE   3806154\n0x401D81C0 WRITE   3806157\n0x401D8100 WRITE   3806160\n0x401D80C0 WRITE   3806163\n0x401D8080 WRITE   3806166\n0x401D8040 WRITE   3806169\n0x401A91C0 WRITE   3806202\n0x401D8180 WRITE   3806632\n0x401D8140 WRITE   3806634\n0x401BCA80 WRITE   3806718\n0x401D8300 WRITE   3807097\n0x401D82C0 WRITE   3807099\n0x401D8280 WRITE   3807106\n0x401D8240 WRITE   3807108\n0x401A9200 WRITE   3807141\n0x401D8380 WRITE   3807604\n0x401D8340 WRITE   3807606\n0x401BCAC0 WRITE   3807690\n0x401D8600 WRITE   3808101\n0x401D85C0 WRITE   3808103\n0x401D8500 WRITE   3808110\n0x401D84C0 WRITE   3808112\n0x401D8480 WRITE   3808122\n0x401D8440 WRITE   3808124\n0x401A9240 WRITE   3808151\n0x401D8580 WRITE   3808592\n0x401D8540 WRITE   3808594\n0x401BCB00 WRITE   3808678\n0x401D8700 WRITE   3809066\n0x401D86C0 WRITE   3809068\n0x401D8680 WRITE   3809075\n0x401D8640 WRITE   3809077\n0x401A9280 WRITE   3809110\n0x401D8780 WRITE   3809583\n0x401D8740 WRITE   3809585\n0x401BCB40 WRITE   3809669\n0x401D8C00 WRITE   3810095\n0x401D8BC0 WRITE   3810097\n0x401D8A00 WRITE   3810104\n0x401D89C0 WRITE   3810106\n0x401D8900 WRITE   3810116\n0x401D88C0 WRITE   3810118\n0x401D8880 WRITE   3810123\n0x401D8840 WRITE   3810126\n0x401A92C0 WRITE   3810151\n0x401D8980 WRITE   3810590\n0x401D8940 WRITE   3810592\n0x401BCB80 WRITE   3810676\n0x401D8B00 WRITE   3811062\n0x401D8AC0 WRITE   3811064\n0x401D8A80 WRITE   3811071\n0x401D8A40 WRITE   3811073\n0x401A9300 WRITE   3811106\n0x401D8B80 WRITE   3811577\n0x401D8B40 WRITE   3811579\n0x401BCBC0 WRITE   3811663\n0x401D8E00 WRITE   3812082\n0x401D8DC0 WRITE   3812084\n0x401D8D00 WRITE   3812091\n0x401D8CC0 WRITE   3812093\n0x401D8C80 WRITE   3812103\n0x401D8C40 WRITE   3812105\n0x401A9340 WRITE   3812132\n0x401D8D80 WRITE   3812580\n0x401D8D40 WRITE   3812582\n0x401BCC00 WRITE   3812666\n0x401D8F00 WRITE   3813061\n0x401D8EC0 WRITE   3813063\n0x401D8E80 WRITE   3813070\n0x401D8E40 WRITE   3813072\n0x401A9380 WRITE   3813105\n0x401D8F80 WRITE   3813585\n0x401D8F40 WRITE   3813587\n0x401BCC40 WRITE   3813671\n0x401D9800 WRITE   3814103\n0x401D97C0 WRITE   3814105\n0x401D9400 WRITE   3814112\n0x401D93C0 WRITE   3814114\n0x401D9200 WRITE   3814124\n0x401D91C0 WRITE   3814126\n0x401D9100 WRITE   3814131\n0x401D90C0 WRITE   3814134\n0x401D9080 WRITE   3814137\n0x401D9040 WRITE   3814140\n0x401A93C0 WRITE   3814165\n0x401D9180 WRITE   3814596\n0x401D9140 WRITE   3814598\n0x401BCC80 WRITE   3814682\n0x401D9300 WRITE   3815066\n0x401D92C0 WRITE   3815068\n0x401D9280 WRITE   3815075\n0x401D9240 WRITE   3815077\n0x401A9400 WRITE   3815110\n0x401D9380 WRITE   3815573\n0x401D9340 WRITE   3815575\n0x401BCCC0 WRITE   3815659\n0x401D9600 WRITE   3816076\n0x401D95C0 WRITE   3816078\n0x401D9500 WRITE   3816085\n0x401D94C0 WRITE   3816087\n0x401D9480 WRITE   3816097\n0x401D9440 WRITE   3816099\n0x401A9440 WRITE   3816126\n0x401D9580 WRITE   3816567\n0x401D9540 WRITE   3816569\n0x401BCD00 WRITE   3816653\n0x401D9700 WRITE   3817047\n0x401D96C0 WRITE   3817049\n0x401D9680 WRITE   3817056\n0x401D9640 WRITE   3817058\n0x401A9480 WRITE   3817091\n0x401D9780 WRITE   3817564\n0x401D9740 WRITE   3817566\n0x401BCD40 WRITE   3817650\n0x401D9C00 WRITE   3818082\n0x401D9BC0 WRITE   3818084\n0x401D9A00 WRITE   3818091\n0x401D99C0 WRITE   3818093\n0x401D9900 WRITE   3818103\n0x401D98C0 WRITE   3818105\n0x401D9880 WRITE   3818110\n0x401D9840 WRITE   3818113\n0x401A94C0 WRITE   3818138\n0x401D9980 WRITE   3818577\n0x401D9940 WRITE   3818579\n0x401BCD80 WRITE   3818663\n0x401D9B00 WRITE   3819055\n0x401D9AC0 WRITE   3819057\n0x401D9A80 WRITE   3819064\n0x401D9A40 WRITE   3819066\n0x401A9500 WRITE   3819099\n0x401D9B80 WRITE   3819570\n0x401D9B40 WRITE   3819572\n0x401BCDC0 WRITE   3819656\n0x401D9E00 WRITE   3820081\n0x401D9DC0 WRITE   3820083\n0x401D9D00 WRITE   3820090\n0x401D9CC0 WRITE   3820092\n0x401D9C80 WRITE   3820102\n0x401D9C40 WRITE   3820104\n0x401A9540 WRITE   3820131\n0x401D9D80 WRITE   3820579\n0x401D9D40 WRITE   3820581\n0x401BCE00 WRITE   3820665\n0x401D9F00 WRITE   3821066\n0x401D9EC0 WRITE   3821068\n0x401D9E80 WRITE   3821075\n0x401D9E40 WRITE   3821077\n0x401A9580 WRITE   3821110\n0x401D9F80 WRITE   3821590\n0x401D9F40 WRITE   3821592\n0x401BCE40 WRITE   3821676\n0x401DBFC0 WRITE   3822160\n0x401DC000 WRITE   3822194\n0x401DB000 WRITE   3822308\n0x401DAFC0 WRITE   3822310\n0x401DA800 WRITE   3822317\n0x401DA7C0 WRITE   3822319\n0x401DA400 WRITE   3822329\n0x401DA3C0 WRITE   3822331\n0x401DA200 WRITE   3822336\n0x401DA1C0 WRITE   3822339\n0x401DA100 WRITE   3822342\n0x401DA0C0 WRITE   3822345\n0x401DA080 WRITE   3822348\n0x401DA040 WRITE   3822351\n0x401A95C0 WRITE   3822384\n0x401DA180 WRITE   3822814\n0x401DA140 WRITE   3822816\n0x401BCE80 WRITE   3822900\n0x401DA300 WRITE   3823279\n0x401DA2C0 WRITE   3823281\n0x401DA280 WRITE   3823288\n0x401DA240 WRITE   3823290\n0x401A9600 WRITE   3823323\n0x401DA380 WRITE   3823786\n0x401DA340 WRITE   3823788\n0x401BCEC0 WRITE   3823872\n0x401DA600 WRITE   3824283\n0x401DA5C0 WRITE   3824285\n0x401DA500 WRITE   3824292\n0x401DA4C0 WRITE   3824294\n0x401DA480 WRITE   3824304\n0x401DA440 WRITE   3824306\n0x401A9640 WRITE   3824333\n0x401DA580 WRITE   3824774\n0x401DA540 WRITE   3824776\n0x401BCF00 WRITE   3824860\n0x401DA700 WRITE   3825248\n0x401DA6C0 WRITE   3825250\n0x401DA680 WRITE   3825257\n0x401DA640 WRITE   3825259\n0x401A9680 WRITE   3825292\n0x401DA780 WRITE   3825765\n0x401DA740 WRITE   3825767\n0x401BCF40 WRITE   3825851\n0x401DAC00 WRITE   3826277\n0x401DABC0 WRITE   3826279\n0x401DAA00 WRITE   3826286\n0x401DA9C0 WRITE   3826288\n0x401DA900 WRITE   3826298\n0x401DA8C0 WRITE   3826300\n0x401DA880 WRITE   3826305\n0x401DA840 WRITE   3826308\n0x401A96C0 WRITE   3826333\n0x401DA980 WRITE   3826772\n0x401DA940 WRITE   3826774\n0x401BCF80 WRITE   3826858\n0x401DAB00 WRITE   3827244\n0x401DAAC0 WRITE   3827246\n0x401DAA80 WRITE   3827253\n0x401DAA40 WRITE   3827255\n0x401A9700 WRITE   3827288\n0x401DAB80 WRITE   3827759\n0x401DAB40 WRITE   3827761\n0x401BCFC0 WRITE   3827845\n0x401DAE00 WRITE   3828264\n0x401DADC0 WRITE   3828266\n0x401DAD00 WRITE   3828273\n0x401DACC0 WRITE   3828275\n0x401DAC80 WRITE   3828285\n0x401DAC40 WRITE   3828287\n0x401A9740 WRITE   3828314\n0x401DAD80 WRITE   3828762\n0x401DAD40 WRITE   3828764\n0x401BD000 WRITE   3828848\n0x401DAF00 WRITE   3829243\n0x401DAEC0 WRITE   3829245\n0x401DAE80 WRITE   3829252\n0x401DAE40 WRITE   3829254\n0x401A9780 WRITE   3829287\n0x401DAF80 WRITE   3829767\n0x401DAF40 WRITE   3829769\n0x401BD040 WRITE   3829853\n0x401DB800 WRITE   3830285\n0x401DB7C0 WRITE   3830287\n0x401DB400 WRITE   3830294\n0x401DB3C0 WRITE   3830296\n0x401DB200 WRITE   3830306\n0x401DB1C0 WRITE   3830308\n0x401DB100 WRITE   3830313\n0x401DB0C0 WRITE   3830316\n0x401DB080 WRITE   3830319\n0x401DB040 WRITE   3830322\n0x401A97C0 WRITE   3830347\n0x401DB180 WRITE   3830778\n0x401DB140 WRITE   3830780\n0x401BD080 WRITE   3830864\n0x401DB300 WRITE   3831248\n0x401DB2C0 WRITE   3831250\n0x401DB280 WRITE   3831257\n0x401DB240 WRITE   3831259\n0x401A9800 WRITE   3831292\n0x401DB380 WRITE   3831755\n0x401DB340 WRITE   3831757\n0x401BD0C0 WRITE   3831841\n0x401DB600 WRITE   3832258\n0x401DB5C0 WRITE   3832260\n0x401DB500 WRITE   3832267\n0x401DB4C0 WRITE   3832269\n0x401DB480 WRITE   3832279\n0x401DB440 WRITE   3832281\n0x401A9840 WRITE   3832308\n0x401DB580 WRITE   3832749\n0x401DB540 WRITE   3832751\n0x401BD100 WRITE   3832835\n0x401DB700 WRITE   3833229\n0x401DB6C0 WRITE   3833231\n0x401DB680 WRITE   3833238\n0x401DB640 WRITE   3833240\n0x401A9880 WRITE   3833273\n0x401DB780 WRITE   3833746\n0x401DB740 WRITE   3833748\n0x401BD140 WRITE   3833832\n0x401DBC00 WRITE   3834264\n0x401DBBC0 WRITE   3834266\n0x401DBA00 WRITE   3834273\n0x401DB9C0 WRITE   3834275\n0x401DB900 WRITE   3834285\n0x401DB8C0 WRITE   3834287\n0x401DB880 WRITE   3834292\n0x401DB840 WRITE   3834295\n0x401A98C0 WRITE   3834320\n0x401DB980 WRITE   3834759\n0x401DB940 WRITE   3834761\n0x401BD180 WRITE   3834845\n0x401DBB00 WRITE   3835237\n0x401DBAC0 WRITE   3835239\n0x401DBA80 WRITE   3835246\n0x401DBA40 WRITE   3835248\n0x401A9900 WRITE   3835281\n0x401DBB80 WRITE   3835752\n0x401DBB40 WRITE   3835754\n0x401BD1C0 WRITE   3835838\n0x401DBE00 WRITE   3836263\n0x401DBDC0 WRITE   3836265\n0x401DBD00 WRITE   3836272\n0x401DBCC0 WRITE   3836274\n0x401DBC80 WRITE   3836284\n0x401DBC40 WRITE   3836286\n0x401A9940 WRITE   3836313\n0x401DBD80 WRITE   3836761\n0x401DBD40 WRITE   3836763\n0x401BD200 WRITE   3836847\n0x401DBF00 WRITE   3837248\n0x401DBEC0 WRITE   3837250\n0x401DBE80 WRITE   3837257\n0x401DBE40 WRITE   3837259\n0x401A9980 WRITE   3837292\n0x401DBF80 WRITE   3837772\n0x401DBF40 WRITE   3837774\n0x401BD240 WRITE   3837858\n0x401DDFC0 WRITE   3838342\n0x401DE000 WRITE   3838376\n0x401DD000 WRITE   3838506\n0x401DCFC0 WRITE   3838508\n0x401DC800 WRITE   3838515\n0x401DC7C0 WRITE   3838517\n0x401DC400 WRITE   3838527\n0x401DC3C0 WRITE   3838529\n0x401DC200 WRITE   3838534\n0x401DC1C0 WRITE   3838537\n0x401DC100 WRITE   3838540\n0x401DC0C0 WRITE   3838543\n0x401DC080 WRITE   3838546\n0x401DC040 WRITE   3838549\n0x401A99C0 WRITE   3838582\n0x401DC180 WRITE   3839012\n0x401DC140 WRITE   3839014\n0x401BD280 WRITE   3839098\n0x401DC300 WRITE   3839477\n0x401DC2C0 WRITE   3839479\n0x401DC280 WRITE   3839486\n0x401DC240 WRITE   3839488\n0x401A9A00 WRITE   3839521\n0x401DC380 WRITE   3839984\n0x401DC340 WRITE   3839986\n0x401BD2C0 WRITE   3840070\n0x401DC600 WRITE   3840481\n0x401DC5C0 WRITE   3840483\n0x401DC500 WRITE   3840490\n0x401DC4C0 WRITE   3840492\n0x401DC480 WRITE   3840502\n0x401DC440 WRITE   3840504\n0x401A9A40 WRITE   3840531\n0x401DC580 WRITE   3840972\n0x401DC540 WRITE   3840974\n0x401BD300 WRITE   3841058\n0x401DC700 WRITE   3841446\n0x401DC6C0 WRITE   3841448\n0x401DC680 WRITE   3841455\n0x401DC640 WRITE   3841457\n0x401A9A80 WRITE   3841490\n0x401DC780 WRITE   3841963\n0x401DC740 WRITE   3841965\n0x401BD340 WRITE   3842049\n0x401DCC00 WRITE   3842475\n0x401DCBC0 WRITE   3842477\n0x401DCA00 WRITE   3842484\n0x401DC9C0 WRITE   3842486\n0x401DC900 WRITE   3842496\n0x401DC8C0 WRITE   3842498\n0x401DC880 WRITE   3842503\n0x401DC840 WRITE   3842506\n0x401A9AC0 WRITE   3842531\n0x401DC980 WRITE   3842970\n0x401DC940 WRITE   3842972\n0x401BD380 WRITE   3843056\n0x401DCB00 WRITE   3843442\n0x401DCAC0 WRITE   3843444\n0x401DCA80 WRITE   3843451\n0x401DCA40 WRITE   3843453\n0x401A9B00 WRITE   3843486\n0x401DCB80 WRITE   3843957\n0x401DCB40 WRITE   3843959\n0x401BD3C0 WRITE   3844043\n0x401DCE00 WRITE   3844462\n0x401DCDC0 WRITE   3844464\n0x401DCD00 WRITE   3844471\n0x401DCCC0 WRITE   3844473\n0x401DCC80 WRITE   3844483\n0x401DCC40 WRITE   3844485\n0x401A9B40 WRITE   3844512\n0x401DCD80 WRITE   3844960\n0x401DCD40 WRITE   3844962\n0x401BD400 WRITE   3845046\n0x401DCF00 WRITE   3845441\n0x401DCEC0 WRITE   3845443\n0x401DCE80 WRITE   3845450\n0x401DCE40 WRITE   3845452\n0x401A9B80 WRITE   3845485\n0x401DCF80 WRITE   3845965\n0x401DCF40 WRITE   3845967\n0x401BD440 WRITE   3846051\n0x401DD800 WRITE   3846483\n0x401DD7C0 WRITE   3846485\n0x401DD400 WRITE   3846492\n0x401DD3C0 WRITE   3846494\n0x401DD200 WRITE   3846504\n0x401DD1C0 WRITE   3846506\n0x401DD100 WRITE   3846511\n0x401DD0C0 WRITE   3846514\n0x401DD080 WRITE   3846517\n0x401DD040 WRITE   3846520\n0x401A9BC0 WRITE   3846545\n0x401DD180 WRITE   3846976\n0x401DD140 WRITE   3846978\n0x401BD480 WRITE   3847062\n0x401DD300 WRITE   3847446\n0x401DD2C0 WRITE   3847448\n0x401DD280 WRITE   3847455\n0x401DD240 WRITE   3847457\n0x401A9C00 WRITE   3847490\n0x401DD380 WRITE   3847953\n0x401DD340 WRITE   3847955\n0x401BD4C0 WRITE   3848039\n0x401DD600 WRITE   3848456\n0x401DD5C0 WRITE   3848458\n0x401DD500 WRITE   3848465\n0x401DD4C0 WRITE   3848467\n0x401DD480 WRITE   3848477\n0x401DD440 WRITE   3848479\n0x401A9C40 WRITE   3848506\n0x401DD580 WRITE   3848947\n0x401DD540 WRITE   3848949\n0x401BD500 WRITE   3849033\n0x401DD700 WRITE   3849427\n0x401DD6C0 WRITE   3849429\n0x401DD680 WRITE   3849436\n0x401DD640 WRITE   3849438\n0x401A9C80 WRITE   3849471\n0x401DD780 WRITE   3849944\n0x401DD740 WRITE   3849946\n0x401BD540 WRITE   3850030\n0x401DDC00 WRITE   3850462\n0x401DDBC0 WRITE   3850464\n0x401DDA00 WRITE   3850471\n0x401DD9C0 WRITE   3850473\n0x401DD900 WRITE   3850483\n0x401DD8C0 WRITE   3850485\n0x401DD880 WRITE   3850490\n0x401DD840 WRITE   3850493\n0x401A9CC0 WRITE   3850518\n0x401DD980 WRITE   3850957\n0x401DD940 WRITE   3850959\n0x401BD580 WRITE   3851043\n0x401DDB00 WRITE   3851435\n0x401DDAC0 WRITE   3851437\n0x401DDA80 WRITE   3851444\n0x401DDA40 WRITE   3851446\n0x401A9D00 WRITE   3851479\n0x401DDB80 WRITE   3851950\n0x401DDB40 WRITE   3851952\n0x401BD5C0 WRITE   3852036\n0x401DDE00 WRITE   3852461\n0x401DDDC0 WRITE   3852463\n0x401DDD00 WRITE   3852470\n0x401DDCC0 WRITE   3852472\n0x401DDC80 WRITE   3852482\n0x401DDC40 WRITE   3852484\n0x401A9D40 WRITE   3852511\n0x401DDD80 WRITE   3852959\n0x401DDD40 WRITE   3852961\n0x401BD600 WRITE   3853045\n0x401DDF00 WRITE   3853446\n0x401DDEC0 WRITE   3853448\n0x401DDE80 WRITE   3853455\n0x401DDE40 WRITE   3853457\n0x401A9D80 WRITE   3853490\n0x401DDF80 WRITE   3853970\n0x401DDF40 WRITE   3853972\n0x401BD640 WRITE   3854056\n0x401DFFC0 WRITE   3854540\n0x401E0000 WRITE   3854574\n0x401DF000 WRITE   3854704\n0x401DEFC0 WRITE   3854706\n0x401DE800 WRITE   3854713\n0x401DE7C0 WRITE   3854715\n0x401DE400 WRITE   3854725\n0x401DE3C0 WRITE   3854727\n0x401DE200 WRITE   3854732\n0x401DE1C0 WRITE   3854735\n0x401DE100 WRITE   3854738\n0x401DE0C0 WRITE   3854741\n0x401DE080 WRITE   3854744\n0x401DE040 WRITE   3854747\n0x401A9DC0 WRITE   3854780\n0x401DE180 WRITE   3855210\n0x401DE140 WRITE   3855212\n0x401BD680 WRITE   3855296\n0x401DE300 WRITE   3855675\n0x401DE2C0 WRITE   3855677\n0x401DE280 WRITE   3855684\n0x401DE240 WRITE   3855686\n0x401A9E00 WRITE   3855719\n0x401DE380 WRITE   3856182\n0x401DE340 WRITE   3856184\n0x401BD6C0 WRITE   3856268\n0x401DE600 WRITE   3856679\n0x401DE5C0 WRITE   3856681\n0x401DE500 WRITE   3856688\n0x401DE4C0 WRITE   3856690\n0x401DE480 WRITE   3856700\n0x401DE440 WRITE   3856702\n0x401A9E40 WRITE   3856729\n0x401DE580 WRITE   3857170\n0x401DE540 WRITE   3857172\n0x401BD700 WRITE   3857256\n0x401DE700 WRITE   3857644\n0x401DE6C0 WRITE   3857646\n0x401DE680 WRITE   3857653\n0x401DE640 WRITE   3857655\n0x401A9E80 WRITE   3857688\n0x401DE780 WRITE   3858161\n0x401DE740 WRITE   3858163\n0x401BD740 WRITE   3858247\n0x401DEC00 WRITE   3858673\n0x401DEBC0 WRITE   3858675\n0x401DEA00 WRITE   3858682\n0x401DE9C0 WRITE   3858684\n0x401DE900 WRITE   3858694\n0x401DE8C0 WRITE   3858696\n0x401DE880 WRITE   3858701\n0x401DE840 WRITE   3858704\n0x401A9EC0 WRITE   3858729\n0x401DE980 WRITE   3859168\n0x401DE940 WRITE   3859170\n0x401BD780 WRITE   3859254\n0x401DEB00 WRITE   3859640\n0x401DEAC0 WRITE   3859642\n0x401DEA80 WRITE   3859649\n0x401DEA40 WRITE   3859651\n0x401A9F00 WRITE   3859684\n0x401DEB80 WRITE   3860155\n0x401DEB40 WRITE   3860157\n0x401BD7C0 WRITE   3860241\n0x401DEE00 WRITE   3860660\n0x401DEDC0 WRITE   3860662\n0x401DED00 WRITE   3860669\n0x401DECC0 WRITE   3860671\n0x401DEC80 WRITE   3860681\n0x401DEC40 WRITE   3860683\n0x401A9F40 WRITE   3860710\n0x401DED80 WRITE   3861158\n0x401DED40 WRITE   3861160\n0x401BD800 WRITE   3861244\n0x401DEF00 WRITE   3861639\n0x401DEEC0 WRITE   3861641\n0x401DEE80 WRITE   3861648\n0x401DEE40 WRITE   3861650\n0x401A9F80 WRITE   3861683\n0x401DEF80 WRITE   3862163\n0x401DEF40 WRITE   3862165\n0x401BD840 WRITE   3862249\n0x401DF800 WRITE   3862681\n0x401DF7C0 WRITE   3862683\n0x401DF400 WRITE   3862690\n0x401DF3C0 WRITE   3862692\n0x401DF200 WRITE   3862702\n0x401DF1C0 WRITE   3862704\n0x401DF100 WRITE   3862709\n0x401DF0C0 WRITE   3862712\n0x401DF080 WRITE   3862715\n0x401DF040 WRITE   3862718\n0x401A9FC0 WRITE   3862743\n0x401DF180 WRITE   3863174\n0x401DF140 WRITE   3863176\n0x401BD880 WRITE   3863260\n0x401DF300 WRITE   3863644\n0x401DF2C0 WRITE   3863646\n0x401DF280 WRITE   3863653\n0x401DF240 WRITE   3863655\n0x401AA000 WRITE   3863688\n0x401DF380 WRITE   3864151\n0x401DF340 WRITE   3864153\n0x401BD8C0 WRITE   3864237\n0x401DF600 WRITE   3864654\n0x401DF5C0 WRITE   3864656\n0x401DF500 WRITE   3864663\n0x401DF4C0 WRITE   3864665\n0x401DF480 WRITE   3864675\n0x401DF440 WRITE   3864677\n0x401AA040 WRITE   3864704\n0x401DF580 WRITE   3865145\n0x401DF540 WRITE   3865147\n0x401BD900 WRITE   3865231\n0x401DF700 WRITE   3865625\n0x401DF6C0 WRITE   3865627\n0x401DF680 WRITE   3865634\n0x401DF640 WRITE   3865636\n0x401AA080 WRITE   3865669\n0x401DF780 WRITE   3866142\n0x401DF740 WRITE   3866144\n0x401BD940 WRITE   3866228\n0x401DFC00 WRITE   3866660\n0x401DFBC0 WRITE   3866662\n0x401DFA00 WRITE   3866669\n0x401DF9C0 WRITE   3866671\n0x401DF900 WRITE   3866681\n0x401DF8C0 WRITE   3866683\n0x401DF880 WRITE   3866688\n0x401DF840 WRITE   3866691\n0x401AA0C0 WRITE   3866716\n0x401DF980 WRITE   3867155\n0x401DF940 WRITE   3867157\n0x401BD980 WRITE   3867241\n0x401DFB00 WRITE   3867633\n0x401DFAC0 WRITE   3867635\n0x401DFA80 WRITE   3867642\n0x401DFA40 WRITE   3867644\n0x401AA100 WRITE   3867677\n0x401DFB80 WRITE   3868148\n0x401DFB40 WRITE   3868150\n0x401BD9C0 WRITE   3868234\n0x401DFE00 WRITE   3868659\n0x401DFDC0 WRITE   3868661\n0x401DFD00 WRITE   3868668\n0x401DFCC0 WRITE   3868670\n0x401DFC80 WRITE   3868680\n0x401DFC40 WRITE   3868682\n0x401AA140 WRITE   3868709\n0x401DFD80 WRITE   3869157\n0x401DFD40 WRITE   3869159\n0x401BDA00 WRITE   3869243\n0x401DFF00 WRITE   3869644\n0x401DFEC0 WRITE   3869646\n0x401DFE80 WRITE   3869653\n0x401DFE40 WRITE   3869655\n0x401AA180 WRITE   3869688\n0x401DFF80 WRITE   3870168\n0x401DFF40 WRITE   3870170\n0x401BDA40 WRITE   3870254\n0x401E1FC0 WRITE   3870738\n0x401E2000 WRITE   3870772\n0x401E1000 WRITE   3870905\n0x401E0FC0 WRITE   3870907\n0x401E0800 WRITE   3870914\n0x401E07C0 WRITE   3870916\n0x401E0400 WRITE   3870926\n0x401E03C0 WRITE   3870928\n0x401E0200 WRITE   3870933\n0x401E01C0 WRITE   3870936\n0x401E0100 WRITE   3870939\n0x401E00C0 WRITE   3870942\n0x401E0080 WRITE   3870945\n0x401E0040 WRITE   3870948\n0x401AA1C0 WRITE   3870981\n0x401E0180 WRITE   3871411\n0x401E0140 WRITE   3871413\n0x401BDA80 WRITE   3871497\n0x401E0300 WRITE   3871876\n0x401E02C0 WRITE   3871878\n0x401E0280 WRITE   3871885\n0x401E0240 WRITE   3871887\n0x401AA200 WRITE   3871920\n0x401E0380 WRITE   3872383\n0x401E0340 WRITE   3872385\n0x401BDAC0 WRITE   3872469\n0x401E0600 WRITE   3872880\n0x401E05C0 WRITE   3872882\n0x401E0500 WRITE   3872889\n0x401E04C0 WRITE   3872891\n0x401E0480 WRITE   3872901\n0x401E0440 WRITE   3872903\n0x401AA240 WRITE   3872930\n0x401E0580 WRITE   3873371\n0x401E0540 WRITE   3873373\n0x401BDB00 WRITE   3873457\n0x401E0700 WRITE   3873845\n0x401E06C0 WRITE   3873847\n0x401E0680 WRITE   3873854\n0x401E0640 WRITE   3873856\n0x401AA280 WRITE   3873889\n0x401E0780 WRITE   3874362\n0x401E0740 WRITE   3874364\n0x401BDB40 WRITE   3874448\n0x401E0C00 WRITE   3874874\n0x401E0BC0 WRITE   3874876\n0x401E0A00 WRITE   3874883\n0x401E09C0 WRITE   3874885\n0x401E0900 WRITE   3874895\n0x401E08C0 WRITE   3874897\n0x401E0880 WRITE   3874902\n0x401E0840 WRITE   3874905\n0x401AA2C0 WRITE   3874930\n0x401E0980 WRITE   3875369\n0x401E0940 WRITE   3875371\n0x401BDB80 WRITE   3875455\n0x401E0B00 WRITE   3875841\n0x401E0AC0 WRITE   3875843\n0x401E0A80 WRITE   3875850\n0x401E0A40 WRITE   3875852\n0x401AA300 WRITE   3875885\n0x401E0B80 WRITE   3876356\n0x401E0B40 WRITE   3876358\n0x401BDBC0 WRITE   3876442\n0x401E0E00 WRITE   3876861\n0x401E0DC0 WRITE   3876863\n0x401E0D00 WRITE   3876870\n0x401E0CC0 WRITE   3876872\n0x401E0C80 WRITE   3876882\n0x401E0C40 WRITE   3876884\n0x401AA340 WRITE   3876911\n0x401E0D80 WRITE   3877359\n0x401E0D40 WRITE   3877361\n0x401BDC00 WRITE   3877445\n0x401E0F00 WRITE   3877840\n0x401E0EC0 WRITE   3877842\n0x401E0E80 WRITE   3877849\n0x401E0E40 WRITE   3877851\n0x401AA380 WRITE   3877884\n0x401E0F80 WRITE   3878364\n0x401E0F40 WRITE   3878366\n0x401BDC40 WRITE   3878450\n0x401E1800 WRITE   3878882\n0x401E17C0 WRITE   3878884\n0x401E1400 WRITE   3878891\n0x401E13C0 WRITE   3878893\n0x401E1200 WRITE   3878903\n0x401E11C0 WRITE   3878905\n0x401E1100 WRITE   3878910\n0x401E10C0 WRITE   3878913\n0x401E1080 WRITE   3878916\n0x401E1040 WRITE   3878919\n0x401AA3C0 WRITE   3878944\n0x401E1180 WRITE   3879375\n0x401E1140 WRITE   3879377\n0x401BDC80 WRITE   3879461\n0x401E1300 WRITE   3879845\n0x401E12C0 WRITE   3879847\n0x401E1280 WRITE   3879854\n0x401E1240 WRITE   3879856\n0x401AA400 WRITE   3879889\n0x401E1380 WRITE   3880352\n0x401E1340 WRITE   3880354\n0x401BDCC0 WRITE   3880438\n0x401E1600 WRITE   3880855\n0x401E15C0 WRITE   3880857\n0x401E1500 WRITE   3880864\n0x401E14C0 WRITE   3880866\n0x401E1480 WRITE   3880876\n0x401E1440 WRITE   3880878\n0x401AA440 WRITE   3880905\n0x401E1580 WRITE   3881346\n0x401E1540 WRITE   3881348\n0x401BDD00 WRITE   3881432\n0x401E1700 WRITE   3881826\n0x401E16C0 WRITE   3881828\n0x401E1680 WRITE   3881835\n0x401E1640 WRITE   3881837\n0x401AA480 WRITE   3881870\n0x401E1780 WRITE   3882343\n0x401E1740 WRITE   3882345\n0x401BDD40 WRITE   3882429\n0x401E1C00 WRITE   3882861\n0x401E1BC0 WRITE   3882863\n0x401E1A00 WRITE   3882870\n0x401E19C0 WRITE   3882872\n0x401E1900 WRITE   3882882\n0x401E18C0 WRITE   3882884\n0x401E1880 WRITE   3882889\n0x401E1840 WRITE   3882892\n0x401AA4C0 WRITE   3882917\n0x401E1980 WRITE   3883356\n0x401E1940 WRITE   3883358\n0x401BDD80 WRITE   3883442\n0x401E1B00 WRITE   3883834\n0x401E1AC0 WRITE   3883836\n0x401E1A80 WRITE   3883843\n0x401E1A40 WRITE   3883845\n0x401AA500 WRITE   3883878\n0x401E1B80 WRITE   3884349\n0x401E1B40 WRITE   3884351\n0x401BDDC0 WRITE   3884435\n0x401E1E00 WRITE   3884860\n0x401E1DC0 WRITE   3884862\n0x401E1D00 WRITE   3884869\n0x401E1CC0 WRITE   3884871\n0x401E1C80 WRITE   3884881\n0x401E1C40 WRITE   3884883\n0x401AA540 WRITE   3884910\n0x401E1D80 WRITE   3885358\n0x401E1D40 WRITE   3885360\n0x401BDE00 WRITE   3885444\n0x401E1F00 WRITE   3885845\n0x401E1EC0 WRITE   3885847\n0x401E1E80 WRITE   3885854\n0x401E1E40 WRITE   3885856\n0x401AA580 WRITE   3885889\n0x401E1F80 WRITE   3886369\n0x401E1F40 WRITE   3886371\n0x401BDE40 WRITE   3886455\n0x401E3FC0 WRITE   3886939\n0x401E4000 WRITE   3886973\n0x401E3000 WRITE   3887094\n0x401E2FC0 WRITE   3887096\n0x401E2800 WRITE   3887103\n0x401E27C0 WRITE   3887105\n0x401E2400 WRITE   3887115\n0x401E23C0 WRITE   3887117\n0x401E2200 WRITE   3887122\n0x401E21C0 WRITE   3887125\n0x401E2100 WRITE   3887128\n0x401E20C0 WRITE   3887131\n0x401E2080 WRITE   3887134\n0x401E2040 WRITE   3887137\n0x401AA5C0 WRITE   3887170\n0x401E2180 WRITE   3887600\n0x401E2140 WRITE   3887602\n0x401BDE80 WRITE   3887686\n0x401E2300 WRITE   3888065\n0x401E22C0 WRITE   3888067\n0x401E2280 WRITE   3888074\n0x401E2240 WRITE   3888076\n0x401AA600 WRITE   3888109\n0x401E2380 WRITE   3888572\n0x401E2340 WRITE   3888574\n0x401BDEC0 WRITE   3888658\n0x401E2600 WRITE   3889069\n0x401E25C0 WRITE   3889071\n0x401E2500 WRITE   3889078\n0x401E24C0 WRITE   3889080\n0x401E2480 WRITE   3889090\n0x401E2440 WRITE   3889092\n0x401AA640 WRITE   3889119\n0x401E2580 WRITE   3889560\n0x401E2540 WRITE   3889562\n0x401BDF00 WRITE   3889646\n0x401E2700 WRITE   3890034\n0x401E26C0 WRITE   3890036\n0x401E2680 WRITE   3890043\n0x401E2640 WRITE   3890045\n0x401AA680 WRITE   3890078\n0x401E2780 WRITE   3890551\n0x401E2740 WRITE   3890553\n0x401BDF40 WRITE   3890637\n0x401E2C00 WRITE   3891063\n0x401E2BC0 WRITE   3891065\n0x401E2A00 WRITE   3891072\n0x401E29C0 WRITE   3891074\n0x401E2900 WRITE   3891084\n0x401E28C0 WRITE   3891086\n0x401E2880 WRITE   3891091\n0x401E2840 WRITE   3891094\n0x401AA6C0 WRITE   3891119\n0x401E2980 WRITE   3891558\n0x401E2940 WRITE   3891560\n0x401BDF80 WRITE   3891644\n0x401E2B00 WRITE   3892030\n0x401E2AC0 WRITE   3892032\n0x401E2A80 WRITE   3892039\n0x401E2A40 WRITE   3892041\n0x401AA700 WRITE   3892074\n0x401E2B80 WRITE   3892545\n0x401E2B40 WRITE   3892547\n0x401BDFC0 WRITE   3892631\n0x401E2E00 WRITE   3893050\n0x401E2DC0 WRITE   3893052\n0x401E2D00 WRITE   3893059\n0x401E2CC0 WRITE   3893061\n0x401E2C80 WRITE   3893071\n0x401E2C40 WRITE   3893073\n0x401AA740 WRITE   3893100\n0x401E2D80 WRITE   3893548\n0x401E2D40 WRITE   3893550\n0x401BE000 WRITE   3893634\n0x401E2F00 WRITE   3894029\n0x401E2EC0 WRITE   3894031\n0x401E2E80 WRITE   3894038\n0x401E2E40 WRITE   3894040\n0x401AA780 WRITE   3894073\n0x401E2F80 WRITE   3894553\n0x401E2F40 WRITE   3894555\n0x401BE040 WRITE   3894639\n0x401E3800 WRITE   3895071\n0x401E37C0 WRITE   3895073\n0x401E3400 WRITE   3895080\n0x401E33C0 WRITE   3895082\n0x401E3200 WRITE   3895092\n0x401E31C0 WRITE   3895094\n0x401E3100 WRITE   3895099\n0x401E30C0 WRITE   3895102\n0x401E3080 WRITE   3895105\n0x401E3040 WRITE   3895108\n0x401AA7C0 WRITE   3895133\n0x401E3180 WRITE   3895564\n0x401E3140 WRITE   3895566\n0x401BE080 WRITE   3895650\n0x401E3300 WRITE   3896034\n0x401E32C0 WRITE   3896036\n0x401E3280 WRITE   3896043\n0x401E3240 WRITE   3896045\n0x401AA800 WRITE   3896078\n0x401E3380 WRITE   3896541\n0x401E3340 WRITE   3896543\n0x401BE0C0 WRITE   3896627\n0x401E3600 WRITE   3897044\n0x401E35C0 WRITE   3897046\n0x401E3500 WRITE   3897053\n0x401E34C0 WRITE   3897055\n0x401E3480 WRITE   3897065\n0x401E3440 WRITE   3897067\n0x401AA840 WRITE   3897094\n0x401E3580 WRITE   3897535\n0x401E3540 WRITE   3897537\n0x401BE100 WRITE   3897621\n0x401E3700 WRITE   3898015\n0x401E36C0 WRITE   3898017\n0x401E3680 WRITE   3898024\n0x401E3640 WRITE   3898026\n0x401E3780 WRITE   3898532\n0x401E3740 WRITE   3898534\n0x401BE140 WRITE   3898618\n0x401E3C00 WRITE   3899050\n0x401E3BC0 WRITE   3899052\n0x401E3A00 WRITE   3899059\n0x401E39C0 WRITE   3899061\n0x401E3900 WRITE   3899071\n0x401E38C0 WRITE   3899073\n0x401E3880 WRITE   3899078\n0x401E3840 WRITE   3899081\n0x401AA8C0 WRITE   3899106\n0x401E3980 WRITE   3899545\n0x401E3940 WRITE   3899547\n0x401BE180 WRITE   3899631\n0x401E3B00 WRITE   3900023\n0x401E3AC0 WRITE   3900025\n0x401E3A80 WRITE   3900032\n0x401E3A40 WRITE   3900034\n0x401AA900 WRITE   3900067\n0x401E3B80 WRITE   3900538\n0x401E3B40 WRITE   3900540\n0x401BE1C0 WRITE   3900624\n0x401E3E00 WRITE   3901049\n0x401E3DC0 WRITE   3901051\n0x401E3D00 WRITE   3901058\n0x401E3CC0 WRITE   3901060\n0x401E3C80 WRITE   3901070\n0x401E3C40 WRITE   3901072\n0x401AA940 WRITE   3901099\n0x401E3D80 WRITE   3901547\n0x401E3D40 WRITE   3901549\n0x401BE200 WRITE   3901633\n0x401E3F00 WRITE   3902034\n0x401E3EC0 WRITE   3902036\n0x401E3E80 WRITE   3902043\n0x401E3E40 WRITE   3902045\n0x401AA980 WRITE   3902078\n0x401E3F80 WRITE   3902558\n0x401E3F40 WRITE   3902560\n0x401BE240 WRITE   3902644\n0x401E5FC0 WRITE   3903128\n0x401E6000 WRITE   3903162\n0x401E5000 WRITE   3903283\n0x401E4FC0 WRITE   3903285\n0x401E4800 WRITE   3903292\n0x401E47C0 WRITE   3903294\n0x401E4400 WRITE   3903304\n0x401E43C0 WRITE   3903306\n0x401E4200 WRITE   3903311\n0x401E41C0 WRITE   3903314\n0x401E4100 WRITE   3903317\n0x401E40C0 WRITE   3903320\n0x401E4080 WRITE   3903323\n0x401E4040 WRITE   3903326\n0x401AA9C0 WRITE   3903359\n0x401E4180 WRITE   3903789\n0x401E4140 WRITE   3903791\n0x401BE280 WRITE   3903875\n0x401E4300 WRITE   3904254\n0x401E42C0 WRITE   3904256\n0x401E4280 WRITE   3904263\n0x401E4240 WRITE   3904265\n0x401AAA00 WRITE   3904298\n0x401E4380 WRITE   3904761\n0x401E4340 WRITE   3904763\n0x401BE2C0 WRITE   3904847\n0x401E4600 WRITE   3905258\n0x401E45C0 WRITE   3905260\n0x401E4500 WRITE   3905267\n0x401E44C0 WRITE   3905269\n0x401E4480 WRITE   3905279\n0x401E4440 WRITE   3905281\n0x401AAA40 WRITE   3905308\n0x401E4580 WRITE   3905749\n0x401E4540 WRITE   3905751\n0x401BE300 WRITE   3905835\n0x401E4700 WRITE   3906223\n0x401E46C0 WRITE   3906225\n0x401E4680 WRITE   3906232\n0x401E4640 WRITE   3906234\n0x401AAA80 WRITE   3906267\n0x401E4780 WRITE   3906740\n0x401E4740 WRITE   3906742\n0x401BE340 WRITE   3906826\n0x401E4C00 WRITE   3907252\n0x401E4BC0 WRITE   3907254\n0x401E4A00 WRITE   3907261\n0x401E49C0 WRITE   3907263\n0x401E4900 WRITE   3907273\n0x401E48C0 WRITE   3907275\n0x401E4880 WRITE   3907280\n0x401E4840 WRITE   3907283\n0x401AAAC0 WRITE   3907308\n0x401E4980 WRITE   3907747\n0x401E4940 WRITE   3907749\n0x401BE380 WRITE   3907833\n0x401E4B00 WRITE   3908219\n0x401E4AC0 WRITE   3908221\n0x401E4A80 WRITE   3908228\n0x401E4A40 WRITE   3908230\n0x401AAB00 WRITE   3908263\n0x401E4B80 WRITE   3908734\n0x401E4B40 WRITE   3908736\n0x401BE3C0 WRITE   3908820\n0x401E4E00 WRITE   3909239\n0x401E4DC0 WRITE   3909241\n0x401E4D00 WRITE   3909248\n0x401E4CC0 WRITE   3909250\n0x401E4C80 WRITE   3909260\n0x401E4C40 WRITE   3909262\n0x401AAB40 WRITE   3909289\n0x401E4D80 WRITE   3909737\n0x401E4D40 WRITE   3909739\n0x401BE400 WRITE   3909823\n0x401E4F00 WRITE   3910218\n0x401E4EC0 WRITE   3910220\n0x401E4E80 WRITE   3910227\n0x401E4E40 WRITE   3910229\n0x401AAB80 WRITE   3910262\n0x401E4F80 WRITE   3910742\n0x401E4F40 WRITE   3910744\n0x401BE440 WRITE   3910828\n0x401E5800 WRITE   3911260\n0x401E57C0 WRITE   3911262\n0x401E5400 WRITE   3911269\n0x401E53C0 WRITE   3911271\n0x401E5200 WRITE   3911281\n0x401E51C0 WRITE   3911283\n0x401E5100 WRITE   3911288\n0x401E50C0 WRITE   3911291\n0x401E5080 WRITE   3911294\n0x401E5040 WRITE   3911297\n0x401AABC0 WRITE   3911322\n0x401E5180 WRITE   3911753\n0x401E5140 WRITE   3911755\n0x401BE480 WRITE   3911839\n0x401E5300 WRITE   3912223\n0x401E52C0 WRITE   3912225\n0x401E5280 WRITE   3912232\n0x401E5240 WRITE   3912234\n0x401AAC00 WRITE   3912267\n0x401E5380 WRITE   3912730\n0x401E5340 WRITE   3912732\n0x401BE4C0 WRITE   3912816\n0x401E5600 WRITE   3913233\n0x401E55C0 WRITE   3913235\n0x401E5500 WRITE   3913242\n0x401E54C0 WRITE   3913244\n0x401E5480 WRITE   3913254\n0x401E5440 WRITE   3913256\n0x401AAC40 WRITE   3913283\n0x401E5580 WRITE   3913724\n0x401E5540 WRITE   3913726\n0x401BE500 WRITE   3913810\n0x401E5700 WRITE   3914204\n0x401E56C0 WRITE   3914206\n0x401E5680 WRITE   3914213\n0x401E5640 WRITE   3914215\n0x401AAC80 WRITE   3914248\n0x401E5780 WRITE   3914721\n0x401E5740 WRITE   3914723\n0x401BE540 WRITE   3914807\n0x401E5C00 WRITE   3915239\n0x401E5BC0 WRITE   3915241\n0x401E5A00 WRITE   3915248\n0x401E59C0 WRITE   3915250\n0x401E5900 WRITE   3915260\n0x401E58C0 WRITE   3915262\n0x401E5880 WRITE   3915267\n0x401E5840 WRITE   3915270\n0x401AACC0 WRITE   3915295\n0x401E5980 WRITE   3915734\n0x401E5940 WRITE   3915736\n0x401BE580 WRITE   3915820\n0x401E5B00 WRITE   3916212\n0x401E5AC0 WRITE   3916214\n0x401E5A80 WRITE   3916221\n0x401E5A40 WRITE   3916223\n0x401AAD00 WRITE   3916256\n0x401E5B80 WRITE   3916727\n0x401E5B40 WRITE   3916729\n0x401BE5C0 WRITE   3916813\n0x401E5E00 WRITE   3917238\n0x401E5DC0 WRITE   3917240\n0x401E5D00 WRITE   3917247\n0x401E5CC0 WRITE   3917249\n0x401E5C80 WRITE   3917259\n0x401E5C40 WRITE   3917261\n0x401AAD40 WRITE   3917288\n0x401E5D80 WRITE   3917736\n0x401E5D40 WRITE   3917738\n0x401BE600 WRITE   3917822\n0x401E5F00 WRITE   3918223\n0x401E5EC0 WRITE   3918225\n0x401E5E80 WRITE   3918232\n0x401E5E40 WRITE   3918234\n0x401AAD80 WRITE   3918267\n0x401E5F80 WRITE   3918747\n0x401E5F40 WRITE   3918749\n0x401BE640 WRITE   3918833\n0x401E7FC0 WRITE   3919317\n0x401E8000 WRITE   3919351\n0x401E7000 WRITE   3919465\n0x401E6FC0 WRITE   3919467\n0x401E6800 WRITE   3919474\n0x401E67C0 WRITE   3919476\n0x401E6400 WRITE   3919486\n0x401E63C0 WRITE   3919488\n0x401E6200 WRITE   3919493\n0x401E61C0 WRITE   3919496\n0x401E6100 WRITE   3919499\n0x401E60C0 WRITE   3919502\n0x401E6080 WRITE   3919505\n0x401E6040 WRITE   3919508\n0x401AADC0 WRITE   3919541\n0x401E6180 WRITE   3919971\n0x401E6140 WRITE   3919973\n0x401BE680 WRITE   3920057\n0x401E6300 WRITE   3920436\n0x401E62C0 WRITE   3920438\n0x401E6280 WRITE   3920445\n0x401E6240 WRITE   3920447\n0x401AAE00 WRITE   3920480\n0x401E6380 WRITE   3920943\n0x401E6340 WRITE   3920945\n0x401BE6C0 WRITE   3921029\n0x401E6600 WRITE   3921440\n0x401E65C0 WRITE   3921442\n0x401E6500 WRITE   3921449\n0x401E64C0 WRITE   3921451\n0x401E6480 WRITE   3921461\n0x401E6440 WRITE   3921463\n0x401AAE40 WRITE   3921490\n0x401E6580 WRITE   3921931\n0x401E6540 WRITE   3921933\n0x401BE700 WRITE   3922017\n0x401E6700 WRITE   3922405\n0x401E66C0 WRITE   3922407\n0x401E6680 WRITE   3922414\n0x401E6640 WRITE   3922416\n0x401AAE80 WRITE   3922449\n0x401E6780 WRITE   3922922\n0x401E6740 WRITE   3922924\n0x401BE740 WRITE   3923008\n0x401E6C00 WRITE   3923434\n0x401E6BC0 WRITE   3923436\n0x401E6A00 WRITE   3923443\n0x401E69C0 WRITE   3923445\n0x401E6900 WRITE   3923455\n0x401E68C0 WRITE   3923457\n0x401E6880 WRITE   3923462\n0x401E6840 WRITE   3923465\n0x401AAEC0 WRITE   3923490\n0x401E6980 WRITE   3923929\n0x401E6940 WRITE   3923931\n0x401BE780 WRITE   3924015\n0x401E6B00 WRITE   3924401\n0x401E6AC0 WRITE   3924403\n0x401E6A80 WRITE   3924410\n0x401E6A40 WRITE   3924412\n0x401AAF00 WRITE   3924445\n0x401E6B80 WRITE   3924916\n0x401E6B40 WRITE   3924918\n0x401BE7C0 WRITE   3925002\n0x401E6E00 WRITE   3925421\n0x401E6DC0 WRITE   3925423\n0x401E6D00 WRITE   3925430\n0x401E6CC0 WRITE   3925432\n0x401E6C80 WRITE   3925442\n0x401E6C40 WRITE   3925444\n0x401AAF40 WRITE   3925471\n0x401E6D80 WRITE   3925919\n0x401E6D40 WRITE   3925921\n0x401BE800 WRITE   3926005\n0x401E6F00 WRITE   3926400\n0x401E6EC0 WRITE   3926402\n0x401E6E80 WRITE   3926409\n0x401E6E40 WRITE   3926411\n0x401AAF80 WRITE   3926444\n0x401E6F80 WRITE   3926924\n0x401E6F40 WRITE   3926926\n0x401BE840 WRITE   3927010\n0x401E7800 WRITE   3927442\n0x401E77C0 WRITE   3927444\n0x401E7400 WRITE   3927451\n0x401E73C0 WRITE   3927453\n0x401E7200 WRITE   3927463\n0x401E71C0 WRITE   3927465\n0x401E7100 WRITE   3927470\n0x401E70C0 WRITE   3927473\n0x401E7080 WRITE   3927476\n0x401E7040 WRITE   3927479\n0x401AAFC0 WRITE   3927504\n0x401E7180 WRITE   3927935\n0x401E7140 WRITE   3927937\n0x401BE880 WRITE   3928021\n0x401E7300 WRITE   3928405\n0x401E72C0 WRITE   3928407\n0x401E7280 WRITE   3928414\n0x401E7240 WRITE   3928416\n0x401AB000 WRITE   3928449\n0x401E7380 WRITE   3928912\n0x401E7340 WRITE   3928914\n0x401BE8C0 WRITE   3928998\n0x401E7600 WRITE   3929415\n0x401E75C0 WRITE   3929417\n0x401E7500 WRITE   3929424\n0x401E74C0 WRITE   3929426\n0x401E7480 WRITE   3929436\n0x401E7440 WRITE   3929438\n0x401AB040 WRITE   3929465\n0x401E7580 WRITE   3929906\n0x401E7540 WRITE   3929908\n0x401BE900 WRITE   3929992\n0x401E7700 WRITE   3930386\n0x401E76C0 WRITE   3930388\n0x401E7680 WRITE   3930395\n0x401E7640 WRITE   3930397\n0x401AB080 WRITE   3930430\n0x401E7780 WRITE   3930903\n0x401E7740 WRITE   3930905\n0x401BE940 WRITE   3930989\n0x401E7C00 WRITE   3931421\n0x401E7BC0 WRITE   3931423\n0x401E7A00 WRITE   3931430\n0x401E79C0 WRITE   3931432\n0x401E7900 WRITE   3931442\n0x401E78C0 WRITE   3931444\n0x401E7880 WRITE   3931449\n0x401E7840 WRITE   3931452\n0x401AB0C0 WRITE   3931477\n0x401E7980 WRITE   3931916\n0x401E7940 WRITE   3931918\n0x401BE980 WRITE   3932002\n0x401E7B00 WRITE   3932394\n0x401E7AC0 WRITE   3932396\n0x401E7A80 WRITE   3932403\n0x401E7A40 WRITE   3932405\n0x401AB100 WRITE   3932438\n0x401E7B80 WRITE   3932909\n0x401E7B40 WRITE   3932911\n0x401BE9C0 WRITE   3932995\n0x401E7E00 WRITE   3933420\n0x401E7DC0 WRITE   3933422\n0x401E7D00 WRITE   3933429\n0x401E7CC0 WRITE   3933431\n0x401E7C80 WRITE   3933441\n0x401E7C40 WRITE   3933443\n0x401AB140 WRITE   3933470\n0x401E7D80 WRITE   3933918\n0x401E7D40 WRITE   3933920\n0x401BEA00 WRITE   3934004\n0x401E7F00 WRITE   3934405\n0x401E7EC0 WRITE   3934407\n0x401E7E80 WRITE   3934414\n0x401E7E40 WRITE   3934416\n0x401AB180 WRITE   3934449\n0x401E7F80 WRITE   3934929\n0x401E7F40 WRITE   3934931\n0x401BEA40 WRITE   3935015\n0x401E9FC0 WRITE   3935499\n0x401EA000 WRITE   3935533\n0x401E9000 WRITE   3935647\n0x401E8FC0 WRITE   3935649\n0x401E8800 WRITE   3935656\n0x401E87C0 WRITE   3935658\n0x401E8400 WRITE   3935668\n0x401E83C0 WRITE   3935670\n0x401E8200 WRITE   3935675\n0x401E81C0 WRITE   3935678\n0x401E8100 WRITE   3935681\n0x401E80C0 WRITE   3935684\n0x401E8080 WRITE   3935687\n0x401E8040 WRITE   3935690\n0x401AB1C0 WRITE   3935723\n0x401E8180 WRITE   3936153\n0x401E8140 WRITE   3936155\n0x401BEA80 WRITE   3936239\n0x401E8300 WRITE   3936618\n0x401E82C0 WRITE   3936620\n0x401E8280 WRITE   3936627\n0x401E8240 WRITE   3936629\n0x401AB200 WRITE   3936662\n0x401E8380 WRITE   3937125\n0x401E8340 WRITE   3937127\n0x401BEAC0 WRITE   3937211\n0x401E8600 WRITE   3937622\n0x401E85C0 WRITE   3937624\n0x401E8500 WRITE   3937631\n0x401E84C0 WRITE   3937633\n0x401E8480 WRITE   3937643\n0x401E8440 WRITE   3937645\n0x401AB240 WRITE   3937672\n0x401E8580 WRITE   3938113\n0x401E8540 WRITE   3938115\n0x401BEB00 WRITE   3938199\n0x401E8700 WRITE   3938587\n0x401E86C0 WRITE   3938589\n0x401E8680 WRITE   3938596\n0x401E8640 WRITE   3938598\n0x401AB280 WRITE   3938631\n0x401E8780 WRITE   3939104\n0x401E8740 WRITE   3939106\n0x401BEB40 WRITE   3939190\n0x401E8C00 WRITE   3939616\n0x401E8BC0 WRITE   3939618\n0x401E8A00 WRITE   3939625\n0x401E89C0 WRITE   3939627\n0x401E8900 WRITE   3939637\n0x401E88C0 WRITE   3939639\n0x401E8880 WRITE   3939644\n0x401E8840 WRITE   3939647\n0x401AB2C0 WRITE   3939672\n0x401E8980 WRITE   3940111\n0x401E8940 WRITE   3940113\n0x401BEB80 WRITE   3940197\n0x401E8B00 WRITE   3940583\n0x401E8AC0 WRITE   3940585\n0x401E8A80 WRITE   3940592\n0x401E8A40 WRITE   3940594\n0x401AB300 WRITE   3940627\n0x401E8B80 WRITE   3941098\n0x401E8B40 WRITE   3941100\n0x401BEBC0 WRITE   3941184\n0x401E8E00 WRITE   3941603\n0x401E8DC0 WRITE   3941605\n0x401E8D00 WRITE   3941612\n0x401E8CC0 WRITE   3941614\n0x401E8C80 WRITE   3941624\n0x401E8C40 WRITE   3941626\n0x401AB340 WRITE   3941653\n0x401E8D80 WRITE   3942101\n0x401E8D40 WRITE   3942103\n0x401BEC00 WRITE   3942187\n0x401E8F00 WRITE   3942582\n0x401E8EC0 WRITE   3942584\n0x401E8E80 WRITE   3942591\n0x401E8E40 WRITE   3942593\n0x401AB380 WRITE   3942626\n0x401E8F80 WRITE   3943106\n0x401E8F40 WRITE   3943108\n0x401BEC40 WRITE   3943192\n0x401E9800 WRITE   3943624\n0x401E97C0 WRITE   3943626\n0x401E9400 WRITE   3943633\n0x401E93C0 WRITE   3943635\n0x401E9200 WRITE   3943645\n0x401E91C0 WRITE   3943647\n0x401E9100 WRITE   3943652\n0x401E90C0 WRITE   3943655\n0x401E9080 WRITE   3943658\n0x401E9040 WRITE   3943661\n0x401AB3C0 WRITE   3943686\n0x401E9180 WRITE   3944117\n0x401E9140 WRITE   3944119\n0x401BEC80 WRITE   3944203\n0x401E9300 WRITE   3944587\n0x401E92C0 WRITE   3944589\n0x401E9280 WRITE   3944596\n0x401E9240 WRITE   3944598\n0x401AB400 WRITE   3944631\n0x401E9380 WRITE   3945094\n0x401E9340 WRITE   3945096\n0x401BECC0 WRITE   3945180\n0x401E9600 WRITE   3945597\n0x401E95C0 WRITE   3945599\n0x401E9500 WRITE   3945606\n0x401E94C0 WRITE   3945608\n0x401E9480 WRITE   3945618\n0x401E9440 WRITE   3945620\n0x401AB440 WRITE   3945647\n0x401E9580 WRITE   3946088\n0x401E9540 WRITE   3946090\n0x401BED00 WRITE   3946174\n0x401E9700 WRITE   3946568\n0x401E96C0 WRITE   3946570\n0x401E9680 WRITE   3946577\n0x401E9640 WRITE   3946579\n0x401AB480 WRITE   3946612\n0x401E9780 WRITE   3947085\n0x401E9740 WRITE   3947087\n0x401BED40 WRITE   3947171\n0x401E9C00 WRITE   3947603\n0x401E9BC0 WRITE   3947605\n0x401E9A00 WRITE   3947612\n0x401E99C0 WRITE   3947614\n0x401E9900 WRITE   3947624\n0x401E98C0 WRITE   3947626\n0x401E9880 WRITE   3947631\n0x401E9840 WRITE   3947634\n0x401AB4C0 WRITE   3947659\n0x401E9980 WRITE   3948098\n0x401E9940 WRITE   3948100\n0x401BED80 WRITE   3948184\n0x401E9B00 WRITE   3948576\n0x401E9AC0 WRITE   3948578\n0x401E9A80 WRITE   3948585\n0x401E9A40 WRITE   3948587\n0x401AB500 WRITE   3948620\n0x401E9B80 WRITE   3949091\n0x401E9B40 WRITE   3949093\n0x401BEDC0 WRITE   3949177\n0x401E9E00 WRITE   3949602\n0x401E9DC0 WRITE   3949604\n0x401E9D00 WRITE   3949611\n0x401E9CC0 WRITE   3949613\n0x401E9C80 WRITE   3949623\n0x401E9C40 WRITE   3949625\n0x401AB540 WRITE   3949652\n0x401E9D80 WRITE   3950100\n0x401E9D40 WRITE   3950102\n0x401BEE00 WRITE   3950186\n0x401E9F00 WRITE   3950587\n0x401E9EC0 WRITE   3950589\n0x401E9E80 WRITE   3950596\n0x401E9E40 WRITE   3950598\n0x401AB580 WRITE   3950631\n0x401E9F80 WRITE   3951111\n0x401E9F40 WRITE   3951113\n0x401BEE40 WRITE   3951197\n0x401EBFC0 WRITE   3951681\n0x401EC000 WRITE   3951715\n0x401EB000 WRITE   3951857\n0x401EAFC0 WRITE   3951859\n0x401EA800 WRITE   3951866\n0x401EA7C0 WRITE   3951868\n0x401EA400 WRITE   3951878\n0x401EA3C0 WRITE   3951880\n0x401EA200 WRITE   3951885\n0x401EA1C0 WRITE   3951888\n0x401EA100 WRITE   3951891\n0x401EA0C0 WRITE   3951894\n0x401EA080 WRITE   3951897\n0x401EA040 WRITE   3951900\n0x401AB5C0 WRITE   3951933\n0x401EA180 WRITE   3952363\n0x401EA140 WRITE   3952365\n0x401BEE80 WRITE   3952449\n0x401EA300 WRITE   3952828\n0x401EA2C0 WRITE   3952830\n0x401EA280 WRITE   3952837\n0x401EA240 WRITE   3952839\n0x401AB600 WRITE   3952872\n0x401EA380 WRITE   3953335\n0x401EA340 WRITE   3953337\n0x401BEEC0 WRITE   3953421\n0x401EA600 WRITE   3953832\n0x401EA5C0 WRITE   3953834\n0x401EA500 WRITE   3953841\n0x401EA4C0 WRITE   3953843\n0x401EA480 WRITE   3953853\n0x401EA440 WRITE   3953855\n0x401AB640 WRITE   3953882\n0x401EA580 WRITE   3954323\n0x401EA540 WRITE   3954325\n0x401BEF00 WRITE   3954409\n0x401EA700 WRITE   3954797\n0x401EA6C0 WRITE   3954799\n0x401EA680 WRITE   3954806\n0x401EA640 WRITE   3954808\n0x401AB680 WRITE   3954841\n0x401EA780 WRITE   3955314\n0x401EA740 WRITE   3955316\n0x401BEF40 WRITE   3955400\n0x401EAC00 WRITE   3955826\n0x401EABC0 WRITE   3955828\n0x401EAA00 WRITE   3955835\n0x401EA9C0 WRITE   3955837\n0x401EA900 WRITE   3955847\n0x401EA8C0 WRITE   3955849\n0x401EA880 WRITE   3955854\n0x401EA840 WRITE   3955857\n0x401AB6C0 WRITE   3955882\n0x401EA980 WRITE   3956321\n0x401EA940 WRITE   3956323\n0x401BEF80 WRITE   3956407\n0x401EAB00 WRITE   3956793\n0x401EAAC0 WRITE   3956795\n0x401EAA80 WRITE   3956802\n0x401EAA40 WRITE   3956804\n0x401AB700 WRITE   3956837\n0x401EAB80 WRITE   3957308\n0x401EAB40 WRITE   3957310\n0x401BEFC0 WRITE   3957394\n0x401EAE00 WRITE   3957813\n0x401EADC0 WRITE   3957815\n0x401EAD00 WRITE   3957822\n0x401EACC0 WRITE   3957824\n0x401EAC80 WRITE   3957834\n0x401EAC40 WRITE   3957836\n0x401AB740 WRITE   3957863\n0x401EAD80 WRITE   3958311\n0x401EAD40 WRITE   3958313\n0x401BF000 WRITE   3958397\n0x401EAF00 WRITE   3958792\n0x401EAEC0 WRITE   3958794\n0x401EAE80 WRITE   3958801\n0x401EAE40 WRITE   3958803\n0x401AB780 WRITE   3958836\n0x401EAF80 WRITE   3959316\n0x401EAF40 WRITE   3959318\n0x401BF040 WRITE   3959402\n0x401EB800 WRITE   3959834\n0x401EB7C0 WRITE   3959836\n0x401EB400 WRITE   3959843\n0x401EB3C0 WRITE   3959845\n0x401EB200 WRITE   3959855\n0x401EB1C0 WRITE   3959857\n0x401EB100 WRITE   3959862\n0x401EB0C0 WRITE   3959865\n0x401EB080 WRITE   3959868\n0x401EB040 WRITE   3959871\n0x401AB7C0 WRITE   3959896\n0x401EB180 WRITE   3960327\n0x401EB140 WRITE   3960329\n0x401BF080 WRITE   3960413\n0x401EB300 WRITE   3960797\n0x401EB2C0 WRITE   3960799\n0x401EB280 WRITE   3960806\n0x401EB240 WRITE   3960808\n0x401AB800 WRITE   3960841\n0x401EB380 WRITE   3961304\n0x401EB340 WRITE   3961306\n0x401BF0C0 WRITE   3961390\n0x401EB600 WRITE   3961807\n0x401EB5C0 WRITE   3961809\n0x401EB500 WRITE   3961816\n0x401EB4C0 WRITE   3961818\n0x401EB480 WRITE   3961828\n0x401EB440 WRITE   3961830\n0x401AB840 WRITE   3961857\n0x401EB580 WRITE   3962298\n0x401EB540 WRITE   3962300\n0x401BF100 WRITE   3962384\n0x401EB700 WRITE   3962778\n0x401EB6C0 WRITE   3962780\n0x401EB680 WRITE   3962787\n0x401EB640 WRITE   3962789\n0x401AB880 WRITE   3962822\n0x401EB780 WRITE   3963295\n0x401EB740 WRITE   3963297\n0x401BF140 WRITE   3963381\n0x401EBC00 WRITE   3963813\n0x401EBBC0 WRITE   3963815\n0x401EBA00 WRITE   3963822\n0x401EB9C0 WRITE   3963824\n0x401EB900 WRITE   3963834\n0x401EB8C0 WRITE   3963836\n0x401EB880 WRITE   3963841\n0x401EB840 WRITE   3963844\n0x401AB8C0 WRITE   3963869\n0x401EB980 WRITE   3964308\n0x401EB940 WRITE   3964310\n0x401BF180 WRITE   3964394\n0x401EBB00 WRITE   3964786\n0x401EBAC0 WRITE   3964788\n0x401EBA80 WRITE   3964795\n0x401EBA40 WRITE   3964797\n0x401AB900 WRITE   3964830\n0x401EBB80 WRITE   3965301\n0x401EBB40 WRITE   3965303\n0x401BF1C0 WRITE   3965387\n0x401EBE00 WRITE   3965812\n0x401EBDC0 WRITE   3965814\n0x401EBD00 WRITE   3965821\n0x401EBCC0 WRITE   3965823\n0x401EBC80 WRITE   3965833\n0x401EBC40 WRITE   3965835\n0x401AB940 WRITE   3965862\n0x401EBD80 WRITE   3966310\n0x401EBD40 WRITE   3966312\n0x401BF200 WRITE   3966396\n0x401EBF00 WRITE   3966797\n0x401EBEC0 WRITE   3966799\n0x401EBE80 WRITE   3966806\n0x401EBE40 WRITE   3966808\n0x401AB980 WRITE   3966841\n0x401EBF80 WRITE   3967321\n0x401EBF40 WRITE   3967323\n0x401BF240 WRITE   3967407\n0x401EDFC0 WRITE   3967896\n0x401EE000 WRITE   3967928\n0x401ED000 WRITE   3968042\n0x401ECFC0 WRITE   3968044\n0x401EC800 WRITE   3968051\n0x401EC7C0 WRITE   3968053\n0x401EC400 WRITE   3968063\n0x401EC3C0 WRITE   3968065\n0x401EC200 WRITE   3968070\n0x401EC1C0 WRITE   3968073\n0x401EC100 WRITE   3968076\n0x401EC0C0 WRITE   3968079\n0x401EC080 WRITE   3968082\n0x401EC040 WRITE   3968085\n0x401AB9C0 WRITE   3968118\n0x401EC180 WRITE   3968548\n0x401EC140 WRITE   3968550\n0x401BF280 WRITE   3968634\n0x401EC300 WRITE   3969013\n0x401EC2C0 WRITE   3969015\n0x401EC280 WRITE   3969022\n0x401EC240 WRITE   3969024\n0x401ABA00 WRITE   3969057\n0x401EC380 WRITE   3969520\n0x401EC340 WRITE   3969522\n0x401BF2C0 WRITE   3969606\n0x401EC600 WRITE   3970017\n0x401EC5C0 WRITE   3970019\n0x401EC500 WRITE   3970026\n0x401EC4C0 WRITE   3970028\n0x401EC480 WRITE   3970038\n0x401EC440 WRITE   3970040\n0x401ABA40 WRITE   3970067\n0x401EC580 WRITE   3970508\n0x401EC540 WRITE   3970510\n0x401BF300 WRITE   3970594\n0x401EC700 WRITE   3970982\n0x401EC6C0 WRITE   3970984\n0x401EC680 WRITE   3970991\n0x401EC640 WRITE   3970993\n0x401ABA80 WRITE   3971026\n0x401EC780 WRITE   3971499\n0x401EC740 WRITE   3971501\n0x401BF340 WRITE   3971585\n0x401ECC00 WRITE   3972011\n0x401ECBC0 WRITE   3972013\n0x401ECA00 WRITE   3972020\n0x401EC9C0 WRITE   3972022\n0x401EC900 WRITE   3972032\n0x401EC8C0 WRITE   3972034\n0x401EC880 WRITE   3972039\n0x401EC840 WRITE   3972042\n0x401ABAC0 WRITE   3972067\n0x401EC980 WRITE   3972506\n0x401EC940 WRITE   3972508\n0x401BF380 WRITE   3972592\n0x401ECB00 WRITE   3972978\n0x401ECAC0 WRITE   3972980\n0x401ECA80 WRITE   3972987\n0x401ECA40 WRITE   3972989\n0x401ABB00 WRITE   3973022\n0x401ECB80 WRITE   3973493\n0x401ECB40 WRITE   3973495\n0x401BF3C0 WRITE   3973579\n0x401ECE00 WRITE   3973998\n0x401ECDC0 WRITE   3974000\n0x401ECD00 WRITE   3974007\n0x401ECCC0 WRITE   3974009\n0x401ECC80 WRITE   3974019\n0x401ECC40 WRITE   3974021\n0x401ABB40 WRITE   3974048\n0x401ECD80 WRITE   3974496\n0x401ECD40 WRITE   3974498\n0x401BF400 WRITE   3974582\n0x401ECF00 WRITE   3974977\n0x401ECEC0 WRITE   3974979\n0x401ECE80 WRITE   3974986\n0x401ECE40 WRITE   3974988\n0x401ABB80 WRITE   3975021\n0x401ECF80 WRITE   3975501\n0x401ECF40 WRITE   3975503\n0x401BF440 WRITE   3975587\n0x401ED800 WRITE   3976019\n0x401ED7C0 WRITE   3976021\n0x401ED400 WRITE   3976028\n0x401ED3C0 WRITE   3976030\n0x401ED200 WRITE   3976040\n0x401ED1C0 WRITE   3976042\n0x401ED100 WRITE   3976047\n0x401ED0C0 WRITE   3976050\n0x401ED080 WRITE   3976053\n0x401ED040 WRITE   3976056\n0x401ABBC0 WRITE   3976081\n0x401ED180 WRITE   3976512\n0x401ED140 WRITE   3976514\n0x401BF480 WRITE   3976598\n0x401ED300 WRITE   3976982\n0x401ED2C0 WRITE   3976984\n0x401ED280 WRITE   3976991\n0x401ED240 WRITE   3976993\n0x401ABC00 WRITE   3977026\n0x401ED380 WRITE   3977489\n0x401ED340 WRITE   3977491\n0x401BF4C0 WRITE   3977575\n0x401ED600 WRITE   3977992\n0x401ED5C0 WRITE   3977994\n0x401ED500 WRITE   3978001\n0x401ED4C0 WRITE   3978003\n0x401ED480 WRITE   3978013\n0x401ED440 WRITE   3978015\n0x401ABC40 WRITE   3978042\n0x401ED580 WRITE   3978483\n0x401ED540 WRITE   3978485\n0x401BF500 WRITE   3978569\n0x401ED700 WRITE   3978963\n0x401ED6C0 WRITE   3978965\n0x401ED680 WRITE   3978972\n0x401ED640 WRITE   3978974\n0x401ABC80 WRITE   3979007\n0x401ED780 WRITE   3979480\n0x401ED740 WRITE   3979482\n0x401BF540 WRITE   3979566\n0x401EDC00 WRITE   3979998\n0x401EDBC0 WRITE   3980000\n0x401EDA00 WRITE   3980007\n0x401ED9C0 WRITE   3980009\n0x401ED900 WRITE   3980019\n0x401ED8C0 WRITE   3980021\n0x401ED880 WRITE   3980026\n0x401ED840 WRITE   3980029\n0x401ABCC0 WRITE   3980054\n0x401ED980 WRITE   3980493\n0x401ED940 WRITE   3980495\n0x401BF580 WRITE   3980579\n0x401EDB00 WRITE   3980971\n0x401EDAC0 WRITE   3980973\n0x401EDA80 WRITE   3980980\n0x401EDA40 WRITE   3980982\n0x401ABD00 WRITE   3981015\n0x401EDB80 WRITE   3981486\n0x401EDB40 WRITE   3981488\n0x401BF5C0 WRITE   3981572\n0x401EDE00 WRITE   3981997\n0x401EDDC0 WRITE   3981999\n0x401EDD00 WRITE   3982006\n0x401EDCC0 WRITE   3982008\n0x401EDC80 WRITE   3982018\n0x401EDC40 WRITE   3982020\n0x401ABD40 WRITE   3982047\n0x401EDD80 WRITE   3982495\n0x401EDD40 WRITE   3982497\n0x401BF600 WRITE   3982581\n0x401EDF00 WRITE   3982982\n0x401EDEC0 WRITE   3982984\n0x401EDE80 WRITE   3982991\n0x401EDE40 WRITE   3982993\n0x401ABD80 WRITE   3983026\n0x401EDF80 WRITE   3983506\n0x401EDF40 WRITE   3983508\n0x401BF640 WRITE   3983592\n0x401EFFC0 WRITE   3984076\n0x401F0000 WRITE   3984110\n0x401EF000 WRITE   3984224\n0x401EEFC0 WRITE   3984226\n0x401EE800 WRITE   3984233\n0x401EE7C0 WRITE   3984235\n0x401EE400 WRITE   3984245\n0x401EE3C0 WRITE   3984247\n0x401EE200 WRITE   3984252\n0x401EE1C0 WRITE   3984255\n0x401EE100 WRITE   3984258\n0x401EE0C0 WRITE   3984261\n0x401EE080 WRITE   3984264\n0x401EE040 WRITE   3984267\n0x401ABDC0 WRITE   3984300\n0x401EE180 WRITE   3984730\n0x401EE140 WRITE   3984732\n0x401BF680 WRITE   3984816\n0x401EE300 WRITE   3985195\n0x401EE2C0 WRITE   3985197\n0x401EE280 WRITE   3985204\n0x401EE240 WRITE   3985206\n0x401ABE00 WRITE   3985239\n0x401EE380 WRITE   3985702\n0x401EE340 WRITE   3985704\n0x401BF6C0 WRITE   3985788\n0x401EE600 WRITE   3986199\n0x401EE5C0 WRITE   3986201\n0x401EE500 WRITE   3986208\n0x401EE4C0 WRITE   3986210\n0x401EE480 WRITE   3986220\n0x401EE440 WRITE   3986222\n0x401ABE40 WRITE   3986249\n0x401EE580 WRITE   3986690\n0x401EE540 WRITE   3986692\n0x401BF700 WRITE   3986776\n0x401EE700 WRITE   3987164\n0x401EE6C0 WRITE   3987166\n0x401EE680 WRITE   3987173\n0x401EE640 WRITE   3987175\n0x401ABE80 WRITE   3987208\n0x401EE780 WRITE   3987681\n0x401EE740 WRITE   3987683\n0x401BF740 WRITE   3987767\n0x401EEC00 WRITE   3988193\n0x401EEBC0 WRITE   3988195\n0x401EEA00 WRITE   3988202\n0x401EE9C0 WRITE   3988204\n0x401EE900 WRITE   3988214\n0x401EE8C0 WRITE   3988216\n0x401EE880 WRITE   3988221\n0x401EE840 WRITE   3988224\n0x401ABEC0 WRITE   3988249\n0x401EE980 WRITE   3988688\n0x401EE940 WRITE   3988690\n0x401BF780 WRITE   3988774\n0x401EEB00 WRITE   3989160\n0x401EEAC0 WRITE   3989162\n0x401EEA80 WRITE   3989169\n0x401EEA40 WRITE   3989171\n0x401ABF00 WRITE   3989204\n0x401EEB80 WRITE   3989675\n0x401EEB40 WRITE   3989677\n0x401BF7C0 WRITE   3989761\n0x401EEE00 WRITE   3990180\n0x401EEDC0 WRITE   3990182\n0x401EED00 WRITE   3990189\n0x401EECC0 WRITE   3990191\n0x401EEC80 WRITE   3990201\n0x401EEC40 WRITE   3990203\n0x401ABF40 WRITE   3990230\n0x401EED80 WRITE   3990678\n0x401EED40 WRITE   3990680\n0x401BF800 WRITE   3990764\n0x401EEF00 WRITE   3991159\n0x401EEEC0 WRITE   3991161\n0x401EEE80 WRITE   3991168\n0x401EEE40 WRITE   3991170\n0x401ABF80 WRITE   3991203\n0x401EEF80 WRITE   3991683\n0x401EEF40 WRITE   3991685\n0x401BF840 WRITE   3991769\n0x401EF800 WRITE   3992201\n0x401EF7C0 WRITE   3992203\n0x401EF400 WRITE   3992210\n0x401EF3C0 WRITE   3992212\n0x401EF200 WRITE   3992222\n0x401EF1C0 WRITE   3992224\n0x401EF100 WRITE   3992229\n0x401EF0C0 WRITE   3992232\n0x401EF080 WRITE   3992235\n0x401EF040 WRITE   3992238\n0x401ABFC0 WRITE   3992263\n0x401EF180 WRITE   3992694\n0x401EF140 WRITE   3992696\n0x401BF880 WRITE   3992780\n0x401EF300 WRITE   3993164\n0x401EF2C0 WRITE   3993166\n0x401EF280 WRITE   3993173\n0x401EF240 WRITE   3993175\n0x401AC000 WRITE   3993208\n0x401EF380 WRITE   3993671\n0x401EF340 WRITE   3993673\n0x401BF8C0 WRITE   3993757\n0x401EF600 WRITE   3994174\n0x401EF5C0 WRITE   3994176\n0x401EF500 WRITE   3994183\n0x401EF4C0 WRITE   3994185\n0x401EF480 WRITE   3994195\n0x401EF440 WRITE   3994197\n0x401AC040 WRITE   3994224\n0x401EF580 WRITE   3994665\n0x401EF540 WRITE   3994667\n0x401BF900 WRITE   3994751\n0x401EF700 WRITE   3995145\n0x401EF6C0 WRITE   3995147\n0x401EF680 WRITE   3995154\n0x401EF640 WRITE   3995156\n0x401AC080 WRITE   3995189\n0x401EF780 WRITE   3995662\n0x401EF740 WRITE   3995664\n0x401BF940 WRITE   3995748\n0x401EFC00 WRITE   3996180\n0x401EFBC0 WRITE   3996182\n0x401EFA00 WRITE   3996189\n0x401EF9C0 WRITE   3996191\n0x401EF900 WRITE   3996201\n0x401EF8C0 WRITE   3996203\n0x401EF880 WRITE   3996208\n0x401EF840 WRITE   3996211\n0x401AC0C0 WRITE   3996236\n0x401EF980 WRITE   3996675\n0x401EF940 WRITE   3996677\n0x401BF980 WRITE   3996761\n0x401EFB00 WRITE   3997153\n0x401EFAC0 WRITE   3997155\n0x401EFA80 WRITE   3997162\n0x401EFA40 WRITE   3997164\n0x401AC100 WRITE   3997197\n0x401EFB80 WRITE   3997668\n0x401EFB40 WRITE   3997670\n0x401BF9C0 WRITE   3997754\n0x401EFE00 WRITE   3998179\n0x401EFDC0 WRITE   3998181\n0x401EFD00 WRITE   3998188\n0x401EFCC0 WRITE   3998190\n0x401EFC80 WRITE   3998200\n0x401EFC40 WRITE   3998202\n0x401AC140 WRITE   3998229\n0x401EFD80 WRITE   3998677\n0x401EFD40 WRITE   3998679\n0x401BFA00 WRITE   3998763\n0x401EFF00 WRITE   3999164\n0x401EFEC0 WRITE   3999166\n0x401EFE80 WRITE   3999173\n0x401EFE40 WRITE   3999175\n0x401AC180 WRITE   3999208\n0x401EFF80 WRITE   3999688\n0x401EFF40 WRITE   3999690\n0x401BFA40 WRITE   3999774\n0x401F1FC0 WRITE   4000258\n0x401F2000 WRITE   4000292\n0x401F1000 WRITE   4000406\n0x401F0FC0 WRITE   4000408\n0x401F0800 WRITE   4000415\n0x401F07C0 WRITE   4000417\n0x401F0400 WRITE   4000427\n0x401F03C0 WRITE   4000429\n0x401F0200 WRITE   4000434\n0x401F01C0 WRITE   4000437\n0x401F0100 WRITE   4000440\n0x401F00C0 WRITE   4000443\n0x401F0080 WRITE   4000446\n0x401F0040 WRITE   4000449\n0x401AC1C0 WRITE   4000482\n0x401F0180 WRITE   4000912\n0x401F0140 WRITE   4000914\n0x401BFA80 WRITE   4000998\n0x401F0300 WRITE   4001377\n0x401F02C0 WRITE   4001379\n0x401F0280 WRITE   4001386\n0x401F0240 WRITE   4001388\n0x401AC200 WRITE   4001421\n0x401F0380 WRITE   4001884\n0x401F0340 WRITE   4001886\n0x401BFAC0 WRITE   4001970\n0x401F0600 WRITE   4002381\n0x401F05C0 WRITE   4002383\n0x401F0500 WRITE   4002390\n0x401F04C0 WRITE   4002392\n0x401F0480 WRITE   4002402\n0x401F0440 WRITE   4002404\n0x401AC240 WRITE   4002431\n0x401F0580 WRITE   4002872\n0x401F0540 WRITE   4002874\n0x401BFB00 WRITE   4002958\n0x401F0700 WRITE   4003346\n0x401F06C0 WRITE   4003348\n0x401F0680 WRITE   4003355\n0x401F0640 WRITE   4003357\n0x401AC280 WRITE   4003390\n0x401F0780 WRITE   4003863\n0x401F0740 WRITE   4003865\n0x401BFB40 WRITE   4003949\n0x401F0C00 WRITE   4004375\n0x401F0BC0 WRITE   4004377\n0x401F0A00 WRITE   4004384\n0x401F09C0 WRITE   4004386\n0x401F0900 WRITE   4004396\n0x401F08C0 WRITE   4004398\n0x401F0880 WRITE   4004403\n0x401F0840 WRITE   4004406\n0x401AC2C0 WRITE   4004431\n0x401F0980 WRITE   4004870\n0x401F0940 WRITE   4004872\n0x401BFB80 WRITE   4004956\n0x401F0B00 WRITE   4005342\n0x401F0AC0 WRITE   4005344\n0x401F0A80 WRITE   4005351\n0x401F0A40 WRITE   4005353\n0x401AC300 WRITE   4005386\n0x401F0B80 WRITE   4005857\n0x401F0B40 WRITE   4005859\n0x401BFBC0 WRITE   4005943\n0x401F0E00 WRITE   4006362\n0x401F0DC0 WRITE   4006364\n0x401F0D00 WRITE   4006371\n0x401F0CC0 WRITE   4006373\n0x401F0C80 WRITE   4006383\n0x401F0C40 WRITE   4006385\n0x401AC340 WRITE   4006412\n0x401F0D80 WRITE   4006860\n0x401F0D40 WRITE   4006862\n0x401BFC00 WRITE   4006946\n0x401F0F00 WRITE   4007341\n0x401F0EC0 WRITE   4007343\n0x401F0E80 WRITE   4007350\n0x401F0E40 WRITE   4007352\n0x401AC380 WRITE   4007385\n0x401F0F80 WRITE   4007865\n0x401F0F40 WRITE   4007867\n0x401BFC40 WRITE   4007951\n0x401F1800 WRITE   4008383\n0x401F17C0 WRITE   4008385\n0x401F1400 WRITE   4008392\n0x401F13C0 WRITE   4008394\n0x401F1200 WRITE   4008404\n0x401F11C0 WRITE   4008406\n0x401F1100 WRITE   4008411\n0x401F10C0 WRITE   4008414\n0x401F1080 WRITE   4008417\n0x401F1040 WRITE   4008420\n0x401AC3C0 WRITE   4008445\n0x401F1180 WRITE   4008876\n0x401F1140 WRITE   4008878\n0x401BFC80 WRITE   4008962\n0x401F1300 WRITE   4009346\n0x401F12C0 WRITE   4009348\n0x401F1280 WRITE   4009355\n0x401F1240 WRITE   4009357\n0x401AC400 WRITE   4009390\n0x401F1380 WRITE   4009853\n0x401F1340 WRITE   4009855\n0x401BFCC0 WRITE   4009939\n0x401F1600 WRITE   4010356\n0x401F15C0 WRITE   4010358\n0x401F1500 WRITE   4010365\n0x401F14C0 WRITE   4010367\n0x401F1480 WRITE   4010377\n0x401F1440 WRITE   4010379\n0x401AC440 WRITE   4010406\n0x401F1580 WRITE   4010847\n0x401F1540 WRITE   4010849\n0x401BFD00 WRITE   4010933\n0x401F1700 WRITE   4011327\n0x401F16C0 WRITE   4011329\n0x401F1680 WRITE   4011336\n0x401F1640 WRITE   4011338\n0x401AC480 WRITE   4011371\n0x401F1780 WRITE   4011844\n0x401F1740 WRITE   4011846\n0x401BFD40 WRITE   4011930\n0x401F1C00 WRITE   4012362\n0x401F1BC0 WRITE   4012364\n0x401F1A00 WRITE   4012371\n0x401F19C0 WRITE   4012373\n0x401F1900 WRITE   4012383\n0x401F18C0 WRITE   4012385\n0x401F1880 WRITE   4012390\n0x401F1840 WRITE   4012393\n0x401AC4C0 WRITE   4012418\n0x401F1980 WRITE   4012857\n0x401F1940 WRITE   4012859\n0x401BFD80 WRITE   4012943\n0x401F1B00 WRITE   4013335\n0x401F1AC0 WRITE   4013337\n0x401F1A80 WRITE   4013344\n0x401F1A40 WRITE   4013346\n0x401AC500 WRITE   4013379\n0x401F1B80 WRITE   4013850\n0x401F1B40 WRITE   4013852\n0x401BFDC0 WRITE   4013936\n0x401F1E00 WRITE   4014361\n0x401F1DC0 WRITE   4014363\n0x401F1D00 WRITE   4014370\n0x401F1CC0 WRITE   4014372\n0x401F1C80 WRITE   4014382\n0x401F1C40 WRITE   4014384\n0x401AC540 WRITE   4014411\n0x401F1D80 WRITE   4014859\n0x401F1D40 WRITE   4014861\n0x401BFE00 WRITE   4014945\n0x401F1F00 WRITE   4015346\n0x401F1EC0 WRITE   4015348\n0x401F1E80 WRITE   4015355\n0x401F1E40 WRITE   4015357\n0x401AC580 WRITE   4015390\n0x401F1F80 WRITE   4015870\n0x401F1F40 WRITE   4015872\n0x401BFE40 WRITE   4015956\n0x401F3FC0 WRITE   4016440\n0x401F4000 WRITE   4016474\n0x401F3000 WRITE   4016588\n0x401F2FC0 WRITE   4016590\n0x401F2800 WRITE   4016597\n0x401F27C0 WRITE   4016599\n0x401F2400 WRITE   4016609\n0x401F23C0 WRITE   4016611\n0x401F2200 WRITE   4016616\n0x401F21C0 WRITE   4016619\n0x401F2100 WRITE   4016622\n0x401F20C0 WRITE   4016625\n0x401F2080 WRITE   4016628\n0x401F2040 WRITE   4016631\n0x401AC5C0 WRITE   4016664\n0x401F2180 WRITE   4017094\n0x401F2140 WRITE   4017096\n0x401BFE80 WRITE   4017180\n0x401F2300 WRITE   4017559\n0x401F22C0 WRITE   4017561\n0x401F2280 WRITE   4017568\n0x401F2240 WRITE   4017570\n0x401AC600 WRITE   4017603\n0x401F2380 WRITE   4018066\n0x401F2340 WRITE   4018068\n0x401BFEC0 WRITE   4018152\n0x401F2600 WRITE   4018563\n0x401F25C0 WRITE   4018565\n0x401F2500 WRITE   4018572\n0x401F24C0 WRITE   4018574\n0x401F2480 WRITE   4018584\n0x401F2440 WRITE   4018586\n0x401AC640 WRITE   4018613\n0x401F2580 WRITE   4019054\n0x401F2540 WRITE   4019056\n0x401BFF00 WRITE   4019140\n0x401F2700 WRITE   4019528\n0x401F26C0 WRITE   4019530\n0x401F2680 WRITE   4019537\n0x401F2640 WRITE   4019539\n0x401AC680 WRITE   4019572\n0x401F2780 WRITE   4020045\n0x401F2740 WRITE   4020047\n0x401BFF40 WRITE   4020131\n0x401F2C00 WRITE   4020557\n0x401F2BC0 WRITE   4020559\n0x401F2A00 WRITE   4020566\n0x401F29C0 WRITE   4020568\n0x401F2900 WRITE   4020578\n0x401F28C0 WRITE   4020580\n0x401F2880 WRITE   4020585\n0x401F2840 WRITE   4020588\n0x401AC6C0 WRITE   4020613\n0x401F2980 WRITE   4021052\n0x401F2940 WRITE   4021054\n0x401BFF80 WRITE   4021138\n0x401F2B00 WRITE   4021524\n0x401F2AC0 WRITE   4021526\n0x401F2A80 WRITE   4021533\n0x401F2A40 WRITE   4021535\n0x401AC700 WRITE   4021568\n0x401F2B80 WRITE   4022039\n0x401F2B40 WRITE   4022041\n0x401BFFC0 WRITE   4022125\n0x401F2E00 WRITE   4022544\n0x401F2DC0 WRITE   4022546\n0x401F2D00 WRITE   4022553\n0x401F2CC0 WRITE   4022555\n0x401F2C80 WRITE   4022565\n0x401F2C40 WRITE   4022567\n0x401AC740 WRITE   4022594\n0x401F2D80 WRITE   4023042\n0x401F2D40 WRITE   4023044\n0x401C0000 WRITE   4023128\n0x401F2F00 WRITE   4023523\n0x401F2EC0 WRITE   4023525\n0x401F2E80 WRITE   4023532\n0x401F2E40 WRITE   4023534\n0x401AC780 WRITE   4023567\n0x401F2F80 WRITE   4024047\n0x401F2F40 WRITE   4024049\n0x401C0040 WRITE   4024133\n0x401F3800 WRITE   4024565\n0x401F37C0 WRITE   4024567\n0x401F3400 WRITE   4024574\n0x401F33C0 WRITE   4024576\n0x401F3200 WRITE   4024586\n0x401F31C0 WRITE   4024588\n0x401F3100 WRITE   4024593\n0x401F30C0 WRITE   4024596\n0x401F3080 WRITE   4024599\n0x401F3040 WRITE   4024602\n0x401AC7C0 WRITE   4024627\n0x401F3180 WRITE   4025058\n0x401F3140 WRITE   4025060\n0x401C0080 WRITE   4025144\n0x401F3300 WRITE   4025528\n0x401F32C0 WRITE   4025530\n0x401F3280 WRITE   4025537\n0x401F3240 WRITE   4025539\n0x401AC800 WRITE   4025572\n0x401F3380 WRITE   4026035\n0x401F3340 WRITE   4026037\n0x401C00C0 WRITE   4026121\n0x401F3600 WRITE   4026538\n0x401F35C0 WRITE   4026540\n0x401F3500 WRITE   4026547\n0x401F34C0 WRITE   4026549\n0x401F3480 WRITE   4026559\n0x401F3440 WRITE   4026561\n0x401AC840 WRITE   4026588\n0x401F3580 WRITE   4027029\n0x401F3540 WRITE   4027031\n0x401C0100 WRITE   4027115\n0x401F3700 WRITE   4027509\n0x401F36C0 WRITE   4027511\n0x401F3680 WRITE   4027518\n0x401F3640 WRITE   4027520\n0x401AC880 WRITE   4027553\n0x401F3780 WRITE   4028026\n0x401F3740 WRITE   4028028\n0x401C0140 WRITE   4028112\n0x401F3C00 WRITE   4028544\n0x401F3BC0 WRITE   4028546\n0x401F3A00 WRITE   4028553\n0x401F39C0 WRITE   4028555\n0x401F3900 WRITE   4028565\n0x401F38C0 WRITE   4028567\n0x401F3880 WRITE   4028572\n0x401F3840 WRITE   4028575\n0x401AC8C0 WRITE   4028600\n0x401F3980 WRITE   4029039\n0x401F3940 WRITE   4029041\n0x401C0180 WRITE   4029125\n0x401F3B00 WRITE   4029517\n0x401F3AC0 WRITE   4029519\n0x401F3A80 WRITE   4029526\n0x401F3A40 WRITE   4029528\n0x401AC900 WRITE   4029561\n0x401F3B80 WRITE   4030032\n0x401F3B40 WRITE   4030034\n0x401C01C0 WRITE   4030118\n0x401F3E00 WRITE   4030543\n0x401F3DC0 WRITE   4030545\n0x401F3D00 WRITE   4030552\n0x401F3CC0 WRITE   4030554\n0x401F3C80 WRITE   4030564\n0x401F3C40 WRITE   4030566\n0x401AC940 WRITE   4030593\n0x401F3D80 WRITE   4031041\n0x401F3D40 WRITE   4031043\n0x401C0200 WRITE   4031127\n0x401F3F00 WRITE   4031528\n0x401F3EC0 WRITE   4031530\n0x401F3E80 WRITE   4031537\n0x401F3E40 WRITE   4031539\n0x401AC980 WRITE   4031572\n0x401F3F80 WRITE   4032052\n0x401F3F40 WRITE   4032054\n0x401C0240 WRITE   4032138\n0x401F5FC0 WRITE   4032622\n0x401F6000 WRITE   4032656\n0x401F5000 WRITE   4032770\n0x401F4FC0 WRITE   4032772\n0x401F4800 WRITE   4032779\n0x401F47C0 WRITE   4032781\n0x401F4400 WRITE   4032791\n0x401F43C0 WRITE   4032793\n0x401F4200 WRITE   4032798\n0x401F41C0 WRITE   4032801\n0x401F4100 WRITE   4032804\n0x401F40C0 WRITE   4032807\n0x401F4080 WRITE   4032810\n0x401F4040 WRITE   4032813\n0x401AC9C0 WRITE   4032846\n0x401F4180 WRITE   4033276\n0x401F4140 WRITE   4033278\n0x401C0280 WRITE   4033362\n0x401F4300 WRITE   4033741\n0x401F42C0 WRITE   4033743\n0x401F4280 WRITE   4033750\n0x401F4240 WRITE   4033752\n0x401ACA00 WRITE   4033785\n0x401F4380 WRITE   4034248\n0x401F4340 WRITE   4034250\n0x401C02C0 WRITE   4034334\n0x401F4600 WRITE   4034745\n0x401F45C0 WRITE   4034747\n0x401F4500 WRITE   4034754\n0x401F44C0 WRITE   4034756\n0x401F4480 WRITE   4034766\n0x401F4440 WRITE   4034768\n0x401ACA40 WRITE   4034795\n0x401F4580 WRITE   4035236\n0x401F4540 WRITE   4035238\n0x401C0300 WRITE   4035322\n0x401F4700 WRITE   4035710\n0x401F46C0 WRITE   4035712\n0x401F4680 WRITE   4035719\n0x401F4640 WRITE   4035721\n0x401ACA80 WRITE   4035754\n0x401F4780 WRITE   4036227\n0x401F4740 WRITE   4036229\n0x401C0340 WRITE   4036313\n0x401F4C00 WRITE   4036739\n0x401F4BC0 WRITE   4036741\n0x401F4A00 WRITE   4036748\n0x401F49C0 WRITE   4036750\n0x401F4900 WRITE   4036760\n0x401F48C0 WRITE   4036762\n0x401F4880 WRITE   4036767\n0x401F4840 WRITE   4036770\n0x401ACAC0 WRITE   4036795\n0x401F4980 WRITE   4037234\n0x401F4940 WRITE   4037236\n0x401C0380 WRITE   4037320\n0x401F4B00 WRITE   4037706\n0x401F4AC0 WRITE   4037708\n0x401F4A80 WRITE   4037715\n0x401F4A40 WRITE   4037717\n0x401ACB00 WRITE   4037750\n0x401F4B80 WRITE   4038221\n0x401F4B40 WRITE   4038223\n0x401C03C0 WRITE   4038307\n0x401F4E00 WRITE   4038726\n0x401F4DC0 WRITE   4038728\n0x401F4D00 WRITE   4038735\n0x401F4CC0 WRITE   4038737\n0x401F4C80 WRITE   4038747\n0x401F4C40 WRITE   4038749\n0x401ACB40 WRITE   4038776\n0x401F4D80 WRITE   4039224\n0x401F4D40 WRITE   4039226\n0x401C0400 WRITE   4039310\n0x401F4F00 WRITE   4039705\n0x401F4EC0 WRITE   4039707\n0x401F4E80 WRITE   4039714\n0x401F4E40 WRITE   4039716\n0x401ACB80 WRITE   4039749\n0x401F4F80 WRITE   4040229\n0x401F4F40 WRITE   4040231\n0x401C0440 WRITE   4040315\n0x401F5800 WRITE   4040747\n0x401F57C0 WRITE   4040749\n0x401F5400 WRITE   4040756\n0x401F53C0 WRITE   4040758\n0x401F5200 WRITE   4040768\n0x401F51C0 WRITE   4040770\n0x401F5100 WRITE   4040775\n0x401F50C0 WRITE   4040778\n0x401F5080 WRITE   4040781\n0x401F5040 WRITE   4040784\n0x401ACBC0 WRITE   4040809\n0x401F5180 WRITE   4041240\n0x401F5140 WRITE   4041242\n0x401C0480 WRITE   4041326\n0x401F5300 WRITE   4041710\n0x401F52C0 WRITE   4041712\n0x401F5280 WRITE   4041719\n0x401F5240 WRITE   4041721\n0x401ACC00 WRITE   4041754\n0x401F5380 WRITE   4042217\n0x401F5340 WRITE   4042219\n0x401C04C0 WRITE   4042303\n0x401F5600 WRITE   4042720\n0x401F55C0 WRITE   4042722\n0x401F5500 WRITE   4042729\n0x401F54C0 WRITE   4042731\n0x401F5480 WRITE   4042741\n0x401F5440 WRITE   4042743\n0x401ACC40 WRITE   4042770\n0x401F5580 WRITE   4043211\n0x401F5540 WRITE   4043213\n0x401C0500 WRITE   4043297\n0x401F5700 WRITE   4043691\n0x401F56C0 WRITE   4043693\n0x401F5680 WRITE   4043700\n0x401F5640 WRITE   4043702\n0x401ACC80 WRITE   4043735\n0x401F5780 WRITE   4044208\n0x401F5740 WRITE   4044210\n0x401C0540 WRITE   4044294\n0x401F5C00 WRITE   4044726\n0x401F5BC0 WRITE   4044728\n0x401F5A00 WRITE   4044735\n0x401F59C0 WRITE   4044737\n0x401F5900 WRITE   4044747\n0x401F58C0 WRITE   4044749\n0x401F5880 WRITE   4044754\n0x401F5840 WRITE   4044757\n0x401ACCC0 WRITE   4044782\n0x401F5980 WRITE   4045221\n0x401F5940 WRITE   4045223\n0x401C0580 WRITE   4045307\n0x401F5B00 WRITE   4045699\n0x401F5AC0 WRITE   4045701\n0x401F5A80 WRITE   4045708\n0x401F5A40 WRITE   4045710\n0x401ACD00 WRITE   4045743\n0x401F5B80 WRITE   4046214\n0x401F5B40 WRITE   4046216\n0x401C05C0 WRITE   4046300\n0x401F5E00 WRITE   4046725\n0x401F5DC0 WRITE   4046727\n0x401F5D00 WRITE   4046734\n0x401F5CC0 WRITE   4046736\n0x401F5C80 WRITE   4046746\n0x401F5C40 WRITE   4046748\n0x401ACD40 WRITE   4046775\n0x401F5D80 WRITE   4047223\n0x401F5D40 WRITE   4047225\n0x401C0600 WRITE   4047309\n0x401F5F00 WRITE   4047710\n0x401F5EC0 WRITE   4047712\n0x401F5E80 WRITE   4047719\n0x401F5E40 WRITE   4047721\n0x401ACD80 WRITE   4047754\n0x401F5F80 WRITE   4048234\n0x401F5F40 WRITE   4048236\n0x401C0640 WRITE   4048320\n0x401F7FC0 WRITE   4048804\n0x401F8000 WRITE   4048838\n0x401F7000 WRITE   4048988\n0x401F6FC0 WRITE   4048990\n0x401F6800 WRITE   4048997\n0x401F67C0 WRITE   4048999\n0x401F6400 WRITE   4049009\n0x401F63C0 WRITE   4049011\n0x401F6200 WRITE   4049016\n0x401F61C0 WRITE   4049019\n0x401F6100 WRITE   4049022\n0x401F60C0 WRITE   4049025\n0x401F6080 WRITE   4049028\n0x401F6040 WRITE   4049031\n0x401ACDC0 WRITE   4049064\n0x401F6180 WRITE   4049494\n0x401F6140 WRITE   4049496\n0x401C0680 WRITE   4049580\n0x401F6300 WRITE   4049959\n0x401F62C0 WRITE   4049961\n0x401F6280 WRITE   4049968\n0x401F6240 WRITE   4049970\n0x401ACE00 WRITE   4050003\n0x401F6380 WRITE   4050466\n0x401F6340 WRITE   4050468\n0x401C06C0 WRITE   4050552\n0x401F6600 WRITE   4050963\n0x401F65C0 WRITE   4050965\n0x401F6500 WRITE   4050972\n0x401F64C0 WRITE   4050974\n0x401F6480 WRITE   4050984\n0x401F6440 WRITE   4050986\n0x401ACE40 WRITE   4051013\n0x401F6580 WRITE   4051454\n0x401F6540 WRITE   4051456\n0x401C0700 WRITE   4051540\n0x401F6700 WRITE   4051928\n0x401F66C0 WRITE   4051930\n0x401F6680 WRITE   4051937\n0x401F6640 WRITE   4051939\n0x401ACE80 WRITE   4051972\n0x401F6780 WRITE   4052445\n0x401F6740 WRITE   4052447\n0x401C0740 WRITE   4052531\n0x401F6C00 WRITE   4052957\n0x401F6BC0 WRITE   4052959\n0x401F6A00 WRITE   4052966\n0x401F69C0 WRITE   4052968\n0x401F6900 WRITE   4052978\n0x401F68C0 WRITE   4052980\n0x401F6880 WRITE   4052985\n0x401F6840 WRITE   4052988\n0x401ACEC0 WRITE   4053013\n0x401F6980 WRITE   4053452\n0x401F6940 WRITE   4053454\n0x401C0780 WRITE   4053538\n0x401F6B00 WRITE   4053924\n0x401F6AC0 WRITE   4053926\n0x401F6A80 WRITE   4053933\n0x401F6A40 WRITE   4053935\n0x401ACF00 WRITE   4053968\n0x401F6B80 WRITE   4054439\n0x401F6B40 WRITE   4054441\n0x401C07C0 WRITE   4054525\n0x401F6E00 WRITE   4054944\n0x401F6DC0 WRITE   4054946\n0x401F6D00 WRITE   4054953\n0x401F6CC0 WRITE   4054955\n0x401F6C80 WRITE   4054965\n0x401F6C40 WRITE   4054967\n0x401ACF40 WRITE   4054994\n0x401F6D80 WRITE   4055442\n0x401F6D40 WRITE   4055444\n0x401C0800 WRITE   4055528\n0x401F6F00 WRITE   4055923\n0x401F6EC0 WRITE   4055925\n0x401F6E80 WRITE   4055932\n0x401F6E40 WRITE   4055934\n0x401ACF80 WRITE   4055967\n0x401F6F80 WRITE   4056447\n0x401F6F40 WRITE   4056449\n0x401C0840 WRITE   4056533\n0x401F7800 WRITE   4056965\n0x401F77C0 WRITE   4056967\n0x401F7400 WRITE   4056974\n0x401F73C0 WRITE   4056976\n0x401F7200 WRITE   4056986\n0x401F71C0 WRITE   4056988\n0x401F7100 WRITE   4056993\n0x401F70C0 WRITE   4056996\n0x401F7080 WRITE   4056999\n0x401F7040 WRITE   4057002\n0x401ACFC0 WRITE   4057027\n0x401F7180 WRITE   4057458\n0x401F7140 WRITE   4057460\n0x401C0880 WRITE   4057544\n0x401F7300 WRITE   4057928\n0x401F72C0 WRITE   4057930\n0x401F7280 WRITE   4057937\n0x401F7240 WRITE   4057939\n0x401AD000 WRITE   4057972\n0x401F7380 WRITE   4058435\n0x401F7340 WRITE   4058437\n0x401C08C0 WRITE   4058521\n0x401F7600 WRITE   4058938\n0x401F75C0 WRITE   4058940\n0x401F7500 WRITE   4058947\n0x401F74C0 WRITE   4058949\n0x401F7480 WRITE   4058959\n0x401F7440 WRITE   4058961\n0x401AD040 WRITE   4058988\n0x401F7580 WRITE   4059429\n0x401F7540 WRITE   4059431\n0x401C0900 WRITE   4059515\n0x401F7700 WRITE   4059909\n0x401F76C0 WRITE   4059911\n0x401F7680 WRITE   4059918\n0x401F7640 WRITE   4059920\n0x401AD080 WRITE   4059953\n0x401F7780 WRITE   4060426\n0x401F7740 WRITE   4060428\n0x401C0940 WRITE   4060512\n0x401F7C00 WRITE   4060944\n0x401F7BC0 WRITE   4060946\n0x401F7A00 WRITE   4060953\n0x401F79C0 WRITE   4060955\n0x401F7900 WRITE   4060965\n0x401F78C0 WRITE   4060967\n0x401F7880 WRITE   4060972\n0x401F7840 WRITE   4060975\n0x401AD0C0 WRITE   4061000\n0x401F7980 WRITE   4061439\n0x401F7940 WRITE   4061441\n0x401C0980 WRITE   4061525\n0x401F7B00 WRITE   4061917\n0x401F7AC0 WRITE   4061919\n0x401F7A80 WRITE   4061926\n0x401F7A40 WRITE   4061928\n0x401AD100 WRITE   4061961\n0x401F7B80 WRITE   4062432\n0x401F7B40 WRITE   4062434\n0x401C09C0 WRITE   4062518\n0x401F7E00 WRITE   4062943\n0x401F7DC0 WRITE   4062945\n0x401F7D00 WRITE   4062952\n0x401F7CC0 WRITE   4062954\n0x401F7C80 WRITE   4062964\n0x401F7C40 WRITE   4062966\n0x401AD140 WRITE   4062993\n0x401F7D80 WRITE   4063441\n0x401F7D40 WRITE   4063443\n0x401C0A00 WRITE   4063527\n0x401F7F00 WRITE   4063928\n0x401F7EC0 WRITE   4063930\n0x401F7E80 WRITE   4063937\n0x401F7E40 WRITE   4063939\n0x401AD180 WRITE   4063972\n0x401F7F80 WRITE   4064452\n0x401F7F40 WRITE   4064454\n0x401C0A40 WRITE   4064538\n0x401F9FC0 WRITE   4065022\n0x401FA000 WRITE   4065056\n0x401F9000 WRITE   4065170\n0x401F8FC0 WRITE   4065172\n0x401F8800 WRITE   4065179\n0x401F87C0 WRITE   4065181\n0x401F8400 WRITE   4065191\n0x401F83C0 WRITE   4065193\n0x401F8200 WRITE   4065198\n0x401F81C0 WRITE   4065201\n0x401F8100 WRITE   4065204\n0x401F80C0 WRITE   4065207\n0x401F8080 WRITE   4065210\n0x401F8040 WRITE   4065213\n0x401AD1C0 WRITE   4065246\n0x401F8180 WRITE   4065676\n0x401F8140 WRITE   4065678\n0x401C0A80 WRITE   4065762\n0x401F8300 WRITE   4066141\n0x401F82C0 WRITE   4066143\n0x401F8280 WRITE   4066150\n0x401F8240 WRITE   4066152\n0x401AD200 WRITE   4066185\n0x401F8380 WRITE   4066648\n0x401F8340 WRITE   4066650\n0x401C0AC0 WRITE   4066734\n0x401F8600 WRITE   4067145\n0x401F85C0 WRITE   4067147\n0x401F8500 WRITE   4067154\n0x401F84C0 WRITE   4067156\n0x401F8480 WRITE   4067166\n0x401F8440 WRITE   4067168\n0x401AD240 WRITE   4067195\n0x401F8580 WRITE   4067636\n0x401F8540 WRITE   4067638\n0x401C0B00 WRITE   4067722\n0x401F8700 WRITE   4068110\n0x401F86C0 WRITE   4068112\n0x401F8680 WRITE   4068119\n0x401F8640 WRITE   4068121\n0x401AD280 WRITE   4068154\n0x401F8780 WRITE   4068627\n0x401F8740 WRITE   4068629\n0x401C0B40 WRITE   4068713\n0x401F8C00 WRITE   4069139\n0x401F8BC0 WRITE   4069141\n0x401F8A00 WRITE   4069148\n0x401F89C0 WRITE   4069150\n0x401F8900 WRITE   4069160\n0x401F88C0 WRITE   4069162\n0x401F8880 WRITE   4069167\n0x401F8840 WRITE   4069170\n0x401AD2C0 WRITE   4069195\n0x401F8980 WRITE   4069634\n0x401F8940 WRITE   4069636\n0x401C0B80 WRITE   4069720\n0x401F8B00 WRITE   4070106\n0x401F8AC0 WRITE   4070108\n0x401F8A80 WRITE   4070115\n0x401F8A40 WRITE   4070117\n0x401AD300 WRITE   4070150\n0x401F8B80 WRITE   4070621\n0x401F8B40 WRITE   4070623\n0x401C0BC0 WRITE   4070707\n0x401F8E00 WRITE   4071126\n0x401F8DC0 WRITE   4071128\n0x401F8D00 WRITE   4071135\n0x401F8CC0 WRITE   4071137\n0x401F8C80 WRITE   4071147\n0x401F8C40 WRITE   4071149\n0x401AD340 WRITE   4071176\n0x401F8D80 WRITE   4071624\n0x401F8D40 WRITE   4071626\n0x401C0C00 WRITE   4071710\n0x401F8F00 WRITE   4072105\n0x401F8EC0 WRITE   4072107\n0x401F8E80 WRITE   4072114\n0x401F8E40 WRITE   4072116\n0x401AD380 WRITE   4072149\n0x401F8F80 WRITE   4072629\n0x401F8F40 WRITE   4072631\n0x401C0C40 WRITE   4072715\n0x401F9800 WRITE   4073147\n0x401F97C0 WRITE   4073149\n0x401F9400 WRITE   4073156\n0x401F93C0 WRITE   4073158\n0x401F9200 WRITE   4073168\n0x401F91C0 WRITE   4073170\n0x401F9100 WRITE   4073175\n0x401F90C0 WRITE   4073178\n0x401F9080 WRITE   4073181\n0x401F9040 WRITE   4073184\n0x401AD3C0 WRITE   4073209\n0x401F9180 WRITE   4073640\n0x401F9140 WRITE   4073642\n0x401C0C80 WRITE   4073726\n0x401F9300 WRITE   4074110\n0x401F92C0 WRITE   4074112\n0x401F9280 WRITE   4074119\n0x401F9240 WRITE   4074121\n0x401AD400 WRITE   4074154\n0x401F9380 WRITE   4074617\n0x401F9340 WRITE   4074619\n0x401C0CC0 WRITE   4074703\n0x401F9600 WRITE   4075120\n0x401F95C0 WRITE   4075122\n0x401F9500 WRITE   4075129\n0x401F94C0 WRITE   4075131\n0x401F9480 WRITE   4075141\n0x401F9440 WRITE   4075143\n0x401AD440 WRITE   4075170\n0x401F9580 WRITE   4075611\n0x401F9540 WRITE   4075613\n0x401C0D00 WRITE   4075697\n0x401F9700 WRITE   4076091\n0x401F96C0 WRITE   4076093\n0x401F9680 WRITE   4076100\n0x401F9640 WRITE   4076102\n0x401AD480 WRITE   4076135\n0x401F9780 WRITE   4076608\n0x401F9740 WRITE   4076610\n0x401C0D40 WRITE   4076694\n0x401F9C00 WRITE   4077126\n0x401F9BC0 WRITE   4077128\n0x401F9A00 WRITE   4077135\n0x401F99C0 WRITE   4077137\n0x401F9900 WRITE   4077147\n0x401F98C0 WRITE   4077149\n0x401F9880 WRITE   4077154\n0x401F9840 WRITE   4077157\n0x401AD4C0 WRITE   4077182\n0x401F9980 WRITE   4077621\n0x401F9940 WRITE   4077623\n0x401C0D80 WRITE   4077707\n0x401F9B00 WRITE   4078099\n0x401F9AC0 WRITE   4078101\n0x401F9A80 WRITE   4078108\n0x401F9A40 WRITE   4078110\n0x401AD500 WRITE   4078143\n0x401F9B80 WRITE   4078614\n0x401F9B40 WRITE   4078616\n0x401C0DC0 WRITE   4078700\n0x401F9E00 WRITE   4079125\n0x401F9DC0 WRITE   4079127\n0x401F9D00 WRITE   4079134\n0x401F9CC0 WRITE   4079136\n0x401F9C80 WRITE   4079146\n0x401F9C40 WRITE   4079148\n0x401AD540 WRITE   4079175\n0x401F9D80 WRITE   4079623\n0x401F9D40 WRITE   4079625\n0x401C0E00 WRITE   4079709\n0x401F9F00 WRITE   4080110\n0x401F9EC0 WRITE   4080112\n0x401F9E80 WRITE   4080119\n0x401F9E40 WRITE   4080121\n0x401AD580 WRITE   4080154\n0x401F9F80 WRITE   4080634\n0x401F9F40 WRITE   4080636\n0x401C0E40 WRITE   4080720\n0x401FBFC0 WRITE   4081204\n0x401FC000 WRITE   4081238\n0x401FB000 WRITE   4081383\n0x401FAFC0 WRITE   4081385\n0x401FA800 WRITE   4081392\n0x401FA7C0 WRITE   4081394\n0x401FA400 WRITE   4081404\n0x401FA3C0 WRITE   4081406\n0x401FA200 WRITE   4081411\n0x401FA1C0 WRITE   4081414\n0x401FA100 WRITE   4081417\n0x401FA0C0 WRITE   4081420\n0x401FA080 WRITE   4081423\n0x401FA040 WRITE   4081426\n0x401AD5C0 WRITE   4081459\n0x401FA180 WRITE   4081889\n0x401FA140 WRITE   4081891\n0x401C0E80 WRITE   4081975\n0x401FA300 WRITE   4082354\n0x401FA2C0 WRITE   4082356\n0x401FA280 WRITE   4082363\n0x401FA240 WRITE   4082365\n0x401AD600 WRITE   4082398\n0x401FA380 WRITE   4082861\n0x401FA340 WRITE   4082863\n0x401C0EC0 WRITE   4082947\n0x401FA600 WRITE   4083358\n0x401FA5C0 WRITE   4083360\n0x401FA500 WRITE   4083367\n0x401FA4C0 WRITE   4083369\n0x401FA480 WRITE   4083379\n0x401FA440 WRITE   4083381\n0x401AD640 WRITE   4083408\n0x401FA580 WRITE   4083849\n0x401FA540 WRITE   4083851\n0x401C0F00 WRITE   4083935\n0x401FA700 WRITE   4084323\n0x401FA6C0 WRITE   4084325\n0x401FA680 WRITE   4084332\n0x401FA640 WRITE   4084334\n0x401AD680 WRITE   4084367\n0x401FA780 WRITE   4084840\n0x401FA740 WRITE   4084842\n0x401C0F40 WRITE   4084926\n0x401FAC00 WRITE   4085352\n0x401FABC0 WRITE   4085354\n0x401FAA00 WRITE   4085361\n0x401FA9C0 WRITE   4085363\n0x401FA900 WRITE   4085373\n0x401FA8C0 WRITE   4085375\n0x401FA880 WRITE   4085380\n0x401FA840 WRITE   4085383\n0x401AD6C0 WRITE   4085408\n0x401FA980 WRITE   4085847\n0x401FA940 WRITE   4085849\n0x401C0F80 WRITE   4085933\n0x401FAB00 WRITE   4086319\n0x401FAAC0 WRITE   4086321\n0x401FAA80 WRITE   4086328\n0x401FAA40 WRITE   4086330\n0x401AD700 WRITE   4086363\n0x401FAB80 WRITE   4086834\n0x401FAB40 WRITE   4086836\n0x401C0FC0 WRITE   4086920\n0x401FAE00 WRITE   4087339\n0x401FADC0 WRITE   4087341\n0x401FAD00 WRITE   4087348\n0x401FACC0 WRITE   4087350\n0x401FAC80 WRITE   4087360\n0x401FAC40 WRITE   4087362\n0x401AD740 WRITE   4087389\n0x401FAD80 WRITE   4087837\n0x401FAD40 WRITE   4087839\n0x401C1000 WRITE   4087923\n0x401FAF00 WRITE   4088318\n0x401FAEC0 WRITE   4088320\n0x401FAE80 WRITE   4088327\n0x401FAE40 WRITE   4088329\n0x401AD780 WRITE   4088362\n0x401FAF80 WRITE   4088842\n0x401FAF40 WRITE   4088844\n0x401C1040 WRITE   4088928\n0x401FB800 WRITE   4089360\n0x401FB7C0 WRITE   4089362\n0x401FB400 WRITE   4089369\n0x401FB3C0 WRITE   4089371\n0x401FB200 WRITE   4089381\n0x401FB1C0 WRITE   4089383\n0x401FB100 WRITE   4089388\n0x401FB0C0 WRITE   4089391\n0x401FB080 WRITE   4089394\n0x401FB040 WRITE   4089397\n0x401AD7C0 WRITE   4089422\n0x401FB180 WRITE   4089853\n0x401FB140 WRITE   4089855\n0x401C1080 WRITE   4089939\n0x401FB300 WRITE   4090323\n0x401FB2C0 WRITE   4090325\n0x401FB280 WRITE   4090332\n0x401FB240 WRITE   4090334\n0x401AD800 WRITE   4090367\n0x401FB380 WRITE   4090830\n0x401FB340 WRITE   4090832\n0x401C10C0 WRITE   4090916\n0x401FB600 WRITE   4091333\n0x401FB5C0 WRITE   4091335\n0x401FB500 WRITE   4091342\n0x401FB4C0 WRITE   4091344\n0x401FB480 WRITE   4091354\n0x401FB440 WRITE   4091356\n0x401AD840 WRITE   4091383\n0x401FB580 WRITE   4091824\n0x401FB540 WRITE   4091826\n0x401C1100 WRITE   4091910\n0x401FB700 WRITE   4092304\n0x401FB6C0 WRITE   4092306\n0x401FB680 WRITE   4092313\n0x401FB640 WRITE   4092315\n0x401AD880 WRITE   4092348\n0x401FB780 WRITE   4092821\n0x401FB740 WRITE   4092823\n0x401C1140 WRITE   4092907\n0x401FBC00 WRITE   4093339\n0x401FBBC0 WRITE   4093341\n0x401FBA00 WRITE   4093348\n0x401FB9C0 WRITE   4093350\n0x401FB900 WRITE   4093360\n0x401FB8C0 WRITE   4093362\n0x401FB880 WRITE   4093367\n0x401FB840 WRITE   4093370\n0x401AD8C0 WRITE   4093395\n0x401FB980 WRITE   4093834\n0x401FB940 WRITE   4093836\n0x401C1180 WRITE   4093920\n0x401FBB00 WRITE   4094312\n0x401FBAC0 WRITE   4094314\n0x401FBA80 WRITE   4094321\n0x401FBA40 WRITE   4094323\n0x401AD900 WRITE   4094356\n0x401FBB80 WRITE   4094827\n0x401FBB40 WRITE   4094829\n0x401C11C0 WRITE   4094913\n0x401FBE00 WRITE   4095338\n0x401FBDC0 WRITE   4095340\n0x401FBD00 WRITE   4095347\n0x401FBCC0 WRITE   4095349\n0x401FBC80 WRITE   4095359\n0x401FBC40 WRITE   4095361\n0x401AD940 WRITE   4095388\n0x401FBD80 WRITE   4095836\n0x401FBD40 WRITE   4095838\n0x401C1200 WRITE   4095922\n0x401FBF00 WRITE   4096323\n0x401FBEC0 WRITE   4096325\n0x401FBE80 WRITE   4096332\n0x401FBE40 WRITE   4096334\n0x401AD980 WRITE   4096367\n0x401FBF80 WRITE   4096847\n0x401FBF40 WRITE   4096849\n0x401C1240 WRITE   4096933\n0x401FDFC0 WRITE   4097417\n0x401FE000 WRITE   4097451\n0x401FD000 WRITE   4097582\n0x401FCFC0 WRITE   4097584\n0x401FC800 WRITE   4097591\n0x401FC7C0 WRITE   4097593\n0x401FC400 WRITE   4097603\n0x401FC3C0 WRITE   4097605\n0x401FC200 WRITE   4097610\n0x401FC1C0 WRITE   4097613\n0x401FC100 WRITE   4097616\n0x401FC0C0 WRITE   4097619\n0x401FC080 WRITE   4097622\n0x401FC040 WRITE   4097625\n0x401AD9C0 WRITE   4097658\n0x401FC180 WRITE   4098088\n0x401FC140 WRITE   4098090\n0x401C1280 WRITE   4098174\n0x401FC300 WRITE   4098553\n0x401FC2C0 WRITE   4098555\n0x401FC280 WRITE   4098562\n0x401FC240 WRITE   4098564\n0x401ADA00 WRITE   4098597\n0x401FC380 WRITE   4099060\n0x401FC340 WRITE   4099062\n0x401C12C0 WRITE   4099146\n0x401FC600 WRITE   4099557\n0x401FC5C0 WRITE   4099559\n0x401FC500 WRITE   4099566\n0x401FC4C0 WRITE   4099568\n0x401FC480 WRITE   4099578\n0x401FC440 WRITE   4099580\n0x401ADA40 WRITE   4099607\n0x401FC580 WRITE   4100048\n0x401FC540 WRITE   4100050\n0x401C1300 WRITE   4100134\n0x401FC700 WRITE   4100522\n0x401FC6C0 WRITE   4100524\n0x401FC680 WRITE   4100531\n0x401FC640 WRITE   4100533\n0x401ADA80 WRITE   4100566\n0x401FC780 WRITE   4101039\n0x401FC740 WRITE   4101041\n0x401C1340 WRITE   4101125\n0x401FCC00 WRITE   4101551\n0x401FCBC0 WRITE   4101553\n0x401FCA00 WRITE   4101560\n0x401FC9C0 WRITE   4101562\n0x401FC900 WRITE   4101572\n0x401FC8C0 WRITE   4101574\n0x401FC880 WRITE   4101579\n0x401FC840 WRITE   4101582\n0x401ADAC0 WRITE   4101607\n0x401FC980 WRITE   4102046\n0x401FC940 WRITE   4102048\n0x401C1380 WRITE   4102132\n0x401FCB00 WRITE   4102518\n0x401FCAC0 WRITE   4102520\n0x401FCA80 WRITE   4102527\n0x401FCA40 WRITE   4102529\n0x401ADB00 WRITE   4102562\n0x401FCB80 WRITE   4103033\n0x401FCB40 WRITE   4103035\n0x401C13C0 WRITE   4103119\n0x401FCE00 WRITE   4103538\n0x401FCDC0 WRITE   4103540\n0x401FCD00 WRITE   4103547\n0x401FCCC0 WRITE   4103549\n0x401FCC80 WRITE   4103559\n0x401FCC40 WRITE   4103561\n0x401ADB40 WRITE   4103588\n0x401FCD80 WRITE   4104036\n0x401FCD40 WRITE   4104038\n0x401C1400 WRITE   4104122\n0x401FCF00 WRITE   4104517\n0x401FCEC0 WRITE   4104519\n0x401FCE80 WRITE   4104526\n0x401FCE40 WRITE   4104528\n0x401ADB80 WRITE   4104561\n0x401FCF80 WRITE   4105041\n0x401FCF40 WRITE   4105043\n0x401C1440 WRITE   4105127\n0x401FD800 WRITE   4105559\n0x401FD7C0 WRITE   4105561\n0x401FD400 WRITE   4105568\n0x401FD3C0 WRITE   4105570\n0x401FD200 WRITE   4105580\n0x401FD1C0 WRITE   4105582\n0x401FD100 WRITE   4105587\n0x401FD0C0 WRITE   4105590\n0x401FD080 WRITE   4105593\n0x401FD040 WRITE   4105596\n0x401ADBC0 WRITE   4105621\n0x401FD180 WRITE   4106052\n0x401FD140 WRITE   4106054\n0x401C1480 WRITE   4106138\n0x401FD300 WRITE   4106522\n0x401FD2C0 WRITE   4106524\n0x401FD280 WRITE   4106531\n0x401FD240 WRITE   4106533\n0x401ADC00 WRITE   4106566\n0x401FD380 WRITE   4107029\n0x401FD340 WRITE   4107031\n0x401C14C0 WRITE   4107115\n0x401FD600 WRITE   4107532\n0x401FD5C0 WRITE   4107534\n0x401FD500 WRITE   4107541\n0x401FD4C0 WRITE   4107543\n0x401FD480 WRITE   4107553\n0x401FD440 WRITE   4107555\n0x401ADC40 WRITE   4107582\n0x401FD580 WRITE   4108023\n0x401FD540 WRITE   4108025\n0x401C1500 WRITE   4108109\n0x401FD700 WRITE   4108503\n0x401FD6C0 WRITE   4108505\n0x401FD680 WRITE   4108512\n0x401FD640 WRITE   4108514\n0x401ADC80 WRITE   4108547\n0x401FD780 WRITE   4109020\n0x401FD740 WRITE   4109022\n0x401C1540 WRITE   4109106\n0x401FDC00 WRITE   4109538\n0x401FDBC0 WRITE   4109540\n0x401FDA00 WRITE   4109547\n0x401FD9C0 WRITE   4109549\n0x401FD900 WRITE   4109559\n0x401FD8C0 WRITE   4109561\n0x401FD880 WRITE   4109566\n0x401FD840 WRITE   4109569\n0x401ADCC0 WRITE   4109594\n0x401FD980 WRITE   4110033\n0x401FD940 WRITE   4110035\n0x401C1580 WRITE   4110119\n0x401FDB00 WRITE   4110511\n0x401FDAC0 WRITE   4110513\n0x401FDA80 WRITE   4110520\n0x401FDA40 WRITE   4110522\n0x401ADD00 WRITE   4110555\n0x401FDB80 WRITE   4111026\n0x401FDB40 WRITE   4111028\n0x401C15C0 WRITE   4111112\n0x401FDE00 WRITE   4111537\n0x401FDDC0 WRITE   4111539\n0x401FDD00 WRITE   4111546\n0x401FDCC0 WRITE   4111548\n0x401FDC80 WRITE   4111558\n0x401FDC40 WRITE   4111560\n0x401ADD40 WRITE   4111587\n0x401FDD80 WRITE   4112035\n0x401FDD40 WRITE   4112037\n0x401C1600 WRITE   4112121\n0x401FDF00 WRITE   4112522\n0x401FDEC0 WRITE   4112524\n0x401FDE80 WRITE   4112531\n0x401FDE40 WRITE   4112533\n0x401ADD80 WRITE   4112566\n0x401FDF80 WRITE   4113046\n0x401FDF40 WRITE   4113048\n0x401C1640 WRITE   4113132\n0x401FFFC0 WRITE   4113616\n0x40200000 WRITE   4113650\n0x401FF000 WRITE   4113771\n0x401FEFC0 WRITE   4113773\n0x401FE800 WRITE   4113780\n0x401FE7C0 WRITE   4113782\n0x401FE400 WRITE   4113792\n0x401FE3C0 WRITE   4113794\n0x401FE200 WRITE   4113799\n0x401FE1C0 WRITE   4113802\n0x401FE100 WRITE   4113805\n0x401FE0C0 WRITE   4113808\n0x401FE080 WRITE   4113811\n0x401FE040 WRITE   4113814\n0x401ADDC0 WRITE   4113847\n0x401FE180 WRITE   4114277\n0x401FE140 WRITE   4114279\n0x401C1680 WRITE   4114363\n0x401FE300 WRITE   4114742\n0x401FE2C0 WRITE   4114744\n0x401FE280 WRITE   4114751\n0x401FE240 WRITE   4114753\n0x401ADE00 WRITE   4114786\n0x401FE380 WRITE   4115249\n0x401FE340 WRITE   4115251\n0x401C16C0 WRITE   4115335\n0x401FE600 WRITE   4115746\n0x401FE5C0 WRITE   4115748\n0x401FE500 WRITE   4115755\n0x401FE4C0 WRITE   4115757\n0x401FE480 WRITE   4115767\n0x401FE440 WRITE   4115769\n0x401ADE40 WRITE   4115796\n0x401FE580 WRITE   4116237\n0x401FE540 WRITE   4116239\n0x401C1700 WRITE   4116323\n0x401FE700 WRITE   4116711\n0x401FE6C0 WRITE   4116713\n0x401FE680 WRITE   4116720\n0x401FE640 WRITE   4116722\n0x401ADE80 WRITE   4116755\n0x401FE780 WRITE   4117228\n0x401FE740 WRITE   4117230\n0x401C1740 WRITE   4117314\n0x401FEC00 WRITE   4117740\n0x401FEBC0 WRITE   4117742\n0x401FEA00 WRITE   4117749\n0x401FE9C0 WRITE   4117751\n0x401FE900 WRITE   4117761\n0x401FE8C0 WRITE   4117763\n0x401FE880 WRITE   4117768\n0x401FE840 WRITE   4117771\n0x401ADEC0 WRITE   4117796\n0x401FE980 WRITE   4118235\n0x401FE940 WRITE   4118237\n0x401C1780 WRITE   4118321\n0x401FEB00 WRITE   4118707\n0x401FEAC0 WRITE   4118709\n0x401FEA80 WRITE   4118716\n0x401FEA40 WRITE   4118718\n0x401ADF00 WRITE   4118751\n0x401FEB80 WRITE   4119222\n0x401FEB40 WRITE   4119224\n0x401C17C0 WRITE   4119308\n0x401FEE00 WRITE   4119727\n0x401FEDC0 WRITE   4119729\n0x401FED00 WRITE   4119736\n0x401FECC0 WRITE   4119738\n0x401FEC80 WRITE   4119748\n0x401FEC40 WRITE   4119750\n0x401ADF40 WRITE   4119777\n0x401FED80 WRITE   4120225\n0x401FED40 WRITE   4120227\n0x401C1800 WRITE   4120311\n0x401FEF00 WRITE   4120706\n0x401FEEC0 WRITE   4120708\n0x401FEE80 WRITE   4120715\n0x401FEE40 WRITE   4120717\n0x401ADF80 WRITE   4120750\n0x401FEF80 WRITE   4121230\n0x401FEF40 WRITE   4121232\n0x401C1840 WRITE   4121316\n0x401FF800 WRITE   4121748\n0x401FF7C0 WRITE   4121750\n0x401FF400 WRITE   4121757\n0x401FF3C0 WRITE   4121759\n0x401FF200 WRITE   4121769\n0x401FF1C0 WRITE   4121771\n0x401FF100 WRITE   4121776\n0x401FF0C0 WRITE   4121779\n0x401FF080 WRITE   4121782\n0x401FF040 WRITE   4121785\n0x401ADFC0 WRITE   4121810\n0x401FF180 WRITE   4122241\n0x401FF140 WRITE   4122243\n0x401C1880 WRITE   4122327\n0x401FF300 WRITE   4122711\n0x401FF2C0 WRITE   4122713\n0x401FF280 WRITE   4122720\n0x401FF240 WRITE   4122722\n0x401AE000 WRITE   4122755\n0x401FF380 WRITE   4123218\n0x401FF340 WRITE   4123220\n0x401C18C0 WRITE   4123304\n0x401FF600 WRITE   4123721\n0x401FF5C0 WRITE   4123723\n0x401FF500 WRITE   4123730\n0x401FF4C0 WRITE   4123732\n0x401FF480 WRITE   4123742\n0x401FF440 WRITE   4123744\n0x401AE040 WRITE   4123771\n0x401FF580 WRITE   4124212\n0x401FF540 WRITE   4124214\n0x401C1900 WRITE   4124298\n0x401FF700 WRITE   4124692\n0x401FF6C0 WRITE   4124694\n0x401FF680 WRITE   4124701\n0x401FF640 WRITE   4124703\n0x401AE080 WRITE   4124736\n0x401FF780 WRITE   4125209\n0x401FF740 WRITE   4125211\n0x401C1940 WRITE   4125295\n0x401FFC00 WRITE   4125727\n0x401FFBC0 WRITE   4125729\n0x401FFA00 WRITE   4125736\n0x401FF9C0 WRITE   4125738\n0x401FF900 WRITE   4125748\n0x401FF8C0 WRITE   4125750\n0x401FF880 WRITE   4125755\n0x401FF840 WRITE   4125758\n0x401AE0C0 WRITE   4125783\n0x401FF980 WRITE   4126222\n0x401FF940 WRITE   4126224\n0x401C1980 WRITE   4126308\n0x401FFB00 WRITE   4126700\n0x401FFAC0 WRITE   4126702\n0x401FFA80 WRITE   4126709\n0x401FFA40 WRITE   4126711\n0x401AE100 WRITE   4126744\n0x401FFB80 WRITE   4127215\n0x401FFB40 WRITE   4127217\n0x401C19C0 WRITE   4127301\n0x401FFE00 WRITE   4127726\n0x401FFDC0 WRITE   4127728\n0x401FFD00 WRITE   4127735\n0x401FFCC0 WRITE   4127737\n0x401FFC80 WRITE   4127747\n0x401FFC40 WRITE   4127749\n0x401AE140 WRITE   4127776\n0x401FFD80 WRITE   4128224\n0x401FFD40 WRITE   4128226\n0x401C1A00 WRITE   4128310\n0x401FFF00 WRITE   4128711\n0x401FFEC0 WRITE   4128713\n0x401FFE80 WRITE   4128720\n0x401FFE40 WRITE   4128722\n0x401AE180 WRITE   4128755\n0x401FFF80 WRITE   4129235\n0x401FFF40 WRITE   4129237\n0x401C1A40 WRITE   4129321\n0x40201FC0 WRITE   4129805\n0x40202000 WRITE   4129867\n0x40201000 WRITE   4129997\n0x40200FC0 WRITE   4129999\n0x40200800 WRITE   4130006\n0x402007C0 WRITE   4130008\n0x40200400 WRITE   4130018\n0x402003C0 WRITE   4130020\n0x40200200 WRITE   4130025\n0x402001C0 WRITE   4130028\n0x40200100 WRITE   4130031\n0x402000C0 WRITE   4130034\n0x40200080 WRITE   4130037\n0x40200040 WRITE   4130040\n0x401AE1C0 WRITE   4130073\n0x40200180 WRITE   4130503\n0x40200140 WRITE   4130505\n0x401C1A80 WRITE   4130589\n0x40200300 WRITE   4130968\n0x402002C0 WRITE   4130970\n0x40200280 WRITE   4130977\n0x40200240 WRITE   4130979\n0x401AE200 WRITE   4131012\n0x40200380 WRITE   4131475\n0x40200340 WRITE   4131477\n0x401C1AC0 WRITE   4131561\n0x40200600 WRITE   4131972\n0x402005C0 WRITE   4131974\n0x40200500 WRITE   4131981\n0x402004C0 WRITE   4131983\n0x40200480 WRITE   4131993\n0x40200440 WRITE   4131995\n0x401AE240 WRITE   4132022\n0x40200580 WRITE   4132463\n0x40200540 WRITE   4132465\n0x401C1B00 WRITE   4132549\n0x40200700 WRITE   4132937\n0x402006C0 WRITE   4132939\n0x40200680 WRITE   4132946\n0x40200640 WRITE   4132948\n0x401AE280 WRITE   4132981\n0x40200780 WRITE   4133454\n0x40200740 WRITE   4133456\n0x401C1B40 WRITE   4133540\n0x40200C00 WRITE   4133966\n0x40200BC0 WRITE   4133968\n0x40200A00 WRITE   4133975\n0x402009C0 WRITE   4133977\n0x40200900 WRITE   4133987\n0x402008C0 WRITE   4133989\n0x40200880 WRITE   4133994\n0x40200840 WRITE   4133997\n0x401AE2C0 WRITE   4134022\n0x40200980 WRITE   4134461\n0x40200940 WRITE   4134463\n0x401C1B80 WRITE   4134547\n0x40200B00 WRITE   4134933\n0x40200AC0 WRITE   4134935\n0x40200A80 WRITE   4134942\n0x40200A40 WRITE   4134944\n0x401AE300 WRITE   4134977\n0x40200B80 WRITE   4135448\n0x40200B40 WRITE   4135450\n0x401C1BC0 WRITE   4135534\n0x40200E00 WRITE   4135953\n0x40200DC0 WRITE   4135955\n0x40200D00 WRITE   4135962\n0x40200CC0 WRITE   4135964\n0x40200C80 WRITE   4135974\n0x40200C40 WRITE   4135976\n0x401AE340 WRITE   4136003\n0x40200D80 WRITE   4136451\n0x40200D40 WRITE   4136453\n0x401C1C00 WRITE   4136537\n0x40200F00 WRITE   4136932\n0x40200EC0 WRITE   4136934\n0x40200E80 WRITE   4136941\n0x40200E40 WRITE   4136943\n0x401AE380 WRITE   4136976\n0x40200F80 WRITE   4137456\n0x40200F40 WRITE   4137458\n0x401C1C40 WRITE   4137542\n0x40201800 WRITE   4137974\n0x402017C0 WRITE   4137976\n0x40201400 WRITE   4137983\n0x402013C0 WRITE   4137985\n0x40201200 WRITE   4137995\n0x402011C0 WRITE   4137997\n0x40201100 WRITE   4138002\n0x402010C0 WRITE   4138005\n0x40201080 WRITE   4138008\n0x40201040 WRITE   4138011\n0x401AE3C0 WRITE   4138036\n0x40201180 WRITE   4138467\n0x40201140 WRITE   4138469\n0x401C1C80 WRITE   4138553\n0x40201300 WRITE   4138937\n0x402012C0 WRITE   4138939\n0x40201280 WRITE   4138946\n0x40201240 WRITE   4138948\n0x401AE400 WRITE   4138981\n0x40201380 WRITE   4139444\n0x40201340 WRITE   4139446\n0x401C1CC0 WRITE   4139530\n0x40201600 WRITE   4139947\n0x402015C0 WRITE   4139949\n0x40201500 WRITE   4139956\n0x402014C0 WRITE   4139958\n0x40201480 WRITE   4139968\n0x40201440 WRITE   4139970\n0x401AE440 WRITE   4139997\n0x40201580 WRITE   4140438\n0x40201540 WRITE   4140440\n0x401C1D00 WRITE   4140524\n0x40201700 WRITE   4140918\n0x402016C0 WRITE   4140920\n0x40201680 WRITE   4140927\n0x40201640 WRITE   4140929\n0x401AE480 WRITE   4140962\n0x40201780 WRITE   4141435\n0x40201740 WRITE   4141437\n0x401C1D40 WRITE   4141521\n0x40201C00 WRITE   4141953\n0x40201BC0 WRITE   4141955\n0x40201A00 WRITE   4141962\n0x402019C0 WRITE   4141964\n0x40201900 WRITE   4141974\n0x402018C0 WRITE   4141976\n0x40201880 WRITE   4141981\n0x40201840 WRITE   4141984\n0x401AE4C0 WRITE   4142009\n0x40201980 WRITE   4142448\n0x40201940 WRITE   4142450\n0x401C1D80 WRITE   4142534\n0x40201B00 WRITE   4142926\n0x40201AC0 WRITE   4142928\n0x40201A80 WRITE   4142935\n0x40201A40 WRITE   4142937\n0x401AE500 WRITE   4142970\n0x40201B80 WRITE   4143441\n0x40201B40 WRITE   4143443\n0x401C1DC0 WRITE   4143527\n0x40201E00 WRITE   4143952\n0x40201DC0 WRITE   4143954\n0x40201D00 WRITE   4143961\n0x40201CC0 WRITE   4143963\n0x40201C80 WRITE   4143973\n0x40201C40 WRITE   4143975\n0x401AE540 WRITE   4144002\n0x40201D80 WRITE   4144450\n0x40201D40 WRITE   4144452\n0x401C1E00 WRITE   4144536\n0x40201F00 WRITE   4144937\n0x40201EC0 WRITE   4144939\n0x40201E80 WRITE   4144946\n0x40201E40 WRITE   4144948\n0x401AE580 WRITE   4144981\n0x40201F80 WRITE   4145461\n0x40201F40 WRITE   4145463\n0x401C1E40 WRITE   4145547\n0x40202880 WRITE   4146174\n0x40203FC0 WRITE   4146311\n0x40204000 WRITE   4146345\n0x40203000 WRITE   4146466\n0x40202FC0 WRITE   4146468\n0x40202800 WRITE   4146475\n0x402027C0 WRITE   4146477\n0x40202400 WRITE   4146487\n0x402023C0 WRITE   4146489\n0x40202200 WRITE   4146494\n0x402021C0 WRITE   4146497\n0x40202100 WRITE   4146500\n0x402020C0 WRITE   4146503\n0x40202080 WRITE   4146506\n0x40202040 WRITE   4146509\n0x401AE5C0 WRITE   4146542\n0x40202180 WRITE   4146977\n0x40202140 WRITE   4146979\n0x401C1E80 WRITE   4147063\n0x40202300 WRITE   4147442\n0x402022C0 WRITE   4147444\n0x40202280 WRITE   4147451\n0x40202240 WRITE   4147453\n0x401AE600 WRITE   4147486\n0x40202380 WRITE   4147949\n0x40202340 WRITE   4147951\n0x401C1EC0 WRITE   4148035\n0x40202600 WRITE   4148446\n0x402025C0 WRITE   4148448\n0x40202500 WRITE   4148455\n0x402024C0 WRITE   4148457\n0x40202480 WRITE   4148467\n0x40202440 WRITE   4148469\n0x401AE640 WRITE   4148496\n0x40202580 WRITE   4148937\n0x40202540 WRITE   4148939\n0x401C1F00 WRITE   4149023\n0x40202700 WRITE   4149411\n0x402026C0 WRITE   4149413\n0x40202680 WRITE   4149420\n0x40202640 WRITE   4149422\n0x401AE680 WRITE   4149455\n0x40202780 WRITE   4149928\n0x40202740 WRITE   4149930\n0x401C1F40 WRITE   4150014\n0x40202C00 WRITE   4150440\n0x40202BC0 WRITE   4150442\n0x40202A00 WRITE   4150449\n0x402029C0 WRITE   4150451\n0x40202900 WRITE   4150461\n0x402028C0 WRITE   4150463\n0x40202840 WRITE   4150471\n0x401AE6C0 WRITE   4150496\n0x40202980 WRITE   4150935\n0x40202940 WRITE   4150937\n0x401C1F80 WRITE   4151021\n0x40202B00 WRITE   4151407\n0x40202AC0 WRITE   4151409\n0x40202A80 WRITE   4151416\n0x40202A40 WRITE   4151418\n0x401AE700 WRITE   4151451\n0x40202B80 WRITE   4151922\n0x40202B40 WRITE   4151924\n0x401C1FC0 WRITE   4152008\n0x40202E00 WRITE   4152427\n0x40202DC0 WRITE   4152429\n0x40202D00 WRITE   4152436\n0x40202CC0 WRITE   4152438\n0x40202C80 WRITE   4152448\n0x40202C40 WRITE   4152450\n0x401AE740 WRITE   4152477\n0x40202D80 WRITE   4152925\n0x40202D40 WRITE   4152927\n0x401C2000 WRITE   4153011\n0x40202F00 WRITE   4153406\n0x40202EC0 WRITE   4153408\n0x40202E80 WRITE   4153415\n0x40202E40 WRITE   4153417\n0x401AE780 WRITE   4153450\n0x40202F80 WRITE   4153930\n0x40202F40 WRITE   4153932\n0x401C2040 WRITE   4154016\n0x40203800 WRITE   4154448\n0x402037C0 WRITE   4154450\n0x40203400 WRITE   4154457\n0x402033C0 WRITE   4154459\n0x40203200 WRITE   4154469\n0x402031C0 WRITE   4154471\n0x40203100 WRITE   4154476\n0x402030C0 WRITE   4154479\n0x40203080 WRITE   4154482\n0x40203040 WRITE   4154485\n0x401AE7C0 WRITE   4154510\n0x40203180 WRITE   4154941\n0x40203140 WRITE   4154943\n0x401C2080 WRITE   4155027\n0x40203300 WRITE   4155411\n0x402032C0 WRITE   4155413\n0x40203280 WRITE   4155420\n0x40203240 WRITE   4155422\n0x401AE800 WRITE   4155455\n0x40203380 WRITE   4155918\n0x40203340 WRITE   4155920\n0x401C20C0 WRITE   4156004\n0x40203600 WRITE   4156421\n0x402035C0 WRITE   4156423\n0x40203500 WRITE   4156430\n0x402034C0 WRITE   4156432\n0x40203480 WRITE   4156442\n0x40203440 WRITE   4156444\n0x401AE840 WRITE   4156471\n0x40203580 WRITE   4156912\n0x40203540 WRITE   4156914\n0x401C2100 WRITE   4156998\n0x40203700 WRITE   4157392\n0x402036C0 WRITE   4157394\n0x40203680 WRITE   4157401\n0x40203640 WRITE   4157403\n0x401AE880 WRITE   4157436\n0x40203780 WRITE   4157909\n0x40203740 WRITE   4157911\n0x401C2140 WRITE   4157995\n0x40203C00 WRITE   4158427\n0x40203BC0 WRITE   4158429\n0x40203A00 WRITE   4158436\n0x402039C0 WRITE   4158438\n0x40203900 WRITE   4158448\n0x402038C0 WRITE   4158450\n0x40203880 WRITE   4158455\n0x40203840 WRITE   4158458\n0x401AE8C0 WRITE   4158483\n0x40203980 WRITE   4158922\n0x40203940 WRITE   4158924\n0x401C2180 WRITE   4159008\n0x40203B00 WRITE   4159400\n0x40203AC0 WRITE   4159402\n0x40203A80 WRITE   4159409\n0x40203A40 WRITE   4159411\n0x401AE900 WRITE   4159444\n0x40203B80 WRITE   4159915\n0x40203B40 WRITE   4159917\n0x401C21C0 WRITE   4160001\n0x40203E00 WRITE   4160426\n0x40203DC0 WRITE   4160428\n0x40203D00 WRITE   4160435\n0x40203CC0 WRITE   4160437\n0x40203C80 WRITE   4160447\n0x40203C40 WRITE   4160449\n0x401AE940 WRITE   4160476\n0x40203D80 WRITE   4160924\n0x40203D40 WRITE   4160926\n0x401C2200 WRITE   4161010\n0x40203F00 WRITE   4161411\n0x40203EC0 WRITE   4161413\n0x40203E80 WRITE   4161420\n0x40203E40 WRITE   4161422\n0x401AE980 WRITE   4161455\n0x40203F80 WRITE   4161935\n0x40203F40 WRITE   4161937\n0x401C2240 WRITE   4162021\n0x40205FC0 WRITE   4162505\n0x40206000 WRITE   4162539\n0x40155C00 WRITE   4162668\n0x40154C40 WRITE   4162742\n0x40154C80 WRITE   4162766\n0x40154CC0 WRITE   4162790\n0x40154D00 WRITE   4162814\n0x40154D40 WRITE   4162838\n0x40154D80 WRITE   4162862\n0x40154DC0 WRITE   4162886\n0x40154E00 WRITE   4162910\n0x40154E40 WRITE   4162934\n0x40154E80 WRITE   4162958\n0x40154EC0 WRITE   4162982\n0x40154F00 WRITE   4163006\n0x40154F40 WRITE   4163030\n0x40154F80 WRITE   4163054\n0x40154FC0 WRITE   4163078\n0x40155000 WRITE   4163102\n0x40155040 WRITE   4163126\n0x40155080 WRITE   4163150\n0x401550C0 WRITE   4163174\n0x40155100 WRITE   4163198\n0x40155140 WRITE   4163222\n0x40155180 WRITE   4163246\n0x401551C0 WRITE   4163270\n0x40155200 WRITE   4163294\n0x40155240 WRITE   4163318\n0x40155280 WRITE   4163342\n0x401552C0 WRITE   4163366\n0x40155300 WRITE   4163397\n0x40155340 WRITE   4163437\n0x40155380 WRITE   4163477\n0x401553C0 WRITE   4163517\n0x40155400 WRITE   4163557\n0x40155440 WRITE   4163597\n0x40155480 WRITE   4163637\n0x401554C0 WRITE   4163677\n0x40155500 WRITE   4163717\n0x40155540 WRITE   4163757\n0x40155580 WRITE   4163797\n0x401555C0 WRITE   4163837\n0x40155600 WRITE   4163877\n0x40155640 WRITE   4163917\n0x40155680 WRITE   4163957\n0x401556C0 WRITE   4163997\n0x40155700 WRITE   4164037\n0x40155740 WRITE   4164077\n0x40155780 WRITE   4164117\n0x401557C0 WRITE   4164157\n0x40155800 WRITE   4164197\n0x40155840 WRITE   4164237\n0x40155880 WRITE   4164277\n0x401558C0 WRITE   4164317\n0x40155900 WRITE   4164357\n0x40155940 WRITE   4164397\n0x40155980 WRITE   4164437\n0x401559C0 WRITE   4164477\n0x40155A00 WRITE   4164517\n0x40155A40 WRITE   4164557\n0x40155A80 WRITE   4164597\n0x40155AC0 WRITE   4164637\n0x40155B00 WRITE   4164677\n0x40155B40 WRITE   4164717\n0x40155B80 WRITE   4164757\n0x40155BC0 WRITE   4164797\n0x40205000 WRITE   4169634\n0x40204FC0 WRITE   4169636\n0x40204800 WRITE   4169643\n0x402047C0 WRITE   4169645\n0x40204400 WRITE   4169655\n0x402043C0 WRITE   4169657\n0x40204200 WRITE   4169662\n0x402041C0 WRITE   4169665\n0x40204100 WRITE   4169673\n0x402040C0 WRITE   4169676\n0x40204080 WRITE   4169679\n0x40204040 WRITE   4169681\n0x401AE9C0 WRITE   4169714\n0x40204180 WRITE   4170152\n0x40204140 WRITE   4170154\n0x401C2280 WRITE   4170238\n0x40204300 WRITE   4170617\n0x402042C0 WRITE   4170619\n0x40204280 WRITE   4170626\n0x40204240 WRITE   4170628\n0x401AEA00 WRITE   4170661\n0x40204380 WRITE   4171124\n0x40204340 WRITE   4171126\n0x401C22C0 WRITE   4171210\n0x40204600 WRITE   4171621\n0x402045C0 WRITE   4171623\n0x40204500 WRITE   4171630\n0x402044C0 WRITE   4171632\n0x40204480 WRITE   4171642\n0x40204440 WRITE   4171644\n0x401AEA40 WRITE   4171671\n0x40204580 WRITE   4172112\n0x40204540 WRITE   4172114\n0x401C2300 WRITE   4172198\n0x40204700 WRITE   4172586\n0x402046C0 WRITE   4172588\n0x40204680 WRITE   4172595\n0x40204640 WRITE   4172597\n0x401AEA80 WRITE   4172630\n0x40204780 WRITE   4173103\n0x40204740 WRITE   4173105\n0x401C2340 WRITE   4173189\n0x40204C00 WRITE   4173615\n0x40204BC0 WRITE   4173617\n0x40204A00 WRITE   4173624\n0x402049C0 WRITE   4173626\n0x40204900 WRITE   4173636\n0x402048C0 WRITE   4173638\n0x40204880 WRITE   4173643\n0x40204840 WRITE   4173646\n0x401AEAC0 WRITE   4173671\n0x40204980 WRITE   4174110\n0x40204940 WRITE   4174112\n0x401C2380 WRITE   4174196\n0x40204B00 WRITE   4174582\n0x40204AC0 WRITE   4174584\n0x40204A80 WRITE   4174591\n0x40204A40 WRITE   4174593\n0x401AEB00 WRITE   4174626\n0x40204B80 WRITE   4175097\n0x40204B40 WRITE   4175099\n0x401C23C0 WRITE   4175183\n0x40204E00 WRITE   4175602\n0x40204DC0 WRITE   4175604\n0x40204D00 WRITE   4175611\n0x40204CC0 WRITE   4175613\n0x40204C80 WRITE   4175623\n0x40204C40 WRITE   4175625\n0x401AEB40 WRITE   4175652\n0x40204D80 WRITE   4176100\n0x40204D40 WRITE   4176102\n0x401C2400 WRITE   4176186\n0x40204F00 WRITE   4176581\n0x40204EC0 WRITE   4176583\n0x40204E80 WRITE   4176590\n0x40204E40 WRITE   4176592\n0x401AEB80 WRITE   4176625\n0x40204F80 WRITE   4177105\n0x40204F40 WRITE   4177107\n0x401C2440 WRITE   4177191\n0x40205800 WRITE   4177623\n0x402057C0 WRITE   4177625\n0x40205400 WRITE   4177632\n0x402053C0 WRITE   4177634\n0x40205200 WRITE   4177644\n0x402051C0 WRITE   4177646\n0x40205100 WRITE   4177651\n0x402050C0 WRITE   4177654\n0x40205080 WRITE   4177657\n0x40205040 WRITE   4177660\n0x401AEBC0 WRITE   4177685\n0x40205180 WRITE   4178116\n0x40205140 WRITE   4178118\n0x401C2480 WRITE   4178202\n0x40205300 WRITE   4178586\n0x402052C0 WRITE   4178588\n0x40205280 WRITE   4178595\n0x40205240 WRITE   4178597\n0x401AEC00 WRITE   4178630\n0x40205380 WRITE   4179093\n0x40205340 WRITE   4179095\n0x401C24C0 WRITE   4179179\n0x40205600 WRITE   4179596\n0x402055C0 WRITE   4179598\n0x40205500 WRITE   4179605\n0x402054C0 WRITE   4179607\n0x40205480 WRITE   4179617\n0x40205440 WRITE   4179619\n0x401AEC40 WRITE   4179646\n0x40205580 WRITE   4180087\n0x40205540 WRITE   4180089\n0x401C2500 WRITE   4180173\n0x40205700 WRITE   4180567\n0x402056C0 WRITE   4180569\n0x40205680 WRITE   4180576\n0x40205640 WRITE   4180578\n0x401AEC80 WRITE   4180611\n0x40205780 WRITE   4181084\n0x40205740 WRITE   4181086\n0x401C2540 WRITE   4181170\n0x40205C00 WRITE   4181602\n0x40205BC0 WRITE   4181604\n0x40205A00 WRITE   4181611\n0x402059C0 WRITE   4181613\n0x40205900 WRITE   4181623\n0x402058C0 WRITE   4181625\n0x40205880 WRITE   4181630\n0x40205840 WRITE   4181633\n0x401AECC0 WRITE   4181658\n0x40205980 WRITE   4182097\n0x40205940 WRITE   4182099\n0x401C2580 WRITE   4182183\n0x40205B00 WRITE   4182575\n0x40205AC0 WRITE   4182577\n0x40205A80 WRITE   4182584\n0x40205A40 WRITE   4182586\n0x401AED00 WRITE   4182619\n0x40205B80 WRITE   4183090\n0x40205B40 WRITE   4183092\n0x401C25C0 WRITE   4183176\n0x40205E00 WRITE   4183601\n0x40205DC0 WRITE   4183603\n0x40205D00 WRITE   4183610\n0x40205CC0 WRITE   4183612\n0x40205C80 WRITE   4183622\n0x40205C40 WRITE   4183624\n0x401AED40 WRITE   4183651\n0x40205D80 WRITE   4184099\n0x40205D40 WRITE   4184101\n0x401C2600 WRITE   4184185\n0x40205F00 WRITE   4184586\n0x40205EC0 WRITE   4184588\n0x40205E80 WRITE   4184595\n0x40205E40 WRITE   4184597\n0x401AED80 WRITE   4184630\n0x40205F80 WRITE   4185110\n0x40205F40 WRITE   4185112\n0x401C2640 WRITE   4185196\n0x40207FC0 WRITE   4185684\n0x40208000 WRITE   4185718\n0x40207000 WRITE   4185834\n0x40206FC0 WRITE   4185836\n0x40206800 WRITE   4185843\n0x402067C0 WRITE   4185845\n0x40206400 WRITE   4185855\n0x402063C0 WRITE   4185857\n0x40206200 WRITE   4185862\n0x402061C0 WRITE   4185865\n0x40206100 WRITE   4185868\n0x402060C0 WRITE   4185871\n0x40206080 WRITE   4185874\n0x40206040 WRITE   4185877\n0x401AEDC0 WRITE   4185910\n0x40206180 WRITE   4186340\n0x40206140 WRITE   4186342\n0x401C2680 WRITE   4186426\n0x40206300 WRITE   4186805\n0x402062C0 WRITE   4186807\n0x40206280 WRITE   4186814\n0x40206240 WRITE   4186816\n0x401AEE00 WRITE   4186849\n0x40206380 WRITE   4187312\n0x40206340 WRITE   4187314\n0x401C26C0 WRITE   4187398\n0x40206600 WRITE   4187809\n0x402065C0 WRITE   4187811\n0x40206500 WRITE   4187818\n0x402064C0 WRITE   4187820\n0x40206480 WRITE   4187830\n0x40206440 WRITE   4187832\n0x401AEE40 WRITE   4187859\n0x40206580 WRITE   4188300\n0x40206540 WRITE   4188302\n0x401C2700 WRITE   4188386\n0x40206700 WRITE   4188774\n0x402066C0 WRITE   4188776\n0x40206680 WRITE   4188783\n0x40206640 WRITE   4188785\n0x401AEE80 WRITE   4188818\n0x40206780 WRITE   4189291\n0x40206740 WRITE   4189293\n0x401C2740 WRITE   4189377\n0x40206C00 WRITE   4189803\n0x40206BC0 WRITE   4189805\n0x40206A00 WRITE   4189812\n0x402069C0 WRITE   4189814\n0x40206900 WRITE   4189824\n0x402068C0 WRITE   4189826\n0x40206880 WRITE   4189831\n0x40206840 WRITE   4189834\n0x401AEEC0 WRITE   4189859\n0x40206980 WRITE   4190298\n0x40206940 WRITE   4190300\n0x401C2780 WRITE   4190384\n0x40206B00 WRITE   4190770\n0x40206AC0 WRITE   4190772\n0x40206A80 WRITE   4190779\n0x40206A40 WRITE   4190781\n0x401AEF00 WRITE   4190814\n0x40206B80 WRITE   4191285\n0x40206B40 WRITE   4191287\n0x401C27C0 WRITE   4191371\n0x40206E00 WRITE   4191790\n0x40206DC0 WRITE   4191792\n0x40206D00 WRITE   4191799\n0x40206CC0 WRITE   4191801\n0x40206C80 WRITE   4191811\n0x40206C40 WRITE   4191813\n0x401AEF40 WRITE   4191840\n0x40206D80 WRITE   4192288\n0x40206D40 WRITE   4192290\n0x401C2800 WRITE   4192374\n0x40206F00 WRITE   4192769\n0x40206EC0 WRITE   4192771\n0x40206E80 WRITE   4192778\n0x40206E40 WRITE   4192780\n0x401AEF80 WRITE   4192813\n0x40206F80 WRITE   4193293\n0x40206F40 WRITE   4193295\n0x401C2840 WRITE   4193379\n0x40207800 WRITE   4193811\n0x402077C0 WRITE   4193813\n0x40207400 WRITE   4193820\n0x402073C0 WRITE   4193822\n0x40207200 WRITE   4193832\n0x402071C0 WRITE   4193834\n0x40207100 WRITE   4193839\n0x402070C0 WRITE   4193842\n0x40207080 WRITE   4193845\n0x40207040 WRITE   4193848\n0x401AEFC0 WRITE   4193873\n0x40207180 WRITE   4194304\n0x40207140 WRITE   4194306\n0x401C2880 WRITE   4194390\n0x40207300 WRITE   4194774\n0x402072C0 WRITE   4194776\n0x40207280 WRITE   4194783\n0x40207240 WRITE   4194785\n0x401AF000 WRITE   4194818\n0x40207380 WRITE   4195281\n0x40207340 WRITE   4195283\n0x401C28C0 WRITE   4195367\n0x40207600 WRITE   4195784\n0x402075C0 WRITE   4195786\n0x40207500 WRITE   4195793\n0x402074C0 WRITE   4195795\n0x40207480 WRITE   4195805\n0x40207440 WRITE   4195807\n0x401AF040 WRITE   4195834\n0x40207580 WRITE   4196275\n0x40207540 WRITE   4196277\n0x401C2900 WRITE   4196361\n0x40207700 WRITE   4196755\n0x402076C0 WRITE   4196757\n0x40207680 WRITE   4196764\n0x40207640 WRITE   4196766\n0x401AF080 WRITE   4196799\n0x40207780 WRITE   4197272\n0x40207740 WRITE   4197274\n0x401C2940 WRITE   4197358\n0x40207C00 WRITE   4197790\n0x40207BC0 WRITE   4197792\n0x40207A00 WRITE   4197799\n0x402079C0 WRITE   4197801\n0x40207900 WRITE   4197811\n0x402078C0 WRITE   4197813\n0x40207880 WRITE   4197818\n0x40207840 WRITE   4197821\n0x401AF0C0 WRITE   4197846\n0x40207980 WRITE   4198285\n0x40207940 WRITE   4198287\n0x401C2980 WRITE   4198371\n0x40207B00 WRITE   4198763\n0x40207AC0 WRITE   4198765\n0x40207A80 WRITE   4198772\n0x40207A40 WRITE   4198774\n0x401AF100 WRITE   4198807\n0x40207B80 WRITE   4199278\n0x40207B40 WRITE   4199280\n0x401C29C0 WRITE   4199364\n0x40207E00 WRITE   4199789\n0x40207DC0 WRITE   4199791\n0x40207D00 WRITE   4199798\n0x40207CC0 WRITE   4199800\n0x40207C80 WRITE   4199810\n0x40207C40 WRITE   4199812\n0x401AF140 WRITE   4199839\n0x40207D80 WRITE   4200287\n0x40207D40 WRITE   4200289\n0x401C2A00 WRITE   4200373\n0x40207F00 WRITE   4200774\n0x40207EC0 WRITE   4200776\n0x40207E80 WRITE   4200783\n0x40207E40 WRITE   4200785\n0x401AF180 WRITE   4200818\n0x40207F80 WRITE   4201298\n0x40207F40 WRITE   4201300\n0x401C2A40 WRITE   4201384\n0x40209FC0 WRITE   4201868\n0x4020A000 WRITE   4201902\n0x40209000 WRITE   4202021\n0x40208FC0 WRITE   4202023\n0x40208800 WRITE   4202030\n0x402087C0 WRITE   4202032\n0x40208400 WRITE   4202042\n0x402083C0 WRITE   4202044\n0x40208200 WRITE   4202049\n0x402081C0 WRITE   4202052\n0x40208100 WRITE   4202055\n0x402080C0 WRITE   4202058\n0x40208080 WRITE   4202061\n0x40208040 WRITE   4202064\n0x401AF1C0 WRITE   4202097\n0x40208180 WRITE   4202527\n0x40208140 WRITE   4202529\n0x401C2A80 WRITE   4202613\n0x40208300 WRITE   4202992\n0x402082C0 WRITE   4202994\n0x40208280 WRITE   4203001\n0x40208240 WRITE   4203003\n0x401AF200 WRITE   4203036\n0x40208380 WRITE   4203499\n0x40208340 WRITE   4203501\n0x401C2AC0 WRITE   4203585\n0x40208600 WRITE   4203996\n0x402085C0 WRITE   4203998\n0x40208500 WRITE   4204005\n0x402084C0 WRITE   4204007\n0x40208480 WRITE   4204017\n0x40208440 WRITE   4204019\n0x401AF240 WRITE   4204046\n0x40208580 WRITE   4204487\n0x40208540 WRITE   4204489\n0x401C2B00 WRITE   4204573\n0x40208700 WRITE   4204961\n0x402086C0 WRITE   4204963\n0x40208680 WRITE   4204970\n0x40208640 WRITE   4204972\n0x401AF280 WRITE   4205005\n0x40208780 WRITE   4205478\n0x40208740 WRITE   4205480\n0x401C2B40 WRITE   4205564\n0x40208C00 WRITE   4205990\n0x40208BC0 WRITE   4205992\n0x40208A00 WRITE   4205999\n0x402089C0 WRITE   4206001\n0x40208900 WRITE   4206011\n0x402088C0 WRITE   4206013\n0x40208880 WRITE   4206018\n0x40208840 WRITE   4206021\n0x401AF2C0 WRITE   4206046\n0x40208980 WRITE   4206485\n0x40208940 WRITE   4206487\n0x401C2B80 WRITE   4206571\n0x40208B00 WRITE   4206957\n0x40208AC0 WRITE   4206959\n0x40208A80 WRITE   4206966\n0x40208A40 WRITE   4206968\n0x401AF300 WRITE   4207001\n0x40208B80 WRITE   4207472\n0x40208B40 WRITE   4207474\n0x401C2BC0 WRITE   4207558\n0x40208E00 WRITE   4207977\n0x40208DC0 WRITE   4207979\n0x40208D00 WRITE   4207986\n0x40208CC0 WRITE   4207988\n0x40208C80 WRITE   4207998\n0x40208C40 WRITE   4208000\n0x401AF340 WRITE   4208027\n0x40208D80 WRITE   4208475\n0x40208D40 WRITE   4208477\n0x401C2C00 WRITE   4208561\n0x40208F00 WRITE   4208956\n0x40208EC0 WRITE   4208958\n0x40208E80 WRITE   4208965\n0x40208E40 WRITE   4208967\n0x401AF380 WRITE   4209000\n0x40208F80 WRITE   4209480\n0x40208F40 WRITE   4209482\n0x401C2C40 WRITE   4209566\n0x40209800 WRITE   4209998\n0x402097C0 WRITE   4210000\n0x40209400 WRITE   4210007\n0x402093C0 WRITE   4210009\n0x40209200 WRITE   4210019\n0x402091C0 WRITE   4210021\n0x40209100 WRITE   4210026\n0x402090C0 WRITE   4210029\n0x40209080 WRITE   4210032\n0x40209040 WRITE   4210035\n0x401AF3C0 WRITE   4210060\n0x40209180 WRITE   4210491\n0x40209140 WRITE   4210493\n0x401C2C80 WRITE   4210577\n0x40209300 WRITE   4210961\n0x402092C0 WRITE   4210963\n0x40209280 WRITE   4210970\n0x40209240 WRITE   4210972\n0x401AF400 WRITE   4211005\n0x40209380 WRITE   4211468\n0x40209340 WRITE   4211470\n0x401C2CC0 WRITE   4211554\n0x40209600 WRITE   4211971\n0x402095C0 WRITE   4211973\n0x40209500 WRITE   4211980\n0x402094C0 WRITE   4211982\n0x40209480 WRITE   4211992\n0x40209440 WRITE   4211994\n0x401AF440 WRITE   4212021\n0x40209580 WRITE   4212462\n0x40209540 WRITE   4212464\n0x401C2D00 WRITE   4212548\n0x40209700 WRITE   4212942\n0x402096C0 WRITE   4212944\n0x40209680 WRITE   4212951\n0x40209640 WRITE   4212953\n0x401AF480 WRITE   4212986\n0x40209780 WRITE   4213459\n0x40209740 WRITE   4213461\n0x401C2D40 WRITE   4213545\n0x40209C00 WRITE   4213977\n0x40209BC0 WRITE   4213979\n0x40209A00 WRITE   4213986\n0x402099C0 WRITE   4213988\n0x40209900 WRITE   4213998\n0x402098C0 WRITE   4214000\n0x40209880 WRITE   4214005\n0x40209840 WRITE   4214008\n0x401AF4C0 WRITE   4214033\n0x40209980 WRITE   4214472\n0x40209940 WRITE   4214474\n0x401C2D80 WRITE   4214558\n0x40209B00 WRITE   4214950\n0x40209AC0 WRITE   4214952\n0x40209A80 WRITE   4214959\n0x40209A40 WRITE   4214961\n0x401AF500 WRITE   4214994\n0x40209B80 WRITE   4215465\n0x40209B40 WRITE   4215467\n0x401C2DC0 WRITE   4215551\n0x40209E00 WRITE   4215976\n0x40209DC0 WRITE   4215978\n0x40209D00 WRITE   4215985\n0x40209CC0 WRITE   4215987\n0x40209C80 WRITE   4215997\n0x40209C40 WRITE   4215999\n0x401AF540 WRITE   4216026\n0x40209D80 WRITE   4216474\n0x40209D40 WRITE   4216476\n0x401C2E00 WRITE   4216560\n0x40209F00 WRITE   4216961\n0x40209EC0 WRITE   4216963\n0x40209E80 WRITE   4216970\n0x40209E40 WRITE   4216972\n0x401AF580 WRITE   4217005\n0x40209F80 WRITE   4217485\n0x40209F40 WRITE   4217487\n0x401C2E40 WRITE   4217571\n0x4020BFC0 WRITE   4218055\n0x4020C000 WRITE   4218089\n0x4020B000 WRITE   4218196\n0x4020AFC0 WRITE   4218198\n0x4020A800 WRITE   4218205\n0x4020A7C0 WRITE   4218207\n0x4020A400 WRITE   4218217\n0x4020A3C0 WRITE   4218219\n0x4020A200 WRITE   4218224\n0x4020A1C0 WRITE   4218227\n0x4020A100 WRITE   4218230\n0x4020A0C0 WRITE   4218233\n0x4020A080 WRITE   4218236\n0x4020A040 WRITE   4218239\n0x401AF5C0 WRITE   4218272\n0x4020A180 WRITE   4218702\n0x4020A140 WRITE   4218704\n0x401C2E80 WRITE   4218788\n0x4020A300 WRITE   4219167\n0x4020A2C0 WRITE   4219169\n0x4020A280 WRITE   4219176\n0x4020A240 WRITE   4219178\n0x401AF600 WRITE   4219211\n0x4020A380 WRITE   4219674\n0x4020A340 WRITE   4219676\n0x401C2EC0 WRITE   4219760\n0x4020A600 WRITE   4220171\n0x4020A5C0 WRITE   4220173\n0x4020A500 WRITE   4220180\n0x4020A4C0 WRITE   4220182\n0x4020A480 WRITE   4220192\n0x4020A440 WRITE   4220194\n0x401AF640 WRITE   4220221\n0x4020A580 WRITE   4220662\n0x4020A540 WRITE   4220664\n0x401C2F00 WRITE   4220748\n0x4020A700 WRITE   4221136\n0x4020A6C0 WRITE   4221138\n0x4020A680 WRITE   4221145\n0x4020A640 WRITE   4221147\n0x401AF680 WRITE   4221180\n0x4020A780 WRITE   4221653\n0x4020A740 WRITE   4221655\n0x401C2F40 WRITE   4221739\n0x4020AC00 WRITE   4222165\n0x4020ABC0 WRITE   4222167\n0x4020AA00 WRITE   4222174\n0x4020A9C0 WRITE   4222176\n0x4020A900 WRITE   4222186\n0x4020A8C0 WRITE   4222188\n0x4020A880 WRITE   4222193\n0x4020A840 WRITE   4222196\n0x401AF6C0 WRITE   4222221\n0x4020A980 WRITE   4222660\n0x4020A940 WRITE   4222662\n0x401C2F80 WRITE   4222746\n0x4020AB00 WRITE   4223132\n0x4020AAC0 WRITE   4223134\n0x4020AA80 WRITE   4223141\n0x4020AA40 WRITE   4223143\n0x401AF700 WRITE   4223176\n0x4020AB80 WRITE   4223647\n0x4020AB40 WRITE   4223649\n0x401C2FC0 WRITE   4223733\n0x4020AE00 WRITE   4224152\n0x4020ADC0 WRITE   4224154\n0x4020AD00 WRITE   4224161\n0x4020ACC0 WRITE   4224163\n0x4020AC80 WRITE   4224173\n0x4020AC40 WRITE   4224175\n0x401AF740 WRITE   4224202\n0x4020AD80 WRITE   4224650\n0x4020AD40 WRITE   4224652\n0x401C3000 WRITE   4224736\n0x4020AF00 WRITE   4225131\n0x4020AEC0 WRITE   4225133\n0x4020AE80 WRITE   4225140\n0x4020AE40 WRITE   4225142\n0x401AF780 WRITE   4225175\n0x4020AF80 WRITE   4225655\n0x4020AF40 WRITE   4225657\n0x401C3040 WRITE   4225741\n0x4020B800 WRITE   4226173\n0x4020B7C0 WRITE   4226175\n0x4020B400 WRITE   4226182\n0x4020B3C0 WRITE   4226184\n0x4020B200 WRITE   4226194\n0x4020B1C0 WRITE   4226196\n0x4020B100 WRITE   4226201\n0x4020B0C0 WRITE   4226204\n0x4020B080 WRITE   4226207\n0x4020B040 WRITE   4226210\n0x401AF7C0 WRITE   4226235\n0x4020B180 WRITE   4226666\n0x4020B140 WRITE   4226668\n0x401C3080 WRITE   4226752\n0x4020B300 WRITE   4227136\n0x4020B2C0 WRITE   4227138\n0x4020B280 WRITE   4227145\n0x4020B240 WRITE   4227147\n0x401AF800 WRITE   4227180\n0x4020B380 WRITE   4227643\n0x4020B340 WRITE   4227645\n0x401C30C0 WRITE   4227729\n0x4020B600 WRITE   4228146\n0x4020B5C0 WRITE   4228148\n0x4020B500 WRITE   4228155\n0x4020B4C0 WRITE   4228157\n0x4020B480 WRITE   4228167\n0x4020B440 WRITE   4228169\n0x401AF840 WRITE   4228196\n0x4020B580 WRITE   4228637\n0x4020B540 WRITE   4228639\n0x401C3100 WRITE   4228723\n0x4020B700 WRITE   4229117\n0x4020B6C0 WRITE   4229119\n0x4020B680 WRITE   4229126\n0x4020B640 WRITE   4229128\n0x401AF880 WRITE   4229161\n0x4020B780 WRITE   4229634\n0x4020B740 WRITE   4229636\n0x401C3140 WRITE   4229720\n0x4020BC00 WRITE   4230152\n0x4020BBC0 WRITE   4230154\n0x4020BA00 WRITE   4230161\n0x4020B9C0 WRITE   4230163\n0x4020B900 WRITE   4230173\n0x4020B8C0 WRITE   4230175\n0x4020B880 WRITE   4230180\n0x4020B840 WRITE   4230183\n0x401AF8C0 WRITE   4230208\n0x4020B980 WRITE   4230647\n0x4020B940 WRITE   4230649\n0x401C3180 WRITE   4230733\n0x4020BB00 WRITE   4231125\n0x4020BAC0 WRITE   4231127\n0x4020BA80 WRITE   4231134\n0x4020BA40 WRITE   4231136\n0x401AF900 WRITE   4231169\n0x4020BB80 WRITE   4231640\n0x4020BB40 WRITE   4231642\n0x401C31C0 WRITE   4231726\n0x4020BE00 WRITE   4232151\n0x4020BDC0 WRITE   4232153\n0x4020BD00 WRITE   4232160\n0x4020BCC0 WRITE   4232162\n0x4020BC80 WRITE   4232172\n0x4020BC40 WRITE   4232174\n0x401AF940 WRITE   4232201\n0x4020BD80 WRITE   4232649\n0x4020BD40 WRITE   4232651\n0x401C3200 WRITE   4232735\n0x4020BF00 WRITE   4233136\n0x4020BEC0 WRITE   4233138\n0x4020BE80 WRITE   4233145\n0x4020BE40 WRITE   4233147\n0x401AF980 WRITE   4233180\n0x4020BF80 WRITE   4233660\n0x4020BF40 WRITE   4233662\n0x401C3240 WRITE   4233746\n0x4020DFC0 WRITE   4234230\n0x4020E000 WRITE   4234264\n0x4020D000 WRITE   4234376\n0x4020CFC0 WRITE   4234378\n0x4020C800 WRITE   4234385\n0x4020C7C0 WRITE   4234387\n0x4020C400 WRITE   4234397\n0x4020C3C0 WRITE   4234399\n0x4020C200 WRITE   4234404\n0x4020C1C0 WRITE   4234407\n0x4020C100 WRITE   4234410\n0x4020C0C0 WRITE   4234413\n0x4020C080 WRITE   4234416\n0x4020C040 WRITE   4234419\n0x401AF9C0 WRITE   4234452\n0x4020C180 WRITE   4234882\n0x4020C140 WRITE   4234884\n0x401C3280 WRITE   4234968\n0x4020C300 WRITE   4235347\n0x4020C2C0 WRITE   4235349\n0x4020C280 WRITE   4235356\n0x4020C240 WRITE   4235358\n0x401AFA00 WRITE   4235391\n0x4020C380 WRITE   4235854\n0x4020C340 WRITE   4235856\n0x401C32C0 WRITE   4235940\n0x4020C600 WRITE   4236351\n0x4020C5C0 WRITE   4236353\n0x4020C500 WRITE   4236360\n0x4020C4C0 WRITE   4236362\n0x4020C480 WRITE   4236372\n0x4020C440 WRITE   4236374\n0x401AFA40 WRITE   4236401\n0x4020C580 WRITE   4236842\n0x4020C540 WRITE   4236844\n0x401C3300 WRITE   4236928\n0x4020C700 WRITE   4237316\n0x4020C6C0 WRITE   4237318\n0x4020C680 WRITE   4237325\n0x4020C640 WRITE   4237327\n0x401AFA80 WRITE   4237360\n0x4020C780 WRITE   4237833\n0x4020C740 WRITE   4237835\n0x401C3340 WRITE   4237919\n0x4020CC00 WRITE   4238345\n0x4020CBC0 WRITE   4238347\n0x4020CA00 WRITE   4238354\n0x4020C9C0 WRITE   4238356\n0x4020C900 WRITE   4238366\n0x4020C8C0 WRITE   4238368\n0x4020C880 WRITE   4238373\n0x4020C840 WRITE   4238376\n0x401AFAC0 WRITE   4238401\n0x4020C980 WRITE   4238840\n0x4020C940 WRITE   4238842\n0x401C3380 WRITE   4238926\n0x4020CB00 WRITE   4239312\n0x4020CAC0 WRITE   4239314\n0x4020CA80 WRITE   4239321\n0x4020CA40 WRITE   4239323\n0x401AFB00 WRITE   4239356\n0x4020CB80 WRITE   4239827\n0x4020CB40 WRITE   4239829\n0x401C33C0 WRITE   4239913\n0x4020CE00 WRITE   4240332\n0x4020CDC0 WRITE   4240334\n0x4020CD00 WRITE   4240341\n0x4020CCC0 WRITE   4240343\n0x4020CC80 WRITE   4240353\n0x4020CC40 WRITE   4240355\n0x401AFB40 WRITE   4240382\n0x4020CD80 WRITE   4240830\n0x4020CD40 WRITE   4240832\n0x401C3400 WRITE   4240916\n0x4020CF00 WRITE   4241311\n0x4020CEC0 WRITE   4241313\n0x4020CE80 WRITE   4241320\n0x4020CE40 WRITE   4241322\n0x401AFB80 WRITE   4241355\n0x4020CF80 WRITE   4241835\n0x4020CF40 WRITE   4241837\n0x401C3440 WRITE   4241921\n0x4020D800 WRITE   4242353\n0x4020D7C0 WRITE   4242355\n0x4020D400 WRITE   4242362\n0x4020D3C0 WRITE   4242364\n0x4020D200 WRITE   4242374\n0x4020D1C0 WRITE   4242376\n0x4020D100 WRITE   4242381\n0x4020D0C0 WRITE   4242384\n0x4020D080 WRITE   4242387\n0x4020D040 WRITE   4242390\n0x401AFBC0 WRITE   4242415\n0x4020D180 WRITE   4242846\n0x4020D140 WRITE   4242848\n0x401C3480 WRITE   4242932\n0x4020D300 WRITE   4243316\n0x4020D2C0 WRITE   4243318\n0x4020D280 WRITE   4243325\n0x4020D240 WRITE   4243327\n0x401AFC00 WRITE   4243360\n0x4020D380 WRITE   4243823\n0x4020D340 WRITE   4243825\n0x401C34C0 WRITE   4243909\n0x4020D600 WRITE   4244326\n0x4020D5C0 WRITE   4244328\n0x4020D500 WRITE   4244335\n0x4020D4C0 WRITE   4244337\n0x4020D480 WRITE   4244347\n0x4020D440 WRITE   4244349\n0x401AFC40 WRITE   4244376\n0x4020D580 WRITE   4244817\n0x4020D540 WRITE   4244819\n0x401C3500 WRITE   4244903\n0x4020D700 WRITE   4245297\n0x4020D6C0 WRITE   4245299\n0x4020D680 WRITE   4245306\n0x4020D640 WRITE   4245308\n0x401AFC80 WRITE   4245341\n0x4020D780 WRITE   4245814\n0x4020D740 WRITE   4245816\n0x401C3540 WRITE   4245900\n0x4020DC00 WRITE   4246332\n0x4020DBC0 WRITE   4246334\n0x4020DA00 WRITE   4246341\n0x4020D9C0 WRITE   4246343\n0x4020D900 WRITE   4246353\n0x4020D8C0 WRITE   4246355\n0x4020D880 WRITE   4246360\n0x4020D840 WRITE   4246363\n0x401AFCC0 WRITE   4246388\n0x4020D980 WRITE   4246827\n0x4020D940 WRITE   4246829\n0x401C3580 WRITE   4246913\n0x4020DB00 WRITE   4247305\n0x4020DAC0 WRITE   4247307\n0x4020DA80 WRITE   4247314\n0x4020DA40 WRITE   4247316\n0x401AFD00 WRITE   4247349\n0x4020DB80 WRITE   4247820\n0x4020DB40 WRITE   4247822\n0x401C35C0 WRITE   4247906\n0x4020DE00 WRITE   4248331\n0x4020DDC0 WRITE   4248333\n0x4020DD00 WRITE   4248340\n0x4020DCC0 WRITE   4248342\n0x4020DC80 WRITE   4248352\n0x4020DC40 WRITE   4248354\n0x401AFD40 WRITE   4248381\n0x4020DD80 WRITE   4248829\n0x4020DD40 WRITE   4248831\n0x401C3600 WRITE   4248915\n0x4020DF00 WRITE   4249316\n0x4020DEC0 WRITE   4249318\n0x4020DE80 WRITE   4249325\n0x4020DE40 WRITE   4249327\n0x401AFD80 WRITE   4249360\n0x4020DF80 WRITE   4249840\n0x4020DF40 WRITE   4249842\n0x401C3640 WRITE   4249926\n0x4020FFC0 WRITE   4250410\n0x40210000 WRITE   4250444\n0x4020F000 WRITE   4250572\n0x4020EFC0 WRITE   4250574\n0x4020E800 WRITE   4250581\n0x4020E7C0 WRITE   4250583\n0x4020E400 WRITE   4250593\n0x4020E3C0 WRITE   4250595\n0x4020E200 WRITE   4250600\n0x4020E1C0 WRITE   4250603\n0x4020E100 WRITE   4250606\n0x4020E0C0 WRITE   4250609\n0x4020E080 WRITE   4250612\n0x4020E040 WRITE   4250615\n0x401AFDC0 WRITE   4250648\n0x4020E180 WRITE   4251078\n0x4020E140 WRITE   4251080\n0x401C3680 WRITE   4251164\n0x4020E300 WRITE   4251543\n0x4020E2C0 WRITE   4251545\n0x4020E280 WRITE   4251552\n0x4020E240 WRITE   4251554\n0x401AFE00 WRITE   4251587\n0x4020E380 WRITE   4252050\n0x4020E340 WRITE   4252052\n0x401C36C0 WRITE   4252136\n0x4020E600 WRITE   4252547\n0x4020E5C0 WRITE   4252549\n0x4020E500 WRITE   4252556\n0x4020E4C0 WRITE   4252558\n0x4020E480 WRITE   4252568\n0x4020E440 WRITE   4252570\n0x401AFE40 WRITE   4252597\n0x4020E580 WRITE   4253038\n0x4020E540 WRITE   4253040\n0x401C3700 WRITE   4253124\n0x4020E700 WRITE   4253512\n0x4020E6C0 WRITE   4253514\n0x4020E680 WRITE   4253521\n0x4020E640 WRITE   4253523\n0x401AFE80 WRITE   4253556\n0x4020E780 WRITE   4254029\n0x4020E740 WRITE   4254031\n0x401C3740 WRITE   4254115\n0x4020EC00 WRITE   4254541\n0x4020EBC0 WRITE   4254543\n0x4020EA00 WRITE   4254550\n0x4020E9C0 WRITE   4254552\n0x4020E900 WRITE   4254562\n0x4020E8C0 WRITE   4254564\n0x4020E880 WRITE   4254569\n0x4020E840 WRITE   4254572\n0x401AFEC0 WRITE   4254597\n0x4020E980 WRITE   4255036\n0x4020E940 WRITE   4255038\n0x401C3780 WRITE   4255122\n0x4020EB00 WRITE   4255508\n0x4020EAC0 WRITE   4255510\n0x4020EA80 WRITE   4255517\n0x4020EA40 WRITE   4255519\n0x401AFF00 WRITE   4255552\n0x4020EB80 WRITE   4256023\n0x4020EB40 WRITE   4256025\n0x401C37C0 WRITE   4256109\n0x4020EE00 WRITE   4256528\n0x4020EDC0 WRITE   4256530\n0x4020ED00 WRITE   4256537\n0x4020ECC0 WRITE   4256539\n0x4020EC80 WRITE   4256549\n0x4020EC40 WRITE   4256551\n0x401AFF40 WRITE   4256578\n0x4020ED80 WRITE   4257026\n0x4020ED40 WRITE   4257028\n0x401C3800 WRITE   4257112\n0x4020EF00 WRITE   4257507\n0x4020EEC0 WRITE   4257509\n0x4020EE80 WRITE   4257516\n0x4020EE40 WRITE   4257518\n0x401AFF80 WRITE   4257551\n0x4020EF80 WRITE   4258031\n0x4020EF40 WRITE   4258033\n0x401C3840 WRITE   4258117\n0x4020F800 WRITE   4258549\n0x4020F7C0 WRITE   4258551\n0x4020F400 WRITE   4258558\n0x4020F3C0 WRITE   4258560\n0x4020F200 WRITE   4258570\n0x4020F1C0 WRITE   4258572\n0x4020F100 WRITE   4258577\n0x4020F0C0 WRITE   4258580\n0x4020F080 WRITE   4258583\n0x4020F040 WRITE   4258586\n0x401AFFC0 WRITE   4258611\n0x4020F180 WRITE   4259042\n0x4020F140 WRITE   4259044\n0x401C3880 WRITE   4259128\n0x4020F300 WRITE   4259512\n0x4020F2C0 WRITE   4259514\n0x4020F280 WRITE   4259521\n0x4020F240 WRITE   4259523\n0x401B0000 WRITE   4259556\n0x4020F380 WRITE   4260019\n0x4020F340 WRITE   4260021\n0x401C38C0 WRITE   4260105\n0x4020F600 WRITE   4260522\n0x4020F5C0 WRITE   4260524\n0x4020F500 WRITE   4260531\n0x4020F4C0 WRITE   4260533\n0x4020F480 WRITE   4260543\n0x4020F440 WRITE   4260545\n0x401B0040 WRITE   4260572\n0x4020F580 WRITE   4261013\n0x4020F540 WRITE   4261015\n0x401C3900 WRITE   4261099\n0x4020F700 WRITE   4261493\n0x4020F6C0 WRITE   4261495\n0x4020F680 WRITE   4261502\n0x4020F640 WRITE   4261504\n0x401B0080 WRITE   4261537\n0x4020F780 WRITE   4262010\n0x4020F740 WRITE   4262012\n0x401C3940 WRITE   4262096\n0x4020FC00 WRITE   4262528\n0x4020FBC0 WRITE   4262530\n0x4020FA00 WRITE   4262537\n0x4020F9C0 WRITE   4262539\n0x4020F900 WRITE   4262549\n0x4020F8C0 WRITE   4262551\n0x4020F880 WRITE   4262556\n0x4020F840 WRITE   4262559\n0x401B00C0 WRITE   4262584\n0x4020F980 WRITE   4263023\n0x4020F940 WRITE   4263025\n0x401C3980 WRITE   4263109\n0x4020FB00 WRITE   4263501\n0x4020FAC0 WRITE   4263503\n0x4020FA80 WRITE   4263510\n0x4020FA40 WRITE   4263512\n0x401B0100 WRITE   4263545\n0x4020FB80 WRITE   4264016\n0x4020FB40 WRITE   4264018\n0x401C39C0 WRITE   4264102\n0x4020FE00 WRITE   4264527\n0x4020FDC0 WRITE   4264529\n0x4020FD00 WRITE   4264536\n0x4020FCC0 WRITE   4264538\n0x4020FC80 WRITE   4264548\n0x4020FC40 WRITE   4264550\n0x401B0140 WRITE   4264577\n0x4020FD80 WRITE   4265025\n0x4020FD40 WRITE   4265027\n0x401C3A00 WRITE   4265111\n0x4020FF00 WRITE   4265512\n0x4020FEC0 WRITE   4265514\n0x4020FE80 WRITE   4265521\n0x4020FE40 WRITE   4265523\n0x401B0180 WRITE   4265556\n0x4020FF80 WRITE   4266036\n0x4020FF40 WRITE   4266038\n0x401C3A40 WRITE   4266122\n0x40211FC0 WRITE   4266606\n0x40212000 WRITE   4266640\n0x40211000 WRITE   4266752\n0x40210FC0 WRITE   4266754\n0x40210800 WRITE   4266761\n0x402107C0 WRITE   4266763\n0x40210400 WRITE   4266773\n0x402103C0 WRITE   4266775\n0x40210200 WRITE   4266780\n0x402101C0 WRITE   4266783\n0x40210100 WRITE   4266786\n0x402100C0 WRITE   4266789\n0x40210080 WRITE   4266792\n0x40210040 WRITE   4266795\n0x401B01C0 WRITE   4266828\n0x40210180 WRITE   4267258\n0x40210140 WRITE   4267260\n0x401C3A80 WRITE   4267344\n0x40210300 WRITE   4267723\n0x402102C0 WRITE   4267725\n0x40210280 WRITE   4267732\n0x40210240 WRITE   4267734\n0x401B0200 WRITE   4267767\n0x40210380 WRITE   4268230\n0x40210340 WRITE   4268232\n0x401C3AC0 WRITE   4268316\n0x40210600 WRITE   4268727\n0x402105C0 WRITE   4268729\n0x40210500 WRITE   4268736\n0x402104C0 WRITE   4268738\n0x40210480 WRITE   4268748\n0x40210440 WRITE   4268750\n0x401B0240 WRITE   4268777\n0x40210580 WRITE   4269218\n0x40210540 WRITE   4269220\n0x401C3B00 WRITE   4269304\n0x40210700 WRITE   4269692\n0x402106C0 WRITE   4269694\n0x40210680 WRITE   4269701\n0x40210640 WRITE   4269703\n0x401B0280 WRITE   4269736\n0x40210780 WRITE   4270209\n0x40210740 WRITE   4270211\n0x401C3B40 WRITE   4270295\n0x40210C00 WRITE   4270721\n0x40210BC0 WRITE   4270723\n0x40210A00 WRITE   4270730\n0x402109C0 WRITE   4270732\n0x40210900 WRITE   4270742\n0x402108C0 WRITE   4270744\n0x40210880 WRITE   4270749\n0x40210840 WRITE   4270752\n0x401B02C0 WRITE   4270777\n0x40210980 WRITE   4271216\n0x40210940 WRITE   4271218\n0x401C3B80 WRITE   4271302\n0x40210B00 WRITE   4271688\n0x40210AC0 WRITE   4271690\n0x40210A80 WRITE   4271697\n0x40210A40 WRITE   4271699\n0x401B0300 WRITE   4271732\n0x40210B80 WRITE   4272203\n0x40210B40 WRITE   4272205\n0x401C3BC0 WRITE   4272289\n0x40210E00 WRITE   4272708\n0x40210DC0 WRITE   4272710\n0x40210D00 WRITE   4272717\n0x40210CC0 WRITE   4272719\n0x40210C80 WRITE   4272729\n0x40210C40 WRITE   4272731\n0x401B0340 WRITE   4272758\n0x40210D80 WRITE   4273206\n0x40210D40 WRITE   4273208\n0x401C3C00 WRITE   4273292\n0x40210F00 WRITE   4273687\n0x40210EC0 WRITE   4273689\n0x40210E80 WRITE   4273696\n0x40210E40 WRITE   4273698\n0x401B0380 WRITE   4273731\n0x40210F80 WRITE   4274211\n0x40210F40 WRITE   4274213\n0x401C3C40 WRITE   4274297\n0x40211800 WRITE   4274729\n0x402117C0 WRITE   4274731\n0x40211400 WRITE   4274738\n0x402113C0 WRITE   4274740\n0x40211200 WRITE   4274750\n0x402111C0 WRITE   4274752\n0x40211100 WRITE   4274757\n0x402110C0 WRITE   4274760\n0x40211080 WRITE   4274763\n0x40211040 WRITE   4274766\n0x401B03C0 WRITE   4274791\n0x40211180 WRITE   4275222\n0x40211140 WRITE   4275224\n0x401C3C80 WRITE   4275308\n0x40211300 WRITE   4275692\n0x402112C0 WRITE   4275694\n0x40211280 WRITE   4275701\n0x40211240 WRITE   4275703\n0x401B0400 WRITE   4275736\n0x40211380 WRITE   4276199\n0x40211340 WRITE   4276201\n0x401C3CC0 WRITE   4276285\n0x40211600 WRITE   4276702\n0x402115C0 WRITE   4276704\n0x40211500 WRITE   4276711\n0x402114C0 WRITE   4276713\n0x40211480 WRITE   4276723\n0x40211440 WRITE   4276725\n0x401B0440 WRITE   4276752\n0x40211580 WRITE   4277193\n0x40211540 WRITE   4277195\n0x401C3D00 WRITE   4277279\n0x40211700 WRITE   4277673\n0x402116C0 WRITE   4277675\n0x40211680 WRITE   4277682\n0x40211640 WRITE   4277684\n0x401B0480 WRITE   4277717\n0x40211780 WRITE   4278190\n0x40211740 WRITE   4278192\n0x401C3D40 WRITE   4278276\n0x40211C00 WRITE   4278708\n0x40211BC0 WRITE   4278710\n0x40211A00 WRITE   4278717\n0x402119C0 WRITE   4278719\n0x40211900 WRITE   4278729\n0x402118C0 WRITE   4278731\n0x40211880 WRITE   4278736\n0x40211840 WRITE   4278739\n0x401B04C0 WRITE   4278764\n0x40211980 WRITE   4279203\n0x40211940 WRITE   4279205\n0x401C3D80 WRITE   4279289\n0x40211B00 WRITE   4279681\n0x40211AC0 WRITE   4279683\n0x40211A80 WRITE   4279690\n0x40211A40 WRITE   4279692\n0x401B0500 WRITE   4279725\n0x40211B80 WRITE   4280196\n0x40211B40 WRITE   4280198\n0x401C3DC0 WRITE   4280282\n0x40211E00 WRITE   4280707\n0x40211DC0 WRITE   4280709\n0x40211D00 WRITE   4280716\n0x40211CC0 WRITE   4280718\n0x40211C80 WRITE   4280728\n0x40211C40 WRITE   4280730\n0x401B0540 WRITE   4280757\n0x40211D80 WRITE   4281205\n0x40211D40 WRITE   4281207\n0x401C3E00 WRITE   4281291\n0x40211F00 WRITE   4281692\n0x40211EC0 WRITE   4281694\n0x40211E80 WRITE   4281701\n0x40211E40 WRITE   4281703\n0x401B0580 WRITE   4281736\n0x40211F80 WRITE   4282216\n0x40211F40 WRITE   4282218\n0x401C3E40 WRITE   4282302\n0x40213FC0 WRITE   4282786\n0x40214000 WRITE   4282820\n0x40213000 WRITE   4282932\n0x40212FC0 WRITE   4282934\n0x40212800 WRITE   4282941\n0x402127C0 WRITE   4282943\n0x40212400 WRITE   4282953\n0x402123C0 WRITE   4282955\n0x40212200 WRITE   4282960\n0x402121C0 WRITE   4282963\n0x40212100 WRITE   4282966\n0x402120C0 WRITE   4282969\n0x40212080 WRITE   4282972\n0x40212040 WRITE   4282975\n0x401B05C0 WRITE   4283008\n0x40212180 WRITE   4283438\n0x40212140 WRITE   4283440\n0x401C3E80 WRITE   4283524\n0x40212300 WRITE   4283903\n0x402122C0 WRITE   4283905\n0x40212280 WRITE   4283912\n0x40212240 WRITE   4283914\n0x401B0600 WRITE   4283947\n0x40212380 WRITE   4284410\n0x40212340 WRITE   4284412\n0x401C3EC0 WRITE   4284496\n0x40212600 WRITE   4284907\n0x402125C0 WRITE   4284909\n0x40212500 WRITE   4284916\n0x402124C0 WRITE   4284918\n0x40212480 WRITE   4284928\n0x40212440 WRITE   4284930\n0x401B0640 WRITE   4284957\n0x40212580 WRITE   4285398\n0x40212540 WRITE   4285400\n0x401C3F00 WRITE   4285484\n0x40212700 WRITE   4285872\n0x402126C0 WRITE   4285874\n0x40212680 WRITE   4285881\n0x40212640 WRITE   4285883\n0x401B0680 WRITE   4285916\n0x40212780 WRITE   4286389\n0x40212740 WRITE   4286391\n0x401C3F40 WRITE   4286475\n0x40212C00 WRITE   4286901\n0x40212BC0 WRITE   4286903\n0x40212A00 WRITE   4286910\n0x402129C0 WRITE   4286912\n0x40212900 WRITE   4286922\n0x402128C0 WRITE   4286924\n0x40212880 WRITE   4286929\n0x40212840 WRITE   4286932\n0x401B06C0 WRITE   4286957\n0x40212980 WRITE   4287396\n0x40212940 WRITE   4287398\n0x401C3F80 WRITE   4287482\n0x40212B00 WRITE   4287868\n0x40212AC0 WRITE   4287870\n0x40212A80 WRITE   4287877\n0x40212A40 WRITE   4287879\n0x401B0700 WRITE   4287912\n0x40212B80 WRITE   4288383\n0x40212B40 WRITE   4288385\n0x401C3FC0 WRITE   4288469\n0x40212E00 WRITE   4288888\n0x40212DC0 WRITE   4288890\n0x40212D00 WRITE   4288897\n0x40212CC0 WRITE   4288899\n0x40212C80 WRITE   4288909\n0x40212C40 WRITE   4288911\n0x401B0740 WRITE   4288938\n0x40212D80 WRITE   4289386\n0x40212D40 WRITE   4289388\n0x401C4000 WRITE   4289472\n0x40212F00 WRITE   4289867\n0x40212EC0 WRITE   4289869\n0x40212E80 WRITE   4289876\n0x40212E40 WRITE   4289878\n0x401B0780 WRITE   4289911\n0x40212F80 WRITE   4290391\n0x40212F40 WRITE   4290393\n0x401C4040 WRITE   4290477\n0x40213800 WRITE   4290909\n0x402137C0 WRITE   4290911\n0x40213400 WRITE   4290918\n0x402133C0 WRITE   4290920\n0x40213200 WRITE   4290930\n0x402131C0 WRITE   4290932\n0x40213100 WRITE   4290937\n0x402130C0 WRITE   4290940\n0x40213080 WRITE   4290943\n0x40213040 WRITE   4290946\n0x401B07C0 WRITE   4290971\n0x40213180 WRITE   4291402\n0x40213140 WRITE   4291404\n0x401C4080 WRITE   4291488\n0x40213300 WRITE   4291872\n0x402132C0 WRITE   4291874\n0x40213280 WRITE   4291881\n0x40213240 WRITE   4291883\n0x401B0800 WRITE   4291916\n0x40213380 WRITE   4292379\n0x40213340 WRITE   4292381\n0x401C40C0 WRITE   4292465\n0x40213600 WRITE   4292882\n0x402135C0 WRITE   4292884\n0x40213500 WRITE   4292891\n0x402134C0 WRITE   4292893\n0x40213480 WRITE   4292903\n0x40213440 WRITE   4292905\n0x401B0840 WRITE   4292932\n0x40213580 WRITE   4293373\n0x40213540 WRITE   4293375\n0x401C4100 WRITE   4293459\n0x40213700 WRITE   4293853\n0x402136C0 WRITE   4293855\n0x40213680 WRITE   4293862\n0x40213640 WRITE   4293864\n0x401B0880 WRITE   4293897\n0x40213780 WRITE   4294370\n0x40213740 WRITE   4294372\n0x401C4140 WRITE   4294456\n0x40213C00 WRITE   4294888\n0x40213BC0 WRITE   4294890\n0x40213A00 WRITE   4294897\n0x402139C0 WRITE   4294899\n0x40213900 WRITE   4294909\n0x402138C0 WRITE   4294911\n0x40213880 WRITE   4294916\n0x40213840 WRITE   4294919\n0x401B08C0 WRITE   4294944\n0x40213980 WRITE   4295383\n0x40213940 WRITE   4295385\n0x401C4180 WRITE   4295469\n0x40213B00 WRITE   4295861\n0x40213AC0 WRITE   4295863\n0x40213A80 WRITE   4295870\n0x40213A40 WRITE   4295872\n0x401B0900 WRITE   4295905\n0x40213B80 WRITE   4296376\n0x40213B40 WRITE   4296378\n0x401C41C0 WRITE   4296462\n0x40213E00 WRITE   4296887\n0x40213DC0 WRITE   4296889\n0x40213D00 WRITE   4296896\n0x40213CC0 WRITE   4296898\n0x40213C80 WRITE   4296908\n0x40213C40 WRITE   4296910\n0x401B0940 WRITE   4296937\n0x40213D80 WRITE   4297385\n0x40213D40 WRITE   4297387\n0x401C4200 WRITE   4297471\n0x40213F00 WRITE   4297872\n0x40213EC0 WRITE   4297874\n0x40213E80 WRITE   4297881\n0x40213E40 WRITE   4297883\n0x401B0980 WRITE   4297916\n0x40213F80 WRITE   4298396\n0x40213F40 WRITE   4298398\n0x401C4240 WRITE   4298482\n0x40215FC0 WRITE   4298966\n0x40216000 WRITE   4299000\n0x40215000 WRITE   4299112\n0x40214FC0 WRITE   4299114\n0x40214800 WRITE   4299121\n0x402147C0 WRITE   4299123\n0x40214400 WRITE   4299133\n0x402143C0 WRITE   4299135\n0x40214200 WRITE   4299140\n0x402141C0 WRITE   4299143\n0x40214100 WRITE   4299146\n0x402140C0 WRITE   4299149\n0x40214080 WRITE   4299152\n0x40214040 WRITE   4299155\n0x401B09C0 WRITE   4299188\n0x40214180 WRITE   4299618\n0x40214140 WRITE   4299620\n0x401C4280 WRITE   4299704\n0x40214300 WRITE   4300083\n0x402142C0 WRITE   4300085\n0x40214280 WRITE   4300092\n0x40214240 WRITE   4300094\n0x401B0A00 WRITE   4300127\n0x40214380 WRITE   4300590\n0x40214340 WRITE   4300592\n0x401C42C0 WRITE   4300676\n0x40214600 WRITE   4301087\n0x402145C0 WRITE   4301089\n0x40214500 WRITE   4301096\n0x402144C0 WRITE   4301098\n0x40214480 WRITE   4301108\n0x40214440 WRITE   4301110\n0x401B0A40 WRITE   4301137\n0x40214580 WRITE   4301578\n0x40214540 WRITE   4301580\n0x401C4300 WRITE   4301664\n0x40214700 WRITE   4302052\n0x402146C0 WRITE   4302054\n0x40214680 WRITE   4302061\n0x40214640 WRITE   4302063\n0x401B0A80 WRITE   4302096\n0x40214780 WRITE   4302569\n0x40214740 WRITE   4302571\n0x401C4340 WRITE   4302655\n0x40214C00 WRITE   4303081\n0x40214BC0 WRITE   4303083\n0x40214A00 WRITE   4303090\n0x402149C0 WRITE   4303092\n0x40214900 WRITE   4303102\n0x402148C0 WRITE   4303104\n0x40214880 WRITE   4303109\n0x40214840 WRITE   4303112\n0x401B0AC0 WRITE   4303137\n0x40214980 WRITE   4303576\n0x40214940 WRITE   4303578\n0x401C4380 WRITE   4303662\n0x40214B00 WRITE   4304048\n0x40214AC0 WRITE   4304050\n0x40214A80 WRITE   4304057\n0x40214A40 WRITE   4304059\n0x401B0B00 WRITE   4304092\n0x40214B80 WRITE   4304563\n0x40214B40 WRITE   4304565\n0x401C43C0 WRITE   4304649\n0x40214E00 WRITE   4305068\n0x40214DC0 WRITE   4305070\n0x40214D00 WRITE   4305077\n0x40214CC0 WRITE   4305079\n0x40214C80 WRITE   4305089\n0x40214C40 WRITE   4305091\n0x401B0B40 WRITE   4305118\n0x40214D80 WRITE   4305566\n0x40214D40 WRITE   4305568\n0x401C4400 WRITE   4305652\n0x40214F00 WRITE   4306047\n0x40214EC0 WRITE   4306049\n0x40214E80 WRITE   4306056\n0x40214E40 WRITE   4306058\n0x401B0B80 WRITE   4306091\n0x40214F80 WRITE   4306571\n0x40214F40 WRITE   4306573\n0x401C4440 WRITE   4306657\n0x40215800 WRITE   4307089\n0x402157C0 WRITE   4307091\n0x40215400 WRITE   4307098\n0x402153C0 WRITE   4307100\n0x40215200 WRITE   4307110\n0x402151C0 WRITE   4307112\n0x40215100 WRITE   4307117\n0x402150C0 WRITE   4307120\n0x40215080 WRITE   4307123\n0x40215040 WRITE   4307126\n0x401B0BC0 WRITE   4307151\n0x40215180 WRITE   4307582\n0x40215140 WRITE   4307584\n0x401C4480 WRITE   4307668\n0x40215300 WRITE   4308052\n0x402152C0 WRITE   4308054\n0x40215280 WRITE   4308061\n0x40215240 WRITE   4308063\n0x401B0C00 WRITE   4308096\n0x40215380 WRITE   4308559\n0x40215340 WRITE   4308561\n0x401C44C0 WRITE   4308645\n0x40215600 WRITE   4309062\n0x402155C0 WRITE   4309064\n0x40215500 WRITE   4309071\n0x402154C0 WRITE   4309073\n0x40215480 WRITE   4309083\n0x40215440 WRITE   4309085\n0x401B0C40 WRITE   4309112\n0x40215580 WRITE   4309553\n0x40215540 WRITE   4309555\n0x401C4500 WRITE   4309639\n0x40215700 WRITE   4310033\n0x402156C0 WRITE   4310035\n0x40215680 WRITE   4310042\n0x40215640 WRITE   4310044\n0x401B0C80 WRITE   4310077\n0x40215780 WRITE   4310550\n0x40215740 WRITE   4310552\n0x401C4540 WRITE   4310636\n0x40215C00 WRITE   4311068\n0x40215BC0 WRITE   4311070\n0x40215A00 WRITE   4311077\n0x402159C0 WRITE   4311079\n0x40215900 WRITE   4311089\n0x402158C0 WRITE   4311091\n0x40215880 WRITE   4311096\n0x40215840 WRITE   4311099\n0x401B0CC0 WRITE   4311124\n0x40215980 WRITE   4311563\n0x40215940 WRITE   4311565\n0x401C4580 WRITE   4311649\n0x40215B00 WRITE   4312041\n0x40215AC0 WRITE   4312043\n0x40215A80 WRITE   4312050\n0x40215A40 WRITE   4312052\n0x401B0D00 WRITE   4312085\n0x40215B80 WRITE   4312556\n0x40215B40 WRITE   4312558\n0x401C45C0 WRITE   4312642\n0x40215E00 WRITE   4313067\n0x40215DC0 WRITE   4313069\n0x40215D00 WRITE   4313076\n0x40215CC0 WRITE   4313078\n0x40215C80 WRITE   4313088\n0x40215C40 WRITE   4313090\n0x401B0D40 WRITE   4313117\n0x40215D80 WRITE   4313565\n0x40215D40 WRITE   4313567\n0x401C4600 WRITE   4313651\n0x40215F00 WRITE   4314052\n0x40215EC0 WRITE   4314054\n0x40215E80 WRITE   4314061\n0x40215E40 WRITE   4314063\n0x401B0D80 WRITE   4314096\n0x40215F80 WRITE   4314576\n0x40215F40 WRITE   4314578\n0x401C4640 WRITE   4314662\n0x40217FC0 WRITE   4315146\n0x40218000 WRITE   4315180\n0x40217000 WRITE   4315292\n0x40216FC0 WRITE   4315294\n0x40216800 WRITE   4315301\n0x402167C0 WRITE   4315303\n0x40216400 WRITE   4315313\n0x402163C0 WRITE   4315315\n0x40216200 WRITE   4315320\n0x402161C0 WRITE   4315323\n0x40216100 WRITE   4315326\n0x402160C0 WRITE   4315329\n0x40216080 WRITE   4315332\n0x40216040 WRITE   4315335\n0x401B0DC0 WRITE   4315368\n0x40216180 WRITE   4315798\n0x40216140 WRITE   4315800\n0x401C4680 WRITE   4315884\n0x40216300 WRITE   4316263\n0x402162C0 WRITE   4316265\n0x40216280 WRITE   4316272\n0x40216240 WRITE   4316274\n0x401B0E00 WRITE   4316307\n0x40216380 WRITE   4316770\n0x40216340 WRITE   4316772\n0x401C46C0 WRITE   4316856\n0x40216600 WRITE   4317267\n0x402165C0 WRITE   4317269\n0x40216500 WRITE   4317276\n0x402164C0 WRITE   4317278\n0x40216480 WRITE   4317288\n0x40216440 WRITE   4317290\n0x401B0E40 WRITE   4317317\n0x40216580 WRITE   4317758\n0x40216540 WRITE   4317760\n0x401C4700 WRITE   4317844\n0x40216700 WRITE   4318232\n0x402166C0 WRITE   4318234\n0x40216680 WRITE   4318241\n0x40216640 WRITE   4318243\n0x401B0E80 WRITE   4318276\n0x40216780 WRITE   4318749\n0x40216740 WRITE   4318751\n0x401C4740 WRITE   4318835\n0x40216C00 WRITE   4319261\n0x40216BC0 WRITE   4319263\n0x40216A00 WRITE   4319270\n0x402169C0 WRITE   4319272\n0x40216900 WRITE   4319282\n0x402168C0 WRITE   4319284\n0x40216880 WRITE   4319289\n0x40216840 WRITE   4319292\n0x401B0EC0 WRITE   4319317\n0x40216980 WRITE   4319756\n0x40216940 WRITE   4319758\n0x401C4780 WRITE   4319842\n0x40216B00 WRITE   4320228\n0x40216AC0 WRITE   4320230\n0x40216A80 WRITE   4320237\n0x40216A40 WRITE   4320239\n0x401B0F00 WRITE   4320272\n0x40216B80 WRITE   4320743\n0x40216B40 WRITE   4320745\n0x401C47C0 WRITE   4320829\n0x40216E00 WRITE   4321248\n0x40216DC0 WRITE   4321250\n0x40216D00 WRITE   4321257\n0x40216CC0 WRITE   4321259\n0x40216C80 WRITE   4321269\n0x40216C40 WRITE   4321271\n0x401B0F40 WRITE   4321298\n0x40216D80 WRITE   4321746\n0x40216D40 WRITE   4321748\n0x401C4800 WRITE   4321832\n0x40216F00 WRITE   4322227\n0x40216EC0 WRITE   4322229\n0x40216E80 WRITE   4322236\n0x40216E40 WRITE   4322238\n0x401B0F80 WRITE   4322271\n0x40216F80 WRITE   4322751\n0x40216F40 WRITE   4322753\n0x401C4840 WRITE   4322837\n0x40217800 WRITE   4323269\n0x402177C0 WRITE   4323271\n0x40217400 WRITE   4323278\n0x402173C0 WRITE   4323280\n0x40217200 WRITE   4323290\n0x402171C0 WRITE   4323292\n0x40217100 WRITE   4323297\n0x402170C0 WRITE   4323300\n0x40217080 WRITE   4323303\n0x40217040 WRITE   4323306\n0x401B0FC0 WRITE   4323331\n0x40217180 WRITE   4323762\n0x40217140 WRITE   4323764\n0x401C4880 WRITE   4323848\n0x40217300 WRITE   4324232\n0x402172C0 WRITE   4324234\n0x40217280 WRITE   4324241\n0x40217240 WRITE   4324243\n0x401B1000 WRITE   4324276\n0x40217380 WRITE   4324739\n0x40217340 WRITE   4324741\n0x401C48C0 WRITE   4324825\n0x40217600 WRITE   4325242\n0x402175C0 WRITE   4325244\n0x40217500 WRITE   4325251\n0x402174C0 WRITE   4325253\n0x40217480 WRITE   4325263\n0x40217440 WRITE   4325265\n0x401B1040 WRITE   4325292\n0x40217580 WRITE   4325733\n0x40217540 WRITE   4325735\n0x401C4900 WRITE   4325819\n0x40217700 WRITE   4326213\n0x402176C0 WRITE   4326215\n0x40217680 WRITE   4326222\n0x40217640 WRITE   4326224\n0x401B1080 WRITE   4326257\n0x40217780 WRITE   4326730\n0x40217740 WRITE   4326732\n0x401C4940 WRITE   4326816\n0x40217C00 WRITE   4327248\n0x40217BC0 WRITE   4327250\n0x40217A00 WRITE   4327257\n0x402179C0 WRITE   4327259\n0x40217900 WRITE   4327269\n0x402178C0 WRITE   4327271\n0x40217880 WRITE   4327276\n0x40217840 WRITE   4327279\n0x401B10C0 WRITE   4327304\n0x40217980 WRITE   4327743\n0x40217940 WRITE   4327745\n0x401C4980 WRITE   4327829\n0x40217B00 WRITE   4328221\n0x40217AC0 WRITE   4328223\n0x40217A80 WRITE   4328230\n0x40217A40 WRITE   4328232\n0x401B1100 WRITE   4328265\n0x40217B80 WRITE   4328736\n0x40217B40 WRITE   4328738\n0x401C49C0 WRITE   4328822\n0x40217E00 WRITE   4329247\n0x40217DC0 WRITE   4329249\n0x40217D00 WRITE   4329256\n0x40217CC0 WRITE   4329258\n0x40217C80 WRITE   4329268\n0x40217C40 WRITE   4329270\n0x401B1140 WRITE   4329297\n0x40217D80 WRITE   4329745\n0x40217D40 WRITE   4329747\n0x401C4A00 WRITE   4329831\n0x40217F00 WRITE   4330232\n0x40217EC0 WRITE   4330234\n0x40217E80 WRITE   4330241\n0x40217E40 WRITE   4330243\n0x401B1180 WRITE   4330276\n0x40217F80 WRITE   4330756\n0x40217F40 WRITE   4330758\n0x401C4A40 WRITE   4330842\n0x40219FC0 WRITE   4331326\n0x4021A000 WRITE   4331360\n0x40219000 WRITE   4331472\n0x40218FC0 WRITE   4331474\n0x40218800 WRITE   4331481\n0x402187C0 WRITE   4331483\n0x40218400 WRITE   4331493\n0x402183C0 WRITE   4331495\n0x40218200 WRITE   4331500\n0x402181C0 WRITE   4331503\n0x40218100 WRITE   4331506\n0x402180C0 WRITE   4331509\n0x40218080 WRITE   4331512\n0x40218040 WRITE   4331515\n0x401B11C0 WRITE   4331548\n0x40218180 WRITE   4331978\n0x40218140 WRITE   4331980\n0x401C4A80 WRITE   4332064\n0x40218300 WRITE   4332443\n0x402182C0 WRITE   4332445\n0x40218280 WRITE   4332452\n0x40218240 WRITE   4332454\n0x401B1200 WRITE   4332487\n0x40218380 WRITE   4332950\n0x40218340 WRITE   4332952\n0x401C4AC0 WRITE   4333036\n0x40218600 WRITE   4333447\n0x402185C0 WRITE   4333449\n0x40218500 WRITE   4333456\n0x402184C0 WRITE   4333458\n0x40218480 WRITE   4333468\n0x40218440 WRITE   4333470\n0x401B1240 WRITE   4333497\n0x40218580 WRITE   4333938\n0x40218540 WRITE   4333940\n0x401C4B00 WRITE   4334024\n0x40218700 WRITE   4334412\n0x402186C0 WRITE   4334414\n0x40218680 WRITE   4334421\n0x40218640 WRITE   4334423\n0x401B1280 WRITE   4334456\n0x40218780 WRITE   4334929\n0x40218740 WRITE   4334931\n0x401C4B40 WRITE   4335015\n0x40218C00 WRITE   4335441\n0x40218BC0 WRITE   4335443\n0x40218A00 WRITE   4335450\n0x402189C0 WRITE   4335452\n0x40218900 WRITE   4335462\n0x402188C0 WRITE   4335464\n0x40218880 WRITE   4335469\n0x40218840 WRITE   4335472\n0x401B12C0 WRITE   4335497\n0x40218980 WRITE   4335936\n0x40218940 WRITE   4335938\n0x401C4B80 WRITE   4336022\n0x40218B00 WRITE   4336408\n0x40218AC0 WRITE   4336410\n0x40218A80 WRITE   4336417\n0x40218A40 WRITE   4336419\n0x401B1300 WRITE   4336452\n0x40218B80 WRITE   4336923\n0x40218B40 WRITE   4336925\n0x401C4BC0 WRITE   4337009\n0x40218E00 WRITE   4337428\n0x40218DC0 WRITE   4337430\n0x40218D00 WRITE   4337437\n0x40218CC0 WRITE   4337439\n0x40218C80 WRITE   4337449\n0x40218C40 WRITE   4337451\n0x401B1340 WRITE   4337478\n0x40218D80 WRITE   4337926\n0x40218D40 WRITE   4337928\n0x401C4C00 WRITE   4338012\n0x40218F00 WRITE   4338407\n0x40218EC0 WRITE   4338409\n0x40218E80 WRITE   4338416\n0x40218E40 WRITE   4338418\n0x401B1380 WRITE   4338451\n0x40218F80 WRITE   4338931\n0x40218F40 WRITE   4338933\n0x401C4C40 WRITE   4339017\n0x40219800 WRITE   4339449\n0x402197C0 WRITE   4339451\n0x40219400 WRITE   4339458\n0x402193C0 WRITE   4339460\n0x40219200 WRITE   4339470\n0x402191C0 WRITE   4339472\n0x40219100 WRITE   4339477\n0x402190C0 WRITE   4339480\n0x40219080 WRITE   4339483\n0x40219040 WRITE   4339486\n0x401B13C0 WRITE   4339511\n0x40219180 WRITE   4339942\n0x40219140 WRITE   4339944\n0x401C4C80 WRITE   4340028\n0x40219300 WRITE   4340412\n0x402192C0 WRITE   4340414\n0x40219280 WRITE   4340421\n0x40219240 WRITE   4340423\n0x401B1400 WRITE   4340456\n0x40219380 WRITE   4340919\n0x40219340 WRITE   4340921\n0x401C4CC0 WRITE   4341005\n0x40219600 WRITE   4341422\n0x402195C0 WRITE   4341424\n0x40219500 WRITE   4341431\n0x402194C0 WRITE   4341433\n0x40219480 WRITE   4341443\n0x40219440 WRITE   4341445\n0x401B1440 WRITE   4341472\n0x40219580 WRITE   4341913\n0x40219540 WRITE   4341915\n0x401C4D00 WRITE   4341999\n0x40219700 WRITE   4342393\n0x402196C0 WRITE   4342395\n0x40219680 WRITE   4342402\n0x40219640 WRITE   4342404\n0x401B1480 WRITE   4342437\n0x40219780 WRITE   4342910\n0x40219740 WRITE   4342912\n0x401C4D40 WRITE   4342996\n0x40219C00 WRITE   4343428\n0x40219BC0 WRITE   4343430\n0x40219A00 WRITE   4343437\n0x402199C0 WRITE   4343439\n0x40219900 WRITE   4343449\n0x402198C0 WRITE   4343451\n0x40219880 WRITE   4343456\n0x40219840 WRITE   4343459\n0x401B14C0 WRITE   4343484\n0x40219980 WRITE   4343923\n0x40219940 WRITE   4343925\n0x401C4D80 WRITE   4344009\n0x40219B00 WRITE   4344401\n0x40219AC0 WRITE   4344403\n0x40219A80 WRITE   4344410\n0x40219A40 WRITE   4344412\n0x401B1500 WRITE   4344445\n0x40219B80 WRITE   4344916\n0x40219B40 WRITE   4344918\n0x401C4DC0 WRITE   4345002\n0x40219E00 WRITE   4345427\n0x40219DC0 WRITE   4345429\n0x40219D00 WRITE   4345436\n0x40219CC0 WRITE   4345438\n0x40219C80 WRITE   4345448\n0x40219C40 WRITE   4345450\n0x401B1540 WRITE   4345477\n0x40219D80 WRITE   4345925\n0x40219D40 WRITE   4345927\n0x401C4E00 WRITE   4346011\n0x40219F00 WRITE   4346412\n0x40219EC0 WRITE   4346414\n0x40219E80 WRITE   4346421\n0x40219E40 WRITE   4346423\n0x401B1580 WRITE   4346456\n0x40219F80 WRITE   4346936\n0x40219F40 WRITE   4346938\n0x401C4E40 WRITE   4347022\n0x4021BFC0 WRITE   4347506\n0x4021C000 WRITE   4347540\n0x4021B000 WRITE   4347663\n0x4021AFC0 WRITE   4347665\n0x4021A800 WRITE   4347672\n0x4021A7C0 WRITE   4347674\n0x4021A400 WRITE   4347684\n0x4021A3C0 WRITE   4347686\n0x4021A200 WRITE   4347691\n0x4021A1C0 WRITE   4347694\n0x4021A100 WRITE   4347697\n0x4021A0C0 WRITE   4347700\n0x4021A080 WRITE   4347703\n0x4021A040 WRITE   4347706\n0x401B15C0 WRITE   4347739\n0x4021A180 WRITE   4348169\n0x4021A140 WRITE   4348171\n0x401C4E80 WRITE   4348255\n0x4021A300 WRITE   4348634\n0x4021A2C0 WRITE   4348636\n0x4021A280 WRITE   4348643\n0x4021A240 WRITE   4348645\n0x401B1600 WRITE   4348678\n0x4021A380 WRITE   4349141\n0x4021A340 WRITE   4349143\n0x401C4EC0 WRITE   4349227\n0x4021A600 WRITE   4349638\n0x4021A5C0 WRITE   4349640\n0x4021A500 WRITE   4349647\n0x4021A4C0 WRITE   4349649\n0x4021A480 WRITE   4349659\n0x4021A440 WRITE   4349661\n0x401B1640 WRITE   4349688\n0x4021A580 WRITE   4350129\n0x4021A540 WRITE   4350131\n0x401C4F00 WRITE   4350215\n0x4021A700 WRITE   4350603\n0x4021A6C0 WRITE   4350605\n0x4021A680 WRITE   4350612\n0x4021A640 WRITE   4350614\n0x401B1680 WRITE   4350647\n0x4021A780 WRITE   4351120\n0x4021A740 WRITE   4351122\n0x401C4F40 WRITE   4351206\n0x4021AC00 WRITE   4351632\n0x4021ABC0 WRITE   4351634\n0x4021AA00 WRITE   4351641\n0x4021A9C0 WRITE   4351643\n0x4021A900 WRITE   4351653\n0x4021A8C0 WRITE   4351655\n0x4021A880 WRITE   4351660\n0x4021A840 WRITE   4351663\n0x401B16C0 WRITE   4351688\n0x4021A980 WRITE   4352127\n0x4021A940 WRITE   4352129\n0x401C4F80 WRITE   4352213\n0x4021AB00 WRITE   4352599\n0x4021AAC0 WRITE   4352601\n0x4021AA80 WRITE   4352608\n0x4021AA40 WRITE   4352610\n0x401B1700 WRITE   4352643\n0x4021AB80 WRITE   4353114\n0x4021AB40 WRITE   4353116\n0x401C4FC0 WRITE   4353200\n0x4021AE00 WRITE   4353619\n0x4021ADC0 WRITE   4353621\n0x4021AD00 WRITE   4353628\n0x4021ACC0 WRITE   4353630\n0x4021AC80 WRITE   4353640\n0x4021AC40 WRITE   4353642\n0x401B1740 WRITE   4353669\n0x4021AD80 WRITE   4354117\n0x4021AD40 WRITE   4354119\n0x401C5000 WRITE   4354203\n0x4021AF00 WRITE   4354598\n0x4021AEC0 WRITE   4354600\n0x4021AE80 WRITE   4354607\n0x4021AE40 WRITE   4354609\n0x401B1780 WRITE   4354642\n0x4021AF80 WRITE   4355122\n0x4021AF40 WRITE   4355124\n0x401C5040 WRITE   4355208\n0x4021B800 WRITE   4355640\n0x4021B7C0 WRITE   4355642\n0x4021B400 WRITE   4355649\n0x4021B3C0 WRITE   4355651\n0x4021B200 WRITE   4355661\n0x4021B1C0 WRITE   4355663\n0x4021B100 WRITE   4355668\n0x4021B0C0 WRITE   4355671\n0x4021B080 WRITE   4355674\n0x4021B040 WRITE   4355677\n0x401B17C0 WRITE   4355702\n0x4021B180 WRITE   4356133\n0x4021B140 WRITE   4356135\n0x401C5080 WRITE   4356219\n0x4021B300 WRITE   4356603\n0x4021B2C0 WRITE   4356605\n0x4021B280 WRITE   4356612\n0x4021B240 WRITE   4356614\n0x401B1800 WRITE   4356647\n0x4021B380 WRITE   4357110\n0x4021B340 WRITE   4357112\n0x401C50C0 WRITE   4357196\n0x4021B600 WRITE   4357613\n0x4021B5C0 WRITE   4357615\n0x4021B500 WRITE   4357622\n0x4021B4C0 WRITE   4357624\n0x4021B480 WRITE   4357634\n0x4021B440 WRITE   4357636\n0x401B1840 WRITE   4357663\n0x4021B580 WRITE   4358104\n0x4021B540 WRITE   4358106\n0x401C5100 WRITE   4358190\n0x4021B700 WRITE   4358584\n0x4021B6C0 WRITE   4358586\n0x4021B680 WRITE   4358593\n0x4021B640 WRITE   4358595\n0x401B1880 WRITE   4358628\n0x4021B780 WRITE   4359101\n0x4021B740 WRITE   4359103\n0x401C5140 WRITE   4359187\n0x4021BC00 WRITE   4359619\n0x4021BBC0 WRITE   4359621\n0x4021BA00 WRITE   4359628\n0x4021B9C0 WRITE   4359630\n0x4021B900 WRITE   4359640\n0x4021B8C0 WRITE   4359642\n0x4021B880 WRITE   4359647\n0x4021B840 WRITE   4359650\n0x401B18C0 WRITE   4359675\n0x4021B980 WRITE   4360114\n0x4021B940 WRITE   4360116\n0x401C5180 WRITE   4360200\n0x4021BB00 WRITE   4360592\n0x4021BAC0 WRITE   4360594\n0x4021BA80 WRITE   4360601\n0x4021BA40 WRITE   4360603\n0x401B1900 WRITE   4360636\n0x4021BB80 WRITE   4361107\n0x4021BB40 WRITE   4361109\n0x401C51C0 WRITE   4361193\n0x4021BE00 WRITE   4361618\n0x4021BDC0 WRITE   4361620\n0x4021BD00 WRITE   4361627\n0x4021BCC0 WRITE   4361629\n0x4021BC80 WRITE   4361639\n0x4021BC40 WRITE   4361641\n0x401B1940 WRITE   4361668\n0x4021BD80 WRITE   4362116\n0x4021BD40 WRITE   4362118\n0x401C5200 WRITE   4362202\n0x4021BF00 WRITE   4362603\n0x4021BEC0 WRITE   4362605\n0x4021BE80 WRITE   4362612\n0x4021BE40 WRITE   4362614\n0x401B1980 WRITE   4362647\n0x4021BF80 WRITE   4363127\n0x4021BF40 WRITE   4363129\n0x401C5240 WRITE   4363213\n0x4021DFC0 WRITE   4363697\n0x4021E000 WRITE   4363731\n0x4021D000 WRITE   4363859\n0x4021CFC0 WRITE   4363861\n0x4021C800 WRITE   4363868\n0x4021C7C0 WRITE   4363870\n0x4021C400 WRITE   4363880\n0x4021C3C0 WRITE   4363882\n0x4021C200 WRITE   4363887\n0x4021C1C0 WRITE   4363890\n0x4021C100 WRITE   4363893\n0x4021C0C0 WRITE   4363896\n0x4021C080 WRITE   4363899\n0x4021C040 WRITE   4363902\n0x401B19C0 WRITE   4363935\n0x4021C180 WRITE   4364365\n0x4021C140 WRITE   4364367\n0x401C5280 WRITE   4364451\n0x4021C300 WRITE   4364830\n0x4021C2C0 WRITE   4364832\n0x4021C280 WRITE   4364839\n0x4021C240 WRITE   4364841\n0x401B1A00 WRITE   4364874\n0x4021C380 WRITE   4365337\n0x4021C340 WRITE   4365339\n0x401C52C0 WRITE   4365423\n0x4021C600 WRITE   4365834\n0x4021C5C0 WRITE   4365836\n0x4021C500 WRITE   4365843\n0x4021C4C0 WRITE   4365845\n0x4021C480 WRITE   4365855\n0x4021C440 WRITE   4365857\n0x401B1A40 WRITE   4365884\n0x4021C580 WRITE   4366325\n0x4021C540 WRITE   4366327\n0x401C5300 WRITE   4366411\n0x4021C700 WRITE   4366799\n0x4021C6C0 WRITE   4366801\n0x4021C680 WRITE   4366808\n0x4021C640 WRITE   4366810\n0x401B1A80 WRITE   4366843\n0x4021C780 WRITE   4367316\n0x4021C740 WRITE   4367318\n0x401C5340 WRITE   4367402\n0x4021CC00 WRITE   4367828\n0x4021CBC0 WRITE   4367830\n0x4021CA00 WRITE   4367837\n0x4021C9C0 WRITE   4367839\n0x4021C900 WRITE   4367849\n0x4021C8C0 WRITE   4367851\n0x4021C880 WRITE   4367856\n0x4021C840 WRITE   4367859\n0x401B1AC0 WRITE   4367884\n0x4021C980 WRITE   4368323\n0x4021C940 WRITE   4368325\n0x401C5380 WRITE   4368409\n0x4021CB00 WRITE   4368795\n0x4021CAC0 WRITE   4368797\n0x4021CA80 WRITE   4368804\n0x4021CA40 WRITE   4368806\n0x401B1B00 WRITE   4368839\n0x4021CB80 WRITE   4369310\n0x4021CB40 WRITE   4369312\n0x401C53C0 WRITE   4369396\n0x4021CE00 WRITE   4369815\n0x4021CDC0 WRITE   4369817\n0x4021CD00 WRITE   4369824\n0x4021CCC0 WRITE   4369826\n0x4021CC80 WRITE   4369836\n0x4021CC40 WRITE   4369838\n0x401B1B40 WRITE   4369865\n0x4021CD80 WRITE   4370313\n0x4021CD40 WRITE   4370315\n0x401C5400 WRITE   4370399\n0x4021CF00 WRITE   4370794\n0x4021CEC0 WRITE   4370796\n0x4021CE80 WRITE   4370803\n0x4021CE40 WRITE   4370805\n0x401B1B80 WRITE   4370838\n0x4021CF80 WRITE   4371318\n0x4021CF40 WRITE   4371320\n0x401C5440 WRITE   4371404\n0x4021D800 WRITE   4371836\n0x4021D7C0 WRITE   4371838\n0x4021D400 WRITE   4371845\n0x4021D3C0 WRITE   4371847\n0x4021D200 WRITE   4371857\n0x4021D1C0 WRITE   4371859\n0x4021D100 WRITE   4371864\n0x4021D0C0 WRITE   4371867\n0x4021D080 WRITE   4371870\n0x4021D040 WRITE   4371873\n0x401B1BC0 WRITE   4371898\n0x4021D180 WRITE   4372329\n0x4021D140 WRITE   4372331\n0x401C5480 WRITE   4372415\n0x4021D300 WRITE   4372799\n0x4021D2C0 WRITE   4372801\n0x4021D280 WRITE   4372808\n0x4021D240 WRITE   4372810\n0x401B1C00 WRITE   4372843\n0x4021D380 WRITE   4373306\n0x4021D340 WRITE   4373308\n0x401C54C0 WRITE   4373392\n0x4021D600 WRITE   4373809\n0x4021D5C0 WRITE   4373811\n0x4021D500 WRITE   4373818\n0x4021D4C0 WRITE   4373820\n0x4021D480 WRITE   4373830\n0x4021D440 WRITE   4373832\n0x401B1C40 WRITE   4373859\n0x4021D580 WRITE   4374300\n0x4021D540 WRITE   4374302\n0x401C5500 WRITE   4374386\n0x4021D700 WRITE   4374780\n0x4021D6C0 WRITE   4374782\n0x4021D680 WRITE   4374789\n0x4021D640 WRITE   4374791\n0x401B1C80 WRITE   4374824\n0x4021D780 WRITE   4375297\n0x4021D740 WRITE   4375299\n0x401C5540 WRITE   4375383\n0x4021DC00 WRITE   4375815\n0x4021DBC0 WRITE   4375817\n0x4021DA00 WRITE   4375824\n0x4021D9C0 WRITE   4375826\n0x4021D900 WRITE   4375836\n0x4021D8C0 WRITE   4375838\n0x4021D880 WRITE   4375843\n0x4021D840 WRITE   4375846\n0x401B1CC0 WRITE   4375871\n0x4021D980 WRITE   4376310\n0x4021D940 WRITE   4376312\n0x401C5580 WRITE   4376396\n0x4021DB00 WRITE   4376788\n0x4021DAC0 WRITE   4376790\n0x4021DA80 WRITE   4376797\n0x4021DA40 WRITE   4376799\n0x401B1D00 WRITE   4376832\n0x4021DB80 WRITE   4377303\n0x4021DB40 WRITE   4377305\n0x401C55C0 WRITE   4377389\n0x4021DE00 WRITE   4377814\n0x4021DDC0 WRITE   4377816\n0x4021DD00 WRITE   4377823\n0x4021DCC0 WRITE   4377825\n0x4021DC80 WRITE   4377835\n0x4021DC40 WRITE   4377837\n0x401B1D40 WRITE   4377864\n0x4021DD80 WRITE   4378312\n0x4021DD40 WRITE   4378314\n0x401C5600 WRITE   4378398\n0x4021DF00 WRITE   4378799\n0x4021DEC0 WRITE   4378801\n0x4021DE80 WRITE   4378808\n0x4021DE40 WRITE   4378810\n0x401B1D80 WRITE   4378843\n0x4021DF80 WRITE   4379323\n0x4021DF40 WRITE   4379325\n0x401C5640 WRITE   4379409\n0x4021FFC0 WRITE   4379893\n0x40220000 WRITE   4379927\n0x4021F000 WRITE   4380046\n0x4021EFC0 WRITE   4380048\n0x4021E800 WRITE   4380055\n0x4021E7C0 WRITE   4380057\n0x4021E400 WRITE   4380067\n0x4021E3C0 WRITE   4380069\n0x4021E200 WRITE   4380074\n0x4021E1C0 WRITE   4380077\n0x4021E100 WRITE   4380080\n0x4021E0C0 WRITE   4380083\n0x4021E080 WRITE   4380086\n0x4021E040 WRITE   4380089\n0x401B1DC0 WRITE   4380122\n0x4021E180 WRITE   4380552\n0x4021E140 WRITE   4380554\n0x401C5680 WRITE   4380638\n0x4021E300 WRITE   4381017\n0x4021E2C0 WRITE   4381019\n0x4021E280 WRITE   4381026\n0x4021E240 WRITE   4381028\n0x401B1E00 WRITE   4381061\n0x4021E380 WRITE   4381524\n0x4021E340 WRITE   4381526\n0x401C56C0 WRITE   4381610\n0x4021E600 WRITE   4382021\n0x4021E5C0 WRITE   4382023\n0x4021E500 WRITE   4382030\n0x4021E4C0 WRITE   4382032\n0x4021E480 WRITE   4382042\n0x4021E440 WRITE   4382044\n0x401B1E40 WRITE   4382071\n0x4021E580 WRITE   4382512\n0x4021E540 WRITE   4382514\n0x401C5700 WRITE   4382598\n0x4021E700 WRITE   4382986\n0x4021E6C0 WRITE   4382988\n0x4021E680 WRITE   4382995\n0x4021E640 WRITE   4382997\n0x401B1E80 WRITE   4383030\n0x4021E780 WRITE   4383503\n0x4021E740 WRITE   4383505\n0x401C5740 WRITE   4383589\n0x4021EC00 WRITE   4384015\n0x4021EBC0 WRITE   4384017\n0x4021EA00 WRITE   4384024\n0x4021E9C0 WRITE   4384026\n0x4021E900 WRITE   4384036\n0x4021E8C0 WRITE   4384038\n0x4021E880 WRITE   4384043\n0x4021E840 WRITE   4384046\n0x401B1EC0 WRITE   4384071\n0x4021E980 WRITE   4384510\n0x4021E940 WRITE   4384512\n0x401C5780 WRITE   4384596\n0x4021EB00 WRITE   4384982\n0x4021EAC0 WRITE   4384984\n0x4021EA80 WRITE   4384991\n0x4021EA40 WRITE   4384993\n0x401B1F00 WRITE   4385026\n0x4021EB80 WRITE   4385497\n0x4021EB40 WRITE   4385499\n0x401C57C0 WRITE   4385583\n0x4021EE00 WRITE   4386002\n0x4021EDC0 WRITE   4386004\n0x4021ED00 WRITE   4386011\n0x4021ECC0 WRITE   4386013\n0x4021EC80 WRITE   4386023\n0x4021EC40 WRITE   4386025\n0x401B1F40 WRITE   4386052\n0x4021ED80 WRITE   4386500\n0x4021ED40 WRITE   4386502\n0x401C5800 WRITE   4386586\n0x4021EF00 WRITE   4386981\n0x4021EEC0 WRITE   4386983\n0x4021EE80 WRITE   4386990\n0x4021EE40 WRITE   4386992\n0x401B1F80 WRITE   4387025\n0x4021EF80 WRITE   4387505\n0x4021EF40 WRITE   4387507\n0x401C5840 WRITE   4387591\n0x4021F800 WRITE   4388023\n0x4021F7C0 WRITE   4388025\n0x4021F400 WRITE   4388032\n0x4021F3C0 WRITE   4388034\n0x4021F200 WRITE   4388044\n0x4021F1C0 WRITE   4388046\n0x4021F100 WRITE   4388051\n0x4021F0C0 WRITE   4388054\n0x4021F080 WRITE   4388057\n0x4021F040 WRITE   4388060\n0x401B1FC0 WRITE   4388085\n0x4021F180 WRITE   4388516\n0x4021F140 WRITE   4388518\n0x401C5880 WRITE   4388602\n0x4021F300 WRITE   4388986\n0x4021F2C0 WRITE   4388988\n0x4021F280 WRITE   4388995\n0x4021F240 WRITE   4388997\n0x401B2000 WRITE   4389030\n0x4021F380 WRITE   4389493\n0x4021F340 WRITE   4389495\n0x401C58C0 WRITE   4389579\n0x4021F600 WRITE   4389996\n0x4021F5C0 WRITE   4389998\n0x4021F500 WRITE   4390005\n0x4021F4C0 WRITE   4390007\n0x4021F480 WRITE   4390017\n0x4021F440 WRITE   4390019\n0x401B2040 WRITE   4390046\n0x4021F580 WRITE   4390487\n0x4021F540 WRITE   4390489\n0x401C5900 WRITE   4390573\n0x4021F700 WRITE   4390967\n0x4021F6C0 WRITE   4390969\n0x4021F680 WRITE   4390976\n0x4021F640 WRITE   4390978\n0x401B2080 WRITE   4391011\n0x4021F780 WRITE   4391484\n0x4021F740 WRITE   4391486\n0x401C5940 WRITE   4391570\n0x4021FC00 WRITE   4392002\n0x4021FBC0 WRITE   4392004\n0x4021FA00 WRITE   4392011\n0x4021F9C0 WRITE   4392013\n0x4021F900 WRITE   4392023\n0x4021F8C0 WRITE   4392025\n0x4021F880 WRITE   4392030\n0x4021F840 WRITE   4392033\n0x401B20C0 WRITE   4392058\n0x4021F980 WRITE   4392497\n0x4021F940 WRITE   4392499\n0x401C5980 WRITE   4392583\n0x4021FB00 WRITE   4392975\n0x4021FAC0 WRITE   4392977\n0x4021FA80 WRITE   4392984\n0x4021FA40 WRITE   4392986\n0x401B2100 WRITE   4393019\n0x4021FB80 WRITE   4393490\n0x4021FB40 WRITE   4393492\n0x401C59C0 WRITE   4393576\n0x4021FE00 WRITE   4394001\n0x4021FDC0 WRITE   4394003\n0x4021FD00 WRITE   4394010\n0x4021FCC0 WRITE   4394012\n0x4021FC80 WRITE   4394022\n0x4021FC40 WRITE   4394024\n0x401B2140 WRITE   4394051\n0x4021FD80 WRITE   4394499\n0x4021FD40 WRITE   4394501\n0x401C5A00 WRITE   4394585\n0x4021FF00 WRITE   4394986\n0x4021FEC0 WRITE   4394988\n0x4021FE80 WRITE   4394995\n0x4021FE40 WRITE   4394997\n0x401B2180 WRITE   4395030\n0x4021FF80 WRITE   4395510\n0x4021FF40 WRITE   4395512\n0x401C5A40 WRITE   4395596\n0x40221FC0 WRITE   4396080\n0x40222000 WRITE   4396114\n0x40221000 WRITE   4396226\n0x40220FC0 WRITE   4396228\n0x40220800 WRITE   4396235\n0x402207C0 WRITE   4396237\n0x40220400 WRITE   4396247\n0x402203C0 WRITE   4396249\n0x40220200 WRITE   4396254\n0x402201C0 WRITE   4396257\n0x40220100 WRITE   4396260\n0x402200C0 WRITE   4396263\n0x40220080 WRITE   4396266\n0x40220040 WRITE   4396269\n0x401B21C0 WRITE   4396302\n0x40220180 WRITE   4396732\n0x40220140 WRITE   4396734\n0x401C5A80 WRITE   4396818\n0x40220300 WRITE   4397197\n0x402202C0 WRITE   4397199\n0x40220280 WRITE   4397206\n0x40220240 WRITE   4397208\n0x401B2200 WRITE   4397241\n0x40220380 WRITE   4397704\n0x40220340 WRITE   4397706\n0x401C5AC0 WRITE   4397790\n0x40220600 WRITE   4398201\n0x402205C0 WRITE   4398203\n0x40220500 WRITE   4398210\n0x402204C0 WRITE   4398212\n0x40220480 WRITE   4398222\n0x40220440 WRITE   4398224\n0x401B2240 WRITE   4398251\n0x40220580 WRITE   4398692\n0x40220540 WRITE   4398694\n0x401C5B00 WRITE   4398778\n0x40220700 WRITE   4399166\n0x402206C0 WRITE   4399168\n0x40220680 WRITE   4399175\n0x40220640 WRITE   4399177\n0x401B2280 WRITE   4399210\n0x40220780 WRITE   4399683\n0x40220740 WRITE   4399685\n0x401C5B40 WRITE   4399769\n0x40220C00 WRITE   4400195\n0x40220BC0 WRITE   4400197\n0x40220A00 WRITE   4400204\n0x402209C0 WRITE   4400206\n0x40220900 WRITE   4400216\n0x402208C0 WRITE   4400218\n0x40220880 WRITE   4400223\n0x40220840 WRITE   4400226\n0x401B22C0 WRITE   4400251\n0x40220980 WRITE   4400690\n0x40220940 WRITE   4400692\n0x401C5B80 WRITE   4400776\n0x40220B00 WRITE   4401162\n0x40220AC0 WRITE   4401164\n0x40220A80 WRITE   4401171\n0x40220A40 WRITE   4401173\n0x401B2300 WRITE   4401206\n0x40220B80 WRITE   4401677\n0x40220B40 WRITE   4401679\n0x401C5BC0 WRITE   4401763\n0x40220E00 WRITE   4402182\n0x40220DC0 WRITE   4402184\n0x40220D00 WRITE   4402191\n0x40220CC0 WRITE   4402193\n0x40220C80 WRITE   4402203\n0x40220C40 WRITE   4402205\n0x401B2340 WRITE   4402232\n0x40220D80 WRITE   4402680\n0x40220D40 WRITE   4402682\n0x401C5C00 WRITE   4402766\n0x40220F00 WRITE   4403161\n0x40220EC0 WRITE   4403163\n0x40220E80 WRITE   4403170\n0x40220E40 WRITE   4403172\n0x401B2380 WRITE   4403205\n0x40220F80 WRITE   4403685\n0x40220F40 WRITE   4403687\n0x401C5C40 WRITE   4403771\n0x40221800 WRITE   4404203\n0x402217C0 WRITE   4404205\n0x40221400 WRITE   4404212\n0x402213C0 WRITE   4404214\n0x40221200 WRITE   4404224\n0x402211C0 WRITE   4404226\n0x40221100 WRITE   4404231\n0x402210C0 WRITE   4404234\n0x40221080 WRITE   4404237\n0x40221040 WRITE   4404240\n0x401B23C0 WRITE   4404265\n0x40221180 WRITE   4404696\n0x40221140 WRITE   4404698\n0x401C5C80 WRITE   4404782\n0x40221300 WRITE   4405166\n0x402212C0 WRITE   4405168\n0x40221280 WRITE   4405175\n0x40221240 WRITE   4405177\n0x401B2400 WRITE   4405210\n0x40221380 WRITE   4405673\n0x40221340 WRITE   4405675\n0x401C5CC0 WRITE   4405759\n0x40221600 WRITE   4406176\n0x402215C0 WRITE   4406178\n0x40221500 WRITE   4406185\n0x402214C0 WRITE   4406187\n0x40221480 WRITE   4406197\n0x40221440 WRITE   4406199\n0x401B2440 WRITE   4406226\n0x40221580 WRITE   4406667\n0x40221540 WRITE   4406669\n0x401C5D00 WRITE   4406753\n0x40221700 WRITE   4407147\n0x402216C0 WRITE   4407149\n0x40221680 WRITE   4407156\n0x40221640 WRITE   4407158\n0x401B2480 WRITE   4407191\n0x40221780 WRITE   4407664\n0x40221740 WRITE   4407666\n0x401C5D40 WRITE   4407750\n0x40221C00 WRITE   4408182\n0x40221BC0 WRITE   4408184\n0x40221A00 WRITE   4408191\n0x402219C0 WRITE   4408193\n0x40221900 WRITE   4408203\n0x402218C0 WRITE   4408205\n0x40221880 WRITE   4408210\n0x40221840 WRITE   4408213\n0x401B24C0 WRITE   4408238\n0x40221980 WRITE   4408677\n0x40221940 WRITE   4408679\n0x401C5D80 WRITE   4408763\n0x40221B00 WRITE   4409155\n0x40221AC0 WRITE   4409157\n0x40221A80 WRITE   4409164\n0x40221A40 WRITE   4409166\n0x401B2500 WRITE   4409199\n0x40221B80 WRITE   4409670\n0x40221B40 WRITE   4409672\n0x401C5DC0 WRITE   4409756\n0x40221E00 WRITE   4410181\n0x40221DC0 WRITE   4410183\n0x40221D00 WRITE   4410190\n0x40221CC0 WRITE   4410192\n0x40221C80 WRITE   4410202\n0x40221C40 WRITE   4410204\n0x401B2540 WRITE   4410231\n0x40221D80 WRITE   4410679\n0x40221D40 WRITE   4410681\n0x401C5E00 WRITE   4410765\n0x40221F00 WRITE   4411166\n0x40221EC0 WRITE   4411168\n0x40221E80 WRITE   4411175\n0x40221E40 WRITE   4411177\n0x401B2580 WRITE   4411210\n0x40221F80 WRITE   4411690\n0x40221F40 WRITE   4411692\n0x401C5E40 WRITE   4411776\n0x40223FC0 WRITE   4412260\n0x40224000 WRITE   4412294\n0x40223000 WRITE   4412406\n0x40222FC0 WRITE   4412408\n0x40222800 WRITE   4412415\n0x402227C0 WRITE   4412417\n0x40222400 WRITE   4412427\n0x402223C0 WRITE   4412429\n0x40222200 WRITE   4412434\n0x402221C0 WRITE   4412437\n0x40222100 WRITE   4412440\n0x402220C0 WRITE   4412443\n0x40222080 WRITE   4412446\n0x40222040 WRITE   4412449\n0x401B25C0 WRITE   4412482\n0x40222180 WRITE   4412912\n0x40222140 WRITE   4412914\n0x401C5E80 WRITE   4412998\n0x40222300 WRITE   4413377\n0x402222C0 WRITE   4413379\n0x40222280 WRITE   4413386\n0x40222240 WRITE   4413388\n0x401B2600 WRITE   4413421\n0x40222380 WRITE   4413884\n0x40222340 WRITE   4413886\n0x401C5EC0 WRITE   4413970\n0x40222600 WRITE   4414381\n0x402225C0 WRITE   4414383\n0x40222500 WRITE   4414390\n0x402224C0 WRITE   4414392\n0x40222480 WRITE   4414402\n0x40222440 WRITE   4414404\n0x401B2640 WRITE   4414431\n0x40222580 WRITE   4414872\n0x40222540 WRITE   4414874\n0x401C5F00 WRITE   4414958\n0x40222700 WRITE   4415346\n0x402226C0 WRITE   4415348\n0x40222680 WRITE   4415355\n0x40222640 WRITE   4415357\n0x401B2680 WRITE   4415390\n0x40222780 WRITE   4415863\n0x40222740 WRITE   4415865\n0x401C5F40 WRITE   4415949\n0x40222C00 WRITE   4416375\n0x40222BC0 WRITE   4416377\n0x40222A00 WRITE   4416384\n0x402229C0 WRITE   4416386\n0x40222900 WRITE   4416396\n0x402228C0 WRITE   4416398\n0x40222880 WRITE   4416403\n0x40222840 WRITE   4416406\n0x401B26C0 WRITE   4416431\n0x40222980 WRITE   4416870\n0x40222940 WRITE   4416872\n0x401C5F80 WRITE   4416956\n0x40222B00 WRITE   4417342\n0x40222AC0 WRITE   4417344\n0x40222A80 WRITE   4417351\n0x40222A40 WRITE   4417353\n0x401B2700 WRITE   4417386\n0x40222B80 WRITE   4417857\n0x40222B40 WRITE   4417859\n0x401C5FC0 WRITE   4417943\n0x40222E00 WRITE   4418362\n0x40222DC0 WRITE   4418364\n0x40222D00 WRITE   4418371\n0x40222CC0 WRITE   4418373\n0x40222C80 WRITE   4418383\n0x40222C40 WRITE   4418385\n0x401B2740 WRITE   4418412\n0x40222D80 WRITE   4418860\n0x40222D40 WRITE   4418862\n0x401C6000 WRITE   4418946\n0x40222F00 WRITE   4419341\n0x40222EC0 WRITE   4419343\n0x40222E80 WRITE   4419350\n0x40222E40 WRITE   4419352\n0x401B2780 WRITE   4419385\n0x40222F80 WRITE   4419865\n0x40222F40 WRITE   4419867\n0x401C6040 WRITE   4419951\n0x40223800 WRITE   4420383\n0x402237C0 WRITE   4420385\n0x40223400 WRITE   4420392\n0x402233C0 WRITE   4420394\n0x40223200 WRITE   4420404\n0x402231C0 WRITE   4420406\n0x40223100 WRITE   4420411\n0x402230C0 WRITE   4420414\n0x40223080 WRITE   4420417\n0x40223040 WRITE   4420420\n0x401B27C0 WRITE   4420445\n0x40223180 WRITE   4420876\n0x40223140 WRITE   4420878\n0x401C6080 WRITE   4420962\n0x40223300 WRITE   4421346\n0x402232C0 WRITE   4421348\n0x40223280 WRITE   4421355\n0x40223240 WRITE   4421357\n0x401B2800 WRITE   4421390\n0x40223380 WRITE   4421853\n0x40223340 WRITE   4421855\n0x401C60C0 WRITE   4421939\n0x40223600 WRITE   4422356\n0x402235C0 WRITE   4422358\n0x40223500 WRITE   4422365\n0x402234C0 WRITE   4422367\n0x40223480 WRITE   4422377\n0x40223440 WRITE   4422379\n0x401B2840 WRITE   4422406\n0x40223580 WRITE   4422847\n0x40223540 WRITE   4422849\n0x401C6100 WRITE   4422933\n0x40223700 WRITE   4423327\n0x402236C0 WRITE   4423329\n0x40223680 WRITE   4423336\n0x40223640 WRITE   4423338\n0x401B2880 WRITE   4423371\n0x40223780 WRITE   4423844\n0x40223740 WRITE   4423846\n0x401C6140 WRITE   4423930\n0x40223C00 WRITE   4424362\n0x40223BC0 WRITE   4424364\n0x40223A00 WRITE   4424371\n0x402239C0 WRITE   4424373\n0x40223900 WRITE   4424383\n0x402238C0 WRITE   4424385\n0x40223880 WRITE   4424390\n0x40223840 WRITE   4424393\n0x401B28C0 WRITE   4424418\n0x40223980 WRITE   4424857\n0x40223940 WRITE   4424859\n0x401C6180 WRITE   4424943\n0x40223B00 WRITE   4425335\n0x40223AC0 WRITE   4425337\n0x40223A80 WRITE   4425344\n0x40223A40 WRITE   4425346\n0x401B2900 WRITE   4425379\n0x40223B80 WRITE   4425850\n0x40223B40 WRITE   4425852\n0x401C61C0 WRITE   4425936\n0x40223E00 WRITE   4426361\n0x40223DC0 WRITE   4426363\n0x40223D00 WRITE   4426370\n0x40223CC0 WRITE   4426372\n0x40223C80 WRITE   4426382\n0x40223C40 WRITE   4426384\n0x401B2940 WRITE   4426411\n0x40223D80 WRITE   4426859\n0x40223D40 WRITE   4426861\n0x401C6200 WRITE   4426945\n0x40223F00 WRITE   4427346\n0x40223EC0 WRITE   4427348\n0x40223E80 WRITE   4427355\n0x40223E40 WRITE   4427357\n0x401B2980 WRITE   4427390\n0x40223F80 WRITE   4427870\n0x40223F40 WRITE   4427872\n0x401C6240 WRITE   4427956\n0x40225FC0 WRITE   4428440\n0x40226000 WRITE   4428474\n0x40225000 WRITE   4428586\n0x40224FC0 WRITE   4428588\n0x40224800 WRITE   4428595\n0x402247C0 WRITE   4428597\n0x40224400 WRITE   4428607\n0x402243C0 WRITE   4428609\n0x40224200 WRITE   4428614\n0x402241C0 WRITE   4428617\n0x40224100 WRITE   4428620\n0x402240C0 WRITE   4428623\n0x40224080 WRITE   4428626\n0x40224040 WRITE   4428629\n0x401B29C0 WRITE   4428662\n0x40224180 WRITE   4429092\n0x40224140 WRITE   4429094\n0x401C6280 WRITE   4429178\n0x40224300 WRITE   4429557\n0x402242C0 WRITE   4429559\n0x40224280 WRITE   4429566\n0x40224240 WRITE   4429568\n0x401B2A00 WRITE   4429601\n0x40224380 WRITE   4430064\n0x40224340 WRITE   4430066\n0x401C62C0 WRITE   4430150\n0x40224600 WRITE   4430561\n0x402245C0 WRITE   4430563\n0x40224500 WRITE   4430570\n0x402244C0 WRITE   4430572\n0x40224480 WRITE   4430582\n0x40224440 WRITE   4430584\n0x401B2A40 WRITE   4430611\n0x40224580 WRITE   4431052\n0x40224540 WRITE   4431054\n0x401C6300 WRITE   4431138\n0x40224700 WRITE   4431526\n0x402246C0 WRITE   4431528\n0x40224680 WRITE   4431535\n0x40224640 WRITE   4431537\n0x401B2A80 WRITE   4431570\n0x40224780 WRITE   4432043\n0x40224740 WRITE   4432045\n0x401C6340 WRITE   4432129\n0x40224C00 WRITE   4432555\n0x40224BC0 WRITE   4432557\n0x40224A00 WRITE   4432564\n0x402249C0 WRITE   4432566\n0x40224900 WRITE   4432576\n0x402248C0 WRITE   4432578\n0x40224880 WRITE   4432583\n0x40224840 WRITE   4432586\n0x401B2AC0 WRITE   4432611\n0x40224980 WRITE   4433050\n0x40224940 WRITE   4433052\n0x401C6380 WRITE   4433136\n0x40224B00 WRITE   4433522\n0x40224AC0 WRITE   4433524\n0x40224A80 WRITE   4433531\n0x40224A40 WRITE   4433533\n0x401B2B00 WRITE   4433566\n0x40224B80 WRITE   4434037\n0x40224B40 WRITE   4434039\n0x401C63C0 WRITE   4434123\n0x40224E00 WRITE   4434542\n0x40224DC0 WRITE   4434544\n0x40224D00 WRITE   4434551\n0x40224CC0 WRITE   4434553\n0x40224C80 WRITE   4434563\n0x40224C40 WRITE   4434565\n0x401B2B40 WRITE   4434592\n0x40224D80 WRITE   4435040\n0x40224D40 WRITE   4435042\n0x401C6400 WRITE   4435126\n0x40224F00 WRITE   4435521\n0x40224EC0 WRITE   4435523\n0x40224E80 WRITE   4435530\n0x40224E40 WRITE   4435532\n0x401B2B80 WRITE   4435565\n0x40224F80 WRITE   4436045\n0x40224F40 WRITE   4436047\n0x401C6440 WRITE   4436131\n0x40225800 WRITE   4436563\n0x402257C0 WRITE   4436565\n0x40225400 WRITE   4436572\n0x402253C0 WRITE   4436574\n0x40225200 WRITE   4436584\n0x402251C0 WRITE   4436586\n0x40225100 WRITE   4436591\n0x402250C0 WRITE   4436594\n0x40225080 WRITE   4436597\n0x40225040 WRITE   4436600\n0x401B2BC0 WRITE   4436625\n0x40225180 WRITE   4437056\n0x40225140 WRITE   4437058\n0x401C6480 WRITE   4437142\n0x40225300 WRITE   4437526\n0x402252C0 WRITE   4437528\n0x40225280 WRITE   4437535\n0x40225240 WRITE   4437537\n0x401B2C00 WRITE   4437570\n0x40225380 WRITE   4438033\n0x40225340 WRITE   4438035\n0x401C64C0 WRITE   4438119\n0x40225600 WRITE   4438536\n0x402255C0 WRITE   4438538\n0x40225500 WRITE   4438545\n0x402254C0 WRITE   4438547\n0x40225480 WRITE   4438557\n0x40225440 WRITE   4438559\n0x401B2C40 WRITE   4438586\n0x40225580 WRITE   4439027\n0x40225540 WRITE   4439029\n0x401C6500 WRITE   4439113\n0x40225700 WRITE   4439507\n0x402256C0 WRITE   4439509\n0x40225680 WRITE   4439516\n0x40225640 WRITE   4439518\n0x401B2C80 WRITE   4439551\n0x40225780 WRITE   4440024\n0x40225740 WRITE   4440026\n0x401C6540 WRITE   4440110\n0x40225C00 WRITE   4440542\n0x40225BC0 WRITE   4440544\n0x40225A00 WRITE   4440551\n0x402259C0 WRITE   4440553\n0x40225900 WRITE   4440563\n0x402258C0 WRITE   4440565\n0x40225880 WRITE   4440570\n0x40225840 WRITE   4440573\n0x401B2CC0 WRITE   4440598\n0x40225980 WRITE   4441037\n0x40225940 WRITE   4441039\n0x401C6580 WRITE   4441123\n0x40225B00 WRITE   4441515\n0x40225AC0 WRITE   4441517\n0x40225A80 WRITE   4441524\n0x40225A40 WRITE   4441526\n0x401B2D00 WRITE   4441559\n0x40225B80 WRITE   4442030\n0x40225B40 WRITE   4442032\n0x401C65C0 WRITE   4442116\n0x40225E00 WRITE   4442541\n0x40225DC0 WRITE   4442543\n0x40225D00 WRITE   4442550\n0x40225CC0 WRITE   4442552\n0x40225C80 WRITE   4442562\n0x40225C40 WRITE   4442564\n0x401B2D40 WRITE   4442591\n0x40225D80 WRITE   4443039\n0x40225D40 WRITE   4443041\n0x401C6600 WRITE   4443125\n0x40225F00 WRITE   4443526\n0x40225EC0 WRITE   4443528\n0x40225E80 WRITE   4443535\n0x40225E40 WRITE   4443537\n0x401B2D80 WRITE   4443570\n0x40225F80 WRITE   4444050\n0x40225F40 WRITE   4444052\n0x401C6640 WRITE   4444136\n0x40227FC0 WRITE   4444620\n0x40228000 WRITE   4444654\n0x40227000 WRITE   4444782\n0x40226FC0 WRITE   4444784\n0x40226800 WRITE   4444791\n0x402267C0 WRITE   4444793\n0x40226400 WRITE   4444803\n0x402263C0 WRITE   4444805\n0x40226200 WRITE   4444810\n0x402261C0 WRITE   4444813\n0x40226100 WRITE   4444816\n0x402260C0 WRITE   4444819\n0x40226080 WRITE   4444822\n0x40226040 WRITE   4444825\n0x401B2DC0 WRITE   4444858\n0x40226180 WRITE   4445288\n0x40226140 WRITE   4445290\n0x401C6680 WRITE   4445374\n0x40226300 WRITE   4445753\n0x402262C0 WRITE   4445755\n0x40226280 WRITE   4445762\n0x40226240 WRITE   4445764\n0x401B2E00 WRITE   4445797\n0x40226380 WRITE   4446260\n0x40226340 WRITE   4446262\n0x401C66C0 WRITE   4446346\n0x40226600 WRITE   4446757\n0x402265C0 WRITE   4446759\n0x40226500 WRITE   4446766\n0x402264C0 WRITE   4446768\n0x40226480 WRITE   4446778\n0x40226440 WRITE   4446780\n0x401B2E40 WRITE   4446807\n0x40226580 WRITE   4447248\n0x40226540 WRITE   4447250\n0x401C6700 WRITE   4447334\n0x40226700 WRITE   4447722\n0x402266C0 WRITE   4447724\n0x40226680 WRITE   4447731\n0x40226640 WRITE   4447733\n0x401B2E80 WRITE   4447766\n0x40226780 WRITE   4448239\n0x40226740 WRITE   4448241\n0x401C6740 WRITE   4448325\n0x40226C00 WRITE   4448751\n0x40226BC0 WRITE   4448753\n0x40226A00 WRITE   4448760\n0x402269C0 WRITE   4448762\n0x40226900 WRITE   4448772\n0x402268C0 WRITE   4448774\n0x40226880 WRITE   4448779\n0x40226840 WRITE   4448782\n0x401B2EC0 WRITE   4448807\n0x40226980 WRITE   4449246\n0x40226940 WRITE   4449248\n0x401C6780 WRITE   4449332\n0x40226B00 WRITE   4449718\n0x40226AC0 WRITE   4449720\n0x40226A80 WRITE   4449727\n0x40226A40 WRITE   4449729\n0x401B2F00 WRITE   4449762\n0x40226B80 WRITE   4450233\n0x40226B40 WRITE   4450235\n0x401C67C0 WRITE   4450319\n0x40226E00 WRITE   4450738\n0x40226DC0 WRITE   4450740\n0x40226D00 WRITE   4450747\n0x40226CC0 WRITE   4450749\n0x40226C80 WRITE   4450759\n0x40226C40 WRITE   4450761\n0x401B2F40 WRITE   4450788\n0x40226D80 WRITE   4451236\n0x40226D40 WRITE   4451238\n0x401C6800 WRITE   4451322\n0x40226F00 WRITE   4451717\n0x40226EC0 WRITE   4451719\n0x40226E80 WRITE   4451726\n0x40226E40 WRITE   4451728\n0x401B2F80 WRITE   4451761\n0x40226F80 WRITE   4452241\n0x40226F40 WRITE   4452243\n0x401C6840 WRITE   4452327\n0x40227800 WRITE   4452759\n0x402277C0 WRITE   4452761\n0x40227400 WRITE   4452768\n0x402273C0 WRITE   4452770\n0x40227200 WRITE   4452780\n0x402271C0 WRITE   4452782\n0x40227100 WRITE   4452787\n0x402270C0 WRITE   4452790\n0x40227080 WRITE   4452793\n0x40227040 WRITE   4452796\n0x401B2FC0 WRITE   4452821\n0x40227180 WRITE   4453252\n0x40227140 WRITE   4453254\n0x401C6880 WRITE   4453338\n0x40227300 WRITE   4453722\n0x402272C0 WRITE   4453724\n0x40227280 WRITE   4453731\n0x40227240 WRITE   4453733\n0x401B3000 WRITE   4453766\n0x40227380 WRITE   4454229\n0x40227340 WRITE   4454231\n0x401C68C0 WRITE   4454315\n0x40227600 WRITE   4454732\n0x402275C0 WRITE   4454734\n0x40227500 WRITE   4454741\n0x402274C0 WRITE   4454743\n0x40227480 WRITE   4454753\n0x40227440 WRITE   4454755\n0x401B3040 WRITE   4454782\n0x40227580 WRITE   4455223\n0x40227540 WRITE   4455225\n0x401C6900 WRITE   4455309\n0x40227700 WRITE   4455703\n0x402276C0 WRITE   4455705\n0x40227680 WRITE   4455712\n0x40227640 WRITE   4455714\n0x401B3080 WRITE   4455747\n0x40227780 WRITE   4456220\n0x40227740 WRITE   4456222\n0x401C6940 WRITE   4456306\n0x40227C00 WRITE   4456738\n0x40227BC0 WRITE   4456740\n0x40227A00 WRITE   4456747\n0x402279C0 WRITE   4456749\n0x40227900 WRITE   4456759\n0x402278C0 WRITE   4456761\n0x40227880 WRITE   4456766\n0x40227840 WRITE   4456769\n0x401B30C0 WRITE   4456794\n0x40227980 WRITE   4457233\n0x40227940 WRITE   4457235\n0x401C6980 WRITE   4457319\n0x40227B00 WRITE   4457711\n0x40227AC0 WRITE   4457713\n0x40227A80 WRITE   4457720\n0x40227A40 WRITE   4457722\n0x401B3100 WRITE   4457755\n0x40227B80 WRITE   4458226\n0x40227B40 WRITE   4458228\n0x401C69C0 WRITE   4458312\n0x40227E00 WRITE   4458737\n0x40227DC0 WRITE   4458739\n0x40227D00 WRITE   4458746\n0x40227CC0 WRITE   4458748\n0x40227C80 WRITE   4458758\n0x40227C40 WRITE   4458760\n0x401B3140 WRITE   4458787\n0x40227D80 WRITE   4459235\n0x40227D40 WRITE   4459237\n0x401C6A00 WRITE   4459321\n0x40227F00 WRITE   4459722\n0x40227EC0 WRITE   4459724\n0x40227E80 WRITE   4459731\n0x40227E40 WRITE   4459733\n0x401B3180 WRITE   4459766\n0x40227F80 WRITE   4460246\n0x40227F40 WRITE   4460248\n0x401C6A40 WRITE   4460332\n0x40229FC0 WRITE   4460816\n0x4022A000 WRITE   4460850\n0x40229000 WRITE   4460962\n0x40228FC0 WRITE   4460964\n0x40228800 WRITE   4460971\n0x402287C0 WRITE   4460973\n0x40228400 WRITE   4460983\n0x402283C0 WRITE   4460985\n0x40228200 WRITE   4460990\n0x402281C0 WRITE   4460993\n0x40228100 WRITE   4460996\n0x402280C0 WRITE   4460999\n0x40228080 WRITE   4461002\n0x40228040 WRITE   4461005\n0x401B31C0 WRITE   4461038\n0x40228180 WRITE   4461468\n0x40228140 WRITE   4461470\n0x401C6A80 WRITE   4461554\n0x40228300 WRITE   4461933\n0x402282C0 WRITE   4461935\n0x40228280 WRITE   4461942\n0x40228240 WRITE   4461944\n0x401B3200 WRITE   4461977\n0x40228380 WRITE   4462440\n0x40228340 WRITE   4462442\n0x401C6AC0 WRITE   4462526\n0x40228600 WRITE   4462937\n0x402285C0 WRITE   4462939\n0x40228500 WRITE   4462946\n0x402284C0 WRITE   4462948\n0x40228480 WRITE   4462958\n0x40228440 WRITE   4462960\n0x401B3240 WRITE   4462987\n0x40228580 WRITE   4463428\n0x40228540 WRITE   4463430\n0x401C6B00 WRITE   4463514\n0x40228700 WRITE   4463902\n0x402286C0 WRITE   4463904\n0x40228680 WRITE   4463911\n0x40228640 WRITE   4463913\n0x401B3280 WRITE   4463946\n0x40228780 WRITE   4464419\n0x40228740 WRITE   4464421\n0x401C6B40 WRITE   4464505\n0x40228C00 WRITE   4464931\n0x40228BC0 WRITE   4464933\n0x40228A00 WRITE   4464940\n0x402289C0 WRITE   4464942\n0x40228900 WRITE   4464952\n0x402288C0 WRITE   4464954\n0x40228880 WRITE   4464959\n0x40228840 WRITE   4464962\n0x401B32C0 WRITE   4464987\n0x40228980 WRITE   4465426\n0x40228940 WRITE   4465428\n0x401C6B80 WRITE   4465512\n0x40228B00 WRITE   4465898\n0x40228AC0 WRITE   4465900\n0x40228A80 WRITE   4465907\n0x40228A40 WRITE   4465909\n0x401B3300 WRITE   4465942\n0x40228B80 WRITE   4466413\n0x40228B40 WRITE   4466415\n0x401C6BC0 WRITE   4466499\n0x40228E00 WRITE   4466918\n0x40228DC0 WRITE   4466920\n0x40228D00 WRITE   4466927\n0x40228CC0 WRITE   4466929\n0x40228C80 WRITE   4466939\n0x40228C40 WRITE   4466941\n0x401B3340 WRITE   4466968\n0x40228D80 WRITE   4467416\n0x40228D40 WRITE   4467418\n0x401C6C00 WRITE   4467502\n0x40228F00 WRITE   4467897\n0x40228EC0 WRITE   4467899\n0x40228E80 WRITE   4467906\n0x40228E40 WRITE   4467908\n0x401B3380 WRITE   4467941\n0x40228F80 WRITE   4468421\n0x40228F40 WRITE   4468423\n0x401C6C40 WRITE   4468507\n0x40229800 WRITE   4468939\n0x402297C0 WRITE   4468941\n0x40229400 WRITE   4468948\n0x402293C0 WRITE   4468950\n0x40229200 WRITE   4468960\n0x402291C0 WRITE   4468962\n0x40229100 WRITE   4468967\n0x402290C0 WRITE   4468970\n0x40229080 WRITE   4468973\n0x40229040 WRITE   4468976\n0x401B33C0 WRITE   4469001\n0x40229180 WRITE   4469432\n0x40229140 WRITE   4469434\n0x401C6C80 WRITE   4469518\n0x40229300 WRITE   4469902\n0x402292C0 WRITE   4469904\n0x40229280 WRITE   4469911\n0x40229240 WRITE   4469913\n0x401B3400 WRITE   4469946\n0x40229380 WRITE   4470409\n0x40229340 WRITE   4470411\n0x401C6CC0 WRITE   4470495\n0x40229600 WRITE   4470912\n0x402295C0 WRITE   4470914\n0x40229500 WRITE   4470921\n0x402294C0 WRITE   4470923\n0x40229480 WRITE   4470933\n0x40229440 WRITE   4470935\n0x401B3440 WRITE   4470962\n0x40229580 WRITE   4471403\n0x40229540 WRITE   4471405\n0x401C6D00 WRITE   4471489\n0x40229700 WRITE   4471883\n0x402296C0 WRITE   4471885\n0x40229680 WRITE   4471892\n0x40229640 WRITE   4471894\n0x401B3480 WRITE   4471927\n0x40229780 WRITE   4472400\n0x40229740 WRITE   4472402\n0x401C6D40 WRITE   4472486\n0x40229C00 WRITE   4472918\n0x40229BC0 WRITE   4472920\n0x40229A00 WRITE   4472927\n0x402299C0 WRITE   4472929\n0x40229900 WRITE   4472939\n0x402298C0 WRITE   4472941\n0x40229880 WRITE   4472946\n0x40229840 WRITE   4472949\n0x401B34C0 WRITE   4472974\n0x40229980 WRITE   4473413\n0x40229940 WRITE   4473415\n0x401C6D80 WRITE   4473499\n0x40229B00 WRITE   4473891\n0x40229AC0 WRITE   4473893\n0x40229A80 WRITE   4473900\n0x40229A40 WRITE   4473902\n0x401B3500 WRITE   4473935\n0x40229B80 WRITE   4474406\n0x40229B40 WRITE   4474408\n0x401C6DC0 WRITE   4474492\n0x40229E00 WRITE   4474917\n0x40229DC0 WRITE   4474919\n0x40229D00 WRITE   4474926\n0x40229CC0 WRITE   4474928\n0x40229C80 WRITE   4474938\n0x40229C40 WRITE   4474940\n0x401B3540 WRITE   4474967\n0x40229D80 WRITE   4475415\n0x40229D40 WRITE   4475417\n0x401C6E00 WRITE   4475501\n0x40229F00 WRITE   4475902\n0x40229EC0 WRITE   4475904\n0x40229E80 WRITE   4475911\n0x40229E40 WRITE   4475913\n0x401B3580 WRITE   4475946\n0x40229F80 WRITE   4476426\n0x40229F40 WRITE   4476428\n0x401C6E40 WRITE   4476512\n0x4022BFC0 WRITE   4476996\n0x4022C000 WRITE   4477030\n0x4022B000 WRITE   4477153\n0x4022AFC0 WRITE   4477155\n0x4022A800 WRITE   4477162\n0x4022A7C0 WRITE   4477164\n0x4022A400 WRITE   4477174\n0x4022A3C0 WRITE   4477176\n0x4022A200 WRITE   4477181\n0x4022A1C0 WRITE   4477184\n0x4022A100 WRITE   4477187\n0x4022A0C0 WRITE   4477190\n0x4022A080 WRITE   4477193\n0x4022A040 WRITE   4477196\n0x401B35C0 WRITE   4477229\n0x4022A180 WRITE   4477659\n0x4022A140 WRITE   4477661\n0x401C6E80 WRITE   4477745\n0x4022A300 WRITE   4478124\n0x4022A2C0 WRITE   4478126\n0x4022A280 WRITE   4478133\n0x4022A240 WRITE   4478135\n0x401B3600 WRITE   4478168\n0x4022A380 WRITE   4478631\n0x4022A340 WRITE   4478633\n0x401C6EC0 WRITE   4478717\n0x4022A600 WRITE   4479128\n0x4022A5C0 WRITE   4479130\n0x4022A500 WRITE   4479137\n0x4022A4C0 WRITE   4479139\n0x4022A480 WRITE   4479149\n0x4022A440 WRITE   4479151\n0x401B3640 WRITE   4479178\n0x4022A580 WRITE   4479619\n0x4022A540 WRITE   4479621\n0x401C6F00 WRITE   4479705\n0x4022A700 WRITE   4480093\n0x4022A6C0 WRITE   4480095\n0x4022A680 WRITE   4480102\n0x4022A640 WRITE   4480104\n0x401B3680 WRITE   4480137\n0x4022A780 WRITE   4480610\n0x4022A740 WRITE   4480612\n0x401C6F40 WRITE   4480696\n0x4022AC00 WRITE   4481122\n0x4022ABC0 WRITE   4481124\n0x4022AA00 WRITE   4481131\n0x4022A9C0 WRITE   4481133\n0x4022A900 WRITE   4481143\n0x4022A8C0 WRITE   4481145\n0x4022A880 WRITE   4481150\n0x4022A840 WRITE   4481153\n0x401B36C0 WRITE   4481178\n0x4022A980 WRITE   4481617\n0x4022A940 WRITE   4481619\n0x401C6F80 WRITE   4481703\n0x4022AB00 WRITE   4482089\n0x4022AAC0 WRITE   4482091\n0x4022AA80 WRITE   4482098\n0x4022AA40 WRITE   4482100\n0x401B3700 WRITE   4482133\n0x4022AB80 WRITE   4482604\n0x4022AB40 WRITE   4482606\n0x401C6FC0 WRITE   4482690\n0x4022AE00 WRITE   4483109\n0x4022ADC0 WRITE   4483111\n0x4022AD00 WRITE   4483118\n0x4022ACC0 WRITE   4483120\n0x4022AC80 WRITE   4483130\n0x4022AC40 WRITE   4483132\n0x401B3740 WRITE   4483159\n0x4022AD80 WRITE   4483607\n0x4022AD40 WRITE   4483609\n0x401C7000 WRITE   4483693\n0x4022AF00 WRITE   4484088\n0x4022AEC0 WRITE   4484090\n0x4022AE80 WRITE   4484097\n0x4022AE40 WRITE   4484099\n0x401B3780 WRITE   4484132\n0x4022AF80 WRITE   4484612\n0x4022AF40 WRITE   4484614\n0x401C7040 WRITE   4484698\n0x4022B800 WRITE   4485130\n0x4022B7C0 WRITE   4485132\n0x4022B400 WRITE   4485139\n0x4022B3C0 WRITE   4485141\n0x4022B200 WRITE   4485151\n0x4022B1C0 WRITE   4485153\n0x4022B100 WRITE   4485158\n0x4022B0C0 WRITE   4485161\n0x4022B080 WRITE   4485164\n0x4022B040 WRITE   4485167\n0x401B37C0 WRITE   4485192\n0x4022B180 WRITE   4485623\n0x4022B140 WRITE   4485625\n0x401C7080 WRITE   4485709\n0x4022B300 WRITE   4486093\n0x4022B2C0 WRITE   4486095\n0x4022B280 WRITE   4486102\n0x4022B240 WRITE   4486104\n0x401B3800 WRITE   4486137\n0x4022B380 WRITE   4486600\n0x4022B340 WRITE   4486602\n0x401C70C0 WRITE   4486686\n0x4022B600 WRITE   4487103\n0x4022B5C0 WRITE   4487105\n0x4022B500 WRITE   4487112\n0x4022B4C0 WRITE   4487114\n0x4022B480 WRITE   4487124\n0x4022B440 WRITE   4487126\n0x401B3840 WRITE   4487153\n0x4022B580 WRITE   4487594\n0x4022B540 WRITE   4487596\n0x401C7100 WRITE   4487680\n0x4022B700 WRITE   4488074\n0x4022B6C0 WRITE   4488076\n0x4022B680 WRITE   4488083\n0x4022B640 WRITE   4488085\n0x401B3880 WRITE   4488118\n0x4022B780 WRITE   4488591\n0x4022B740 WRITE   4488593\n0x401C7140 WRITE   4488677\n0x4022BC00 WRITE   4489109\n0x4022BBC0 WRITE   4489111\n0x4022BA00 WRITE   4489118\n0x4022B9C0 WRITE   4489120\n0x4022B900 WRITE   4489130\n0x4022B8C0 WRITE   4489132\n0x4022B880 WRITE   4489137\n0x4022B840 WRITE   4489140\n0x401B38C0 WRITE   4489165\n0x4022B980 WRITE   4489604\n0x4022B940 WRITE   4489606\n0x401C7180 WRITE   4489690\n0x4022BB00 WRITE   4490082\n0x4022BAC0 WRITE   4490084\n0x4022BA80 WRITE   4490091\n0x4022BA40 WRITE   4490093\n0x401B3900 WRITE   4490126\n0x4022BB80 WRITE   4490597\n0x4022BB40 WRITE   4490599\n0x401C71C0 WRITE   4490683\n0x4022BE00 WRITE   4491108\n0x4022BDC0 WRITE   4491110\n0x4022BD00 WRITE   4491117\n0x4022BCC0 WRITE   4491119\n0x4022BC80 WRITE   4491129\n0x4022BC40 WRITE   4491131\n0x401B3940 WRITE   4491158\n0x4022BD80 WRITE   4491606\n0x4022BD40 WRITE   4491608\n0x401C7200 WRITE   4491692\n0x4022BF00 WRITE   4492093\n0x4022BEC0 WRITE   4492095\n0x4022BE80 WRITE   4492102\n0x4022BE40 WRITE   4492104\n0x401B3980 WRITE   4492137\n0x4022BF80 WRITE   4492617\n0x4022BF40 WRITE   4492619\n0x401C7240 WRITE   4492703\n0x4022DFC0 WRITE   4493192\n0x4022E000 WRITE   4493224\n0x4022D000 WRITE   4493352\n0x4022CFC0 WRITE   4493354\n0x4022C800 WRITE   4493361\n0x4022C7C0 WRITE   4493363\n0x4022C400 WRITE   4493373\n0x4022C3C0 WRITE   4493375\n0x4022C200 WRITE   4493380\n0x4022C1C0 WRITE   4493383\n0x4022C100 WRITE   4493386\n0x4022C0C0 WRITE   4493389\n0x4022C080 WRITE   4493392\n0x4022C040 WRITE   4493395\n0x401B39C0 WRITE   4493428\n0x4022C180 WRITE   4493858\n0x4022C140 WRITE   4493860\n0x401C7280 WRITE   4493944\n0x4022C300 WRITE   4494323\n0x4022C2C0 WRITE   4494325\n0x4022C280 WRITE   4494332\n0x4022C240 WRITE   4494334\n0x401B3A00 WRITE   4494367\n0x4022C380 WRITE   4494830\n0x4022C340 WRITE   4494832\n0x401C72C0 WRITE   4494916\n0x4022C600 WRITE   4495327\n0x4022C5C0 WRITE   4495329\n0x4022C500 WRITE   4495336\n0x4022C4C0 WRITE   4495338\n0x4022C480 WRITE   4495348\n0x4022C440 WRITE   4495350\n0x401B3A40 WRITE   4495377\n0x4022C580 WRITE   4495818\n0x4022C540 WRITE   4495820\n0x401C7300 WRITE   4495904\n0x4022C700 WRITE   4496292\n0x4022C6C0 WRITE   4496294\n0x4022C680 WRITE   4496301\n0x4022C640 WRITE   4496303\n0x401B3A80 WRITE   4496336\n0x4022C780 WRITE   4496809\n0x4022C740 WRITE   4496811\n0x401C7340 WRITE   4496895\n0x4022CC00 WRITE   4497321\n0x4022CBC0 WRITE   4497323\n0x4022CA00 WRITE   4497330\n0x4022C9C0 WRITE   4497332\n0x4022C900 WRITE   4497342\n0x4022C8C0 WRITE   4497344\n0x4022C880 WRITE   4497349\n0x4022C840 WRITE   4497352\n0x401B3AC0 WRITE   4497377\n0x4022C980 WRITE   4497816\n0x4022C940 WRITE   4497818\n0x401C7380 WRITE   4497902\n0x4022CB00 WRITE   4498288\n0x4022CAC0 WRITE   4498290\n0x4022CA80 WRITE   4498297\n0x4022CA40 WRITE   4498299\n0x401B3B00 WRITE   4498332\n0x4022CB80 WRITE   4498803\n0x4022CB40 WRITE   4498805\n0x401C73C0 WRITE   4498889\n0x4022CE00 WRITE   4499308\n0x4022CDC0 WRITE   4499310\n0x4022CD00 WRITE   4499317\n0x4022CCC0 WRITE   4499319\n0x4022CC80 WRITE   4499329\n0x4022CC40 WRITE   4499331\n0x401B3B40 WRITE   4499358\n0x4022CD80 WRITE   4499806\n0x4022CD40 WRITE   4499808\n0x401C7400 WRITE   4499892\n0x4022CF00 WRITE   4500287\n0x4022CEC0 WRITE   4500289\n0x4022CE80 WRITE   4500296\n0x4022CE40 WRITE   4500298\n0x401B3B80 WRITE   4500331\n0x4022CF80 WRITE   4500811\n0x4022CF40 WRITE   4500813\n0x401C7440 WRITE   4500897\n0x4022D800 WRITE   4501329\n0x4022D7C0 WRITE   4501331\n0x4022D400 WRITE   4501338\n0x4022D3C0 WRITE   4501340\n0x4022D200 WRITE   4501350\n0x4022D1C0 WRITE   4501352\n0x4022D100 WRITE   4501357\n0x4022D0C0 WRITE   4501360\n0x4022D080 WRITE   4501363\n0x4022D040 WRITE   4501366\n0x401B3BC0 WRITE   4501391\n0x4022D180 WRITE   4501822\n0x4022D140 WRITE   4501824\n0x401C7480 WRITE   4501908\n0x4022D300 WRITE   4502292\n0x4022D2C0 WRITE   4502294\n0x4022D280 WRITE   4502301\n0x4022D240 WRITE   4502303\n0x401B3C00 WRITE   4502336\n0x4022D380 WRITE   4502799\n0x4022D340 WRITE   4502801\n0x401C74C0 WRITE   4502885\n0x4022D600 WRITE   4503302\n0x4022D5C0 WRITE   4503304\n0x4022D500 WRITE   4503311\n0x4022D4C0 WRITE   4503313\n0x4022D480 WRITE   4503323\n0x4022D440 WRITE   4503325\n0x401B3C40 WRITE   4503352\n0x4022D580 WRITE   4503793\n0x4022D540 WRITE   4503795\n0x401C7500 WRITE   4503879\n0x4022D700 WRITE   4504273\n0x4022D6C0 WRITE   4504275\n0x4022D680 WRITE   4504282\n0x4022D640 WRITE   4504284\n0x401B3C80 WRITE   4504317\n0x4022D780 WRITE   4504790\n0x4022D740 WRITE   4504792\n0x401C7540 WRITE   4504876\n0x4022DC00 WRITE   4505308\n0x4022DBC0 WRITE   4505310\n0x4022DA00 WRITE   4505317\n0x4022D9C0 WRITE   4505319\n0x4022D900 WRITE   4505329\n0x4022D8C0 WRITE   4505331\n0x4022D880 WRITE   4505336\n0x4022D840 WRITE   4505339\n0x401B3CC0 WRITE   4505364\n0x4022D980 WRITE   4505803\n0x4022D940 WRITE   4505805\n0x401C7580 WRITE   4505889\n0x4022DB00 WRITE   4506281\n0x4022DAC0 WRITE   4506283\n0x4022DA80 WRITE   4506290\n0x4022DA40 WRITE   4506292\n0x401B3D00 WRITE   4506325\n0x4022DB80 WRITE   4506796\n0x4022DB40 WRITE   4506798\n0x401C75C0 WRITE   4506882\n0x4022DE00 WRITE   4507307\n0x4022DDC0 WRITE   4507309\n0x4022DD00 WRITE   4507316\n0x4022DCC0 WRITE   4507318\n0x4022DC80 WRITE   4507328\n0x4022DC40 WRITE   4507330\n0x401B3D40 WRITE   4507357\n0x4022DD80 WRITE   4507805\n0x4022DD40 WRITE   4507807\n0x401C7600 WRITE   4507891\n0x4022DF00 WRITE   4508292\n0x4022DEC0 WRITE   4508294\n0x4022DE80 WRITE   4508301\n0x4022DE40 WRITE   4508303\n0x401B3D80 WRITE   4508336\n0x4022DF80 WRITE   4508816\n0x4022DF40 WRITE   4508818\n0x401C7640 WRITE   4508902\n0x4022FFC0 WRITE   4509386\n0x40230000 WRITE   4509420\n0x4022F000 WRITE   4509539\n0x4022EFC0 WRITE   4509541\n0x4022E800 WRITE   4509548\n0x4022E7C0 WRITE   4509550\n0x4022E400 WRITE   4509560\n0x4022E3C0 WRITE   4509562\n0x4022E200 WRITE   4509567\n0x4022E1C0 WRITE   4509570\n0x4022E100 WRITE   4509573\n0x4022E0C0 WRITE   4509576\n0x4022E080 WRITE   4509579\n0x4022E040 WRITE   4509582\n0x401B3DC0 WRITE   4509615\n0x4022E180 WRITE   4510045\n0x4022E140 WRITE   4510047\n0x401C7680 WRITE   4510131\n0x4022E300 WRITE   4510510\n0x4022E2C0 WRITE   4510512\n0x4022E280 WRITE   4510519\n0x4022E240 WRITE   4510521\n0x401B3E00 WRITE   4510554\n0x4022E380 WRITE   4511017\n0x4022E340 WRITE   4511019\n0x401C76C0 WRITE   4511103\n0x4022E600 WRITE   4511514\n0x4022E5C0 WRITE   4511516\n0x4022E500 WRITE   4511523\n0x4022E4C0 WRITE   4511525\n0x4022E480 WRITE   4511535\n0x4022E440 WRITE   4511537\n0x401B3E40 WRITE   4511564\n0x4022E580 WRITE   4512005\n0x4022E540 WRITE   4512007\n0x401C7700 WRITE   4512091\n0x4022E700 WRITE   4512479\n0x4022E6C0 WRITE   4512481\n0x4022E680 WRITE   4512488\n0x4022E640 WRITE   4512490\n0x401B3E80 WRITE   4512523\n0x4022E780 WRITE   4512996\n0x4022E740 WRITE   4512998\n0x401C7740 WRITE   4513082\n0x4022EC00 WRITE   4513508\n0x4022EBC0 WRITE   4513510\n0x4022EA00 WRITE   4513517\n0x4022E9C0 WRITE   4513519\n0x4022E900 WRITE   4513529\n0x4022E8C0 WRITE   4513531\n0x4022E880 WRITE   4513536\n0x4022E840 WRITE   4513539\n0x401B3EC0 WRITE   4513564\n0x4022E980 WRITE   4514003\n0x4022E940 WRITE   4514005\n0x401C7780 WRITE   4514089\n0x4022EB00 WRITE   4514475\n0x4022EAC0 WRITE   4514477\n0x4022EA80 WRITE   4514484\n0x4022EA40 WRITE   4514486\n0x401B3F00 WRITE   4514519\n0x4022EB80 WRITE   4514990\n0x4022EB40 WRITE   4514992\n0x401C77C0 WRITE   4515076\n0x4022EE00 WRITE   4515495\n0x4022EDC0 WRITE   4515497\n0x4022ED00 WRITE   4515504\n0x4022ECC0 WRITE   4515506\n0x4022EC80 WRITE   4515516\n0x4022EC40 WRITE   4515518\n0x401B3F40 WRITE   4515545\n0x4022ED80 WRITE   4515993\n0x4022ED40 WRITE   4515995\n0x401C7800 WRITE   4516079\n0x4022EF00 WRITE   4516474\n0x4022EEC0 WRITE   4516476\n0x4022EE80 WRITE   4516483\n0x4022EE40 WRITE   4516485\n0x401B3F80 WRITE   4516518\n0x4022EF80 WRITE   4516998\n0x4022EF40 WRITE   4517000\n0x401C7840 WRITE   4517084\n0x4022F800 WRITE   4517516\n0x4022F7C0 WRITE   4517518\n0x4022F400 WRITE   4517525\n0x4022F3C0 WRITE   4517527\n0x4022F200 WRITE   4517537\n0x4022F1C0 WRITE   4517539\n0x4022F100 WRITE   4517544\n0x4022F0C0 WRITE   4517547\n0x4022F080 WRITE   4517550\n0x4022F040 WRITE   4517553\n0x401B3FC0 WRITE   4517578\n0x4022F180 WRITE   4518009\n0x4022F140 WRITE   4518011\n0x401C7880 WRITE   4518095\n0x4022F300 WRITE   4518479\n0x4022F2C0 WRITE   4518481\n0x4022F280 WRITE   4518488\n0x4022F240 WRITE   4518490\n0x401B4000 WRITE   4518523\n0x4022F380 WRITE   4518986\n0x4022F340 WRITE   4518988\n0x401C78C0 WRITE   4519072\n0x4022F600 WRITE   4519489\n0x4022F5C0 WRITE   4519491\n0x4022F500 WRITE   4519498\n0x4022F4C0 WRITE   4519500\n0x4022F480 WRITE   4519510\n0x4022F440 WRITE   4519512\n0x401B4040 WRITE   4519539\n0x4022F580 WRITE   4519980\n0x4022F540 WRITE   4519982\n0x401C7900 WRITE   4520066\n0x4022F700 WRITE   4520460\n0x4022F6C0 WRITE   4520462\n0x4022F680 WRITE   4520469\n0x4022F640 WRITE   4520471\n0x401B4080 WRITE   4520504\n0x4022F780 WRITE   4520977\n0x4022F740 WRITE   4520979\n0x401C7940 WRITE   4521063\n0x4022FC00 WRITE   4521495\n0x4022FBC0 WRITE   4521497\n0x4022FA00 WRITE   4521504\n0x4022F9C0 WRITE   4521506\n0x4022F900 WRITE   4521516\n0x4022F8C0 WRITE   4521518\n0x4022F880 WRITE   4521523\n0x4022F840 WRITE   4521526\n0x401B40C0 WRITE   4521551\n0x4022F980 WRITE   4521990\n0x4022F940 WRITE   4521992\n0x401C7980 WRITE   4522076\n0x4022FB00 WRITE   4522468\n0x4022FAC0 WRITE   4522470\n0x4022FA80 WRITE   4522477\n0x4022FA40 WRITE   4522479\n0x401B4100 WRITE   4522512\n0x4022FB80 WRITE   4522983\n0x4022FB40 WRITE   4522985\n0x401C79C0 WRITE   4523069\n0x4022FE00 WRITE   4523494\n0x4022FDC0 WRITE   4523496\n0x4022FD00 WRITE   4523503\n0x4022FCC0 WRITE   4523505\n0x4022FC80 WRITE   4523515\n0x4022FC40 WRITE   4523517\n0x401B4140 WRITE   4523544\n0x4022FD80 WRITE   4523992\n0x4022FD40 WRITE   4523994\n0x401C7A00 WRITE   4524078\n0x4022FF00 WRITE   4524479\n0x4022FEC0 WRITE   4524481\n0x4022FE80 WRITE   4524488\n0x4022FE40 WRITE   4524490\n0x401B4180 WRITE   4524523\n0x4022FF80 WRITE   4525003\n0x4022FF40 WRITE   4525005\n0x401C7A40 WRITE   4525089\n0x40231FC0 WRITE   4525573\n0x40232000 WRITE   4525607\n0x40231000 WRITE   4525719\n0x40230FC0 WRITE   4525721\n0x40230800 WRITE   4525728\n0x402307C0 WRITE   4525730\n0x40230400 WRITE   4525740\n0x402303C0 WRITE   4525742\n0x40230200 WRITE   4525747\n0x402301C0 WRITE   4525750\n0x40230100 WRITE   4525753\n0x402300C0 WRITE   4525756\n0x40230080 WRITE   4525759\n0x40230040 WRITE   4525762\n0x401B41C0 WRITE   4525795\n0x40230180 WRITE   4526225\n0x40230140 WRITE   4526227\n0x401C7A80 WRITE   4526311\n0x40230300 WRITE   4526690\n0x402302C0 WRITE   4526692\n0x40230280 WRITE   4526699\n0x40230240 WRITE   4526701\n0x401B4200 WRITE   4526734\n0x40230380 WRITE   4527197\n0x40230340 WRITE   4527199\n0x401C7AC0 WRITE   4527283\n0x40230600 WRITE   4527694\n0x402305C0 WRITE   4527696\n0x40230500 WRITE   4527703\n0x402304C0 WRITE   4527705\n0x40230480 WRITE   4527715\n0x40230440 WRITE   4527717\n0x401B4240 WRITE   4527744\n0x40230580 WRITE   4528185\n0x40230540 WRITE   4528187\n0x401C7B00 WRITE   4528271\n0x40230700 WRITE   4528659\n0x402306C0 WRITE   4528661\n0x40230680 WRITE   4528668\n0x40230640 WRITE   4528670\n0x401B4280 WRITE   4528703\n0x40230780 WRITE   4529176\n0x40230740 WRITE   4529178\n0x401C7B40 WRITE   4529262\n0x40230C00 WRITE   4529688\n0x40230BC0 WRITE   4529690\n0x40230A00 WRITE   4529697\n0x402309C0 WRITE   4529699\n0x40230900 WRITE   4529709\n0x402308C0 WRITE   4529711\n0x40230880 WRITE   4529716\n0x40230840 WRITE   4529719\n0x401B42C0 WRITE   4529744\n0x40230980 WRITE   4530183\n0x40230940 WRITE   4530185\n0x401C7B80 WRITE   4530269\n0x40230B00 WRITE   4530655\n0x40230AC0 WRITE   4530657\n0x40230A80 WRITE   4530664\n0x40230A40 WRITE   4530666\n0x401B4300 WRITE   4530699\n0x40230B80 WRITE   4531170\n0x40230B40 WRITE   4531172\n0x401C7BC0 WRITE   4531256\n0x40230E00 WRITE   4531675\n0x40230DC0 WRITE   4531677\n0x40230D00 WRITE   4531684\n0x40230CC0 WRITE   4531686\n0x40230C80 WRITE   4531696\n0x40230C40 WRITE   4531698\n0x401B4340 WRITE   4531725\n0x40230D80 WRITE   4532173\n0x40230D40 WRITE   4532175\n0x401C7C00 WRITE   4532259\n0x40230F00 WRITE   4532654\n0x40230EC0 WRITE   4532656\n0x40230E80 WRITE   4532663\n0x40230E40 WRITE   4532665\n0x401B4380 WRITE   4532698\n0x40230F80 WRITE   4533178\n0x40230F40 WRITE   4533180\n0x401C7C40 WRITE   4533264\n0x40231800 WRITE   4533696\n0x402317C0 WRITE   4533698\n0x40231400 WRITE   4533705\n0x402313C0 WRITE   4533707\n0x40231200 WRITE   4533717\n0x402311C0 WRITE   4533719\n0x40231100 WRITE   4533724\n0x402310C0 WRITE   4533727\n0x40231080 WRITE   4533730\n0x40231040 WRITE   4533733\n0x401B43C0 WRITE   4533758\n0x40231180 WRITE   4534189\n0x40231140 WRITE   4534191\n0x401C7C80 WRITE   4534275\n0x40231300 WRITE   4534659\n0x402312C0 WRITE   4534661\n0x40231280 WRITE   4534668\n0x40231240 WRITE   4534670\n0x401B4400 WRITE   4534703\n0x40231380 WRITE   4535166\n0x40231340 WRITE   4535168\n0x401C7CC0 WRITE   4535252\n0x40231600 WRITE   4535669\n0x402315C0 WRITE   4535671\n0x40231500 WRITE   4535678\n0x402314C0 WRITE   4535680\n0x40231480 WRITE   4535690\n0x40231440 WRITE   4535692\n0x401B4440 WRITE   4535719\n0x40231580 WRITE   4536160\n0x40231540 WRITE   4536162\n0x401C7D00 WRITE   4536246\n0x40231700 WRITE   4536640\n0x402316C0 WRITE   4536642\n0x40231680 WRITE   4536649\n0x40231640 WRITE   4536651\n0x401B4480 WRITE   4536684\n0x40231780 WRITE   4537157\n0x40231740 WRITE   4537159\n0x401C7D40 WRITE   4537243\n0x40231C00 WRITE   4537675\n0x40231BC0 WRITE   4537677\n0x40231A00 WRITE   4537684\n0x402319C0 WRITE   4537686\n0x40231900 WRITE   4537696\n0x402318C0 WRITE   4537698\n0x40231880 WRITE   4537703\n0x40231840 WRITE   4537706\n0x401B44C0 WRITE   4537731\n0x40231980 WRITE   4538170\n0x40231940 WRITE   4538172\n0x401C7D80 WRITE   4538256\n0x40231B00 WRITE   4538648\n0x40231AC0 WRITE   4538650\n0x40231A80 WRITE   4538657\n0x40231A40 WRITE   4538659\n0x401B4500 WRITE   4538692\n0x40231B80 WRITE   4539163\n0x40231B40 WRITE   4539165\n0x401C7DC0 WRITE   4539249\n0x40231E00 WRITE   4539674\n0x40231DC0 WRITE   4539676\n0x40231D00 WRITE   4539683\n0x40231CC0 WRITE   4539685\n0x40231C80 WRITE   4539695\n0x40231C40 WRITE   4539697\n0x401B4540 WRITE   4539724\n0x40231D80 WRITE   4540172\n0x40231D40 WRITE   4540174\n0x401C7E00 WRITE   4540258\n0x40231F00 WRITE   4540659\n0x40231EC0 WRITE   4540661\n0x40231E80 WRITE   4540668\n0x40231E40 WRITE   4540670\n0x401B4580 WRITE   4540703\n0x40231F80 WRITE   4541183\n0x40231F40 WRITE   4541185\n0x401C7E40 WRITE   4541269\n0x40233FC0 WRITE   4541753\n0x40234000 WRITE   4541793\n0x40233000 WRITE   4541938\n0x40232FC0 WRITE   4541940\n0x40232800 WRITE   4541947\n0x402327C0 WRITE   4541949\n0x40232400 WRITE   4541959\n0x402323C0 WRITE   4541961\n0x40232200 WRITE   4541966\n0x402321C0 WRITE   4541969\n0x40232100 WRITE   4541972\n0x402320C0 WRITE   4541975\n0x40232080 WRITE   4541978\n0x40232040 WRITE   4541981\n0x401B45C0 WRITE   4542014\n0x40232180 WRITE   4542444\n0x40232140 WRITE   4542446\n0x401C7E80 WRITE   4542530\n0x40232300 WRITE   4542909\n0x402322C0 WRITE   4542911\n0x40232280 WRITE   4542918\n0x40232240 WRITE   4542920\n0x401B4600 WRITE   4542953\n0x40232380 WRITE   4543416\n0x40232340 WRITE   4543418\n0x401C7EC0 WRITE   4543502\n0x40232600 WRITE   4543913\n0x402325C0 WRITE   4543915\n0x40232500 WRITE   4543922\n0x402324C0 WRITE   4543924\n0x40232480 WRITE   4543934\n0x40232440 WRITE   4543936\n0x401B4640 WRITE   4543963\n0x40232580 WRITE   4544404\n0x40232540 WRITE   4544406\n0x401C7F00 WRITE   4544490\n0x40232700 WRITE   4544878\n0x402326C0 WRITE   4544880\n0x40232680 WRITE   4544887\n0x40232640 WRITE   4544889\n0x401B4680 WRITE   4544922\n0x40232780 WRITE   4545395\n0x40232740 WRITE   4545397\n0x401C7F40 WRITE   4545481\n0x40232C00 WRITE   4545907\n0x40232BC0 WRITE   4545909\n0x40232A00 WRITE   4545916\n0x402329C0 WRITE   4545918\n0x40232900 WRITE   4545928\n0x402328C0 WRITE   4545930\n0x40232880 WRITE   4545935\n0x40232840 WRITE   4545938\n0x401B46C0 WRITE   4545963\n0x40232980 WRITE   4546402\n0x40232940 WRITE   4546404\n0x401C7F80 WRITE   4546488\n0x40232B00 WRITE   4546874\n0x40232AC0 WRITE   4546876\n0x40232A80 WRITE   4546883\n0x40232A40 WRITE   4546885\n0x401B4700 WRITE   4546918\n0x40232B80 WRITE   4547389\n0x40232B40 WRITE   4547391\n0x401C7FC0 WRITE   4547475\n0x40232E00 WRITE   4547894\n0x40232DC0 WRITE   4547896\n0x40232D00 WRITE   4547903\n0x40232CC0 WRITE   4547905\n0x40232C80 WRITE   4547915\n0x40232C40 WRITE   4547917\n0x401B4740 WRITE   4547944\n0x40232D80 WRITE   4548392\n0x40232D40 WRITE   4548394\n0x401C8000 WRITE   4548478\n0x40232F00 WRITE   4548873\n0x40232EC0 WRITE   4548875\n0x40232E80 WRITE   4548882\n0x40232E40 WRITE   4548884\n0x401B4780 WRITE   4548917\n0x40232F80 WRITE   4549397\n0x40232F40 WRITE   4549399\n0x401C8040 WRITE   4549483\n0x40233800 WRITE   4549915\n0x402337C0 WRITE   4549917\n0x40233400 WRITE   4549924\n0x402333C0 WRITE   4549926\n0x40233200 WRITE   4549936\n0x402331C0 WRITE   4549938\n0x40233100 WRITE   4549943\n0x402330C0 WRITE   4549946\n0x40233080 WRITE   4549949\n0x40233040 WRITE   4549952\n0x401B47C0 WRITE   4549977\n0x40233180 WRITE   4550408\n0x40233140 WRITE   4550410\n0x401C8080 WRITE   4550494\n0x40233300 WRITE   4550878\n0x402332C0 WRITE   4550880\n0x40233280 WRITE   4550887\n0x40233240 WRITE   4550889\n0x401B4800 WRITE   4550922\n0x40233380 WRITE   4551385\n0x40233340 WRITE   4551387\n0x401C80C0 WRITE   4551471\n0x40233600 WRITE   4551888\n0x402335C0 WRITE   4551890\n0x40233500 WRITE   4551897\n0x402334C0 WRITE   4551899\n0x40233480 WRITE   4551909\n0x40233440 WRITE   4551911\n0x401B4840 WRITE   4551938\n0x40233580 WRITE   4552379\n0x40233540 WRITE   4552381\n0x401C8100 WRITE   4552465\n0x40233700 WRITE   4552859\n0x402336C0 WRITE   4552861\n0x40233680 WRITE   4552868\n0x40233640 WRITE   4552870\n0x401B4880 WRITE   4552903\n0x40233780 WRITE   4553376\n0x40233740 WRITE   4553378\n0x401C8140 WRITE   4553462\n0x40233C00 WRITE   4553894\n0x40233BC0 WRITE   4553896\n0x40233A00 WRITE   4553903\n0x402339C0 WRITE   4553905\n0x40233900 WRITE   4553915\n0x402338C0 WRITE   4553917\n0x40233880 WRITE   4553922\n0x40233840 WRITE   4553925\n0x401B48C0 WRITE   4553950\n0x40233980 WRITE   4554389\n0x40233940 WRITE   4554391\n0x401C8180 WRITE   4554475\n0x40233B00 WRITE   4554867\n0x40233AC0 WRITE   4554869\n0x40233A80 WRITE   4554876\n0x40233A40 WRITE   4554878\n0x401B4900 WRITE   4554911\n0x40233B80 WRITE   4555382\n0x40233B40 WRITE   4555384\n0x401C81C0 WRITE   4555468\n0x40233E00 WRITE   4555893\n0x40233DC0 WRITE   4555895\n0x40233D00 WRITE   4555902\n0x40233CC0 WRITE   4555904\n0x40233C80 WRITE   4555914\n0x40233C40 WRITE   4555916\n0x401B4940 WRITE   4555943\n0x40233D80 WRITE   4556391\n0x40233D40 WRITE   4556393\n0x401C8200 WRITE   4556477\n0x40233F00 WRITE   4556878\n0x40233EC0 WRITE   4556880\n0x40233E80 WRITE   4556887\n0x40233E40 WRITE   4556889\n0x401B4980 WRITE   4556922\n0x40233F80 WRITE   4557402\n0x40233F40 WRITE   4557404\n0x401C8240 WRITE   4557488\n0x40234880 WRITE   4558143\n0x40235FC0 WRITE   4558274\n0x40236000 WRITE   4558308\n0x40235000 WRITE   4558478\n0x40234FC0 WRITE   4558480\n0x40234800 WRITE   4558487\n0x402347C0 WRITE   4558489\n0x40234400 WRITE   4558499\n0x402343C0 WRITE   4558501\n0x40234200 WRITE   4558506\n0x402341C0 WRITE   4558509\n0x40234100 WRITE   4558512\n0x402340C0 WRITE   4558515\n0x40234080 WRITE   4558518\n0x40234040 WRITE   4558521\n0x401B49C0 WRITE   4558554\n0x40234180 WRITE   4558989\n0x40234140 WRITE   4558991\n0x401C8280 WRITE   4559075\n0x40234300 WRITE   4559454\n0x402342C0 WRITE   4559456\n0x40234280 WRITE   4559463\n0x40234240 WRITE   4559465\n0x401B4A00 WRITE   4559498\n0x40234380 WRITE   4559961\n0x40234340 WRITE   4559963\n0x401C82C0 WRITE   4560047\n0x40234600 WRITE   4560458\n0x402345C0 WRITE   4560460\n0x40234500 WRITE   4560467\n0x402344C0 WRITE   4560469\n0x40234480 WRITE   4560479\n0x40234440 WRITE   4560481\n0x401B4A40 WRITE   4560508\n0x40234580 WRITE   4560949\n0x40234540 WRITE   4560951\n0x401C8300 WRITE   4561035\n0x40234700 WRITE   4561423\n0x402346C0 WRITE   4561425\n0x40234680 WRITE   4561432\n0x40234640 WRITE   4561434\n0x401B4A80 WRITE   4561467\n0x40234780 WRITE   4561940\n0x40234740 WRITE   4561942\n0x401C8340 WRITE   4562026\n0x40234C00 WRITE   4562452\n0x40234BC0 WRITE   4562454\n0x40234A00 WRITE   4562461\n0x402349C0 WRITE   4562463\n0x40234900 WRITE   4562473\n0x402348C0 WRITE   4562475\n0x40234840 WRITE   4562483\n0x401B4AC0 WRITE   4562508\n0x40234980 WRITE   4562947\n0x40234940 WRITE   4562949\n0x401C8380 WRITE   4563033\n0x40234B00 WRITE   4563419\n0x40234AC0 WRITE   4563421\n0x40234A80 WRITE   4563428\n0x40234A40 WRITE   4563430\n0x401B4B00 WRITE   4563463\n0x40234B80 WRITE   4563934\n0x40234B40 WRITE   4563936\n0x401C83C0 WRITE   4564020\n0x40234E00 WRITE   4564439\n0x40234DC0 WRITE   4564441\n0x40234D00 WRITE   4564448\n0x40234CC0 WRITE   4564450\n0x40234C80 WRITE   4564460\n0x40234C40 WRITE   4564462\n0x401B4B40 WRITE   4564489\n0x40234D80 WRITE   4564937\n0x40234D40 WRITE   4564939\n0x401C8400 WRITE   4565023\n0x40234F00 WRITE   4565418\n0x40234EC0 WRITE   4565420\n0x40234E80 WRITE   4565427\n0x40234E40 WRITE   4565429\n0x401B4B80 WRITE   4565462\n0x40234F80 WRITE   4565942\n0x40234F40 WRITE   4565944\n0x401C8440 WRITE   4566028\n0x40235800 WRITE   4566460\n0x402357C0 WRITE   4566462\n0x40235400 WRITE   4566469\n0x402353C0 WRITE   4566471\n0x40235200 WRITE   4566481\n0x402351C0 WRITE   4566483\n0x40235100 WRITE   4566488\n0x402350C0 WRITE   4566491\n0x40235080 WRITE   4566494\n0x40235040 WRITE   4566497\n0x401B4BC0 WRITE   4566522\n0x40235180 WRITE   4566953\n0x40235140 WRITE   4566955\n0x401C8480 WRITE   4567039\n0x40235300 WRITE   4567423\n0x402352C0 WRITE   4567425\n0x40235280 WRITE   4567432\n0x40235240 WRITE   4567434\n0x401B4C00 WRITE   4567467\n0x40235380 WRITE   4567930\n0x40235340 WRITE   4567932\n0x401C84C0 WRITE   4568016\n0x40235600 WRITE   4568433\n0x402355C0 WRITE   4568435\n0x40235500 WRITE   4568442\n0x402354C0 WRITE   4568444\n0x40235480 WRITE   4568454\n0x40235440 WRITE   4568456\n0x401B4C40 WRITE   4568483\n0x40235580 WRITE   4568924\n0x40235540 WRITE   4568926\n0x401C8500 WRITE   4569010\n0x40235700 WRITE   4569404\n0x402356C0 WRITE   4569406\n0x40235680 WRITE   4569413\n0x40235640 WRITE   4569415\n0x401B4C80 WRITE   4569448\n0x40235780 WRITE   4569921\n0x40235740 WRITE   4569923\n0x401C8540 WRITE   4570007\n0x40235C00 WRITE   4570439\n0x40235BC0 WRITE   4570441\n0x40235A00 WRITE   4570448\n0x402359C0 WRITE   4570450\n0x40235900 WRITE   4570460\n0x402358C0 WRITE   4570462\n0x40235880 WRITE   4570467\n0x40235840 WRITE   4570470\n0x401B4CC0 WRITE   4570495\n0x40235980 WRITE   4570934\n0x40235940 WRITE   4570936\n0x401C8580 WRITE   4571020\n0x40235B00 WRITE   4571412\n0x40235AC0 WRITE   4571414\n0x40235A80 WRITE   4571421\n0x40235A40 WRITE   4571423\n0x401B4D00 WRITE   4571456\n0x40235B80 WRITE   4571927\n0x40235B40 WRITE   4571929\n0x401C85C0 WRITE   4572013\n0x40235E00 WRITE   4572438\n0x40235DC0 WRITE   4572440\n0x40235D00 WRITE   4572447\n0x40235CC0 WRITE   4572449\n0x40235C80 WRITE   4572459\n0x40235C40 WRITE   4572461\n0x401B4D40 WRITE   4572488\n0x40235D80 WRITE   4572936\n0x40235D40 WRITE   4572938\n0x401C8600 WRITE   4573022\n0x40235F00 WRITE   4573423\n0x40235EC0 WRITE   4573425\n0x40235E80 WRITE   4573432\n0x40235E40 WRITE   4573434\n0x401B4D80 WRITE   4573467\n0x40235F80 WRITE   4573947\n0x40235F40 WRITE   4573949\n0x401C8640 WRITE   4574033\n0x40237FC0 WRITE   4574517\n0x40238000 WRITE   4574551\n0x40237000 WRITE   4574670\n0x40236FC0 WRITE   4574672\n0x40236800 WRITE   4574679\n0x402367C0 WRITE   4574681\n0x40236400 WRITE   4574691\n0x402363C0 WRITE   4574693\n0x40236200 WRITE   4574698\n0x402361C0 WRITE   4574701\n0x40236100 WRITE   4574704\n0x402360C0 WRITE   4574707\n0x40236080 WRITE   4574710\n0x40236040 WRITE   4574713\n0x401B4DC0 WRITE   4574746\n0x40236180 WRITE   4575176\n0x40236140 WRITE   4575178\n0x401C8680 WRITE   4575262\n0x40236300 WRITE   4575641\n0x402362C0 WRITE   4575643\n0x40236280 WRITE   4575650\n0x40236240 WRITE   4575652\n0x401B4E00 WRITE   4575685\n0x40236380 WRITE   4576148\n0x40236340 WRITE   4576150\n0x401C86C0 WRITE   4576234\n0x40236600 WRITE   4576645\n0x402365C0 WRITE   4576647\n0x40236500 WRITE   4576654\n0x402364C0 WRITE   4576656\n0x40236480 WRITE   4576666\n0x40236440 WRITE   4576668\n0x401B4E40 WRITE   4576695\n0x40236580 WRITE   4577136\n0x40236540 WRITE   4577138\n0x401C8700 WRITE   4577222\n0x40236700 WRITE   4577610\n0x402366C0 WRITE   4577612\n0x40236680 WRITE   4577619\n0x40236640 WRITE   4577621\n0x401B4E80 WRITE   4577654\n0x40236780 WRITE   4578127\n0x40236740 WRITE   4578129\n0x401C8740 WRITE   4578213\n0x40236C00 WRITE   4578639\n0x40236BC0 WRITE   4578641\n0x40236A00 WRITE   4578648\n0x402369C0 WRITE   4578650\n0x40236900 WRITE   4578660\n0x402368C0 WRITE   4578662\n0x40236880 WRITE   4578667\n0x40236840 WRITE   4578670\n0x401B4EC0 WRITE   4578695\n0x40236980 WRITE   4579134\n0x40236940 WRITE   4579136\n0x401C8780 WRITE   4579220\n0x40236B00 WRITE   4579606\n0x40236AC0 WRITE   4579608\n0x40236A80 WRITE   4579615\n0x40236A40 WRITE   4579617\n0x401B4F00 WRITE   4579650\n0x40236B80 WRITE   4580121\n0x40236B40 WRITE   4580123\n0x401C87C0 WRITE   4580207\n0x40236E00 WRITE   4580626\n0x40236DC0 WRITE   4580628\n0x40236D00 WRITE   4580635\n0x40236CC0 WRITE   4580637\n0x40236C80 WRITE   4580647\n0x40236C40 WRITE   4580649\n0x401B4F40 WRITE   4580676\n0x40236D80 WRITE   4581124\n0x40236D40 WRITE   4581126\n0x401C8800 WRITE   4581210\n0x40236F00 WRITE   4581605\n0x40236EC0 WRITE   4581607\n0x40236E80 WRITE   4581614\n0x40236E40 WRITE   4581616\n0x401B4F80 WRITE   4581649\n0x40236F80 WRITE   4582129\n0x40236F40 WRITE   4582131\n0x401C8840 WRITE   4582215\n0x40237800 WRITE   4582647\n0x402377C0 WRITE   4582649\n0x40237400 WRITE   4582656\n0x402373C0 WRITE   4582658\n0x40237200 WRITE   4582668\n0x402371C0 WRITE   4582670\n0x40237100 WRITE   4582675\n0x402370C0 WRITE   4582678\n0x40237080 WRITE   4582681\n0x40237040 WRITE   4582684\n0x401B4FC0 WRITE   4582709\n0x40237180 WRITE   4583140\n0x40237140 WRITE   4583142\n0x401C8880 WRITE   4583226\n0x40237300 WRITE   4583610\n0x402372C0 WRITE   4583612\n0x40237280 WRITE   4583619\n0x40237240 WRITE   4583621\n0x401B5000 WRITE   4583654\n0x40237380 WRITE   4584117\n0x40237340 WRITE   4584119\n0x401C88C0 WRITE   4584203\n0x40237600 WRITE   4584620\n0x402375C0 WRITE   4584622\n0x40237500 WRITE   4584629\n0x402374C0 WRITE   4584631\n0x40237480 WRITE   4584641\n0x40237440 WRITE   4584643\n0x401B5040 WRITE   4584670\n0x40237580 WRITE   4585111\n0x40237540 WRITE   4585113\n0x401C8900 WRITE   4585197\n0x40237700 WRITE   4585591\n0x402376C0 WRITE   4585593\n0x40237680 WRITE   4585600\n0x40237640 WRITE   4585602\n0x401B5080 WRITE   4585635\n0x40237780 WRITE   4586108\n0x40237740 WRITE   4586110\n0x401C8940 WRITE   4586194\n0x40237C00 WRITE   4586626\n0x40237BC0 WRITE   4586628\n0x40237A00 WRITE   4586635\n0x402379C0 WRITE   4586637\n0x40237900 WRITE   4586647\n0x402378C0 WRITE   4586649\n0x40237880 WRITE   4586654\n0x40237840 WRITE   4586657\n0x401B50C0 WRITE   4586682\n0x40237980 WRITE   4587121\n0x40237940 WRITE   4587123\n0x401C8980 WRITE   4587207\n0x40237B00 WRITE   4587599\n0x40237AC0 WRITE   4587601\n0x40237A80 WRITE   4587608\n0x40237A40 WRITE   4587610\n0x401B5100 WRITE   4587643\n0x40237B80 WRITE   4588114\n0x40237B40 WRITE   4588116\n0x401C89C0 WRITE   4588200\n0x40237E00 WRITE   4588625\n0x40237DC0 WRITE   4588627\n0x40237D00 WRITE   4588634\n0x40237CC0 WRITE   4588636\n0x40237C80 WRITE   4588646\n0x40237C40 WRITE   4588648\n0x401B5140 WRITE   4588675\n0x40237D80 WRITE   4589123\n0x40237D40 WRITE   4589125\n0x401C8A00 WRITE   4589209\n0x40237F00 WRITE   4589610\n0x40237EC0 WRITE   4589612\n0x40237E80 WRITE   4589619\n0x40237E40 WRITE   4589621\n0x401B5180 WRITE   4589654\n0x40237F80 WRITE   4590134\n0x40237F40 WRITE   4590136\n0x401C8A40 WRITE   4590220\n0x40239FC0 WRITE   4590704\n0x4023A000 WRITE   4590738\n0x40239000 WRITE   4590866\n0x40238FC0 WRITE   4590868\n0x40238800 WRITE   4590875\n0x402387C0 WRITE   4590877\n0x40238400 WRITE   4590887\n0x402383C0 WRITE   4590889\n0x40238200 WRITE   4590894\n0x402381C0 WRITE   4590897\n0x40238100 WRITE   4590900\n0x402380C0 WRITE   4590903\n0x40238080 WRITE   4590906\n0x40238040 WRITE   4590909\n0x401B51C0 WRITE   4590942\n0x40238180 WRITE   4591372\n0x40238140 WRITE   4591374\n0x401C8A80 WRITE   4591458\n0x40238300 WRITE   4591837\n0x402382C0 WRITE   4591839\n0x40238280 WRITE   4591846\n0x40238240 WRITE   4591848\n0x401B5200 WRITE   4591881\n0x40238380 WRITE   4592344\n0x40238340 WRITE   4592346\n0x401C8AC0 WRITE   4592430\n0x40238600 WRITE   4592841\n0x402385C0 WRITE   4592843\n0x40238500 WRITE   4592850\n0x402384C0 WRITE   4592852\n0x40238480 WRITE   4592862\n0x40238440 WRITE   4592864\n0x401B5240 WRITE   4592891\n0x40238580 WRITE   4593332\n0x40238540 WRITE   4593334\n0x401C8B00 WRITE   4593418\n0x40238700 WRITE   4593806\n0x402386C0 WRITE   4593808\n0x40238680 WRITE   4593815\n0x40238640 WRITE   4593817\n0x401B5280 WRITE   4593850\n0x40238780 WRITE   4594323\n0x40238740 WRITE   4594325\n0x401C8B40 WRITE   4594409\n0x40238C00 WRITE   4594835\n0x40238BC0 WRITE   4594837\n0x40238A00 WRITE   4594844\n0x402389C0 WRITE   4594846\n0x40238900 WRITE   4594856\n0x402388C0 WRITE   4594858\n0x40238880 WRITE   4594863\n0x40238840 WRITE   4594866\n0x401B52C0 WRITE   4594891\n0x40238980 WRITE   4595330\n0x40238940 WRITE   4595332\n0x401C8B80 WRITE   4595416\n0x40238B00 WRITE   4595802\n0x40238AC0 WRITE   4595804\n0x40238A80 WRITE   4595811\n0x40238A40 WRITE   4595813\n0x401B5300 WRITE   4595846\n0x40238B80 WRITE   4596317\n0x40238B40 WRITE   4596319\n0x401C8BC0 WRITE   4596403\n0x40238E00 WRITE   4596822\n0x40238DC0 WRITE   4596824\n0x40238D00 WRITE   4596831\n0x40238CC0 WRITE   4596833\n0x40238C80 WRITE   4596843\n0x40238C40 WRITE   4596845\n0x401B5340 WRITE   4596872\n0x40238D80 WRITE   4597320\n0x40238D40 WRITE   4597322\n0x401C8C00 WRITE   4597406\n0x40238F00 WRITE   4597801\n0x40238EC0 WRITE   4597803\n0x40238E80 WRITE   4597810\n0x40238E40 WRITE   4597812\n0x401B5380 WRITE   4597845\n0x40238F80 WRITE   4598325\n0x40238F40 WRITE   4598327\n0x401C8C40 WRITE   4598411\n0x40239800 WRITE   4598843\n0x402397C0 WRITE   4598845\n0x40239400 WRITE   4598852\n0x402393C0 WRITE   4598854\n0x40239200 WRITE   4598864\n0x402391C0 WRITE   4598866\n0x40239100 WRITE   4598871\n0x402390C0 WRITE   4598874\n0x40239080 WRITE   4598877\n0x40239040 WRITE   4598880\n0x401B53C0 WRITE   4598905\n0x40239180 WRITE   4599336\n0x40239140 WRITE   4599338\n0x401C8C80 WRITE   4599422\n0x40239300 WRITE   4599806\n0x402392C0 WRITE   4599808\n0x40239280 WRITE   4599815\n0x40239240 WRITE   4599817\n0x401B5400 WRITE   4599850\n0x40239380 WRITE   4600313\n0x40239340 WRITE   4600315\n0x401C8CC0 WRITE   4600399\n0x40239600 WRITE   4600816\n0x402395C0 WRITE   4600818\n0x40239500 WRITE   4600825\n0x402394C0 WRITE   4600827\n0x40239480 WRITE   4600837\n0x40239440 WRITE   4600839\n0x401B5440 WRITE   4600866\n0x40239580 WRITE   4601307\n0x40239540 WRITE   4601309\n0x401C8D00 WRITE   4601393\n0x40239700 WRITE   4601787\n0x402396C0 WRITE   4601789\n0x40239680 WRITE   4601796\n0x40239640 WRITE   4601798\n0x401B5480 WRITE   4601831\n0x40239780 WRITE   4602304\n0x40239740 WRITE   4602306\n0x401C8D40 WRITE   4602390\n0x40239C00 WRITE   4602822\n0x40239BC0 WRITE   4602824\n0x40239A00 WRITE   4602831\n0x402399C0 WRITE   4602833\n0x40239900 WRITE   4602843\n0x402398C0 WRITE   4602845\n0x40239880 WRITE   4602850\n0x40239840 WRITE   4602853\n0x401B54C0 WRITE   4602878\n0x40239980 WRITE   4603317\n0x40239940 WRITE   4603319\n0x401C8D80 WRITE   4603403\n0x40239B00 WRITE   4603795\n0x40239AC0 WRITE   4603797\n0x40239A80 WRITE   4603804\n0x40239A40 WRITE   4603806\n0x401B5500 WRITE   4603839\n0x40239B80 WRITE   4604310\n0x40239B40 WRITE   4604312\n0x401C8DC0 WRITE   4604396\n0x40239E00 WRITE   4604821\n0x40239DC0 WRITE   4604823\n0x40239D00 WRITE   4604830\n0x40239CC0 WRITE   4604832\n0x40239C80 WRITE   4604842\n0x40239C40 WRITE   4604844\n0x401B5540 WRITE   4604871\n0x40239D80 WRITE   4605319\n0x40239D40 WRITE   4605321\n0x401C8E00 WRITE   4605405\n0x40239F00 WRITE   4605806\n0x40239EC0 WRITE   4605808\n0x40239E80 WRITE   4605815\n0x40239E40 WRITE   4605817\n0x401B5580 WRITE   4605850\n0x40239F80 WRITE   4606330\n0x40239F40 WRITE   4606332\n0x401C8E40 WRITE   4606416\n0x4023BFC0 WRITE   4606900\n0x4023C000 WRITE   4606934\n0x4023B000 WRITE   4607048\n0x4023AFC0 WRITE   4607050\n0x4023A800 WRITE   4607057\n0x4023A7C0 WRITE   4607059\n0x4023A400 WRITE   4607069\n0x4023A3C0 WRITE   4607071\n0x4023A200 WRITE   4607076\n0x4023A1C0 WRITE   4607079\n0x4023A100 WRITE   4607082\n0x4023A0C0 WRITE   4607085\n0x4023A080 WRITE   4607088\n0x4023A040 WRITE   4607091\n0x401B55C0 WRITE   4607124\n0x4023A180 WRITE   4607554\n0x4023A140 WRITE   4607556\n0x401C8E80 WRITE   4607640\n0x4023A300 WRITE   4608019\n0x4023A2C0 WRITE   4608021\n0x4023A280 WRITE   4608028\n0x4023A240 WRITE   4608030\n0x401B5600 WRITE   4608063\n0x4023A380 WRITE   4608526\n0x4023A340 WRITE   4608528\n0x401C8EC0 WRITE   4608612\n0x4023A600 WRITE   4609023\n0x4023A5C0 WRITE   4609025\n0x4023A500 WRITE   4609032\n0x4023A4C0 WRITE   4609034\n0x4023A480 WRITE   4609044\n0x4023A440 WRITE   4609046\n0x401B5640 WRITE   4609073\n0x4023A580 WRITE   4609514\n0x4023A540 WRITE   4609516\n0x401C8F00 WRITE   4609600\n0x4023A700 WRITE   4609988\n0x4023A6C0 WRITE   4609990\n0x4023A680 WRITE   4609997\n0x4023A640 WRITE   4609999\n0x401B5680 WRITE   4610032\n0x4023A780 WRITE   4610505\n0x4023A740 WRITE   4610507\n0x401C8F40 WRITE   4610591\n0x4023AC00 WRITE   4611017\n0x4023ABC0 WRITE   4611019\n0x4023AA00 WRITE   4611026\n0x4023A9C0 WRITE   4611028\n0x4023A900 WRITE   4611038\n0x4023A8C0 WRITE   4611040\n0x4023A880 WRITE   4611045\n0x4023A840 WRITE   4611048\n0x401B56C0 WRITE   4611073\n0x4023A980 WRITE   4611512\n0x4023A940 WRITE   4611514\n0x401C8F80 WRITE   4611598\n0x4023AB00 WRITE   4611984\n0x4023AAC0 WRITE   4611986\n0x4023AA80 WRITE   4611993\n0x4023AA40 WRITE   4611995\n0x401B5700 WRITE   4612028\n0x4023AB80 WRITE   4612499\n0x4023AB40 WRITE   4612501\n0x401C8FC0 WRITE   4612585\n0x4023AE00 WRITE   4613004\n0x4023ADC0 WRITE   4613006\n0x4023AD00 WRITE   4613013\n0x4023ACC0 WRITE   4613015\n0x4023AC80 WRITE   4613025\n0x4023AC40 WRITE   4613027\n0x401B5740 WRITE   4613054\n0x4023AD80 WRITE   4613502\n0x4023AD40 WRITE   4613504\n0x401C9000 WRITE   4613588\n0x4023AF00 WRITE   4613983\n0x4023AEC0 WRITE   4613985\n0x4023AE80 WRITE   4613992\n0x4023AE40 WRITE   4613994\n0x401B5780 WRITE   4614027\n0x4023AF80 WRITE   4614507\n0x4023AF40 WRITE   4614509\n0x401C9040 WRITE   4614593\n0x4023B800 WRITE   4615025\n0x4023B7C0 WRITE   4615027\n0x4023B400 WRITE   4615034\n0x4023B3C0 WRITE   4615036\n0x4023B200 WRITE   4615046\n0x4023B1C0 WRITE   4615048\n0x4023B100 WRITE   4615053\n0x4023B0C0 WRITE   4615056\n0x4023B080 WRITE   4615059\n0x4023B040 WRITE   4615062\n0x401B57C0 WRITE   4615087\n0x4023B180 WRITE   4615518\n0x4023B140 WRITE   4615520\n0x401C9080 WRITE   4615604\n0x4023B300 WRITE   4615988\n0x4023B2C0 WRITE   4615990\n0x4023B280 WRITE   4615997\n0x4023B240 WRITE   4615999\n0x401B5800 WRITE   4616032\n0x4023B380 WRITE   4616495\n0x4023B340 WRITE   4616497\n0x401C90C0 WRITE   4616581\n0x4023B600 WRITE   4616998\n0x4023B5C0 WRITE   4617000\n0x4023B500 WRITE   4617007\n0x4023B4C0 WRITE   4617009\n0x4023B480 WRITE   4617019\n0x4023B440 WRITE   4617021\n0x401B5840 WRITE   4617048\n0x4023B580 WRITE   4617489\n0x4023B540 WRITE   4617491\n0x401C9100 WRITE   4617575\n0x4023B700 WRITE   4617969\n0x4023B6C0 WRITE   4617971\n0x4023B680 WRITE   4617978\n0x4023B640 WRITE   4617980\n0x401B5880 WRITE   4618013\n0x4023B780 WRITE   4618486\n0x4023B740 WRITE   4618488\n0x401C9140 WRITE   4618572\n0x4023BC00 WRITE   4619004\n0x4023BBC0 WRITE   4619006\n0x4023BA00 WRITE   4619013\n0x4023B9C0 WRITE   4619015\n0x4023B900 WRITE   4619025\n0x4023B8C0 WRITE   4619027\n0x4023B880 WRITE   4619032\n0x4023B840 WRITE   4619035\n0x401B58C0 WRITE   4619060\n0x4023B980 WRITE   4619499\n0x4023B940 WRITE   4619501\n0x401C9180 WRITE   4619585\n0x4023BB00 WRITE   4619977\n0x4023BAC0 WRITE   4619979\n0x4023BA80 WRITE   4619986\n0x4023BA40 WRITE   4619988\n0x401B5900 WRITE   4620021\n0x4023BB80 WRITE   4620492\n0x4023BB40 WRITE   4620494\n0x401C91C0 WRITE   4620578\n0x4023BE00 WRITE   4621003\n0x4023BDC0 WRITE   4621005\n0x4023BD00 WRITE   4621012\n0x4023BCC0 WRITE   4621014\n0x4023BC80 WRITE   4621024\n0x4023BC40 WRITE   4621026\n0x401B5940 WRITE   4621053\n0x4023BD80 WRITE   4621501\n0x4023BD40 WRITE   4621503\n0x401C9200 WRITE   4621587\n0x4023BF00 WRITE   4621988\n0x4023BEC0 WRITE   4621990\n0x4023BE80 WRITE   4621997\n0x4023BE40 WRITE   4621999\n0x401B5980 WRITE   4622032\n0x4023BF80 WRITE   4622512\n0x4023BF40 WRITE   4622514\n0x401C9240 WRITE   4622598\n0x4023DFC0 WRITE   4623082\n0x4023E000 WRITE   4623116\n0x4023D000 WRITE   4623228\n0x4023CFC0 WRITE   4623230\n0x4023C800 WRITE   4623237\n0x4023C7C0 WRITE   4623239\n0x4023C400 WRITE   4623249\n0x4023C3C0 WRITE   4623251\n0x4023C200 WRITE   4623256\n0x4023C1C0 WRITE   4623259\n0x4023C100 WRITE   4623262\n0x4023C0C0 WRITE   4623265\n0x4023C080 WRITE   4623268\n0x4023C040 WRITE   4623271\n0x401B59C0 WRITE   4623304\n0x4023C180 WRITE   4623734\n0x4023C140 WRITE   4623736\n0x401C9280 WRITE   4623820\n0x4023C300 WRITE   4624199\n0x4023C2C0 WRITE   4624201\n0x4023C280 WRITE   4624208\n0x4023C240 WRITE   4624210\n0x401B5A00 WRITE   4624243\n0x4023C380 WRITE   4624706\n0x4023C340 WRITE   4624708\n0x401C92C0 WRITE   4624792\n0x4023C600 WRITE   4625203\n0x4023C5C0 WRITE   4625205\n0x4023C500 WRITE   4625212\n0x4023C4C0 WRITE   4625214\n0x4023C480 WRITE   4625224\n0x4023C440 WRITE   4625226\n0x401B5A40 WRITE   4625253\n0x4023C580 WRITE   4625694\n0x4023C540 WRITE   4625696\n0x401C9300 WRITE   4625780\n0x4023C700 WRITE   4626168\n0x4023C6C0 WRITE   4626170\n0x4023C680 WRITE   4626177\n0x4023C640 WRITE   4626179\n0x401B5A80 WRITE   4626212\n0x4023C780 WRITE   4626685\n0x4023C740 WRITE   4626687\n0x401C9340 WRITE   4626771\n0x4023CC00 WRITE   4627197\n0x4023CBC0 WRITE   4627199\n0x4023CA00 WRITE   4627206\n0x4023C9C0 WRITE   4627208\n0x4023C900 WRITE   4627218\n0x4023C8C0 WRITE   4627220\n0x4023C880 WRITE   4627225\n0x4023C840 WRITE   4627228\n0x401B5AC0 WRITE   4627253\n0x4023C980 WRITE   4627692\n0x4023C940 WRITE   4627694\n0x401C9380 WRITE   4627778\n0x4023CB00 WRITE   4628164\n0x4023CAC0 WRITE   4628166\n0x4023CA80 WRITE   4628173\n0x4023CA40 WRITE   4628175\n0x401B5B00 WRITE   4628208\n0x4023CB80 WRITE   4628679\n0x4023CB40 WRITE   4628681\n0x401C93C0 WRITE   4628765\n0x4023CE00 WRITE   4629184\n0x4023CDC0 WRITE   4629186\n0x4023CD00 WRITE   4629193\n0x4023CCC0 WRITE   4629195\n0x4023CC80 WRITE   4629205\n0x4023CC40 WRITE   4629207\n0x401B5B40 WRITE   4629234\n0x4023CD80 WRITE   4629682\n0x4023CD40 WRITE   4629684\n0x401C9400 WRITE   4629768\n0x4023CF00 WRITE   4630163\n0x4023CEC0 WRITE   4630165\n0x4023CE80 WRITE   4630172\n0x4023CE40 WRITE   4630174\n0x401B5B80 WRITE   4630207\n0x4023CF80 WRITE   4630687\n0x4023CF40 WRITE   4630689\n0x401C9440 WRITE   4630773\n0x4023D800 WRITE   4631205\n0x4023D7C0 WRITE   4631207\n0x4023D400 WRITE   4631214\n0x4023D3C0 WRITE   4631216\n0x4023D200 WRITE   4631226\n0x4023D1C0 WRITE   4631228\n0x4023D100 WRITE   4631233\n0x4023D0C0 WRITE   4631236\n0x4023D080 WRITE   4631239\n0x4023D040 WRITE   4631242\n0x401B5BC0 WRITE   4631267\n0x4023D180 WRITE   4631698\n0x4023D140 WRITE   4631700\n0x401C9480 WRITE   4631784\n0x4023D300 WRITE   4632168\n0x4023D2C0 WRITE   4632170\n0x4023D280 WRITE   4632177\n0x4023D240 WRITE   4632179\n0x401B5C00 WRITE   4632212\n0x4023D380 WRITE   4632675\n0x4023D340 WRITE   4632677\n0x401C94C0 WRITE   4632761\n0x4023D600 WRITE   4633178\n0x4023D5C0 WRITE   4633180\n0x4023D500 WRITE   4633187\n0x4023D4C0 WRITE   4633189\n0x4023D480 WRITE   4633199\n0x4023D440 WRITE   4633201\n0x401B5C40 WRITE   4633228\n0x4023D580 WRITE   4633669\n0x4023D540 WRITE   4633671\n0x401C9500 WRITE   4633755\n0x4023D700 WRITE   4634149\n0x4023D6C0 WRITE   4634151\n0x4023D680 WRITE   4634158\n0x4023D640 WRITE   4634160\n0x401B5C80 WRITE   4634193\n0x4023D780 WRITE   4634666\n0x4023D740 WRITE   4634668\n0x401C9540 WRITE   4634752\n0x4023DC00 WRITE   4635184\n0x4023DBC0 WRITE   4635186\n0x4023DA00 WRITE   4635193\n0x4023D9C0 WRITE   4635195\n0x4023D900 WRITE   4635205\n0x4023D8C0 WRITE   4635207\n0x4023D880 WRITE   4635212\n0x4023D840 WRITE   4635215\n0x401B5CC0 WRITE   4635240\n0x4023D980 WRITE   4635679\n0x4023D940 WRITE   4635681\n0x401C9580 WRITE   4635765\n0x4023DB00 WRITE   4636157\n0x4023DAC0 WRITE   4636159\n0x4023DA80 WRITE   4636166\n0x4023DA40 WRITE   4636168\n0x401B5D00 WRITE   4636201\n0x4023DB80 WRITE   4636672\n0x4023DB40 WRITE   4636674\n0x401C95C0 WRITE   4636758\n0x4023DE00 WRITE   4637183\n0x4023DDC0 WRITE   4637185\n0x4023DD00 WRITE   4637192\n0x4023DCC0 WRITE   4637194\n0x4023DC80 WRITE   4637204\n0x4023DC40 WRITE   4637206\n0x401B5D40 WRITE   4637233\n0x4023DD80 WRITE   4637681\n0x4023DD40 WRITE   4637683\n0x401C9600 WRITE   4637767\n0x4023DF00 WRITE   4638168\n0x4023DEC0 WRITE   4638170\n0x4023DE80 WRITE   4638177\n0x4023DE40 WRITE   4638179\n0x401B5D80 WRITE   4638212\n0x4023DF80 WRITE   4638692\n0x4023DF40 WRITE   4638694\n0x401C9640 WRITE   4638778\n0x4023FFC0 WRITE   4639262\n0x40240000 WRITE   4639296\n0x4023F000 WRITE   4639408\n0x4023EFC0 WRITE   4639410\n0x4023E800 WRITE   4639417\n0x4023E7C0 WRITE   4639419\n0x4023E400 WRITE   4639429\n0x4023E3C0 WRITE   4639431\n0x4023E200 WRITE   4639436\n0x4023E1C0 WRITE   4639439\n0x4023E100 WRITE   4639442\n0x4023E0C0 WRITE   4639445\n0x4023E080 WRITE   4639448\n0x4023E040 WRITE   4639451\n0x401B5DC0 WRITE   4639484\n0x4023E180 WRITE   4639914\n0x4023E140 WRITE   4639916\n0x401C9680 WRITE   4640000\n0x4023E300 WRITE   4640379\n0x4023E2C0 WRITE   4640381\n0x4023E280 WRITE   4640388\n0x4023E240 WRITE   4640390\n0x401B5E00 WRITE   4640423\n0x4023E380 WRITE   4640886\n0x4023E340 WRITE   4640888\n0x401C96C0 WRITE   4640972\n0x4023E600 WRITE   4641383\n0x4023E5C0 WRITE   4641385\n0x4023E500 WRITE   4641392\n0x4023E4C0 WRITE   4641394\n0x4023E480 WRITE   4641404\n0x4023E440 WRITE   4641406\n0x401B5E40 WRITE   4641433\n0x4023E580 WRITE   4641874\n0x4023E540 WRITE   4641876\n0x401C9700 WRITE   4641960\n0x4023E700 WRITE   4642348\n0x4023E6C0 WRITE   4642350\n0x4023E680 WRITE   4642357\n0x4023E640 WRITE   4642359\n0x401B5E80 WRITE   4642392\n0x4023E780 WRITE   4642865\n0x4023E740 WRITE   4642867\n0x401C9740 WRITE   4642951\n0x4023EC00 WRITE   4643377\n0x4023EBC0 WRITE   4643379\n0x4023EA00 WRITE   4643386\n0x4023E9C0 WRITE   4643388\n0x4023E900 WRITE   4643398\n0x4023E8C0 WRITE   4643400\n0x4023E880 WRITE   4643405\n0x4023E840 WRITE   4643408\n0x401B5EC0 WRITE   4643433\n0x4023E980 WRITE   4643872\n0x4023E940 WRITE   4643874\n0x401C9780 WRITE   4643958\n0x4023EB00 WRITE   4644344\n0x4023EAC0 WRITE   4644346\n0x4023EA80 WRITE   4644353\n0x4023EA40 WRITE   4644355\n0x401B5F00 WRITE   4644388\n0x4023EB80 WRITE   4644859\n0x4023EB40 WRITE   4644861\n0x401C97C0 WRITE   4644945\n0x4023EE00 WRITE   4645364\n0x4023EDC0 WRITE   4645366\n0x4023ED00 WRITE   4645373\n0x4023ECC0 WRITE   4645375\n0x4023EC80 WRITE   4645385\n0x4023EC40 WRITE   4645387\n0x401B5F40 WRITE   4645414\n0x4023ED80 WRITE   4645862\n0x4023ED40 WRITE   4645864\n0x401C9800 WRITE   4645948\n0x4023EF00 WRITE   4646343\n0x4023EEC0 WRITE   4646345\n0x4023EE80 WRITE   4646352\n0x4023EE40 WRITE   4646354\n0x401B5F80 WRITE   4646387\n0x4023EF80 WRITE   4646867\n0x4023EF40 WRITE   4646869\n0x401C9840 WRITE   4646953\n0x4023F800 WRITE   4647385\n0x4023F7C0 WRITE   4647387\n0x4023F400 WRITE   4647394\n0x4023F3C0 WRITE   4647396\n0x4023F200 WRITE   4647406\n0x4023F1C0 WRITE   4647408\n0x4023F100 WRITE   4647413\n0x4023F0C0 WRITE   4647416\n0x4023F080 WRITE   4647419\n0x4023F040 WRITE   4647422\n0x401B5FC0 WRITE   4647447\n0x4023F180 WRITE   4647878\n0x4023F140 WRITE   4647880\n0x401C9880 WRITE   4647964\n0x4023F300 WRITE   4648348\n0x4023F2C0 WRITE   4648350\n0x4023F280 WRITE   4648357\n0x4023F240 WRITE   4648359\n0x401B6000 WRITE   4648392\n0x4023F380 WRITE   4648855\n0x4023F340 WRITE   4648857\n0x401C98C0 WRITE   4648941\n0x4023F600 WRITE   4649358\n0x4023F5C0 WRITE   4649360\n0x4023F500 WRITE   4649367\n0x4023F4C0 WRITE   4649369\n0x4023F480 WRITE   4649379\n0x4023F440 WRITE   4649381\n0x401B6040 WRITE   4649408\n0x4023F580 WRITE   4649849\n0x4023F540 WRITE   4649851\n0x401C9900 WRITE   4649935\n0x4023F700 WRITE   4650329\n0x4023F6C0 WRITE   4650331\n0x4023F680 WRITE   4650338\n0x4023F640 WRITE   4650340\n0x401B6080 WRITE   4650373\n0x4023F780 WRITE   4650846\n0x4023F740 WRITE   4650848\n0x401C9940 WRITE   4650932\n0x4023FC00 WRITE   4651364\n0x4023FBC0 WRITE   4651366\n0x4023FA00 WRITE   4651373\n0x4023F9C0 WRITE   4651375\n0x4023F900 WRITE   4651385\n0x4023F8C0 WRITE   4651387\n0x4023F880 WRITE   4651392\n0x4023F840 WRITE   4651395\n0x401B60C0 WRITE   4651420\n0x4023F980 WRITE   4651859\n0x4023F940 WRITE   4651861\n0x401C9980 WRITE   4651945\n0x4023FB00 WRITE   4652337\n0x4023FAC0 WRITE   4652339\n0x4023FA80 WRITE   4652346\n0x4023FA40 WRITE   4652348\n0x401B6100 WRITE   4652381\n0x4023FB80 WRITE   4652852\n0x4023FB40 WRITE   4652854\n0x401C99C0 WRITE   4652938\n0x4023FE00 WRITE   4653363\n0x4023FDC0 WRITE   4653365\n0x4023FD00 WRITE   4653372\n0x4023FCC0 WRITE   4653374\n0x4023FC80 WRITE   4653384\n0x4023FC40 WRITE   4653386\n0x401B6140 WRITE   4653413\n0x4023FD80 WRITE   4653861\n0x4023FD40 WRITE   4653863\n0x401C9A00 WRITE   4653947\n0x4023FF00 WRITE   4654348\n0x4023FEC0 WRITE   4654350\n0x4023FE80 WRITE   4654357\n0x4023FE40 WRITE   4654359\n0x401B6180 WRITE   4654392\n0x4023FF80 WRITE   4654872\n0x4023FF40 WRITE   4654874\n0x401C9A40 WRITE   4654958\n0x40241FC0 WRITE   4655442\n0x40242000 WRITE   4655476\n0x40241000 WRITE   4655588\n0x40240FC0 WRITE   4655590\n0x40240800 WRITE   4655597\n0x402407C0 WRITE   4655599\n0x40240400 WRITE   4655609\n0x402403C0 WRITE   4655611\n0x40240200 WRITE   4655616\n0x402401C0 WRITE   4655619\n0x40240100 WRITE   4655622\n0x402400C0 WRITE   4655625\n0x40240080 WRITE   4655628\n0x40240040 WRITE   4655631\n0x401B61C0 WRITE   4655664\n0x40240180 WRITE   4656094\n0x40240140 WRITE   4656096\n0x401C9A80 WRITE   4656180\n0x40240300 WRITE   4656559\n0x402402C0 WRITE   4656561\n0x40240280 WRITE   4656568\n0x40240240 WRITE   4656570\n0x401B6200 WRITE   4656603\n0x40240380 WRITE   4657066\n0x40240340 WRITE   4657068\n0x401C9AC0 WRITE   4657152\n0x40240600 WRITE   4657563\n0x402405C0 WRITE   4657565\n0x40240500 WRITE   4657572\n0x402404C0 WRITE   4657574\n0x40240480 WRITE   4657584\n0x40240440 WRITE   4657586\n0x401B6240 WRITE   4657613\n0x40240580 WRITE   4658054\n0x40240540 WRITE   4658056\n0x401C9B00 WRITE   4658140\n0x40240700 WRITE   4658528\n0x402406C0 WRITE   4658530\n0x40240680 WRITE   4658537\n0x40240640 WRITE   4658539\n0x401B6280 WRITE   4658572\n0x40240780 WRITE   4659045\n0x40240740 WRITE   4659047\n0x401C9B40 WRITE   4659131\n0x40240C00 WRITE   4659557\n0x40240BC0 WRITE   4659559\n0x40240A00 WRITE   4659566\n0x402409C0 WRITE   4659568\n0x40240900 WRITE   4659578\n0x402408C0 WRITE   4659580\n0x40240880 WRITE   4659585\n0x40240840 WRITE   4659588\n0x401B62C0 WRITE   4659613\n0x40240980 WRITE   4660052\n0x40240940 WRITE   4660054\n0x401C9B80 WRITE   4660138\n0x40240B00 WRITE   4660524\n0x40240AC0 WRITE   4660526\n0x40240A80 WRITE   4660533\n0x40240A40 WRITE   4660535\n0x401B6300 WRITE   4660568\n0x40240B80 WRITE   4661039\n0x40240B40 WRITE   4661041\n0x401C9BC0 WRITE   4661125\n0x40240E00 WRITE   4661544\n0x40240DC0 WRITE   4661546\n0x40240D00 WRITE   4661553\n0x40240CC0 WRITE   4661555\n0x40240C80 WRITE   4661565\n0x40240C40 WRITE   4661567\n0x401B6340 WRITE   4661594\n0x40240D80 WRITE   4662042\n0x40240D40 WRITE   4662044\n0x401C9C00 WRITE   4662128\n0x40240F00 WRITE   4662523\n0x40240EC0 WRITE   4662525\n0x40240E80 WRITE   4662532\n0x40240E40 WRITE   4662534\n0x401B6380 WRITE   4662567\n0x40240F80 WRITE   4663047\n0x40240F40 WRITE   4663049\n0x401C9C40 WRITE   4663133\n0x40241800 WRITE   4663565\n0x402417C0 WRITE   4663567\n0x40241400 WRITE   4663574\n0x402413C0 WRITE   4663576\n0x40241200 WRITE   4663586\n0x402411C0 WRITE   4663588\n0x40241100 WRITE   4663593\n0x402410C0 WRITE   4663596\n0x40241080 WRITE   4663599\n0x40241040 WRITE   4663602\n0x401B63C0 WRITE   4663627\n0x40241180 WRITE   4664058\n0x40241140 WRITE   4664060\n0x401C9C80 WRITE   4664144\n0x40241300 WRITE   4664528\n0x402412C0 WRITE   4664530\n0x40241280 WRITE   4664537\n0x40241240 WRITE   4664539\n0x401B6400 WRITE   4664572\n0x40241380 WRITE   4665035\n0x40241340 WRITE   4665037\n0x401C9CC0 WRITE   4665121\n0x40241600 WRITE   4665538\n0x402415C0 WRITE   4665540\n0x40241500 WRITE   4665547\n0x402414C0 WRITE   4665549\n0x40241480 WRITE   4665559\n0x40241440 WRITE   4665561\n0x401B6440 WRITE   4665588\n0x40241580 WRITE   4666029\n0x40241540 WRITE   4666031\n0x401C9D00 WRITE   4666115\n0x40241700 WRITE   4666509\n0x402416C0 WRITE   4666511\n0x40241680 WRITE   4666518\n0x40241640 WRITE   4666520\n0x401B6480 WRITE   4666553\n0x40241780 WRITE   4667026\n0x40241740 WRITE   4667028\n0x401C9D40 WRITE   4667112\n0x40241C00 WRITE   4667544\n0x40241BC0 WRITE   4667546\n0x40241A00 WRITE   4667553\n0x402419C0 WRITE   4667555\n0x40241900 WRITE   4667565\n0x402418C0 WRITE   4667567\n0x40241880 WRITE   4667572\n0x40241840 WRITE   4667575\n0x401B64C0 WRITE   4667600\n0x40241980 WRITE   4668039\n0x40241940 WRITE   4668041\n0x401C9D80 WRITE   4668125\n0x40241B00 WRITE   4668517\n0x40241AC0 WRITE   4668519\n0x40241A80 WRITE   4668526\n0x40241A40 WRITE   4668528\n0x401B6500 WRITE   4668561\n0x40241B80 WRITE   4669032\n0x40241B40 WRITE   4669034\n0x401C9DC0 WRITE   4669118\n0x40241E00 WRITE   4669543\n0x40241DC0 WRITE   4669545\n0x40241D00 WRITE   4669552\n0x40241CC0 WRITE   4669554\n0x40241C80 WRITE   4669564\n0x40241C40 WRITE   4669566\n0x401B6540 WRITE   4669593\n0x40241D80 WRITE   4670041\n0x40241D40 WRITE   4670043\n0x401C9E00 WRITE   4670127\n0x40241F00 WRITE   4670528\n0x40241EC0 WRITE   4670530\n0x40241E80 WRITE   4670537\n0x40241E40 WRITE   4670539\n0x401B6580 WRITE   4670572\n0x40241F80 WRITE   4671052\n0x40241F40 WRITE   4671054\n0x401C9E40 WRITE   4671138\n0x40243FC0 WRITE   4671622\n0x40244000 WRITE   4671656\n0x40243000 WRITE   4671768\n0x40242FC0 WRITE   4671770\n0x40242800 WRITE   4671777\n0x402427C0 WRITE   4671779\n0x40242400 WRITE   4671789\n0x402423C0 WRITE   4671791\n0x40242200 WRITE   4671796\n0x402421C0 WRITE   4671799\n0x40242100 WRITE   4671802\n0x402420C0 WRITE   4671805\n0x40242080 WRITE   4671808\n0x40242040 WRITE   4671811\n0x401B65C0 WRITE   4671844\n0x40242180 WRITE   4672274\n0x40242140 WRITE   4672276\n0x401C9E80 WRITE   4672360\n0x40242300 WRITE   4672739\n0x402422C0 WRITE   4672741\n0x40242280 WRITE   4672748\n0x40242240 WRITE   4672750\n0x401B6600 WRITE   4672783\n0x40242380 WRITE   4673246\n0x40242340 WRITE   4673248\n0x401C9EC0 WRITE   4673332\n0x40242600 WRITE   4673743\n0x402425C0 WRITE   4673745\n0x40242500 WRITE   4673752\n0x402424C0 WRITE   4673754\n0x40242480 WRITE   4673764\n0x40242440 WRITE   4673766\n0x401B6640 WRITE   4673793\n0x40242580 WRITE   4674234\n0x40242540 WRITE   4674236\n0x401C9F00 WRITE   4674320\n0x40242700 WRITE   4674708\n0x402426C0 WRITE   4674710\n0x40242680 WRITE   4674717\n0x40242640 WRITE   4674719\n0x401B6680 WRITE   4674752\n0x40242780 WRITE   4675225\n0x40242740 WRITE   4675227\n0x401C9F40 WRITE   4675311\n0x40242C00 WRITE   4675737\n0x40242BC0 WRITE   4675739\n0x40242A00 WRITE   4675746\n0x402429C0 WRITE   4675748\n0x40242900 WRITE   4675758\n0x402428C0 WRITE   4675760\n0x40242880 WRITE   4675765\n0x40242840 WRITE   4675768\n0x401B66C0 WRITE   4675793\n0x40242980 WRITE   4676232\n0x40242940 WRITE   4676234\n0x401C9F80 WRITE   4676318\n0x40242B00 WRITE   4676704\n0x40242AC0 WRITE   4676706\n0x40242A80 WRITE   4676713\n0x40242A40 WRITE   4676715\n0x401B6700 WRITE   4676748\n0x40242B80 WRITE   4677219\n0x40242B40 WRITE   4677221\n0x401C9FC0 WRITE   4677305\n0x40242E00 WRITE   4677724\n0x40242DC0 WRITE   4677726\n0x40242D00 WRITE   4677733\n0x40242CC0 WRITE   4677735\n0x40242C80 WRITE   4677745\n0x40242C40 WRITE   4677747\n0x401B6740 WRITE   4677774\n0x40242D80 WRITE   4678222\n0x40242D40 WRITE   4678224\n0x401CA000 WRITE   4678308\n0x40242F00 WRITE   4678703\n0x40242EC0 WRITE   4678705\n0x40242E80 WRITE   4678712\n0x40242E40 WRITE   4678714\n0x401B6780 WRITE   4678747\n0x40242F80 WRITE   4679227\n0x40242F40 WRITE   4679229\n0x401CA040 WRITE   4679313\n0x40243800 WRITE   4679745\n0x402437C0 WRITE   4679747\n0x40243400 WRITE   4679754\n0x402433C0 WRITE   4679756\n0x40243200 WRITE   4679766\n0x402431C0 WRITE   4679768\n0x40243100 WRITE   4679773\n0x402430C0 WRITE   4679776\n0x40243080 WRITE   4679779\n0x40243040 WRITE   4679782\n0x401B67C0 WRITE   4679807\n0x40243180 WRITE   4680238\n0x40243140 WRITE   4680240\n0x401CA080 WRITE   4680324\n0x40243300 WRITE   4680708\n0x402432C0 WRITE   4680710\n0x40243280 WRITE   4680717\n0x40243240 WRITE   4680719\n0x401B6800 WRITE   4680752\n0x40243380 WRITE   4681215\n0x40243340 WRITE   4681217\n0x401CA0C0 WRITE   4681301\n0x40243600 WRITE   4681718\n0x402435C0 WRITE   4681720\n0x40243500 WRITE   4681727\n0x402434C0 WRITE   4681729\n0x40243480 WRITE   4681739\n0x40243440 WRITE   4681741\n0x401B6840 WRITE   4681768\n0x40243580 WRITE   4682209\n0x40243540 WRITE   4682211\n0x401CA100 WRITE   4682295\n0x40243700 WRITE   4682689\n0x402436C0 WRITE   4682691\n0x40243680 WRITE   4682698\n0x40243640 WRITE   4682700\n0x401B6880 WRITE   4682733\n0x40243780 WRITE   4683206\n0x40243740 WRITE   4683208\n0x401CA140 WRITE   4683292\n0x40243C00 WRITE   4683724\n0x40243BC0 WRITE   4683726\n0x40243A00 WRITE   4683733\n0x402439C0 WRITE   4683735\n0x40243900 WRITE   4683745\n0x402438C0 WRITE   4683747\n0x40243880 WRITE   4683752\n0x40243840 WRITE   4683755\n0x401B68C0 WRITE   4683780\n0x40243980 WRITE   4684219\n0x40243940 WRITE   4684221\n0x401CA180 WRITE   4684305\n0x40243B00 WRITE   4684697\n0x40243AC0 WRITE   4684699\n0x40243A80 WRITE   4684706\n0x40243A40 WRITE   4684708\n0x401B6900 WRITE   4684741\n0x40243B80 WRITE   4685212\n0x40243B40 WRITE   4685214\n0x401CA1C0 WRITE   4685298\n0x40243E00 WRITE   4685723\n0x40243DC0 WRITE   4685725\n0x40243D00 WRITE   4685732\n0x40243CC0 WRITE   4685734\n0x40243C80 WRITE   4685744\n0x40243C40 WRITE   4685746\n0x401B6940 WRITE   4685773\n0x40243D80 WRITE   4686221\n0x40243D40 WRITE   4686223\n0x401CA200 WRITE   4686307\n0x40243F00 WRITE   4686708\n0x40243EC0 WRITE   4686710\n0x40243E80 WRITE   4686717\n0x40243E40 WRITE   4686719\n0x401B6980 WRITE   4686752\n0x40243F80 WRITE   4687232\n0x40243F40 WRITE   4687234\n0x401CA240 WRITE   4687318\n0x40245FC0 WRITE   4687802\n0x40246000 WRITE   4687836\n0x40245000 WRITE   4687948\n0x40244FC0 WRITE   4687950\n0x40244800 WRITE   4687957\n0x402447C0 WRITE   4687959\n0x40244400 WRITE   4687969\n0x402443C0 WRITE   4687971\n0x40244200 WRITE   4687976\n0x402441C0 WRITE   4687979\n0x40244100 WRITE   4687982\n0x402440C0 WRITE   4687985\n0x40244080 WRITE   4687988\n0x40244040 WRITE   4687991\n0x401B69C0 WRITE   4688024\n0x40244180 WRITE   4688454\n0x40244140 WRITE   4688456\n0x401CA280 WRITE   4688540\n0x40244300 WRITE   4688919\n0x402442C0 WRITE   4688921\n0x40244280 WRITE   4688928\n0x40244240 WRITE   4688930\n0x401B6A00 WRITE   4688963\n0x40244380 WRITE   4689426\n0x40244340 WRITE   4689428\n0x401CA2C0 WRITE   4689512\n0x40244600 WRITE   4689923\n0x402445C0 WRITE   4689925\n0x40244500 WRITE   4689932\n0x402444C0 WRITE   4689934\n0x40244480 WRITE   4689944\n0x40244440 WRITE   4689946\n0x401B6A40 WRITE   4689973\n0x40244580 WRITE   4690414\n0x40244540 WRITE   4690416\n0x401CA300 WRITE   4690500\n0x40244700 WRITE   4690888\n0x402446C0 WRITE   4690890\n0x40244680 WRITE   4690897\n0x40244640 WRITE   4690899\n0x401B6A80 WRITE   4690932\n0x40244780 WRITE   4691405\n0x40244740 WRITE   4691407\n0x401CA340 WRITE   4691491\n0x40244C00 WRITE   4691917\n0x40244BC0 WRITE   4691919\n0x40244A00 WRITE   4691926\n0x402449C0 WRITE   4691928\n0x40244900 WRITE   4691938\n0x402448C0 WRITE   4691940\n0x40244880 WRITE   4691945\n0x40244840 WRITE   4691948\n0x401B6AC0 WRITE   4691973\n0x40244980 WRITE   4692412\n0x40244940 WRITE   4692414\n0x401CA380 WRITE   4692498\n0x40244B00 WRITE   4692884\n0x40244AC0 WRITE   4692886\n0x40244A80 WRITE   4692893\n0x40244A40 WRITE   4692895\n0x401B6B00 WRITE   4692928\n0x40244B80 WRITE   4693399\n0x40244B40 WRITE   4693401\n0x401CA3C0 WRITE   4693485\n0x40244E00 WRITE   4693904\n0x40244DC0 WRITE   4693906\n0x40244D00 WRITE   4693913\n0x40244CC0 WRITE   4693915\n0x40244C80 WRITE   4693925\n0x40244C40 WRITE   4693927\n0x401B6B40 WRITE   4693954\n0x40244D80 WRITE   4694402\n0x40244D40 WRITE   4694404\n0x401CA400 WRITE   4694488\n0x40244F00 WRITE   4694883\n0x40244EC0 WRITE   4694885\n0x40244E80 WRITE   4694892\n0x40244E40 WRITE   4694894\n0x401B6B80 WRITE   4694927\n0x40244F80 WRITE   4695407\n0x40244F40 WRITE   4695409\n0x401CA440 WRITE   4695493\n0x40245800 WRITE   4695925\n0x402457C0 WRITE   4695927\n0x40245400 WRITE   4695934\n0x402453C0 WRITE   4695936\n0x40245200 WRITE   4695946\n0x402451C0 WRITE   4695948\n0x40245100 WRITE   4695953\n0x402450C0 WRITE   4695956\n0x40245080 WRITE   4695959\n0x40245040 WRITE   4695962\n0x401B6BC0 WRITE   4695987\n0x40245180 WRITE   4696418\n0x40245140 WRITE   4696420\n0x401CA480 WRITE   4696504\n0x40245300 WRITE   4696888\n0x402452C0 WRITE   4696890\n0x40245280 WRITE   4696897\n0x40245240 WRITE   4696899\n0x401B6C00 WRITE   4696932\n0x40245380 WRITE   4697395\n0x40245340 WRITE   4697397\n0x401CA4C0 WRITE   4697481\n0x40245600 WRITE   4697898\n0x402455C0 WRITE   4697900\n0x40245500 WRITE   4697907\n0x402454C0 WRITE   4697909\n0x40245480 WRITE   4697919\n0x40245440 WRITE   4697921\n0x401B6C40 WRITE   4697948\n0x40245580 WRITE   4698389\n0x40245540 WRITE   4698391\n0x401CA500 WRITE   4698475\n0x40245700 WRITE   4698869\n0x402456C0 WRITE   4698871\n0x40245680 WRITE   4698878\n0x40245640 WRITE   4698880\n0x401B6C80 WRITE   4698913\n0x40245780 WRITE   4699386\n0x40245740 WRITE   4699388\n0x401CA540 WRITE   4699472\n0x40245C00 WRITE   4699904\n0x40245BC0 WRITE   4699906\n0x40245A00 WRITE   4699913\n0x402459C0 WRITE   4699915\n0x40245900 WRITE   4699925\n0x402458C0 WRITE   4699927\n0x40245880 WRITE   4699932\n0x40245840 WRITE   4699935\n0x401B6CC0 WRITE   4699960\n0x40245980 WRITE   4700399\n0x40245940 WRITE   4700401\n0x401CA580 WRITE   4700485\n0x40245B00 WRITE   4700877\n0x40245AC0 WRITE   4700879\n0x40245A80 WRITE   4700886\n0x40245A40 WRITE   4700888\n0x401B6D00 WRITE   4700921\n0x40245B80 WRITE   4701392\n0x40245B40 WRITE   4701394\n0x401CA5C0 WRITE   4701478\n0x40245E00 WRITE   4701903\n0x40245DC0 WRITE   4701905\n0x40245D00 WRITE   4701912\n0x40245CC0 WRITE   4701914\n0x40245C80 WRITE   4701924\n0x40245C40 WRITE   4701926\n0x401B6D40 WRITE   4701953\n0x40245D80 WRITE   4702401\n0x40245D40 WRITE   4702403\n0x401CA600 WRITE   4702487\n0x40245F00 WRITE   4702888\n0x40245EC0 WRITE   4702890\n0x40245E80 WRITE   4702897\n0x40245E40 WRITE   4702899\n0x401B6D80 WRITE   4702932\n0x40245F80 WRITE   4703412\n0x40245F40 WRITE   4703414\n0x401CA640 WRITE   4703498\n0x40247FC0 WRITE   4703982\n0x40248000 WRITE   4704016\n0x40247000 WRITE   4704128\n0x40246FC0 WRITE   4704130\n0x40246800 WRITE   4704137\n0x402467C0 WRITE   4704139\n0x40246400 WRITE   4704149\n0x402463C0 WRITE   4704151\n0x40246200 WRITE   4704156\n0x402461C0 WRITE   4704159\n0x40246100 WRITE   4704162\n0x402460C0 WRITE   4704165\n0x40246080 WRITE   4704168\n0x40246040 WRITE   4704171\n0x401B6DC0 WRITE   4704204\n0x40246180 WRITE   4704634\n0x40246140 WRITE   4704636\n0x401CA680 WRITE   4704720\n0x40246300 WRITE   4705099\n0x402462C0 WRITE   4705101\n0x40246280 WRITE   4705108\n0x40246240 WRITE   4705110\n0x401B6E00 WRITE   4705143\n0x40246380 WRITE   4705606\n0x40246340 WRITE   4705608\n0x401CA6C0 WRITE   4705692\n0x40246600 WRITE   4706103\n0x402465C0 WRITE   4706105\n0x40246500 WRITE   4706112\n0x402464C0 WRITE   4706114\n0x40246480 WRITE   4706124\n0x40246440 WRITE   4706126\n0x401B6E40 WRITE   4706153\n0x40246580 WRITE   4706594\n0x40246540 WRITE   4706596\n0x401CA700 WRITE   4706680\n0x40246700 WRITE   4707068\n0x402466C0 WRITE   4707070\n0x40246680 WRITE   4707077\n0x40246640 WRITE   4707079\n0x401B6E80 WRITE   4707112\n0x40246780 WRITE   4707585\n0x40246740 WRITE   4707587\n0x401CA740 WRITE   4707671\n0x40246C00 WRITE   4708097\n0x40246BC0 WRITE   4708099\n0x40246A00 WRITE   4708106\n0x402469C0 WRITE   4708108\n0x40246900 WRITE   4708118\n0x402468C0 WRITE   4708120\n0x40246880 WRITE   4708125\n0x40246840 WRITE   4708128\n0x401B6EC0 WRITE   4708153\n0x40246980 WRITE   4708592\n0x40246940 WRITE   4708594\n0x401CA780 WRITE   4708678\n0x40246B00 WRITE   4709064\n0x40246AC0 WRITE   4709066\n0x40246A80 WRITE   4709073\n0x40246A40 WRITE   4709075\n0x401B6F00 WRITE   4709108\n0x40246B80 WRITE   4709579\n0x40246B40 WRITE   4709581\n0x401CA7C0 WRITE   4709665\n0x40246E00 WRITE   4710084\n0x40246DC0 WRITE   4710086\n0x40246D00 WRITE   4710093\n0x40246CC0 WRITE   4710095\n0x40246C80 WRITE   4710105\n0x40246C40 WRITE   4710107\n0x401B6F40 WRITE   4710134\n0x40246D80 WRITE   4710582\n0x40246D40 WRITE   4710584\n0x401CA800 WRITE   4710668\n0x40246F00 WRITE   4711063\n0x40246EC0 WRITE   4711065\n0x40246E80 WRITE   4711072\n0x40246E40 WRITE   4711074\n0x401B6F80 WRITE   4711107\n0x40246F80 WRITE   4711587\n0x40246F40 WRITE   4711589\n0x401CA840 WRITE   4711673\n0x40247800 WRITE   4712105\n0x402477C0 WRITE   4712107\n0x40247400 WRITE   4712114\n0x402473C0 WRITE   4712116\n0x40247200 WRITE   4712126\n0x402471C0 WRITE   4712128\n0x40247100 WRITE   4712133\n0x402470C0 WRITE   4712136\n0x40247080 WRITE   4712139\n0x40247040 WRITE   4712142\n0x401B6FC0 WRITE   4712167\n0x40247180 WRITE   4712598\n0x40247140 WRITE   4712600\n0x401CA880 WRITE   4712684\n0x40247300 WRITE   4713068\n0x402472C0 WRITE   4713070\n0x40247280 WRITE   4713077\n0x40247240 WRITE   4713079\n0x401B7000 WRITE   4713112\n0x40247380 WRITE   4713575\n0x40247340 WRITE   4713577\n0x401CA8C0 WRITE   4713661\n0x40247600 WRITE   4714078\n0x402475C0 WRITE   4714080\n0x40247500 WRITE   4714087\n0x402474C0 WRITE   4714089\n0x40247480 WRITE   4714099\n0x40247440 WRITE   4714101\n0x401B7040 WRITE   4714128\n0x40247580 WRITE   4714569\n0x40247540 WRITE   4714571\n0x401CA900 WRITE   4714655\n0x40247700 WRITE   4715049\n0x402476C0 WRITE   4715051\n0x40247680 WRITE   4715058\n0x40247640 WRITE   4715060\n0x401B7080 WRITE   4715093\n0x40247780 WRITE   4715566\n0x40247740 WRITE   4715568\n0x401CA940 WRITE   4715652\n0x40247C00 WRITE   4716084\n0x40247BC0 WRITE   4716086\n0x40247A00 WRITE   4716093\n0x402479C0 WRITE   4716095\n0x40247900 WRITE   4716105\n0x402478C0 WRITE   4716107\n0x40247880 WRITE   4716112\n0x40247840 WRITE   4716115\n0x401B70C0 WRITE   4716140\n0x40247980 WRITE   4716579\n0x40247940 WRITE   4716581\n0x401CA980 WRITE   4716665\n0x40247B00 WRITE   4717057\n0x40247AC0 WRITE   4717059\n0x40247A80 WRITE   4717066\n0x40247A40 WRITE   4717068\n0x401B7100 WRITE   4717101\n0x40247B80 WRITE   4717572\n0x40247B40 WRITE   4717574\n0x401CA9C0 WRITE   4717658\n0x40247E00 WRITE   4718083\n0x40247DC0 WRITE   4718085\n0x40247D00 WRITE   4718092\n0x40247CC0 WRITE   4718094\n0x40247C80 WRITE   4718104\n0x40247C40 WRITE   4718106\n0x401B7140 WRITE   4718133\n0x40247D80 WRITE   4718581\n0x40247D40 WRITE   4718583\n0x401CAA00 WRITE   4718667\n0x40247F00 WRITE   4719068\n0x40247EC0 WRITE   4719070\n0x40247E80 WRITE   4719077\n0x40247E40 WRITE   4719079\n0x401B7180 WRITE   4719112\n0x40247F80 WRITE   4719592\n0x40247F40 WRITE   4719594\n0x401CAA40 WRITE   4719678\n0x40249FC0 WRITE   4720162\n0x4024A000 WRITE   4720196\n0x40249000 WRITE   4720308\n0x40248FC0 WRITE   4720310\n0x40248800 WRITE   4720317\n0x402487C0 WRITE   4720319\n0x40248400 WRITE   4720329\n0x402483C0 WRITE   4720331\n0x40248200 WRITE   4720336\n0x402481C0 WRITE   4720339\n0x40248100 WRITE   4720342\n0x402480C0 WRITE   4720345\n0x40248080 WRITE   4720348\n0x40248040 WRITE   4720351\n0x401B71C0 WRITE   4720384\n0x40248180 WRITE   4720814\n0x40248140 WRITE   4720816\n0x401CAA80 WRITE   4720900\n0x40248300 WRITE   4721279\n0x402482C0 WRITE   4721281\n0x40248280 WRITE   4721288\n0x40248240 WRITE   4721290\n0x401B7200 WRITE   4721323\n0x40248380 WRITE   4721786\n0x40248340 WRITE   4721788\n0x401CAAC0 WRITE   4721872\n0x40248600 WRITE   4722283\n0x402485C0 WRITE   4722285\n0x40248500 WRITE   4722292\n0x402484C0 WRITE   4722294\n0x40248480 WRITE   4722304\n0x40248440 WRITE   4722306\n0x401B7240 WRITE   4722333\n0x40248580 WRITE   4722774\n0x40248540 WRITE   4722776\n0x401CAB00 WRITE   4722860\n0x40248700 WRITE   4723248\n0x402486C0 WRITE   4723250\n0x40248680 WRITE   4723257\n0x40248640 WRITE   4723259\n0x401B7280 WRITE   4723292\n0x40248780 WRITE   4723765\n0x40248740 WRITE   4723767\n0x401CAB40 WRITE   4723851\n0x40248C00 WRITE   4724277\n0x40248BC0 WRITE   4724279\n0x40248A00 WRITE   4724286\n0x402489C0 WRITE   4724288\n0x40248900 WRITE   4724298\n0x402488C0 WRITE   4724300\n0x40248880 WRITE   4724305\n0x40248840 WRITE   4724308\n0x401B72C0 WRITE   4724333\n0x40248980 WRITE   4724772\n0x40248940 WRITE   4724774\n0x401CAB80 WRITE   4724858\n0x40248B00 WRITE   4725244\n0x40248AC0 WRITE   4725246\n0x40248A80 WRITE   4725253\n0x40248A40 WRITE   4725255\n0x401B7300 WRITE   4725288\n0x40248B80 WRITE   4725759\n0x40248B40 WRITE   4725761\n0x401CABC0 WRITE   4725845\n0x40248E00 WRITE   4726264\n0x40248DC0 WRITE   4726266\n0x40248D00 WRITE   4726273\n0x40248CC0 WRITE   4726275\n0x40248C80 WRITE   4726285\n0x40248C40 WRITE   4726287\n0x401B7340 WRITE   4726314\n0x40248D80 WRITE   4726762\n0x40248D40 WRITE   4726764\n0x401CAC00 WRITE   4726848\n0x40248F00 WRITE   4727243\n0x40248EC0 WRITE   4727245\n0x40248E80 WRITE   4727252\n0x40248E40 WRITE   4727254\n0x401B7380 WRITE   4727287\n0x40248F80 WRITE   4727767\n0x40248F40 WRITE   4727769\n0x401CAC40 WRITE   4727853\n0x40249800 WRITE   4728285\n0x402497C0 WRITE   4728287\n0x40249400 WRITE   4728294\n0x402493C0 WRITE   4728296\n0x40249200 WRITE   4728306\n0x402491C0 WRITE   4728308\n0x40249100 WRITE   4728313\n0x402490C0 WRITE   4728316\n0x40249080 WRITE   4728319\n0x40249040 WRITE   4728322\n0x401B73C0 WRITE   4728347\n0x40249180 WRITE   4728778\n0x40249140 WRITE   4728780\n0x401CAC80 WRITE   4728864\n0x40249300 WRITE   4729248\n0x402492C0 WRITE   4729250\n0x40249280 WRITE   4729257\n0x40249240 WRITE   4729259\n0x401B7400 WRITE   4729292\n0x40249380 WRITE   4729755\n0x40249340 WRITE   4729757\n0x401CACC0 WRITE   4729841\n0x40249600 WRITE   4730258\n0x402495C0 WRITE   4730260\n0x40249500 WRITE   4730267\n0x402494C0 WRITE   4730269\n0x40249480 WRITE   4730279\n0x40249440 WRITE   4730281\n0x401B7440 WRITE   4730308\n0x40249580 WRITE   4730749\n0x40249540 WRITE   4730751\n0x401CAD00 WRITE   4730835\n0x40249700 WRITE   4731229\n0x402496C0 WRITE   4731231\n0x40249680 WRITE   4731238\n0x40249640 WRITE   4731240\n0x401B7480 WRITE   4731273\n0x40249780 WRITE   4731746\n0x40249740 WRITE   4731748\n0x401CAD40 WRITE   4731832\n0x40249C00 WRITE   4732264\n0x40249BC0 WRITE   4732266\n0x40249A00 WRITE   4732273\n0x402499C0 WRITE   4732275\n0x40249900 WRITE   4732285\n0x402498C0 WRITE   4732287\n0x40249880 WRITE   4732292\n0x40249840 WRITE   4732295\n0x401B74C0 WRITE   4732320\n0x40249980 WRITE   4732759\n0x40249940 WRITE   4732761\n0x401CAD80 WRITE   4732845\n0x40249B00 WRITE   4733237\n0x40249AC0 WRITE   4733239\n0x40249A80 WRITE   4733246\n0x40249A40 WRITE   4733248\n0x401B7500 WRITE   4733281\n0x40249B80 WRITE   4733752\n0x40249B40 WRITE   4733754\n0x401CADC0 WRITE   4733838\n0x40249E00 WRITE   4734263\n0x40249DC0 WRITE   4734265\n0x40249D00 WRITE   4734272\n0x40249CC0 WRITE   4734274\n0x40249C80 WRITE   4734284\n0x40249C40 WRITE   4734286\n0x401B7540 WRITE   4734313\n0x40249D80 WRITE   4734761\n0x40249D40 WRITE   4734763\n0x401CAE00 WRITE   4734847\n0x40249F00 WRITE   4735248\n0x40249EC0 WRITE   4735250\n0x40249E80 WRITE   4735257\n0x40249E40 WRITE   4735259\n0x401B7580 WRITE   4735292\n0x40249F80 WRITE   4735772\n0x40249F40 WRITE   4735774\n0x401CAE40 WRITE   4735858\n0x4024BFC0 WRITE   4736342\n0x4024C000 WRITE   4736376\n0x4024B000 WRITE   4736483\n0x4024AFC0 WRITE   4736485\n0x4024A800 WRITE   4736492\n0x4024A7C0 WRITE   4736494\n0x4024A400 WRITE   4736504\n0x4024A3C0 WRITE   4736506\n0x4024A200 WRITE   4736511\n0x4024A1C0 WRITE   4736514\n0x4024A100 WRITE   4736517\n0x4024A0C0 WRITE   4736520\n0x4024A080 WRITE   4736523\n0x4024A040 WRITE   4736526\n0x401B75C0 WRITE   4736559\n0x4024A180 WRITE   4736989\n0x4024A140 WRITE   4736991\n0x401CAE80 WRITE   4737075\n0x4024A300 WRITE   4737454\n0x4024A2C0 WRITE   4737456\n0x4024A280 WRITE   4737463\n0x4024A240 WRITE   4737465\n0x401B7600 WRITE   4737498\n0x4024A380 WRITE   4737961\n0x4024A340 WRITE   4737963\n0x401CAEC0 WRITE   4738047\n0x4024A600 WRITE   4738458\n0x4024A5C0 WRITE   4738460\n0x4024A500 WRITE   4738467\n0x4024A4C0 WRITE   4738469\n0x4024A480 WRITE   4738479\n0x4024A440 WRITE   4738481\n0x401B7640 WRITE   4738508\n0x4024A580 WRITE   4738949\n0x4024A540 WRITE   4738951\n0x401CAF00 WRITE   4739035\n0x4024A700 WRITE   4739423\n0x4024A6C0 WRITE   4739425\n0x4024A680 WRITE   4739432\n0x4024A640 WRITE   4739434\n0x401B7680 WRITE   4739467\n0x4024A780 WRITE   4739940\n0x4024A740 WRITE   4739942\n0x401CAF40 WRITE   4740026\n0x4024AC00 WRITE   4740452\n0x4024ABC0 WRITE   4740454\n0x4024AA00 WRITE   4740461\n0x4024A9C0 WRITE   4740463\n0x4024A900 WRITE   4740473\n0x4024A8C0 WRITE   4740475\n0x4024A880 WRITE   4740480\n0x4024A840 WRITE   4740483\n0x401B76C0 WRITE   4740508\n0x4024A980 WRITE   4740947\n0x4024A940 WRITE   4740949\n0x401CAF80 WRITE   4741033\n0x4024AB00 WRITE   4741419\n0x4024AAC0 WRITE   4741421\n0x4024AA80 WRITE   4741428\n0x4024AA40 WRITE   4741430\n0x401B7700 WRITE   4741463\n0x4024AB80 WRITE   4741934\n0x4024AB40 WRITE   4741936\n0x401CAFC0 WRITE   4742020\n0x4024AE00 WRITE   4742439\n0x4024ADC0 WRITE   4742441\n0x4024AD00 WRITE   4742448\n0x4024ACC0 WRITE   4742450\n0x4024AC80 WRITE   4742460\n0x4024AC40 WRITE   4742462\n0x401B7740 WRITE   4742489\n0x4024AD80 WRITE   4742937\n0x4024AD40 WRITE   4742939\n0x401CB000 WRITE   4743023\n0x4024AF00 WRITE   4743418\n0x4024AEC0 WRITE   4743420\n0x4024AE80 WRITE   4743427\n0x4024AE40 WRITE   4743429\n0x401B7780 WRITE   4743462\n0x4024AF80 WRITE   4743942\n0x4024AF40 WRITE   4743944\n0x401CB040 WRITE   4744028\n0x4024B800 WRITE   4744460\n0x4024B7C0 WRITE   4744462\n0x4024B400 WRITE   4744469\n0x4024B3C0 WRITE   4744471\n0x4024B200 WRITE   4744481\n0x4024B1C0 WRITE   4744483\n0x4024B100 WRITE   4744488\n0x4024B0C0 WRITE   4744491\n0x4024B080 WRITE   4744494\n0x4024B040 WRITE   4744497\n0x401B77C0 WRITE   4744522\n0x4024B180 WRITE   4744953\n0x4024B140 WRITE   4744955\n0x401CB080 WRITE   4745039\n0x4024B300 WRITE   4745423\n0x4024B2C0 WRITE   4745425\n0x4024B280 WRITE   4745432\n0x4024B240 WRITE   4745434\n0x401B7800 WRITE   4745467\n0x4024B380 WRITE   4745930\n0x4024B340 WRITE   4745932\n0x401CB0C0 WRITE   4746016\n0x4024B600 WRITE   4746433\n0x4024B5C0 WRITE   4746435\n0x4024B500 WRITE   4746442\n0x4024B4C0 WRITE   4746444\n0x4024B480 WRITE   4746454\n0x4024B440 WRITE   4746456\n0x401B7840 WRITE   4746483\n0x4024B580 WRITE   4746924\n0x4024B540 WRITE   4746926\n0x401CB100 WRITE   4747010\n0x4024B700 WRITE   4747404\n0x4024B6C0 WRITE   4747406\n0x4024B680 WRITE   4747413\n0x4024B640 WRITE   4747415\n0x401B7880 WRITE   4747448\n0x4024B780 WRITE   4747921\n0x4024B740 WRITE   4747923\n0x401CB140 WRITE   4748007\n0x4024BC00 WRITE   4748439\n0x4024BBC0 WRITE   4748441\n0x4024BA00 WRITE   4748448\n0x4024B9C0 WRITE   4748450\n0x4024B900 WRITE   4748460\n0x4024B8C0 WRITE   4748462\n0x4024B880 WRITE   4748467\n0x4024B840 WRITE   4748470\n0x401B78C0 WRITE   4748495\n0x4024B980 WRITE   4748934\n0x4024B940 WRITE   4748936\n0x401CB180 WRITE   4749020\n0x4024BB00 WRITE   4749412\n0x4024BAC0 WRITE   4749414\n0x4024BA80 WRITE   4749421\n0x4024BA40 WRITE   4749423\n0x401B7900 WRITE   4749456\n0x4024BB80 WRITE   4749927\n0x4024BB40 WRITE   4749929\n0x401CB1C0 WRITE   4750013\n0x4024BE00 WRITE   4750438\n0x4024BDC0 WRITE   4750440\n0x4024BD00 WRITE   4750447\n0x4024BCC0 WRITE   4750449\n0x4024BC80 WRITE   4750459\n0x4024BC40 WRITE   4750461\n0x401B7940 WRITE   4750488\n0x4024BD80 WRITE   4750936\n0x4024BD40 WRITE   4750938\n0x401CB200 WRITE   4751022\n0x4024BF00 WRITE   4751423\n0x4024BEC0 WRITE   4751425\n0x4024BE80 WRITE   4751432\n0x4024BE40 WRITE   4751434\n0x401B7980 WRITE   4751467\n0x4024BF80 WRITE   4751947\n0x4024BF40 WRITE   4751949\n0x401CB240 WRITE   4752033\n0x4024DFC0 WRITE   4752517\n0x4024E000 WRITE   4752551\n0x4024D000 WRITE   4752663\n0x4024CFC0 WRITE   4752665\n0x4024C800 WRITE   4752672\n0x4024C7C0 WRITE   4752674\n0x4024C400 WRITE   4752684\n0x4024C3C0 WRITE   4752686\n0x4024C200 WRITE   4752691\n0x4024C1C0 WRITE   4752694\n0x4024C100 WRITE   4752697\n0x4024C0C0 WRITE   4752700\n0x4024C080 WRITE   4752703\n0x4024C040 WRITE   4752706\n0x401B79C0 WRITE   4752739\n0x4024C180 WRITE   4753169\n0x4024C140 WRITE   4753171\n0x401CB280 WRITE   4753255\n0x4024C300 WRITE   4753634\n0x4024C2C0 WRITE   4753636\n0x4024C280 WRITE   4753643\n0x4024C240 WRITE   4753645\n0x401B7A00 WRITE   4753678\n0x4024C380 WRITE   4754141\n0x4024C340 WRITE   4754143\n0x401CB2C0 WRITE   4754227\n0x4024C600 WRITE   4754638\n0x4024C5C0 WRITE   4754640\n0x4024C500 WRITE   4754647\n0x4024C4C0 WRITE   4754649\n0x4024C480 WRITE   4754659\n0x4024C440 WRITE   4754661\n0x401B7A40 WRITE   4754688\n0x4024C580 WRITE   4755129\n0x4024C540 WRITE   4755131\n0x401CB300 WRITE   4755215\n0x4024C700 WRITE   4755603\n0x4024C6C0 WRITE   4755605\n0x4024C680 WRITE   4755612\n0x4024C640 WRITE   4755614\n0x401B7A80 WRITE   4755647\n0x4024C780 WRITE   4756120\n0x4024C740 WRITE   4756122\n0x401CB340 WRITE   4756206\n0x4024CC00 WRITE   4756632\n0x4024CBC0 WRITE   4756634\n0x4024CA00 WRITE   4756641\n0x4024C9C0 WRITE   4756643\n0x4024C900 WRITE   4756653\n0x4024C8C0 WRITE   4756655\n0x4024C880 WRITE   4756660\n0x4024C840 WRITE   4756663\n0x401B7AC0 WRITE   4756688\n0x4024C980 WRITE   4757127\n0x4024C940 WRITE   4757129\n0x401CB380 WRITE   4757213\n0x4024CB00 WRITE   4757599\n0x4024CAC0 WRITE   4757601\n0x4024CA80 WRITE   4757608\n0x4024CA40 WRITE   4757610\n0x401B7B00 WRITE   4757643\n0x4024CB80 WRITE   4758114\n0x4024CB40 WRITE   4758116\n0x401CB3C0 WRITE   4758200\n0x4024CE00 WRITE   4758619\n0x4024CDC0 WRITE   4758621\n0x4024CD00 WRITE   4758628\n0x4024CCC0 WRITE   4758630\n0x4024CC80 WRITE   4758640\n0x4024CC40 WRITE   4758642\n0x401B7B40 WRITE   4758669\n0x4024CD80 WRITE   4759117\n0x4024CD40 WRITE   4759119\n0x401CB400 WRITE   4759203\n0x4024CF00 WRITE   4759598\n0x4024CEC0 WRITE   4759600\n0x4024CE80 WRITE   4759607\n0x4024CE40 WRITE   4759609\n0x401B7B80 WRITE   4759642\n0x4024CF80 WRITE   4760122\n0x4024CF40 WRITE   4760124\n0x401CB440 WRITE   4760208\n0x4024D800 WRITE   4760640\n0x4024D7C0 WRITE   4760642\n0x4024D400 WRITE   4760649\n0x4024D3C0 WRITE   4760651\n0x4024D200 WRITE   4760661\n0x4024D1C0 WRITE   4760663\n0x4024D100 WRITE   4760668\n0x4024D0C0 WRITE   4760671\n0x4024D080 WRITE   4760674\n0x4024D040 WRITE   4760677\n0x401B7BC0 WRITE   4760702\n0x4024D180 WRITE   4761133\n0x4024D140 WRITE   4761135\n0x401CB480 WRITE   4761219\n0x4024D300 WRITE   4761603\n0x4024D2C0 WRITE   4761605\n0x4024D280 WRITE   4761612\n0x4024D240 WRITE   4761614\n0x401B7C00 WRITE   4761647\n0x4024D380 WRITE   4762110\n0x4024D340 WRITE   4762112\n0x401CB4C0 WRITE   4762196\n0x4024D600 WRITE   4762613\n0x4024D5C0 WRITE   4762615\n0x4024D500 WRITE   4762622\n0x4024D4C0 WRITE   4762624\n0x4024D480 WRITE   4762634\n0x4024D440 WRITE   4762636\n0x401B7C40 WRITE   4762663\n0x4024D580 WRITE   4763104\n0x4024D540 WRITE   4763106\n0x401CB500 WRITE   4763190\n0x4024D700 WRITE   4763584\n0x4024D6C0 WRITE   4763586\n0x4024D680 WRITE   4763593\n0x4024D640 WRITE   4763595\n0x401B7C80 WRITE   4763628\n0x4024D780 WRITE   4764101\n0x4024D740 WRITE   4764103\n0x401CB540 WRITE   4764187\n0x4024DC00 WRITE   4764619\n0x4024DBC0 WRITE   4764621\n0x4024DA00 WRITE   4764628\n0x4024D9C0 WRITE   4764630\n0x4024D900 WRITE   4764640\n0x4024D8C0 WRITE   4764642\n0x4024D880 WRITE   4764647\n0x4024D840 WRITE   4764650\n0x401B7CC0 WRITE   4764675\n0x4024D980 WRITE   4765114\n0x4024D940 WRITE   4765116\n0x401CB580 WRITE   4765200\n0x4024DB00 WRITE   4765592\n0x4024DAC0 WRITE   4765594\n0x4024DA80 WRITE   4765601\n0x4024DA40 WRITE   4765603\n0x401B7D00 WRITE   4765636\n0x4024DB80 WRITE   4766107\n0x4024DB40 WRITE   4766109\n0x401CB5C0 WRITE   4766193\n0x4024DE00 WRITE   4766618\n0x4024DDC0 WRITE   4766620\n0x4024DD00 WRITE   4766627\n0x4024DCC0 WRITE   4766629\n0x4024DC80 WRITE   4766639\n0x4024DC40 WRITE   4766641\n0x401B7D40 WRITE   4766668\n0x4024DD80 WRITE   4767116\n0x4024DD40 WRITE   4767118\n0x401CB600 WRITE   4767202\n0x4024DF00 WRITE   4767603\n0x4024DEC0 WRITE   4767605\n0x4024DE80 WRITE   4767612\n0x4024DE40 WRITE   4767614\n0x401B7D80 WRITE   4767647\n0x4024DF80 WRITE   4768127\n0x4024DF40 WRITE   4768129\n0x401CB640 WRITE   4768213\n0x4024FFC0 WRITE   4768697\n0x40250000 WRITE   4768731\n0x4024F000 WRITE   4768843\n0x4024EFC0 WRITE   4768845\n0x4024E800 WRITE   4768852\n0x4024E7C0 WRITE   4768854\n0x4024E400 WRITE   4768864\n0x4024E3C0 WRITE   4768866\n0x4024E200 WRITE   4768871\n0x4024E1C0 WRITE   4768874\n0x4024E100 WRITE   4768877\n0x4024E0C0 WRITE   4768880\n0x4024E080 WRITE   4768883\n0x4024E040 WRITE   4768886\n0x401B7DC0 WRITE   4768919\n0x4024E180 WRITE   4769349\n0x4024E140 WRITE   4769351\n0x401CB680 WRITE   4769435\n0x4024E300 WRITE   4769814\n0x4024E2C0 WRITE   4769816\n0x4024E280 WRITE   4769823\n0x4024E240 WRITE   4769825\n0x401B7E00 WRITE   4769858\n0x4024E380 WRITE   4770321\n0x4024E340 WRITE   4770323\n0x401CB6C0 WRITE   4770407\n0x4024E600 WRITE   4770818\n0x4024E5C0 WRITE   4770820\n0x4024E500 WRITE   4770827\n0x4024E4C0 WRITE   4770829\n0x4024E480 WRITE   4770839\n0x4024E440 WRITE   4770841\n0x401B7E40 WRITE   4770868\n0x4024E580 WRITE   4771309\n0x4024E540 WRITE   4771311\n0x401CB700 WRITE   4771395\n0x4024E700 WRITE   4771783\n0x4024E6C0 WRITE   4771785\n0x4024E680 WRITE   4771792\n0x4024E640 WRITE   4771794\n0x401B7E80 WRITE   4771827\n0x4024E780 WRITE   4772300\n0x4024E740 WRITE   4772302\n0x401CB740 WRITE   4772386\n0x4024EC00 WRITE   4772812\n0x4024EBC0 WRITE   4772814\n0x4024EA00 WRITE   4772821\n0x4024E9C0 WRITE   4772823\n0x4024E900 WRITE   4772833\n0x4024E8C0 WRITE   4772835\n0x4024E880 WRITE   4772840\n0x4024E840 WRITE   4772843\n0x401B7EC0 WRITE   4772868\n0x4024E980 WRITE   4773307\n0x4024E940 WRITE   4773309\n0x401CB780 WRITE   4773393\n0x4024EB00 WRITE   4773779\n0x4024EAC0 WRITE   4773781\n0x4024EA80 WRITE   4773788\n0x4024EA40 WRITE   4773790\n0x401B7F00 WRITE   4773823\n0x4024EB80 WRITE   4774294\n0x4024EB40 WRITE   4774296\n0x401CB7C0 WRITE   4774380\n0x4024EE00 WRITE   4774799\n0x4024EDC0 WRITE   4774801\n0x4024ED00 WRITE   4774808\n0x4024ECC0 WRITE   4774810\n0x4024EC80 WRITE   4774820\n0x4024EC40 WRITE   4774822\n0x401B7F40 WRITE   4774849\n0x4024ED80 WRITE   4775297\n0x4024ED40 WRITE   4775299\n0x401CB800 WRITE   4775383\n0x4024EF00 WRITE   4775778\n0x4024EEC0 WRITE   4775780\n0x4024EE80 WRITE   4775787\n0x4024EE40 WRITE   4775789\n0x401B7F80 WRITE   4775822\n0x4024EF80 WRITE   4776302\n0x4024EF40 WRITE   4776304\n0x401CB840 WRITE   4776388\n0x4024F800 WRITE   4776820\n0x4024F7C0 WRITE   4776822\n0x4024F400 WRITE   4776829\n0x4024F3C0 WRITE   4776831\n0x4024F200 WRITE   4776841\n0x4024F1C0 WRITE   4776843\n0x4024F100 WRITE   4776848\n0x4024F0C0 WRITE   4776851\n0x4024F080 WRITE   4776854\n0x4024F040 WRITE   4776857\n0x401B7FC0 WRITE   4776882\n0x4024F180 WRITE   4777313\n0x4024F140 WRITE   4777315\n0x401CB880 WRITE   4777399\n0x4024F300 WRITE   4777783\n0x4024F2C0 WRITE   4777785\n0x4024F280 WRITE   4777792\n0x4024F240 WRITE   4777794\n0x401B8000 WRITE   4777827\n0x4024F380 WRITE   4778290\n0x4024F340 WRITE   4778292\n0x401CB8C0 WRITE   4778376\n0x4024F600 WRITE   4778793\n0x4024F5C0 WRITE   4778795\n0x4024F500 WRITE   4778802\n0x4024F4C0 WRITE   4778804\n0x4024F480 WRITE   4778814\n0x4024F440 WRITE   4778816\n0x401B8040 WRITE   4778843\n0x4024F580 WRITE   4779284\n0x4024F540 WRITE   4779286\n0x401CB900 WRITE   4779370\n0x4024F700 WRITE   4779764\n0x4024F6C0 WRITE   4779766\n0x4024F680 WRITE   4779773\n0x4024F640 WRITE   4779775\n0x401B8080 WRITE   4779808\n0x4024F780 WRITE   4780281\n0x4024F740 WRITE   4780283\n0x401CB940 WRITE   4780367\n0x4024FC00 WRITE   4780799\n0x4024FBC0 WRITE   4780801\n0x4024FA00 WRITE   4780808\n0x4024F9C0 WRITE   4780810\n0x4024F900 WRITE   4780820\n0x4024F8C0 WRITE   4780822\n0x4024F880 WRITE   4780827\n0x4024F840 WRITE   4780830\n0x401B80C0 WRITE   4780855\n0x4024F980 WRITE   4781294\n0x4024F940 WRITE   4781296\n0x401CB980 WRITE   4781380\n0x4024FB00 WRITE   4781772\n0x4024FAC0 WRITE   4781774\n0x4024FA80 WRITE   4781781\n0x4024FA40 WRITE   4781783\n0x401B8100 WRITE   4781816\n0x4024FB80 WRITE   4782287\n0x4024FB40 WRITE   4782289\n0x401CB9C0 WRITE   4782373\n0x4024FE00 WRITE   4782798\n0x4024FDC0 WRITE   4782800\n0x4024FD00 WRITE   4782807\n0x4024FCC0 WRITE   4782809\n0x4024FC80 WRITE   4782819\n0x4024FC40 WRITE   4782821\n0x401B8140 WRITE   4782848\n0x4024FD80 WRITE   4783296\n0x4024FD40 WRITE   4783298\n0x401CBA00 WRITE   4783382\n0x4024FF00 WRITE   4783783\n0x4024FEC0 WRITE   4783785\n0x4024FE80 WRITE   4783792\n0x4024FE40 WRITE   4783794\n0x401B8180 WRITE   4783827\n0x4024FF80 WRITE   4784307\n0x4024FF40 WRITE   4784309\n0x401CBA40 WRITE   4784393\n0x40251FC0 WRITE   4784877\n0x40252000 WRITE   4784911\n0x40251000 WRITE   4785023\n0x40250FC0 WRITE   4785025\n0x40250800 WRITE   4785032\n0x402507C0 WRITE   4785034\n0x40250400 WRITE   4785044\n0x402503C0 WRITE   4785046\n0x40250200 WRITE   4785051\n0x402501C0 WRITE   4785054\n0x40250100 WRITE   4785057\n0x402500C0 WRITE   4785060\n0x40250080 WRITE   4785063\n0x40250040 WRITE   4785066\n0x401B81C0 WRITE   4785099\n0x40250180 WRITE   4785529\n0x40250140 WRITE   4785531\n0x401CBA80 WRITE   4785615\n0x40250300 WRITE   4785994\n0x402502C0 WRITE   4785996\n0x40250280 WRITE   4786003\n0x40250240 WRITE   4786005\n0x401B8200 WRITE   4786038\n0x40250380 WRITE   4786501\n0x40250340 WRITE   4786503\n0x401CBAC0 WRITE   4786587\n0x40250600 WRITE   4786998\n0x402505C0 WRITE   4787000\n0x40250500 WRITE   4787007\n0x402504C0 WRITE   4787009\n0x40250480 WRITE   4787019\n0x40250440 WRITE   4787021\n0x401B8240 WRITE   4787048\n0x40250580 WRITE   4787489\n0x40250540 WRITE   4787491\n0x401CBB00 WRITE   4787575\n0x40250700 WRITE   4787963\n0x402506C0 WRITE   4787965\n0x40250680 WRITE   4787972\n0x40250640 WRITE   4787974\n0x401B8280 WRITE   4788007\n0x40250780 WRITE   4788480\n0x40250740 WRITE   4788482\n0x401CBB40 WRITE   4788566\n0x40250C00 WRITE   4788992\n0x40250BC0 WRITE   4788994\n0x40250A00 WRITE   4789001\n0x402509C0 WRITE   4789003\n0x40250900 WRITE   4789013\n0x402508C0 WRITE   4789015\n0x40250880 WRITE   4789020\n0x40250840 WRITE   4789023\n0x401B82C0 WRITE   4789048\n0x40250980 WRITE   4789487\n0x40250940 WRITE   4789489\n0x401CBB80 WRITE   4789573\n0x40250B00 WRITE   4789959\n0x40250AC0 WRITE   4789961\n0x40250A80 WRITE   4789968\n0x40250A40 WRITE   4789970\n0x401B8300 WRITE   4790003\n0x40250B80 WRITE   4790474\n0x40250B40 WRITE   4790476\n0x401CBBC0 WRITE   4790560\n0x40250E00 WRITE   4790979\n0x40250DC0 WRITE   4790981\n0x40250D00 WRITE   4790988\n0x40250CC0 WRITE   4790990\n0x40250C80 WRITE   4791000\n0x40250C40 WRITE   4791002\n0x401B8340 WRITE   4791029\n0x40250D80 WRITE   4791477\n0x40250D40 WRITE   4791479\n0x401CBC00 WRITE   4791563\n0x40250F00 WRITE   4791958\n0x40250EC0 WRITE   4791960\n0x40250E80 WRITE   4791967\n0x40250E40 WRITE   4791969\n0x401B8380 WRITE   4792002\n0x40250F80 WRITE   4792482\n0x40250F40 WRITE   4792484\n0x401CBC40 WRITE   4792568\n0x40251800 WRITE   4793000\n0x402517C0 WRITE   4793002\n0x40251400 WRITE   4793009\n0x402513C0 WRITE   4793011\n0x40251200 WRITE   4793021\n0x402511C0 WRITE   4793023\n0x40251100 WRITE   4793028\n0x402510C0 WRITE   4793031\n0x40251080 WRITE   4793034\n0x40251040 WRITE   4793037\n0x401B83C0 WRITE   4793062\n0x40251180 WRITE   4793493\n0x40251140 WRITE   4793495\n0x401CBC80 WRITE   4793579\n0x40251300 WRITE   4793963\n0x402512C0 WRITE   4793965\n0x40251280 WRITE   4793972\n0x40251240 WRITE   4793974\n0x401B8400 WRITE   4794007\n0x40251380 WRITE   4794470\n0x40251340 WRITE   4794472\n0x401CBCC0 WRITE   4794556\n0x40251600 WRITE   4794973\n0x402515C0 WRITE   4794975\n0x40251500 WRITE   4794982\n0x402514C0 WRITE   4794984\n0x40251480 WRITE   4794994\n0x40251440 WRITE   4794996\n0x401B8440 WRITE   4795023\n0x40251580 WRITE   4795464\n0x40251540 WRITE   4795466\n0x401CBD00 WRITE   4795550\n0x40251700 WRITE   4795944\n0x402516C0 WRITE   4795946\n0x40251680 WRITE   4795953\n0x40251640 WRITE   4795955\n0x401B8480 WRITE   4795988\n0x40251780 WRITE   4796461\n0x40251740 WRITE   4796463\n0x401CBD40 WRITE   4796547\n0x40251C00 WRITE   4796979\n0x40251BC0 WRITE   4796981\n0x40251A00 WRITE   4796988\n0x402519C0 WRITE   4796990\n0x40251900 WRITE   4797000\n0x402518C0 WRITE   4797002\n0x40251880 WRITE   4797007\n0x40251840 WRITE   4797010\n0x401B84C0 WRITE   4797035\n0x40251980 WRITE   4797474\n0x40251940 WRITE   4797476\n0x401CBD80 WRITE   4797560\n0x40251B00 WRITE   4797952\n0x40251AC0 WRITE   4797954\n0x40251A80 WRITE   4797961\n0x40251A40 WRITE   4797963\n0x401B8500 WRITE   4797996\n0x40251B80 WRITE   4798467\n0x40251B40 WRITE   4798469\n0x401CBDC0 WRITE   4798553\n0x40251E00 WRITE   4798978\n0x40251DC0 WRITE   4798980\n0x40251D00 WRITE   4798987\n0x40251CC0 WRITE   4798989\n0x40251C80 WRITE   4798999\n0x40251C40 WRITE   4799001\n0x401B8540 WRITE   4799028\n0x40251D80 WRITE   4799476\n0x40251D40 WRITE   4799478\n0x401CBE00 WRITE   4799562\n0x40251F00 WRITE   4799963\n0x40251EC0 WRITE   4799965\n0x40251E80 WRITE   4799972\n0x40251E40 WRITE   4799974\n0x401B8580 WRITE   4800007\n0x40251F80 WRITE   4800487\n0x40251F40 WRITE   4800489\n0x401CBE40 WRITE   4800573\n0x40253FC0 WRITE   4801057\n0x40254000 WRITE   4801091\n0x40253000 WRITE   4801203\n0x40252FC0 WRITE   4801205\n0x40252800 WRITE   4801212\n0x402527C0 WRITE   4801214\n0x40252400 WRITE   4801224\n0x402523C0 WRITE   4801226\n0x40252200 WRITE   4801231\n0x402521C0 WRITE   4801234\n0x40252100 WRITE   4801237\n0x402520C0 WRITE   4801240\n0x40252080 WRITE   4801243\n0x40252040 WRITE   4801246\n0x401B85C0 WRITE   4801279\n0x40252180 WRITE   4801709\n0x40252140 WRITE   4801711\n0x401CBE80 WRITE   4801795\n0x40252300 WRITE   4802174\n0x402522C0 WRITE   4802176\n0x40252280 WRITE   4802183\n0x40252240 WRITE   4802185\n0x401B8600 WRITE   4802218\n0x40252380 WRITE   4802681\n0x40252340 WRITE   4802683\n0x401CBEC0 WRITE   4802767\n0x40252600 WRITE   4803178\n0x402525C0 WRITE   4803180\n0x40252500 WRITE   4803187\n0x402524C0 WRITE   4803189\n0x40252480 WRITE   4803199\n0x40252440 WRITE   4803201\n0x401B8640 WRITE   4803228\n0x40252580 WRITE   4803669\n0x40252540 WRITE   4803671\n0x401CBF00 WRITE   4803755\n0x40252700 WRITE   4804143\n0x402526C0 WRITE   4804145\n0x40252680 WRITE   4804152\n0x40252640 WRITE   4804154\n0x401B8680 WRITE   4804187\n0x40252780 WRITE   4804660\n0x40252740 WRITE   4804662\n0x401CBF40 WRITE   4804746\n0x40252C00 WRITE   4805172\n0x40252BC0 WRITE   4805174\n0x40252A00 WRITE   4805181\n0x402529C0 WRITE   4805183\n0x40252900 WRITE   4805193\n0x402528C0 WRITE   4805195\n0x40252880 WRITE   4805200\n0x40252840 WRITE   4805203\n0x401B86C0 WRITE   4805228\n0x40252980 WRITE   4805667\n0x40252940 WRITE   4805669\n0x401CBF80 WRITE   4805753\n0x40252B00 WRITE   4806139\n0x40252AC0 WRITE   4806141\n0x40252A80 WRITE   4806148\n0x40252A40 WRITE   4806150\n0x401B8700 WRITE   4806183\n0x40252B80 WRITE   4806654\n0x40252B40 WRITE   4806656\n0x401CBFC0 WRITE   4806740\n0x40252E00 WRITE   4807159\n0x40252DC0 WRITE   4807161\n0x40252D00 WRITE   4807168\n0x40252CC0 WRITE   4807170\n0x40252C80 WRITE   4807180\n0x40252C40 WRITE   4807182\n0x401B8740 WRITE   4807209\n0x40252D80 WRITE   4807657\n0x40252D40 WRITE   4807659\n0x401CC000 WRITE   4807743\n0x40252F00 WRITE   4808138\n0x40252EC0 WRITE   4808140\n0x40252E80 WRITE   4808147\n0x40252E40 WRITE   4808149\n0x401B8780 WRITE   4808182\n0x40252F80 WRITE   4808662\n0x40252F40 WRITE   4808664\n0x401CC040 WRITE   4808748\n0x40253800 WRITE   4809180\n0x402537C0 WRITE   4809182\n0x40253400 WRITE   4809189\n0x402533C0 WRITE   4809191\n0x40253200 WRITE   4809201\n0x402531C0 WRITE   4809203\n0x40253100 WRITE   4809208\n0x402530C0 WRITE   4809211\n0x40253080 WRITE   4809214\n0x40253040 WRITE   4809217\n0x401B87C0 WRITE   4809242\n0x40253180 WRITE   4809673\n0x40253140 WRITE   4809675\n0x401CC080 WRITE   4809759\n0x40253300 WRITE   4810143\n0x402532C0 WRITE   4810145\n0x40253280 WRITE   4810152\n0x40253240 WRITE   4810154\n0x401B8800 WRITE   4810187\n0x40253380 WRITE   4810650\n0x40253340 WRITE   4810652\n0x401CC0C0 WRITE   4810736\n0x40253600 WRITE   4811153\n0x402535C0 WRITE   4811155\n0x40253500 WRITE   4811162\n0x402534C0 WRITE   4811164\n0x40253480 WRITE   4811174\n0x40253440 WRITE   4811176\n0x401B8840 WRITE   4811203\n0x40253580 WRITE   4811644\n0x40253540 WRITE   4811646\n0x401CC100 WRITE   4811730\n0x40253700 WRITE   4812124\n0x402536C0 WRITE   4812126\n0x40253680 WRITE   4812133\n0x40253640 WRITE   4812135\n0x401B8880 WRITE   4812168\n0x40253780 WRITE   4812641\n0x40253740 WRITE   4812643\n0x401CC140 WRITE   4812727\n0x40253C00 WRITE   4813159\n0x40253BC0 WRITE   4813161\n0x40253A00 WRITE   4813168\n0x402539C0 WRITE   4813170\n0x40253900 WRITE   4813180\n0x402538C0 WRITE   4813182\n0x40253880 WRITE   4813187\n0x40253840 WRITE   4813190\n0x401B88C0 WRITE   4813215\n0x40253980 WRITE   4813654\n0x40253940 WRITE   4813656\n0x401CC180 WRITE   4813740\n0x40253B00 WRITE   4814132\n0x40253AC0 WRITE   4814134\n0x40253A80 WRITE   4814141\n0x40253A40 WRITE   4814143\n0x401B8900 WRITE   4814176\n0x40253B80 WRITE   4814647\n0x40253B40 WRITE   4814649\n0x401CC1C0 WRITE   4814733\n0x40253E00 WRITE   4815158\n0x40253DC0 WRITE   4815160\n0x40253D00 WRITE   4815167\n0x40253CC0 WRITE   4815169\n0x40253C80 WRITE   4815179\n0x40253C40 WRITE   4815181\n0x401B8940 WRITE   4815208\n0x40253D80 WRITE   4815656\n0x40253D40 WRITE   4815658\n0x401CC200 WRITE   4815742\n0x40253F00 WRITE   4816143\n0x40253EC0 WRITE   4816145\n0x40253E80 WRITE   4816152\n0x40253E40 WRITE   4816154\n0x401B8980 WRITE   4816187\n0x40253F80 WRITE   4816667\n0x40253F40 WRITE   4816669\n0x401CC240 WRITE   4816753\n0x40255FC0 WRITE   4817237\n0x40256000 WRITE   4817271\n0x40255000 WRITE   4817383\n0x40254FC0 WRITE   4817385\n0x40254800 WRITE   4817392\n0x402547C0 WRITE   4817394\n0x40254400 WRITE   4817404\n0x402543C0 WRITE   4817406\n0x40254200 WRITE   4817411\n0x402541C0 WRITE   4817414\n0x40254100 WRITE   4817417\n0x402540C0 WRITE   4817420\n0x40254080 WRITE   4817423\n0x40254040 WRITE   4817426\n0x401B89C0 WRITE   4817459\n0x40254180 WRITE   4817889\n0x40254140 WRITE   4817891\n0x401CC280 WRITE   4817975\n0x40254300 WRITE   4818354\n0x402542C0 WRITE   4818356\n0x40254280 WRITE   4818363\n0x40254240 WRITE   4818365\n0x401B8A00 WRITE   4818398\n0x40254380 WRITE   4818861\n0x40254340 WRITE   4818863\n0x401CC2C0 WRITE   4818947\n0x40254600 WRITE   4819358\n0x402545C0 WRITE   4819360\n0x40254500 WRITE   4819367\n0x402544C0 WRITE   4819369\n0x40254480 WRITE   4819379\n0x40254440 WRITE   4819381\n0x401B8A40 WRITE   4819408\n0x40254580 WRITE   4819849\n0x40254540 WRITE   4819851\n0x401CC300 WRITE   4819935\n0x40254700 WRITE   4820323\n0x402546C0 WRITE   4820325\n0x40254680 WRITE   4820332\n0x40254640 WRITE   4820334\n0x401B8A80 WRITE   4820367\n0x40254780 WRITE   4820840\n0x40254740 WRITE   4820842\n0x401CC340 WRITE   4820926\n0x40254C00 WRITE   4821352\n0x40254BC0 WRITE   4821354\n0x40254A00 WRITE   4821361\n0x402549C0 WRITE   4821363\n0x40254900 WRITE   4821373\n0x402548C0 WRITE   4821375\n0x40254880 WRITE   4821380\n0x40254840 WRITE   4821383\n0x401B8AC0 WRITE   4821408\n0x40254980 WRITE   4821847\n0x40254940 WRITE   4821849\n0x401CC380 WRITE   4821933\n0x40254B00 WRITE   4822319\n0x40254AC0 WRITE   4822321\n0x40254A80 WRITE   4822328\n0x40254A40 WRITE   4822330\n0x401B8B00 WRITE   4822363\n0x40254B80 WRITE   4822834\n0x40254B40 WRITE   4822836\n0x401CC3C0 WRITE   4822920\n0x40254E00 WRITE   4823339\n0x40254DC0 WRITE   4823341\n0x40254D00 WRITE   4823348\n0x40254CC0 WRITE   4823350\n0x40254C80 WRITE   4823360\n0x40254C40 WRITE   4823362\n0x401B8B40 WRITE   4823389\n0x40254D80 WRITE   4823837\n0x40254D40 WRITE   4823839\n0x401CC400 WRITE   4823923\n0x40254F00 WRITE   4824318\n0x40254EC0 WRITE   4824320\n0x40254E80 WRITE   4824327\n0x40254E40 WRITE   4824329\n0x401B8B80 WRITE   4824362\n0x40254F80 WRITE   4824842\n0x40254F40 WRITE   4824844\n0x401CC440 WRITE   4824928\n0x40255800 WRITE   4825360\n0x402557C0 WRITE   4825362\n0x40255400 WRITE   4825369\n0x402553C0 WRITE   4825371\n0x40255200 WRITE   4825381\n0x402551C0 WRITE   4825383\n0x40255100 WRITE   4825388\n0x402550C0 WRITE   4825391\n0x40255080 WRITE   4825394\n0x40255040 WRITE   4825397\n0x401B8BC0 WRITE   4825422\n0x40255180 WRITE   4825853\n0x40255140 WRITE   4825855\n0x401CC480 WRITE   4825939\n0x40255300 WRITE   4826323\n0x402552C0 WRITE   4826325\n0x40255280 WRITE   4826332\n0x40255240 WRITE   4826334\n0x401B8C00 WRITE   4826367\n0x40255380 WRITE   4826830\n0x40255340 WRITE   4826832\n0x401CC4C0 WRITE   4826916\n0x40255600 WRITE   4827333\n0x402555C0 WRITE   4827335\n0x40255500 WRITE   4827342\n0x402554C0 WRITE   4827344\n0x40255480 WRITE   4827354\n0x40255440 WRITE   4827356\n0x401B8C40 WRITE   4827383\n0x40255580 WRITE   4827824\n0x40255540 WRITE   4827826\n0x401CC500 WRITE   4827910\n0x40255700 WRITE   4828304\n0x402556C0 WRITE   4828306\n0x40255680 WRITE   4828313\n0x40255640 WRITE   4828315\n0x401B8C80 WRITE   4828348\n0x40255780 WRITE   4828821\n0x40255740 WRITE   4828823\n0x401CC540 WRITE   4828907\n0x40255C00 WRITE   4829339\n0x40255BC0 WRITE   4829341\n0x40255A00 WRITE   4829348\n0x402559C0 WRITE   4829350\n0x40255900 WRITE   4829360\n0x402558C0 WRITE   4829362\n0x40255880 WRITE   4829367\n0x40255840 WRITE   4829370\n0x401B8CC0 WRITE   4829395\n0x40255980 WRITE   4829834\n0x40255940 WRITE   4829836\n0x401CC580 WRITE   4829920\n0x40255B00 WRITE   4830312\n0x40255AC0 WRITE   4830314\n0x40255A80 WRITE   4830321\n0x40255A40 WRITE   4830323\n0x401B8D00 WRITE   4830356\n0x40255B80 WRITE   4830827\n0x40255B40 WRITE   4830829\n0x401CC5C0 WRITE   4830913\n0x40255E00 WRITE   4831338\n0x40255DC0 WRITE   4831340\n0x40255D00 WRITE   4831347\n0x40255CC0 WRITE   4831349\n0x40255C80 WRITE   4831359\n0x40255C40 WRITE   4831361\n0x401B8D40 WRITE   4831388\n0x40255D80 WRITE   4831836\n0x40255D40 WRITE   4831838\n0x401CC600 WRITE   4831922\n0x40255F00 WRITE   4832323\n0x40255EC0 WRITE   4832325\n0x40255E80 WRITE   4832332\n0x40255E40 WRITE   4832334\n0x401B8D80 WRITE   4832367\n0x40255F80 WRITE   4832847\n0x40255F40 WRITE   4832849\n0x401CC640 WRITE   4832933\n0x40257FC0 WRITE   4833417\n0x40258000 WRITE   4833451\n0x40257000 WRITE   4833563\n0x40256FC0 WRITE   4833565\n0x40256800 WRITE   4833572\n0x402567C0 WRITE   4833574\n0x40256400 WRITE   4833584\n0x402563C0 WRITE   4833586\n0x40256200 WRITE   4833591\n0x402561C0 WRITE   4833594\n0x40256100 WRITE   4833597\n0x402560C0 WRITE   4833600\n0x40256080 WRITE   4833603\n0x40256040 WRITE   4833606\n0x401B8DC0 WRITE   4833639\n0x40256180 WRITE   4834069\n0x40256140 WRITE   4834071\n0x401CC680 WRITE   4834155\n0x40256300 WRITE   4834534\n0x402562C0 WRITE   4834536\n0x40256280 WRITE   4834543\n0x40256240 WRITE   4834545\n0x401B8E00 WRITE   4834578\n0x40256380 WRITE   4835041\n0x40256340 WRITE   4835043\n0x401CC6C0 WRITE   4835127\n0x40256600 WRITE   4835538\n0x402565C0 WRITE   4835540\n0x40256500 WRITE   4835547\n0x402564C0 WRITE   4835549\n0x40256480 WRITE   4835559\n0x40256440 WRITE   4835561\n0x401B8E40 WRITE   4835588\n0x40256580 WRITE   4836029\n0x40256540 WRITE   4836031\n0x401CC700 WRITE   4836115\n0x40256700 WRITE   4836503\n0x402566C0 WRITE   4836505\n0x40256680 WRITE   4836512\n0x40256640 WRITE   4836514\n0x401B8E80 WRITE   4836547\n0x40256780 WRITE   4837020\n0x40256740 WRITE   4837022\n0x401CC740 WRITE   4837106\n0x40256C00 WRITE   4837532\n0x40256BC0 WRITE   4837534\n0x40256A00 WRITE   4837541\n0x402569C0 WRITE   4837543\n0x40256900 WRITE   4837553\n0x402568C0 WRITE   4837555\n0x40256880 WRITE   4837560\n0x40256840 WRITE   4837563\n0x401B8EC0 WRITE   4837588\n0x40256980 WRITE   4838027\n0x40256940 WRITE   4838029\n0x401CC780 WRITE   4838113\n0x40256B00 WRITE   4838499\n0x40256AC0 WRITE   4838501\n0x40256A80 WRITE   4838508\n0x40256A40 WRITE   4838510\n0x401B8F00 WRITE   4838543\n0x40256B80 WRITE   4839014\n0x40256B40 WRITE   4839016\n0x401CC7C0 WRITE   4839100\n0x40256E00 WRITE   4839519\n0x40256DC0 WRITE   4839521\n0x40256D00 WRITE   4839528\n0x40256CC0 WRITE   4839530\n0x40256C80 WRITE   4839540\n0x40256C40 WRITE   4839542\n0x401B8F40 WRITE   4839569\n0x40256D80 WRITE   4840017\n0x40256D40 WRITE   4840019\n0x401CC800 WRITE   4840103\n0x40256F00 WRITE   4840498\n0x40256EC0 WRITE   4840500\n0x40256E80 WRITE   4840507\n0x40256E40 WRITE   4840509\n0x401B8F80 WRITE   4840542\n0x40256F80 WRITE   4841022\n0x40256F40 WRITE   4841024\n0x401CC840 WRITE   4841108\n0x40257800 WRITE   4841540\n0x402577C0 WRITE   4841542\n0x40257400 WRITE   4841549\n0x402573C0 WRITE   4841551\n0x40257200 WRITE   4841561\n0x402571C0 WRITE   4841563\n0x40257100 WRITE   4841568\n0x402570C0 WRITE   4841571\n0x40257080 WRITE   4841574\n0x40257040 WRITE   4841577\n0x401B8FC0 WRITE   4841602\n0x40257180 WRITE   4842033\n0x40257140 WRITE   4842035\n0x401CC880 WRITE   4842119\n0x40257300 WRITE   4842503\n0x402572C0 WRITE   4842505\n0x40257280 WRITE   4842512\n0x40257240 WRITE   4842514\n0x401B9000 WRITE   4842547\n0x40257380 WRITE   4843010\n0x40257340 WRITE   4843012\n0x401CC8C0 WRITE   4843096\n0x40257600 WRITE   4843513\n0x402575C0 WRITE   4843515\n0x40257500 WRITE   4843522\n0x402574C0 WRITE   4843524\n0x40257480 WRITE   4843534\n0x40257440 WRITE   4843536\n0x401B9040 WRITE   4843563\n0x40257580 WRITE   4844004\n0x40257540 WRITE   4844006\n0x401CC900 WRITE   4844090\n0x40257700 WRITE   4844484\n0x402576C0 WRITE   4844486\n0x40257680 WRITE   4844493\n0x40257640 WRITE   4844495\n0x401B9080 WRITE   4844528\n0x40257780 WRITE   4845001\n0x40257740 WRITE   4845003\n0x401CC940 WRITE   4845087\n0x40257C00 WRITE   4845519\n0x40257BC0 WRITE   4845521\n0x40257A00 WRITE   4845528\n0x402579C0 WRITE   4845530\n0x40257900 WRITE   4845540\n0x402578C0 WRITE   4845542\n0x40257880 WRITE   4845547\n0x40257840 WRITE   4845550\n0x401B90C0 WRITE   4845575\n0x40257980 WRITE   4846014\n0x40257940 WRITE   4846016\n0x401CC980 WRITE   4846100\n0x40257B00 WRITE   4846492\n0x40257AC0 WRITE   4846494\n0x40257A80 WRITE   4846501\n0x40257A40 WRITE   4846503\n0x401B9100 WRITE   4846536\n0x40257B80 WRITE   4847007\n0x40257B40 WRITE   4847009\n0x401CC9C0 WRITE   4847093\n0x40257E00 WRITE   4847518\n0x40257DC0 WRITE   4847520\n0x40257D00 WRITE   4847527\n0x40257CC0 WRITE   4847529\n0x40257C80 WRITE   4847539\n0x40257C40 WRITE   4847541\n0x401B9140 WRITE   4847568\n0x40257D80 WRITE   4848016\n0x40257D40 WRITE   4848018\n0x401CCA00 WRITE   4848102\n0x40257F00 WRITE   4848503\n0x40257EC0 WRITE   4848505\n0x40257E80 WRITE   4848512\n0x40257E40 WRITE   4848514\n0x401B9180 WRITE   4848547\n0x40257F80 WRITE   4849027\n0x40257F40 WRITE   4849029\n0x401CCA40 WRITE   4849113\n0x40259FC0 WRITE   4849597\n0x4025A000 WRITE   4849631\n0x40259000 WRITE   4849747\n0x40258FC0 WRITE   4849749\n0x40258800 WRITE   4849756\n0x402587C0 WRITE   4849758\n0x40258400 WRITE   4849768\n0x402583C0 WRITE   4849770\n0x40258200 WRITE   4849775\n0x402581C0 WRITE   4849778\n0x40258100 WRITE   4849781\n0x402580C0 WRITE   4849784\n0x40258080 WRITE   4849787\n0x40258040 WRITE   4849790\n0x401B91C0 WRITE   4849823\n0x40258180 WRITE   4850253\n0x40258140 WRITE   4850255\n0x401CCA80 WRITE   4850339\n0x40258300 WRITE   4850718\n0x402582C0 WRITE   4850720\n0x40258280 WRITE   4850727\n0x40258240 WRITE   4850729\n0x401B9200 WRITE   4850762\n0x40258380 WRITE   4851225\n0x40258340 WRITE   4851227\n0x401CCAC0 WRITE   4851311\n0x40258600 WRITE   4851722\n0x402585C0 WRITE   4851724\n0x40258500 WRITE   4851731\n0x402584C0 WRITE   4851733\n0x40258480 WRITE   4851743\n0x40258440 WRITE   4851745\n0x401B9240 WRITE   4851772\n0x40258580 WRITE   4852213\n0x40258540 WRITE   4852215\n0x401CCB00 WRITE   4852299\n0x40258700 WRITE   4852687\n0x402586C0 WRITE   4852689\n0x40258680 WRITE   4852696\n0x40258640 WRITE   4852698\n0x401B9280 WRITE   4852731\n0x40258780 WRITE   4853204\n0x40258740 WRITE   4853206\n0x401CCB40 WRITE   4853290\n0x40258C00 WRITE   4853716\n0x40258BC0 WRITE   4853718\n0x40258A00 WRITE   4853725\n0x402589C0 WRITE   4853727\n0x40258900 WRITE   4853737\n0x402588C0 WRITE   4853739\n0x40258880 WRITE   4853744\n0x40258840 WRITE   4853747\n0x401B92C0 WRITE   4853772\n0x40258980 WRITE   4854211\n0x40258940 WRITE   4854213\n0x401CCB80 WRITE   4854297\n0x40258B00 WRITE   4854683\n0x40258AC0 WRITE   4854685\n0x40258A80 WRITE   4854692\n0x40258A40 WRITE   4854694\n0x401B9300 WRITE   4854727\n0x40258B80 WRITE   4855198\n0x40258B40 WRITE   4855200\n0x401CCBC0 WRITE   4855284\n0x40258E00 WRITE   4855703\n0x40258DC0 WRITE   4855705\n0x40258D00 WRITE   4855712\n0x40258CC0 WRITE   4855714\n0x40258C80 WRITE   4855724\n0x40258C40 WRITE   4855726\n0x401B9340 WRITE   4855753\n0x40258D80 WRITE   4856201\n0x40258D40 WRITE   4856203\n0x401CCC00 WRITE   4856287\n0x40258F00 WRITE   4856682\n0x40258EC0 WRITE   4856684\n0x40258E80 WRITE   4856691\n0x40258E40 WRITE   4856693\n0x401B9380 WRITE   4856726\n0x40258F80 WRITE   4857206\n0x40258F40 WRITE   4857208\n0x401CCC40 WRITE   4857292\n0x40259800 WRITE   4857724\n0x402597C0 WRITE   4857726\n0x40259400 WRITE   4857733\n0x402593C0 WRITE   4857735\n0x40259200 WRITE   4857745\n0x402591C0 WRITE   4857747\n0x40259100 WRITE   4857752\n0x402590C0 WRITE   4857755\n0x40259080 WRITE   4857758\n0x40259040 WRITE   4857761\n0x401B93C0 WRITE   4857786\n0x40259180 WRITE   4858217\n0x40259140 WRITE   4858219\n0x401CCC80 WRITE   4858303\n0x40259300 WRITE   4858687\n0x402592C0 WRITE   4858689\n0x40259280 WRITE   4858696\n0x40259240 WRITE   4858698\n0x401B9400 WRITE   4858731\n0x40259380 WRITE   4859194\n0x40259340 WRITE   4859196\n0x401CCCC0 WRITE   4859280\n0x40259600 WRITE   4859697\n0x402595C0 WRITE   4859699\n0x40259500 WRITE   4859706\n0x402594C0 WRITE   4859708\n0x40259480 WRITE   4859718\n0x40259440 WRITE   4859720\n0x401B9440 WRITE   4859747\n0x40259580 WRITE   4860188\n0x40259540 WRITE   4860190\n0x401CCD00 WRITE   4860274\n0x40259700 WRITE   4860668\n0x402596C0 WRITE   4860670\n0x40259680 WRITE   4860677\n0x40259640 WRITE   4860679\n0x401B9480 WRITE   4860712\n0x40259780 WRITE   4861185\n0x40259740 WRITE   4861187\n0x401CCD40 WRITE   4861271\n0x40259C00 WRITE   4861703\n0x40259BC0 WRITE   4861705\n0x40259A00 WRITE   4861712\n0x402599C0 WRITE   4861714\n0x40259900 WRITE   4861724\n0x402598C0 WRITE   4861726\n0x40259880 WRITE   4861731\n0x40259840 WRITE   4861734\n0x401B94C0 WRITE   4861759\n0x40259980 WRITE   4862198\n0x40259940 WRITE   4862200\n0x401CCD80 WRITE   4862284\n0x40259B00 WRITE   4862676\n0x40259AC0 WRITE   4862678\n0x40259A80 WRITE   4862685\n0x40259A40 WRITE   4862687\n0x401B9500 WRITE   4862720\n0x40259B80 WRITE   4863191\n0x40259B40 WRITE   4863193\n0x401CCDC0 WRITE   4863277\n0x40259E00 WRITE   4863702\n0x40259DC0 WRITE   4863704\n0x40259D00 WRITE   4863711\n0x40259CC0 WRITE   4863713\n0x40259C80 WRITE   4863723\n0x40259C40 WRITE   4863725\n0x401B9540 WRITE   4863752\n0x40259D80 WRITE   4864200\n0x40259D40 WRITE   4864202\n0x401CCE00 WRITE   4864286\n0x40259F00 WRITE   4864687\n0x40259EC0 WRITE   4864689\n0x40259E80 WRITE   4864696\n0x40259E40 WRITE   4864698\n0x401B9580 WRITE   4864731\n0x40259F80 WRITE   4865211\n0x40259F40 WRITE   4865213\n0x401CCE40 WRITE   4865297\n0x4025BFC0 WRITE   4865781\n0x4025C000 WRITE   4865815\n0x4025B000 WRITE   4865938\n0x4025AFC0 WRITE   4865940\n0x4025A800 WRITE   4865947\n0x4025A7C0 WRITE   4865949\n0x4025A400 WRITE   4865959\n0x4025A3C0 WRITE   4865961\n0x4025A200 WRITE   4865966\n0x4025A1C0 WRITE   4865969\n0x4025A100 WRITE   4865972\n0x4025A0C0 WRITE   4865975\n0x4025A080 WRITE   4865978\n0x4025A040 WRITE   4865981\n0x401B95C0 WRITE   4866014\n0x4025A180 WRITE   4866444\n0x4025A140 WRITE   4866446\n0x401CCE80 WRITE   4866530\n0x4025A300 WRITE   4866909\n0x4025A2C0 WRITE   4866911\n0x4025A280 WRITE   4866918\n0x4025A240 WRITE   4866920\n0x401B9600 WRITE   4866953\n0x4025A380 WRITE   4867416\n0x4025A340 WRITE   4867418\n0x401CCEC0 WRITE   4867502\n0x4025A600 WRITE   4867913\n0x4025A5C0 WRITE   4867915\n0x4025A500 WRITE   4867922\n0x4025A4C0 WRITE   4867924\n0x4025A480 WRITE   4867934\n0x4025A440 WRITE   4867936\n0x401B9640 WRITE   4867963\n0x4025A580 WRITE   4868404\n0x4025A540 WRITE   4868406\n0x401CCF00 WRITE   4868490\n0x4025A700 WRITE   4868878\n0x4025A6C0 WRITE   4868880\n0x4025A680 WRITE   4868887\n0x4025A640 WRITE   4868889\n0x401B9680 WRITE   4868922\n0x4025A780 WRITE   4869395\n0x4025A740 WRITE   4869397\n0x401CCF40 WRITE   4869481\n0x4025AC00 WRITE   4869907\n0x4025ABC0 WRITE   4869909\n0x4025AA00 WRITE   4869916\n0x4025A9C0 WRITE   4869918\n0x4025A900 WRITE   4869928\n0x4025A8C0 WRITE   4869930\n0x4025A880 WRITE   4869935\n0x4025A840 WRITE   4869938\n0x401B96C0 WRITE   4869963\n0x4025A980 WRITE   4870402\n0x4025A940 WRITE   4870404\n0x401CCF80 WRITE   4870488\n0x4025AB00 WRITE   4870874\n0x4025AAC0 WRITE   4870876\n0x4025AA80 WRITE   4870883\n0x4025AA40 WRITE   4870885\n0x401B9700 WRITE   4870918\n0x4025AB80 WRITE   4871389\n0x4025AB40 WRITE   4871391\n0x401CCFC0 WRITE   4871475\n0x4025AE00 WRITE   4871894\n0x4025ADC0 WRITE   4871896\n0x4025AD00 WRITE   4871903\n0x4025ACC0 WRITE   4871905\n0x4025AC80 WRITE   4871915\n0x4025AC40 WRITE   4871917\n0x401B9740 WRITE   4871944\n0x4025AD80 WRITE   4872392\n0x4025AD40 WRITE   4872394\n0x401CD000 WRITE   4872478\n0x4025AF00 WRITE   4872873\n0x4025AEC0 WRITE   4872875\n0x4025AE80 WRITE   4872882\n0x4025AE40 WRITE   4872884\n0x401B9780 WRITE   4872917\n0x4025AF80 WRITE   4873397\n0x4025AF40 WRITE   4873399\n0x401CD040 WRITE   4873483\n0x4025B800 WRITE   4873915\n0x4025B7C0 WRITE   4873917\n0x4025B400 WRITE   4873924\n0x4025B3C0 WRITE   4873926\n0x4025B200 WRITE   4873936\n0x4025B1C0 WRITE   4873938\n0x4025B100 WRITE   4873943\n0x4025B0C0 WRITE   4873946\n0x4025B080 WRITE   4873949\n0x4025B040 WRITE   4873952\n0x401B97C0 WRITE   4873977\n0x4025B180 WRITE   4874408\n0x4025B140 WRITE   4874410\n0x401CD080 WRITE   4874494\n0x4025B300 WRITE   4874878\n0x4025B2C0 WRITE   4874880\n0x4025B280 WRITE   4874887\n0x4025B240 WRITE   4874889\n0x401B9800 WRITE   4874922\n0x4025B380 WRITE   4875385\n0x4025B340 WRITE   4875387\n0x401CD0C0 WRITE   4875471\n0x4025B600 WRITE   4875888\n0x4025B5C0 WRITE   4875890\n0x4025B500 WRITE   4875897\n0x4025B4C0 WRITE   4875899\n0x4025B480 WRITE   4875909\n0x4025B440 WRITE   4875911\n0x401B9840 WRITE   4875938\n0x4025B580 WRITE   4876379\n0x4025B540 WRITE   4876381\n0x401CD100 WRITE   4876465\n0x4025B700 WRITE   4876859\n0x4025B6C0 WRITE   4876861\n0x4025B680 WRITE   4876868\n0x4025B640 WRITE   4876870\n0x401B9880 WRITE   4876903\n0x4025B780 WRITE   4877376\n0x4025B740 WRITE   4877378\n0x401CD140 WRITE   4877462\n0x4025BC00 WRITE   4877894\n0x4025BBC0 WRITE   4877896\n0x4025BA00 WRITE   4877903\n0x4025B9C0 WRITE   4877905\n0x4025B900 WRITE   4877915\n0x4025B8C0 WRITE   4877917\n0x4025B880 WRITE   4877922\n0x4025B840 WRITE   4877925\n0x401B98C0 WRITE   4877950\n0x4025B980 WRITE   4878389\n0x4025B940 WRITE   4878391\n0x401CD180 WRITE   4878475\n0x4025BB00 WRITE   4878867\n0x4025BAC0 WRITE   4878869\n0x4025BA80 WRITE   4878876\n0x4025BA40 WRITE   4878878\n0x401B9900 WRITE   4878911\n0x4025BB80 WRITE   4879382\n0x4025BB40 WRITE   4879384\n0x401CD1C0 WRITE   4879468\n0x4025BE00 WRITE   4879893\n0x4025BDC0 WRITE   4879895\n0x4025BD00 WRITE   4879902\n0x4025BCC0 WRITE   4879904\n0x4025BC80 WRITE   4879914\n0x4025BC40 WRITE   4879916\n0x401B9940 WRITE   4879943\n0x4025BD80 WRITE   4880391\n0x4025BD40 WRITE   4880393\n0x401CD200 WRITE   4880477\n0x4025BF00 WRITE   4880878\n0x4025BEC0 WRITE   4880880\n0x4025BE80 WRITE   4880887\n0x4025BE40 WRITE   4880889\n0x401B9980 WRITE   4880922\n0x4025BF80 WRITE   4881402\n0x4025BF40 WRITE   4881404\n0x401CD240 WRITE   4881488\n0x4025DFC0 WRITE   4881972\n0x4025E000 WRITE   4882006\n0x4025D000 WRITE   4882118\n0x4025CFC0 WRITE   4882120\n0x4025C800 WRITE   4882127\n0x4025C7C0 WRITE   4882129\n0x4025C400 WRITE   4882139\n0x4025C3C0 WRITE   4882141\n0x4025C200 WRITE   4882146\n0x4025C1C0 WRITE   4882149\n0x4025C100 WRITE   4882152\n0x4025C0C0 WRITE   4882155\n0x4025C080 WRITE   4882158\n0x4025C040 WRITE   4882161\n0x401B99C0 WRITE   4882194\n0x4025C180 WRITE   4882624\n0x4025C140 WRITE   4882626\n0x401CD280 WRITE   4882710\n0x4025C300 WRITE   4883089\n0x4025C2C0 WRITE   4883091\n0x4025C280 WRITE   4883098\n0x4025C240 WRITE   4883100\n0x401B9A00 WRITE   4883133\n0x4025C380 WRITE   4883596\n0x4025C340 WRITE   4883598\n0x401CD2C0 WRITE   4883682\n0x4025C600 WRITE   4884093\n0x4025C5C0 WRITE   4884095\n0x4025C500 WRITE   4884102\n0x4025C4C0 WRITE   4884104\n0x4025C480 WRITE   4884114\n0x4025C440 WRITE   4884116\n0x401B9A40 WRITE   4884143\n0x4025C580 WRITE   4884584\n0x4025C540 WRITE   4884586\n0x401CD300 WRITE   4884670\n0x4025C700 WRITE   4885058\n0x4025C6C0 WRITE   4885060\n0x4025C680 WRITE   4885067\n0x4025C640 WRITE   4885069\n0x401B9A80 WRITE   4885102\n0x4025C780 WRITE   4885575\n0x4025C740 WRITE   4885577\n0x401CD340 WRITE   4885661\n0x4025CC00 WRITE   4886087\n0x4025CBC0 WRITE   4886089\n0x4025CA00 WRITE   4886096\n0x4025C9C0 WRITE   4886098\n0x4025C900 WRITE   4886108\n0x4025C8C0 WRITE   4886110\n0x4025C880 WRITE   4886115\n0x4025C840 WRITE   4886118\n0x401B9AC0 WRITE   4886143\n0x4025C980 WRITE   4886582\n0x4025C940 WRITE   4886584\n0x401CD380 WRITE   4886668\n0x4025CB00 WRITE   4887054\n0x4025CAC0 WRITE   4887056\n0x4025CA80 WRITE   4887063\n0x4025CA40 WRITE   4887065\n0x401B9B00 WRITE   4887098\n0x4025CB80 WRITE   4887569\n0x4025CB40 WRITE   4887571\n0x401CD3C0 WRITE   4887655\n0x4025CE00 WRITE   4888074\n0x4025CDC0 WRITE   4888076\n0x4025CD00 WRITE   4888083\n0x4025CCC0 WRITE   4888085\n0x4025CC80 WRITE   4888095\n0x4025CC40 WRITE   4888097\n0x401B9B40 WRITE   4888124\n0x4025CD80 WRITE   4888572\n0x4025CD40 WRITE   4888574\n0x401CD400 WRITE   4888658\n0x4025CF00 WRITE   4889053\n0x4025CEC0 WRITE   4889055\n0x4025CE80 WRITE   4889062\n0x4025CE40 WRITE   4889064\n0x401B9B80 WRITE   4889097\n0x4025CF80 WRITE   4889577\n0x4025CF40 WRITE   4889579\n0x401CD440 WRITE   4889663\n0x4025D800 WRITE   4890095\n0x4025D7C0 WRITE   4890097\n0x4025D400 WRITE   4890104\n0x4025D3C0 WRITE   4890106\n0x4025D200 WRITE   4890116\n0x4025D1C0 WRITE   4890118\n0x4025D100 WRITE   4890123\n0x4025D0C0 WRITE   4890126\n0x4025D080 WRITE   4890129\n0x4025D040 WRITE   4890132\n0x401B9BC0 WRITE   4890157\n0x4025D180 WRITE   4890588\n0x4025D140 WRITE   4890590\n0x401CD480 WRITE   4890674\n0x4025D300 WRITE   4891058\n0x4025D2C0 WRITE   4891060\n0x4025D280 WRITE   4891067\n0x4025D240 WRITE   4891069\n0x401B9C00 WRITE   4891102\n0x4025D380 WRITE   4891565\n0x4025D340 WRITE   4891567\n0x401CD4C0 WRITE   4891651\n0x4025D600 WRITE   4892068\n0x4025D5C0 WRITE   4892070\n0x4025D500 WRITE   4892077\n0x4025D4C0 WRITE   4892079\n0x4025D480 WRITE   4892089\n0x4025D440 WRITE   4892091\n0x401B9C40 WRITE   4892118\n0x4025D580 WRITE   4892559\n0x4025D540 WRITE   4892561\n0x401CD500 WRITE   4892645\n0x4025D700 WRITE   4893039\n0x4025D6C0 WRITE   4893041\n0x4025D680 WRITE   4893048\n0x4025D640 WRITE   4893050\n0x401B9C80 WRITE   4893083\n0x4025D780 WRITE   4893556\n0x4025D740 WRITE   4893558\n0x401CD540 WRITE   4893642\n0x4025DC00 WRITE   4894074\n0x4025DBC0 WRITE   4894076\n0x4025DA00 WRITE   4894083\n0x4025D9C0 WRITE   4894085\n0x4025D900 WRITE   4894095\n0x4025D8C0 WRITE   4894097\n0x4025D880 WRITE   4894102\n0x4025D840 WRITE   4894105\n0x401B9CC0 WRITE   4894130\n0x4025D980 WRITE   4894569\n0x4025D940 WRITE   4894571\n0x401CD580 WRITE   4894655\n0x4025DB00 WRITE   4895047\n0x4025DAC0 WRITE   4895049\n0x4025DA80 WRITE   4895056\n0x4025DA40 WRITE   4895058\n0x401B9D00 WRITE   4895091\n0x4025DB80 WRITE   4895562\n0x4025DB40 WRITE   4895564\n0x401CD5C0 WRITE   4895648\n0x4025DE00 WRITE   4896073\n0x4025DDC0 WRITE   4896075\n0x4025DD00 WRITE   4896082\n0x4025DCC0 WRITE   4896084\n0x4025DC80 WRITE   4896094\n0x4025DC40 WRITE   4896096\n0x401B9D40 WRITE   4896123\n0x4025DD80 WRITE   4896571\n0x4025DD40 WRITE   4896573\n0x401CD600 WRITE   4896657\n0x4025DF00 WRITE   4897058\n0x4025DEC0 WRITE   4897060\n0x4025DE80 WRITE   4897067\n0x4025DE40 WRITE   4897069\n0x401B9D80 WRITE   4897102\n0x4025DF80 WRITE   4897582\n0x4025DF40 WRITE   4897584\n0x401CD640 WRITE   4897668\n0x4025FFC0 WRITE   4898152\n0x40260000 WRITE   4898186\n0x4025F000 WRITE   4898298\n0x4025EFC0 WRITE   4898300\n0x4025E800 WRITE   4898307\n0x4025E7C0 WRITE   4898309\n0x4025E400 WRITE   4898319\n0x4025E3C0 WRITE   4898321\n0x4025E200 WRITE   4898326\n0x4025E1C0 WRITE   4898329\n0x4025E100 WRITE   4898332\n0x4025E0C0 WRITE   4898335\n0x4025E080 WRITE   4898338\n0x4025E040 WRITE   4898341\n0x401B9DC0 WRITE   4898374\n0x4025E180 WRITE   4898804\n0x4025E140 WRITE   4898806\n0x401CD680 WRITE   4898890\n0x4025E300 WRITE   4899269\n0x4025E2C0 WRITE   4899271\n0x4025E280 WRITE   4899278\n0x4025E240 WRITE   4899280\n0x401B9E00 WRITE   4899313\n0x4025E380 WRITE   4899776\n0x4025E340 WRITE   4899778\n0x401CD6C0 WRITE   4899862\n0x4025E600 WRITE   4900273\n0x4025E5C0 WRITE   4900275\n0x4025E500 WRITE   4900282\n0x4025E4C0 WRITE   4900284\n0x4025E480 WRITE   4900294\n0x4025E440 WRITE   4900296\n0x401B9E40 WRITE   4900323\n0x4025E580 WRITE   4900764\n0x4025E540 WRITE   4900766\n0x401CD700 WRITE   4900850\n0x4025E700 WRITE   4901238\n0x4025E6C0 WRITE   4901240\n0x4025E680 WRITE   4901247\n0x4025E640 WRITE   4901249\n0x401B9E80 WRITE   4901282\n0x4025E780 WRITE   4901755\n0x4025E740 WRITE   4901757\n0x401CD740 WRITE   4901841\n0x4025EC00 WRITE   4902267\n0x4025EBC0 WRITE   4902269\n0x4025EA00 WRITE   4902276\n0x4025E9C0 WRITE   4902278\n0x4025E900 WRITE   4902288\n0x4025E8C0 WRITE   4902290\n0x4025E880 WRITE   4902295\n0x4025E840 WRITE   4902298\n0x401B9EC0 WRITE   4902323\n0x4025E980 WRITE   4902762\n0x4025E940 WRITE   4902764\n0x401CD780 WRITE   4902848\n0x4025EB00 WRITE   4903234\n0x4025EAC0 WRITE   4903236\n0x4025EA80 WRITE   4903243\n0x4025EA40 WRITE   4903245\n0x401B9F00 WRITE   4903278\n0x4025EB80 WRITE   4903749\n0x4025EB40 WRITE   4903751\n0x401CD7C0 WRITE   4903835\n0x4025EE00 WRITE   4904254\n0x4025EDC0 WRITE   4904256\n0x4025ED00 WRITE   4904263\n0x4025ECC0 WRITE   4904265\n0x4025EC80 WRITE   4904275\n0x4025EC40 WRITE   4904277\n0x401B9F40 WRITE   4904304\n0x4025ED80 WRITE   4904752\n0x4025ED40 WRITE   4904754\n0x401CD800 WRITE   4904838\n0x4025EF00 WRITE   4905233\n0x4025EEC0 WRITE   4905235\n0x4025EE80 WRITE   4905242\n0x4025EE40 WRITE   4905244\n0x401B9F80 WRITE   4905277\n0x4025EF80 WRITE   4905757\n0x4025EF40 WRITE   4905759\n0x401CD840 WRITE   4905843\n0x4025F800 WRITE   4906275\n0x4025F7C0 WRITE   4906277\n0x4025F400 WRITE   4906284\n0x4025F3C0 WRITE   4906286\n0x4025F200 WRITE   4906296\n0x4025F1C0 WRITE   4906298\n0x4025F100 WRITE   4906303\n0x4025F0C0 WRITE   4906306\n0x4025F080 WRITE   4906309\n0x4025F040 WRITE   4906312\n0x401B9FC0 WRITE   4906337\n0x4025F180 WRITE   4906768\n0x4025F140 WRITE   4906770\n0x401CD880 WRITE   4906854\n0x4025F300 WRITE   4907238\n0x4025F2C0 WRITE   4907240\n0x4025F280 WRITE   4907247\n0x4025F240 WRITE   4907249\n0x401BA000 WRITE   4907282\n0x4025F380 WRITE   4907745\n0x4025F340 WRITE   4907747\n0x401CD8C0 WRITE   4907831\n0x4025F600 WRITE   4908248\n0x4025F5C0 WRITE   4908250\n0x4025F500 WRITE   4908257\n0x4025F4C0 WRITE   4908259\n0x4025F480 WRITE   4908269\n0x4025F440 WRITE   4908271\n0x401BA040 WRITE   4908298\n0x4025F580 WRITE   4908739\n0x4025F540 WRITE   4908741\n0x401CD900 WRITE   4908825\n0x4025F700 WRITE   4909219\n0x4025F6C0 WRITE   4909221\n0x4025F680 WRITE   4909228\n0x4025F640 WRITE   4909230\n0x401BA080 WRITE   4909263\n0x4025F780 WRITE   4909736\n0x4025F740 WRITE   4909738\n0x401CD940 WRITE   4909822\n0x4025FC00 WRITE   4910254\n0x4025FBC0 WRITE   4910256\n0x4025FA00 WRITE   4910263\n0x4025F9C0 WRITE   4910265\n0x4025F900 WRITE   4910275\n0x4025F8C0 WRITE   4910277\n0x4025F880 WRITE   4910282\n0x4025F840 WRITE   4910285\n0x401BA0C0 WRITE   4910310\n0x4025F980 WRITE   4910749\n0x4025F940 WRITE   4910751\n0x401CD980 WRITE   4910835\n0x4025FB00 WRITE   4911227\n0x4025FAC0 WRITE   4911229\n0x4025FA80 WRITE   4911236\n0x4025FA40 WRITE   4911238\n0x401BA100 WRITE   4911271\n0x4025FB80 WRITE   4911742\n0x4025FB40 WRITE   4911744\n0x401CD9C0 WRITE   4911828\n0x4025FE00 WRITE   4912253\n0x4025FDC0 WRITE   4912255\n0x4025FD00 WRITE   4912262\n0x4025FCC0 WRITE   4912264\n0x4025FC80 WRITE   4912274\n0x4025FC40 WRITE   4912276\n0x401BA140 WRITE   4912303\n0x4025FD80 WRITE   4912751\n0x4025FD40 WRITE   4912753\n0x401CDA00 WRITE   4912837\n0x4025FF00 WRITE   4913238\n0x4025FEC0 WRITE   4913240\n0x4025FE80 WRITE   4913247\n0x4025FE40 WRITE   4913249\n0x401BA180 WRITE   4913282\n0x4025FF80 WRITE   4913762\n0x4025FF40 WRITE   4913764\n0x401CDA40 WRITE   4913848\n0x40261FC0 WRITE   4914332\n0x40262000 WRITE   4914366\n0x40261000 WRITE   4914480\n0x40260FC0 WRITE   4914482\n0x40260800 WRITE   4914489\n0x402607C0 WRITE   4914491\n0x40260400 WRITE   4914501\n0x402603C0 WRITE   4914503\n0x40260200 WRITE   4914508\n0x402601C0 WRITE   4914511\n0x40260100 WRITE   4914514\n0x402600C0 WRITE   4914517\n0x40260080 WRITE   4914520\n0x40260040 WRITE   4914523\n0x401BA1C0 WRITE   4914556\n0x40260180 WRITE   4914986\n0x40260140 WRITE   4914988\n0x401CDA80 WRITE   4915072\n0x40260300 WRITE   4915451\n0x402602C0 WRITE   4915453\n0x40260280 WRITE   4915460\n0x40260240 WRITE   4915462\n0x401BA200 WRITE   4915495\n0x40260380 WRITE   4915958\n0x40260340 WRITE   4915960\n0x401CDAC0 WRITE   4916044\n0x40260600 WRITE   4916455\n0x402605C0 WRITE   4916457\n0x40260500 WRITE   4916464\n0x402604C0 WRITE   4916466\n0x40260480 WRITE   4916476\n0x40260440 WRITE   4916478\n0x401BA240 WRITE   4916505\n0x40260580 WRITE   4916946\n0x40260540 WRITE   4916948\n0x401CDB00 WRITE   4917032\n0x40260700 WRITE   4917420\n0x402606C0 WRITE   4917422\n0x40260680 WRITE   4917429\n0x40260640 WRITE   4917431\n0x401BA280 WRITE   4917464\n0x40260780 WRITE   4917937\n0x40260740 WRITE   4917939\n0x401CDB40 WRITE   4918023\n0x40260C00 WRITE   4918449\n0x40260BC0 WRITE   4918451\n0x40260A00 WRITE   4918458\n0x402609C0 WRITE   4918460\n0x40260900 WRITE   4918470\n0x402608C0 WRITE   4918472\n0x40260880 WRITE   4918477\n0x40260840 WRITE   4918480\n0x401BA2C0 WRITE   4918505\n0x40260980 WRITE   4918944\n0x40260940 WRITE   4918946\n0x401CDB80 WRITE   4919030\n0x40260B00 WRITE   4919416\n0x40260AC0 WRITE   4919418\n0x40260A80 WRITE   4919425\n0x40260A40 WRITE   4919427\n0x401BA300 WRITE   4919460\n0x40260B80 WRITE   4919931\n0x40260B40 WRITE   4919933\n0x401CDBC0 WRITE   4920017\n0x40260E00 WRITE   4920436\n0x40260DC0 WRITE   4920438\n0x40260D00 WRITE   4920445\n0x40260CC0 WRITE   4920447\n0x40260C80 WRITE   4920457\n0x40260C40 WRITE   4920459\n0x401BA340 WRITE   4920486\n0x40260D80 WRITE   4920934\n0x40260D40 WRITE   4920936\n0x401CDC00 WRITE   4921020\n0x40260F00 WRITE   4921415\n0x40260EC0 WRITE   4921417\n0x40260E80 WRITE   4921424\n0x40260E40 WRITE   4921426\n0x401BA380 WRITE   4921459\n0x40260F80 WRITE   4921939\n0x40260F40 WRITE   4921941\n0x401CDC40 WRITE   4922025\n0x40261800 WRITE   4922457\n0x402617C0 WRITE   4922459\n0x40261400 WRITE   4922466\n0x402613C0 WRITE   4922468\n0x40261200 WRITE   4922478\n0x402611C0 WRITE   4922480\n0x40261100 WRITE   4922485\n0x402610C0 WRITE   4922488\n0x40261080 WRITE   4922491\n0x40261040 WRITE   4922494\n0x401BA3C0 WRITE   4922519\n0x40261180 WRITE   4922950\n0x40261140 WRITE   4922952\n0x401CDC80 WRITE   4923036\n0x40261300 WRITE   4923420\n0x402612C0 WRITE   4923422\n0x40261280 WRITE   4923429\n0x40261240 WRITE   4923431\n0x401BA400 WRITE   4923464\n0x40261380 WRITE   4923927\n0x40261340 WRITE   4923929\n0x401CDCC0 WRITE   4924013\n0x40261600 WRITE   4924430\n0x402615C0 WRITE   4924432\n0x40261500 WRITE   4924439\n0x402614C0 WRITE   4924441\n0x40261480 WRITE   4924451\n0x40261440 WRITE   4924453\n0x401BA440 WRITE   4924480\n0x40261580 WRITE   4924921\n0x40261540 WRITE   4924923\n0x401CDD00 WRITE   4925007\n0x40261700 WRITE   4925401\n0x402616C0 WRITE   4925403\n0x40261680 WRITE   4925410\n0x40261640 WRITE   4925412\n0x401BA480 WRITE   4925445\n0x40261780 WRITE   4925918\n0x40261740 WRITE   4925920\n0x401CDD40 WRITE   4926004\n0x40261C00 WRITE   4926436\n0x40261BC0 WRITE   4926438\n0x40261A00 WRITE   4926445\n0x402619C0 WRITE   4926447\n0x40261900 WRITE   4926457\n0x402618C0 WRITE   4926459\n0x40261880 WRITE   4926464\n0x40261840 WRITE   4926467\n0x401BA4C0 WRITE   4926492\n0x40261980 WRITE   4926931\n0x40261940 WRITE   4926933\n0x401CDD80 WRITE   4927017\n0x40261B00 WRITE   4927409\n0x40261AC0 WRITE   4927411\n0x40261A80 WRITE   4927418\n0x40261A40 WRITE   4927420\n0x401BA500 WRITE   4927453\n0x40261B80 WRITE   4927924\n0x40261B40 WRITE   4927926\n0x401CDDC0 WRITE   4928010\n0x40261E00 WRITE   4928435\n0x40261DC0 WRITE   4928437\n0x40261D00 WRITE   4928444\n0x40261CC0 WRITE   4928446\n0x40261C80 WRITE   4928456\n0x40261C40 WRITE   4928458\n0x401BA540 WRITE   4928485\n0x40261D80 WRITE   4928933\n0x40261D40 WRITE   4928935\n0x401CDE00 WRITE   4929019\n0x40261F00 WRITE   4929420\n0x40261EC0 WRITE   4929422\n0x40261E80 WRITE   4929429\n0x40261E40 WRITE   4929431\n0x401BA580 WRITE   4929464\n0x40261F80 WRITE   4929944\n0x40261F40 WRITE   4929946\n0x401CDE40 WRITE   4930030\n0x40263FC0 WRITE   4930514\n0x40264000 WRITE   4930548\n0x40263000 WRITE   4930660\n0x40262FC0 WRITE   4930662\n0x40262800 WRITE   4930669\n0x402627C0 WRITE   4930671\n0x40262400 WRITE   4930681\n0x402623C0 WRITE   4930683\n0x40262200 WRITE   4930688\n0x402621C0 WRITE   4930691\n0x40262100 WRITE   4930694\n0x402620C0 WRITE   4930697\n0x40262080 WRITE   4930700\n0x40262040 WRITE   4930703\n0x401BA5C0 WRITE   4930736\n0x40262180 WRITE   4931166\n0x40262140 WRITE   4931168\n0x401CDE80 WRITE   4931252\n0x40262300 WRITE   4931631\n0x402622C0 WRITE   4931633\n0x40262280 WRITE   4931640\n0x40262240 WRITE   4931642\n0x401BA600 WRITE   4931675\n0x40262380 WRITE   4932138\n0x40262340 WRITE   4932140\n0x401CDEC0 WRITE   4932224\n0x40262600 WRITE   4932635\n0x402625C0 WRITE   4932637\n0x40262500 WRITE   4932644\n0x402624C0 WRITE   4932646\n0x40262480 WRITE   4932656\n0x40262440 WRITE   4932658\n0x401BA640 WRITE   4932685\n0x40262580 WRITE   4933126\n0x40262540 WRITE   4933128\n0x401CDF00 WRITE   4933212\n0x40262700 WRITE   4933600\n0x402626C0 WRITE   4933602\n0x40262680 WRITE   4933609\n0x40262640 WRITE   4933611\n0x401BA680 WRITE   4933644\n0x40262780 WRITE   4934117\n0x40262740 WRITE   4934119\n0x401CDF40 WRITE   4934203\n0x40262C00 WRITE   4934629\n0x40262BC0 WRITE   4934631\n0x40262A00 WRITE   4934638\n0x402629C0 WRITE   4934640\n0x40262900 WRITE   4934650\n0x402628C0 WRITE   4934652\n0x40262880 WRITE   4934657\n0x40262840 WRITE   4934660\n0x401BA6C0 WRITE   4934685\n0x40262980 WRITE   4935124\n0x40262940 WRITE   4935126\n0x401CDF80 WRITE   4935210\n0x40262B00 WRITE   4935596\n0x40262AC0 WRITE   4935598\n0x40262A80 WRITE   4935605\n0x40262A40 WRITE   4935607\n0x401BA700 WRITE   4935640\n0x40262B80 WRITE   4936111\n0x40262B40 WRITE   4936113\n0x401CDFC0 WRITE   4936197\n0x40262E00 WRITE   4936616\n0x40262DC0 WRITE   4936618\n0x40262D00 WRITE   4936625\n0x40262CC0 WRITE   4936627\n0x40262C80 WRITE   4936637\n0x40262C40 WRITE   4936639\n0x401BA740 WRITE   4936666\n0x40262D80 WRITE   4937114\n0x40262D40 WRITE   4937116\n0x401CE000 WRITE   4937200\n0x40262F00 WRITE   4937595\n0x40262EC0 WRITE   4937597\n0x40262E80 WRITE   4937604\n0x40262E40 WRITE   4937606\n0x401BA780 WRITE   4937639\n0x40262F80 WRITE   4938119\n0x40262F40 WRITE   4938121\n0x401CE040 WRITE   4938205\n0x40263800 WRITE   4938637\n0x402637C0 WRITE   4938639\n0x40263400 WRITE   4938646\n0x402633C0 WRITE   4938648\n0x40263200 WRITE   4938658\n0x402631C0 WRITE   4938660\n0x40263100 WRITE   4938665\n0x402630C0 WRITE   4938668\n0x40263080 WRITE   4938671\n0x40263040 WRITE   4938674\n0x401BA7C0 WRITE   4938699\n0x40263180 WRITE   4939130\n0x40263140 WRITE   4939132\n0x401CE080 WRITE   4939216\n0x40263300 WRITE   4939600\n0x402632C0 WRITE   4939602\n0x40263280 WRITE   4939609\n0x40263240 WRITE   4939611\n0x401BA800 WRITE   4939644\n0x40263380 WRITE   4940107\n0x40263340 WRITE   4940109\n0x401CE0C0 WRITE   4940193\n0x40263600 WRITE   4940610\n0x402635C0 WRITE   4940612\n0x40263500 WRITE   4940619\n0x402634C0 WRITE   4940621\n0x40263480 WRITE   4940631\n0x40263440 WRITE   4940633\n0x401BA840 WRITE   4940660\n0x40263580 WRITE   4941101\n0x40263540 WRITE   4941103\n0x401CE100 WRITE   4941187\n0x40263700 WRITE   4941581\n0x402636C0 WRITE   4941583\n0x40263680 WRITE   4941590\n0x40263640 WRITE   4941592\n0x401BA880 WRITE   4941625\n0x40263780 WRITE   4942098\n0x40263740 WRITE   4942100\n0x401CE140 WRITE   4942184\n0x40263C00 WRITE   4942616\n0x40263BC0 WRITE   4942618\n0x40263A00 WRITE   4942625\n0x402639C0 WRITE   4942627\n0x40263900 WRITE   4942637\n0x402638C0 WRITE   4942639\n0x40263880 WRITE   4942644\n0x40263840 WRITE   4942647\n0x401BA8C0 WRITE   4942672\n0x40263980 WRITE   4943111\n0x40263940 WRITE   4943113\n0x401CE180 WRITE   4943197\n0x40263B00 WRITE   4943589\n0x40263AC0 WRITE   4943591\n0x40263A80 WRITE   4943598\n0x40263A40 WRITE   4943600\n0x401BA900 WRITE   4943633\n0x40263B80 WRITE   4944104\n0x40263B40 WRITE   4944106\n0x401CE1C0 WRITE   4944190\n0x40263E00 WRITE   4944615\n0x40263DC0 WRITE   4944617\n0x40263D00 WRITE   4944624\n0x40263CC0 WRITE   4944626\n0x40263C80 WRITE   4944636\n0x40263C40 WRITE   4944638\n0x401BA940 WRITE   4944665\n0x40263D80 WRITE   4945113\n0x40263D40 WRITE   4945115\n0x401CE200 WRITE   4945199\n0x40263F00 WRITE   4945600\n0x40263EC0 WRITE   4945602\n0x40263E80 WRITE   4945609\n0x40263E40 WRITE   4945611\n0x401BA980 WRITE   4945644\n0x40263F80 WRITE   4946124\n0x40263F40 WRITE   4946126\n0x401CE240 WRITE   4946210\n0x40265FC0 WRITE   4946694\n0x40266000 WRITE   4946728\n0x40265000 WRITE   4946840\n0x40264FC0 WRITE   4946842\n0x40264800 WRITE   4946849\n0x402647C0 WRITE   4946851\n0x40264400 WRITE   4946861\n0x402643C0 WRITE   4946863\n0x40264200 WRITE   4946868\n0x402641C0 WRITE   4946871\n0x40264100 WRITE   4946874\n0x402640C0 WRITE   4946877\n0x40264080 WRITE   4946880\n0x40264040 WRITE   4946883\n0x401BA9C0 WRITE   4946916\n0x40264180 WRITE   4947346\n0x40264140 WRITE   4947348\n0x401CE280 WRITE   4947432\n0x40264300 WRITE   4947811\n0x402642C0 WRITE   4947813\n0x40264280 WRITE   4947820\n0x40264240 WRITE   4947822\n0x401BAA00 WRITE   4947855\n0x40264380 WRITE   4948318\n0x40264340 WRITE   4948320\n0x401CE2C0 WRITE   4948404\n0x40264600 WRITE   4948815\n0x402645C0 WRITE   4948817\n0x40264500 WRITE   4948824\n0x402644C0 WRITE   4948826\n0x40264480 WRITE   4948836\n0x40264440 WRITE   4948838\n0x401BAA40 WRITE   4948865\n0x40264580 WRITE   4949306\n0x40264540 WRITE   4949308\n0x401CE300 WRITE   4949392\n0x40264700 WRITE   4949780\n0x402646C0 WRITE   4949782\n0x40264680 WRITE   4949789\n0x40264640 WRITE   4949791\n0x401BAA80 WRITE   4949824\n0x40264780 WRITE   4950297\n0x40264740 WRITE   4950299\n0x401CE340 WRITE   4950383\n0x40264C00 WRITE   4950809\n0x40264BC0 WRITE   4950811\n0x40264A00 WRITE   4950818\n0x402649C0 WRITE   4950820\n0x40264900 WRITE   4950830\n0x402648C0 WRITE   4950832\n0x40264880 WRITE   4950837\n0x40264840 WRITE   4950840\n0x401BAAC0 WRITE   4950865\n0x40264980 WRITE   4951304\n0x40264940 WRITE   4951306\n0x401CE380 WRITE   4951390\n0x40264B00 WRITE   4951776\n0x40264AC0 WRITE   4951778\n0x40264A80 WRITE   4951785\n0x40264A40 WRITE   4951787\n0x401BAB00 WRITE   4951820\n0x40264B80 WRITE   4952291\n0x40264B40 WRITE   4952293\n0x401CE3C0 WRITE   4952377\n0x40264E00 WRITE   4952796\n0x40264DC0 WRITE   4952798\n0x40264D00 WRITE   4952805\n0x40264CC0 WRITE   4952807\n0x40264C80 WRITE   4952817\n0x40264C40 WRITE   4952819\n0x401BAB40 WRITE   4952846\n0x40264D80 WRITE   4953294\n0x40264D40 WRITE   4953296\n0x401CE400 WRITE   4953380\n0x40264F00 WRITE   4953775\n0x40264EC0 WRITE   4953777\n0x40264E80 WRITE   4953784\n0x40264E40 WRITE   4953786\n0x401BAB80 WRITE   4953819\n0x40264F80 WRITE   4954299\n0x40264F40 WRITE   4954301\n0x401CE440 WRITE   4954385\n0x40265800 WRITE   4954817\n0x402657C0 WRITE   4954819\n0x40265400 WRITE   4954826\n0x402653C0 WRITE   4954828\n0x40265200 WRITE   4954838\n0x402651C0 WRITE   4954840\n0x40265100 WRITE   4954845\n0x402650C0 WRITE   4954848\n0x40265080 WRITE   4954851\n0x40265040 WRITE   4954854\n0x401BABC0 WRITE   4954879\n0x40265180 WRITE   4955310\n0x40265140 WRITE   4955312\n0x401CE480 WRITE   4955396\n0x40265300 WRITE   4955780\n0x402652C0 WRITE   4955782\n0x40265280 WRITE   4955789\n0x40265240 WRITE   4955791\n0x401BAC00 WRITE   4955824\n0x40265380 WRITE   4956287\n0x40265340 WRITE   4956289\n0x401CE4C0 WRITE   4956373\n0x40265600 WRITE   4956790\n0x402655C0 WRITE   4956792\n0x40265500 WRITE   4956799\n0x402654C0 WRITE   4956801\n0x40265480 WRITE   4956811\n0x40265440 WRITE   4956813\n0x401BAC40 WRITE   4956840\n0x40265580 WRITE   4957281\n0x40265540 WRITE   4957283\n0x401CE500 WRITE   4957367\n0x40265700 WRITE   4957761\n0x402656C0 WRITE   4957763\n0x40265680 WRITE   4957770\n0x40265640 WRITE   4957772\n0x401BAC80 WRITE   4957805\n0x40265780 WRITE   4958278\n0x40265740 WRITE   4958280\n0x401CE540 WRITE   4958364\n0x40265C00 WRITE   4958796\n0x40265BC0 WRITE   4958798\n0x40265A00 WRITE   4958805\n0x402659C0 WRITE   4958807\n0x40265900 WRITE   4958817\n0x402658C0 WRITE   4958819\n0x40265880 WRITE   4958824\n0x40265840 WRITE   4958827\n0x401BACC0 WRITE   4958852\n0x40265980 WRITE   4959291\n0x40265940 WRITE   4959293\n0x401CE580 WRITE   4959377\n0x40265B00 WRITE   4959769\n0x40265AC0 WRITE   4959771\n0x40265A80 WRITE   4959778\n0x40265A40 WRITE   4959780\n0x401BAD00 WRITE   4959813\n0x40265B80 WRITE   4960284\n0x40265B40 WRITE   4960286\n0x401CE5C0 WRITE   4960370\n0x40265E00 WRITE   4960795\n0x40265DC0 WRITE   4960797\n0x40265D00 WRITE   4960804\n0x40265CC0 WRITE   4960806\n0x40265C80 WRITE   4960816\n0x40265C40 WRITE   4960818\n0x401BAD40 WRITE   4960845\n0x40265D80 WRITE   4961293\n0x40265D40 WRITE   4961295\n0x401CE600 WRITE   4961379\n0x40265F00 WRITE   4961780\n0x40265EC0 WRITE   4961782\n0x40265E80 WRITE   4961789\n0x40265E40 WRITE   4961791\n0x401BAD80 WRITE   4961824\n0x40265F80 WRITE   4962304\n0x40265F40 WRITE   4962306\n0x401CE640 WRITE   4962390\n0x40267FC0 WRITE   4962874\n0x40268000 WRITE   4962908\n0x40267000 WRITE   4963020\n0x40266FC0 WRITE   4963022\n0x40266800 WRITE   4963029\n0x402667C0 WRITE   4963031\n0x40266400 WRITE   4963041\n0x402663C0 WRITE   4963043\n0x40266200 WRITE   4963048\n0x402661C0 WRITE   4963051\n0x40266100 WRITE   4963054\n0x402660C0 WRITE   4963057\n0x40266080 WRITE   4963060\n0x40266040 WRITE   4963063\n0x401BADC0 WRITE   4963096\n0x40266180 WRITE   4963526\n0x40266140 WRITE   4963528\n0x401CE680 WRITE   4963612\n0x40266300 WRITE   4963991\n0x402662C0 WRITE   4963993\n0x40266280 WRITE   4964000\n0x40266240 WRITE   4964002\n0x401BAE00 WRITE   4964035\n0x40266380 WRITE   4964498\n0x40266340 WRITE   4964500\n0x401CE6C0 WRITE   4964584\n0x40266600 WRITE   4964995\n0x402665C0 WRITE   4964997\n0x40266500 WRITE   4965004\n0x402664C0 WRITE   4965006\n0x40266480 WRITE   4965016\n0x40266440 WRITE   4965018\n0x401BAE40 WRITE   4965045\n0x40266580 WRITE   4965486\n0x40266540 WRITE   4965488\n0x401CE700 WRITE   4965572\n0x40266700 WRITE   4965960\n0x402666C0 WRITE   4965962\n0x40266680 WRITE   4965969\n0x40266640 WRITE   4965971\n0x401BAE80 WRITE   4966004\n0x40266780 WRITE   4966477\n0x40266740 WRITE   4966479\n0x401CE740 WRITE   4966563\n0x40266C00 WRITE   4966989\n0x40266BC0 WRITE   4966991\n0x40266A00 WRITE   4966998\n0x402669C0 WRITE   4967000\n0x40266900 WRITE   4967010\n0x402668C0 WRITE   4967012\n0x40266880 WRITE   4967017\n0x40266840 WRITE   4967020\n0x401BAEC0 WRITE   4967045\n0x40266980 WRITE   4967484\n0x40266940 WRITE   4967486\n0x401CE780 WRITE   4967570\n0x40266B00 WRITE   4967956\n0x40266AC0 WRITE   4967958\n0x40266A80 WRITE   4967965\n0x40266A40 WRITE   4967967\n0x401BAF00 WRITE   4968000\n0x40266B80 WRITE   4968471\n0x40266B40 WRITE   4968473\n0x401CE7C0 WRITE   4968557\n0x40266E00 WRITE   4968976\n0x40266DC0 WRITE   4968978\n0x40266D00 WRITE   4968985\n0x40266CC0 WRITE   4968987\n0x40266C80 WRITE   4968997\n0x40266C40 WRITE   4968999\n0x401BAF40 WRITE   4969026\n0x40266D80 WRITE   4969474\n0x40266D40 WRITE   4969476\n0x401CE800 WRITE   4969560\n0x40266F00 WRITE   4969955\n0x40266EC0 WRITE   4969957\n0x40266E80 WRITE   4969964\n0x40266E40 WRITE   4969966\n0x401BAF80 WRITE   4969999\n0x40266F80 WRITE   4970479\n0x40266F40 WRITE   4970481\n0x401CE840 WRITE   4970565\n0x40267800 WRITE   4970997\n0x402677C0 WRITE   4970999\n0x40267400 WRITE   4971006\n0x402673C0 WRITE   4971008\n0x40267200 WRITE   4971018\n0x402671C0 WRITE   4971020\n0x40267100 WRITE   4971025\n0x402670C0 WRITE   4971028\n0x40267080 WRITE   4971031\n0x40267040 WRITE   4971034\n0x401BAFC0 WRITE   4971059\n0x40267180 WRITE   4971490\n0x40267140 WRITE   4971492\n0x401CE880 WRITE   4971576\n0x40267300 WRITE   4971960\n0x402672C0 WRITE   4971962\n0x40267280 WRITE   4971969\n0x40267240 WRITE   4971971\n0x401BB000 WRITE   4972004\n0x40267380 WRITE   4972467\n0x40267340 WRITE   4972469\n0x401CE8C0 WRITE   4972553\n0x40267600 WRITE   4972970\n0x402675C0 WRITE   4972972\n0x40267500 WRITE   4972979\n0x402674C0 WRITE   4972981\n0x40267480 WRITE   4972991\n0x40267440 WRITE   4972993\n0x401BB040 WRITE   4973020\n0x40267580 WRITE   4973461\n0x40267540 WRITE   4973463\n0x401CE900 WRITE   4973547\n0x40267700 WRITE   4973941\n0x402676C0 WRITE   4973943\n0x40267680 WRITE   4973950\n0x40267640 WRITE   4973952\n0x401BB080 WRITE   4973985\n0x40267780 WRITE   4974458\n0x40267740 WRITE   4974460\n0x401CE940 WRITE   4974544\n0x40267C00 WRITE   4974976\n0x40267BC0 WRITE   4974978\n0x40267A00 WRITE   4974985\n0x402679C0 WRITE   4974987\n0x40267900 WRITE   4974997\n0x402678C0 WRITE   4974999\n0x40267880 WRITE   4975004\n0x40267840 WRITE   4975007\n0x401BB0C0 WRITE   4975032\n0x40267980 WRITE   4975471\n0x40267940 WRITE   4975473\n0x401CE980 WRITE   4975557\n0x40267B00 WRITE   4975949\n0x40267AC0 WRITE   4975951\n0x40267A80 WRITE   4975958\n0x40267A40 WRITE   4975960\n0x401BB100 WRITE   4975993\n0x40267B80 WRITE   4976464\n0x40267B40 WRITE   4976466\n0x401CE9C0 WRITE   4976550\n0x40267E00 WRITE   4976975\n0x40267DC0 WRITE   4976977\n0x40267D00 WRITE   4976984\n0x40267CC0 WRITE   4976986\n0x40267C80 WRITE   4976996\n0x40267C40 WRITE   4976998\n0x401BB140 WRITE   4977025\n0x40267D80 WRITE   4977473\n0x40267D40 WRITE   4977475\n0x401CEA00 WRITE   4977559\n0x40267F00 WRITE   4977960\n0x40267EC0 WRITE   4977962\n0x40267E80 WRITE   4977969\n0x40267E40 WRITE   4977971\n0x401BB180 WRITE   4978004\n0x40267F80 WRITE   4978484\n0x40267F40 WRITE   4978486\n0x401CEA40 WRITE   4978570\n0x40269FC0 WRITE   4979054\n0x4026A000 WRITE   4979088\n0x40269000 WRITE   4979200\n0x40268FC0 WRITE   4979202\n0x40268800 WRITE   4979209\n0x402687C0 WRITE   4979211\n0x40268400 WRITE   4979221\n0x402683C0 WRITE   4979223\n0x40268200 WRITE   4979228\n0x402681C0 WRITE   4979231\n0x40268100 WRITE   4979234\n0x402680C0 WRITE   4979237\n0x40268080 WRITE   4979240\n0x40268040 WRITE   4979243\n0x401BB1C0 WRITE   4979276\n0x40268180 WRITE   4979706\n0x40268140 WRITE   4979708\n0x401CEA80 WRITE   4979792\n0x40268300 WRITE   4980171\n0x402682C0 WRITE   4980173\n0x40268280 WRITE   4980180\n0x40268240 WRITE   4980182\n0x401BB200 WRITE   4980215\n0x40268380 WRITE   4980678\n0x40268340 WRITE   4980680\n0x401CEAC0 WRITE   4980764\n0x40268600 WRITE   4981175\n0x402685C0 WRITE   4981177\n0x40268500 WRITE   4981184\n0x402684C0 WRITE   4981186\n0x40268480 WRITE   4981196\n0x40268440 WRITE   4981198\n0x401BB240 WRITE   4981225\n0x40268580 WRITE   4981666\n0x40268540 WRITE   4981668\n0x401CEB00 WRITE   4981752\n0x40268700 WRITE   4982140\n0x402686C0 WRITE   4982142\n0x40268680 WRITE   4982149\n0x40268640 WRITE   4982151\n0x401BB280 WRITE   4982184\n0x40268780 WRITE   4982657\n0x40268740 WRITE   4982659\n0x401CEB40 WRITE   4982743\n0x40268C00 WRITE   4983169\n0x40268BC0 WRITE   4983171\n0x40268A00 WRITE   4983178\n0x402689C0 WRITE   4983180\n0x40268900 WRITE   4983190\n0x402688C0 WRITE   4983192\n0x40268880 WRITE   4983197\n0x40268840 WRITE   4983200\n0x401BB2C0 WRITE   4983225\n0x40268980 WRITE   4983664\n0x40268940 WRITE   4983666\n0x401CEB80 WRITE   4983750\n0x40268B00 WRITE   4984136\n0x40268AC0 WRITE   4984138\n0x40268A80 WRITE   4984145\n0x40268A40 WRITE   4984147\n0x401BB300 WRITE   4984180\n0x40268B80 WRITE   4984651\n0x40268B40 WRITE   4984653\n0x401CEBC0 WRITE   4984737\n0x40268E00 WRITE   4985156\n0x40268DC0 WRITE   4985158\n0x40268D00 WRITE   4985165\n0x40268CC0 WRITE   4985167\n0x40268C80 WRITE   4985177\n0x40268C40 WRITE   4985179\n0x401BB340 WRITE   4985206\n0x40268D80 WRITE   4985654\n0x40268D40 WRITE   4985656\n0x401CEC00 WRITE   4985740\n0x40268F00 WRITE   4986135\n0x40268EC0 WRITE   4986137\n0x40268E80 WRITE   4986144\n0x40268E40 WRITE   4986146\n0x401BB380 WRITE   4986179\n0x40268F80 WRITE   4986659\n0x40268F40 WRITE   4986661\n0x401CEC40 WRITE   4986745\n0x40269800 WRITE   4987177\n0x402697C0 WRITE   4987179\n0x40269400 WRITE   4987186\n0x402693C0 WRITE   4987188\n0x40269200 WRITE   4987198\n0x402691C0 WRITE   4987200\n0x40269100 WRITE   4987205\n0x402690C0 WRITE   4987208\n0x40269080 WRITE   4987211\n0x40269040 WRITE   4987214\n0x401BB3C0 WRITE   4987239\n0x40269180 WRITE   4987670\n0x40269140 WRITE   4987672\n0x401CEC80 WRITE   4987756\n0x40269300 WRITE   4988140\n0x402692C0 WRITE   4988142\n0x40269280 WRITE   4988149\n0x40269240 WRITE   4988151\n0x401BB400 WRITE   4988184\n0x40269380 WRITE   4988647\n0x40269340 WRITE   4988649\n0x401CECC0 WRITE   4988733\n0x40269600 WRITE   4989150\n0x402695C0 WRITE   4989152\n0x40269500 WRITE   4989159\n0x402694C0 WRITE   4989161\n0x40269480 WRITE   4989171\n0x40269440 WRITE   4989173\n0x401BB440 WRITE   4989200\n0x40269580 WRITE   4989641\n0x40269540 WRITE   4989643\n0x401CED00 WRITE   4989727\n0x40269700 WRITE   4990121\n0x402696C0 WRITE   4990123\n0x40269680 WRITE   4990130\n0x40269640 WRITE   4990132\n0x401BB480 WRITE   4990165\n0x40269780 WRITE   4990638\n0x40269740 WRITE   4990640\n0x401CED40 WRITE   4990724\n0x40269C00 WRITE   4991156\n0x40269BC0 WRITE   4991158\n0x40269A00 WRITE   4991165\n0x402699C0 WRITE   4991167\n0x40269900 WRITE   4991177\n0x402698C0 WRITE   4991179\n0x40269880 WRITE   4991184\n0x40269840 WRITE   4991187\n0x401BB4C0 WRITE   4991212\n0x40269980 WRITE   4991651\n0x40269940 WRITE   4991653\n0x401CED80 WRITE   4991737\n0x40269B00 WRITE   4992129\n0x40269AC0 WRITE   4992131\n0x40269A80 WRITE   4992138\n0x40269A40 WRITE   4992140\n0x401BB500 WRITE   4992173\n0x40269B80 WRITE   4992644\n0x40269B40 WRITE   4992646\n0x401CEDC0 WRITE   4992730\n0x40269E00 WRITE   4993155\n0x40269DC0 WRITE   4993157\n0x40269D00 WRITE   4993164\n0x40269CC0 WRITE   4993166\n0x40269C80 WRITE   4993176\n0x40269C40 WRITE   4993178\n0x401BB540 WRITE   4993205\n0x40269D80 WRITE   4993653\n0x40269D40 WRITE   4993655\n0x401CEE00 WRITE   4993739\n0x40269F00 WRITE   4994140\n0x40269EC0 WRITE   4994142\n0x40269E80 WRITE   4994149\n0x40269E40 WRITE   4994151\n0x401BB580 WRITE   4994184\n0x40269F80 WRITE   4994664\n0x40269F40 WRITE   4994666\n0x401CEE40 WRITE   4994750\n0x4026BFC0 WRITE   4995234\n0x4026C000 WRITE   4995274\n0x4026B000 WRITE   4995381\n0x4026AFC0 WRITE   4995383\n0x4026A800 WRITE   4995390\n0x4026A7C0 WRITE   4995392\n0x4026A400 WRITE   4995402\n0x4026A3C0 WRITE   4995404\n0x4026A200 WRITE   4995409\n0x4026A1C0 WRITE   4995412\n0x4026A100 WRITE   4995415\n0x4026A0C0 WRITE   4995418\n0x4026A080 WRITE   4995421\n0x4026A040 WRITE   4995424\n0x401BB5C0 WRITE   4995457\n0x4026A180 WRITE   4995887\n0x4026A140 WRITE   4995889\n0x401CEE80 WRITE   4995973\n0x4026A300 WRITE   4996352\n0x4026A2C0 WRITE   4996354\n0x4026A280 WRITE   4996361\n0x4026A240 WRITE   4996363\n0x401BB600 WRITE   4996396\n0x4026A380 WRITE   4996859\n0x4026A340 WRITE   4996861\n0x401CEEC0 WRITE   4996945\n0x4026A600 WRITE   4997356\n0x4026A5C0 WRITE   4997358\n0x4026A500 WRITE   4997365\n0x4026A4C0 WRITE   4997367\n0x4026A480 WRITE   4997377\n0x4026A440 WRITE   4997379\n0x401BB640 WRITE   4997406\n0x4026A580 WRITE   4997847\n0x4026A540 WRITE   4997849\n0x401CEF00 WRITE   4997933\n0x4026A700 WRITE   4998321\n0x4026A6C0 WRITE   4998323\n0x4026A680 WRITE   4998330\n0x4026A640 WRITE   4998332\n0x401BB680 WRITE   4998365\n0x4026A780 WRITE   4998838\n0x4026A740 WRITE   4998840\n0x401CEF40 WRITE   4998924\n0x4026AC00 WRITE   4999350\n0x4026ABC0 WRITE   4999352\n0x4026AA00 WRITE   4999359\n0x4026A9C0 WRITE   4999361\n0x4026A900 WRITE   4999371\n0x4026A8C0 WRITE   4999373\n0x4026A880 WRITE   4999378\n0x4026A840 WRITE   4999381\n0x401BB6C0 WRITE   4999406\n0x4026A980 WRITE   4999845\n0x4026A940 WRITE   4999847\n0x401CEF80 WRITE   4999931\n0x4026AB00 WRITE   5000317\n0x4026AAC0 WRITE   5000319\n0x4026AA80 WRITE   5000326\n0x4026AA40 WRITE   5000328\n0x401BB700 WRITE   5000361\n0x4026AB80 WRITE   5000832\n0x4026AB40 WRITE   5000834\n0x401CEFC0 WRITE   5000918\n0x4026AE00 WRITE   5001337\n0x4026ADC0 WRITE   5001339\n0x4026AD00 WRITE   5001346\n0x4026ACC0 WRITE   5001348\n0x4026AC80 WRITE   5001358\n0x4026AC40 WRITE   5001360\n0x401BB740 WRITE   5001387\n0x4026AD80 WRITE   5001835\n0x4026AD40 WRITE   5001837\n0x401CF000 WRITE   5001921\n0x4026AF00 WRITE   5002316\n0x4026AEC0 WRITE   5002318\n0x4026AE80 WRITE   5002325\n0x4026AE40 WRITE   5002327\n0x401BB780 WRITE   5002360\n0x4026AF80 WRITE   5002840\n0x4026AF40 WRITE   5002842\n0x401CF040 WRITE   5002926\n0x4026B800 WRITE   5003358\n0x4026B7C0 WRITE   5003360\n0x4026B400 WRITE   5003367\n0x4026B3C0 WRITE   5003369\n0x4026B200 WRITE   5003379\n0x4026B1C0 WRITE   5003381\n0x4026B100 WRITE   5003386\n0x4026B0C0 WRITE   5003389\n0x4026B080 WRITE   5003392\n0x4026B040 WRITE   5003395\n0x401BB7C0 WRITE   5003420\n0x4026B180 WRITE   5003851\n0x4026B140 WRITE   5003853\n0x401CF080 WRITE   5003937\n0x4026B300 WRITE   5004321\n0x4026B2C0 WRITE   5004323\n0x4026B280 WRITE   5004330\n0x4026B240 WRITE   5004332\n0x401BB800 WRITE   5004365\n0x4026B380 WRITE   5004828\n0x4026B340 WRITE   5004830\n0x401CF0C0 WRITE   5004914\n0x4026B600 WRITE   5005331\n0x4026B5C0 WRITE   5005333\n0x4026B500 WRITE   5005340\n0x4026B4C0 WRITE   5005342\n0x4026B480 WRITE   5005352\n0x4026B440 WRITE   5005354\n0x401BB840 WRITE   5005381\n0x4026B580 WRITE   5005822\n0x4026B540 WRITE   5005824\n0x20010940 READ  5006257\n0x20010980 READ  5006427\n0x200109C0 READ  5006521\n0x20010A00 READ  5006620\n0x20010A40 READ  5147234\n0x20010A80 READ  5147329\n0x20010AC0 READ  5147412\n0x20011D00 READ  5147510\n0x2000ED00 READ  5477989\n0x2000ED40 READ  5478149\n0x2000E640 READ  5478234\n0x2000E680 READ  5478319\n0x2000E6C0 READ  5478412\n0x2000E700 READ  5478497\n0x2000E740 READ  5571993\n0x2000E780 READ  5572086\n0x2000E7C0 READ  5572177\n0x2000E800 READ  5572269\n0x2000ED80 READ  5572363\n0x2000EDC0 READ  5572452\n0x2000EE00 READ  5572542\n0x2000EE40 READ  5572641\n0x2000EE80 READ  5572733\n0x2000EEC0 READ  5572822\n0x2000EF00 READ  5572912\n0x2000EF40 READ  5668707\n0x2000EF80 READ  5668793\n0x2000EFC0 READ  5668884\n0x2000F000 READ  5717902\n0x2000F040 READ  5717994\n0x2000F080 READ  5718082\n0x2000F0C0 READ  5718172\n0x2000F100 READ  5718262\n0x2000F140 READ  5718352\n0x2000F180 READ  5812562\n0x2000F1C0 READ  5812648\n0x2000F200 READ  5812739\n0x2000F240 READ  5864027\n0x2000F280 READ  5864120\n0x2000A380 READ    5864150\n0x2000F2C0 READ  5864344\n0x2000F300 READ  5864457\n0x2000F340 READ  6280968\n0x2000F380 READ  6323000\n0x2000F3C0 READ  6323091\n0x2000F400 READ  6323192\n0x2000F440 READ  6323282\n0x2000F4C0 READ  6418054\n0x2000F500 READ  6512931\n0x2000F580 READ  6513012\n0x2000F5C0 READ  6513101\n0x2000D840 READ  13589613\n0x2000D880 READ  13589694\n0x2000D8C0 READ  13589786\n0x2000D900 READ  13620025\n0x2000D940 READ  13620116\n0x2000D980 READ  13620210\n0x2000D9C0 READ  13650132\n0x2000DA00 READ  13650221\n0x2000DA40 READ  13650316\n0x2000DA80 READ  13650403\n0x2000DAC0 READ  13712159\n0x2000DB00 READ  13712251\n0x2000DB40 READ  13712342\n0x2000DB80 READ  13742348\n0x2000DBC0 READ  13742436\n0x2000DD40 READ  13742527\n0x2000DD80 READ  13742612\n0x2000DDC0 READ  13742697\n0x2000D6C0 READ  13742795\n0x2000DE00 READ  13742887\n0x2000D700 READ  13742968\n0x2000DE40 READ  13743061\n0x2000DE80 READ  14232668\n0x2000DEC0 READ  14232766\n0x2000F600 READ  14232869\n0x2000F6C0 READ  14232955\n0x2000F700 READ  14712444\n"
  },
  {
    "path": "src/DRAMsim3/tests/test_config.cc",
    "content": "#define CATCH_CONFIG_MAIN\n#include \"catch.hpp\"\n#include \"configuration.h\"\n\nTEST_CASE(\"Address Mapping\", \"[config]\") {\n    dramsim3::Config config(\"configs/HBM1_4Gb_x128.ini\", \".\");\n\n    SECTION(\"TEST address mapping set up\") {\n        REQUIRE(config.address_mapping == \"rorabgbachco\");\n        // COL width is not necessarily the same as col bits because BL\n        REQUIRE(config.co_pos == 0);\n        REQUIRE(config.ch_pos == 5);\n        REQUIRE(config.ba_pos == 8);\n        REQUIRE(config.bg_pos == 10);\n        REQUIRE(config.ra_pos == 12);\n        REQUIRE(config.ro_pos == 12);\n    }\n\n    SECTION(\"Test address mapping column\") {\n        uint64_t hex_addr = 0x0;\n        auto addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.column == 0);\n\n        hex_addr = 0b11111000000;\n        addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.column == 31);\n    }\n\n    SECTION(\"Test address mapping channel\") {\n        uint64_t hex_addr = 0b11111111111;\n        auto addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.channel == 0);\n\n        hex_addr = 0b111110111111111111;\n        addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.channel == 5);\n\n        hex_addr = 0b000011111111111111;\n        addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.channel == 7);\n    }\n\n    SECTION(\"Test address mapping bank\") {\n        uint64_t hex_addr = 0b11111111111111;\n        auto addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.bank == 0);\n\n        hex_addr = 0b1011111111111111;\n        addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.bank == 2);\n\n        hex_addr = 0b1111011111111111111;\n        addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.bank == 2);\n    }\n\n    SECTION(\"Test address mapping bankgroup\") {\n        uint64_t hex_addr = 0b1111111111111111;\n        auto addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.bankgroup == 0);\n\n        hex_addr = 0b101111111111111111;\n        addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.bankgroup == 2);\n\n        hex_addr = 0b111101111111111111111;\n        addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.bankgroup == 2);\n    }\n\n    SECTION(\"Test address mapping rank\") {\n        uint64_t hex_addr = 0xFFFFFFFFFFFF;\n        auto addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.rank == 0);\n    }\n\n    SECTION(\"Test address mapping row\") {\n        uint64_t hex_addr = 0b111111111111111111;\n        auto addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.row == 0);\n\n        hex_addr = 0b10001111111111111111111;\n        addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.row == 17);\n\n        hex_addr = 0b10000000000000111111111111111111;\n        addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.row == 0b10000000000000);\n\n        hex_addr = 0b11110000000000000111111111111111111;\n        addr = config.AddressMapping(hex_addr);\n        REQUIRE(addr.row == 0b10000000000000);\n    }\n}\n\n"
  },
  {
    "path": "src/DRAMsim3/tests/test_dramsys.cc",
    "content": "#include \"catch.hpp\"\n#include \"configuration.h\"\n#include \"dram_system.h\"\n\nbool call_back_called = false;\nvoid dummy_call_back(uint64_t addr) {\n    call_back_called = true;\n    return;\n}\n\nTEST_CASE(\"Jedec DRAMSystem Testing\", \"[dramsim3]\") {\n    dramsim3::Config config(\"configs/HBM1_4Gb_x128.ini\", \".\");\n\n    dramsim3::JedecDRAMSystem dramsys(config, \".\", dummy_call_back,\n                                      dummy_call_back);\n\n    SECTION(\"TEST interaction with controller\") {\n        dramsys.AddTransaction(1, false);\n        int clk = 0;\n        while (true) {\n            dramsys.ClockTick();\n            clk++;\n            if (call_back_called) {\n                call_back_called = false;\n                break;\n            }\n        }\n\n        int tRC = config.tRCDRD + config.CL + config.BL;\n        REQUIRE(clk == tRC);\n    }\n}\n"
  },
  {
    "path": "src/DRAMsim3/tests/test_hmcsys.cc",
    "content": "#include \"catch.hpp\"\n#include \"configuration.h\"\n#include \"memory_system.h\"\n\nbool hmc_called = false;\n\nvoid hmc_callback(uint64_t addr) {\n    hmc_called = true;\n    return;\n}\n\nTEST_CASE(\"HMC System Testing\", \"[dramsim3][hmc]\") {\n    // but THIS doesn't work?\n    // dramsim3::Config config(\"configs/HMC_2GB_4Lx16.ini\", \".\");\n    // dramsim3::HMCMemorySystem hmc(config, \".\", hmc_callback, hmc_callback);\n    dramsim3::MemorySystem hmc(\"configs/HMC_2GB_4Lx16.ini\", \".\", hmc_callback, hmc_callback);\n\n    SECTION(\"TEST HMC interaction with controller\") {\n        REQUIRE(hmc.GetBurstLength() == 16);\n        hmc.AddTransaction(1, false);\n        int clk = 0;\n        while (true) {\n            hmc.ClockTick();\n            clk++;\n            if (hmc_called || clk == 1000) {\n                break;\n            }\n        }\n\n        // For HMC things are complicated, e.g. for a 64B read request and x2 bandwidth xbar\n        // takes 1 cycle from CPU to Link\n        // takes 1 cycle from Link to Quad\n        // takes 1 cycle from Quad to DRAM\n        // takes xx cycles for DRAM to finish\n        // takes 1 cycle from DRAM to quad\n        // takes multiple cycles from quad to CPU\n        // (depending on packet size, and contention)\n        int idle_lat = 52;\n        REQUIRE(clk == idle_lat);\n    }\n}\n"
  },
  {
    "path": "src/MIT-LICENSE.txt",
    "content": "MIT License\n\nCopyright (c) 2016-2017 Fabrice Bellard\nCopyright (c) 2017-2020 Gaurav Kothari\nCopyright (c) 2018-2019 Parikshit Sarnaik\nCopyright (c) 2019 Göktürk Yüksek\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "src/Makefile",
    "content": "#\n# TinyEMU\n# \n# Copyright (c) 2016-2018 Fabrice Bellard\n#\n# MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n#\n# Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n# State University of New York at Binghamton\n#\n# Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n# State University of New York at Binghamton\n#\n# Copyright (c) 2019 Göktürk Yüksek {gokturk@binghamton.edu}\n# State University of New York at Binghamton\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\n# Set the XLEN value\nCONFIG_XLEN=64\n\n# if set, network filesystem is enabled. libcurl and libcrypto\n# (openssl) must be installed.\nCONFIG_FS_NET=y\n\n# SDL support (optional)\nCONFIG_SDL=y\n\n# user space network redirector\nCONFIG_SLIRP=y\n\nCROSS_PREFIX=\nEXE=\nCC=$(CROSS_PREFIX)gcc\nSTRIP=$(CROSS_PREFIX)strip\nCFLAGS=-O2 -Wall -g -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -MMD\nCFLAGS+=-D_GNU_SOURCE -DCONFIG_VERSION=\\\"$(shell cat VERSION)\\\"\nCFLAGS+=-DMAX_XLEN=$(CONFIG_XLEN)\nLDFLAGS=\n\nPROGS+= marss-riscv$(EXE) sim-stats-display\nifdef CONFIG_FS_NET\nPROGS+=build_filelist splitimg\nendif\n\n# DRAMSIM3 connections for the simulator\nDRAMSIM3_WRAPPER_C_CONNECTOR_LIB+=libdramsim_wrapper_c_connector.so\nDRAMSIM3_WRAPPER_C_CONNECTOR_OBJ:=$(addprefix riscvsim/memory_hierarchy/, dramsim_wrapper_c_connector.o)\nDRAMSIM3_WRAPPER_LIB+=libdramsim_wrapper_lib.so\nDRAMSIM3_WRAPPER_OBJ:=$(addprefix riscvsim/memory_hierarchy/, dramsim_wrapper.o)\nDRAMSIM3_LIB_SO+=libdramsim3.so\nDRAMSIM3_FMT_LIB_DIR=DRAMsim3/ext/fmt/include\nDRAMSIM3_INI_LIB_DIR=DRAMsim3/ext/headers\nDRAMSIM3_JSON_LIB_DIR=DRAMsim3/ext/headers\nDRAMSIM3_ARGS_LIB_DIR=DRAMsim3/ext/headers\nDRAMSIM3_INC=-IDRAMsim3/src/ -I$(DRAMSIM3_FMT_LIB_DIR) -I$(DRAMSIM3_INI_LIB_DIR) -I$(DRAMSIM3_ARGS_LIB_DIR) -I$(DRAMSIM3_JSON_LIB_DIR)\n\n# Ramulator connections for the simulator\nRAMULATOR_WRAPPER_C_CONNECTOR_LIB+=libramulator_wrapper_c_connector.so\nRAMULATOR_WRAPPER_C_CONNECTOR_OBJ:=$(addprefix riscvsim/memory_hierarchy/, ramulator_wrapper_c_connector.o)\nRAMULATOR_WRAPPER_LIB+=libramulator_wrapper_lib.so\nRAMULATOR_WRAPPER_OBJ:=$(addprefix riscvsim/memory_hierarchy/, ramulator_wrapper.o)\nRAMULATOR_LIB_SO+=libramulator.so\nRAMULATOR_INC+=-I./ramulator/src\n\n# Top-level simulator object file\nSIM_OBJ_FILE=riscvsim.o\n\n# Simulator object files for each module\nSIM_UTILS:=$(addprefix riscvsim/utils/, sim_exception.o sim_trace.o cpu_latches.o evict_policy.o circular_queue.o sim_params.o sim_stats.o sim_log.o)\nSIM_DECODER_OBJS:=$(addprefix riscvsim/decoder/, riscv_isa_string_generator.o riscv_isa_decoder.o riscv_isa_execute.o)\nSIM_BPU_OBJS:=$(addprefix riscvsim/bpu/, ras.o bht.o btb.o adaptive_predictor.o bpu.o)\nSIM_MEM_HY_OBJS:=$(addprefix riscvsim/memory_hierarchy/, temu_mem_map_wrapper.o dram.o memory_hierarchy.o memory_controller.o cache.o )\nSIM_IN_CORE_OBJS:=$(addprefix riscvsim/core/, inorder_frontend.o inorder_backend.o inorder.o)\nSIM_CORE_OBJS:=$(addprefix riscvsim/core/, riscv_sim_cpu.o)\nSIM_OO_CORE_OBJS:=$(addprefix riscvsim/core/, ooo_frontend.o ooo_branch.o ooo_lsu.o ooo_backend.o ooo.o)\nSIM_OBJS:=$(SIM_UTILS) $(SIM_DECODER_OBJS) $(SIM_BPU_OBJS) $(SIM_MEM_HY_OBJS) $(SIM_CORE_OBJS) $(SIM_IN_CORE_OBJS) $(SIM_OO_CORE_OBJS)\n\nall: $(PROGS)\n\nEMU_OBJS:=virtio.o pci.o fs.o cutils.o iomem.o simplefb.o \\\n    json.o machine.o rtc_timer.o temu.o\n\nifdef CONFIG_SLIRP\nCFLAGS+=-DCONFIG_SLIRP\nEMU_OBJS+=$(addprefix slirp/, bootp.o ip_icmp.o mbuf.o slirp.o tcp_output.o cksum.o ip_input.o misc.o socket.o tcp_subr.o udp.o if.o ip_output.o sbuf.o tcp_input.o tcp_timer.o)\nendif\n\nEMU_OBJS+=fs_disk.o\nEMU_LIBS=-lrt -lpthread -lm\n\nifdef CONFIG_FS_NET\nCFLAGS+=-DCONFIG_FS_NET\nEMU_OBJS+=fs_net.o fs_wget.o fs_utils.o block_net.o\nEMU_LIBS+=-lcurl -lcrypto\nendif # CONFIG_FS_NET\n\nifdef CONFIG_SDL\nEMU_LIBS+=-lSDL\nEMU_OBJS+=sdl.o\nCFLAGS+=-DCONFIG_SDL\nendif\n\nEMU_OBJS+=riscv_machine.o softfp.o riscv_cpu.o\nCFLAGS+=-DCONFIG_RISCV_MAX_XLEN=64\n\nlibdramsim_wrapper_c_connector.so: $(DRAMSIM3_WRAPPER_LIB) $(DRAMSIM3_WRAPPER_C_CONNECTOR_OBJ)\n\t$(CXX) -shared -o $(DRAMSIM3_WRAPPER_C_CONNECTOR_LIB) $(DRAMSIM3_WRAPPER_C_CONNECTOR_OBJ) -L. -ldramsim_wrapper_lib -Wl,-rpath=.\n\nlibdramsim_wrapper_lib.so: $(DRAMSIM3_LIB_SO) $(DRAMSIM3_WRAPPER_OBJ)\n\t$(CXX) -shared -o $(DRAMSIM3_WRAPPER_LIB) $(DRAMSIM3_WRAPPER_OBJ) -L./DRAMsim3 -ldramsim3 -Wl,-rpath=./DRAMsim3\n\nlibdramsim3.so:\n\tcd DRAMsim3/ && $(MAKE) $(DRAMSIM3_LIB_SO) && cd ..\n\nlibramulator_wrapper_c_connector.so: $(RAMULATOR_WRAPPER_LIB) $(RAMULATOR_WRAPPER_C_CONNECTOR_OBJ)\n\t$(CXX) -shared -o $(RAMULATOR_WRAPPER_C_CONNECTOR_LIB) $(RAMULATOR_WRAPPER_C_CONNECTOR_OBJ) -L. -lramulator_wrapper_lib -Wl,-rpath=.\n\nlibramulator_wrapper_lib.so: $(RAMULATOR_LIB_SO) $(RAMULATOR_WRAPPER_OBJ)\n\t$(CXX) -shared -o $(RAMULATOR_WRAPPER_LIB) $(RAMULATOR_WRAPPER_OBJ) -L./ramulator -lramulator -Wl,-rpath=./ramulator\n\nlibramulator.so:\n\tcd ramulator && $(MAKE) $(RAMULATOR_LIB_SO) && cd ..\n\nriscvsim.o: $(SIM_OBJS)\n\t$(LD) -r -o $@ $^ $(SIM_LIBS)\n\nsim-stats-display: stats_display.o\n\t$(CC) -o sim-stats-display stats_display.o -lrt\n\nmarss-riscv$(EXE): $(SIM_OBJ_FILE) $(DRAMSIM3_WRAPPER_C_CONNECTOR_LIB) $(RAMULATOR_WRAPPER_C_CONNECTOR_LIB) $(EMU_OBJS)\n\t$(CC) $(LDFLAGS) -o $@ $^ $(EMU_LIBS) -L. -ldramsim_wrapper_c_connector -Wl,-rpath=. -L. -lramulator_wrapper_c_connector -Wl,-rpath=.\n\nriscv_cpu.o: riscv_cpu.c\n\t$(CC) $(CFLAGS) -DMAX_XLEN=$(CONFIG_XLEN) -c -o $@ $<\n\nbuild_filelist: build_filelist.o fs_utils.o cutils.o\n\t$(CC) $(LDFLAGS) -o $@ $^ -lm\n\nsplitimg: splitimg.o\n\t$(CC) $(LDFLAGS) -o $@ $^\n\n%.o: %.c\n\t$(CC) $(CFLAGS) -c -o $@ $<\n\n%.o: %.cpp\n\t$(CXX) -g -DMAX_XLEN=$(CONFIG_XLEN) $(DRAMSIM3_INC) -I./ramulator/src -fpic -shared -c -std=c++11 -o $@ $<\n\nclean:\n\trm -f *.o *.so *.d *~ $(PROGS) slirp/*.o slirp/*.d slirp/*~ riscvsim/bpu/*.d riscvsim/core/*.d  riscvsim/decoder/*.d riscvsim/utils/*.d  riscvsim/memory_hierarchy/*.d $(SIM_OBJS)\n\trm -f $(RAMULATOR_WRAPPER_C_CONNECTOR_OBJ) $(RAMULATOR_WRAPPER_OBJ)\n\tcd ramulator && $(MAKE) clean && cd ..\n\trm -f $(DRAMSIM3_WRAPPER_C_CONNECTOR_OBJ) $(DRAMSIM3_WRAPPER_OBJ)\n\tcd DRAMsim3 && $(MAKE) clean && cd ..\n\n-include $(wildcard *.d)\n-include $(wildcard slirp/*.d)\n"
  },
  {
    "path": "src/VERSION",
    "content": "4.1a\n"
  },
  {
    "path": "src/aes.c",
    "content": "/**\n *\n * aes.c - integrated in QEMU by Fabrice Bellard from the OpenSSL project.\n */\n/*\n * rijndael-alg-fst.c\n *\n * @version 3.0 (December 2000)\n *\n * Optimised ANSI C code for the Rijndael cipher (now AES)\n *\n * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>\n * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>\n * @author Paulo Barreto <paulo.barreto@terra.com.br>\n *\n * This code is hereby placed in the public domain.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\n * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include <string.h>\n#include <inttypes.h>\n#include \"aes.h\"\n\n#ifndef NDEBUG\n#define NDEBUG\n#endif\n\n#include <assert.h>\n\ntypedef uint32_t u32;\ntypedef uint16_t u16;\ntypedef uint8_t u8;\n\n#define MAXKC   (256/32)\n#define MAXKB   (256/8)\n#define MAXNR   14\n\n/* This controls loop-unrolling in aes_core.c */\n#undef FULL_UNROLL\n# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))\n# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }\n\n/*\nTe0[x] = S [x].[02, 01, 01, 03];\nTe1[x] = S [x].[03, 02, 01, 01];\nTe2[x] = S [x].[01, 03, 02, 01];\nTe3[x] = S [x].[01, 01, 03, 02];\nTe4[x] = S [x].[01, 01, 01, 01];\n\nTd0[x] = Si[x].[0e, 09, 0d, 0b];\nTd1[x] = Si[x].[0b, 0e, 09, 0d];\nTd2[x] = Si[x].[0d, 0b, 0e, 09];\nTd3[x] = Si[x].[09, 0d, 0b, 0e];\nTd4[x] = Si[x].[01, 01, 01, 01];\n*/\n\nstatic const u32 Te0[256] = {\n    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,\n    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,\n    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,\n    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,\n    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,\n    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,\n    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,\n    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,\n    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,\n    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,\n    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,\n    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,\n    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,\n    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,\n    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,\n    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,\n    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,\n    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,\n    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,\n    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,\n    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,\n    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,\n    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,\n    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,\n    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,\n    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,\n    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,\n    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,\n    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,\n    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,\n    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,\n    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,\n    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,\n    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,\n    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,\n    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,\n    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,\n    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,\n    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,\n    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,\n    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,\n    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,\n    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,\n    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,\n    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,\n    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,\n    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,\n    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,\n    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,\n    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,\n    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,\n    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,\n    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,\n    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,\n    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,\n    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,\n    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,\n    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,\n    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,\n    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,\n    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,\n    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,\n    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,\n    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,\n};\nstatic const u32 Te1[256] = {\n    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,\n    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,\n    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,\n    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,\n    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,\n    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,\n    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,\n    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,\n    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,\n    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,\n    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,\n    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,\n    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,\n    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,\n    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,\n    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,\n    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,\n    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,\n    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,\n    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,\n    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,\n    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,\n    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,\n    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,\n    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,\n    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,\n    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,\n    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,\n    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,\n    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,\n    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,\n    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,\n    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,\n    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,\n    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,\n    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,\n    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,\n    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,\n    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,\n    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,\n    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,\n    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,\n    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,\n    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,\n    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,\n    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,\n    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,\n    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,\n    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,\n    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,\n    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,\n    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,\n    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,\n    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,\n    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,\n    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,\n    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,\n    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,\n    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,\n    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,\n    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,\n    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,\n    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,\n    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,\n};\nstatic const u32 Te2[256] = {\n    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,\n    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,\n    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,\n    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,\n    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,\n    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,\n    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,\n    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,\n    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,\n    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,\n    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,\n    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,\n    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,\n    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,\n    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,\n    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,\n    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,\n    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,\n    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,\n    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,\n    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,\n    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,\n    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,\n    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,\n    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,\n    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,\n    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,\n    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,\n    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,\n    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,\n    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,\n    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,\n    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,\n    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,\n    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,\n    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,\n    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,\n    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,\n    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,\n    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,\n    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,\n    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,\n    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,\n    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,\n    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,\n    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,\n    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,\n    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,\n    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,\n    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,\n    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,\n    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,\n    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,\n    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,\n    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,\n    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,\n    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,\n    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,\n    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,\n    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,\n    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,\n    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,\n    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,\n    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,\n};\nstatic const u32 Te3[256] = {\n\n    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,\n    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,\n    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,\n    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,\n    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,\n    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,\n    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,\n    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,\n    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,\n    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,\n    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,\n    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,\n    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,\n    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,\n    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,\n    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,\n    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,\n    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,\n    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,\n    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,\n    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,\n    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,\n    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,\n    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,\n    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,\n    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,\n    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,\n    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,\n    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,\n    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,\n    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,\n    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,\n    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,\n    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,\n    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,\n    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,\n    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,\n    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,\n    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,\n    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,\n    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,\n    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,\n    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,\n    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,\n    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,\n    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,\n    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,\n    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,\n    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,\n    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,\n    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,\n    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,\n    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,\n    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,\n    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,\n    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,\n    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,\n    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,\n    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,\n    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,\n    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,\n    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,\n    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,\n    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,\n};\nstatic const u32 Te4[256] = {\n    0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,\n    0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,\n    0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,\n    0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,\n    0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,\n    0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,\n    0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,\n    0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,\n    0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,\n    0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,\n    0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,\n    0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,\n    0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,\n    0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,\n    0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,\n    0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,\n    0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,\n    0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,\n    0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,\n    0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,\n    0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,\n    0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,\n    0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,\n    0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,\n    0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,\n    0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,\n    0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,\n    0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,\n    0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,\n    0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,\n    0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,\n    0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,\n    0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,\n    0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,\n    0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,\n    0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,\n    0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,\n    0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,\n    0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,\n    0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,\n    0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,\n    0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,\n    0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,\n    0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,\n    0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,\n    0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,\n    0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,\n    0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,\n    0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,\n    0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,\n    0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,\n    0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,\n    0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,\n    0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,\n    0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,\n    0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,\n    0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,\n    0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,\n    0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,\n    0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,\n    0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,\n    0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,\n    0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,\n    0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,\n};\nstatic const u32 Td0[256] = {\n    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,\n    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,\n    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,\n    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,\n    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,\n    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,\n    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,\n    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,\n    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,\n    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,\n    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,\n    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,\n    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,\n    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,\n    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,\n    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,\n    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,\n    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,\n    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,\n    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,\n    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,\n    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,\n    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,\n    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,\n    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,\n    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,\n    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,\n    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,\n    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,\n    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,\n    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,\n    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,\n    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,\n    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,\n    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,\n    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,\n    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,\n    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,\n    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,\n    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,\n    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,\n    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,\n    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,\n    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,\n    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,\n    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,\n    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,\n    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,\n    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,\n    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,\n    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,\n    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,\n    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,\n    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,\n    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,\n    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,\n    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,\n    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,\n    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,\n    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,\n    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,\n    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,\n    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,\n    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,\n};\nstatic const u32 Td1[256] = {\n    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,\n    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,\n    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,\n    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,\n    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,\n    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,\n    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,\n    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,\n    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,\n    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,\n    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,\n    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,\n    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,\n    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,\n    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,\n    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,\n    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,\n    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,\n    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,\n    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,\n    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,\n    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,\n    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,\n    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,\n    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,\n    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,\n    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,\n    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,\n    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,\n    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,\n    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,\n    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,\n    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,\n    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,\n    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,\n    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,\n    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,\n    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,\n    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,\n    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,\n    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,\n    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,\n    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,\n    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,\n    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,\n    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,\n    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,\n    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,\n    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,\n    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,\n    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,\n    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,\n    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,\n    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,\n    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,\n    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,\n    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,\n    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,\n    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,\n    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,\n    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,\n    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,\n    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,\n    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,\n};\nstatic const u32 Td2[256] = {\n    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,\n    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,\n    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,\n    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,\n    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,\n    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,\n    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,\n    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,\n    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,\n    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,\n    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,\n    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,\n    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,\n    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,\n    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,\n    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,\n    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,\n    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,\n    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,\n    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,\n\n    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,\n    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,\n    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,\n    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,\n    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,\n    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,\n    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,\n    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,\n    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,\n    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,\n    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,\n    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,\n    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,\n    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,\n    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,\n    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,\n    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,\n    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,\n    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,\n    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,\n    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,\n    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,\n    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,\n    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,\n    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,\n    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,\n    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,\n    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,\n    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,\n    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,\n    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,\n    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,\n    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,\n    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,\n    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,\n    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,\n    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,\n    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,\n    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,\n    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,\n    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,\n    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,\n    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,\n    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,\n};\nstatic const u32 Td3[256] = {\n    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,\n    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,\n    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,\n    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,\n    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,\n    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,\n    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,\n    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,\n    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,\n    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,\n    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,\n    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,\n    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,\n    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,\n    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,\n    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,\n    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,\n    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,\n    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,\n    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,\n    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,\n    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,\n    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,\n    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,\n    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,\n    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,\n    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,\n    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,\n    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,\n    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,\n    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,\n    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,\n    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,\n    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,\n    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,\n    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,\n    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,\n    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,\n    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,\n    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,\n    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,\n    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,\n    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,\n    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,\n    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,\n    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,\n    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,\n    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,\n    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,\n    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,\n    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,\n    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,\n    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,\n    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,\n    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,\n    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,\n    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,\n    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,\n    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,\n    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,\n    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,\n    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,\n    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,\n    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,\n};\nstatic const u32 Td4[256] = {\n    0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,\n    0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,\n    0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,\n    0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,\n    0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,\n    0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,\n    0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,\n    0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,\n    0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,\n    0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,\n    0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,\n    0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,\n    0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,\n    0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,\n    0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,\n    0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,\n    0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,\n    0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,\n    0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,\n    0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,\n    0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,\n    0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,\n    0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,\n    0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,\n    0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,\n    0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,\n    0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,\n    0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,\n    0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,\n    0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,\n    0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,\n    0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,\n    0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,\n    0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,\n    0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,\n    0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,\n    0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,\n    0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,\n    0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,\n    0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,\n    0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,\n    0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,\n    0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,\n    0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,\n    0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,\n    0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,\n    0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,\n    0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,\n    0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,\n    0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,\n    0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,\n    0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,\n    0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,\n    0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,\n    0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,\n    0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,\n    0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,\n    0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,\n    0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,\n    0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,\n    0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,\n    0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,\n    0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,\n    0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,\n};\nstatic const u32 rcon[] = {\n\t0x01000000, 0x02000000, 0x04000000, 0x08000000,\n\t0x10000000, 0x20000000, 0x40000000, 0x80000000,\n\t0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */\n};\n\n/**\n * Expand the cipher key into the encryption key schedule.\n */\nint AES_set_encrypt_key(const unsigned char *userKey, const int bits,\n\t\t\tAES_KEY *key) {\n\n\tu32 *rk;\n   \tint i = 0;\n\tu32 temp;\n\n\tif (!userKey || !key)\n\t\treturn -1;\n\tif (bits != 128 && bits != 192 && bits != 256)\n\t\treturn -2;\n\n\trk = key->rd_key;\n\n\tif (bits==128)\n\t\tkey->rounds = 10;\n\telse if (bits==192)\n\t\tkey->rounds = 12;\n\telse\n\t\tkey->rounds = 14;\n\n\trk[0] = GETU32(userKey     );\n\trk[1] = GETU32(userKey +  4);\n\trk[2] = GETU32(userKey +  8);\n\trk[3] = GETU32(userKey + 12);\n\tif (bits == 128) {\n\t\twhile (1) {\n\t\t\ttemp  = rk[3];\n\t\t\trk[4] = rk[0] ^\n\t\t\t\t(Te4[(temp >> 16) & 0xff] & 0xff000000) ^\n\t\t\t\t(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^\n\t\t\t\t(Te4[(temp      ) & 0xff] & 0x0000ff00) ^\n\t\t\t\t(Te4[(temp >> 24)       ] & 0x000000ff) ^\n\t\t\t\trcon[i];\n\t\t\trk[5] = rk[1] ^ rk[4];\n\t\t\trk[6] = rk[2] ^ rk[5];\n\t\t\trk[7] = rk[3] ^ rk[6];\n\t\t\tif (++i == 10) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\trk += 4;\n\t\t}\n\t}\n\trk[4] = GETU32(userKey + 16);\n\trk[5] = GETU32(userKey + 20);\n\tif (bits == 192) {\n\t\twhile (1) {\n\t\t\ttemp = rk[ 5];\n\t\t\trk[ 6] = rk[ 0] ^\n\t\t\t\t(Te4[(temp >> 16) & 0xff] & 0xff000000) ^\n\t\t\t\t(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^\n\t\t\t\t(Te4[(temp      ) & 0xff] & 0x0000ff00) ^\n\t\t\t\t(Te4[(temp >> 24)       ] & 0x000000ff) ^\n\t\t\t\trcon[i];\n\t\t\trk[ 7] = rk[ 1] ^ rk[ 6];\n\t\t\trk[ 8] = rk[ 2] ^ rk[ 7];\n\t\t\trk[ 9] = rk[ 3] ^ rk[ 8];\n\t\t\tif (++i == 8) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\trk[10] = rk[ 4] ^ rk[ 9];\n\t\t\trk[11] = rk[ 5] ^ rk[10];\n\t\t\trk += 6;\n\t\t}\n\t}\n\trk[6] = GETU32(userKey + 24);\n\trk[7] = GETU32(userKey + 28);\n\tif (bits == 256) {\n\t\twhile (1) {\n\t\t\ttemp = rk[ 7];\n\t\t\trk[ 8] = rk[ 0] ^\n\t\t\t\t(Te4[(temp >> 16) & 0xff] & 0xff000000) ^\n\t\t\t\t(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^\n\t\t\t\t(Te4[(temp      ) & 0xff] & 0x0000ff00) ^\n\t\t\t\t(Te4[(temp >> 24)       ] & 0x000000ff) ^\n\t\t\t\trcon[i];\n\t\t\trk[ 9] = rk[ 1] ^ rk[ 8];\n\t\t\trk[10] = rk[ 2] ^ rk[ 9];\n\t\t\trk[11] = rk[ 3] ^ rk[10];\n\t\t\tif (++i == 7) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\ttemp = rk[11];\n\t\t\trk[12] = rk[ 4] ^\n\t\t\t\t(Te4[(temp >> 24)       ] & 0xff000000) ^\n\t\t\t\t(Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^\n\t\t\t\t(Te4[(temp >>  8) & 0xff] & 0x0000ff00) ^\n\t\t\t\t(Te4[(temp      ) & 0xff] & 0x000000ff);\n\t\t\trk[13] = rk[ 5] ^ rk[12];\n\t\t\trk[14] = rk[ 6] ^ rk[13];\n\t\t\trk[15] = rk[ 7] ^ rk[14];\n\n\t\t\trk += 8;\n        \t}\n\t}\n\treturn 0;\n}\n\n/**\n * Expand the cipher key into the decryption key schedule.\n */\nint AES_set_decrypt_key(const unsigned char *userKey, const int bits,\n\t\t\t AES_KEY *key) {\n\n        u32 *rk;\n\tint i, j, status;\n\tu32 temp;\n\n\t/* first, start with an encryption schedule */\n\tstatus = AES_set_encrypt_key(userKey, bits, key);\n\tif (status < 0)\n\t\treturn status;\n\n\trk = key->rd_key;\n\n\t/* invert the order of the round keys: */\n\tfor (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) {\n\t\ttemp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;\n\t\ttemp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;\n\t\ttemp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;\n\t\ttemp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;\n\t}\n\t/* apply the inverse MixColumn transform to all round keys but the first and the last: */\n\tfor (i = 1; i < (key->rounds); i++) {\n\t\trk += 4;\n\t\trk[0] =\n\t\t\tTd0[Te4[(rk[0] >> 24)       ] & 0xff] ^\n\t\t\tTd1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^\n\t\t\tTd2[Te4[(rk[0] >>  8) & 0xff] & 0xff] ^\n\t\t\tTd3[Te4[(rk[0]      ) & 0xff] & 0xff];\n\t\trk[1] =\n\t\t\tTd0[Te4[(rk[1] >> 24)       ] & 0xff] ^\n\t\t\tTd1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^\n\t\t\tTd2[Te4[(rk[1] >>  8) & 0xff] & 0xff] ^\n\t\t\tTd3[Te4[(rk[1]      ) & 0xff] & 0xff];\n\t\trk[2] =\n\t\t\tTd0[Te4[(rk[2] >> 24)       ] & 0xff] ^\n\t\t\tTd1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^\n\t\t\tTd2[Te4[(rk[2] >>  8) & 0xff] & 0xff] ^\n\t\t\tTd3[Te4[(rk[2]      ) & 0xff] & 0xff];\n\t\trk[3] =\n\t\t\tTd0[Te4[(rk[3] >> 24)       ] & 0xff] ^\n\t\t\tTd1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^\n\t\t\tTd2[Te4[(rk[3] >>  8) & 0xff] & 0xff] ^\n\t\t\tTd3[Te4[(rk[3]      ) & 0xff] & 0xff];\n\t}\n\treturn 0;\n}\n\n#ifndef AES_ASM\n/*\n * Encrypt a single block\n * in and out can overlap\n */\nvoid AES_encrypt(const unsigned char *in, unsigned char *out,\n\t\t const AES_KEY *key) {\n\n\tconst u32 *rk;\n\tu32 s0, s1, s2, s3, t0, t1, t2, t3;\n#ifndef FULL_UNROLL\n\tint r;\n#endif /* ?FULL_UNROLL */\n\n\tassert(in && out && key);\n\trk = key->rd_key;\n\n\t/*\n\t * map byte array block to cipher state\n\t * and add initial round key:\n\t */\n\ts0 = GETU32(in     ) ^ rk[0];\n\ts1 = GETU32(in +  4) ^ rk[1];\n\ts2 = GETU32(in +  8) ^ rk[2];\n\ts3 = GETU32(in + 12) ^ rk[3];\n#ifdef FULL_UNROLL\n\t/* round 1: */\n   \tt0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];\n   \tt1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];\n   \tt2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];\n   \tt3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];\n   \t/* round 2: */\n   \ts0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];\n   \ts1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];\n   \ts2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];\n   \ts3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];\n\t/* round 3: */\n   \tt0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];\n   \tt1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];\n   \tt2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];\n   \tt3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];\n   \t/* round 4: */\n   \ts0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];\n   \ts1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];\n   \ts2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];\n   \ts3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];\n\t/* round 5: */\n   \tt0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];\n   \tt1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];\n   \tt2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];\n   \tt3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];\n   \t/* round 6: */\n   \ts0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];\n   \ts1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];\n   \ts2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];\n   \ts3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];\n\t/* round 7: */\n   \tt0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];\n   \tt1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];\n   \tt2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];\n   \tt3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];\n   \t/* round 8: */\n   \ts0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];\n   \ts1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];\n   \ts2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];\n   \ts3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];\n\t/* round 9: */\n   \tt0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];\n   \tt1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];\n   \tt2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];\n   \tt3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];\n    if (key->rounds > 10) {\n        /* round 10: */\n        s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];\n        s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];\n        s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];\n        s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];\n        /* round 11: */\n        t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];\n        t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];\n        t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];\n        t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];\n        if (key->rounds > 12) {\n            /* round 12: */\n            s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];\n            s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];\n            s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];\n            s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];\n            /* round 13: */\n            t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];\n            t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];\n            t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];\n            t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];\n        }\n    }\n    rk += key->rounds << 2;\n#else  /* !FULL_UNROLL */\n    /*\n     * Nr - 1 full rounds:\n     */\n    r = key->rounds >> 1;\n    for (;;) {\n        t0 =\n            Te0[(s0 >> 24)       ] ^\n            Te1[(s1 >> 16) & 0xff] ^\n            Te2[(s2 >>  8) & 0xff] ^\n            Te3[(s3      ) & 0xff] ^\n            rk[4];\n        t1 =\n            Te0[(s1 >> 24)       ] ^\n            Te1[(s2 >> 16) & 0xff] ^\n            Te2[(s3 >>  8) & 0xff] ^\n            Te3[(s0      ) & 0xff] ^\n            rk[5];\n        t2 =\n            Te0[(s2 >> 24)       ] ^\n            Te1[(s3 >> 16) & 0xff] ^\n            Te2[(s0 >>  8) & 0xff] ^\n            Te3[(s1      ) & 0xff] ^\n            rk[6];\n        t3 =\n            Te0[(s3 >> 24)       ] ^\n            Te1[(s0 >> 16) & 0xff] ^\n            Te2[(s1 >>  8) & 0xff] ^\n            Te3[(s2      ) & 0xff] ^\n            rk[7];\n\n        rk += 8;\n        if (--r == 0) {\n            break;\n        }\n\n        s0 =\n            Te0[(t0 >> 24)       ] ^\n            Te1[(t1 >> 16) & 0xff] ^\n            Te2[(t2 >>  8) & 0xff] ^\n            Te3[(t3      ) & 0xff] ^\n            rk[0];\n        s1 =\n            Te0[(t1 >> 24)       ] ^\n            Te1[(t2 >> 16) & 0xff] ^\n            Te2[(t3 >>  8) & 0xff] ^\n            Te3[(t0      ) & 0xff] ^\n            rk[1];\n        s2 =\n            Te0[(t2 >> 24)       ] ^\n            Te1[(t3 >> 16) & 0xff] ^\n            Te2[(t0 >>  8) & 0xff] ^\n            Te3[(t1      ) & 0xff] ^\n            rk[2];\n        s3 =\n            Te0[(t3 >> 24)       ] ^\n            Te1[(t0 >> 16) & 0xff] ^\n            Te2[(t1 >>  8) & 0xff] ^\n            Te3[(t2      ) & 0xff] ^\n            rk[3];\n    }\n#endif /* ?FULL_UNROLL */\n    /*\n\t * apply last round and\n\t * map cipher state to byte array block:\n\t */\n\ts0 =\n\t\t(Te4[(t0 >> 24)       ] & 0xff000000) ^\n\t\t(Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^\n\t\t(Te4[(t2 >>  8) & 0xff] & 0x0000ff00) ^\n\t\t(Te4[(t3      ) & 0xff] & 0x000000ff) ^\n\t\trk[0];\n\tPUTU32(out     , s0);\n\ts1 =\n\t\t(Te4[(t1 >> 24)       ] & 0xff000000) ^\n\t\t(Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^\n\t\t(Te4[(t3 >>  8) & 0xff] & 0x0000ff00) ^\n\t\t(Te4[(t0      ) & 0xff] & 0x000000ff) ^\n\t\trk[1];\n\tPUTU32(out +  4, s1);\n\ts2 =\n\t\t(Te4[(t2 >> 24)       ] & 0xff000000) ^\n\t\t(Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^\n\t\t(Te4[(t0 >>  8) & 0xff] & 0x0000ff00) ^\n\t\t(Te4[(t1      ) & 0xff] & 0x000000ff) ^\n\t\trk[2];\n\tPUTU32(out +  8, s2);\n\ts3 =\n\t\t(Te4[(t3 >> 24)       ] & 0xff000000) ^\n\t\t(Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^\n\t\t(Te4[(t1 >>  8) & 0xff] & 0x0000ff00) ^\n\t\t(Te4[(t2      ) & 0xff] & 0x000000ff) ^\n\t\trk[3];\n\tPUTU32(out + 12, s3);\n}\n\n/*\n * Decrypt a single block\n * in and out can overlap\n */\nvoid AES_decrypt(const unsigned char *in, unsigned char *out,\n\t\t const AES_KEY *key) {\n\n\tconst u32 *rk;\n\tu32 s0, s1, s2, s3, t0, t1, t2, t3;\n#ifndef FULL_UNROLL\n\tint r;\n#endif /* ?FULL_UNROLL */\n\n\tassert(in && out && key);\n\trk = key->rd_key;\n\n\t/*\n\t * map byte array block to cipher state\n\t * and add initial round key:\n\t */\n    s0 = GETU32(in     ) ^ rk[0];\n    s1 = GETU32(in +  4) ^ rk[1];\n    s2 = GETU32(in +  8) ^ rk[2];\n    s3 = GETU32(in + 12) ^ rk[3];\n#ifdef FULL_UNROLL\n    /* round 1: */\n    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];\n    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];\n    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];\n    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];\n    /* round 2: */\n    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];\n    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];\n    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];\n    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];\n    /* round 3: */\n    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];\n    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];\n    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];\n    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];\n    /* round 4: */\n    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];\n    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];\n    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];\n    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];\n    /* round 5: */\n    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];\n    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];\n    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];\n    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];\n    /* round 6: */\n    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];\n    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];\n    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];\n    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];\n    /* round 7: */\n    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];\n    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];\n    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];\n    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];\n    /* round 8: */\n    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];\n    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];\n    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];\n    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];\n    /* round 9: */\n    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];\n    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];\n    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];\n    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];\n    if (key->rounds > 10) {\n        /* round 10: */\n        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];\n        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];\n        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];\n        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];\n        /* round 11: */\n        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];\n        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];\n        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];\n        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];\n        if (key->rounds > 12) {\n            /* round 12: */\n            s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];\n            s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];\n            s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];\n            s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];\n            /* round 13: */\n            t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];\n            t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];\n            t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];\n            t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];\n        }\n    }\n\trk += key->rounds << 2;\n#else  /* !FULL_UNROLL */\n    /*\n     * Nr - 1 full rounds:\n     */\n    r = key->rounds >> 1;\n    for (;;) {\n        t0 =\n            Td0[(s0 >> 24)       ] ^\n            Td1[(s3 >> 16) & 0xff] ^\n            Td2[(s2 >>  8) & 0xff] ^\n            Td3[(s1      ) & 0xff] ^\n            rk[4];\n        t1 =\n            Td0[(s1 >> 24)       ] ^\n            Td1[(s0 >> 16) & 0xff] ^\n            Td2[(s3 >>  8) & 0xff] ^\n            Td3[(s2      ) & 0xff] ^\n            rk[5];\n        t2 =\n            Td0[(s2 >> 24)       ] ^\n            Td1[(s1 >> 16) & 0xff] ^\n            Td2[(s0 >>  8) & 0xff] ^\n            Td3[(s3      ) & 0xff] ^\n            rk[6];\n        t3 =\n            Td0[(s3 >> 24)       ] ^\n            Td1[(s2 >> 16) & 0xff] ^\n            Td2[(s1 >>  8) & 0xff] ^\n            Td3[(s0      ) & 0xff] ^\n            rk[7];\n\n        rk += 8;\n        if (--r == 0) {\n            break;\n        }\n\n        s0 =\n            Td0[(t0 >> 24)       ] ^\n            Td1[(t3 >> 16) & 0xff] ^\n            Td2[(t2 >>  8) & 0xff] ^\n            Td3[(t1      ) & 0xff] ^\n            rk[0];\n        s1 =\n            Td0[(t1 >> 24)       ] ^\n            Td1[(t0 >> 16) & 0xff] ^\n            Td2[(t3 >>  8) & 0xff] ^\n            Td3[(t2      ) & 0xff] ^\n            rk[1];\n        s2 =\n            Td0[(t2 >> 24)       ] ^\n            Td1[(t1 >> 16) & 0xff] ^\n            Td2[(t0 >>  8) & 0xff] ^\n            Td3[(t3      ) & 0xff] ^\n            rk[2];\n        s3 =\n            Td0[(t3 >> 24)       ] ^\n            Td1[(t2 >> 16) & 0xff] ^\n            Td2[(t1 >>  8) & 0xff] ^\n            Td3[(t0      ) & 0xff] ^\n            rk[3];\n    }\n#endif /* ?FULL_UNROLL */\n    /*\n\t * apply last round and\n\t * map cipher state to byte array block:\n\t */\n   \ts0 =\n   \t\t(Td4[(t0 >> 24)       ] & 0xff000000) ^\n   \t\t(Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^\n   \t\t(Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^\n   \t\t(Td4[(t1      ) & 0xff] & 0x000000ff) ^\n   \t\trk[0];\n\tPUTU32(out     , s0);\n   \ts1 =\n   \t\t(Td4[(t1 >> 24)       ] & 0xff000000) ^\n   \t\t(Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^\n   \t\t(Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^\n   \t\t(Td4[(t2      ) & 0xff] & 0x000000ff) ^\n   \t\trk[1];\n\tPUTU32(out +  4, s1);\n   \ts2 =\n   \t\t(Td4[(t2 >> 24)       ] & 0xff000000) ^\n   \t\t(Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^\n   \t\t(Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^\n   \t\t(Td4[(t3      ) & 0xff] & 0x000000ff) ^\n   \t\trk[2];\n\tPUTU32(out +  8, s2);\n   \ts3 =\n   \t\t(Td4[(t3 >> 24)       ] & 0xff000000) ^\n   \t\t(Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^\n   \t\t(Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^\n   \t\t(Td4[(t0      ) & 0xff] & 0x000000ff) ^\n   \t\trk[3];\n\tPUTU32(out + 12, s3);\n}\n\n#endif /* AES_ASM */\n\nvoid AES_cbc_encrypt(const unsigned char *in, unsigned char *out,\n\t\t     const unsigned long length, const AES_KEY *key,\n\t\t     unsigned char *ivec, const int enc)\n{\n\n\tunsigned long n;\n\tunsigned long len = length;\n\tunsigned char tmp[AES_BLOCK_SIZE];\n\n\tassert(in && out && key && ivec);\n\n\tif (enc) {\n\t\twhile (len >= AES_BLOCK_SIZE) {\n\t\t\tfor(n=0; n < AES_BLOCK_SIZE; ++n)\n\t\t\t\ttmp[n] = in[n] ^ ivec[n];\n\t\t\tAES_encrypt(tmp, out, key);\n\t\t\tmemcpy(ivec, out, AES_BLOCK_SIZE);\n\t\t\tlen -= AES_BLOCK_SIZE;\n\t\t\tin += AES_BLOCK_SIZE;\n\t\t\tout += AES_BLOCK_SIZE;\n\t\t}\n\t\tif (len) {\n\t\t\tfor(n=0; n < len; ++n)\n\t\t\t\ttmp[n] = in[n] ^ ivec[n];\n\t\t\tfor(n=len; n < AES_BLOCK_SIZE; ++n)\n\t\t\t\ttmp[n] = ivec[n];\n\t\t\tAES_encrypt(tmp, tmp, key);\n\t\t\tmemcpy(out, tmp, AES_BLOCK_SIZE);\n\t\t\tmemcpy(ivec, tmp, AES_BLOCK_SIZE);\n\t\t}\n\t} else {\n\t\twhile (len >= AES_BLOCK_SIZE) {\n\t\t\tmemcpy(tmp, in, AES_BLOCK_SIZE);\n\t\t\tAES_decrypt(in, out, key);\n\t\t\tfor(n=0; n < AES_BLOCK_SIZE; ++n)\n\t\t\t\tout[n] ^= ivec[n];\n\t\t\tmemcpy(ivec, tmp, AES_BLOCK_SIZE);\n\t\t\tlen -= AES_BLOCK_SIZE;\n\t\t\tin += AES_BLOCK_SIZE;\n\t\t\tout += AES_BLOCK_SIZE;\n\t\t}\n\t\tif (len) {\n\t\t\tmemcpy(tmp, in, AES_BLOCK_SIZE);\n\t\t\tAES_decrypt(tmp, tmp, key);\n\t\t\tfor(n=0; n < len; ++n)\n\t\t\t\tout[n] = tmp[n] ^ ivec[n];\n\t\t\tmemcpy(ivec, tmp, AES_BLOCK_SIZE);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/aes.h",
    "content": "/*\n * OpenSSL compatible AES header\n * \n * Copyright (c) 2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef AES_H\n#define AES_H\n\n#define AES_MAXNR 14\n#define AES_BLOCK_SIZE 16\n\nstruct aes_key_st {\n    uint32_t rd_key[4 *(AES_MAXNR + 1)];\n    int rounds;\n};\ntypedef struct aes_key_st AES_KEY;\n\nint AES_set_encrypt_key(const unsigned char *userKey, const int bits,\n\tAES_KEY *key);\nint AES_set_decrypt_key(const unsigned char *userKey, const int bits,\n\tAES_KEY *key);\n\nvoid AES_encrypt(const unsigned char *in, unsigned char *out,\n\tconst AES_KEY *key);\nvoid AES_decrypt(const unsigned char *in, unsigned char *out,\n\tconst AES_KEY *key);\nvoid AES_cbc_encrypt(const unsigned char *in, unsigned char *out,\n\t\t     const unsigned long length, const AES_KEY *key,\n\t\t     unsigned char *ivec, const int enc);\n\n#endif\n"
  },
  {
    "path": "src/block_net.c",
    "content": "/*\n * HTTP block device\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <unistd.h>\n#include <time.h>\n\n#include \"cutils.h\"\n#include \"virtio.h\"\n#include \"fs_wget.h\"\n#include \"list.h\"\n#include \"fbuf.h\"\n#include \"machine.h\"\n\ntypedef enum {\n    CBLOCK_LOADING,\n    CBLOCK_LOADED,\n} CachedBlockStateEnum;\n\ntypedef struct CachedBlock {\n    struct list_head link;\n    struct BlockDeviceHTTP *bf;\n    unsigned int block_num;\n    CachedBlockStateEnum state;\n    FileBuffer fbuf;\n} CachedBlock;\n\n#define BLK_FMT \"%sblk%09u.bin\"\n#define GROUP_FMT \"%sgrp%09u.bin\"\n#define PREFETCH_GROUP_LEN_MAX 32\n\ntypedef struct {\n    struct BlockDeviceHTTP *bf;\n    int group_num;\n    int n_block_num;\n    CachedBlock *tab_block[PREFETCH_GROUP_LEN_MAX];\n} PrefetchGroupRequest;\n\n/* modified data is stored per cluster (smaller than cached blocks to\n   avoid losing space) */\ntypedef struct Cluster {\n    FileBuffer fbuf;\n} Cluster;\n\ntypedef struct BlockDeviceHTTP {\n    BlockDevice *bs;\n    int max_cache_size_kb;\n    char url[1024];\n    int prefetch_count;\n    void (*start_cb)(void *opaque);\n    void *start_opaque;\n    \n    int64_t nb_sectors;\n    int block_size; /* in sectors, power of two */\n    int nb_blocks;\n    struct list_head cached_blocks; /* list of CachedBlock */\n    int n_cached_blocks;\n    int n_cached_blocks_max;\n\n    /* write support */\n    int sectors_per_cluster; /* power of two */\n    Cluster **clusters; /* NULL if no written data */\n    int n_clusters;\n    int n_allocated_clusters;\n    \n    /* statistics */\n    int64_t n_read_sectors;\n    int64_t n_read_blocks;\n    int64_t n_write_sectors;\n\n    /* current read request */\n    BOOL is_write;\n    uint64_t sector_num;\n    int cur_block_num;\n    int sector_index, sector_count;\n    BlockDeviceCompletionFunc *cb;\n    void *opaque;\n    uint8_t *io_buf;\n\n    /* prefetch */\n    int prefetch_group_len;\n} BlockDeviceHTTP;\n\nstatic void bf_update_block(CachedBlock *b, const uint8_t *data);\nstatic void bf_read_onload(void *opaque, int err, void *data, size_t size);\nstatic void bf_init_onload(void *opaque, int err, void *data, size_t size);\nstatic void bf_prefetch_group_onload(void *opaque, int err, void *data,\n                                     size_t size);\n\nstatic CachedBlock *bf_find_block(BlockDeviceHTTP *bf, unsigned int block_num)\n{\n    CachedBlock *b;\n    struct list_head *el;\n    \n    list_for_each(el, &bf->cached_blocks) {\n        b = list_entry(el, CachedBlock, link);\n        if (b->block_num == block_num) {\n            /* move to front */\n            if (bf->cached_blocks.next != el) {\n                list_del(&b->link);\n                list_add(&b->link, &bf->cached_blocks);\n            }\n            return b;\n        }\n    }\n    return NULL;\n}\n\nstatic void bf_free_block(BlockDeviceHTTP *bf, CachedBlock *b)\n{\n    bf->n_cached_blocks--;\n    file_buffer_reset(&b->fbuf);\n    list_del(&b->link);\n    free(b);\n}\n\nstatic CachedBlock *bf_add_block(BlockDeviceHTTP *bf, unsigned int block_num)\n{\n    CachedBlock *b;\n    if (bf->n_cached_blocks >= bf->n_cached_blocks_max) {\n        struct list_head *el, *el1;\n        /* start by looking at the least unused blocks */\n        list_for_each_prev_safe(el, el1, &bf->cached_blocks) {\n            b = list_entry(el, CachedBlock, link);\n            if (b->state == CBLOCK_LOADED) {\n                bf_free_block(bf, b);\n                if (bf->n_cached_blocks < bf->n_cached_blocks_max)\n                    break;\n            }\n        }\n    }\n    b = mallocz(sizeof(CachedBlock));\n    b->bf = bf;\n    b->block_num = block_num;\n    b->state = CBLOCK_LOADING;\n    file_buffer_init(&b->fbuf);\n    file_buffer_resize(&b->fbuf, bf->block_size * 512);\n    list_add(&b->link, &bf->cached_blocks);\n    bf->n_cached_blocks++;\n    return b;\n}\n\nstatic int64_t bf_get_sector_count(BlockDevice *bs)\n{\n    BlockDeviceHTTP *bf = bs->opaque;\n    return bf->nb_sectors;\n}\n\nstatic void bf_start_load_block(BlockDevice *bs, int block_num)\n{\n    BlockDeviceHTTP *bf = bs->opaque;\n    char filename[1024];\n    CachedBlock *b;\n    b = bf_add_block(bf, block_num);\n    bf->n_read_blocks++;\n    /* make a XHR to read the block */\n#if 0\n    printf(\"%u,\\n\", block_num);\n#endif\n#if 0\n    printf(\"load_blk=%d cached=%d read=%d KB (%d KB) write=%d KB (%d KB)\\n\",\n           block_num, bf->n_cached_blocks,\n           (int)(bf->n_read_sectors / 2),\n           (int)(bf->n_read_blocks * bf->block_size / 2),\n           (int)(bf->n_write_sectors / 2),\n           (int)(bf->n_allocated_clusters * bf->sectors_per_cluster / 2));\n#endif\n    snprintf(filename, sizeof(filename), BLK_FMT, bf->url, block_num);\n    //    printf(\"wget %s\\n\", filename);\n    fs_wget(filename, NULL, NULL, b, bf_read_onload, TRUE);\n}\n\nstatic void bf_start_load_prefetch_group(BlockDevice *bs, int group_num,\n                                         const int *tab_block_num,\n                                         int n_block_num)\n{\n    BlockDeviceHTTP *bf = bs->opaque;\n    CachedBlock *b;\n    PrefetchGroupRequest *req;\n    char filename[1024];\n    BOOL req_flag;\n    int i;\n    \n    req_flag = FALSE;\n    req = malloc(sizeof(*req));\n    req->bf = bf;\n    req->group_num = group_num;\n    req->n_block_num = n_block_num;\n    for(i = 0; i < n_block_num; i++) {\n        b = bf_find_block(bf, tab_block_num[i]);\n        if (!b) {\n            b = bf_add_block(bf, tab_block_num[i]);\n            req_flag = TRUE;\n        } else {\n            /* no need to read the block if it is already loading or\n               loaded */\n            b = NULL;\n        }\n        req->tab_block[i] = b;\n    }\n\n    if (req_flag) {\n        snprintf(filename, sizeof(filename), GROUP_FMT, bf->url, group_num);\n        //        printf(\"wget %s\\n\", filename);\n        fs_wget(filename, NULL, NULL, req, bf_prefetch_group_onload, TRUE);\n        /* XXX: should add request in a list to free it for clean exit */\n    } else {\n        free(req);\n    }\n}\n\nstatic void bf_prefetch_group_onload(void *opaque, int err, void *data,\n                                     size_t size)\n{\n    PrefetchGroupRequest *req = opaque;\n    BlockDeviceHTTP *bf = req->bf;\n    CachedBlock *b;\n    int block_bytes, i;\n    \n    if (err < 0) {\n        fprintf(stderr, \"Could not load group %u\\n\", req->group_num);\n        exit(1);\n    }\n    block_bytes = bf->block_size * 512;\n    assert(size == block_bytes * req->n_block_num);\n    for(i = 0; i < req->n_block_num; i++) {\n        b = req->tab_block[i];\n        if (b) {\n            bf_update_block(b, (const uint8_t *)data + block_bytes * i);\n        }\n    }\n    free(req);\n}\n\nstatic int bf_rw_async1(BlockDevice *bs, BOOL is_sync)\n{\n    BlockDeviceHTTP *bf = bs->opaque;\n    int offset, block_num, n, cluster_num;\n    CachedBlock *b;\n    Cluster *c;\n    \n    for(;;) {\n        n = bf->sector_count - bf->sector_index;\n        if (n == 0)\n            break;\n        cluster_num = bf->sector_num / bf->sectors_per_cluster;\n        c = bf->clusters[cluster_num];\n        if (c) {\n            offset = bf->sector_num % bf->sectors_per_cluster;\n            n = min_int(n, bf->sectors_per_cluster - offset);\n            if (bf->is_write) {\n                file_buffer_write(&c->fbuf, offset * 512,\n                                  bf->io_buf + bf->sector_index * 512, n * 512);\n            } else {\n                file_buffer_read(&c->fbuf, offset * 512,\n                                 bf->io_buf + bf->sector_index * 512, n * 512);\n            }\n            bf->sector_index += n;\n            bf->sector_num += n;\n        } else {\n            block_num = bf->sector_num / bf->block_size;\n            offset = bf->sector_num % bf->block_size;\n            n = min_int(n, bf->block_size - offset);\n            bf->cur_block_num = block_num;\n            \n            b = bf_find_block(bf, block_num);\n            if (b) {\n                if (b->state == CBLOCK_LOADING) {\n                    /* wait until the block is loaded */\n                    return 1;\n                } else {\n                    if (bf->is_write) {\n                        int cluster_size, cluster_offset;\n                        uint8_t *buf;\n                        /* allocate a new cluster */\n                        c = mallocz(sizeof(Cluster));\n                        cluster_size = bf->sectors_per_cluster * 512;\n                        buf = malloc(cluster_size);\n                        file_buffer_init(&c->fbuf);\n                        file_buffer_resize(&c->fbuf, cluster_size);\n                        bf->clusters[cluster_num] = c;\n                        /* copy the cached block data to the cluster */\n                        cluster_offset = (cluster_num * bf->sectors_per_cluster) &\n                            (bf->block_size - 1);\n                        file_buffer_read(&b->fbuf, cluster_offset * 512,\n                                         buf, cluster_size);\n                        file_buffer_write(&c->fbuf, 0, buf, cluster_size);\n                        free(buf);\n                        bf->n_allocated_clusters++;\n                        continue; /* write to the allocated cluster */\n                    } else {\n                        file_buffer_read(&b->fbuf, offset * 512,\n                                         bf->io_buf + bf->sector_index * 512, n * 512);\n                    }\n                    bf->sector_index += n;\n                    bf->sector_num += n;\n                }\n            } else {\n                bf_start_load_block(bs, block_num);\n                return 1;\n            }\n            bf->cur_block_num = -1;\n        }\n    }\n\n    if (!is_sync) {\n        //        printf(\"end of request\\n\");\n        /* end of request */\n        bf->cb(bf->opaque, 0);\n    } \n    return 0;\n}\n\nstatic void bf_update_block(CachedBlock *b, const uint8_t *data)\n{\n    BlockDeviceHTTP *bf = b->bf;\n    BlockDevice *bs = bf->bs;\n\n    assert(b->state == CBLOCK_LOADING);\n    file_buffer_write(&b->fbuf, 0, data, bf->block_size * 512);\n    b->state = CBLOCK_LOADED;\n    \n    /* continue I/O read/write if necessary */\n    if (b->block_num == bf->cur_block_num) {\n        bf_rw_async1(bs, FALSE);\n    }\n}\n\nstatic void bf_read_onload(void *opaque, int err, void *data, size_t size)\n{\n    CachedBlock *b = opaque;\n    BlockDeviceHTTP *bf = b->bf;\n\n    if (err < 0) {\n        fprintf(stderr, \"Could not load block %u\\n\", b->block_num);\n        exit(1);\n    }\n    \n    assert(size == bf->block_size * 512);\n    bf_update_block(b, data);\n}\n\nstatic int bf_read_async(BlockDevice *bs,\n                         uint64_t sector_num, uint8_t *buf, int n,\n                         BlockDeviceCompletionFunc *cb, void *opaque)\n{\n    BlockDeviceHTTP *bf = bs->opaque;\n    //    printf(\"bf_read_async: sector_num=%\" PRId64 \" n=%d\\n\", sector_num, n);\n    bf->is_write = FALSE;\n    bf->sector_num = sector_num;\n    bf->io_buf = buf;\n    bf->sector_count = n;\n    bf->sector_index = 0;\n    bf->cb = cb;\n    bf->opaque = opaque;\n    bf->n_read_sectors += n;\n    return bf_rw_async1(bs, TRUE);\n}\n\nstatic int bf_write_async(BlockDevice *bs,\n                          uint64_t sector_num, const uint8_t *buf, int n,\n                          BlockDeviceCompletionFunc *cb, void *opaque)\n{\n    BlockDeviceHTTP *bf = bs->opaque;\n    //    printf(\"bf_write_async: sector_num=%\" PRId64 \" n=%d\\n\", sector_num, n);\n    bf->is_write = TRUE;\n    bf->sector_num = sector_num;\n    bf->io_buf = (uint8_t *)buf;\n    bf->sector_count = n;\n    bf->sector_index = 0;\n    bf->cb = cb;\n    bf->opaque = opaque;\n    bf->n_write_sectors += n;\n    return bf_rw_async1(bs, TRUE);\n}\n\nBlockDevice *block_device_init_http(const char *url,\n                                    int max_cache_size_kb,\n                                    void (*start_cb)(void *opaque),\n                                    void *start_opaque)\n{\n    BlockDevice *bs;\n    BlockDeviceHTTP *bf;\n    char *p;\n\n    bs = mallocz(sizeof(*bs));\n    bf = mallocz(sizeof(*bf));\n    strcpy(bf->url, url);\n    /* get the path with the trailing '/' */\n    p = strrchr(bf->url, '/');\n    if (!p)\n        p = bf->url;\n    else\n        p++;\n    *p = '\\0';\n\n    init_list_head(&bf->cached_blocks);\n    bf->max_cache_size_kb = max_cache_size_kb;\n    bf->start_cb = start_cb;\n    bf->start_opaque = start_opaque;\n    bf->bs = bs;\n    \n    bs->opaque = bf;\n    bs->get_sector_count = bf_get_sector_count;\n    bs->read_async = bf_read_async;\n    bs->write_async = bf_write_async;\n    \n    fs_wget(url, NULL, NULL, bs, bf_init_onload, TRUE);\n    return bs;\n}\n\nstatic void bf_init_onload(void *opaque, int err, void *data, size_t size)\n{\n    BlockDevice *bs = opaque;\n    BlockDeviceHTTP *bf = bs->opaque;\n    int block_size_kb, block_num;\n    JSONValue cfg, array;\n    \n    if (err < 0) {\n        fprintf(stderr, \"Could not load block device file (err=%d)\\n\", -err);\n        exit(1);\n    }\n\n    /* parse the disk image info */\n    cfg = json_parse_value_len(data, size);\n    if (json_is_error(cfg)) {\n        vm_error(\"error: %s\\n\", json_get_error(cfg));\n    config_error:\n        json_free(cfg);\n        exit(1);\n    }\n\n    if (vm_get_int(cfg, \"block_size\", &block_size_kb) < 0)\n        goto config_error;\n    bf->block_size = block_size_kb * 2;\n    if (bf->block_size <= 0 ||\n        (bf->block_size & (bf->block_size - 1)) != 0) {\n        vm_error(\"invalid block_size\\n\");\n        goto config_error;\n    }\n    if (vm_get_int(cfg, \"n_block\", &bf->nb_blocks) < 0)\n        goto config_error;\n    if (bf->nb_blocks <= 0) {\n        vm_error(\"invalid n_block\\n\");\n        goto config_error;\n    }\n\n    bf->nb_sectors = bf->block_size * (uint64_t)bf->nb_blocks;\n    bf->n_cached_blocks = 0;\n    bf->n_cached_blocks_max = max_int(1, bf->max_cache_size_kb / block_size_kb);\n    bf->cur_block_num = -1; /* no request in progress */\n    \n    bf->sectors_per_cluster = 8; /* 4 KB */\n    bf->n_clusters = (bf->nb_sectors + bf->sectors_per_cluster - 1) / bf->sectors_per_cluster;\n    bf->clusters = mallocz(sizeof(bf->clusters[0]) * bf->n_clusters);\n\n    if (vm_get_int_opt(cfg, \"prefetch_group_len\",\n                       &bf->prefetch_group_len, 1) < 0)\n        goto config_error;\n    if (bf->prefetch_group_len > PREFETCH_GROUP_LEN_MAX) {\n        vm_error(\"prefetch_group_len is too large\");\n        goto config_error;\n    }\n    \n    array = json_object_get(cfg, \"prefetch\");\n    if (!json_is_undefined(array)) {\n        int idx, prefetch_len, l, i;\n        JSONValue el;\n        int tab_block_num[PREFETCH_GROUP_LEN_MAX];\n                          \n        if (array.type != JSON_ARRAY) {\n            vm_error(\"expecting an array\\n\");\n            goto config_error;\n        }\n        prefetch_len = array.u.array->len;\n        idx = 0;\n        while (idx < prefetch_len) {\n            l = min_int(prefetch_len - idx, bf->prefetch_group_len);\n            for(i = 0; i < l; i++) {\n                el = json_array_get(array, idx + i);\n                if (el.type != JSON_INT) {\n                    vm_error(\"expecting an integer\\n\");\n                    goto config_error;\n                }\n                tab_block_num[i] = el.u.int32;\n            }\n            if (l == 1) {\n                block_num = tab_block_num[0];\n                if (!bf_find_block(bf, block_num)) {\n                    bf_start_load_block(bs, block_num);\n                }\n            } else {\n                bf_start_load_prefetch_group(bs, idx / bf->prefetch_group_len,\n                                             tab_block_num, l);\n            }\n            idx += l;\n        }\n    }\n    json_free(cfg);\n    \n    if (bf->start_cb) {\n        bf->start_cb(bf->start_opaque);\n    }\n}\n"
  },
  {
    "path": "src/build_filelist.c",
    "content": "/*\n * File list builder for RISCVEMU network filesystem\n * \n * Copyright (c) 2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <stdarg.h>\n#include <sys/statfs.h>\n#include <sys/stat.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <dirent.h>\n#include <errno.h>\n#include <sys/sysmacros.h>\n\n#include \"cutils.h\"\n#include \"fs_utils.h\"\n\nvoid print_str(FILE *f, const char *str)\n{\n    const char *s;\n    int c;\n    s = str;\n    while (*s != '\\0') {\n        if (*s <= ' ' || *s > '~')\n            goto use_quote;\n        s++;\n    }\n    fputs(str, f);\n    return;\n use_quote:\n    s = str;\n    fputc('\"', f);\n    while (*s != '\\0') {\n        c = *(uint8_t *)s;\n        if (c < ' ' || c == 127) {\n            fprintf(f, \"\\\\x%02x\", c);\n        } else if (c == '\\\\' || c == '\\\"') {\n            fprintf(f, \"\\\\%c\", c);\n        } else {\n            fputc(c, f);\n        }\n        s++;\n    }\n    fputc('\"', f);\n}\n\n#define COPY_BUF_LEN (1024 * 1024)\n\nstatic void copy_file(const char *src_filename, const char *dst_filename)\n{\n    uint8_t *buf;\n    FILE *fi, *fo;\n    int len;\n    \n    buf = malloc(COPY_BUF_LEN);\n    fi = fopen(src_filename, \"rb\");\n    if (!fi) {\n        perror(src_filename);\n        exit(1);\n    }\n    fo = fopen(dst_filename, \"wb\");\n    if (!fo) {\n        perror(dst_filename);\n        exit(1);\n    }\n    for(;;) {\n        len = fread(buf, 1, COPY_BUF_LEN, fi);\n        if (len == 0)\n            break;\n        fwrite(buf, 1, len, fo);\n    }\n    fclose(fo);\n    fclose(fi);\n}\n\ntypedef struct {\n    char *files_path;\n    uint64_t next_inode_num;\n    uint64_t fs_size;\n    uint64_t fs_max_size;\n    FILE *f;\n} ScanState;\n\nstatic void add_file_size(ScanState *s, uint64_t size)\n{\n    s->fs_size += block_align(size, FS_BLOCK_SIZE);\n    if (s->fs_size > s->fs_max_size) {\n        fprintf(stderr, \"Filesystem Quota exceeded (%\" PRId64 \" bytes)\\n\", s->fs_max_size);\n        exit(1);\n    }\n}\n\nvoid scan_dir(ScanState *s, const char *path)\n{\n    FILE *f = s->f;\n    DIR *dirp;\n    struct dirent *de;\n    const char *name;\n    struct stat st;\n    char *path1;\n    uint32_t mode, v;\n\n    dirp = opendir(path);\n    if (!dirp) {\n        perror(path);\n        exit(1);\n    }\n    for(;;) {\n        de = readdir(dirp);\n        if (!de)\n            break;\n        name = de->d_name;\n        if (!strcmp(name, \".\") || !strcmp(name, \"..\"))\n            continue;\n        path1 = compose_path(path, name);\n        if (lstat(path1, &st) < 0) {\n            perror(path1);\n            exit(1);\n        }\n\n        mode = st.st_mode & 0xffff;\n        fprintf(f, \"%06o %u %u\", \n                mode, \n                (int)st.st_uid,\n                (int)st.st_gid);\n        if (S_ISCHR(mode) || S_ISBLK(mode)) {\n            fprintf(f, \" %u %u\",\n                    (int)major(st.st_rdev),\n                    (int)minor(st.st_rdev));\n        }\n        if (S_ISREG(mode)) {\n            fprintf(f, \" %\" PRIu64, st.st_size);\n        }\n        /* modification time (at most ms resolution) */\n        fprintf(f, \" %u\", (int)st.st_mtim.tv_sec);\n        v = st.st_mtim.tv_nsec;\n        if (v != 0) {\n            fprintf(f, \".\");\n            while (v != 0) {\n                fprintf(f, \"%u\", v / 100000000);\n                v = (v % 100000000) * 10;\n            }\n        }\n        \n        fprintf(f, \" \");\n        print_str(f, name);\n        if (S_ISLNK(mode)) {\n            char buf[1024];\n            int len;\n            len = readlink(path1, buf, sizeof(buf) - 1);\n            if (len < 0) {\n                perror(\"readlink\");\n                exit(1);\n            }\n            buf[len] = '\\0';\n            fprintf(f, \" \");\n            print_str(f, buf);\n        } else if (S_ISREG(mode) && st.st_size > 0) {\n            char buf1[FILEID_SIZE_MAX], *fname;\n            FSFileID file_id;\n            file_id = s->next_inode_num++;\n            fprintf(f, \" %\" PRIx64, file_id);\n            file_id_to_filename(buf1, file_id);\n            fname = compose_path(s->files_path, buf1);\n            copy_file(path1, fname);\n            add_file_size(s, st.st_size);\n        }\n\n        fprintf(f, \"\\n\");\n        if (S_ISDIR(mode)) {\n            scan_dir(s, path1);\n        }\n        free(path1);\n    }\n\n    closedir(dirp);\n    fprintf(f, \".\\n\"); /* end of directory */\n}\n\nvoid help(void)\n{\n    printf(\"usage: build_filelist [options] source_path dest_path\\n\"\n           \"\\n\"\n           \"Options:\\n\"\n           \"-m size_mb  set the max filesystem size in MiB\\n\");\n    exit(1);\n}\n\n#define LOCK_FILENAME \"lock\"\n\nint main(int argc, char **argv)\n{\n    const char *dst_path, *src_path;\n    ScanState s_s, *s = &s_s;\n    FILE *f;\n    char *filename;\n    FSFileID root_id;\n    char fname[FILEID_SIZE_MAX];\n    struct stat st;\n    uint64_t first_inode, fs_max_size;\n    int c;\n    \n    first_inode = 1;\n    fs_max_size = (uint64_t)1 << 30;\n    for(;;) {\n        c = getopt(argc, argv, \"hi:m:\");\n        if (c == -1)\n            break;\n        switch(c) {\n        case 'h':\n            help();\n        case 'i':\n            first_inode = strtoul(optarg, NULL, 0);\n            break;\n        case 'm':\n            fs_max_size = (uint64_t)strtoul(optarg, NULL, 0) << 20;\n            break;\n        default:\n            exit(1);\n        }\n    }\n\n    if (optind + 1 >= argc)\n        help();\n    src_path = argv[optind];\n    dst_path = argv[optind + 1];\n    \n    mkdir(dst_path, 0755);\n\n    s->files_path = compose_path(dst_path, ROOT_FILENAME);\n    s->next_inode_num = first_inode;\n    s->fs_size = 0;\n    s->fs_max_size = fs_max_size;\n        \n    mkdir(s->files_path, 0755);\n\n    root_id = s->next_inode_num++;\n    file_id_to_filename(fname, root_id);\n    filename = compose_path(s->files_path, fname);\n    f = fopen(filename, \"wb\");\n    if (!f) {\n        perror(filename);\n        exit(1);\n    }\n    fprintf(f, \"Version: 1\\n\");\n    fprintf(f, \"Revision: 1\\n\");\n    fprintf(f, \"\\n\");\n    s->f = f;\n    scan_dir(s, src_path);\n    fclose(f);\n\n    /* take into account the filelist size */\n    if (stat(filename, &st) < 0) {\n        perror(filename);\n        exit(1);\n    }\n    add_file_size(s, st.st_size);\n    \n    free(filename);\n    \n    filename = compose_path(dst_path, HEAD_FILENAME);\n    f = fopen(filename, \"wb\");\n    if (!f) {\n        perror(filename);\n        exit(1);\n    }\n    fprintf(f, \"Version: 1\\n\");\n    fprintf(f, \"Revision: 1\\n\");\n    fprintf(f, \"NextFileID: %\" PRIx64 \"\\n\", s->next_inode_num);\n    fprintf(f, \"FSFileCount: %\" PRIu64 \"\\n\", s->next_inode_num - 1);\n    fprintf(f, \"FSSize: %\" PRIu64 \"\\n\", s->fs_size);\n    fprintf(f, \"FSMaxSize: %\" PRIu64 \"\\n\", s->fs_max_size);\n    fprintf(f, \"Key:\\n\"); /* not encrypted */\n    fprintf(f, \"RootID: %\" PRIx64 \"\\n\", root_id);\n    fclose(f);\n    free(filename);\n    \n    filename = compose_path(dst_path, LOCK_FILENAME);\n    f = fopen(filename, \"wb\");\n    if (!f) {\n        perror(filename);\n        exit(1);\n    }\n    fclose(f);\n    free(filename);\n\n    return 0;\n}\n"
  },
  {
    "path": "src/cutils.c",
    "content": "/*\n * Misc C utilities\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <stdarg.h>\n#include <sys/time.h>\n#include <ctype.h>\n\n#include \"cutils.h\"\n\nvoid *mallocz(size_t size)\n{\n    void *ptr;\n    ptr = malloc(size);\n    if (!ptr)\n        return NULL;\n    memset(ptr, 0, size);\n    return ptr;\n}\n\nvoid pstrcpy(char *buf, int buf_size, const char *str)\n{\n    int c;\n    char *q = buf;\n\n    if (buf_size <= 0)\n        return;\n\n    for(;;) {\n        c = *str++;\n        if (c == 0 || q >= buf + buf_size - 1)\n            break;\n        *q++ = c;\n    }\n    *q = '\\0';\n}\n\nchar *pstrcat(char *buf, int buf_size, const char *s)\n{\n    int len;\n    len = strlen(buf);\n    if (len < buf_size)\n        pstrcpy(buf + len, buf_size - len, s);\n    return buf;\n}\n\nint strstart(const char *str, const char *val, const char **ptr)\n{\n    const char *p, *q;\n    p = str;\n    q = val;\n    while (*q != '\\0') {\n        if (*p != *q)\n            return 0;\n        p++;\n        q++;\n    }\n    if (ptr)\n        *ptr = p;\n    return 1;\n}\n\nvoid dbuf_init(DynBuf *s)\n{\n    memset(s, 0, sizeof(*s));\n}\n\nvoid dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)\n{\n    size_t end, new_size;\n    new_size = end = offset + len;\n    if (new_size > s->allocated_size) {\n        new_size = max_int(new_size, s->allocated_size * 3 / 2);\n        s->buf = realloc(s->buf, new_size);\n        s->allocated_size = new_size;\n    }\n    memcpy(s->buf + offset, data, len);\n    if (end > s->size)\n        s->size = end;\n}\n\nvoid dbuf_putc(DynBuf *s, uint8_t c)\n{\n    dbuf_write(s, s->size, &c, 1);\n}\n\nvoid dbuf_putstr(DynBuf *s, const char *str)\n{\n    dbuf_write(s, s->size, (const uint8_t *)str, strlen(str));\n}\n\nvoid dbuf_free(DynBuf *s)\n{\n    free(s->buf);\n    memset(s, 0, sizeof(*s));\n}\n"
  },
  {
    "path": "src/cutils.h",
    "content": "/*\n * C utilities\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef CUTILS_H\n#define CUTILS_H\n\n#include <inttypes.h>\n\n#define likely(x)       __builtin_expect(!!(x), 1)\n#define unlikely(x)     __builtin_expect(!!(x), 0)\n#define force_inline inline __attribute__((always_inline))\n#define no_inline __attribute__((noinline))\n#define __maybe_unused __attribute__((unused))\n\n#define xglue(x, y) x ## y\n#define glue(x, y) xglue(x, y)\n#define stringify(s)    tostring(s)\n#define tostring(s)     #s\n\n#ifndef offsetof\n#define offsetof(type, field) ((size_t) &((type *)0)->field)\n#endif\n#define countof(x) (sizeof(x) / sizeof(x[0]))\n\n#define DLL_PUBLIC __attribute__ ((visibility (\"default\")))\n\n#ifndef _BOOL_defined\n#define _BOOL_defined\n#undef FALSE\n#undef TRUE\n\ntypedef int BOOL;\nenum {\n    FALSE = 0,\n    TRUE = 1,\n};\n#endif\n\n/* this test works at least with gcc */\n#if defined(__SIZEOF_INT128__)\n#define HAVE_INT128\n#endif\n\n#ifdef HAVE_INT128\ntypedef __int128 int128_t;\ntypedef unsigned __int128 uint128_t;\n#endif\n\nstatic inline int max_int(int a, int b)\n{\n    if (a > b)\n        return a;\n    else\n        return b;\n}\n\nstatic inline int min_int(int a, int b)\n{\n    if (a < b)\n        return a;\n    else\n        return b;\n}\n\nvoid *mallocz(size_t size);\n\n#if defined(_WIN32)\nstatic inline uint32_t bswap_32(uint32_t v)\n{\n    return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >>  8) |\n        ((v & 0x0000ff00) <<  8) | ((v & 0x000000ff) << 24);\n}\n#else\n#include <byteswap.h>\n#endif\n\nstatic inline uint16_t get_le16(const uint8_t *ptr)\n{\n    return ptr[0] | (ptr[1] << 8);\n}\n\nstatic inline uint32_t get_le32(const uint8_t *ptr)\n{\n    return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);\n}\n\nstatic inline uint64_t get_le64(const uint8_t *ptr)\n{\n    return get_le32(ptr) | ((uint64_t)get_le32(ptr + 4) << 32);\n}\n\nstatic inline void put_le16(uint8_t *ptr, uint16_t v)\n{\n    ptr[0] = v;\n    ptr[1] = v >> 8;\n}\n\nstatic inline void put_le32(uint8_t *ptr, uint32_t v)\n{\n    ptr[0] = v;\n    ptr[1] = v >> 8;\n    ptr[2] = v >> 16;\n    ptr[3] = v >> 24;\n}\n\nstatic inline void put_le64(uint8_t *ptr, uint64_t v)\n{\n    put_le32(ptr, v);\n    put_le32(ptr + 4, v >> 32);\n}\n\nstatic inline uint32_t get_be32(const uint8_t *d)\n{\n    return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];\n}\n\nstatic inline void put_be32(uint8_t *d, uint32_t v)\n{\n    d[0] = v >> 24;\n    d[1] = v >> 16;\n    d[2] = v >> 8;\n    d[3] = v >> 0;\n}\n\nstatic inline void put_be64(uint8_t *d, uint64_t v)\n{\n    put_be32(d, v >> 32);\n    put_be32(d + 4, v);\n}\n\n#ifdef WORDS_BIGENDIAN\nstatic inline uint32_t cpu_to_be32(uint32_t v)\n{\n    return v;\n}\n#else\nstatic inline uint32_t cpu_to_be32(uint32_t v)\n{\n    return bswap_32(v);\n}\n#endif\n\n/* XXX: optimize */\nstatic inline int ctz32(uint32_t a)\n{\n    int i;\n    if (a == 0)\n        return 32;\n    for(i = 0; i < 32; i++) {\n        if ((a >> i) & 1)\n            return i;\n    }\n    return 32;\n}\n\n\nvoid *mallocz(size_t size);\nvoid pstrcpy(char *buf, int buf_size, const char *str);\nchar *pstrcat(char *buf, int buf_size, const char *s);\nint strstart(const char *str, const char *val, const char **ptr);\n\ntypedef struct {\n    uint8_t *buf;\n    size_t size;\n    size_t allocated_size;\n} DynBuf;\n\nvoid dbuf_init(DynBuf *s);\nvoid dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);\nvoid dbuf_putc(DynBuf *s, uint8_t c);\nvoid dbuf_putstr(DynBuf *s, const char *str);\nvoid dbuf_free(DynBuf *s);\n\n#endif /* CUTILS_H */\n"
  },
  {
    "path": "src/fbuf.h",
    "content": "#ifndef FBUF_H\n#define FBUF_H\n\ntypedef struct {\n#if defined(EMSCRIPTEN)\n    int handle;\n#else\n    uint8_t *data;\n#endif\n    size_t allocated_size;\n} FileBuffer;\n\nvoid file_buffer_init(FileBuffer *bs);\nvoid file_buffer_reset(FileBuffer *bs);\nint file_buffer_resize(FileBuffer *bs, size_t new_size);\nvoid file_buffer_write(FileBuffer *bs, size_t offset, const uint8_t *buf,\n                       size_t size);\nvoid file_buffer_set(FileBuffer *bs, size_t offset, int val, size_t size);\nvoid file_buffer_read(FileBuffer *bs, size_t offset, uint8_t *buf,\n                      size_t size);\n\n#endif /* FBUF_H */\n"
  },
  {
    "path": "src/fs.c",
    "content": "/*\n * Filesystem utilities\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <stdarg.h>\n\n#include \"cutils.h\"\n#include \"fs.h\"\n\nFSFile *fs_dup(FSDevice *fs, FSFile *f)\n{\n    FSQID qid;\n    fs->fs_walk(fs, &f, &qid, f, 0, NULL);\n    return f;\n}\n\nFSFile *fs_walk_path1(FSDevice *fs, FSFile *f, const char *path,\n                      char **pname)\n{\n    const char *p;\n    char *name;\n    FSFile *f1;\n    FSQID qid;\n    int len, ret;\n    BOOL is_last, is_first;\n\n    if (path[0] == '/')\n        path++;\n    \n    is_first = TRUE;\n    for(;;) {\n        p = strchr(path, '/');\n        if (!p) {\n            name = (char *)path;\n            if (pname) {\n                *pname = name;\n                if (is_first) {\n                    ret = fs->fs_walk(fs, &f, &qid, f, 0, NULL);\n                    if (ret < 0)\n                        f = NULL;\n                }\n                return f;\n            }\n            is_last = TRUE;\n        } else {\n            len = p - path;\n            name = malloc(len + 1);\n            memcpy(name, path, len);\n            name[len] = '\\0';\n            is_last = FALSE;\n        }\n        ret = fs->fs_walk(fs, &f1, &qid, f, 1, &name);\n        if (!is_last)\n            free(name);\n        if (!is_first)\n            fs->fs_delete(fs, f);\n        f = f1;\n        is_first = FALSE;\n        if (ret <= 0) {\n            fs->fs_delete(fs, f);\n            f = NULL;\n            break;\n        } else if (is_last) {\n            break;\n        }\n        path = p + 1;\n    }\n    return f;\n}\n\nFSFile *fs_walk_path(FSDevice *fs, FSFile *f, const char *path)\n{\n    return fs_walk_path1(fs, f, path, NULL);\n}\n\nvoid fs_end(FSDevice *fs)\n{\n    fs->fs_end(fs);\n    free(fs);\n}\n"
  },
  {
    "path": "src/fs.h",
    "content": "/*\n * Filesystem abstraction\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n/* FSQID.type */\n#define P9_QTDIR 0x80\n#define P9_QTAPPEND 0x40\n#define P9_QTEXCL 0x20\n#define P9_QTMOUNT 0x10\n#define P9_QTAUTH 0x08\n#define P9_QTTMP 0x04\n#define P9_QTSYMLINK 0x02\n#define P9_QTLINK 0x01\n#define P9_QTFILE 0x00\n\n/* mode bits */\n#define P9_S_IRWXUGO 0x01FF\n#define P9_S_ISVTX   0x0200\n#define P9_S_ISGID   0x0400\n#define P9_S_ISUID   0x0800\n\n#define P9_S_IFMT   0xF000\n#define P9_S_IFIFO  0x1000\n#define P9_S_IFCHR  0x2000\n#define P9_S_IFDIR  0x4000\n#define P9_S_IFBLK  0x6000\n#define P9_S_IFREG  0x8000\n#define P9_S_IFLNK  0xA000\n#define P9_S_IFSOCK 0xC000\n\n/* flags for lopen()/lcreate() */\n#define P9_O_RDONLY        0x00000000\n#define P9_O_WRONLY        0x00000001\n#define P9_O_RDWR          0x00000002\n#define P9_O_NOACCESS      0x00000003\n#define P9_O_CREAT         0x00000040\n#define P9_O_EXCL          0x00000080\n#define P9_O_NOCTTY        0x00000100\n#define P9_O_TRUNC         0x00000200\n#define P9_O_APPEND        0x00000400\n#define P9_O_NONBLOCK      0x00000800\n#define P9_O_DSYNC         0x00001000\n#define P9_O_FASYNC        0x00002000\n#define P9_O_DIRECT        0x00004000\n#define P9_O_LARGEFILE     0x00008000\n#define P9_O_DIRECTORY     0x00010000\n#define P9_O_NOFOLLOW      0x00020000\n#define P9_O_NOATIME       0x00040000\n#define P9_O_CLOEXEC       0x00080000\n#define P9_O_SYNC          0x00100000\n\n/* for fs_setattr() */\n#define P9_SETATTR_MODE      0x00000001\n#define P9_SETATTR_UID       0x00000002\n#define P9_SETATTR_GID       0x00000004\n#define P9_SETATTR_SIZE      0x00000008\n#define P9_SETATTR_ATIME     0x00000010\n#define P9_SETATTR_MTIME     0x00000020\n#define P9_SETATTR_CTIME     0x00000040\n#define P9_SETATTR_ATIME_SET 0x00000080\n#define P9_SETATTR_MTIME_SET 0x00000100\n\n#define P9_EPERM     1\n#define P9_ENOENT    2\n#define P9_EIO       5\n#define\tP9_EEXIST    17\n#define\tP9_ENOTDIR   20\n#define P9_EINVAL    22\n#define\tP9_ENOSPC    28\n#define P9_ENOTEMPTY 39\n#define P9_EPROTO    71\n#define P9_ENOTSUP   524\n\ntypedef struct FSDevice FSDevice;\ntypedef struct FSFile FSFile;\n\ntypedef struct {\n    uint32_t f_bsize;\n    uint64_t f_blocks;\n    uint64_t f_bfree;\n    uint64_t f_bavail;\n    uint64_t f_files;\n    uint64_t f_ffree;\n} FSStatFS;\n\ntypedef struct {\n    uint8_t type; /* P9_IFx */\n    uint32_t version;\n    uint64_t path;\n} FSQID;\n\ntypedef struct {\n    FSQID qid;\n    uint32_t st_mode;\n    uint32_t st_uid;\n    uint32_t st_gid;\n    uint64_t st_nlink;\n    uint64_t st_rdev;\n    uint64_t st_size;\n    uint64_t st_blksize;\n    uint64_t st_blocks;\n    uint64_t st_atime_sec;\n    uint32_t st_atime_nsec;\n    uint64_t st_mtime_sec;\n    uint32_t st_mtime_nsec;\n    uint64_t st_ctime_sec;\n    uint32_t st_ctime_nsec;\n} FSStat;\n\n#define P9_LOCK_TYPE_RDLCK 0\n#define P9_LOCK_TYPE_WRLCK 1\n#define P9_LOCK_TYPE_UNLCK 2\n\n#define P9_LOCK_FLAGS_BLOCK 1\n#define P9_LOCK_FLAGS_RECLAIM 2\n\n#define P9_LOCK_SUCCESS 0\n#define P9_LOCK_BLOCKED 1\n#define P9_LOCK_ERROR   2\n#define P9_LOCK_GRACE   3\n\n#define FSCMD_NAME \".fscmd\"\n\ntypedef struct {\n    uint8_t type;\n    uint32_t flags;\n    uint64_t start;\n    uint64_t length;\n    uint32_t proc_id;\n    char *client_id;\n} FSLock;\n\ntypedef void FSOpenCompletionFunc(FSDevice *fs, FSQID *qid, int err,\n                                  void *opaque);\n\nstruct FSDevice {\n    void (*fs_end)(FSDevice *s);\n    void (*fs_delete)(FSDevice *s, FSFile *f);\n    void (*fs_statfs)(FSDevice *fs, FSStatFS *st);\n    int (*fs_attach)(FSDevice *fs, FSFile **pf, FSQID *qid, uint32_t uid,\n                     const char *uname, const char *aname);\n    int (*fs_walk)(FSDevice *fs, FSFile **pf, FSQID *qids,\n                   FSFile *f, int n, char **names);\n    int (*fs_mkdir)(FSDevice *fs, FSQID *qid, FSFile *f,\n                    const char *name, uint32_t mode, uint32_t gid);\n    int (*fs_open)(FSDevice *fs, FSQID *qid, FSFile *f, uint32_t flags,\n                   FSOpenCompletionFunc *cb, void *opaque);\n    int (*fs_create)(FSDevice *fs, FSQID *qid, FSFile *f, const char *name, \n                     uint32_t flags, uint32_t mode, uint32_t gid);\n    int (*fs_stat)(FSDevice *fs, FSFile *f, FSStat *st);\n    int (*fs_setattr)(FSDevice *fs, FSFile *f, uint32_t mask,\n                      uint32_t mode, uint32_t uid, uint32_t gid,\n                      uint64_t size, uint64_t atime_sec, uint64_t atime_nsec,\n                      uint64_t mtime_sec, uint64_t mtime_nsec);\n    void (*fs_close)(FSDevice *fs, FSFile *f);\n    int (*fs_readdir)(FSDevice *fs, FSFile *f, uint64_t offset,\n                      uint8_t *buf, int count);\n    int (*fs_read)(FSDevice *fs, FSFile *f, uint64_t offset,\n            uint8_t *buf, int count);\n    int (*fs_write)(FSDevice *fs, FSFile *f, uint64_t offset,\n             const uint8_t *buf, int count);\n    int (*fs_link)(FSDevice *fs, FSFile *df, FSFile *f, const char *name);\n    int (*fs_symlink)(FSDevice *fs, FSQID *qid,\n                      FSFile *f, const char *name, const char *symgt, uint32_t gid);\n    int (*fs_mknod)(FSDevice *fs, FSQID *qid,\n                    FSFile *f, const char *name, uint32_t mode, uint32_t major,\n                    uint32_t minor, uint32_t gid);\n    int (*fs_readlink)(FSDevice *fs, char *buf, int buf_size, FSFile *f);\n    int (*fs_renameat)(FSDevice *fs, FSFile *f, const char *name, \n                       FSFile *new_f, const char *new_name);\n    int (*fs_unlinkat)(FSDevice *fs, FSFile *f, const char *name);\n    int (*fs_lock)(FSDevice *fs, FSFile *f, const FSLock *lock);\n    int (*fs_getlock)(FSDevice *fs, FSFile *f, FSLock *lock);\n};\n\nFSDevice *fs_disk_init(const char *root_path);\nFSDevice *fs_mem_init(void);\nFSDevice *fs_net_init(const char *url, void (*start)(void *opaque), void *opaque);\nvoid fs_net_set_pwd(FSDevice *fs, const char *pwd);\n#ifdef EMSCRIPTEN\nvoid fs_import_file(const char *filename, uint8_t *buf, int buf_len);\n#endif\nvoid fs_export_file(const char *filename,\n                    const uint8_t *buf, int buf_len);\nvoid fs_end(FSDevice *fs);\nvoid fs_dump_cache_load(FSDevice *fs1, const char *filename);\n\nFSFile *fs_dup(FSDevice *fs, FSFile *f);\nFSFile *fs_walk_path1(FSDevice *fs, FSFile *f, const char *path,\n                      char **pname);\nFSFile *fs_walk_path(FSDevice *fs, FSFile *f, const char *path);\n"
  },
  {
    "path": "src/fs_disk.c",
    "content": "/*\n * Filesystem on disk\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <stdarg.h>\n#include <sys/statfs.h>\n#include <sys/stat.h>\n#include <sys/sysmacros.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <dirent.h>\n#include <errno.h>\n\n#include \"cutils.h\"\n#include \"list.h\"\n#include \"fs.h\"\n\ntypedef struct {\n    FSDevice common;\n    char *root_path;\n} FSDeviceDisk;\n\nstatic void fs_close(FSDevice *fs, FSFile *f);\n\nstruct FSFile {\n    uint32_t uid;\n    char *path; /* complete path */\n    BOOL is_opened;\n    BOOL is_dir;\n    union {\n        int fd;\n        DIR *dirp;\n    } u;\n};\n\nstatic void fs_delete(FSDevice *fs, FSFile *f)\n{\n    if (f->is_opened)\n        fs_close(fs, f);\n    free(f->path);\n    free(f);\n}\n\n/* warning: path belong to fid_create() */\nstatic FSFile *fid_create(FSDevice *s1, char *path, uint32_t uid)\n{\n    FSFile *f;\n    f = mallocz(sizeof(*f));\n    f->path = path;\n    f->uid = uid;\n    return f;\n}\n\n\nstatic int errno_table[][2] = {\n    { P9_EPERM, EPERM },\n    { P9_ENOENT, ENOENT },\n    { P9_EIO, EIO },\n    { P9_EEXIST, EEXIST },\n    { P9_EINVAL, EINVAL },\n    { P9_ENOSPC, ENOSPC },\n    { P9_ENOTEMPTY, ENOTEMPTY },\n    { P9_EPROTO, EPROTO },\n    { P9_ENOTSUP, ENOTSUP },\n};\n\nstatic int errno_to_p9(int err)\n{\n    int i;\n    if (err == 0)\n        return 0;\n    for(i = 0; i < countof(errno_table); i++) {\n        if (err == errno_table[i][1])\n            return errno_table[i][0];\n    }\n    return P9_EINVAL;\n}\n\nstatic int open_flags[][2] = {\n    { P9_O_CREAT, O_CREAT },\n    { P9_O_EXCL, O_EXCL },\n    //    { P9_O_NOCTTY, O_NOCTTY },\n    { P9_O_TRUNC, O_TRUNC },\n    { P9_O_APPEND, O_APPEND },\n    { P9_O_NONBLOCK, O_NONBLOCK },\n    { P9_O_DSYNC, O_DSYNC },\n    //    { P9_O_FASYNC, O_FASYNC },\n    //    { P9_O_DIRECT, O_DIRECT },\n    //    { P9_O_LARGEFILE, O_LARGEFILE },\n    //    { P9_O_DIRECTORY, O_DIRECTORY },\n    { P9_O_NOFOLLOW, O_NOFOLLOW },\n    //    { P9_O_NOATIME, O_NOATIME },\n    //    { P9_O_CLOEXEC, O_CLOEXEC },\n    { P9_O_SYNC, O_SYNC },\n};\n\nstatic int p9_flags_to_host(int flags)\n{\n    int ret, i;\n\n    ret = (flags & P9_O_NOACCESS);\n    for(i = 0; i < countof(open_flags); i++) {\n        if (flags & open_flags[i][0])\n            ret |= open_flags[i][1];\n    }\n    return ret;\n}\n\nstatic void stat_to_qid(FSQID *qid, const struct stat *st)\n{\n    if (S_ISDIR(st->st_mode))\n        qid->type = P9_QTDIR;\n    else if (S_ISLNK(st->st_mode))\n        qid->type = P9_QTSYMLINK;\n    else\n        qid->type = P9_QTFILE;\n    qid->version = 0; /* no caching on client */\n    qid->path = st->st_ino;\n}\n\nstatic void fs_statfs(FSDevice *fs1, FSStatFS *st)\n{\n    FSDeviceDisk *fs = (FSDeviceDisk *)fs1;\n    struct statfs st1;\n    statfs(fs->root_path, &st1);\n    st->f_bsize = st1.f_bsize;\n    st->f_blocks = st1.f_blocks;\n    st->f_bfree = st1.f_bfree;\n    st->f_bavail = st1.f_bavail;\n    st->f_files = st1.f_files;\n    st->f_ffree = st1.f_ffree;\n}\n\nstatic char *compose_path(const char *path, const char *name)\n{\n    int path_len, name_len;\n    char *d;\n\n    path_len = strlen(path);\n    name_len = strlen(name);\n    d = malloc(path_len + 1 + name_len + 1);\n    memcpy(d, path, path_len);\n    d[path_len] = '/';\n    memcpy(d + path_len + 1, name, name_len + 1);\n    return d;\n}\n\nstatic int fs_attach(FSDevice *fs1, FSFile **pf,\n                     FSQID *qid, uint32_t uid,\n                     const char *uname, const char *aname)\n{\n    FSDeviceDisk *fs = (FSDeviceDisk *)fs1;\n    struct stat st;\n    FSFile *f;\n    \n    if (lstat(fs->root_path, &st) != 0) {\n        *pf = NULL;\n        return -errno_to_p9(errno);\n    }\n    f = fid_create(fs1, strdup(fs->root_path), uid);\n    stat_to_qid(qid, &st);\n    *pf = f;\n    return 0;\n}\n\nstatic int fs_walk(FSDevice *fs, FSFile **pf, FSQID *qids,\n                   FSFile *f, int n, char **names)\n{\n    char *path, *path1;\n    struct stat st;\n    int i;\n\n    path = strdup(f->path);\n    for(i = 0; i < n; i++) {\n        path1 = compose_path(path, names[i]);\n        if (lstat(path1, &st) != 0) {\n            free(path1);\n            break;\n        }\n        free(path);\n        path = path1;\n        stat_to_qid(&qids[i], &st);\n    }\n    *pf = fid_create(fs, path, f->uid);\n    return i;\n}\n\n\nstatic int fs_mkdir(FSDevice *fs, FSQID *qid, FSFile *f,\n                    const char *name, uint32_t mode, uint32_t gid)\n{\n    char *path;\n    struct stat st;\n    \n    path = compose_path(f->path, name);\n    if (mkdir(path, mode) < 0) {\n        free(path);\n        return -errno_to_p9(errno);\n    }\n    if (lstat(path, &st) != 0) {\n        free(path);\n        return -errno_to_p9(errno);\n    }\n    free(path);\n    stat_to_qid(qid, &st);\n    return 0;\n}\n\nstatic int fs_open(FSDevice *fs, FSQID *qid, FSFile *f, uint32_t flags,\n                   FSOpenCompletionFunc *cb, void *opaque)\n{\n    struct stat st;\n    fs_close(fs, f);\n\n    if (stat(f->path, &st) != 0) \n        return -errno_to_p9(errno);\n    stat_to_qid(qid, &st);\n    \n    if (flags & P9_O_DIRECTORY) {\n        DIR *dirp;\n        dirp = opendir(f->path);\n        if (!dirp)\n            return -errno_to_p9(errno);\n        f->is_opened = TRUE;\n        f->is_dir = TRUE;\n        f->u.dirp = dirp;\n    } else {\n        int fd;\n        fd = open(f->path, p9_flags_to_host(flags) & ~O_CREAT);\n        if (fd < 0)\n            return -errno_to_p9(errno);\n        f->is_opened = TRUE;\n        f->is_dir = FALSE;\n        f->u.fd = fd;\n    }\n    return 0;\n}\n\nstatic int fs_create(FSDevice *fs, FSQID *qid, FSFile *f, const char *name, \n                     uint32_t flags, uint32_t mode, uint32_t gid)\n{\n    struct stat st;\n    char *path;\n    int ret, fd;\n\n    fs_close(fs, f);\n    \n    path = compose_path(f->path, name);\n    fd = open(path, p9_flags_to_host(flags) | O_CREAT, mode);\n    if (fd < 0) {\n        free(path);\n        return -errno_to_p9(errno);\n    }\n    ret = lstat(path, &st);\n    if (ret != 0) {\n        free(path);\n        close(fd);\n        return -errno_to_p9(errno);\n    }\n    free(f->path);\n    f->path = path;\n    f->is_opened = TRUE;\n    f->is_dir = FALSE;\n    f->u.fd = fd;\n    stat_to_qid(qid, &st);\n    return 0;\n}\n\nstatic int fs_readdir(FSDevice *fs, FSFile *f, uint64_t offset,\n                      uint8_t *buf, int count)\n{\n    struct dirent *de;\n    int len, pos, name_len, type, d_type;\n\n    if (!f->is_opened || !f->is_dir)\n        return -P9_EPROTO;\n    if (offset == 0)\n        rewinddir(f->u.dirp);\n    else\n        seekdir(f->u.dirp, offset);\n    pos = 0;\n    for(;;) {\n        de = readdir(f->u.dirp);\n        if (de == NULL)\n            break;\n        name_len = strlen(de->d_name);\n        len = 13 + 8 + 1 + 2 + name_len;\n        if ((pos + len) > count)\n            break;\n        offset = telldir(f->u.dirp);\n        d_type = de->d_type;\n        if (d_type == DT_UNKNOWN) {\n            char *path;\n            struct stat st;\n            path = compose_path(f->path, de->d_name);\n            if (lstat(path, &st) == 0) {\n                d_type = st.st_mode >> 12;\n            } else {\n                d_type = DT_REG; /* default */\n            }\n            free(path);\n        }\n        if (d_type == DT_DIR)\n            type = P9_QTDIR;\n        else if (d_type == DT_LNK)\n            type = P9_QTSYMLINK;\n        else\n            type = P9_QTFILE;\n        buf[pos++] = type;\n        put_le32(buf + pos, 0); /* version */\n        pos += 4;\n        put_le64(buf + pos, de->d_ino);\n        pos += 8;\n        put_le64(buf + pos, offset);\n        pos += 8;\n        buf[pos++] = d_type;\n        put_le16(buf + pos, name_len);\n        pos += 2;\n        memcpy(buf + pos, de->d_name, name_len);\n        pos += name_len;\n    }\n    return pos;\n}\n\nstatic int fs_read(FSDevice *fs, FSFile *f, uint64_t offset,\n                   uint8_t *buf, int count)\n{\n    int ret;\n\n    if (!f->is_opened || f->is_dir)\n        return -P9_EPROTO;\n    ret = pread(f->u.fd, buf, count, offset);\n    if (ret < 0) \n        return -errno_to_p9(errno);\n    else\n        return ret;\n}\n\nstatic int fs_write(FSDevice *fs, FSFile *f, uint64_t offset,\n                    const uint8_t *buf, int count)\n{\n    int ret;\n\n    if (!f->is_opened || f->is_dir)\n        return -P9_EPROTO;\n    ret = pwrite(f->u.fd, buf, count, offset);\n    if (ret < 0) \n        return -errno_to_p9(errno);\n    else\n        return ret;\n}\n\nstatic void fs_close(FSDevice *fs, FSFile *f)\n{\n    if (!f->is_opened)\n        return;\n    if (f->is_dir)\n        closedir(f->u.dirp);\n    else\n        close(f->u.fd);\n    f->is_opened = FALSE;\n}\n\nstatic int fs_stat(FSDevice *fs, FSFile *f, FSStat *st)\n{\n    struct stat st1;\n\n    if (lstat(f->path, &st1) != 0)\n        return -P9_ENOENT;\n    stat_to_qid(&st->qid, &st1);\n    st->st_mode = st1.st_mode;\n    st->st_uid = st1.st_uid;\n    st->st_gid = st1.st_gid;\n    st->st_nlink = st1.st_nlink;\n    st->st_rdev = st1.st_rdev;\n    st->st_size = st1.st_size;\n    st->st_blksize = st1.st_blksize;\n    st->st_blocks = st1.st_blocks;\n    st->st_atime_sec = st1.st_atim.tv_sec;\n    st->st_atime_nsec = st1.st_atim.tv_nsec;\n    st->st_mtime_sec = st1.st_mtim.tv_sec;\n    st->st_mtime_nsec = st1.st_mtim.tv_nsec;\n    st->st_ctime_sec = st1.st_ctim.tv_sec;\n    st->st_ctime_nsec = st1.st_ctim.tv_nsec;\n    return 0;\n}\n\nstatic int fs_setattr(FSDevice *fs, FSFile *f, uint32_t mask,\n                      uint32_t mode, uint32_t uid, uint32_t gid,\n                      uint64_t size, uint64_t atime_sec, uint64_t atime_nsec,\n                      uint64_t mtime_sec, uint64_t mtime_nsec)\n{\n    BOOL ctime_updated = FALSE;\n\n    if (mask & (P9_SETATTR_UID | P9_SETATTR_GID)) {\n        if (lchown(f->path, (mask & P9_SETATTR_UID) ? uid : -1,\n                   (mask & P9_SETATTR_GID) ? gid : -1) < 0)\n            return -errno_to_p9(errno);\n        ctime_updated = TRUE;\n    }\n    /* must be done after uid change for suid */\n    if (mask & P9_SETATTR_MODE) {\n        if (chmod(f->path, mode) < 0)\n            return -errno_to_p9(errno);\n        ctime_updated = TRUE;\n    }\n    if (mask & P9_SETATTR_SIZE) {\n        if (truncate(f->path, size) < 0)\n            return -errno_to_p9(errno);\n        ctime_updated = TRUE;\n    }\n    if (mask & (P9_SETATTR_ATIME | P9_SETATTR_MTIME)) {\n        struct timespec ts[2];\n        if (mask & P9_SETATTR_ATIME) {\n            if (mask & P9_SETATTR_ATIME_SET) {\n                ts[0].tv_sec = atime_sec;\n                ts[0].tv_nsec = atime_nsec;\n            } else {\n                ts[0].tv_sec = 0;\n                ts[0].tv_nsec = UTIME_NOW;\n            }\n        } else {\n            ts[0].tv_sec = 0;\n            ts[0].tv_nsec = UTIME_OMIT;\n        }\n        if (mask & P9_SETATTR_MTIME) {\n            if (mask & P9_SETATTR_MTIME_SET) {\n                ts[1].tv_sec = mtime_sec;\n                ts[1].tv_nsec = mtime_nsec;\n            } else {\n                ts[1].tv_sec = 0;\n                ts[1].tv_nsec = UTIME_NOW;\n            }\n        } else {\n            ts[1].tv_sec = 0;\n            ts[1].tv_nsec = UTIME_OMIT;\n        }\n        if (utimensat(AT_FDCWD, f->path, ts, AT_SYMLINK_NOFOLLOW) < 0)\n            return -errno_to_p9(errno);\n        ctime_updated = TRUE;\n    }\n    if ((mask & P9_SETATTR_CTIME) && !ctime_updated) {\n        if (lchown(f->path, -1, -1) < 0)\n            return -errno_to_p9(errno);\n    }\n    return 0;\n}\n\nstatic int fs_link(FSDevice *fs, FSFile *df, FSFile *f, const char *name)\n{\n    char *path;\n    \n    path = compose_path(df->path, name);\n    if (link(f->path, path) < 0) {\n        free(path);\n        return -errno_to_p9(errno);\n    }\n    free(path);\n    return 0;\n}\n\nstatic int fs_symlink(FSDevice *fs, FSQID *qid,\n                      FSFile *f, const char *name, const char *symgt, uint32_t gid)\n{\n    char *path;\n    struct stat st;\n    \n    path = compose_path(f->path, name);\n    if (symlink(symgt, path) < 0) {\n        free(path);\n        return -errno_to_p9(errno);\n    }\n    if (lstat(path, &st) != 0) {\n        free(path);\n        return -errno_to_p9(errno);\n    }\n    free(path);\n    stat_to_qid(qid, &st);\n    return 0;\n}\n\nstatic int fs_mknod(FSDevice *fs, FSQID *qid,\n             FSFile *f, const char *name, uint32_t mode, uint32_t major,\n             uint32_t minor, uint32_t gid)\n{\n    char *path;\n    struct stat st;\n    \n    path = compose_path(f->path, name);\n    if (mknod(path, mode, makedev(major, minor)) < 0) {\n        free(path);\n        return -errno_to_p9(errno);\n    }\n    if (lstat(path, &st) != 0) {\n        free(path);\n        return -errno_to_p9(errno);\n    }\n    free(path);\n    stat_to_qid(qid, &st);\n    return 0;\n}\n\nstatic int fs_readlink(FSDevice *fs, char *buf, int buf_size, FSFile *f)\n{\n    int ret;\n    ret = readlink(f->path, buf, buf_size - 1);\n    if (ret < 0)\n        return -errno_to_p9(errno);\n    buf[ret] = '\\0';\n    return 0;\n}\n\nstatic int fs_renameat(FSDevice *fs, FSFile *f, const char *name, \n                FSFile *new_f, const char *new_name)\n{\n    char *path, *new_path;\n    int ret;\n\n    path = compose_path(f->path, name);\n    new_path = compose_path(new_f->path, new_name);\n    ret = rename(path, new_path);\n    free(path);\n    free(new_path);\n    if (ret < 0)\n        return -errno_to_p9(errno);\n    return 0;\n}\n\nstatic int fs_unlinkat(FSDevice *fs, FSFile *f, const char *name)\n{\n    char *path;\n    int ret;\n\n    path = compose_path(f->path, name);\n    ret = remove(path);\n    free(path);\n    if (ret < 0)\n        return -errno_to_p9(errno);\n    return 0;\n    \n}\n\nstatic int fs_lock(FSDevice *fs, FSFile *f, const FSLock *lock)\n{\n    int ret;\n    struct flock fl;\n    \n    /* XXX: lock directories too */\n    if (!f->is_opened || f->is_dir)\n        return -P9_EPROTO;\n\n    fl.l_type = lock->type;\n    fl.l_whence = SEEK_SET;\n    fl.l_start = lock->start;\n    fl.l_len = lock->length;\n    \n    ret = fcntl(f->u.fd, F_SETLK, &fl);\n    if (ret == 0) {\n        ret = P9_LOCK_SUCCESS;\n    } else if (errno == EAGAIN || errno == EACCES) {\n        ret = P9_LOCK_BLOCKED;\n    } else {\n        ret = -errno_to_p9(errno);\n    }\n    return ret;\n}\n\nstatic int fs_getlock(FSDevice *fs, FSFile *f, FSLock *lock)\n{\n    int ret;\n    struct flock fl;\n    \n    /* XXX: lock directories too */\n    if (!f->is_opened || f->is_dir)\n        return -P9_EPROTO;\n\n    fl.l_type = lock->type;\n    fl.l_whence = SEEK_SET;\n    fl.l_start = lock->start;\n    fl.l_len = lock->length;\n\n    ret = fcntl(f->u.fd, F_GETLK, &fl);\n    if (ret < 0) {\n        ret = -errno_to_p9(errno);\n    } else {\n        lock->type = fl.l_type;\n        lock->start = fl.l_start;\n        lock->length = fl.l_len;\n    }\n    return ret;\n}\n\nstatic void fs_disk_end(FSDevice *fs1)\n{\n    FSDeviceDisk *fs = (FSDeviceDisk *)fs1;\n    free(fs->root_path);\n}\n\nFSDevice *fs_disk_init(const char *root_path)\n{\n    FSDeviceDisk *fs;\n    struct stat st;\n\n    lstat(root_path, &st);\n    if (!S_ISDIR(st.st_mode))\n        return NULL;\n\n    fs = mallocz(sizeof(*fs));\n\n    fs->common.fs_end = fs_disk_end;\n    fs->common.fs_delete = fs_delete;\n    fs->common.fs_statfs = fs_statfs;\n    fs->common.fs_attach = fs_attach;\n    fs->common.fs_walk = fs_walk;\n    fs->common.fs_mkdir = fs_mkdir;\n    fs->common.fs_open = fs_open;\n    fs->common.fs_create = fs_create;\n    fs->common.fs_stat = fs_stat;\n    fs->common.fs_setattr = fs_setattr;\n    fs->common.fs_close = fs_close;\n    fs->common.fs_readdir = fs_readdir;\n    fs->common.fs_read = fs_read;\n    fs->common.fs_write = fs_write;\n    fs->common.fs_link = fs_link;\n    fs->common.fs_symlink = fs_symlink;\n    fs->common.fs_mknod = fs_mknod;\n    fs->common.fs_readlink = fs_readlink;\n    fs->common.fs_renameat = fs_renameat;\n    fs->common.fs_unlinkat = fs_unlinkat;\n    fs->common.fs_lock = fs_lock;\n    fs->common.fs_getlock = fs_getlock;\n    \n    fs->root_path = strdup(root_path);\n    return (FSDevice *)fs;\n}\n"
  },
  {
    "path": "src/fs_net.c",
    "content": "/*\n * Networked Filesystem using HTTP\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <stdarg.h>\n#include <sys/time.h>\n#include <ctype.h>\n\n#include \"cutils.h\"\n#include \"list.h\"\n#include \"fs.h\"\n#include \"fs_utils.h\"\n#include \"fs_wget.h\"\n#include \"fbuf.h\"\n\n#if defined(EMSCRIPTEN)\n#include <emscripten.h>\n#endif\n\n/*\n  TODO:\n  - implement fs_lock/fs_getlock\n  - update fs_size with links ?\n  - limit fs_size in dirent creation\n  - limit filename length\n*/\n\n//#define DEBUG_CACHE\n#if !defined(EMSCRIPTEN)\n#define DUMP_CACHE_LOAD\n#endif\n\n#if defined(EMSCRIPTEN)\n#define DEFAULT_INODE_CACHE_SIZE (64 * 1024 * 1024)\n#else\n#define DEFAULT_INODE_CACHE_SIZE (256 * 1024 * 1024)\n#endif\n\ntypedef enum {\n    FT_FIFO = 1,\n    FT_CHR = 2,\n    FT_DIR = 4,\n    FT_BLK = 6,\n    FT_REG = 8,\n    FT_LNK = 10,\n    FT_SOCK = 12,\n} FSINodeTypeEnum;\n\ntypedef enum {\n    REG_STATE_LOCAL, /* local content */\n    REG_STATE_UNLOADED, /* content not loaded */\n    REG_STATE_LOADING, /* content is being loaded */\n    REG_STATE_LOADED, /* loaded, not modified, stored in cached_inode_list */\n} FSINodeRegStateEnum;\n\ntypedef struct FSBaseURL {\n    struct list_head link;\n    int ref_count;\n    char *base_url_id;\n    char *url;\n    char *user;\n    char *password;\n    BOOL encrypted;\n    AES_KEY aes_state;\n} FSBaseURL;\n\ntypedef struct FSINode {\n    struct list_head link;\n    uint64_t inode_num; /* inode number */\n    int32_t refcount;\n    int32_t open_count;\n    FSINodeTypeEnum type;\n    uint32_t mode;\n    uint32_t uid;\n    uint32_t gid;\n    uint32_t mtime_sec;\n    uint32_t ctime_sec;\n    uint32_t mtime_nsec;\n    uint32_t ctime_nsec;\n    union {\n        struct {\n            FSINodeRegStateEnum state;\n            size_t size; /* real file size */\n            FileBuffer fbuf;\n            FSBaseURL *base_url;\n            FSFileID file_id; /* network file ID */\n            struct list_head link;\n            struct FSOpenInfo *open_info; /* used in LOADING state */\n            BOOL is_fscmd;\n#ifdef DUMP_CACHE_LOAD\n            char *filename;\n#endif\n        } reg;\n        struct {\n            struct list_head de_list; /* list of FSDirEntry */\n            int size;\n        } dir;\n        struct {\n            uint32_t major;\n            uint32_t minor;\n        } dev;\n        struct {\n            char *name;\n        } symlink;\n    } u;\n} FSINode;\n\ntypedef struct {\n    struct list_head link;\n    FSINode *inode;\n    uint8_t mark; /* temporary use only */\n    char name[0];\n} FSDirEntry;\n\ntypedef enum {\n    FS_CMD_XHR,\n    FS_CMD_PBKDF2,\n} FSCMDRequestEnum;\n\n#define FS_CMD_REPLY_LEN_MAX 64\n\ntypedef struct {\n    FSCMDRequestEnum type;\n    struct CmdXHRState *xhr_state;\n    int reply_len;\n    uint8_t reply_buf[FS_CMD_REPLY_LEN_MAX];\n} FSCMDRequest;\n\nstruct FSFile {\n    uint32_t uid;\n    FSINode *inode;\n    BOOL is_opened;\n    uint32_t open_flags;\n    FSCMDRequest *req;\n};\n\ntypedef struct {\n    struct list_head link;\n    BOOL is_archive;\n    const char *name;\n} PreloadFile;\n\ntypedef struct {\n    struct list_head link;\n    FSFileID file_id;\n    struct list_head file_list; /* list of PreloadFile.link */\n} PreloadEntry;\n\ntypedef struct {\n    struct list_head link;\n    FSFileID file_id;\n    uint64_t size;\n    const char *name;\n} PreloadArchiveFile;\n\ntypedef struct {\n    struct list_head link;\n    const char *name;\n    struct list_head file_list; /* list of PreloadArchiveFile.link */\n} PreloadArchive;\n\ntypedef struct FSDeviceMem {\n    FSDevice common;\n\n    struct list_head inode_list; /* list of FSINode */\n    int64_t inode_count; /* current number of inodes */\n    uint64_t inode_limit;\n    int64_t fs_blocks;\n    uint64_t fs_max_blocks;\n    uint64_t inode_num_alloc;\n    int block_size_log2;\n    uint32_t block_size; /* for stat/statfs */\n    FSINode *root_inode;\n    struct list_head inode_cache_list; /* list of FSINode.u.reg.link */\n    int64_t inode_cache_size;\n    int64_t inode_cache_size_limit;\n    struct list_head preload_list; /* list of PreloadEntry.link */\n    struct list_head preload_archive_list; /* list of PreloadArchive.link */\n    /* network */\n    struct list_head base_url_list; /* list of FSBaseURL.link */\n    char *import_dir;\n#ifdef DUMP_CACHE_LOAD\n    BOOL dump_cache_load;\n    BOOL dump_started;\n    char *dump_preload_dir;\n    FILE *dump_preload_file;\n    FILE *dump_preload_archive_file;\n\n    char *dump_archive_name;\n    uint64_t dump_archive_size;\n    FILE *dump_archive_file;\n\n    int dump_archive_num;\n    struct list_head dump_preload_list; /* list of PreloadFile.link */\n    struct list_head dump_exclude_list; /* list of PreloadFile.link */\n#endif\n} FSDeviceMem;\n\ntypedef enum {\n    FS_OPEN_WGET_REG,\n    FS_OPEN_WGET_ARCHIVE,\n    FS_OPEN_WGET_ARCHIVE_FILE,\n} FSOpenWgetEnum;\n\ntypedef struct FSOpenInfo {\n    FSDevice *fs;\n    FSOpenWgetEnum open_type;\n\n    /* used for FS_OPEN_WGET_REG, FS_OPEN_WGET_ARCHIVE */\n    XHRState *xhr;\n    FSINode *n;\n    DecryptFileState *dec_state;\n    size_t cur_pos;\n\n    struct list_head archive_link; /* FS_OPEN_WGET_ARCHIVE_FILE */\n    uint64_t archive_offset;  /* FS_OPEN_WGET_ARCHIVE_FILE */\n    struct list_head archive_file_list; /* FS_OPEN_WGET_ARCHIVE */\n    \n    /* the following is set in case there is a fs_open callback */\n    FSFile *f;\n    FSOpenCompletionFunc *cb;\n    void *opaque;\n} FSOpenInfo;\n\nstatic void fs_close(FSDevice *fs, FSFile *f);\nstatic void inode_decref(FSDevice *fs1, FSINode *n);\nstatic int fs_cmd_write(FSDevice *fs, FSFile *f, uint64_t offset,\n                        const uint8_t *buf, int buf_len);\nstatic int fs_cmd_read(FSDevice *fs, FSFile *f, uint64_t offset,\n                       uint8_t *buf, int buf_len);\nstatic int fs_truncate(FSDevice *fs1, FSINode *n, uint64_t size);\nstatic void fs_open_end(FSOpenInfo *oi);\nstatic void fs_base_url_decref(FSDevice *fs, FSBaseURL *bu);\nstatic FSBaseURL *fs_net_set_base_url(FSDevice *fs1,\n                                      const char *base_url_id,\n                                      const char *url,\n                                      const char *user, const char *password,\n                                      AES_KEY *aes_state);\nstatic void fs_cmd_close(FSDevice *fs, FSFile *f);\nstatic void fs_error_archive(FSOpenInfo *oi);\n#ifdef DUMP_CACHE_LOAD\nstatic void dump_loaded_file(FSDevice *fs1, FSINode *n);\n#endif\n\n#if !defined(EMSCRIPTEN)\n/* file buffer (the content of the buffer can be stored elsewhere) */\nvoid file_buffer_init(FileBuffer *bs)\n{\n    bs->data = NULL;\n    bs->allocated_size = 0;\n}\n\nvoid file_buffer_reset(FileBuffer *bs)\n{\n    free(bs->data);\n    file_buffer_init(bs);\n}\n\nint file_buffer_resize(FileBuffer *bs, size_t new_size)\n{\n    uint8_t *new_data;\n    new_data = realloc(bs->data, new_size);\n    if (!new_data && new_size != 0)\n        return -1;\n    bs->data = new_data;\n    bs->allocated_size = new_size;\n    return 0;\n}\n\nvoid file_buffer_write(FileBuffer *bs, size_t offset, const uint8_t *buf,\n                       size_t size)\n{\n    memcpy(bs->data + offset, buf, size);\n}\n\nvoid file_buffer_set(FileBuffer *bs, size_t offset, int val, size_t size)\n{\n    memset(bs->data + offset, val, size);\n}\n\nvoid file_buffer_read(FileBuffer *bs, size_t offset, uint8_t *buf,\n                       size_t size)\n{\n    memcpy(buf, bs->data + offset, size);\n}\n#endif\n\nstatic int64_t to_blocks(FSDeviceMem *fs, uint64_t size)\n{\n    return (size + fs->block_size - 1) >> fs->block_size_log2;\n}\n\nstatic FSINode *inode_incref(FSDevice *fs, FSINode *n)\n{\n    n->refcount++;\n    return n;\n}\n\nstatic FSINode *inode_inc_open(FSDevice *fs, FSINode *n)\n{\n    n->open_count++;\n    return n;\n}\n\nstatic void inode_free(FSDevice *fs1, FSINode *n)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n\n    //    printf(\"inode_free=%\" PRId64 \"\\n\", n->inode_num);\n    assert(n->refcount == 0);\n    assert(n->open_count == 0);\n    switch(n->type) {\n    case FT_REG:\n        fs->fs_blocks -= to_blocks(fs, n->u.reg.size);\n        assert(fs->fs_blocks >= 0);\n        file_buffer_reset(&n->u.reg.fbuf);\n#ifdef DUMP_CACHE_LOAD\n        free(n->u.reg.filename);\n#endif\n        switch(n->u.reg.state)  {\n        case REG_STATE_LOADED:\n            list_del(&n->u.reg.link);\n            fs->inode_cache_size -= n->u.reg.size;\n            assert(fs->inode_cache_size >= 0);\n            fs_base_url_decref(fs1, n->u.reg.base_url);\n            break;\n        case REG_STATE_LOADING:\n            {\n                FSOpenInfo *oi = n->u.reg.open_info;\n                if (oi->xhr)\n                    fs_wget_free(oi->xhr);\n                if (oi->open_type == FS_OPEN_WGET_ARCHIVE) {\n                    fs_error_archive(oi);\n                }\n                fs_open_end(oi);\n                fs_base_url_decref(fs1, n->u.reg.base_url);\n            }\n            break;\n        case REG_STATE_UNLOADED:\n            fs_base_url_decref(fs1, n->u.reg.base_url);\n            break;\n        case REG_STATE_LOCAL:\n            break;\n        default:\n            abort();\n        }\n        break;\n    case FT_LNK:\n        free(n->u.symlink.name);\n        break;\n    case FT_DIR:\n        assert(list_empty(&n->u.dir.de_list));\n        break;\n    default:\n        break;\n    }\n    list_del(&n->link);\n    free(n);\n    fs->inode_count--;\n    assert(fs->inode_count >= 0);\n}\n\nstatic void inode_decref(FSDevice *fs1, FSINode *n)\n{\n    assert(n->refcount >= 1);\n    if (--n->refcount <= 0 && n->open_count <= 0) {\n        inode_free(fs1, n);\n    }\n}\n\nstatic void inode_dec_open(FSDevice *fs1, FSINode *n)\n{\n    assert(n->open_count >= 1);\n    if (--n->open_count <= 0 && n->refcount <= 0) {\n        inode_free(fs1, n);\n    }\n}\n\nstatic void inode_update_mtime(FSDevice *fs, FSINode *n)\n{\n    struct timeval tv;\n    gettimeofday(&tv, NULL);\n    n->mtime_sec = tv.tv_sec;\n    n->mtime_nsec = tv.tv_usec * 1000;\n}\n\nstatic FSINode *inode_new(FSDevice *fs1, FSINodeTypeEnum type,\n                          uint32_t mode, uint32_t uid, uint32_t gid)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    FSINode *n;\n\n    n = mallocz(sizeof(*n));\n    n->refcount = 1;\n    n->open_count = 0;\n    n->inode_num = fs->inode_num_alloc;\n    fs->inode_num_alloc++;\n    n->type = type;\n    n->mode = mode & 0xfff;\n    n->uid = uid;\n    n->gid = gid;\n\n    switch(type) {\n    case FT_REG:\n        file_buffer_init(&n->u.reg.fbuf);\n        break;\n    case FT_DIR:\n        init_list_head(&n->u.dir.de_list);\n        break;\n    default:\n        break;\n    }\n\n    list_add(&n->link, &fs->inode_list);\n    fs->inode_count++;\n\n    inode_update_mtime(fs1, n);\n    n->ctime_sec = n->mtime_sec;\n    n->ctime_nsec = n->mtime_nsec;\n\n    return n;\n}\n\n/* warning: the refcount of 'n1' is not incremented by this function */\n/* XXX: test FS max size */\nstatic FSDirEntry *inode_dir_add(FSDevice *fs1, FSINode *n, const char *name,\n                                 FSINode *n1)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    FSDirEntry *de;\n    int name_len, dirent_size, new_size;\n    assert(n->type == FT_DIR);\n\n    name_len = strlen(name);\n    de = mallocz(sizeof(*de) + name_len + 1);\n    de->inode = n1;\n    memcpy(de->name, name, name_len + 1);\n    dirent_size = sizeof(*de) + name_len + 1;\n    new_size = n->u.dir.size + dirent_size;\n    fs->fs_blocks += to_blocks(fs, new_size) - to_blocks(fs, n->u.dir.size);\n    n->u.dir.size = new_size;\n    list_add_tail(&de->link, &n->u.dir.de_list);\n    return de;\n}\n\nstatic FSDirEntry *inode_search(FSINode *n, const char *name)\n{\n    struct list_head *el;\n    FSDirEntry *de;\n    \n    if (n->type != FT_DIR)\n        return NULL;\n\n    list_for_each(el, &n->u.dir.de_list) {\n        de = list_entry(el, FSDirEntry, link);\n        if (!strcmp(de->name, name))\n            return de;\n    }\n    return NULL;\n}\n\nstatic FSINode *inode_search_path1(FSDevice *fs, FSINode *n, const char *path)\n{\n    char name[1024];\n    const char *p, *p1;\n    int len;\n    FSDirEntry *de;\n    \n    p = path;\n    if (*p == '/')\n        p++;\n    if (*p == '\\0')\n        return n;\n    for(;;) {\n        p1 = strchr(p, '/');\n        if (!p1) {\n            len = strlen(p);\n        } else {\n            len = p1 - p;\n            p1++;\n        }\n        if (len > sizeof(name) - 1)\n            return NULL;\n        memcpy(name, p, len);\n        name[len] = '\\0';\n        if (n->type != FT_DIR)\n            return NULL;\n        de = inode_search(n, name);\n        if (!de)\n            return NULL;\n        n = de->inode;\n        p = p1;\n        if (!p)\n            break;\n    }\n    return n;\n}\n\nstatic FSINode *inode_search_path(FSDevice *fs1, const char *path)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    if (!fs1)\n        return NULL;\n    return inode_search_path1(fs1, fs->root_inode, path);\n}\n\nstatic BOOL is_empty_dir(FSDevice *fs, FSINode *n)\n{\n    struct list_head *el;\n    FSDirEntry *de;\n\n    list_for_each(el, &n->u.dir.de_list) {\n        de = list_entry(el, FSDirEntry, link);\n        if (strcmp(de->name, \".\") != 0 &&\n            strcmp(de->name, \"..\") != 0)\n            return FALSE;\n    }\n    return TRUE;\n}\n\nstatic void inode_dirent_delete_no_decref(FSDevice *fs1, FSINode *n, FSDirEntry *de)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    int dirent_size, new_size;\n    dirent_size = sizeof(*de) + strlen(de->name) + 1;\n\n    new_size = n->u.dir.size - dirent_size;\n    fs->fs_blocks += to_blocks(fs, new_size) - to_blocks(fs, n->u.dir.size);\n    n->u.dir.size = new_size;\n    assert(n->u.dir.size >= 0);\n    assert(fs->fs_blocks >= 0);\n    list_del(&de->link);\n    free(de);\n}\n\nstatic void inode_dirent_delete(FSDevice *fs, FSINode *n, FSDirEntry *de)\n{\n    FSINode *n1;\n    n1 = de->inode;\n    inode_dirent_delete_no_decref(fs, n, de);\n    inode_decref(fs, n1);\n}\n\nstatic void flush_dir(FSDevice *fs, FSINode *n)\n{\n    struct list_head *el, *el1;\n    FSDirEntry *de;\n    list_for_each_safe(el, el1, &n->u.dir.de_list) {\n        de = list_entry(el, FSDirEntry, link);\n        inode_dirent_delete(fs, n, de);\n    }\n    assert(n->u.dir.size == 0);\n}\n\nstatic void fs_delete(FSDevice *fs, FSFile *f)\n{\n    fs_close(fs, f);\n    inode_dec_open(fs, f->inode);\n    free(f);\n}\n\nstatic FSFile *fid_create(FSDevice *fs1, FSINode *n, uint32_t uid)\n{\n    FSFile *f;\n\n    f = mallocz(sizeof(*f));\n    f->inode = inode_inc_open(fs1, n);\n    f->uid = uid;\n    return f;\n}\n\nstatic void inode_to_qid(FSQID *qid, FSINode *n)\n{\n    if (n->type == FT_DIR)\n        qid->type = P9_QTDIR;\n    else if (n->type == FT_LNK)\n        qid->type = P9_QTSYMLINK;\n    else\n        qid->type = P9_QTFILE;\n    qid->version = 0; /* no caching on client */\n    qid->path = n->inode_num;\n}\n\nstatic void fs_statfs(FSDevice *fs1, FSStatFS *st)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    st->f_bsize = 1024;\n    st->f_blocks = fs->fs_max_blocks <<\n        (fs->block_size_log2 - 10);\n    st->f_bfree = (fs->fs_max_blocks - fs->fs_blocks) <<\n        (fs->block_size_log2 - 10);\n    st->f_bavail = st->f_bfree;\n    st->f_files = fs->inode_limit;\n    st->f_ffree = fs->inode_limit - fs->inode_count;\n}\n\nstatic int fs_attach(FSDevice *fs1, FSFile **pf, FSQID *qid, uint32_t uid,\n                     const char *uname, const char *aname)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n\n    *pf = fid_create(fs1, fs->root_inode, uid);\n    inode_to_qid(qid, fs->root_inode);\n    return 0;\n}\n\nstatic int fs_walk(FSDevice *fs, FSFile **pf, FSQID *qids,\n                   FSFile *f, int count, char **names)\n{\n    int i;\n    FSINode *n;\n    FSDirEntry *de;\n\n    n = f->inode;\n    for(i = 0; i < count; i++) {\n        de = inode_search(n, names[i]);\n        if (!de)\n            break;\n        n = de->inode;\n        inode_to_qid(&qids[i], n);\n    }\n    *pf = fid_create(fs, n, f->uid);\n    return i;\n}\n\nstatic int fs_mkdir(FSDevice *fs, FSQID *qid, FSFile *f,\n                    const char *name, uint32_t mode, uint32_t gid)\n{\n    FSINode *n, *n1;\n\n    n = f->inode;\n    if (n->type != FT_DIR)\n        return -P9_ENOTDIR;\n    if (inode_search(n, name))\n        return -P9_EEXIST;\n    n1 = inode_new(fs, FT_DIR, mode, f->uid, gid);\n    inode_dir_add(fs, n1, \".\", inode_incref(fs, n1));\n    inode_dir_add(fs, n1, \"..\", inode_incref(fs, n));\n    inode_dir_add(fs, n, name, n1);\n    inode_to_qid(qid, n1);\n    return 0;\n}\n\n/* remove elements in the cache considering that 'added_size' will be\n   added */\nstatic void fs_trim_cache(FSDevice *fs1, int64_t added_size)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    struct list_head *el, *el1;\n    FSINode *n;\n\n    if ((fs->inode_cache_size + added_size) <= fs->inode_cache_size_limit)\n        return;\n    list_for_each_prev_safe(el, el1, &fs->inode_cache_list) {\n        n = list_entry(el, FSINode, u.reg.link);\n        assert(n->u.reg.state == REG_STATE_LOADED);\n        /* cannot remove open files */\n        //        printf(\"open_count=%d\\n\", n->open_count);\n        if (n->open_count != 0)\n            continue;\n#ifdef DEBUG_CACHE\n        printf(\"fs_trim_cache: remove '%s' size=%ld\\n\",\n               n->u.reg.filename, (long)n->u.reg.size);\n#endif\n        file_buffer_reset(&n->u.reg.fbuf);\n        n->u.reg.state = REG_STATE_UNLOADED;\n        list_del(&n->u.reg.link);\n        fs->inode_cache_size -= n->u.reg.size;\n        assert(fs->inode_cache_size >= 0);\n        if ((fs->inode_cache_size + added_size) <= fs->inode_cache_size_limit)\n            break;\n    }\n}\n\nstatic void fs_open_end(FSOpenInfo *oi)\n{\n    if (oi->open_type == FS_OPEN_WGET_ARCHIVE_FILE) {\n        list_del(&oi->archive_link);\n    }\n    if (oi->dec_state)\n        decrypt_file_end(oi->dec_state);\n    free(oi);\n}\n\nstatic int fs_open_write_cb(void *opaque, const uint8_t *data, size_t size)\n{\n    FSOpenInfo *oi = opaque;\n    size_t len;\n    FSINode *n = oi->n;\n    \n    /* we ignore extraneous data */\n    len = n->u.reg.size - oi->cur_pos;\n    if (size < len)\n        len = size;\n    file_buffer_write(&n->u.reg.fbuf, oi->cur_pos, data, len);\n    oi->cur_pos += len;\n    return 0;\n}\n\nstatic void fs_wget_set_loaded(FSINode *n)\n{\n    FSOpenInfo *oi;\n    FSDeviceMem *fs;\n    FSFile *f;\n    FSQID qid;\n\n    assert(n->u.reg.state == REG_STATE_LOADING);\n    oi = n->u.reg.open_info;\n    fs = (FSDeviceMem *)oi->fs;\n    n->u.reg.state = REG_STATE_LOADED;\n    list_add(&n->u.reg.link, &fs->inode_cache_list);\n    fs->inode_cache_size += n->u.reg.size;\n    \n    if (oi->cb) {\n        f = oi->f;\n        f->is_opened = TRUE;\n        inode_to_qid(&qid, n);\n        oi->cb(oi->fs, &qid, 0, oi->opaque);\n    }\n    fs_open_end(oi);\n}\n\nstatic void fs_wget_set_error(FSINode *n)\n{\n    FSOpenInfo *oi;\n    assert(n->u.reg.state == REG_STATE_LOADING);\n    oi = n->u.reg.open_info;\n    n->u.reg.state = REG_STATE_UNLOADED;\n    file_buffer_reset(&n->u.reg.fbuf);\n    if (oi->cb) {\n        oi->cb(oi->fs, NULL, -P9_EIO, oi->opaque);\n    }\n    fs_open_end(oi);\n}\n\nstatic void fs_read_archive(FSOpenInfo *oi)\n{\n    FSINode *n = oi->n;\n    uint64_t pos, pos1, l;\n    uint8_t buf[1024];\n    FSINode *n1;\n    FSOpenInfo *oi1;\n    struct list_head *el, *el1;\n    \n    list_for_each_safe(el, el1, &oi->archive_file_list) {\n        oi1 = list_entry(el, FSOpenInfo, archive_link);\n        n1 = oi1->n;\n        /* copy the archive data to the file */\n        pos = oi1->archive_offset;\n        pos1 = 0;\n        while (pos1 < n1->u.reg.size) {\n            l = n1->u.reg.size - pos1;\n            if (l > sizeof(buf))\n                l = sizeof(buf);\n            file_buffer_read(&n->u.reg.fbuf, pos, buf, l);\n            file_buffer_write(&n1->u.reg.fbuf, pos1, buf, l);\n            pos += l;\n            pos1 += l;\n        }\n        fs_wget_set_loaded(n1);\n    }\n}\n\nstatic void fs_error_archive(FSOpenInfo *oi)\n{\n    FSOpenInfo *oi1;\n    struct list_head *el, *el1;\n    \n    list_for_each_safe(el, el1, &oi->archive_file_list) {\n        oi1 = list_entry(el, FSOpenInfo, archive_link);\n        fs_wget_set_error(oi1->n);\n    }\n}\n\nstatic void fs_open_cb(void *opaque, int err, void *data, size_t size)\n{\n    FSOpenInfo *oi = opaque;\n    FSINode *n = oi->n;\n    \n    //    printf(\"open_cb: err=%d size=%ld\\n\", err, size);\n    if (err < 0) {\n    error:\n        if (oi->open_type == FS_OPEN_WGET_ARCHIVE)\n            fs_error_archive(oi);\n        fs_wget_set_error(n);\n    } else {\n        if (oi->dec_state) {\n            if (decrypt_file(oi->dec_state, data, size) < 0)\n                goto error;\n            if (err == 0) {\n                if (decrypt_file_flush(oi->dec_state) < 0)\n                    goto error;\n            }\n        } else {\n            fs_open_write_cb(oi, data, size);\n        }\n\n        if (err == 0) {\n            /* end of transfer */\n            if (oi->cur_pos != n->u.reg.size)\n                goto error;\n#ifdef DUMP_CACHE_LOAD\n            dump_loaded_file(oi->fs, n);\n#endif\n            if (oi->open_type == FS_OPEN_WGET_ARCHIVE)\n                fs_read_archive(oi);\n            fs_wget_set_loaded(n);\n        }\n    }\n}\n\n\nstatic int fs_open_wget(FSDevice *fs1, FSINode *n, FSOpenWgetEnum open_type)\n{\n    char *url;\n    FSOpenInfo *oi;\n    char fname[FILEID_SIZE_MAX];\n    FSBaseURL *bu;\n\n    assert(n->u.reg.state == REG_STATE_UNLOADED);\n    \n    fs_trim_cache(fs1, n->u.reg.size);\n    \n    if (file_buffer_resize(&n->u.reg.fbuf, n->u.reg.size) < 0)\n        return -P9_EIO;\n    n->u.reg.state = REG_STATE_LOADING;\n    oi = mallocz(sizeof(*oi));\n    oi->cur_pos = 0;\n    oi->fs = fs1;\n    oi->n = n;\n    oi->open_type = open_type;\n    if (open_type != FS_OPEN_WGET_ARCHIVE_FILE) {\n        if (open_type == FS_OPEN_WGET_ARCHIVE)\n            init_list_head(&oi->archive_file_list);\n        file_id_to_filename(fname, n->u.reg.file_id);\n        bu = n->u.reg.base_url;\n        url = compose_path(bu->url, fname);\n        if (bu->encrypted) {\n            oi->dec_state = decrypt_file_init(&bu->aes_state, fs_open_write_cb, oi);\n        }\n        oi->xhr = fs_wget(url, bu->user, bu->password, oi, fs_open_cb, FALSE);\n    }\n    n->u.reg.open_info = oi;\n    return 0;\n}\n\n\nstatic void fs_preload_file(FSDevice *fs1, const char *filename)\n{\n    FSINode *n;\n\n    n = inode_search_path(fs1, filename);\n    if (n && n->type == FT_REG && n->u.reg.state == REG_STATE_UNLOADED) {\n#if defined(DEBUG_CACHE)\n        printf(\"preload: %s\\n\", filename);\n#endif\n        fs_open_wget(fs1, n, FS_OPEN_WGET_REG);\n    }\n}\n\nstatic PreloadArchive *find_preload_archive(FSDeviceMem *fs,\n                                            const char *filename)\n{\n    PreloadArchive *pa;\n    struct list_head *el;\n    list_for_each(el, &fs->preload_archive_list) {\n        pa = list_entry(el, PreloadArchive, link);\n        if (!strcmp(pa->name, filename))\n            return pa;\n    }\n    return NULL;\n}\n\nstatic void fs_preload_archive(FSDevice *fs1, const char *filename)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    PreloadArchive *pa;\n    PreloadArchiveFile *paf;\n    struct list_head *el;\n    FSINode *n, *n1;\n    uint64_t offset;\n    BOOL has_unloaded;\n    \n    pa = find_preload_archive(fs, filename);\n    if (!pa)\n        return;\n#if defined(DEBUG_CACHE)\n    printf(\"preload archive: %s\\n\", filename);\n#endif\n    n = inode_search_path(fs1, filename);\n    if (n && n->type == FT_REG && n->u.reg.state == REG_STATE_UNLOADED) {\n        /* if all the files are loaded, no need to load the archive */\n        offset = 0;\n        has_unloaded = FALSE;\n        list_for_each(el, &pa->file_list) {\n            paf = list_entry(el, PreloadArchiveFile, link);\n            n1 = inode_search_path(fs1, paf->name);\n            if (n1 && n1->type == FT_REG &&\n                n1->u.reg.state == REG_STATE_UNLOADED) {\n                has_unloaded = TRUE;\n            }\n            offset += paf->size;\n        }\n        if (!has_unloaded) {\n#if defined(DEBUG_CACHE)\n            printf(\"archive files already loaded\\n\");\n#endif\n            return;\n        }\n        /* check archive size consistency */\n        if (offset != n->u.reg.size) {\n#if defined(DEBUG_CACHE)\n            printf(\"  inconsistent archive size: %\" PRId64 \" %\" PRId64 \"\\n\",\n                   offset, n->u.reg.size);\n#endif\n            goto load_fallback;\n        }\n\n        /* start loading the archive */\n        fs_open_wget(fs1, n, FS_OPEN_WGET_ARCHIVE);\n        \n        /* indicate that all the archive files are being loaded. Also\n           check consistency of size and file id */\n        offset = 0;\n        list_for_each(el, &pa->file_list) {\n            paf = list_entry(el, PreloadArchiveFile, link);\n            n1 = inode_search_path(fs1, paf->name);\n            if (n1 && n1->type == FT_REG &&\n                n1->u.reg.state == REG_STATE_UNLOADED) {\n                if (n1->u.reg.size == paf->size &&\n                    n1->u.reg.file_id == paf->file_id) {\n                    fs_open_wget(fs1, n1, FS_OPEN_WGET_ARCHIVE_FILE);\n                    list_add_tail(&n1->u.reg.open_info->archive_link,\n                                  &n->u.reg.open_info->archive_file_list);\n                    n1->u.reg.open_info->archive_offset = offset;\n                } else {\n#if defined(DEBUG_CACHE)\n                    printf(\" inconsistent archive file: %s\\n\", paf->name);\n#endif\n                    /* fallback to file preload */\n                    fs_preload_file(fs1, paf->name);\n                }\n            }\n            offset += paf->size;\n        }\n    } else {\n    load_fallback:\n        /* if the archive is already loaded or not loaded, we load the\n           files separately (XXX: not optimal if the archive is\n           already loaded, but it should not happen often) */\n        list_for_each(el, &pa->file_list) {\n            paf = list_entry(el, PreloadArchiveFile, link);\n            fs_preload_file(fs1, paf->name);\n        }\n    }\n}\n\nstatic void fs_preload_files(FSDevice *fs1, FSFileID file_id)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    struct list_head *el;\n    PreloadEntry *pe;\n    PreloadFile *pf;\n    \n    list_for_each(el, &fs->preload_list) {\n        pe = list_entry(el, PreloadEntry, link);\n        if (pe->file_id == file_id)\n            goto found;\n    }\n    return;\n found:\n    list_for_each(el, &pe->file_list) {\n        pf = list_entry(el, PreloadFile, link);\n        if (pf->is_archive)\n            fs_preload_archive(fs1, pf->name);\n        else\n            fs_preload_file(fs1, pf->name);\n    }\n}\n\n/* return < 0 if error, 0 if OK, 1 if asynchronous completion */\n/* XXX: we don't support several simultaneous asynchronous open on the\n   same inode */\nstatic int fs_open(FSDevice *fs1, FSQID *qid, FSFile *f, uint32_t flags,\n                   FSOpenCompletionFunc *cb, void *opaque)\n{\n    FSINode *n = f->inode;\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    int ret;\n    \n    fs_close(fs1, f);\n\n    if (flags & P9_O_DIRECTORY) {\n        if (n->type != FT_DIR)\n            return -P9_ENOTDIR;\n    } else {\n        if (n->type != FT_REG && n->type != FT_DIR)\n        return -P9_EINVAL; /* XXX */\n    }\n    f->open_flags = flags;\n    if (n->type == FT_REG) {\n        if ((flags & P9_O_TRUNC) && (flags & P9_O_NOACCESS) != P9_O_RDONLY) {\n            fs_truncate(fs1, n, 0);\n        }\n\n        switch(n->u.reg.state) {\n        case REG_STATE_UNLOADED:\n            {\n                FSOpenInfo *oi;\n                /* need to load the file */\n                fs_preload_files(fs1, n->u.reg.file_id);\n                /* The state can be modified by the fs_preload_files */\n                if (n->u.reg.state == REG_STATE_LOADING)\n                    goto handle_loading;\n                ret = fs_open_wget(fs1, n, FS_OPEN_WGET_REG);\n                if (ret)\n                    return ret;\n                oi = n->u.reg.open_info;\n                oi->f = f;\n                oi->cb = cb;\n                oi->opaque = opaque;\n                return 1; /* completion callback will be called later */\n            }\n            break;\n        case REG_STATE_LOADING:\n        handle_loading:\n            {\n                FSOpenInfo *oi;\n                /* we only handle the case where the file is being preloaded */\n                oi = n->u.reg.open_info;\n                if (oi->cb)\n                    return -P9_EIO;\n                oi = n->u.reg.open_info;\n                oi->f = f;\n                oi->cb = cb;\n                oi->opaque = opaque;\n                return 1; /* completion callback will be called later */\n            }\n            break;\n        case REG_STATE_LOCAL:\n            goto do_open;\n        case REG_STATE_LOADED:\n            /* move to front */\n            list_del(&n->u.reg.link);\n            list_add(&n->u.reg.link, &fs->inode_cache_list);\n            goto do_open;\n        default:\n            abort();\n        }\n    } else {\n    do_open:\n        f->is_opened = TRUE;\n        inode_to_qid(qid, n);\n        return 0;\n    }\n}\n\nstatic int fs_create(FSDevice *fs, FSQID *qid, FSFile *f, const char *name, \n                     uint32_t flags, uint32_t mode, uint32_t gid)\n{\n    FSINode *n1, *n = f->inode;\n    \n    if (n->type != FT_DIR)\n        return -P9_ENOTDIR;\n    if (inode_search(n, name)) {\n        /* XXX: support it, but Linux does not seem to use this case */\n        return -P9_EEXIST;\n    } else {\n        fs_close(fs, f);\n        \n        n1 = inode_new(fs, FT_REG, mode, f->uid, gid);\n        inode_dir_add(fs, n, name, n1);\n        \n        inode_dec_open(fs, f->inode);\n        f->inode = inode_inc_open(fs, n1);\n        f->is_opened = TRUE;\n        f->open_flags = flags;\n        inode_to_qid(qid, n1);\n        return 0;\n    }\n}\n\nstatic int fs_readdir(FSDevice *fs, FSFile *f, uint64_t offset1,\n                      uint8_t *buf, int count)\n{\n    FSINode *n1, *n = f->inode;\n    int len, pos, name_len, type;\n    struct list_head *el;\n    FSDirEntry *de;\n    uint64_t offset;\n\n    if (!f->is_opened || n->type != FT_DIR)\n        return -P9_EPROTO;\n    \n    el = n->u.dir.de_list.next;\n    offset = 0;\n    while (offset < offset1) {\n        if (el == &n->u.dir.de_list)\n            return 0; /* no more entries */\n        offset++;\n        el = el->next;\n    }\n    \n    pos = 0;\n    for(;;) {\n        if (el == &n->u.dir.de_list)\n            break;\n        de = list_entry(el, FSDirEntry, link);\n        name_len = strlen(de->name);\n        len = 13 + 8 + 1 + 2 + name_len;\n        if ((pos + len) > count)\n            break;\n        offset++;\n        n1 = de->inode;\n        if (n1->type == FT_DIR)\n            type = P9_QTDIR;\n        else if (n1->type == FT_LNK)\n            type = P9_QTSYMLINK;\n        else\n            type = P9_QTFILE;\n        buf[pos++] = type;\n        put_le32(buf + pos, 0); /* version */\n        pos += 4;\n        put_le64(buf + pos, n1->inode_num);\n        pos += 8;\n        put_le64(buf + pos, offset);\n        pos += 8;\n        buf[pos++] = n1->type;\n        put_le16(buf + pos, name_len);\n        pos += 2;\n        memcpy(buf + pos, de->name, name_len);\n        pos += name_len;\n        el = el->next;\n    }\n    return pos;\n}\n\nstatic int fs_read(FSDevice *fs, FSFile *f, uint64_t offset,\n                   uint8_t *buf, int count)\n{\n    FSINode *n = f->inode;\n    uint64_t count1;\n\n    if (!f->is_opened)\n        return -P9_EPROTO;\n    if (n->type != FT_REG)\n        return -P9_EIO;\n    if ((f->open_flags & P9_O_NOACCESS) == P9_O_WRONLY)\n        return -P9_EIO;\n    if (n->u.reg.is_fscmd)\n        return fs_cmd_read(fs, f, offset, buf, count);\n    if (offset >= n->u.reg.size)\n        return 0;\n    count1 = n->u.reg.size - offset;\n    if (count1 < count)\n        count = count1;\n    file_buffer_read(&n->u.reg.fbuf, offset, buf, count);\n    return count;\n}\n\nstatic int fs_truncate(FSDevice *fs1, FSINode *n, uint64_t size)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    intptr_t diff, diff_blocks;\n    size_t new_allocated_size;\n    \n    if (n->type != FT_REG)\n        return -P9_EINVAL;\n    if (size > UINTPTR_MAX)\n        return -P9_ENOSPC;\n    diff = size - n->u.reg.size;\n    if (diff == 0)\n        return 0;\n    diff_blocks = to_blocks(fs, size) - to_blocks(fs, n->u.reg.size);\n    /* currently cannot resize while loading */\n    switch(n->u.reg.state) {\n    case REG_STATE_LOADING:\n        return -P9_EIO;\n    case REG_STATE_UNLOADED:\n        if (size == 0) {\n            /* now local content */\n            n->u.reg.state = REG_STATE_LOCAL;\n        }\n        break;\n    case REG_STATE_LOADED:\n    case REG_STATE_LOCAL:\n        if (diff > 0) {\n            if ((fs->fs_blocks + diff_blocks) > fs->fs_max_blocks)\n                return -P9_ENOSPC;\n            if (size > n->u.reg.fbuf.allocated_size) {\n                new_allocated_size = n->u.reg.fbuf.allocated_size * 5 / 4;\n                if (size > new_allocated_size)\n                    new_allocated_size = size;\n                if (file_buffer_resize(&n->u.reg.fbuf, new_allocated_size) < 0)\n                    return -P9_ENOSPC;\n            }\n            file_buffer_set(&n->u.reg.fbuf, n->u.reg.size, 0, diff);\n        } else {\n            new_allocated_size = n->u.reg.fbuf.allocated_size * 4 / 5;\n            if (size <= new_allocated_size) {\n                if (file_buffer_resize(&n->u.reg.fbuf, new_allocated_size) < 0)\n                    return -P9_ENOSPC;\n            }\n        }\n        /* file is modified, so it is now local */\n        if (n->u.reg.state == REG_STATE_LOADED) {\n            list_del(&n->u.reg.link);\n            fs->inode_cache_size -= n->u.reg.size;\n            assert(fs->inode_cache_size >= 0);\n            n->u.reg.state = REG_STATE_LOCAL;\n        }\n        break;\n    default:\n        abort();\n    }\n    fs->fs_blocks += diff_blocks;\n    assert(fs->fs_blocks >= 0);\n    n->u.reg.size = size;\n    return 0;\n}\n\nstatic int fs_write(FSDevice *fs1, FSFile *f, uint64_t offset,\n                    const uint8_t *buf, int count)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    FSINode *n = f->inode;\n    uint64_t end;\n    int err;\n    \n    if (!f->is_opened)\n        return -P9_EPROTO;\n    if (n->type != FT_REG)\n        return -P9_EIO;\n    if ((f->open_flags & P9_O_NOACCESS) == P9_O_RDONLY)\n        return -P9_EIO;\n    if (count == 0)\n        return 0;\n    if (n->u.reg.is_fscmd) {\n        return fs_cmd_write(fs1, f, offset, buf, count);\n    }\n    end = offset + count;\n    if (end > n->u.reg.size) {\n        err = fs_truncate(fs1, n, end);\n        if (err)\n            return err;\n    }\n    inode_update_mtime(fs1, n);\n    /* file is modified, so it is now local */\n    if (n->u.reg.state == REG_STATE_LOADED) {\n        list_del(&n->u.reg.link);\n        fs->inode_cache_size -= n->u.reg.size;\n        assert(fs->inode_cache_size >= 0);\n        n->u.reg.state = REG_STATE_LOCAL;\n    }\n    file_buffer_write(&n->u.reg.fbuf, offset, buf, count);\n    return count;\n}\n\nstatic void fs_close(FSDevice *fs, FSFile *f)\n{\n    if (f->is_opened) {\n        f->is_opened = FALSE;\n    }\n    if (f->req)\n        fs_cmd_close(fs, f);\n}\n\nstatic int fs_stat(FSDevice *fs1, FSFile *f, FSStat *st)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    FSINode *n = f->inode;\n\n    inode_to_qid(&st->qid, n);\n    st->st_mode = n->mode | (n->type << 12);\n    st->st_uid = n->uid;\n    st->st_gid = n->gid;\n    st->st_nlink = n->refcount;\n    if (n->type == FT_BLK || n->type == FT_CHR) {\n        /* XXX: check */\n        st->st_rdev = (n->u.dev.major << 8) | n->u.dev.minor;\n    } else {\n        st->st_rdev = 0;\n    }\n    st->st_blksize = fs->block_size;\n    if (n->type == FT_REG) {\n        st->st_size = n->u.reg.size;\n    } else if (n->type == FT_LNK) {\n        st->st_size = strlen(n->u.symlink.name);\n    } else if (n->type == FT_DIR) {\n        st->st_size = n->u.dir.size;\n    } else {\n        st->st_size = 0;\n    }\n    /* in 512 byte blocks */\n    st->st_blocks = to_blocks(fs, st->st_size) << (fs->block_size_log2 - 9);\n    \n    /* Note: atime is not supported */\n    st->st_atime_sec = n->mtime_sec;\n    st->st_atime_nsec = n->mtime_nsec;\n    st->st_mtime_sec = n->mtime_sec;\n    st->st_mtime_nsec = n->mtime_nsec;\n    st->st_ctime_sec = n->ctime_sec;\n    st->st_ctime_nsec = n->ctime_nsec;\n    return 0;\n}\n\nstatic int fs_setattr(FSDevice *fs1, FSFile *f, uint32_t mask,\n                      uint32_t mode, uint32_t uid, uint32_t gid,\n                      uint64_t size, uint64_t atime_sec, uint64_t atime_nsec,\n                      uint64_t mtime_sec, uint64_t mtime_nsec)\n{\n    FSINode *n = f->inode;\n    int ret;\n    \n    if (mask & P9_SETATTR_MODE) {\n        n->mode = mode;\n    }\n    if (mask & P9_SETATTR_UID) {\n        n->uid = uid;\n    }\n    if (mask & P9_SETATTR_GID) {\n        n->gid = gid;\n    }\n    if (mask & P9_SETATTR_SIZE) {\n        ret = fs_truncate(fs1, n, size);\n        if (ret)\n            return ret;\n    }\n    if (mask & P9_SETATTR_MTIME) {\n        if (mask & P9_SETATTR_MTIME_SET) {\n            n->mtime_sec = mtime_sec;\n            n->mtime_nsec = mtime_nsec;\n        } else {\n            inode_update_mtime(fs1, n);\n        }\n    }\n    if (mask & P9_SETATTR_CTIME) {\n        struct timeval tv;\n        gettimeofday(&tv, NULL);\n        n->ctime_sec = tv.tv_sec;\n        n->ctime_nsec = tv.tv_usec * 1000;\n    }\n    return 0;\n}\n\nstatic int fs_link(FSDevice *fs, FSFile *df, FSFile *f, const char *name)\n{\n    FSINode *n = df->inode;\n    \n    if (f->inode->type == FT_DIR)\n        return -P9_EPERM;\n    if (inode_search(n, name))\n        return -P9_EEXIST;\n    inode_dir_add(fs, n, name, inode_incref(fs, f->inode));\n    return 0;\n}\n\nstatic int fs_symlink(FSDevice *fs, FSQID *qid,\n                      FSFile *f, const char *name, const char *symgt, uint32_t gid)\n{\n    FSINode *n1, *n = f->inode;\n    \n    if (inode_search(n, name))\n        return -P9_EEXIST;\n\n    n1 = inode_new(fs, FT_LNK, 0777, f->uid, gid);\n    n1->u.symlink.name = strdup(symgt);\n    inode_dir_add(fs, n, name, n1);\n    inode_to_qid(qid, n1);\n    return 0;\n}\n\nstatic int fs_mknod(FSDevice *fs, FSQID *qid,\n             FSFile *f, const char *name, uint32_t mode, uint32_t major,\n             uint32_t minor, uint32_t gid)\n{\n    int type;\n    FSINode *n1, *n = f->inode;\n\n    type = (mode & P9_S_IFMT) >> 12;\n    /* XXX: add FT_DIR support */\n    if (type != FT_FIFO && type != FT_CHR && type != FT_BLK &&\n        type != FT_REG && type != FT_SOCK)\n        return -P9_EINVAL;\n    if (inode_search(n, name))\n        return -P9_EEXIST;\n    n1 = inode_new(fs, type, mode, f->uid, gid);\n    if (type == FT_CHR || type == FT_BLK) {\n        n1->u.dev.major = major;\n        n1->u.dev.minor = minor;\n    }\n    inode_dir_add(fs, n, name, n1);\n    inode_to_qid(qid, n1);\n    return 0;\n}\n\nstatic int fs_readlink(FSDevice *fs, char *buf, int buf_size, FSFile *f)\n{\n    FSINode *n = f->inode;\n    int len;\n    if (n->type != FT_LNK)\n        return -P9_EIO;\n    len = min_int(strlen(n->u.symlink.name), buf_size - 1);\n    memcpy(buf, n->u.symlink.name, len);\n    buf[len] = '\\0';\n    return 0;\n}\n\nstatic int fs_renameat(FSDevice *fs, FSFile *f, const char *name, \n                       FSFile *new_f, const char *new_name)\n{\n    FSDirEntry *de, *de1;\n    FSINode *n1;\n    \n    de = inode_search(f->inode, name);\n    if (!de)\n        return -P9_ENOENT;\n    de1 = inode_search(new_f->inode, new_name);\n    n1 = NULL;\n    if (de1) {\n        n1 = de1->inode;\n        if (n1->type == FT_DIR)\n            return -P9_EEXIST; /* XXX: handle the case */\n        inode_dirent_delete_no_decref(fs, new_f->inode, de1);\n    }\n    inode_dir_add(fs, new_f->inode, new_name, inode_incref(fs, de->inode));\n    inode_dirent_delete(fs, f->inode, de);\n    if (n1)\n        inode_decref(fs, n1);\n    return 0;\n}\n\nstatic int fs_unlinkat(FSDevice *fs, FSFile *f, const char *name)\n{\n    FSDirEntry *de;\n    FSINode *n;\n\n    if (!strcmp(name, \".\") || !strcmp(name, \"..\"))\n        return -P9_ENOENT;\n    de = inode_search(f->inode, name);\n    if (!de)\n        return -P9_ENOENT;\n    n = de->inode;\n    if (n->type == FT_DIR) {\n        if (!is_empty_dir(fs, n))\n            return -P9_ENOTEMPTY;\n        flush_dir(fs, n);\n    }\n    inode_dirent_delete(fs, f->inode, de);\n    return 0;\n}\n\nstatic int fs_lock(FSDevice *fs, FSFile *f, const FSLock *lock)\n{\n    FSINode *n = f->inode;\n    if (!f->is_opened)\n        return -P9_EPROTO;\n    if (n->type != FT_REG)\n        return -P9_EIO;\n    /* XXX: implement it */\n    return P9_LOCK_SUCCESS;\n}\n\nstatic int fs_getlock(FSDevice *fs, FSFile *f, FSLock *lock)\n{\n    FSINode *n = f->inode;\n    if (!f->is_opened)\n        return -P9_EPROTO;\n    if (n->type != FT_REG)\n        return -P9_EIO;\n    /* XXX: implement it */\n    return 0;\n}\n\n/* XXX: only used with file lists, so not all the data is released */\nstatic void fs_mem_end(FSDevice *fs1)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    struct list_head *el, *el1, *el2, *el3;\n    FSINode *n;\n    FSDirEntry *de;\n\n    list_for_each_safe(el, el1, &fs->inode_list) {\n        n = list_entry(el, FSINode, link);\n        n->refcount = 0;\n        if (n->type == FT_DIR) {\n            list_for_each_safe(el2, el3, &n->u.dir.de_list) {\n                de = list_entry(el2, FSDirEntry, link);\n                list_del(&de->link);\n                free(de);\n            }\n            init_list_head(&n->u.dir.de_list);\n        }\n        inode_free(fs1, n);\n    }\n    assert(list_empty(&fs->inode_cache_list));\n    free(fs->import_dir);\n}\n\nFSDevice *fs_mem_init(void)\n{\n    FSDeviceMem *fs;\n    FSDevice *fs1;\n    FSINode *n;\n\n    fs = mallocz(sizeof(*fs));\n    fs1 = &fs->common;\n\n    fs->common.fs_end = fs_mem_end;\n    fs->common.fs_delete = fs_delete;\n    fs->common.fs_statfs = fs_statfs;\n    fs->common.fs_attach = fs_attach;\n    fs->common.fs_walk = fs_walk;\n    fs->common.fs_mkdir = fs_mkdir;\n    fs->common.fs_open = fs_open;\n    fs->common.fs_create = fs_create;\n    fs->common.fs_stat = fs_stat;\n    fs->common.fs_setattr = fs_setattr;\n    fs->common.fs_close = fs_close;\n    fs->common.fs_readdir = fs_readdir;\n    fs->common.fs_read = fs_read;\n    fs->common.fs_write = fs_write;\n    fs->common.fs_link = fs_link;\n    fs->common.fs_symlink = fs_symlink;\n    fs->common.fs_mknod = fs_mknod;\n    fs->common.fs_readlink = fs_readlink;\n    fs->common.fs_renameat = fs_renameat;\n    fs->common.fs_unlinkat = fs_unlinkat;\n    fs->common.fs_lock = fs_lock;\n    fs->common.fs_getlock = fs_getlock;\n\n    init_list_head(&fs->inode_list);\n    fs->inode_num_alloc = 1;\n    fs->block_size_log2 = FS_BLOCK_SIZE_LOG2;\n    fs->block_size = 1 << fs->block_size_log2;\n    fs->inode_limit = 1 << 20; /* arbitrary */\n    fs->fs_max_blocks = 1 << (30 - fs->block_size_log2); /* arbitrary */\n\n    init_list_head(&fs->inode_cache_list);\n    fs->inode_cache_size_limit = DEFAULT_INODE_CACHE_SIZE;\n\n    init_list_head(&fs->preload_list);\n    init_list_head(&fs->preload_archive_list);\n\n    init_list_head(&fs->base_url_list);\n\n    /* create the root inode */\n    n = inode_new(fs1, FT_DIR, 0777, 0, 0);\n    inode_dir_add(fs1, n, \".\", inode_incref(fs1, n));\n    inode_dir_add(fs1, n, \"..\", inode_incref(fs1, n));\n    fs->root_inode = n;\n\n    return (FSDevice *)fs;\n}\n\nstatic BOOL fs_is_net(FSDevice *fs)\n{\n    return (fs->fs_end == fs_mem_end);\n}\n\nstatic FSBaseURL *fs_find_base_url(FSDevice *fs1,\n                                   const char *base_url_id)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    struct list_head *el;\n    FSBaseURL *bu;\n    \n    list_for_each(el, &fs->base_url_list) {\n        bu = list_entry(el, FSBaseURL, link);\n        if (!strcmp(bu->base_url_id, base_url_id))\n            return bu;\n    }\n    return NULL;\n}\n\nstatic void fs_base_url_decref(FSDevice *fs, FSBaseURL *bu)\n{\n    assert(bu->ref_count >= 1);\n    if (--bu->ref_count == 0) {\n        free(bu->base_url_id);\n        free(bu->url);\n        free(bu->user);\n        free(bu->password);\n        list_del(&bu->link);\n        free(bu);\n    }\n}\n\nstatic FSBaseURL *fs_net_set_base_url(FSDevice *fs1,\n                                      const char *base_url_id,\n                                      const char *url,\n                                      const char *user, const char *password,\n                                      AES_KEY *aes_state)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    FSBaseURL *bu;\n    \n    assert(fs_is_net(fs1));\n    bu = fs_find_base_url(fs1, base_url_id);\n    if (!bu) {\n        bu = mallocz(sizeof(*bu));\n        bu->base_url_id = strdup(base_url_id);\n        bu->ref_count = 1;\n        list_add_tail(&bu->link, &fs->base_url_list);\n    } else {\n        free(bu->url);\n        free(bu->user);\n        free(bu->password);\n    }\n\n    bu->url = strdup(url);\n    if (user)\n        bu->user = strdup(user);\n    else\n        bu->user = NULL;\n    if (password)\n        bu->password = strdup(password);\n    else\n        bu->password = NULL;\n    if (aes_state) {\n        bu->encrypted = TRUE;\n        bu->aes_state = *aes_state;\n    } else {\n        bu->encrypted = FALSE;\n    }\n    return bu;\n}\n\nstatic int fs_net_reset_base_url(FSDevice *fs1,\n                                 const char *base_url_id)\n{\n    FSBaseURL *bu;\n    \n    assert(fs_is_net(fs1));\n    bu = fs_find_base_url(fs1, base_url_id);\n    if (!bu)\n        return -P9_ENOENT;\n    fs_base_url_decref(fs1, bu);\n    return 0;\n}\n\nstatic void fs_net_set_fs_max_size(FSDevice *fs1, uint64_t fs_max_size)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n\n    assert(fs_is_net(fs1));\n    fs->fs_max_blocks = to_blocks(fs, fs_max_size);\n}\n\nstatic int fs_net_set_url(FSDevice *fs1, FSINode *n,\n                          const char *base_url_id, FSFileID file_id, uint64_t size)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    FSBaseURL *bu;\n\n    assert(fs_is_net(fs1));\n\n    bu = fs_find_base_url(fs1, base_url_id);\n    if (!bu)\n        return -P9_ENOENT;\n\n    /* XXX: could accept more state */\n    if (n->type != FT_REG ||\n        n->u.reg.state != REG_STATE_LOCAL ||\n        n->u.reg.fbuf.allocated_size != 0)\n        return -P9_EIO;\n        \n    if (size > 0) {\n        n->u.reg.state = REG_STATE_UNLOADED;\n        n->u.reg.base_url = bu;\n        bu->ref_count++;\n        n->u.reg.size = size;\n        fs->fs_blocks += to_blocks(fs, size);\n        n->u.reg.file_id = file_id;\n    }\n    return 0;\n}\n\n#ifdef DUMP_CACHE_LOAD\n\n#include \"json.h\"\n\n#define ARCHIVE_SIZE_MAX (4 << 20)\n\nstatic void fs_dump_add_file(struct list_head *head, const char *name)\n{\n    PreloadFile *pf;\n    pf = mallocz(sizeof(*pf));\n    pf->name = strdup(name);\n    list_add_tail(&pf->link, head);\n}\n\nstatic PreloadFile *fs_dump_find_file(struct list_head *head, const char *name)\n{\n    PreloadFile *pf;\n    struct list_head *el;\n    list_for_each(el, head) {\n        pf = list_entry(el, PreloadFile, link);\n        if (!strcmp(pf->name, name))\n            return pf;\n    }\n    return NULL;\n}\n\nstatic void dump_close_archive(FSDevice *fs1)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    if (fs->dump_archive_file) {\n        fclose(fs->dump_archive_file);\n    }\n    fs->dump_archive_file = NULL;\n    fs->dump_archive_size = 0;\n}\n\nstatic void dump_loaded_file(FSDevice *fs1, FSINode *n)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    char filename[1024];\n    const char *fname, *p;\n    \n    if (!fs->dump_cache_load || !n->u.reg.filename)\n        return;\n    fname = n->u.reg.filename;\n    \n    if (fs_dump_find_file(&fs->dump_preload_list, fname)) {\n        dump_close_archive(fs1);\n        p = strrchr(fname, '/');\n        if (!p)\n            p = fname;\n        else\n            p++;\n        free(fs->dump_archive_name);\n        fs->dump_archive_name = strdup(p);\n        fs->dump_started = TRUE;\n        fs->dump_archive_num = 0;\n\n        fprintf(fs->dump_preload_file, \"\\n%s :\\n\", fname);\n    }\n    if (!fs->dump_started)\n        return;\n    \n    if (!fs->dump_archive_file) {\n        snprintf(filename, sizeof(filename), \"%s/%s%d\",\n                 fs->dump_preload_dir, fs->dump_archive_name,\n                 fs->dump_archive_num);\n        fs->dump_archive_file = fopen(filename, \"wb\");\n        if (!fs->dump_archive_file) {\n            perror(filename);\n            exit(1);\n        }\n        fprintf(fs->dump_preload_archive_file, \"\\n@.preload2/%s%d :\\n\",\n                fs->dump_archive_name, fs->dump_archive_num);\n        fprintf(fs->dump_preload_file, \"  @.preload2/%s%d\\n\",\n                fs->dump_archive_name, fs->dump_archive_num);\n        fflush(fs->dump_preload_file);\n        fs->dump_archive_num++;\n    }\n\n    if (n->u.reg.size >= ARCHIVE_SIZE_MAX) {\n        /* exclude large files from archive */\n        /* add indicative size */\n        fprintf(fs->dump_preload_file, \"  %s %\" PRId64 \"\\n\",\n                fname, n->u.reg.size);\n        fflush(fs->dump_preload_file);\n    } else {\n        fprintf(fs->dump_preload_archive_file, \"  %s %\" PRId64 \" %\" PRIx64 \"\\n\",\n                n->u.reg.filename, n->u.reg.size, n->u.reg.file_id);\n        fflush(fs->dump_preload_archive_file);\n        fwrite(n->u.reg.fbuf.data, 1, n->u.reg.size, fs->dump_archive_file);\n        fflush(fs->dump_archive_file);\n        fs->dump_archive_size += n->u.reg.size;\n        if (fs->dump_archive_size >= ARCHIVE_SIZE_MAX) {\n            dump_close_archive(fs1);\n        }\n    }\n}\n\nstatic JSONValue json_load(const char *filename)\n{\n    FILE *f;\n    JSONValue val;\n    size_t size;\n    char *buf;\n    \n    f = fopen(filename, \"rb\");\n    if (!f) {\n        perror(filename);\n        exit(1);\n    }\n    fseek(f, 0, SEEK_END);\n    size = ftell(f);\n    fseek(f, 0, SEEK_SET);\n    buf = malloc(size + 1);\n    fread(buf, 1, size, f);\n    fclose(f);\n    val = json_parse_value_len(buf, size);\n    free(buf);\n    return val;\n}\n\nvoid fs_dump_cache_load(FSDevice *fs1, const char *cfg_filename)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    JSONValue cfg, val, array;\n    char *fname;\n    const char *preload_dir, *name;\n    int i;\n    \n    if (!fs_is_net(fs1))\n        return;\n    cfg = json_load(cfg_filename);\n    if (json_is_error(cfg)) {\n        fprintf(stderr, \"%s\\n\", json_get_error(cfg));\n        exit(1);\n    }\n\n    val = json_object_get(cfg, \"preload_dir\");\n    if (json_is_undefined(cfg)) {\n    config_error:\n        exit(1);\n    }\n    preload_dir = json_get_str(val);\n    if (!preload_dir) {\n        fprintf(stderr, \"expecting preload_filename\\n\");\n        goto config_error;\n    }\n    fs->dump_preload_dir = strdup(preload_dir);\n    \n    init_list_head(&fs->dump_preload_list);\n    init_list_head(&fs->dump_exclude_list);\n\n    array = json_object_get(cfg, \"preload\");\n    if (array.type != JSON_ARRAY) {\n        fprintf(stderr, \"expecting preload array\\n\");\n        goto config_error;\n    }\n    for(i = 0; i < array.u.array->len; i++) {\n        val = json_array_get(array, i);\n        name = json_get_str(val);\n        if (!name) {\n            fprintf(stderr, \"expecting a string\\n\");\n            goto config_error;\n        }\n        fs_dump_add_file(&fs->dump_preload_list, name);\n    }\n    json_free(cfg);\n\n    fname = compose_path(fs->dump_preload_dir, \"preload.txt\");\n    fs->dump_preload_file = fopen(fname, \"w\");\n    if (!fs->dump_preload_file) {\n        perror(fname);\n        exit(1);\n    }\n    free(fname);\n\n    fname = compose_path(fs->dump_preload_dir, \"preload_archive.txt\");\n    fs->dump_preload_archive_file = fopen(fname, \"w\");\n    if (!fs->dump_preload_archive_file) {\n        perror(fname);\n        exit(1);\n    }\n    free(fname);\n\n    fs->dump_cache_load = TRUE;\n}\n#else\nvoid fs_dump_cache_load(FSDevice *fs1, const char *cfg_filename)\n{\n}\n#endif\n\n/***********************************************/\n/* file list processing */\n\nstatic int filelist_load_rec(FSDevice *fs1, const char **pp, FSINode *dir,\n                             const char *path)\n{\n    //    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    char fname[1024], lname[1024];\n    int ret;\n    const char *p;\n    FSINodeTypeEnum type;\n    uint32_t mode, uid, gid;\n    uint64_t size;\n    FSINode *n;\n\n    p = *pp;\n    for(;;) {\n        /* skip comments or empty lines */\n        if (*p == '\\0')\n            break;\n        if (*p == '#') {\n            skip_line(&p);\n            continue;\n        }\n        /* end of directory */\n        if (*p == '.') {\n            p++;\n            skip_line(&p);\n            break;\n        }\n        if (parse_uint32_base(&mode, &p, 8) < 0) {\n            fprintf(stderr, \"invalid mode\\n\");\n            return -1;\n        }\n        type = mode >> 12;\n        mode &= 0xfff;\n        \n        if (parse_uint32(&uid, &p) < 0) {\n            fprintf(stderr, \"invalid uid\\n\");\n            return -1;\n        }\n\n        if (parse_uint32(&gid, &p) < 0) {\n            fprintf(stderr, \"invalid gid\\n\");\n            return -1;\n        }\n\n        n = inode_new(fs1, type, mode, uid, gid);\n        \n        size = 0;\n        switch(type) {\n        case FT_CHR:\n        case FT_BLK:\n            if (parse_uint32(&n->u.dev.major, &p) < 0) {\n                fprintf(stderr, \"invalid major\\n\");\n                return -1;\n            }\n            if (parse_uint32(&n->u.dev.minor, &p) < 0) {\n                fprintf(stderr, \"invalid minor\\n\");\n                return -1;\n            }\n            break;\n        case FT_REG:\n            if (parse_uint64(&size, &p) < 0) {\n                fprintf(stderr, \"invalid size\\n\");\n                return -1;\n            }\n            break;\n        case FT_DIR:\n            inode_dir_add(fs1, n, \".\", inode_incref(fs1, n));\n            inode_dir_add(fs1, n, \"..\", inode_incref(fs1, dir));\n            break;\n        default:\n            break;\n        }\n        \n        /* modification time */\n        if (parse_time(&n->mtime_sec, &n->mtime_nsec, &p) < 0) {\n            fprintf(stderr, \"invalid mtime\\n\");\n            return -1;\n        }\n\n        if (parse_fname(fname, sizeof(fname), &p) < 0) {\n            fprintf(stderr, \"invalid filename\\n\");\n            return -1;\n        }\n        inode_dir_add(fs1, dir, fname, n);\n        \n        if (type == FT_LNK) {\n            if (parse_fname(lname, sizeof(lname), &p) < 0) {\n                fprintf(stderr, \"invalid symlink name\\n\");\n                return -1;\n            }\n            n->u.symlink.name = strdup(lname);\n        } else if (type == FT_REG && size > 0) {\n            FSFileID file_id;\n            if (parse_file_id(&file_id, &p) < 0) {\n                fprintf(stderr, \"invalid file id\\n\");\n                return -1;\n            }\n            fs_net_set_url(fs1, n, \"/\", file_id, size);\n#ifdef DUMP_CACHE_LOAD\n            {\n                FSDeviceMem *fs = (FSDeviceMem *)fs1;\n                if (fs->dump_cache_load\n#ifdef DEBUG_CACHE\n                    || 1\n#endif\n                    ) {\n                    n->u.reg.filename = compose_path(path, fname);\n                } else {\n                    n->u.reg.filename = NULL;\n                }\n            }\n#endif\n        }\n\n        skip_line(&p);\n        \n        if (type == FT_DIR) {\n            char *path1;\n            path1 = compose_path(path, fname);\n            ret = filelist_load_rec(fs1, &p, n, path1);\n            free(path1);\n            if (ret)\n                return ret;\n        }\n    }\n    *pp = p;\n    return 0;\n}\n\nstatic int filelist_load(FSDevice *fs1, const char *str)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    int ret;\n    const char *p;\n    \n    if (parse_tag_version(str) != 1)\n        return -1;\n    p = skip_header(str);\n    if (!p)\n        return -1;\n    ret = filelist_load_rec(fs1, &p, fs->root_inode, \"\");\n    return ret;\n}\n\n/************************************************************/\n/* FS init from network */\n\nstatic void __attribute__((format(printf, 1, 2))) fatal_error(const char *fmt, ...)\n{\n    va_list ap;\n    va_start(ap, fmt);\n    fprintf(stderr, \"Error: \");\n    vfprintf(stderr, fmt, ap);\n    fprintf(stderr, \"\\n\");\n    va_end(ap);\n    exit(1);\n}\n\nstatic void fs_create_cmd(FSDevice *fs)\n{\n    FSFile *root_fd;\n    FSQID qid;\n    FSINode *n;\n    int ret;\n    \n    ret = fs->fs_attach(fs, &root_fd, &qid, 0, \"\", \"\");\n    assert(ret == 0);\n    ret = fs->fs_create(fs, &qid, root_fd, FSCMD_NAME, P9_O_RDWR | P9_O_TRUNC,\n                    0666, 0);\n    assert(ret == 0);\n    n = root_fd->inode;\n    n->u.reg.is_fscmd = TRUE;\n    fs->fs_delete(fs, root_fd);\n}\n\ntypedef struct {\n    FSDevice *fs;\n    char *url;\n    void (*start_cb)(void *opaque);\n    void *start_opaque;\n    \n    FSFile *root_fd;\n    FSFile *fd;\n    int file_index;\n    \n} FSNetInitState;\n\nstatic void fs_initial_sync(FSDevice *fs,\n                            const char *url, void (*start_cb)(void *opaque),\n                            void *start_opaque);\nstatic void head_loaded(FSDevice *fs, FSFile *f, int64_t size, void *opaque);\nstatic void filelist_loaded(FSDevice *fs, FSFile *f, int64_t size, void *opaque);\nstatic void kernel_load_cb(FSDevice *fs, FSQID *qid, int err,\n                           void *opaque);\nstatic int preload_parse(FSDevice *fs, const char *fname, BOOL is_new);\n\n#ifdef EMSCRIPTEN\nstatic FSDevice *fs_import_fs;\n#endif\n\n#define DEFAULT_IMPORT_FILE_PATH \"/tmp\"\n\nFSDevice *fs_net_init(const char *url, void (*start_cb)(void *opaque),\n                      void *start_opaque)\n{\n    FSDevice *fs;\n    FSDeviceMem *fs1;\n    \n    fs_wget_init();\n    \n    fs = fs_mem_init();\n#ifdef EMSCRIPTEN\n    if (!fs_import_fs)\n        fs_import_fs = fs;\n#endif\n    fs1 = (FSDeviceMem *)fs;\n    fs1->import_dir = strdup(DEFAULT_IMPORT_FILE_PATH);\n    \n    fs_create_cmd(fs);\n\n    if (url) {\n        fs_initial_sync(fs, url, start_cb, start_opaque);\n    }\n    return fs;\n}\n\nstatic void fs_initial_sync(FSDevice *fs,\n                            const char *url, void (*start_cb)(void *opaque),\n                            void *start_opaque)\n{\n    FSNetInitState *s;\n    FSFile *head_fd;\n    FSQID qid;\n    char *head_url;\n    char buf[128];\n    struct timeval tv;\n    int err;\n    \n    s = mallocz(sizeof(*s));\n    s->fs = fs;\n    s->url = strdup(url);\n    s->start_cb = start_cb;\n    s->start_opaque = start_opaque;\n    err = fs->fs_attach(fs, &s->root_fd, &qid, 0, \"\", \"\");\n    assert(err == 0);\n    \n    /* avoid using cached version */\n    gettimeofday(&tv, NULL);\n    snprintf(buf, sizeof(buf), HEAD_FILENAME \"?nocache=%\" PRId64,\n             (int64_t)tv.tv_sec * 1000000 + tv.tv_usec);\n    head_url = compose_url(s->url, buf);\n    head_fd = fs_dup(fs, s->root_fd);\n    err = fs->fs_create(fs, &qid, head_fd, \".head\",\n                    P9_O_RDWR | P9_O_TRUNC, 0644, 0);\n    assert(err == 0);\n    fs_wget_file2(fs, head_fd, head_url, NULL, NULL, NULL, 0,\n                  head_loaded, s, NULL);\n    free(head_url);\n}\n\nstatic void head_loaded(FSDevice *fs, FSFile *f, int64_t size, void *opaque)\n{\n    FSNetInitState *s = opaque;\n    char *buf, *root_url, *url;\n    char fname[FILEID_SIZE_MAX];\n    FSFileID root_id;\n    FSFile *new_filelist_fd;\n    FSQID qid;\n    uint64_t fs_max_size;\n    int err;\n    \n    if (size < 0)\n        fatal_error(\"could not load 'head' file (HTTP error=%d)\", -(int)size);\n    \n    buf = malloc(size + 1);\n    fs->fs_read(fs, f, 0, (uint8_t *)buf, size);\n    buf[size] = '\\0';\n    fs->fs_delete(fs, f);\n    fs->fs_unlinkat(fs, s->root_fd, \".head\");\n\n    if (parse_tag_version(buf) != 1)\n        fatal_error(\"invalid head version\");\n\n    if (parse_tag_file_id(&root_id, buf, \"RootID\") < 0)\n        fatal_error(\"expected RootID tag\");\n\n    if (parse_tag_uint64(&fs_max_size, buf, \"FSMaxSize\") == 0 &&\n        fs_max_size >= ((uint64_t)1 << 20)) {\n        fs_net_set_fs_max_size(fs, fs_max_size);\n    }\n                       \n    /* set the Root URL in the filesystem */\n    root_url = compose_url(s->url, ROOT_FILENAME);\n    fs_net_set_base_url(fs, \"/\", root_url, NULL, NULL, NULL);\n    \n    new_filelist_fd = fs_dup(fs, s->root_fd);\n    err = fs->fs_create(fs, &qid, new_filelist_fd, \".filelist.txt\",\n                    P9_O_RDWR | P9_O_TRUNC, 0644, 0);\n    assert(err == 0);\n\n    file_id_to_filename(fname, root_id);\n    url = compose_url(root_url, fname);\n    fs_wget_file2(fs, new_filelist_fd, url, NULL, NULL, NULL, 0,\n                  filelist_loaded, s, NULL);\n    free(root_url);\n    free(url);\n}\n\nstatic void filelist_loaded(FSDevice *fs, FSFile *f, int64_t size, void *opaque)\n{\n    FSNetInitState *s = opaque;\n    uint8_t *buf;\n\n    if (size < 0)\n        fatal_error(\"could not load file list (HTTP error=%d)\", -(int)size);\n    \n    buf = malloc(size + 1);\n    fs->fs_read(fs, f, 0, buf, size);\n    buf[size] = '\\0';\n    fs->fs_delete(fs, f);\n    fs->fs_unlinkat(fs, s->root_fd, \".filelist.txt\");\n    \n    if (filelist_load(fs, (char *)buf) != 0)\n        fatal_error(\"error while parsing file list\");\n\n    /* try to load the kernel and the preload file */\n    s->file_index = 0;\n    kernel_load_cb(fs, NULL, 0, s);\n}\n\n\n#define FILE_LOAD_COUNT 2\n\nstatic const char *kernel_file_list[FILE_LOAD_COUNT] = {\n    \".preload\",\n    \".preload2/preload.txt\",\n};\n\nstatic void kernel_load_cb(FSDevice *fs, FSQID *qid1, int err,\n                           void *opaque)\n{\n    FSNetInitState *s = opaque;\n    FSQID qid;\n\n#ifdef DUMP_CACHE_LOAD\n    /* disable preloading if dumping cache load */\n    if (((FSDeviceMem *)fs)->dump_cache_load)\n        return;\n#endif\n\n    if (s->fd) {\n        fs->fs_delete(fs, s->fd);\n        s->fd = NULL;\n    }\n    \n    if (s->file_index >= FILE_LOAD_COUNT) {\n        /* all files are loaded */\n        if (preload_parse(fs, \".preload2/preload.txt\", TRUE) < 0) { \n            preload_parse(fs, \".preload\", FALSE);\n        }\n        fs->fs_delete(fs, s->root_fd);\n        if (s->start_cb)\n            s->start_cb(s->start_opaque);\n        free(s);\n    } else {\n        s->fd = fs_walk_path(fs, s->root_fd, kernel_file_list[s->file_index++]);\n        if (!s->fd)\n            goto done;\n        err = fs->fs_open(fs, &qid, s->fd, P9_O_RDONLY, kernel_load_cb, s);\n        if (err <= 0) {\n        done:\n            kernel_load_cb(fs, NULL, 0, s);\n        }\n    }\n}\n\nstatic void preload_parse_str_old(FSDevice *fs1, const char *p)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    char fname[1024];\n    PreloadEntry *pe;\n    PreloadFile *pf;\n    FSINode *n;\n\n    for(;;) {\n        while (isspace_nolf(*p))\n            p++;\n        if (*p == '\\n') {\n            p++;\n            continue;\n        }\n        if (*p == '\\0')\n            break;\n        if (parse_fname(fname, sizeof(fname), &p) < 0) {\n            fprintf(stderr, \"invalid filename\\n\");\n            return;\n        }\n        //        printf(\"preload file='%s\\n\", fname);\n        n = inode_search_path(fs1, fname);\n        if (!n || n->type != FT_REG || n->u.reg.state == REG_STATE_LOCAL) {\n            fprintf(stderr, \"invalid preload file: '%s'\\n\", fname);\n            while (*p != '\\n' && *p != '\\0')\n                p++;\n        } else {\n            pe = mallocz(sizeof(*pe));\n            pe->file_id = n->u.reg.file_id;\n            init_list_head(&pe->file_list);\n            list_add_tail(&pe->link, &fs->preload_list);\n            for(;;) {\n                while (isspace_nolf(*p))\n                    p++;\n                if (*p == '\\0' || *p == '\\n')\n                    break;\n                if (parse_fname(fname, sizeof(fname), &p) < 0) {\n                    fprintf(stderr, \"invalid filename\\n\");\n                    return;\n                }\n                //                printf(\"  adding '%s'\\n\", fname);\n                pf = mallocz(sizeof(*pf));\n                pf->name = strdup(fname);\n                list_add_tail(&pf->link, &pe->file_list); \n            }\n        }\n    }\n}\n\nstatic void preload_parse_str(FSDevice *fs1, const char *p)\n{\n    FSDeviceMem *fs = (FSDeviceMem *)fs1;\n    PreloadEntry *pe;\n    PreloadArchive *pa;\n    FSINode *n;\n    BOOL is_archive;\n    char fname[1024];\n    \n    pe = NULL;\n    pa = NULL;\n    for(;;) {\n        while (isspace_nolf(*p))\n            p++;\n        if (*p == '\\n') {\n            pe = NULL;\n            p++;\n            continue;\n        }\n        if (*p == '#')\n            continue; /* comment */\n        if (*p == '\\0')\n            break;\n\n        is_archive = FALSE;\n        if (*p == '@') {\n            is_archive = TRUE;\n            p++;\n        }\n        if (parse_fname(fname, sizeof(fname), &p) < 0) {\n            fprintf(stderr, \"invalid filename\\n\");\n            return;\n        }\n        while (isspace_nolf(*p))\n            p++;\n        if (*p == ':') {\n            p++;\n            //            printf(\"preload file='%s' archive=%d\\n\", fname, is_archive);\n            n = inode_search_path(fs1, fname);\n            pe = NULL;\n            pa = NULL;\n            if (!n || n->type != FT_REG || n->u.reg.state == REG_STATE_LOCAL) {\n                fprintf(stderr, \"invalid preload file: '%s'\\n\", fname);\n                while (*p != '\\n' && *p != '\\0')\n                    p++;\n            } else if (is_archive) {\n                pa = mallocz(sizeof(*pa));\n                pa->name = strdup(fname);\n                init_list_head(&pa->file_list);\n                list_add_tail(&pa->link, &fs->preload_archive_list);\n            } else {\n                pe = mallocz(sizeof(*pe));\n                pe->file_id = n->u.reg.file_id;\n                init_list_head(&pe->file_list);\n                list_add_tail(&pe->link, &fs->preload_list);\n            }\n        } else {\n            if (!pe && !pa) {\n                fprintf(stderr, \"filename without target: %s\\n\", fname);\n                return;\n            }\n            if (pa) {\n                PreloadArchiveFile *paf;\n                FSFileID file_id;\n                uint64_t size;\n\n                if (parse_uint64(&size, &p) < 0) {\n                    fprintf(stderr, \"invalid size\\n\");\n                    return;\n                }\n\n                if (parse_file_id(&file_id, &p) < 0) {\n                    fprintf(stderr, \"invalid file id\\n\");\n                    return;\n                }\n\n                paf = mallocz(sizeof(*paf));\n                paf->name = strdup(fname);\n                paf->file_id = file_id;\n                paf->size = size;\n                list_add_tail(&paf->link, &pa->file_list);\n            } else {\n                PreloadFile *pf;\n                pf = mallocz(sizeof(*pf));\n                pf->name = strdup(fname);\n                pf->is_archive = is_archive;\n                list_add_tail(&pf->link, &pe->file_list);\n            }\n        }\n        /* skip the rest of the line */\n        while (*p != '\\n' && *p != '\\0')\n            p++;\n        if (*p == '\\n')\n            p++;\n    }\n}\n\nstatic int preload_parse(FSDevice *fs, const char *fname, BOOL is_new)\n{\n    FSINode *n;\n    char *buf;\n    size_t size;\n    \n    n = inode_search_path(fs, fname);\n    if (!n || n->type != FT_REG || n->u.reg.state != REG_STATE_LOADED)\n        return -1;\n    /* transform to zero terminated string */\n    size = n->u.reg.size;\n    buf = malloc(size + 1);\n    file_buffer_read(&n->u.reg.fbuf, 0, (uint8_t *)buf, size);\n    buf[size] = '\\0';\n    if (is_new)\n        preload_parse_str(fs, buf);\n    else\n        preload_parse_str_old(fs, buf);\n    free(buf);\n    return 0;\n}\n\n\n\n/************************************************************/\n/* FS user interface */\n\ntypedef struct CmdXHRState {\n    FSFile *req_fd;\n    FSFile *root_fd;\n    FSFile *fd;\n    FSFile *post_fd;\n    AES_KEY aes_state;\n} CmdXHRState;\n\nstatic void fs_cmd_xhr_on_load(FSDevice *fs, FSFile *f, int64_t size,\n                               void *opaque);\n\nstatic int parse_hex_buf(uint8_t *buf, int buf_size, const char **pp)\n{\n    char buf1[1024];\n    int len;\n    \n    if (parse_fname(buf1, sizeof(buf1), pp) < 0)\n        return -1;\n    len = strlen(buf1);\n    if ((len & 1) != 0)\n        return -1;\n    len >>= 1;\n    if (len > buf_size)\n        return -1;\n    if (decode_hex(buf, buf1, len) < 0)\n        return -1;\n    return len;\n}\n\nstatic int fs_cmd_xhr(FSDevice *fs, FSFile *f,\n                      const char *p, uint32_t uid, uint32_t gid)\n{\n    char url[1024], post_filename[1024], filename[1024];\n    char user_buf[128], *user;\n    char password_buf[128], *password;\n    FSQID qid;\n    FSFile *fd, *root_fd, *post_fd;\n    uint64_t post_data_len;\n    int err, aes_key_len;\n    CmdXHRState *s;\n    char *name;\n    AES_KEY *paes_state;\n    uint8_t aes_key[FS_KEY_LEN];\n    uint32_t flags;\n    FSCMDRequest *req;\n\n    /* a request is already done or in progress */\n    if (f->req != NULL)\n        return -P9_EIO;\n\n    if (parse_fname(url, sizeof(url), &p) < 0)\n        goto fail;\n    if (parse_fname(user_buf, sizeof(user_buf), &p) < 0)\n        goto fail;\n    if (parse_fname(password_buf, sizeof(password_buf), &p) < 0)\n        goto fail;\n    if (parse_fname(post_filename, sizeof(post_filename), &p) < 0)\n        goto fail;\n    if (parse_fname(filename, sizeof(filename), &p) < 0)\n        goto fail;\n    aes_key_len = parse_hex_buf(aes_key, FS_KEY_LEN, &p);\n    if (aes_key_len < 0)\n        goto fail;\n    if (parse_uint32(&flags, &p) < 0)\n        goto fail;\n    if (aes_key_len != 0 && aes_key_len != FS_KEY_LEN)\n        goto fail;\n\n    if (user_buf[0] != '\\0')\n        user = user_buf;\n    else\n        user = NULL;\n    if (password_buf[0] != '\\0')\n        password = password_buf;\n    else\n        password = NULL;\n\n    //    printf(\"url='%s' '%s' '%s' filename='%s'\\n\", url, user, password, filename);\n    err = fs->fs_attach(fs, &root_fd, &qid, uid, \"\", \"\");\n    assert(err == 0);\n    post_fd = NULL;\n\n    fd = fs_walk_path1(fs, root_fd, filename, &name);\n    if (!fd) {\n        err = -P9_ENOENT;\n        goto fail1;\n    }\n    /* XXX: until fs_create is fixed */\n    fs->fs_unlinkat(fs, fd, name);\n\n    err = fs->fs_create(fs, &qid, fd, name,\n                        P9_O_RDWR | P9_O_TRUNC, 0600, gid);\n    if (err < 0) {\n        goto fail1;\n    }\n\n    if (post_filename[0] != '\\0') {\n        FSINode *n;\n        \n        post_fd = fs_walk_path(fs, root_fd, post_filename);\n        if (!post_fd) {\n            err = -P9_ENOENT;\n            goto fail1;\n        }\n        err = fs->fs_open(fs, &qid, post_fd, P9_O_RDONLY, NULL, NULL);\n        if (err < 0)\n            goto fail1;\n        n = post_fd->inode;\n        assert(n->type == FT_REG && n->u.reg.state == REG_STATE_LOCAL);\n        post_data_len = n->u.reg.size;\n    } else {\n        post_data_len = 0;\n    }\n\n    s = mallocz(sizeof(*s));\n    s->root_fd = root_fd;\n    s->fd = fd;\n    s->post_fd = post_fd;\n    if (aes_key_len != 0) {\n        AES_set_decrypt_key(aes_key, FS_KEY_LEN * 8, &s->aes_state);\n        paes_state = &s->aes_state;\n    } else {\n        paes_state = NULL;\n    }\n\n    req = mallocz(sizeof(*req));\n    req->type = FS_CMD_XHR;\n    req->reply_len = 0;\n    req->xhr_state = s;\n    s->req_fd = f;\n    f->req = req;\n    \n    fs_wget_file2(fs, fd, url, user, password, post_fd, post_data_len,\n                  fs_cmd_xhr_on_load, s, paes_state);\n    return 0;\n fail1:\n    if (fd)\n        fs->fs_delete(fs, fd);\n    if (post_fd)\n        fs->fs_delete(fs, post_fd);\n    fs->fs_delete(fs, root_fd);\n    return err;\n fail:\n    return -P9_EIO;\n}\n\nstatic void fs_cmd_xhr_on_load(FSDevice *fs, FSFile *f, int64_t size,\n                               void *opaque)\n{\n    CmdXHRState *s = opaque;\n    FSCMDRequest *req;\n    int ret;\n    \n    //    printf(\"fs_cmd_xhr_on_load: size=%d\\n\", (int)size);\n\n    if (s->fd)\n        fs->fs_delete(fs, s->fd);\n    if (s->post_fd)\n        fs->fs_delete(fs, s->post_fd);\n    fs->fs_delete(fs, s->root_fd);\n    \n    if (s->req_fd) {\n        req = s->req_fd->req;\n        if (size < 0) {\n            ret = size;\n        } else {\n            ret = 0;\n        }\n        put_le32(req->reply_buf, ret);\n        req->reply_len = sizeof(ret);\n        req->xhr_state = NULL;\n    }\n    free(s);\n}\n\nstatic int fs_cmd_set_base_url(FSDevice *fs, const char *p)\n{\n    //    FSDeviceMem *fs1 = (FSDeviceMem *)fs;\n    char url[1024], base_url_id[1024];\n    char user_buf[128], *user;\n    char password_buf[128], *password;\n    AES_KEY aes_state, *paes_state;\n    uint8_t aes_key[FS_KEY_LEN];\n    int aes_key_len;\n    \n    if (parse_fname(base_url_id, sizeof(base_url_id), &p) < 0)\n        goto fail;\n    if (parse_fname(url, sizeof(url), &p) < 0)\n        goto fail;\n    if (parse_fname(user_buf, sizeof(user_buf), &p) < 0)\n        goto fail;\n    if (parse_fname(password_buf, sizeof(password_buf), &p) < 0)\n        goto fail;\n    aes_key_len = parse_hex_buf(aes_key, FS_KEY_LEN, &p);\n    if (aes_key_len < 0)\n        goto fail;\n\n    if (user_buf[0] != '\\0')\n        user = user_buf;\n    else\n        user = NULL;\n    if (password_buf[0] != '\\0')\n        password = password_buf;\n    else\n        password = NULL;\n\n    if (aes_key_len != 0) {\n        if (aes_key_len != FS_KEY_LEN)\n            goto fail;\n        AES_set_decrypt_key(aes_key, FS_KEY_LEN * 8, &aes_state);\n        paes_state = &aes_state;\n    } else {\n        paes_state = NULL;\n    }\n\n    fs_net_set_base_url(fs, base_url_id, url, user, password,\n                        paes_state);\n    return 0;\n fail:\n    return -P9_EINVAL;\n}\n\nstatic int fs_cmd_reset_base_url(FSDevice *fs, const char *p)\n{\n    char base_url_id[1024];\n    \n    if (parse_fname(base_url_id, sizeof(base_url_id), &p) < 0)\n        goto fail;\n    fs_net_reset_base_url(fs, base_url_id);\n    return 0;\n fail:\n    return -P9_EINVAL;\n}\n\nstatic int fs_cmd_set_url(FSDevice *fs, const char *p)\n{\n    char base_url_id[1024];\n    char filename[1024];\n    FSFileID file_id;\n    uint64_t size;\n    FSINode *n;\n    \n    if (parse_fname(filename, sizeof(filename), &p) < 0)\n        goto fail;\n    if (parse_fname(base_url_id, sizeof(base_url_id), &p) < 0)\n        goto fail;\n    if (parse_file_id(&file_id, &p) < 0)\n        goto fail;\n    if (parse_uint64(&size, &p) < 0)\n        goto fail;\n    \n    n = inode_search_path(fs, filename);\n    if (!n) {\n        return -P9_ENOENT;\n    }\n    return fs_net_set_url(fs, n, base_url_id, file_id, size);\n fail:\n    return -P9_EINVAL;\n}\n\nstatic int fs_cmd_export_file(FSDevice *fs, const char *p)\n{\n    char filename[1024];\n    FSINode *n;\n    const char *name;\n    uint8_t *buf;\n    \n    if (parse_fname(filename, sizeof(filename), &p) < 0)\n        goto fail;\n    n = inode_search_path(fs, filename);\n    if (!n)\n        return -P9_ENOENT;\n    if (n->type != FT_REG ||\n        (n->u.reg.state != REG_STATE_LOCAL &&\n         n->u.reg.state != REG_STATE_LOADED))\n        goto fail;\n    name = strrchr(filename, '/');\n    if (name)\n        name++;\n    else\n        name = filename;\n    /* XXX: pass the buffer to JS to avoid the allocation */\n    buf = malloc(n->u.reg.size);\n    file_buffer_read(&n->u.reg.fbuf, 0, buf, n->u.reg.size);\n    fs_export_file(name, buf, n->u.reg.size);\n    free(buf);\n    return 0;\n fail:\n    return -P9_EIO;\n}\n\n/* PBKDF2 crypto acceleration */\nstatic int fs_cmd_pbkdf2(FSDevice *fs, FSFile *f, const char *p)\n{\n    uint8_t pwd[1024];\n    uint8_t salt[128];\n    uint32_t iter, key_len;\n    int pwd_len, salt_len;\n    FSCMDRequest *req;\n    \n    /* a request is already done or in progress */\n    if (f->req != NULL)\n        return -P9_EIO;\n\n    pwd_len = parse_hex_buf(pwd, sizeof(pwd), &p);\n    if (pwd_len < 0)\n        goto fail;\n    salt_len = parse_hex_buf(salt, sizeof(salt), &p);\n    if (pwd_len < 0)\n        goto fail;\n    if (parse_uint32(&iter, &p) < 0)\n        goto fail;\n    if (parse_uint32(&key_len, &p) < 0)\n        goto fail;\n    if (key_len > FS_CMD_REPLY_LEN_MAX ||\n        key_len == 0)\n        goto fail;\n    req = mallocz(sizeof(*req));\n    req->type = FS_CMD_PBKDF2;\n    req->reply_len = key_len;\n    pbkdf2_hmac_sha256(pwd, pwd_len, salt, salt_len, iter, key_len,\n                       req->reply_buf);\n    f->req = req;\n    return 0;\n fail:\n    return -P9_EINVAL;\n}\n\nstatic int fs_cmd_set_import_dir(FSDevice *fs, FSFile *f, const char *p)\n{\n    FSDeviceMem *fs1 = (FSDeviceMem *)fs;\n    char filename[1024];\n\n    if (parse_fname(filename, sizeof(filename), &p) < 0)\n        return -P9_EINVAL;\n    free(fs1->import_dir);\n    fs1->import_dir = strdup(filename);\n    return 0;\n}\n\nstatic int fs_cmd_write(FSDevice *fs, FSFile *f, uint64_t offset,\n                        const uint8_t *buf, int buf_len)\n{\n    char *buf1;\n    const char *p;\n    char cmd[64];\n    int err;\n    \n    /* transform into a string */\n    buf1 = malloc(buf_len + 1);\n    memcpy(buf1, buf, buf_len);\n    buf1[buf_len] = '\\0';\n    \n    err = 0;\n    p = buf1;\n    if (parse_fname(cmd, sizeof(cmd), &p) < 0)\n        goto fail;\n    if (!strcmp(cmd, \"xhr\")) {\n        err = fs_cmd_xhr(fs, f, p, f->uid, 0);\n    } else if (!strcmp(cmd, \"set_base_url\")) {\n        err = fs_cmd_set_base_url(fs, p);\n    } else if (!strcmp(cmd, \"reset_base_url\")) {\n        err = fs_cmd_reset_base_url(fs, p);\n    } else if (!strcmp(cmd, \"set_url\")) {\n        err = fs_cmd_set_url(fs, p);\n    } else if (!strcmp(cmd, \"export_file\")) {\n        err = fs_cmd_export_file(fs, p);\n    } else if (!strcmp(cmd, \"pbkdf2\")) {\n        err = fs_cmd_pbkdf2(fs, f, p);\n    } else if (!strcmp(cmd, \"set_import_dir\")) {\n        err = fs_cmd_set_import_dir(fs, f, p);\n    } else {\n        printf(\"unknown command: '%s'\\n\", cmd);\n    fail:\n        err = -P9_EIO;\n    }\n    free(buf1);\n    if (err == 0)\n        return buf_len;\n    else\n        return err;\n}\n\nstatic int fs_cmd_read(FSDevice *fs, FSFile *f, uint64_t offset,\n                       uint8_t *buf, int buf_len)\n{\n    FSCMDRequest *req;\n    int l;\n    \n    req = f->req;\n    if (!req)\n        return -P9_EIO;\n    l = min_int(req->reply_len, buf_len);\n    memcpy(buf, req->reply_buf, l);\n    return l;\n}\n\nstatic void fs_cmd_close(FSDevice *fs, FSFile *f)\n{\n    FSCMDRequest *req;\n    req = f->req;\n\n    if (req) {\n        if (req->xhr_state) {\n            req->xhr_state->req_fd = NULL;\n        }\n        free(req);\n        f->req = NULL;\n    }\n}\n\n/* Create a .fscmd_pwd file to avoid passing the password thru the\n   Linux command line */\nvoid fs_net_set_pwd(FSDevice *fs, const char *pwd)\n{\n    FSFile *root_fd;\n    FSQID qid;\n    int err;\n    \n    assert(fs_is_net(fs));\n    \n    err = fs->fs_attach(fs, &root_fd, &qid, 0, \"\", \"\");\n    assert(err == 0);\n    err = fs->fs_create(fs, &qid, root_fd, \".fscmd_pwd\", P9_O_RDWR | P9_O_TRUNC,\n                    0600, 0);\n    assert(err == 0);\n    fs->fs_write(fs, root_fd, 0, (uint8_t *)pwd, strlen(pwd));\n    fs->fs_delete(fs, root_fd);\n}\n\n/* external file import */\n\n#ifdef EMSCRIPTEN\n\nvoid fs_import_file(const char *filename, uint8_t *buf, int buf_len)\n{\n    FSDevice *fs;\n    FSDeviceMem *fs1;\n    FSFile *fd, *root_fd;\n    FSQID qid;\n    int err;\n    \n    //    printf(\"importing file: %s len=%d\\n\", filename, buf_len);\n    fs = fs_import_fs;\n    if (!fs) {\n        free(buf);\n        return;\n    }\n    \n    err = fs->fs_attach(fs, &root_fd, &qid, 1000, \"\", \"\");\n    assert(err == 0);\n    fs1 = (FSDeviceMem *)fs;\n    fd = fs_walk_path(fs, root_fd, fs1->import_dir);\n    if (!fd)\n        goto fail;\n    fs_unlinkat(fs, root_fd, filename);\n    if (fs->fs_create(fs, &qid, fd, filename, P9_O_RDWR | P9_O_TRUNC,\n                      0600, 0) < 0)\n        goto fail;\n    fs->fs_write(fs, fd, 0, buf, buf_len);\n fail:\n    if (fd)\n        fs->fs_delete(fs, fd);\n    if (root_fd)\n        fs->fs_delete(fs, root_fd);\n    free(buf);\n}\n\n#else\n\nvoid fs_export_file(const char *filename,\n                    const uint8_t *buf, int buf_len)\n{\n}\n\n#endif\n"
  },
  {
    "path": "src/fs_utils.c",
    "content": "/*\n * Misc FS utilities\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <unistd.h>\n#include <time.h>\n#include <ctype.h>\n#include <sys/file.h>\n\n#include \"cutils.h\"\n#include \"list.h\"\n#include \"fs_utils.h\"\n\n/* last byte is the version */\nconst uint8_t encrypted_file_magic[4] = { 0xfb, 0xa2, 0xe9, 0x01 };\n\nchar *compose_path(const char *path, const char *name)\n{\n    int path_len, name_len;\n    char *d, *q;\n\n    if (path[0] == '\\0') {\n        d = strdup(name);\n    } else {\n        path_len = strlen(path);\n        name_len = strlen(name);\n        d = malloc(path_len + 1 + name_len + 1);\n        q = d;\n        memcpy(q, path, path_len);\n        q += path_len;\n        if (path[path_len - 1] != '/')\n            *q++ = '/';\n        memcpy(q, name, name_len + 1);\n    }\n    return d;\n}\n\nchar *compose_url(const char *base_url, const char *name)\n{\n    if (strchr(name, ':')) {\n        return strdup(name);\n    } else {\n        return compose_path(base_url, name);\n    }\n}\n\nvoid skip_line(const char **pp)\n{\n    const char *p;\n    p = *pp;\n    while (*p != '\\n' && *p != '\\0')\n        p++;\n    if (*p == '\\n')\n        p++;\n    *pp = p;\n}\n\nchar *quoted_str(const char *str)\n{\n    const char *s;\n    char *q;\n    int c;\n    char *buf;\n\n    if (str[0] == '\\0')\n        goto use_quote;\n    s = str;\n    while (*s != '\\0') {\n        if (*s <= ' ' || *s > '~')\n            goto use_quote;\n        s++;\n    }\n    return strdup(str);\n use_quote:\n    buf = malloc(strlen(str) * 4 + 2 + 1);\n    q = buf;\n    s = str;\n    *q++ = '\"';\n    while (*s != '\\0') {\n        c = *(uint8_t *)s;\n        if (c < ' ' || c == 127) {\n            q += sprintf(q, \"\\\\x%02x\", c);\n        } else if (c == '\\\\' || c == '\\\"') {\n            q += sprintf(q, \"\\\\%c\", c);\n        } else {\n            *q++ = c;\n        }\n        s++;\n    }\n    *q++ = '\"';\n    *q = '\\0';\n    return buf;\n}\n\nint parse_fname(char *buf, int buf_size, const char **pp)\n{\n    const char *p;\n    char *q;\n    int c, h;\n    \n    p = *pp;\n    while (isspace_nolf(*p))\n        p++;\n    if (*p == '\\0')\n        return -1;\n    q = buf;\n    if (*p == '\"') {\n        p++;\n        for(;;) {\n            c = *p++;\n            if (c == '\\0' || c == '\\n') {\n                return -1;\n            } else if (c == '\\\"') {\n                break;\n            } else if (c == '\\\\') {\n                c = *p++;\n                switch(c) {\n                case '\\'':\n                case '\\\"':\n                case '\\\\':\n                    goto add_char;\n                case 'n':\n                    c = '\\n';\n                    goto add_char;\n                case 'r':\n                    c = '\\r';\n                    goto add_char;\n                case 't':\n                    c = '\\t';\n                    goto add_char;\n                case 'x':\n                    h = from_hex(*p++);\n                    if (h < 0)\n                        return -1;\n                    c = h << 4;\n                    h = from_hex(*p++);\n                    if (h < 0)\n                        return -1;\n                    c |= h;\n                    goto add_char;\n                default:\n                    return -1;\n                }\n            } else {\n            add_char:\n                if (q >= buf + buf_size - 1)\n                    return -1;\n                *q++ = c;\n            }\n        }\n    } else {\n        while (!isspace_nolf(*p) && *p != '\\0' && *p != '\\n') {\n            if (q >= buf + buf_size - 1)\n                return -1;\n            *q++ = *p++;\n        }\n    }\n    *q = '\\0';\n    *pp = p;\n    return 0;\n}\n\nint parse_uint32_base(uint32_t *pval, const char **pp, int base)\n{\n    const char *p, *p1;\n    p = *pp;\n    while (isspace_nolf(*p))\n        p++;\n    *pval = strtoul(p, (char **)&p1, base);\n    if (p1 == p)\n        return -1;\n    *pp = p1;\n    return 0;\n}\n\nint parse_uint64_base(uint64_t *pval, const char **pp, int base)\n{\n    const char *p, *p1;\n    p = *pp;\n    while (isspace_nolf(*p))\n        p++;\n    *pval = strtoull(p, (char **)&p1, base);\n    if (p1 == p)\n        return -1;\n    *pp = p1;\n    return 0;\n}\n\nint parse_uint64(uint64_t *pval, const char **pp)\n{\n    return parse_uint64_base(pval, pp, 0);\n}\n\nint parse_uint32(uint32_t *pval, const char **pp)\n{\n    return parse_uint32_base(pval, pp, 0);\n}\n\nint parse_time(uint32_t *psec, uint32_t *pnsec, const char **pp)\n{\n    const char *p;\n    uint32_t v, m;\n    p = *pp;\n    if (parse_uint32(psec, &p) < 0)\n        return -1;\n    v = 0;\n    if (*p == '.') {\n        p++;\n        /* XXX: inefficient */\n        m = 1000000000;\n        v = 0;\n        while (*p >= '0' && *p <= '9') {\n            m /= 10;\n            v += (*p - '0') * m;\n            p++;\n        }\n    }\n    *pnsec = v;\n    *pp = p;\n    return 0;\n}\n\nint parse_file_id(FSFileID *pval, const char **pp)\n{\n    return parse_uint64_base(pval, pp, 16);\n}\n\nchar *file_id_to_filename(char *buf, FSFileID file_id)\n{\n    sprintf(buf, \"%016\" PRIx64, file_id);\n    return buf;\n}\n\nvoid encode_hex(char *str, const uint8_t *buf, int len)\n{\n    int i;\n    for(i = 0; i < len; i++)\n        sprintf(str + 2 * i, \"%02x\", buf[i]);\n}\n\nint decode_hex(uint8_t *buf, const char *str, int len)\n{\n    int h0, h1, i;\n\n    for(i = 0; i < len; i++) {\n        h0 = from_hex(str[2 * i]);\n        if (h0 < 0)\n            return -1;\n        h1 = from_hex(str[2 * i + 1]);\n        if (h1 < 0)\n            return -1;\n        buf[i] = (h0 << 4) | h1;\n    }\n    return 0;\n}\n\n/* return NULL if no end of header found */\nconst char *skip_header(const char *p)\n{\n    p = strstr(p, \"\\n\\n\");\n    if (!p)\n        return NULL;\n    return p + 2;\n}\n\n/* return 0 if OK, < 0 if error */\nint parse_tag(char *buf, int buf_size, const char *str, const char *tag)\n{\n    char tagname[128], *q;\n    const char *p, *p1;\n    int len;\n    \n    p = str;\n    for(;;) {\n        if (*p == '\\0' || *p == '\\n')\n            break;\n        q = tagname;\n        while (*p != ':' && *p != '\\n' && *p != '\\0') {\n            if ((q - tagname) < sizeof(tagname) - 1)\n                *q++ = *p;\n            p++;\n        }\n        *q = '\\0';\n        if (*p != ':')\n            return -1;\n        p++;\n        while (isspace_nolf(*p))\n            p++;\n        p1 = p;\n        p = strchr(p, '\\n');\n        if (!p)\n            len = strlen(p1);\n        else\n            len = p - p1;\n        if (!strcmp(tagname, tag)) {\n            if (len > buf_size - 1)\n                len = buf_size - 1;\n            memcpy(buf, p1, len);\n            buf[len] = '\\0';\n            return 0;\n        }\n        if (!p)\n            break;\n        else\n            p++;\n    }\n    return -1;\n}\n\nint parse_tag_uint64(uint64_t *pval, const char *str, const char *tag)\n{\n    char buf[64];\n    const char *p;\n    if (parse_tag(buf, sizeof(buf), str, tag))\n        return -1;\n    p = buf;\n    return parse_uint64(pval, &p);\n}\n\nint parse_tag_file_id(FSFileID *pval, const char *str, const char *tag)\n{\n    char buf[64];\n    const char *p;\n    if (parse_tag(buf, sizeof(buf), str, tag))\n        return -1;\n    p = buf;\n    return parse_uint64_base(pval, &p, 16);\n}\n\nint parse_tag_version(const char *str)\n{\n    uint64_t version;\n    if (parse_tag_uint64(&version, str, \"Version\"))\n        return -1;\n    return version;\n}\n\nBOOL is_url(const char *path)\n{\n    return (strstart(path, \"http:\", NULL) ||\n            strstart(path, \"https:\", NULL) ||\n            strstart(path, \"file:\", NULL));\n}\n"
  },
  {
    "path": "src/fs_utils.h",
    "content": "/*\n * Misc FS utilities\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#define HEAD_FILENAME \"head\"\n#define ROOT_FILENAME \"files\"\n\n#define FILEID_SIZE_MAX 32\n\n#define FS_KEY_LEN 16\n\n/* default block size to determine the total filesytem size */\n#define FS_BLOCK_SIZE_LOG2 12\n#define FS_BLOCK_SIZE (1 << FS_BLOCK_SIZE_LOG2)\n\ntypedef enum {\n    FS_ERR_OK = 0,\n    FS_ERR_GENERIC = -1,\n    FS_ERR_SYNTAX = -2,\n    FS_ERR_REVISION = -3,\n    FS_ERR_FILE_ID = -4,\n    FS_ERR_IO = -5,\n    FS_ERR_NOENT = -6,\n    FS_ERR_COUNTERS = -7,\n    FS_ERR_QUOTA = -8,\n    FS_ERR_PROTOCOL_VERSION = -9,\n    FS_ERR_HEAD = -10,\n} FSCommitErrorCode;\n\ntypedef uint64_t FSFileID;\n\nstatic inline BOOL isspace_nolf(int c)\n{\n    return (c == ' ' || c == '\\t');\n}\n\nstatic inline int from_hex(int c)\n{\n    if (c >= '0' && c <= '9')\n        return c - '0';\n    else if (c >= 'A' && c <= 'F')\n        return c - 'A' + 10;\n    else if (c >= 'a' && c <= 'f')\n        return c - 'a' + 10;\n    else\n        return -1;\n}\n\nstatic inline uint64_t block_align(uint64_t val, uint64_t align)\n{\n    return (val + align - 1) & ~(align - 1);\n}\n\nvoid pstrcpy(char *buf, int buf_size, const char *str);\nchar *pstrcat(char *buf, int buf_size, const char *s);\nchar *compose_path(const char *path, const char *name);\nchar *compose_url(const char *base_url, const char *name);\nvoid skip_line(const char **pp);\nchar *quoted_str(const char *str);\nint parse_fname(char *buf, int buf_size, const char **pp);\nint parse_uint32_base(uint32_t *pval, const char **pp, int base);\nint parse_uint64_base(uint64_t *pval, const char **pp, int base);\nint parse_uint64(uint64_t *pval, const char **pp);\nint parse_uint32(uint32_t *pval, const char **pp);\nint parse_time(uint32_t *psec, uint32_t *pnsec, const char **pp);\nint parse_file_id(FSFileID *pval, const char **pp);\nchar *file_id_to_filename(char *buf, FSFileID file_id);\nvoid encode_hex(char *str, const uint8_t *buf, int len);\nint decode_hex(uint8_t *buf, const char *str, int len);\nBOOL is_url(const char *path);\n\nconst char *skip_header(const char *p);\nint parse_tag(char *buf, int buf_size, const char *str, const char *tag);\nint parse_tag_uint64(uint64_t *pval, const char *str, const char *tag);\nint parse_tag_file_id(FSFileID *pval, const char *str, const char *tag);\nint parse_tag_version(const char *str);\n"
  },
  {
    "path": "src/fs_wget.c",
    "content": "/*\n * HTTP file download\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <stdarg.h>\n#include <sys/time.h>\n#include <ctype.h>\n\n#include \"cutils.h\"\n#include \"list.h\"\n#include \"fs.h\"\n#include \"fs_utils.h\"\n#include \"fs_wget.h\"\n\n#if defined(EMSCRIPTEN)\n#include <emscripten.h>\n#else\n#include <curl/multi.h>\n#endif\n\n/***********************************************/\n/* HTTP get */\n\n#ifdef EMSCRIPTEN\n\nstruct XHRState {\n    void *opaque;\n    WGetWriteCallback *cb;\n};\n\nstatic int downloading_count;\n\nvoid fs_wget_init(void)\n{\n}\n\nextern void fs_wget_update_downloading(int flag);\n\nstatic void fs_wget_update_downloading_count(int incr)\n{\n    int prev_state, state;\n    prev_state = (downloading_count > 0);\n    downloading_count += incr;\n    state = (downloading_count > 0);\n    if (prev_state != state)\n        fs_wget_update_downloading(state);\n}\n\nstatic void fs_wget_onerror(unsigned int handle, void *opaque, int status,\n                            const char *status_text)\n{\n    XHRState *s = opaque;\n    if (status <= 0)\n        status = -404; /* HTTP not found error */\n    else\n        status = -status;\n    fs_wget_update_downloading_count(-1);\n    if (s->cb)\n        s->cb(s->opaque, status, NULL, 0);\n}\n\nstatic void fs_wget_onload(unsigned int handle,\n                           void *opaque, void *data, unsigned int size)\n{\n    XHRState *s = opaque;\n    fs_wget_update_downloading_count(-1);\n    if (s->cb)\n        s->cb(s->opaque, 0, data, size);\n}\n\nextern int emscripten_async_wget3_data(const char* url, const char* requesttype, const char *user, const char *password, const uint8_t *post_data, int post_data_len, void *arg, int free, em_async_wget2_data_onload_func onload, em_async_wget2_data_onerror_func onerror, em_async_wget2_data_onprogress_func onprogress);\n\nXHRState *fs_wget2(const char *url, const char *user, const char *password,\n                   WGetReadCallback *read_cb, uint64_t post_data_len,\n                   void *opaque, WGetWriteCallback *cb, BOOL single_write)\n{\n    XHRState *s;\n    const char *request;\n    uint8_t *post_data;\n    \n    s = mallocz(sizeof(*s));\n    s->opaque = opaque;\n    s->cb = cb;\n\n    if (post_data_len != 0) {\n        request = \"POST\";\n        post_data = malloc(post_data_len);\n        read_cb(opaque, post_data, post_data_len);\n    } else {\n        request = \"GET\";\n        post_data = NULL;\n    }\n    fs_wget_update_downloading_count(1);\n\n    emscripten_async_wget3_data(url, request, user, password,\n                                post_data, post_data_len, s, 1, fs_wget_onload,\n                                fs_wget_onerror, NULL);\n    if (post_data_len != 0)\n        free(post_data);\n    return s;\n}\n\nvoid fs_wget_free(XHRState *s)\n{\n    s->cb = NULL;\n    s->opaque = NULL;\n}\n\n#else\n\nstruct XHRState {\n    struct list_head link;\n    CURL *eh;\n    void *opaque;\n    WGetWriteCallback *write_cb;\n    WGetReadCallback *read_cb;\n\n    BOOL single_write;\n    DynBuf dbuf; /* used if single_write */\n};\n\ntypedef struct {\n    struct list_head link;\n    int64_t timeout;\n    void (*cb)(void *opaque);\n    void *opaque;\n} AsyncCallState;\n\nstatic CURLM *curl_multi_ctx;\nstatic struct list_head xhr_list; /* list of XHRState.link */\n\nvoid fs_wget_init(void)\n{\n    if (curl_multi_ctx)\n        return;\n    curl_global_init(CURL_GLOBAL_ALL);\n    curl_multi_ctx = curl_multi_init();\n    init_list_head(&xhr_list);\n}\n\nvoid fs_wget_end(void)\n{\n    curl_multi_cleanup(curl_multi_ctx);\n    curl_global_cleanup();\n}\n\nstatic size_t fs_wget_write_cb(char *ptr, size_t size, size_t nmemb,\n                               void *userdata)\n{\n    XHRState *s = userdata;\n    size *= nmemb;\n\n    if (s->single_write) {\n        dbuf_write(&s->dbuf, s->dbuf.size, (void *)ptr, size);\n    } else {\n        s->write_cb(s->opaque, 1, ptr, size);\n    }\n    return size;\n}\n\nstatic size_t fs_wget_read_cb(char *ptr, size_t size, size_t nmemb,\n                              void *userdata)\n{\n    XHRState *s = userdata;\n    size *= nmemb;\n    return s->read_cb(s->opaque, ptr, size);\n}\n\nXHRState *fs_wget2(const char *url, const char *user, const char *password,\n                   WGetReadCallback *read_cb, uint64_t post_data_len,\n                   void *opaque, WGetWriteCallback *write_cb, BOOL single_write)\n{\n    XHRState *s;\n    s = mallocz(sizeof(*s));\n    s->eh = curl_easy_init();\n    s->opaque = opaque;\n    s->write_cb = write_cb;\n    s->read_cb = read_cb;\n    s->single_write = single_write;\n    dbuf_init(&s->dbuf);\n    \n    curl_easy_setopt(s->eh, CURLOPT_PRIVATE, s);\n    curl_easy_setopt(s->eh, CURLOPT_WRITEDATA, s);\n    curl_easy_setopt(s->eh, CURLOPT_WRITEFUNCTION, fs_wget_write_cb);\n    curl_easy_setopt(s->eh, CURLOPT_HEADER, 0);\n    curl_easy_setopt(s->eh, CURLOPT_URL, url);\n    curl_easy_setopt(s->eh, CURLOPT_VERBOSE, 0L);\n    curl_easy_setopt(s->eh, CURLOPT_ACCEPT_ENCODING, \"\");\n    if (user) {\n        curl_easy_setopt(s->eh, CURLOPT_USERNAME, user);\n        curl_easy_setopt(s->eh, CURLOPT_PASSWORD, password);\n    }\n    if (post_data_len != 0) {\n        struct curl_slist *headers = NULL;\n        headers = curl_slist_append(headers,\n                                    \"Content-Type: application/octet-stream\");\n        curl_easy_setopt(s->eh, CURLOPT_HTTPHEADER, headers);\n        curl_easy_setopt(s->eh, CURLOPT_POST, 1L);\n        curl_easy_setopt(s->eh, CURLOPT_POSTFIELDSIZE_LARGE,\n                         (curl_off_t)post_data_len);\n        curl_easy_setopt(s->eh, CURLOPT_READDATA, s);\n        curl_easy_setopt(s->eh, CURLOPT_READFUNCTION, fs_wget_read_cb);\n    }\n    curl_multi_add_handle(curl_multi_ctx, s->eh);\n    list_add_tail(&s->link, &xhr_list);\n    return s;\n}\n\nvoid fs_wget_free(XHRState *s)\n{\n    dbuf_free(&s->dbuf);\n    curl_easy_cleanup(s->eh);\n    list_del(&s->link);\n    free(s);\n}\n\n/* timeout is in ms */\nvoid fs_net_set_fdset(int *pfd_max, fd_set *rfds, fd_set *wfds, fd_set *efds,\n                      int *ptimeout)\n{\n    long timeout;\n    int n, fd_max;\n    CURLMsg *msg;\n    \n    if (!curl_multi_ctx)\n        return;\n    \n    curl_multi_perform(curl_multi_ctx, &n);\n\n    for(;;) {\n        msg = curl_multi_info_read(curl_multi_ctx, &n);\n        if (!msg)\n            break;\n        if (msg->msg == CURLMSG_DONE) {\n            XHRState *s;\n            long http_code;\n\n            curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char **)&s);\n            curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE,\n                              &http_code);\n            /* signal the end of the transfer or error */\n            if (http_code == 200) {\n                if (s->single_write) {\n                    s->write_cb(s->opaque, 0, s->dbuf.buf, s->dbuf.size);\n                } else {\n                    s->write_cb(s->opaque, 0, NULL, 0);\n                }\n            } else {\n                s->write_cb(s->opaque, -http_code, NULL, 0);\n            }\n            curl_multi_remove_handle(curl_multi_ctx, s->eh);\n            curl_easy_cleanup(s->eh);\n            dbuf_free(&s->dbuf);\n            list_del(&s->link);\n            free(s);\n        }\n    }\n\n    curl_multi_fdset(curl_multi_ctx, rfds, wfds, efds, &fd_max);\n    *pfd_max = max_int(*pfd_max, fd_max);\n    curl_multi_timeout(curl_multi_ctx, &timeout);\n    if (timeout >= 0)\n        *ptimeout = min_int(*ptimeout, timeout);\n}\n\nvoid fs_net_event_loop(FSNetEventLoopCompletionFunc *cb, void *opaque)\n{\n    fd_set rfds, wfds, efds;\n    int timeout, fd_max;\n    struct timeval tv;\n    \n    if (!curl_multi_ctx)\n        return;\n\n    for(;;) {\n        fd_max = -1;\n        FD_ZERO(&rfds);\n        FD_ZERO(&wfds);\n        FD_ZERO(&efds);\n        timeout = 10000;\n        fs_net_set_fdset(&fd_max, &rfds, &wfds, &efds, &timeout);\n        if (cb) {\n            if (cb(opaque))\n                break;\n        } else {\n            if (list_empty(&xhr_list))\n                break;\n        }\n        tv.tv_sec = timeout / 1000;\n        tv.tv_usec = (timeout % 1000) * 1000;\n        select(fd_max + 1, &rfds, &wfds, &efds, &tv);\n    }\n}\n\n#endif /* !EMSCRIPTEN */\n\nXHRState *fs_wget(const char *url, const char *user, const char *password,\n                  void *opaque, WGetWriteCallback *cb, BOOL single_write)\n{\n    return fs_wget2(url, user, password, NULL, 0, opaque, cb, single_write);\n}\n\n/***********************************************/\n/* file decryption */\n\n#define ENCRYPTED_FILE_HEADER_SIZE (4 + AES_BLOCK_SIZE)\n\n#define DEC_BUF_SIZE (256 * AES_BLOCK_SIZE)\n\nstruct DecryptFileState {\n    DecryptFileCB *write_cb;\n    void *opaque;\n    int dec_state;\n    int dec_buf_pos;\n    AES_KEY *aes_state;\n    uint8_t iv[AES_BLOCK_SIZE];\n    uint8_t dec_buf[DEC_BUF_SIZE];\n};\n\nDecryptFileState *decrypt_file_init(AES_KEY *aes_state,\n                                    DecryptFileCB *write_cb,\n                                    void *opaque)\n{\n    DecryptFileState *s;\n    s = mallocz(sizeof(*s));\n    s->write_cb = write_cb;\n    s->opaque = opaque;\n    s->aes_state = aes_state;\n    return s;\n}\n    \nint decrypt_file(DecryptFileState *s, const uint8_t *data,\n                 size_t size)\n{\n    int l, len, ret;\n\n    while (size != 0) {\n        switch(s->dec_state) {\n        case 0:\n            l = min_int(size, ENCRYPTED_FILE_HEADER_SIZE - s->dec_buf_pos);\n            memcpy(s->dec_buf + s->dec_buf_pos, data, l);\n            s->dec_buf_pos += l;\n            if (s->dec_buf_pos >= ENCRYPTED_FILE_HEADER_SIZE) {\n                if (memcmp(s->dec_buf, encrypted_file_magic, 4) != 0)\n                    return -1;\n                memcpy(s->iv, s->dec_buf + 4, AES_BLOCK_SIZE);\n                s->dec_state = 1;\n                s->dec_buf_pos = 0;\n            }\n            break;\n        case 1:\n            l = min_int(size, DEC_BUF_SIZE - s->dec_buf_pos);\n            memcpy(s->dec_buf + s->dec_buf_pos, data, l);\n            s->dec_buf_pos += l;\n            if (s->dec_buf_pos >= DEC_BUF_SIZE) {\n                /* keep one block in case it is the padding */\n                len = s->dec_buf_pos - AES_BLOCK_SIZE;\n                AES_cbc_encrypt(s->dec_buf, s->dec_buf, len,\n                                s->aes_state, s->iv, FALSE);\n                ret = s->write_cb(s->opaque, s->dec_buf, len);\n                if (ret < 0)\n                    return ret;\n                memcpy(s->dec_buf, s->dec_buf + s->dec_buf_pos - AES_BLOCK_SIZE,\n                       AES_BLOCK_SIZE);\n                s->dec_buf_pos = AES_BLOCK_SIZE;\n            }\n            break;\n        default:\n            abort();\n        }\n        data += l;\n        size -= l;\n    }\n    return 0;\n}\n\n/* write last blocks */\nint decrypt_file_flush(DecryptFileState *s)\n{\n    int len, pad_len, ret;\n\n    if (s->dec_state != 1)\n        return -1;\n    len = s->dec_buf_pos;\n    if (len == 0 || \n        (len % AES_BLOCK_SIZE) != 0)\n        return -1;\n    AES_cbc_encrypt(s->dec_buf, s->dec_buf, len,\n                    s->aes_state, s->iv, FALSE);\n    pad_len = s->dec_buf[s->dec_buf_pos - 1];\n    if (pad_len < 1 || pad_len > AES_BLOCK_SIZE)\n        return -1;\n    len -= pad_len;\n    if (len != 0) {\n        ret = s->write_cb(s->opaque, s->dec_buf, len);\n        if (ret < 0)\n            return ret;\n    }\n    return 0;\n}\n\nvoid decrypt_file_end(DecryptFileState *s)\n{\n    free(s);\n}\n\n/* XHR file */\n\ntypedef struct {\n    FSDevice *fs;\n    FSFile *f;\n    int64_t pos;\n    FSWGetFileCB *cb;\n    void *opaque;\n    FSFile *posted_file;\n    int64_t read_pos;\n    DecryptFileState *dec_state;\n} FSWGetFileState;\n\nstatic int fs_wget_file_write_cb(void *opaque, const uint8_t *data,\n                                 size_t size)\n{\n    FSWGetFileState *s = opaque;\n    FSDevice *fs = s->fs;\n    int ret;\n\n    ret = fs->fs_write(fs, s->f, s->pos, data, size);\n    if (ret < 0)\n        return ret;\n    s->pos += ret;\n    return ret;\n}\n\nstatic void fs_wget_file_on_load(void *opaque, int err, void *data, size_t size)\n{\n    FSWGetFileState *s = opaque;\n    FSDevice *fs = s->fs;\n    int ret;\n    int64_t ret_size;\n    \n    //    printf(\"err=%d size=%ld\\n\", err, size);\n    if (err < 0) {\n        ret_size = err;\n        goto done;\n    } else {\n        if (s->dec_state) {\n            ret = decrypt_file(s->dec_state, data, size);\n            if (ret >= 0 && err == 0) {\n                /* handle the end of file */\n                decrypt_file_flush(s->dec_state);\n            }\n        } else {\n            ret = fs_wget_file_write_cb(s, data, size);\n        }\n        if (ret < 0) {\n            ret_size = ret;\n            goto done;\n        } else if (err == 0) {\n            /* end of transfer */\n            ret_size = s->pos;\n        done:\n            s->cb(fs, s->f, ret_size, s->opaque);\n            if (s->dec_state)\n                decrypt_file_end(s->dec_state);\n            free(s);\n        }\n    }\n}\n\nstatic size_t fs_wget_file_read_cb(void *opaque, void *data, size_t size)\n{\n    FSWGetFileState *s = opaque;\n    FSDevice *fs = s->fs;\n    int ret;\n    \n    if (!s->posted_file)\n        return 0;\n    ret = fs->fs_read(fs, s->posted_file, s->read_pos, data, size);\n    if (ret < 0)\n        return 0;\n    s->read_pos += ret;\n    return ret;\n}\n\nvoid fs_wget_file2(FSDevice *fs, FSFile *f, const char *url,\n                   const char *user, const char *password,\n                   FSFile *posted_file, uint64_t post_data_len,\n                   FSWGetFileCB *cb, void *opaque,\n                   AES_KEY *aes_state)\n{\n    FSWGetFileState *s;\n    s = mallocz(sizeof(*s));\n    s->fs = fs;\n    s->f = f;\n    s->pos = 0;\n    s->cb = cb;\n    s->opaque = opaque;\n    s->posted_file = posted_file;\n    s->read_pos = 0;\n    if (aes_state) {\n        s->dec_state = decrypt_file_init(aes_state, fs_wget_file_write_cb, s);\n    }\n    \n    fs_wget2(url, user, password, fs_wget_file_read_cb, post_data_len,\n             s, fs_wget_file_on_load, FALSE);\n}\n\n/***********************************************/\n/* PBKDF2 */\n\n#ifdef USE_BUILTIN_CRYPTO\n\n#define HMAC_BLOCK_SIZE 64\n\ntypedef struct {\n    SHA256_CTX ctx;\n    uint8_t K[HMAC_BLOCK_SIZE + SHA256_DIGEST_LENGTH];\n} HMAC_SHA256_CTX;\n\nvoid hmac_sha256_init(HMAC_SHA256_CTX *s, const uint8_t *key, int key_len)\n{\n    int i, l;\n    \n    if (key_len > HMAC_BLOCK_SIZE) {\n        SHA256(key, key_len, s->K);\n        l = SHA256_DIGEST_LENGTH;\n    } else {\n        memcpy(s->K, key, key_len);\n        l = key_len;\n    }\n    memset(s->K + l, 0, HMAC_BLOCK_SIZE - l);\n    for(i = 0; i < HMAC_BLOCK_SIZE; i++)\n        s->K[i] ^= 0x36;\n    SHA256_Init(&s->ctx);\n    SHA256_Update(&s->ctx, s->K, HMAC_BLOCK_SIZE);\n}\n\nvoid hmac_sha256_update(HMAC_SHA256_CTX *s, const uint8_t *buf, int len)\n{\n    SHA256_Update(&s->ctx, buf, len);\n}\n\n/* out has a length of SHA256_DIGEST_LENGTH */\nvoid hmac_sha256_final(HMAC_SHA256_CTX *s, uint8_t *out)\n{\n    int i;\n    \n    SHA256_Final(s->K + HMAC_BLOCK_SIZE, &s->ctx);\n    for(i = 0; i < HMAC_BLOCK_SIZE; i++)\n        s->K[i] ^= (0x36 ^ 0x5c);\n    SHA256(s->K, HMAC_BLOCK_SIZE + SHA256_DIGEST_LENGTH, out);\n}\n\n#define SALT_LEN_MAX 32\n\nvoid pbkdf2_hmac_sha256(const uint8_t *pwd, int pwd_len,\n                        const uint8_t *salt, int salt_len,\n                        int iter, int key_len, uint8_t *out)\n{\n    uint8_t F[SHA256_DIGEST_LENGTH], U[SALT_LEN_MAX + 4];\n    HMAC_SHA256_CTX ctx;\n    int it, U_len, j, l;\n    uint32_t i;\n    \n    assert(salt_len <= SALT_LEN_MAX);\n    i = 1;\n    while (key_len > 0) {\n        memset(F, 0, SHA256_DIGEST_LENGTH);\n        memcpy(U, salt, salt_len);\n        U[salt_len] = i >> 24;\n        U[salt_len + 1] = i >> 16;\n        U[salt_len + 2] = i >> 8;\n        U[salt_len + 3] = i;\n        U_len = salt_len + 4;\n        for(it = 0; it < iter; it++) {\n            hmac_sha256_init(&ctx, pwd, pwd_len);\n            hmac_sha256_update(&ctx, U, U_len);\n            hmac_sha256_final(&ctx, U);\n            for(j = 0; j < SHA256_DIGEST_LENGTH; j++)\n                F[j] ^= U[j];\n            U_len = SHA256_DIGEST_LENGTH;\n        }\n        l = min_int(key_len, SHA256_DIGEST_LENGTH);\n        memcpy(out, F, l);\n        out += l;\n        key_len -= l;\n        i++;\n    }\n}\n\n#else\n\nvoid pbkdf2_hmac_sha256(const uint8_t *pwd, int pwd_len,\n                        const uint8_t *salt, int salt_len,\n                        int iter, int key_len, uint8_t *out)\n{\n    PKCS5_PBKDF2_HMAC((const char *)pwd, pwd_len, salt, salt_len,\n                      iter, EVP_sha256(), key_len, out);\n}\n\n#endif /* !USE_BUILTIN_CRYPTO */\n"
  },
  {
    "path": "src/fs_wget.h",
    "content": "/*\n * HTTP file download\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#if defined(EMSCRIPTEN)\n#define USE_BUILTIN_CRYPTO\n#endif\n\n#ifdef USE_BUILTIN_CRYPTO\n#include \"aes.h\"\n#include \"sha256.h\"\n#else\n#include <openssl/aes.h>\n#include <openssl/sha.h>\n#include <openssl/evp.h>\n#endif\n#ifdef _WIN32\n#include <winsock2.h>\n#endif\n\n#define LOG() printf(\"%s:%d\\n\", __func__, __LINE__)\n\n/* XHR */\n\n/* err < 0: error (no data provided)\n   err = 0: end of transfer (data can be provided too)\n   err = 1: data chunk\n*/\ntypedef void WGetWriteCallback(void *opaque, int err, void *data, size_t size);\ntypedef size_t WGetReadCallback(void *opaque, void *data, size_t size);\ntypedef struct XHRState XHRState;\n\nXHRState *fs_wget(const char *url, const char *user, const char *password,\n                  void *opaque, WGetWriteCallback *cb, BOOL single_write);\nvoid fs_wget_free(XHRState *s);\n\nvoid fs_wget_init(void);\nvoid fs_wget_end(void);\n\n#ifndef EMSCRIPTEN\ntypedef BOOL FSNetEventLoopCompletionFunc(void *opaque);\nvoid fs_net_set_fdset(int *pfd_max, fd_set *rfds, fd_set *wfds, fd_set *efds,\n                      int *ptimeout);\nvoid fs_net_event_loop(FSNetEventLoopCompletionFunc *cb, void *opaque);\n#endif\n\n/* crypto */\n\nextern const uint8_t encrypted_file_magic[4];\n\ntypedef int DecryptFileCB(void *opaque, const uint8_t *data, size_t len);\ntypedef struct DecryptFileState DecryptFileState;\n\nDecryptFileState *decrypt_file_init(AES_KEY *aes_state,\n                                    DecryptFileCB *write_cb,\n                                    void *opaque);\nint decrypt_file(DecryptFileState *s, const uint8_t *data,\n                 size_t size);\nint decrypt_file_flush(DecryptFileState *s);\nvoid decrypt_file_end(DecryptFileState *s);\n\nvoid pbkdf2_hmac_sha256(const uint8_t *pwd, int pwd_len,\n                        const uint8_t *salt, int salt_len,\n                        int iter, int key_len, uint8_t *out);\n\n/* XHR file */\n\ntypedef void FSWGetFileCB(FSDevice *fs, FSFile *f, int64_t size, void *opaque);\n\nvoid fs_wget_file2(FSDevice *fs, FSFile *f, const char *url,\n                   const char *user, const char *password,\n                   FSFile *posted_file, uint64_t post_data_len,\n                   FSWGetFileCB *cb, void *opaque,\n                   AES_KEY *aes_state);\n"
  },
  {
    "path": "src/ide.c",
    "content": "/*\n * IDE emulation\n * \n * Copyright (c) 2003-2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n\n#include \"cutils.h\"\n#include \"ide.h\"\n\n//#define DEBUG_IDE\n\n/* Bits of HD_STATUS */\n#define ERR_STAT\t\t0x01\n#define INDEX_STAT\t\t0x02\n#define ECC_STAT\t\t0x04\t/* Corrected error */\n#define DRQ_STAT\t\t0x08\n#define SEEK_STAT\t\t0x10\n#define SRV_STAT\t\t0x10\n#define WRERR_STAT\t\t0x20\n#define READY_STAT\t\t0x40\n#define BUSY_STAT\t\t0x80\n\n/* Bits for HD_ERROR */\n#define MARK_ERR\t\t0x01\t/* Bad address mark */\n#define TRK0_ERR\t\t0x02\t/* couldn't find track 0 */\n#define ABRT_ERR\t\t0x04\t/* Command aborted */\n#define MCR_ERR\t\t\t0x08\t/* media change request */\n#define ID_ERR\t\t\t0x10\t/* ID field not found */\n#define MC_ERR\t\t\t0x20\t/* media changed */\n#define ECC_ERR\t\t\t0x40\t/* Uncorrectable ECC error */\n#define BBD_ERR\t\t\t0x80\t/* pre-EIDE meaning:  block marked bad */\n#define ICRC_ERR\t\t0x80\t/* new meaning:  CRC error during transfer */\n\n/* Bits of HD_NSECTOR */\n#define CD\t\t\t0x01\n#define IO\t\t\t0x02\n#define REL\t\t\t0x04\n#define TAG_MASK\t\t0xf8\n\n#define IDE_CMD_RESET           0x04\n#define IDE_CMD_DISABLE_IRQ     0x02\n\n/* ATA/ATAPI Commands pre T13 Spec */\n#define WIN_NOP\t\t\t\t0x00\n/*\n *\t0x01->0x02 Reserved\n */\n#define CFA_REQ_EXT_ERROR_CODE\t\t0x03 /* CFA Request Extended Error Code */\n/*\n *\t0x04->0x07 Reserved\n */\n#define WIN_SRST\t\t\t0x08 /* ATAPI soft reset command */\n#define WIN_DEVICE_RESET\t\t0x08\n/*\n *\t0x09->0x0F Reserved\n */\n#define WIN_RECAL\t\t\t0x10\n#define WIN_RESTORE\t\t\tWIN_RECAL\n/*\n *\t0x10->0x1F Reserved\n */\n#define WIN_READ\t\t\t0x20 /* 28-Bit */\n#define WIN_READ_ONCE\t\t\t0x21 /* 28-Bit without retries */\n#define WIN_READ_LONG\t\t\t0x22 /* 28-Bit */\n#define WIN_READ_LONG_ONCE\t\t0x23 /* 28-Bit without retries */\n#define WIN_READ_EXT\t\t\t0x24 /* 48-Bit */\n#define WIN_READDMA_EXT\t\t\t0x25 /* 48-Bit */\n#define WIN_READDMA_QUEUED_EXT\t\t0x26 /* 48-Bit */\n#define WIN_READ_NATIVE_MAX_EXT\t\t0x27 /* 48-Bit */\n/*\n *\t0x28\n */\n#define WIN_MULTREAD_EXT\t\t0x29 /* 48-Bit */\n/*\n *\t0x2A->0x2F Reserved\n */\n#define WIN_WRITE\t\t\t0x30 /* 28-Bit */\n#define WIN_WRITE_ONCE\t\t\t0x31 /* 28-Bit without retries */\n#define WIN_WRITE_LONG\t\t\t0x32 /* 28-Bit */\n#define WIN_WRITE_LONG_ONCE\t\t0x33 /* 28-Bit without retries */\n#define WIN_WRITE_EXT\t\t\t0x34 /* 48-Bit */\n#define WIN_WRITEDMA_EXT\t\t0x35 /* 48-Bit */\n#define WIN_WRITEDMA_QUEUED_EXT\t\t0x36 /* 48-Bit */\n#define WIN_SET_MAX_EXT\t\t\t0x37 /* 48-Bit */\n#define CFA_WRITE_SECT_WO_ERASE\t\t0x38 /* CFA Write Sectors without erase */\n#define WIN_MULTWRITE_EXT\t\t0x39 /* 48-Bit */\n/*\n *\t0x3A->0x3B Reserved\n */\n#define WIN_WRITE_VERIFY\t\t0x3C /* 28-Bit */\n/*\n *\t0x3D->0x3F Reserved\n */\n#define WIN_VERIFY\t\t\t0x40 /* 28-Bit - Read Verify Sectors */\n#define WIN_VERIFY_ONCE\t\t\t0x41 /* 28-Bit - without retries */\n#define WIN_VERIFY_EXT\t\t\t0x42 /* 48-Bit */\n/*\n *\t0x43->0x4F Reserved\n */\n#define WIN_FORMAT\t\t\t0x50\n/*\n *\t0x51->0x5F Reserved\n */\n#define WIN_INIT\t\t\t0x60\n/*\n *\t0x61->0x5F Reserved\n */\n#define WIN_SEEK\t\t\t0x70 /* 0x70-0x7F Reserved */\n#define CFA_TRANSLATE_SECTOR\t\t0x87 /* CFA Translate Sector */\n#define WIN_DIAGNOSE\t\t\t0x90\n#define WIN_SPECIFY\t\t\t0x91 /* set drive geometry translation */\n#define WIN_DOWNLOAD_MICROCODE\t\t0x92\n#define WIN_STANDBYNOW2\t\t\t0x94\n#define WIN_STANDBY2\t\t\t0x96\n#define WIN_SETIDLE2\t\t\t0x97\n#define WIN_CHECKPOWERMODE2\t\t0x98\n#define WIN_SLEEPNOW2\t\t\t0x99\n/*\n *\t0x9A VENDOR\n */\n#define WIN_PACKETCMD\t\t\t0xA0 /* Send a packet command. */\n#define WIN_PIDENTIFY\t\t\t0xA1 /* identify ATAPI device\t*/\n#define WIN_QUEUED_SERVICE\t\t0xA2\n#define WIN_SMART\t\t\t0xB0 /* self-monitoring and reporting */\n#define CFA_ERASE_SECTORS       \t0xC0\n#define WIN_MULTREAD\t\t\t0xC4 /* read sectors using multiple mode*/\n#define WIN_MULTWRITE\t\t\t0xC5 /* write sectors using multiple mode */\n#define WIN_SETMULT\t\t\t0xC6 /* enable/disable multiple mode */\n#define WIN_READDMA_QUEUED\t\t0xC7 /* read sectors using Queued DMA transfers */\n#define WIN_READDMA\t\t\t0xC8 /* read sectors using DMA transfers */\n#define WIN_READDMA_ONCE\t\t0xC9 /* 28-Bit - without retries */\n#define WIN_WRITEDMA\t\t\t0xCA /* write sectors using DMA transfers */\n#define WIN_WRITEDMA_ONCE\t\t0xCB /* 28-Bit - without retries */\n#define WIN_WRITEDMA_QUEUED\t\t0xCC /* write sectors using Queued DMA transfers */\n#define CFA_WRITE_MULTI_WO_ERASE\t0xCD /* CFA Write multiple without erase */\n#define WIN_GETMEDIASTATUS\t\t0xDA\t\n#define WIN_ACKMEDIACHANGE\t\t0xDB /* ATA-1, ATA-2 vendor */\n#define WIN_POSTBOOT\t\t\t0xDC\n#define WIN_PREBOOT\t\t\t0xDD\n#define WIN_DOORLOCK\t\t\t0xDE /* lock door on removable drives */\n#define WIN_DOORUNLOCK\t\t\t0xDF /* unlock door on removable drives */\n#define WIN_STANDBYNOW1\t\t\t0xE0\n#define WIN_IDLEIMMEDIATE\t\t0xE1 /* force drive to become \"ready\" */\n#define WIN_STANDBY             \t0xE2 /* Set device in Standby Mode */\n#define WIN_SETIDLE1\t\t\t0xE3\n#define WIN_READ_BUFFER\t\t\t0xE4 /* force read only 1 sector */\n#define WIN_CHECKPOWERMODE1\t\t0xE5\n#define WIN_SLEEPNOW1\t\t\t0xE6\n#define WIN_FLUSH_CACHE\t\t\t0xE7\n#define WIN_WRITE_BUFFER\t\t0xE8 /* force write only 1 sector */\n#define WIN_WRITE_SAME\t\t\t0xE9 /* read ata-2 to use */\n\t/* SET_FEATURES 0x22 or 0xDD */\n#define WIN_FLUSH_CACHE_EXT\t\t0xEA /* 48-Bit */\n#define WIN_IDENTIFY\t\t\t0xEC /* ask drive to identify itself\t*/\n#define WIN_MEDIAEJECT\t\t\t0xED\n#define WIN_IDENTIFY_DMA\t\t0xEE /* same as WIN_IDENTIFY, but DMA */\n#define WIN_SETFEATURES\t\t\t0xEF /* set special drive features */\n#define EXABYTE_ENABLE_NEST\t\t0xF0\n#define WIN_SECURITY_SET_PASS\t\t0xF1\n#define WIN_SECURITY_UNLOCK\t\t0xF2\n#define WIN_SECURITY_ERASE_PREPARE\t0xF3\n#define WIN_SECURITY_ERASE_UNIT\t\t0xF4\n#define WIN_SECURITY_FREEZE_LOCK\t0xF5\n#define WIN_SECURITY_DISABLE\t\t0xF6\n#define WIN_READ_NATIVE_MAX\t\t0xF8 /* return the native maximum address */\n#define WIN_SET_MAX\t\t\t0xF9\n#define DISABLE_SEAGATE\t\t\t0xFB\n\n#define MAX_MULT_SECTORS 128\n\ntypedef struct IDEState IDEState;\n\ntypedef void EndTransferFunc(IDEState *);\n\nstruct IDEState {\n    IDEIFState *ide_if;\n    BlockDevice *bs;\n    int cylinders, heads, sectors;\n    int mult_sectors;\n    int64_t nb_sectors;\n\n    /* ide regs */\n    uint8_t feature;\n    uint8_t error;\n    uint16_t nsector; /* 0 is 256 to ease computations */\n    uint8_t sector;\n    uint8_t lcyl;\n    uint8_t hcyl;\n    uint8_t select;\n    uint8_t status;\n\n    int io_nb_sectors;\n    int req_nb_sectors;\n    EndTransferFunc *end_transfer_func;\n    \n    int data_index;\n    int data_end;\n    uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4];\n};\n\nstruct IDEIFState {\n    IRQSignal *irq;\n    IDEState *cur_drive;\n    IDEState *drives[2];\n    /* 0x3f6 command */\n    uint8_t cmd;\n};\n\nstatic void ide_sector_read_cb(void *opaque, int ret);\nstatic void ide_sector_read_cb_end(IDEState *s);\nstatic void ide_sector_write_cb2(void *opaque, int ret);\n\nstatic void padstr(char *str, const char *src, int len)\n{\n    int i, v;\n    for(i = 0; i < len; i++) {\n        if (*src)\n            v = *src++;\n        else\n            v = ' ';\n        *(char *)((long)str ^ 1) = v;\n        str++;\n    }\n}\n\n/* little endian assume */\nstatic void stw(uint16_t *buf, int v)\n{\n    *buf = v;\n}\n\nstatic void ide_identify(IDEState *s)\n{\n    uint16_t *tab;\n    uint32_t oldsize;\n    \n    tab = (uint16_t *)s->io_buffer;\n\n    memset(tab, 0, 512 * 2);\n\n    stw(tab + 0, 0x0040);\n    stw(tab + 1, s->cylinders); \n    stw(tab + 3, s->heads);\n    stw(tab + 4, 512 * s->sectors); /* sectors */\n    stw(tab + 5, 512); /* sector size */\n    stw(tab + 6, s->sectors); \n    stw(tab + 20, 3); /* buffer type */\n    stw(tab + 21, 512); /* cache size in sectors */\n    stw(tab + 22, 4); /* ecc bytes */\n    padstr((char *)(tab + 27), \"RISCVEMU HARDDISK\", 40);\n    stw(tab + 47, 0x8000 | MAX_MULT_SECTORS);\n    stw(tab + 48, 0); /* dword I/O */\n    stw(tab + 49, 1 << 9); /* LBA supported, no DMA */\n    stw(tab + 51, 0x200); /* PIO transfer cycle */\n    stw(tab + 52, 0x200); /* DMA transfer cycle */\n    stw(tab + 54, s->cylinders);\n    stw(tab + 55, s->heads);\n    stw(tab + 56, s->sectors);\n    oldsize = s->cylinders * s->heads * s->sectors;\n    stw(tab + 57, oldsize);\n    stw(tab + 58, oldsize >> 16);\n    if (s->mult_sectors)\n        stw(tab + 59, 0x100 | s->mult_sectors);\n    stw(tab + 60, s->nb_sectors);\n    stw(tab + 61, s->nb_sectors >> 16);\n    stw(tab + 80, (1 << 1) | (1 << 2));\n    stw(tab + 82, (1 << 14));\n    stw(tab + 83, (1 << 14));\n    stw(tab + 84, (1 << 14));\n    stw(tab + 85, (1 << 14));\n    stw(tab + 86, 0);\n    stw(tab + 87, (1 << 14));\n}\n\nstatic void ide_set_signature(IDEState *s) \n{\n    s->select &= 0xf0;\n    s->nsector = 1;\n    s->sector = 1;\n    s->lcyl = 0;\n    s->hcyl = 0;\n}\n\nstatic void ide_abort_command(IDEState *s) \n{\n    s->status = READY_STAT | ERR_STAT;\n    s->error = ABRT_ERR;\n}\n\nstatic void ide_set_irq(IDEState *s) \n{\n    IDEIFState *ide_if = s->ide_if;\n    if (!(ide_if->cmd & IDE_CMD_DISABLE_IRQ)) {\n        set_irq(ide_if->irq, 1);\n    }\n}\n\n/* prepare data transfer and tell what to do after */\nstatic void ide_transfer_start(IDEState *s, int size,\n                               EndTransferFunc *end_transfer_func)\n{\n    s->end_transfer_func = end_transfer_func;\n    s->data_index = 0;\n    s->data_end = size;\n}\n\nstatic void ide_transfer_stop(IDEState *s)\n{\n    s->end_transfer_func = ide_transfer_stop;\n    s->data_index = 0;\n    s->data_end = 0;\n}\n\nstatic int64_t ide_get_sector(IDEState *s)\n{\n    int64_t sector_num;\n    if (s->select & 0x40) {\n        /* lba */\n        sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |\n            (s->lcyl << 8) | s->sector;\n    } else {\n        sector_num = ((s->hcyl << 8) | s->lcyl) * \n            s->heads * s->sectors +\n            (s->select & 0x0f) * s->sectors + (s->sector - 1);\n    }\n    return sector_num;\n}\n\nstatic void ide_set_sector(IDEState *s, int64_t sector_num)\n{\n    unsigned int cyl, r;\n    if (s->select & 0x40) {\n        s->select = (s->select & 0xf0) | ((sector_num >> 24) & 0x0f);\n        s->hcyl = (sector_num >> 16) & 0xff;\n        s->lcyl = (sector_num >> 8) & 0xff;\n        s->sector = sector_num & 0xff;\n    } else {\n        cyl = sector_num / (s->heads * s->sectors);\n        r = sector_num % (s->heads * s->sectors);\n        s->hcyl = (cyl >> 8) & 0xff;\n        s->lcyl = cyl & 0xff;\n        s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f);\n        s->sector = (r % s->sectors) + 1;\n    }\n}\n\nstatic void ide_sector_read(IDEState *s)\n{\n    int64_t sector_num;\n    int ret, n;\n\n    sector_num = ide_get_sector(s);\n    n = s->nsector;\n    if (n == 0) \n        n = 256;\n    if (n > s->req_nb_sectors)\n        n = s->req_nb_sectors;\n#if defined(DEBUG_IDE)\n    printf(\"read sector=%\" PRId64 \" count=%d\\n\", sector_num, n);\n#endif\n    s->io_nb_sectors = n;\n    ret = s->bs->read_async(s->bs, sector_num, s->io_buffer, n, \n                            ide_sector_read_cb, s);\n    if (ret < 0) {\n        /* error */\n        ide_abort_command(s);\n        ide_set_irq(s);\n    } else if (ret == 0) {\n        /* synchronous case (needed for performance) */\n        ide_sector_read_cb(s, 0);\n    } else {\n        /* async case */\n        s->status = READY_STAT | SEEK_STAT | BUSY_STAT;\n        s->error = 0; /* not needed by IDE spec, but needed by Windows */\n    }\n}\n\nstatic void ide_sector_read_cb(void *opaque, int ret)\n{\n    IDEState *s = opaque;\n    int n;\n    EndTransferFunc *func;\n    \n    n = s->io_nb_sectors;\n    ide_set_sector(s, ide_get_sector(s) + n);\n    s->nsector = (s->nsector - n) & 0xff;\n    if (s->nsector == 0)\n        func = ide_sector_read_cb_end;\n    else\n        func = ide_sector_read;\n    ide_transfer_start(s, 512 * n, func);\n    ide_set_irq(s);\n    s->status = READY_STAT | SEEK_STAT | DRQ_STAT;\n    s->error = 0; /* not needed by IDE spec, but needed by Windows */\n}\n\nstatic void ide_sector_read_cb_end(IDEState *s)\n{\n    /* no more sector to read from disk */\n    s->status = READY_STAT | SEEK_STAT;\n    s->error = 0; /* not needed by IDE spec, but needed by Windows */\n    ide_transfer_stop(s);\n}\n\nstatic void ide_sector_write_cb1(IDEState *s)\n{\n    int64_t sector_num;\n    int ret;\n\n    ide_transfer_stop(s);\n    sector_num = ide_get_sector(s);\n#if defined(DEBUG_IDE)\n    printf(\"write sector=%\" PRId64 \"  count=%d\\n\",\n           sector_num, s->io_nb_sectors);\n#endif\n    ret = s->bs->write_async(s->bs, sector_num, s->io_buffer, s->io_nb_sectors, \n                             ide_sector_write_cb2, s);\n    if (ret < 0) {\n        /* error */\n        ide_abort_command(s);\n        ide_set_irq(s);\n    } else if (ret == 0) {\n        /* synchronous case (needed for performance) */\n        ide_sector_write_cb2(s, 0);\n    } else {\n        /* async case */\n        s->status = READY_STAT | SEEK_STAT | BUSY_STAT;\n    }\n}\n\nstatic void ide_sector_write_cb2(void *opaque, int ret)\n{\n    IDEState *s = opaque;\n    int n;\n\n    n = s->io_nb_sectors;\n    ide_set_sector(s, ide_get_sector(s) + n);\n    s->nsector = (s->nsector - n) & 0xff;\n    if (s->nsector == 0) {\n        /* no more sectors to write */\n        s->status = READY_STAT | SEEK_STAT;\n    } else {\n        n = s->nsector;\n        if (n > s->req_nb_sectors)\n            n = s->req_nb_sectors;\n        s->io_nb_sectors = n;\n        ide_transfer_start(s, 512 * n, ide_sector_write_cb1);\n        s->status = READY_STAT | SEEK_STAT | DRQ_STAT;\n    }\n    ide_set_irq(s);\n}\n\nstatic void ide_sector_write(IDEState *s)\n{\n    int n;\n    n = s->nsector;\n    if (n == 0)\n        n = 256;\n    if (n > s->req_nb_sectors)\n        n = s->req_nb_sectors;\n    s->io_nb_sectors = n;\n    ide_transfer_start(s, 512 * n, ide_sector_write_cb1);\n    s->status = READY_STAT | SEEK_STAT | DRQ_STAT;\n}\n\nstatic void ide_identify_cb(IDEState *s)\n{\n    ide_transfer_stop(s);\n    s->status = READY_STAT;\n}\n\nstatic void ide_exec_cmd(IDEState *s, int val)\n{\n#if defined(DEBUG_IDE)\n    printf(\"ide: exec_cmd=0x%02x\\n\", val);\n#endif\n    switch(val) {\n    case WIN_IDENTIFY:\n        ide_identify(s);\n        s->status = READY_STAT | SEEK_STAT | DRQ_STAT;\n        ide_transfer_start(s, 512, ide_identify_cb);\n        ide_set_irq(s);\n        break;\n    case WIN_SPECIFY:\n    case WIN_RECAL:\n        s->error = 0;\n        s->status = READY_STAT | SEEK_STAT;\n        ide_set_irq(s);\n        break;\n    case WIN_SETMULT:\n        if (s->nsector > MAX_MULT_SECTORS || \n            (s->nsector & (s->nsector - 1)) != 0) {\n            ide_abort_command(s);\n        } else {\n            s->mult_sectors = s->nsector;\n#if defined(DEBUG_IDE)\n            printf(\"ide: setmult=%d\\n\", s->mult_sectors);\n#endif\n            s->status = READY_STAT;\n        }\n        ide_set_irq(s);\n        break;\n    case WIN_READ:\n    case WIN_READ_ONCE:\n        s->req_nb_sectors = 1;\n        ide_sector_read(s);\n        break;\n    case WIN_WRITE:\n    case WIN_WRITE_ONCE:\n        s->req_nb_sectors = 1;\n        ide_sector_write(s);\n        break;\n    case WIN_MULTREAD:\n        if (!s->mult_sectors) {\n            ide_abort_command(s);\n            ide_set_irq(s);\n        } else {\n            s->req_nb_sectors = s->mult_sectors;\n            ide_sector_read(s);\n        }\n        break;\n    case WIN_MULTWRITE:\n        if (!s->mult_sectors) {\n            ide_abort_command(s);\n            ide_set_irq(s);\n        } else {\n            s->req_nb_sectors = s->mult_sectors;\n            ide_sector_write(s);\n        }\n        break;\n    case WIN_READ_NATIVE_MAX:\n        ide_set_sector(s, s->nb_sectors - 1);\n        s->status = READY_STAT;\n        ide_set_irq(s);\n        break;\n    default:\n        ide_abort_command(s);\n        ide_set_irq(s);\n        break;\n    }\n}\n\nstatic void ide_ioport_write(void *opaque, uint32_t offset,\n                             uint32_t val, int size_log2)\n{\n    IDEIFState *s1 = opaque;\n    IDEState *s = s1->cur_drive;\n    int addr = offset + 1;\n    \n#ifdef DEBUG_IDE\n    printf(\"ide: write addr=0x%02x val=0x%02x\\n\", addr, val);\n#endif\n    switch(addr) {\n    case 0:\n        break;\n    case 1:\n        if (s) {\n            s->feature = val;\n        }\n        break;\n    case 2:\n        if (s) {\n            s->nsector = val;\n        }\n        break;\n    case 3:\n        if (s) {\n            s->sector = val;\n        }\n        break;\n    case 4:\n        if (s) {\n            s->lcyl = val;\n        }\n        break;\n    case 5:\n        if (s) {\n            s->hcyl = val;\n        }\n        break;\n    case 6:\n        /* select drive */\n        s = s1->cur_drive = s1->drives[(val >> 4) & 1];\n        if (s) {\n            s->select = val;\n        }\n        break;\n    default:\n    case 7:\n        /* command */\n        if (s) {\n            ide_exec_cmd(s, val);\n        }\n        break;\n    }\n}\n\nstatic uint32_t ide_ioport_read(void *opaque, uint32_t offset, int size_log2)\n{\n    IDEIFState *s1 = opaque;\n    IDEState *s = s1->cur_drive;\n    int ret, addr = offset + 1;\n\n    if (!s) {\n        ret = 0x00;\n    } else {\n        switch(addr) {\n        case 0:\n           ret = 0xff;\n           break;\n        case 1:\n            ret = s->error;\n            break;\n        case 2:\n            ret = s->nsector;\n            break;\n        case 3:\n            ret = s->sector;\n            break;\n        case 4:\n            ret = s->lcyl;\n            break;\n        case 5:\n            ret = s->hcyl;\n            break;\n        case 6:\n            ret = s->select;\n            break;\n        default:\n        case 7:\n            ret = s->status;\n            set_irq(s1->irq, 0);\n            break;\n        }\n    }\n#ifdef DEBUG_IDE\n    printf(\"ide: read addr=0x%02x val=0x%02x\\n\", addr, ret);\n#endif\n    return ret;\n}\n\nstatic uint32_t ide_status_read(void *opaque, uint32_t offset, int size_log2)\n{\n    IDEIFState *s1 = opaque;\n    IDEState *s = s1->cur_drive;\n    int ret;\n\n    if (s) {\n        ret = s->status;\n    } else {\n        ret = 0;\n    }\n#ifdef DEBUG_IDE\n    printf(\"ide: read status=0x%02x\\n\", ret);\n#endif\n    return ret;\n}\n\nstatic void ide_cmd_write(void *opaque, uint32_t offset,\n                          uint32_t val, int size_log2)\n{\n    IDEIFState *s1 = opaque;\n    IDEState *s;\n    int i;\n    \n#ifdef DEBUG_IDE\n    printf(\"ide: cmd write=0x%02x\\n\", val);\n#endif\n    if (!(s1->cmd & IDE_CMD_RESET) && (val & IDE_CMD_RESET)) {\n        /* low to high */\n        for(i = 0; i < 2; i++) {\n            s = s1->drives[i];\n            if (s) {\n                s->status = BUSY_STAT | SEEK_STAT;\n                s->error = 0x01;\n            }\n        }\n    } else if ((s1->cmd & IDE_CMD_RESET) && !(val & IDE_CMD_RESET)) {\n        /* high to low */\n        for(i = 0; i < 2; i++) {\n            s = s1->drives[i];\n            if (s) {\n                s->status = READY_STAT | SEEK_STAT;\n                ide_set_signature(s);\n            }\n        }\n    }\n    s1->cmd = val;\n}\n\nstatic void ide_data_writew(void *opaque, uint32_t offset,\n                            uint32_t val, int size_log2)\n{\n    IDEIFState *s1 = opaque;\n    IDEState *s = s1->cur_drive;\n    int p;\n    uint8_t *tab;\n    \n    if (!s)\n        return;\n    p = s->data_index;\n    tab = s->io_buffer;\n    tab[p] = val & 0xff;\n    tab[p + 1] = (val >> 8) & 0xff;\n    p += 2;\n    s->data_index = p;\n    if (p >= s->data_end)\n        s->end_transfer_func(s);\n}\n\nstatic uint32_t ide_data_readw(void *opaque, uint32_t offset, int size_log2)\n{\n    IDEIFState *s1 = opaque;\n    IDEState *s = s1->cur_drive;\n    int p, ret;\n    uint8_t *tab;\n    \n    if (!s) {\n        ret = 0;\n    } else {\n        p = s->data_index;\n        tab = s->io_buffer;\n        ret = tab[p] | (tab[p + 1] << 8);\n        p += 2;\n        s->data_index = p;\n        if (p >= s->data_end)\n            s->end_transfer_func(s);\n    }\n    return ret;\n}\n\nstatic IDEState *ide_drive_init(IDEIFState *ide_if, BlockDevice *bs)\n{\n    IDEState *s;\n    uint32_t cylinders;\n    uint64_t nb_sectors;\n\n    s = malloc(sizeof(*s));\n    memset(s, 0, sizeof(*s));\n\n    s->ide_if = ide_if;\n    s->bs = bs;\n\n    nb_sectors = s->bs->get_sector_count(s->bs);\n    cylinders = nb_sectors / (16 * 63);\n    if (cylinders > 16383)\n        cylinders = 16383;\n    else if (cylinders < 2)\n        cylinders = 2;\n    s->cylinders = cylinders;\n    s->heads = 16;\n    s->sectors = 63;\n    s->nb_sectors = nb_sectors;\n\n    s->mult_sectors = MAX_MULT_SECTORS;\n    /* ide regs */\n    s->feature = 0;\n    s->error = 0;\n    s->nsector = 0;\n    s->sector = 0;\n    s->lcyl = 0;\n    s->hcyl = 0;\n    s->select = 0xa0;\n    s->status = READY_STAT | SEEK_STAT;\n\n    /* init I/O buffer */\n    s->data_index = 0;\n    s->data_end = 0;\n    s->end_transfer_func = ide_transfer_stop;\n\n    s->req_nb_sectors = 0; /* temp for read/write */\n    s->io_nb_sectors = 0; /* temp for read/write */\n    return s;\n}\n\nIDEIFState *ide_init(PhysMemoryMap *port_map, uint32_t addr, uint32_t addr2,\n                     IRQSignal *irq, BlockDevice **tab_bs)\n{\n    int i;\n    IDEIFState *s;\n    \n    s = malloc(sizeof(IDEIFState));\n    memset(s, 0, sizeof(*s));\n    \n    s->irq = irq;\n    s->cmd = 0;\n\n    cpu_register_device(port_map, addr, 1, s, ide_data_readw, ide_data_writew, \n                        DEVIO_SIZE16);\n    cpu_register_device(port_map, addr + 1, 7, s, ide_ioport_read, ide_ioport_write, \n                        DEVIO_SIZE8);\n    if (addr2) {\n        cpu_register_device(port_map, addr2, 1, s, ide_status_read, ide_cmd_write, \n                            DEVIO_SIZE8);\n    }\n    \n    for(i = 0; i < 2; i++) {\n        if (tab_bs[i])\n            s->drives[i] = ide_drive_init(s, tab_bs[i]);\n    }\n    s->cur_drive = s->drives[0];\n    return s;\n}\n\n/* dummy PCI device for the IDE */\nPCIDevice *piix3_ide_init(PCIBus *pci_bus, int devfn)\n{\n    PCIDevice *d;\n    d = pci_register_device(pci_bus, \"PIIX3 IDE\", devfn, 0x8086, 0x7010, 0x00, 0x0101);\n    pci_device_set_config8(d, 0x09, 0x00); /* ISA IDE ports, no DMA */\n    return d;\n}\n"
  },
  {
    "path": "src/ide.h",
    "content": "/*\n * IDE emulation\n * \n * Copyright (c) 2003-2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"virtio.h\"\n#include \"iomem.h\"\n#include \"pci.h\"\n\ntypedef struct IDEIFState IDEIFState;\n\nIDEIFState *ide_init(PhysMemoryMap *port_map, uint32_t addr, uint32_t addr2,\n                     IRQSignal *irq, BlockDevice **tab_bs);\nPCIDevice *piix3_ide_init(PCIBus *pci_bus, int devfn);\n"
  },
  {
    "path": "src/iomem.c",
    "content": "/*\n * IO memory handling\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n\n#include \"cutils.h\"\n#include \"iomem.h\"\n\nstatic PhysMemoryRange *default_register_ram(PhysMemoryMap *s, uint64_t addr,\n                                             uint64_t size, int devram_flags);\nstatic void default_free_ram(PhysMemoryMap *s, PhysMemoryRange *pr);\nstatic const uint32_t *default_get_dirty_bits(PhysMemoryMap *map, PhysMemoryRange *pr);\nstatic void default_set_addr(PhysMemoryMap *map,\n                             PhysMemoryRange *pr, uint64_t addr, BOOL enabled);\n\nPhysMemoryMap *phys_mem_map_init(void)\n{\n    PhysMemoryMap *s;\n    s = mallocz(sizeof(*s));\n    s->register_ram = default_register_ram;\n    s->free_ram = default_free_ram;\n    s->get_dirty_bits = default_get_dirty_bits;\n    s->set_ram_addr = default_set_addr;\n    return s;\n}\n\nvoid phys_mem_map_end(PhysMemoryMap *s)\n{\n    int i;\n    PhysMemoryRange *pr;\n\n    for(i = 0; i < s->n_phys_mem_range; i++) {\n        pr = &s->phys_mem_range[i];\n        if (pr->is_ram) {\n            s->free_ram(s, pr);\n        }\n    }\n    free(s);\n}\n\n/* return NULL if not found */\n/* XXX: optimize */\nPhysMemoryRange *get_phys_mem_range(PhysMemoryMap *s, uint64_t paddr)\n{\n    PhysMemoryRange *pr;\n    int i;\n    for(i = 0; i < s->n_phys_mem_range; i++) {\n        pr = &s->phys_mem_range[i];\n        if (paddr >= pr->addr && paddr < pr->addr + pr->size)\n            return pr;\n    }\n    return NULL;\n}\n\nPhysMemoryRange *register_ram_entry(PhysMemoryMap *s, uint64_t addr,\n                                    uint64_t size, int devram_flags)\n{\n    PhysMemoryRange *pr;\n\n    assert(s->n_phys_mem_range < PHYS_MEM_RANGE_MAX);\n    assert((size & (DEVRAM_PAGE_SIZE - 1)) == 0 && size != 0);\n    pr = &s->phys_mem_range[s->n_phys_mem_range++];\n    pr->map = s;\n    pr->is_ram = TRUE;\n    pr->devram_flags = devram_flags & ~DEVRAM_FLAG_DISABLED;\n    pr->addr = addr;\n    pr->org_size = size;\n    if (devram_flags & DEVRAM_FLAG_DISABLED)\n        pr->size = 0;\n    else\n        pr->size = pr->org_size;\n    pr->phys_mem = NULL;\n    pr->dirty_bits = NULL;\n    return pr;\n}\n\nstatic PhysMemoryRange *default_register_ram(PhysMemoryMap *s, uint64_t addr,\n                                             uint64_t size, int devram_flags)\n{\n    PhysMemoryRange *pr;\n\n    pr = register_ram_entry(s, addr, size, devram_flags);\n\n    pr->phys_mem = mallocz(size);\n    if (!pr->phys_mem) {\n        fprintf(stderr, \"Could not allocate VM memory\\n\");\n        exit(1);\n    }\n\n    if (devram_flags & DEVRAM_FLAG_DIRTY_BITS) {\n        size_t nb_pages;\n        int i;\n        nb_pages = size >> DEVRAM_PAGE_SIZE_LOG2;\n        pr->dirty_bits_size = ((nb_pages + 31) / 32) * sizeof(uint32_t);\n        pr->dirty_bits_index = 0;\n        for(i = 0; i < 2; i++) {\n            pr->dirty_bits_tab[i] = mallocz(pr->dirty_bits_size);\n        }\n        pr->dirty_bits = pr->dirty_bits_tab[pr->dirty_bits_index];\n    }\n    return pr;\n}\n\n/* return a pointer to the bitmap of dirty bits and reset them */\nstatic const uint32_t *default_get_dirty_bits(PhysMemoryMap *map,\n                                              PhysMemoryRange *pr)\n{\n    uint32_t *dirty_bits;\n    BOOL has_dirty_bits;\n    size_t n, i;\n    \n    dirty_bits = pr->dirty_bits;\n\n    has_dirty_bits = FALSE;\n    n = pr->dirty_bits_size / sizeof(uint32_t);\n    for(i = 0; i < n; i++) {\n        if (dirty_bits[i] != 0) {\n            has_dirty_bits = TRUE;\n            break;\n        }\n    }\n    if (has_dirty_bits && pr->size != 0) {\n        /* invalidate the corresponding CPU write TLBs */\n        map->flush_tlb_write_range(map->opaque, pr->phys_mem, pr->org_size);\n    }\n    \n    pr->dirty_bits_index ^= 1;\n    pr->dirty_bits = pr->dirty_bits_tab[pr->dirty_bits_index];\n    memset(pr->dirty_bits, 0, pr->dirty_bits_size);\n    return dirty_bits;\n}\n\n/* reset the dirty bit of one page at 'offset' inside 'pr' */\nvoid phys_mem_reset_dirty_bit(PhysMemoryRange *pr, size_t offset)\n{\n    size_t page_index;\n    uint32_t mask, *dirty_bits_ptr;\n    PhysMemoryMap *map;\n    if (pr->dirty_bits) {\n        page_index = offset >> DEVRAM_PAGE_SIZE_LOG2;\n        mask = 1 << (page_index & 0x1f);\n        dirty_bits_ptr = pr->dirty_bits + (page_index >> 5);\n        if (*dirty_bits_ptr & mask) {\n            *dirty_bits_ptr &= ~mask;\n            /* invalidate the corresponding CPU write TLBs */\n            map = pr->map;\n            map->flush_tlb_write_range(map->opaque,\n                                       pr->phys_mem + (offset & ~(DEVRAM_PAGE_SIZE - 1)),\n                                       DEVRAM_PAGE_SIZE);\n        }\n    }\n}\n\nstatic void default_free_ram(PhysMemoryMap *s, PhysMemoryRange *pr)\n{\n    free(pr->phys_mem);\n}\n\nPhysMemoryRange *cpu_register_device(PhysMemoryMap *s, uint64_t addr,\n                                     uint64_t size, void *opaque,\n                                     DeviceReadFunc *read_func, DeviceWriteFunc *write_func,\n                                     int devio_flags)\n{\n    PhysMemoryRange *pr;\n    assert(s->n_phys_mem_range < PHYS_MEM_RANGE_MAX);\n    assert(size <= 0xffffffff);\n    pr = &s->phys_mem_range[s->n_phys_mem_range++];\n    pr->map = s;\n    pr->addr = addr;\n    pr->org_size = size;\n    if (devio_flags & DEVIO_DISABLED)\n        pr->size = 0;\n    else\n        pr->size = pr->org_size;\n    pr->is_ram = FALSE;\n    pr->opaque = opaque;\n    pr->read_func = read_func;\n    pr->write_func = write_func;\n    pr->devio_flags = devio_flags;\n    return pr;\n}\n\nstatic void default_set_addr(PhysMemoryMap *map,\n                             PhysMemoryRange *pr, uint64_t addr, BOOL enabled)\n{\n    if (enabled) {\n        if (pr->size == 0 || pr->addr != addr) {\n            /* enable or move mapping */\n            if (pr->is_ram) {\n                map->flush_tlb_write_range(map->opaque,\n                                           pr->phys_mem, pr->org_size);\n            }\n            pr->addr = addr;\n            pr->size = pr->org_size;\n        }\n    } else {\n        if (pr->size != 0) {\n            /* disable mapping */\n            if (pr->is_ram) {\n                map->flush_tlb_write_range(map->opaque,\n                                           pr->phys_mem, pr->org_size);\n            }\n            pr->addr = 0;\n            pr->size = 0;\n        }\n    }\n}\n\nvoid phys_mem_set_addr(PhysMemoryRange *pr, uint64_t addr, BOOL enabled)\n{\n    PhysMemoryMap *map = pr->map;\n    if (!pr->is_ram) {\n        default_set_addr(map, pr, addr, enabled);\n    } else {\n        return map->set_ram_addr(map, pr, addr, enabled);\n    }\n}\n\n/* return NULL if no valid RAM page. The access can only be done in the page */\nuint8_t *phys_mem_get_ram_ptr(PhysMemoryMap *map, uint64_t paddr, BOOL is_rw)\n{\n    PhysMemoryRange *pr = get_phys_mem_range(map, paddr);\n    uintptr_t offset;\n    if (!pr || !pr->is_ram)\n        return NULL;\n    offset = paddr - pr->addr;\n    if (is_rw)\n        phys_mem_set_dirty_bit(pr, offset);\n    return pr->phys_mem + (uintptr_t)offset;\n}\n\n/* IRQ support */\n\nvoid irq_init(IRQSignal *irq, SetIRQFunc *set_irq, void *opaque, int irq_num)\n{\n    irq->set_irq = set_irq;\n    irq->opaque = opaque;\n    irq->irq_num = irq_num;\n}\n"
  },
  {
    "path": "src/iomem.h",
    "content": "/*\n * IO memory handling\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef IOMEM_H\n#define IOMEM_H\n\ntypedef void DeviceWriteFunc(void *opaque, uint32_t offset,\n                             uint32_t val, int size_log2);\ntypedef uint32_t DeviceReadFunc(void *opaque, uint32_t offset, int size_log2);\n\n#define DEVIO_SIZE8  (1 << 0)\n#define DEVIO_SIZE16 (1 << 1)\n#define DEVIO_SIZE32 (1 << 2)\n/* not supported, could add specific 64 bit callbacks when needed */\n//#define DEVIO_SIZE64 (1 << 3) \n#define DEVIO_DISABLED (1 << 4)\n\n#define DEVRAM_FLAG_ROM        (1 << 0) /* not writable */\n#define DEVRAM_FLAG_DIRTY_BITS (1 << 1) /* maintain dirty bits */\n#define DEVRAM_FLAG_DISABLED   (1 << 2) /* allocated but not mapped */\n#define DEVRAM_PAGE_SIZE_LOG2 12\n#define DEVRAM_PAGE_SIZE (1 << DEVRAM_PAGE_SIZE_LOG2)\n\ntypedef struct PhysMemoryMap PhysMemoryMap;\n\ntypedef struct {\n    PhysMemoryMap *map;\n    uint64_t addr;\n    uint64_t org_size; /* original size */\n    uint64_t size; /* =org_size or 0 if the mapping is disabled */\n    BOOL is_ram;\n    /* the following is used for RAM access */\n    int devram_flags;\n    uint8_t *phys_mem;\n    int dirty_bits_size; /* in bytes */\n    uint32_t *dirty_bits; /* NULL if not used */\n    uint32_t *dirty_bits_tab[2];\n    int dirty_bits_index; /* 0-1 */\n    /* the following is used for I/O access */\n    void *opaque;\n    DeviceReadFunc *read_func;\n    DeviceWriteFunc *write_func;\n    int devio_flags;\n} PhysMemoryRange;\n\n#define PHYS_MEM_RANGE_MAX 32\n\nstruct PhysMemoryMap {\n    int n_phys_mem_range;\n    PhysMemoryRange phys_mem_range[PHYS_MEM_RANGE_MAX];\n    PhysMemoryRange *(*register_ram)(PhysMemoryMap *s, uint64_t addr,\n                                     uint64_t size, int devram_flags);\n    void (*free_ram)(PhysMemoryMap *s, PhysMemoryRange *pr);\n    const uint32_t *(*get_dirty_bits)(PhysMemoryMap *s, PhysMemoryRange *pr);\n    void (*set_ram_addr)(PhysMemoryMap *s, PhysMemoryRange *pr, uint64_t addr,\n                         BOOL enabled);\n    void *opaque;\n    void (*flush_tlb_write_range)(void *opaque, uint8_t *ram_addr,\n                                  size_t ram_size);\n};\n\n\nPhysMemoryMap *phys_mem_map_init(void);\nvoid phys_mem_map_end(PhysMemoryMap *s);\nPhysMemoryRange *register_ram_entry(PhysMemoryMap *s, uint64_t addr,\n                                    uint64_t size, int devram_flags);\nstatic inline PhysMemoryRange *cpu_register_ram(PhysMemoryMap *s, uint64_t addr,\n                                  uint64_t size, int devram_flags)\n{\n    return s->register_ram(s, addr, size, devram_flags);\n}\nPhysMemoryRange *cpu_register_device(PhysMemoryMap *s, uint64_t addr,\n                                     uint64_t size, void *opaque,\n                                     DeviceReadFunc *read_func, DeviceWriteFunc *write_func,\n                                     int devio_flags);\nPhysMemoryRange *get_phys_mem_range(PhysMemoryMap *s, uint64_t paddr);\nvoid phys_mem_set_addr(PhysMemoryRange *pr, uint64_t addr, BOOL enabled);\n\nstatic inline const uint32_t *phys_mem_get_dirty_bits(PhysMemoryRange *pr)\n{\n    PhysMemoryMap *map = pr->map;\n    return map->get_dirty_bits(map, pr);\n}\n\nstatic inline void phys_mem_set_dirty_bit(PhysMemoryRange *pr, size_t offset)\n{\n    size_t page_index;\n    uint32_t mask, *dirty_bits_ptr;\n    if (pr->dirty_bits) {\n        page_index = offset >> DEVRAM_PAGE_SIZE_LOG2;\n        mask = 1 << (page_index & 0x1f);\n        dirty_bits_ptr = pr->dirty_bits + (page_index >> 5);\n        *dirty_bits_ptr |= mask;\n    }\n}\n\nstatic inline BOOL phys_mem_is_dirty_bit(PhysMemoryRange *pr, size_t offset)\n{\n    size_t page_index;\n    uint32_t *dirty_bits_ptr;\n    if (!pr->dirty_bits)\n        return TRUE;\n    page_index = offset >> DEVRAM_PAGE_SIZE_LOG2;\n    dirty_bits_ptr = pr->dirty_bits + (page_index >> 5);\n    return (*dirty_bits_ptr >> (page_index & 0x1f)) & 1;\n}\n\nvoid phys_mem_reset_dirty_bit(PhysMemoryRange *pr, size_t offset);\nuint8_t *phys_mem_get_ram_ptr(PhysMemoryMap *map, uint64_t paddr, BOOL is_rw);\n\n/* IRQ support */\n\ntypedef void SetIRQFunc(void *opaque, int irq_num, int level);\n\ntypedef struct {\n    SetIRQFunc *set_irq;\n    void *opaque;\n    int irq_num;\n} IRQSignal;\n\nvoid irq_init(IRQSignal *irq, SetIRQFunc *set_irq, void *opaque, int irq_num);\n\nstatic inline void set_irq(IRQSignal *irq, int level)\n{\n    irq->set_irq(irq->opaque, irq->irq_num, level);\n}\n\n#endif /* IOMEM_H */\n"
  },
  {
    "path": "src/json.c",
    "content": "/*\n * Pseudo JSON parser\n * \n * Copyright (c) 2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <unistd.h>\n#include <time.h>\n#include <ctype.h>\n\n#include \"cutils.h\"\n#include \"json.h\"\n#include \"fs_utils.h\"\n\nstatic JSONValue parse_string(const char **pp)\n{\n    char buf[4096], *q;\n    const char *p;\n    int c, h;\n    \n    q = buf;\n    p = *pp;\n    p++;\n    for(;;) {\n        c = *p++;\n        if (c == '\\0' || c == '\\n') {\n            return json_error_new(\"unterminated string\");\n        } else if (c == '\\\"') {\n            break;\n            } else if (c == '\\\\') {\n                c = *p++;\n                switch(c) {\n                case '\\'':\n                case '\\\"':\n                case '\\\\':\n                    goto add_char;\n                case 'n':\n                    c = '\\n';\n                    goto add_char;\n                case 'r':\n                    c = '\\r';\n                    goto add_char;\n                case 't':\n                    c = '\\t';\n                    goto add_char;\n                case 'x':\n                    h = from_hex(*p++);\n                    if (h < 0)\n                        return json_error_new(\"invalig hex digit\");\n                    c = h << 4;\n                    h = from_hex(*p++);\n                    if (h < 0)\n                        return json_error_new(\"invalig hex digit\");\n                    c |= h;\n                    goto add_char;\n                default:\n                    return json_error_new(\"unknown escape code\");\n                }\n            } else {\n            add_char:\n            if (q >= buf + sizeof(buf) - 1)\n                return json_error_new(\"string too long\");\n            *q++ = c;\n        }\n    }\n    *q = '\\0';\n    *pp = p;\n    return json_string_new(buf);\n}\n\nstatic JSONProperty *json_object_get2(JSONObject *obj, const char *name)\n{\n    JSONProperty *f;\n    int i;\n    for(i = 0; i < obj->len; i++) {\n        f = &obj->props[i];\n        if (!strcmp(f->name.u.str->data, name))\n            return f;\n    }\n    return NULL;\n}\n\nJSONValue json_object_get(JSONValue val, const char *name)\n{\n    JSONProperty *f;\n    JSONObject *obj;\n    \n    if (val.type != JSON_OBJ)\n        return json_undefined_new();\n    obj = val.u.obj;\n    f = json_object_get2(obj, name);\n    if (!f)\n        return json_undefined_new();\n    return f->value;\n}\n\nint json_object_set(JSONValue val, const char *name, JSONValue prop_val)\n{\n    JSONObject *obj;\n    JSONProperty *f;\n    int new_size;\n    \n    if (val.type != JSON_OBJ)\n        return -1;\n    obj = val.u.obj;\n    f = json_object_get2(obj, name);\n    if (f) {\n        json_free(f->value);\n        f->value = prop_val;\n    } else {\n        if (obj->len >= obj->size) {\n            new_size = max_int(obj->len + 1, obj->size * 3 / 2);\n            obj->props = realloc(obj->props, new_size * sizeof(JSONProperty));\n            obj->size = new_size;\n        }\n        f = &obj->props[obj->len++];\n        f->name = json_string_new(name);\n        f->value = prop_val;\n    }\n    return 0;\n}\n\nJSONValue json_array_get(JSONValue val, unsigned int idx)\n{\n    JSONArray *array;\n    \n    if (val.type != JSON_ARRAY)\n        return json_undefined_new();\n    array = val.u.array;\n    if (idx < array->len) {\n        return array->tab[idx];\n    } else {\n        return json_undefined_new();\n    }\n}\n\nint json_array_set(JSONValue val, unsigned int idx, JSONValue prop_val)\n{\n    JSONArray *array;\n    int new_size;\n    \n    if (val.type != JSON_ARRAY)\n        return -1;\n    array = val.u.array;\n    if (idx < array->len) {\n        json_free(array->tab[idx]);\n        array->tab[idx] = prop_val;\n    } else if (idx == array->len) {\n        if (array->len >= array->size) {\n            new_size = max_int(array->len + 1, array->size * 3 / 2);\n            array->tab = realloc(array->tab, new_size * sizeof(JSONValue));\n            array->size = new_size;\n        }\n        array->tab[array->len++] = prop_val;\n    } else {\n        return -1;\n    }\n    return 0;\n}\n\nconst char *json_get_str(JSONValue val)\n{\n    if (val.type != JSON_STR)\n        return NULL;\n    return val.u.str->data;\n}\n\nconst char *json_get_error(JSONValue val)\n{\n    if (val.type != JSON_EXCEPTION)\n        return NULL;\n    return val.u.str->data;\n}\n\nJSONValue json_string_new2(const char *str, int len)\n{\n    JSONValue val;\n    JSONString *str1;\n\n    str1 = malloc(sizeof(JSONString) + len + 1);\n    str1->len = len;\n    memcpy(str1->data, str, len + 1);\n    val.type = JSON_STR;\n    val.u.str = str1;\n    return val;\n}\n\nJSONValue json_string_new(const char *str)\n{\n    return json_string_new2(str, strlen(str));\n}\n\nJSONValue __attribute__((format(printf, 1, 2))) json_error_new(const char *fmt, ...)\n{\n    JSONValue val;\n    va_list ap;\n    char buf[256];\n    \n    va_start(ap, fmt);\n    vsnprintf(buf, sizeof(buf), fmt, ap);\n    va_end(ap);\n    val = json_string_new(buf);\n    val.type = JSON_EXCEPTION;\n    return val;\n}\n\nJSONValue json_object_new(void)\n{\n    JSONValue val;\n    JSONObject *obj;\n    obj = mallocz(sizeof(JSONObject));\n    val.type = JSON_OBJ;\n    val.u.obj = obj;\n    return val;\n}\n\nJSONValue json_array_new(void)\n{\n    JSONValue val;\n    JSONArray *array;\n    array = mallocz(sizeof(JSONArray));\n    val.type = JSON_ARRAY;\n    val.u.array = array;\n    return val;\n}\n\nvoid json_free(JSONValue val)\n{\n    switch(val.type) {\n    case JSON_STR:\n    case JSON_EXCEPTION:\n        free(val.u.str);\n        break;\n    case JSON_INT:\n    case JSON_BOOL:\n    case JSON_NULL:\n    case JSON_UNDEFINED:\n        break;\n    case JSON_ARRAY:\n        {\n            JSONArray *array = val.u.array;\n            int i;\n            \n            for(i = 0; i < array->len; i++) {\n                json_free(array->tab[i]);\n            }\n            free(array);\n        }\n        break;\n    case JSON_OBJ:\n        {\n            JSONObject *obj = val.u.obj;\n            JSONProperty *f;\n            int i;\n            \n            for(i = 0; i < obj->len; i++) {\n                f = &obj->props[i];\n                json_free(f->name);\n                json_free(f->value);\n            }\n            free(obj);\n        }\n        break;\n    default:\n        abort();\n    }\n}\n\nstatic void skip_spaces(const char **pp)\n{\n    const char *p;\n    p = *pp;\n    for(;;) {\n        if (isspace(*p)) {\n            p++;\n        } else if (p[0] == '/' && p[1] == '/') {\n            p += 2;\n            while (*p != '\\0' && *p != '\\n')\n                p++;\n        } else if (p[0] == '/' && p[1] == '*') {\n            p += 2;\n            while (*p != '\\0' && (p[0] != '*' || p[1] != '/'))\n                p++;\n            if (*p != '\\0')\n                p += 2;\n        } else {\n            break;\n        }\n    }\n    *pp = p;\n}\n\nstatic inline BOOL is_ident_first(int c)\n{\n    return (c >= 'a' && c <= 'z') ||\n        (c >= 'A' && c <= 'Z') ||\n        c == '_' || c == '$';\n}\n\nstatic int parse_ident(char *buf, int buf_size, const char **pp)\n{\n    char *q;\n    const char *p;\n    p = *pp;\n    q = buf;\n    *q++ = *p++; /* first char is already tested */\n    while (is_ident_first(*p) || isdigit(*p)) {\n        if ((q - buf) >= buf_size - 1)\n            return -1;\n        *q++ = *p++;\n    }\n    *pp = p;\n    *q = '\\0';\n    return 0;\n}\n\nJSONValue json_parse_value2(const char **pp)\n{\n    char buf[128];\n    const char *p;\n    JSONValue val, val1, tag;\n    \n    p = *pp;\n    skip_spaces(&p);\n    if (*p == '\\0') {\n        return json_error_new(\"unexpected end of file\");\n    }\n    if (isdigit(*p)) {\n        val = json_int32_new(strtol(p, (char **)&p, 0));\n    } else if (*p == '\"') {\n        val = parse_string(&p);\n    } else if (*p == '{') {\n        p++;\n        val = json_object_new();\n        for(;;) {\n            skip_spaces(&p);\n            if (*p == '}') {\n                p++;\n                break;\n            }\n            if (*p == '\"') {\n                tag = parse_string(&p);\n                if (json_is_error(tag))\n                    return tag;\n            } else if (is_ident_first(*p)) {\n                if (parse_ident(buf, sizeof(buf), &p) < 0)\n                    goto invalid_prop;\n                tag = json_string_new(buf);\n            } else {\n                goto invalid_prop;\n            }\n            //            printf(\"property: %s\\n\", json_get_str(tag));\n            if (tag.u.str->len == 0) {\n            invalid_prop:\n                return json_error_new(\"Invalid property name\");\n            }\n            skip_spaces(&p);\n            if (*p != ':') {\n                return json_error_new(\"':' expected\");\n            }\n            p++;\n            \n            val1 = json_parse_value2(&p);\n            json_object_set(val, tag.u.str->data, val1);\n\n            skip_spaces(&p);\n            if (*p == ',') {\n                p++;\n            } else if (*p != '}') {\n                return json_error_new(\"expecting ',' or '}'\");\n            }\n        }\n    } else if (*p == '[') {\n        int idx;\n        \n        p++;\n        val = json_array_new();\n        idx = 0;\n        for(;;) {\n            skip_spaces(&p);\n            if (*p == ']') {\n                p++;\n                break;\n            }\n            val1 = json_parse_value2(&p);\n            json_array_set(val, idx++, val1);\n\n            skip_spaces(&p);\n            if (*p == ',') {\n                p++;\n            } else if (*p != ']') {\n                return json_error_new(\"expecting ',' or ']'\");\n            }\n        }\n    } else if (is_ident_first(*p)) {\n        if (parse_ident(buf, sizeof(buf), &p) < 0)\n            goto unknown_id;\n        if (!strcmp(buf, \"null\")) {\n            val = json_null_new();\n        } else if (!strcmp(buf, \"true\")) {\n            val = json_bool_new(TRUE);\n        } else if (!strcmp(buf, \"false\")) {\n            val = json_bool_new(FALSE);\n        } else {\n        unknown_id:\n            return json_error_new(\"unknown identifier: '%s'\", buf);\n        }\n    } else {\n        return json_error_new(\"unexpected character\");\n    }\n    *pp = p;\n    return val;\n}\n\nJSONValue json_parse_value(const char *p)\n{\n    JSONValue val;\n    val = json_parse_value2(&p); \n    if (json_is_error(val))\n        return val;\n    skip_spaces(&p);\n    if (*p != '\\0') {\n        json_free(val);\n        return json_error_new(\"unexpected characters at the end\");\n    }\n    return val;\n}\n\nJSONValue json_parse_value_len(const char *p, int len)\n{\n    char *str;\n    JSONValue val;\n    str = malloc(len + 1);\n    memcpy(str, p, len);\n    str[len] = '\\0';\n    val = json_parse_value(str);\n    free(str);\n    return val;\n}\n\nvoid __attribute__((format(printf, 1, 2))) vm_error(const char *fmt, ...)\n{\n    va_list ap;\n    va_start(ap, fmt);\n#ifdef EMSCRIPTEN\n    vprintf(fmt, ap);\n#else\n    vfprintf(stderr, fmt, ap);\n#endif\n    va_end(ap);\n}\n\nint vm_get_int(JSONValue obj, const char *name, int *pval)\n{ \n    JSONValue val;\n    val = json_object_get(obj, name);\n    if (json_is_undefined(val)) {\n        vm_error(\"expecting '%s' property\\n\", name);\n        return -1;\n    }\n    if (val.type != JSON_INT) {\n        vm_error(\"%s: integer expected\\n\", name);\n        return -1;\n    }\n    *pval = val.u.int32;\n    return 0;\n}\n\nint vm_get_int_opt(JSONValue obj, const char *name, int *pval, int def_val)\n{ \n    JSONValue val;\n    val = json_object_get(obj, name);\n    if (json_is_undefined(val)) {\n        *pval = def_val;\n        return 0;\n    }\n    if (val.type != JSON_INT) {\n        vm_error(\"%s: integer expected\\n\", name);\n        return -1;\n    }\n    *pval = val.u.int32;\n    return 0;\n}\n\nstatic int vm_get_str2(JSONValue obj, const char *name, const char **pstr,\n                      BOOL is_opt)\n{ \n    JSONValue val;\n    val = json_object_get(obj, name);\n    if (json_is_undefined(val)) {\n        if (is_opt) {\n            *pstr = NULL;\n            return 0;\n        } else {\n            vm_error(\"expecting '%s' property\\n\", name);\n            return -1;\n        }\n    }\n    if (val.type != JSON_STR) {\n        vm_error(\"%s: string expected\\n\", name);\n        return -1;\n    }\n    *pstr = val.u.str->data;\n    return 0;\n}\n\nint vm_get_str(JSONValue obj, const char *name, const char **pstr)\n{ \n    return vm_get_str2(obj, name, pstr, FALSE);\n}\n\nint vm_get_str_opt(JSONValue obj, const char *name, const char **pstr)\n{ \n    return vm_get_str2(obj, name, pstr, TRUE);\n}"
  },
  {
    "path": "src/json.h",
    "content": "/*\n * Pseudo JSON parser\n * \n * Copyright (c) 2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef JSON_H\n#define JSON_H\n\n#include \"cutils.h\"\n\ntypedef enum {\n    JSON_STR,\n    JSON_INT,\n    JSON_OBJ,\n    JSON_ARRAY,\n    JSON_BOOL,\n    JSON_NULL,\n    JSON_UNDEFINED,\n    JSON_EXCEPTION,\n} JSONTypeEnum;\n\ntypedef struct {\n    int len;\n    char data[0];\n} JSONString;\n\ntypedef struct JSONValue {\n    JSONTypeEnum type;\n    union {\n        JSONString *str;\n        int int32;\n        BOOL b;\n        struct JSONObject *obj;\n        struct JSONArray *array;\n    } u;\n} JSONValue;\n\ntypedef struct JSONProperty {\n    JSONValue name;\n    JSONValue value;\n} JSONProperty;\n\ntypedef struct JSONObject {\n    int len;\n    int size;\n    JSONProperty *props;\n} JSONObject;\n\ntypedef struct JSONArray {\n    int len;\n    int size;\n    JSONValue *tab;\n} JSONArray;\n\nJSONValue json_string_new2(const char *str, int len);\nJSONValue json_string_new(const char *str);\nJSONValue __attribute__((format(printf, 1, 2))) json_error_new(const char *fmt, ...);\nvoid json_free(JSONValue val);\n\nJSONValue json_object_new(void);\nJSONValue json_object_get(JSONValue val, const char *name);\nint json_object_set(JSONValue val, const char *name, JSONValue prop_val);\n\nJSONValue json_array_new(void);\nJSONValue json_array_get(JSONValue val, unsigned int idx);\nint json_array_set(JSONValue val, unsigned int idx, JSONValue prop_val);\n\nstatic inline BOOL json_is_error(JSONValue val)\n{\n    return val.type == JSON_EXCEPTION;\n}\n\nstatic inline BOOL json_is_undefined(JSONValue val)\n{\n    return val.type == JSON_UNDEFINED;\n}\n\nstatic inline JSONValue json_undefined_new(void)\n{\n    JSONValue val;\n    val.type = JSON_UNDEFINED;\n    val.u.int32 = 0;\n    return val;\n}\n\nstatic inline JSONValue json_null_new(void)\n{\n    JSONValue val;\n    val.type = JSON_NULL;\n    val.u.int32 = 0;\n    return val;\n}\n\nstatic inline JSONValue json_int32_new(int v)\n{\n    JSONValue val;\n    val.type = JSON_INT;\n    val.u.int32 = v;\n    return val;\n}\n\nstatic inline JSONValue json_bool_new(BOOL v)\n{\n    JSONValue val;\n    val.type = JSON_BOOL;\n    val.u.b = v;\n    return val;\n}\n\nconst char *json_get_str(JSONValue val);\nconst char *json_get_error(JSONValue val);\n\nJSONValue json_parse_value(const char *p);\nJSONValue json_parse_value_len(const char *p, int len);\n\nvoid __attribute__((format(printf, 1, 2))) vm_error(const char *fmt, ...);\n\nint vm_get_int(JSONValue obj, const char *name, int *pval);\nint vm_get_int_opt(JSONValue obj, const char *name, int *pval, int def_val);\nint vm_get_str(JSONValue obj, const char *name, const char **pstr);\nint vm_get_str_opt(JSONValue obj, const char *name, const char **pstr);\n#endif /* JSON_H */\n"
  },
  {
    "path": "src/list.h",
    "content": "/*\n * Linux klist like system\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef LIST_H\n#define LIST_H\n\nstruct list_head {\n    struct list_head *prev;\n    struct list_head *next;\n};\n\n/* return the pointer of type 'type *' containing 'el' as field 'member' */\n#define list_entry(el, type, member) \\\n    ((type *)((uint8_t *)(el) - offsetof(type, member)))\n\nstatic inline void init_list_head(struct list_head *head)\n{\n    head->prev = head;\n    head->next = head;\n}\n\n/* insert 'el' between 'prev' and 'next' */\nstatic inline void __list_add(struct list_head *el, \n                              struct list_head *prev, struct list_head *next)\n{\n    prev->next = el;\n    el->prev = prev;\n    el->next = next;\n    next->prev = el;\n}\n\n/* add 'el' at the head of the list 'head' (= after element head) */\nstatic inline void list_add(struct list_head *el, struct list_head *head)\n{\n    __list_add(el, head, head->next);\n}\n\n/* add 'el' at the end of the list 'head' (= before element head) */\nstatic inline void list_add_tail(struct list_head *el, struct list_head *head)\n{\n    __list_add(el, head->prev, head);\n}\n\nstatic inline void list_del(struct list_head *el)\n{\n    struct list_head *prev, *next;\n    prev = el->prev;\n    next = el->next;\n    prev->next = next;\n    next->prev = prev;\n    el->prev = NULL; /* fail safe */\n    el->next = NULL; /* fail safe */\n}\n\nstatic inline int list_empty(struct list_head *el)\n{\n    return el->next == el;\n}\n\n#define list_for_each(el, head) \\\n  for(el = (head)->next; el != (head); el = el->next)\n\n#define list_for_each_safe(el, el1, head)                \\\n    for(el = (head)->next, el1 = el->next; el != (head); \\\n        el = el1, el1 = el->next)\n\n#define list_for_each_prev(el, head) \\\n  for(el = (head)->prev; el != (head); el = el->prev)\n\n#define list_for_each_prev_safe(el, el1, head)           \\\n    for(el = (head)->prev, el1 = el->prev; el != (head); \\\n        el = el1, el1 = el->prev)\n\n#endif /* LIST_H */\n"
  },
  {
    "path": "src/machine.c",
    "content": "/*\n * VM utilities\n *\n * Copyright (c) 2017 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <unistd.h>\n#include <time.h>\n\n#include \"cutils.h\"\n#include \"iomem.h\"\n#include \"virtio.h\"\n#include \"machine.h\"\n#include \"fs_utils.h\"\n#ifdef CONFIG_FS_NET\n#include \"fs_wget.h\"\n#endif\n\n#include \"riscvsim/utils/sim_params.h\"\n#include \"riscvsim/utils/sim_log.h\"\n\nstatic char *strdup_null(const char *str)\n{\n    if (!str)\n        return NULL;\n    else\n        return strdup(str);\n}\n\n/* currently only for \"TZ\" */\nstatic char *cmdline_subst(const char *cmdline)\n{\n    DynBuf dbuf;\n    const char *p;\n    char var_name[32], *q, buf[32];\n    \n    dbuf_init(&dbuf);\n    p = cmdline;\n    while (*p != '\\0') {\n        if (p[0] == '$' && p[1] == '{') {\n            p += 2;\n            q = var_name;\n            while (*p != '\\0' && *p != '}') {\n                if ((q - var_name) < sizeof(var_name) - 1)\n                    *q++ = *p;\n                p++;\n            }\n            *q = '\\0';\n            if (*p == '}')\n                p++;\n            if (!strcmp(var_name, \"TZ\")) {\n                time_t ti;\n                struct tm tm;\n                int n, sg;\n                /* get the offset to UTC */\n                time(&ti);\n                localtime_r(&ti, &tm);\n                n = tm.tm_gmtoff / 60;\n                sg = '-';\n                if (n < 0) {\n                    sg = '+';\n                    n = -n;\n                }\n                snprintf(buf, sizeof(buf), \"UTC%c%02d:%02d\",\n                         sg, n / 60, n % 60);\n                dbuf_putstr(&dbuf, buf);\n            }\n        } else {\n            dbuf_putc(&dbuf, *p++);\n        }\n    }\n    dbuf_putc(&dbuf, 0);\n    return (char *)dbuf.buf;\n}\n\nstatic BOOL find_name(const char *name, const char *name_list)\n{\n    size_t len;\n    const char *p, *r;\n    \n    p = name_list;\n    for(;;) {\n        r = strchr(p, ',');\n        if (!r) {\n            if (!strcmp(name, p))\n                return TRUE;\n            break;\n        } else {\n            len = r - p;\n            if (len == strlen(name) && !memcmp(name, p, len))\n                return TRUE;\n            p = r + 1;\n        }\n    }\n    return FALSE;\n}\n\nstatic const VirtMachineClass *virt_machine_list[] = {\n#if defined(EMSCRIPTEN)\n    /* only a single machine in the EMSCRIPTEN target */\n#ifndef CONFIG_X86EMU\n    &riscv_machine_class,\n#endif    \n#else\n    &riscv_machine_class,\n#endif /* !EMSCRIPTEN */\n#ifdef CONFIG_X86EMU\n    &pc_machine_class,\n#endif\n    NULL,\n};\n\nstatic const VirtMachineClass *virt_machine_find_class(const char *machine_name)\n{\n    const VirtMachineClass *vmc, **pvmc;\n    \n    for(pvmc = virt_machine_list; *pvmc != NULL; pvmc++) {\n        vmc = *pvmc;\n        if (find_name(machine_name, vmc->machine_names))\n            return vmc;\n    }\n    return NULL;\n}\n\nstatic int virt_machine_parse_config(VirtMachineParams *p,\n                                     char *config_file_str, int len)\n{\n    int version, val;\n    const char *tag_name, *str;\n    char buf1[256];\n    JSONValue cfg, obj, el;\n\n    cfg = json_parse_value_len(config_file_str, len);\n    if (json_is_error(cfg)) {\n        vm_error(\"error: %s\\n\", json_get_error(cfg));\n        json_free(cfg);\n        return -1;\n    }\n\n    if (vm_get_int(cfg, \"version\", &version) < 0)\n        goto tag_fail;\n    if (version != VM_CONFIG_VERSION) {\n        if (version > VM_CONFIG_VERSION) {\n            vm_error(\"The emulator is too old to run this VM: please upgrade\\n\");\n            return -1;\n        } else {\n            vm_error(\"The VM configuration file is too old for this emulator version: please upgrade the VM configuration file\\n\");\n            return -1;\n        }\n    }\n    \n    if (vm_get_str(cfg, \"machine\", &str) < 0)\n        goto tag_fail;\n    p->machine_name = strdup(str);\n    p->vmc = virt_machine_find_class(p->machine_name);\n    if (!p->vmc) {\n        vm_error(\"Unknown machine name: %s\\n\", p->machine_name);\n        goto tag_fail;\n    }\n    p->vmc->virt_machine_set_defaults(p);\n\n    tag_name = \"memory_size\";\n    if (vm_get_int(cfg, tag_name, &val) < 0)\n        goto tag_fail;\n    p->ram_size = (uint64_t)val << 20;\n    \n    tag_name = \"bios\";\n    if (vm_get_str_opt(cfg, tag_name, &str) < 0)\n        goto tag_fail;\n    if (str) {\n        p->files[VM_FILE_BIOS].filename = strdup(str);\n    }\n\n    tag_name = \"kernel\";\n    if (vm_get_str_opt(cfg, tag_name, &str) < 0)\n        goto tag_fail;\n    if (str) {\n        p->files[VM_FILE_KERNEL].filename = strdup(str);\n    }\n\n    sim_log_event(sim_log, \"%s: %s\", \"bios\", p->files[VM_FILE_BIOS].filename);\n    sim_log_event(sim_log, \"%s: %s\", \"kernel\",\n                  p->files[VM_FILE_KERNEL].filename);\n\n    tag_name = \"initrd\";\n    if (vm_get_str_opt(cfg, tag_name, &str) < 0)\n        goto tag_fail;\n    if (str) {\n        p->files[VM_FILE_INITRD].filename = strdup(str);\n    }\n\n    if (vm_get_str_opt(cfg, \"cmdline\", &str) < 0)\n        goto tag_fail;\n    if (str) {\n        p->cmdline = cmdline_subst(str);\n    }\n    \n    for(;;) {\n        snprintf(buf1, sizeof(buf1), \"drive%d\", p->drive_count);\n        obj = json_object_get(cfg, buf1);\n        if (json_is_undefined(obj))\n            break;\n        if (p->drive_count >= MAX_DRIVE_DEVICE) {\n            vm_error(\"Too many drives\\n\");\n            return -1;\n        }\n        if (vm_get_str(obj, \"file\", &str) < 0)\n            goto tag_fail;\n        p->tab_drive[p->drive_count].filename = strdup(str);\n\n        sim_log_event(sim_log, \"drive%d-file: %s\", p->drive_count,\n                      p->tab_drive[p->drive_count].filename);\n\n        if (vm_get_str_opt(obj, \"device\", &str) < 0)\n            goto tag_fail;\n        p->tab_drive[p->drive_count].device = strdup_null(str);\n        p->drive_count++;\n    }\n\n    for(;;) {\n        snprintf(buf1, sizeof(buf1), \"fs%d\", p->fs_count);\n        obj = json_object_get(cfg, buf1);\n        if (json_is_undefined(obj))\n            break;\n        if (p->fs_count >= MAX_DRIVE_DEVICE) {\n            vm_error(\"Too many filesystems\\n\");\n            return -1;\n        }\n        if (vm_get_str(obj, \"file\", &str) < 0)\n            goto tag_fail;\n        p->tab_fs[p->fs_count].filename = strdup(str);\n        if (vm_get_str_opt(obj, \"tag\", &str) < 0)\n            goto tag_fail;\n        if (!str) {\n            if (p->fs_count == 0)\n                strcpy(buf1, \"/dev/root\");\n            else\n                snprintf(buf1, sizeof(buf1), \"/dev/root%d\", p->fs_count);\n            str = buf1;\n        }\n        p->tab_fs[p->fs_count].tag = strdup(str);\n        p->fs_count++;\n    }\n\n    for(;;) {\n        snprintf(buf1, sizeof(buf1), \"eth%d\", p->eth_count);\n        obj = json_object_get(cfg, buf1);\n        if (json_is_undefined(obj))\n            break;\n        if (p->eth_count >= MAX_ETH_DEVICE) {\n            vm_error(\"Too many ethernet interfaces\\n\");\n            return -1;\n        }\n        if (vm_get_str(obj, \"driver\", &str) < 0)\n            goto tag_fail;\n        p->tab_eth[p->eth_count].driver = strdup(str);\n        if (!strcmp(str, \"tap\")) {\n            if (vm_get_str(obj, \"ifname\", &str) < 0)\n                goto tag_fail;\n            p->tab_eth[p->eth_count].ifname = strdup(str);\n        }\n        p->eth_count++;\n    }\n\n    p->display_device = NULL;\n    obj = json_object_get(cfg, \"display0\");\n    if (!json_is_undefined(obj)) {\n        if (vm_get_str(obj, \"device\", &str) < 0)\n            goto tag_fail;\n        p->display_device = strdup(str);\n        if (vm_get_int(obj, \"width\", &p->width) < 0)\n            goto tag_fail;\n        if (vm_get_int(obj, \"height\", &p->height) < 0)\n            goto tag_fail;\n        if (vm_get_str_opt(obj, \"vga_bios\", &str) < 0)\n            goto tag_fail;\n        if (str) {\n            p->files[VM_FILE_VGA_BIOS].filename = strdup(str);\n        }\n    }\n\n    if (vm_get_str_opt(cfg, \"input_device\", &str) < 0)\n        goto tag_fail;\n    p->input_device = strdup_null(str);\n\n    if (vm_get_str_opt(cfg, \"accel\", &str) < 0)\n        goto tag_fail;\n    if (str) {\n        if (!strcmp(str, \"none\")) {\n            p->accel_enable = FALSE;\n        } else if (!strcmp(str, \"auto\")) {\n            p->accel_enable = TRUE;\n        } else {\n            vm_error(\"unsupported 'accel' config: %s\\n\", str);\n            return -1;\n        }\n    }\n\n    tag_name = \"rtc_local_time\";\n    el = json_object_get(cfg, tag_name);\n    if (!json_is_undefined(el)) {\n        if (el.type != JSON_BOOL) {\n            vm_error(\"%s: boolean expected\\n\", tag_name);\n            goto tag_fail;\n        }\n        p->rtc_local_time = el.u.b;\n    }\n\n    sim_params_parse(p->sim_params, cfg);\n    p->sim_params->guest_ram_size = p->ram_size >> 20;\n\n    json_free(cfg);\n    return 0;\n tag_fail:\n    json_free(cfg);\n    return -1;\n}\n\ntypedef void FSLoadFileCB(void *opaque, uint8_t *buf, int buf_len);\n\ntypedef struct {\n    VirtMachineParams *vm_params;\n    void (*start_cb)(void *opaque);\n    void *opaque;\n    \n    FSLoadFileCB *file_load_cb;\n    void *file_load_opaque;\n    int file_index;\n} VMConfigLoadState;\n\nstatic void config_file_loaded(void *opaque, uint8_t *buf, int buf_len);\nstatic void config_additional_file_load(VMConfigLoadState *s);\nstatic void config_additional_file_load_cb(void *opaque,\n                                           uint8_t *buf, int buf_len);\n\n/* XXX: win32, URL */\nchar *get_file_path(const char *base_filename, const char *filename)\n{\n    int len, len1;\n    char *fname, *p;\n    \n    if (!base_filename)\n        goto done;\n    if (strchr(filename, ':'))\n        goto done; /* full URL */\n    if (filename[0] == '/')\n        goto done;\n    p = strrchr(base_filename, '/');\n    if (!p) {\n    done:\n        return strdup(filename);\n    }\n    len = p + 1 - base_filename;\n    len1 = strlen(filename);\n    fname = malloc(len + len1 + 1);\n    memcpy(fname, base_filename, len);\n    memcpy(fname + len, filename, len1 + 1);\n    return fname;\n}\n\n\n#ifdef EMSCRIPTEN\nstatic int load_file(uint8_t **pbuf, const char *filename)\n{\n    abort();\n}\n#else\n/* return -1 if error. */\nstatic int load_file(uint8_t **pbuf, const char *filename)\n{\n    FILE *f;\n    int size;\n    uint8_t *buf;\n    \n    f = fopen(filename, \"rb\");\n    if (!f) {\n        perror(filename);\n        exit(1);\n    }\n    fseek(f, 0, SEEK_END);\n    size = ftell(f);\n    fseek(f, 0, SEEK_SET);\n    buf = malloc(size);\n    if (fread(buf, 1, size, f) != size) {\n        fprintf(stderr, \"%s: read error\\n\", filename);\n        exit(1);\n    }\n    fclose(f);\n    *pbuf = buf;\n    return size;\n}\n#endif\n\n#ifdef CONFIG_FS_NET\nstatic void config_load_file_cb(void *opaque, int err, void *data, size_t size)\n{\n    VMConfigLoadState *s = opaque;\n    \n    //    printf(\"err=%d data=%p size=%ld\\n\", err, data, size);\n    if (err < 0) {\n        vm_error(\"Error %d while loading file\\n\", -err);\n        exit(1);\n    }\n    s->file_load_cb(s->file_load_opaque, data, size);\n}\n#endif\n\nstatic void config_load_file(VMConfigLoadState *s, const char *filename,\n                             FSLoadFileCB *cb, void *opaque)\n{\n    //    printf(\"loading %s\\n\", filename);\n#ifdef CONFIG_FS_NET\n    if (is_url(filename)) {\n        s->file_load_cb = cb;\n        s->file_load_opaque = opaque;\n        fs_wget(filename, NULL, NULL, s, config_load_file_cb, TRUE);\n    } else\n#endif\n    {\n        uint8_t *buf;\n        int size;\n        size = load_file(&buf, filename);\n        cb(opaque, buf, size);\n        free(buf);\n    }\n}\n\nvoid virt_machine_load_config_file(VirtMachineParams *p,\n                                   const char *filename,\n                                   void (*start_cb)(void *opaque),\n                                   void *opaque)\n{\n    VMConfigLoadState *s;\n    \n    s = mallocz(sizeof(*s));\n    s->vm_params = p;\n    s->start_cb = start_cb;\n    s->opaque = opaque;\n    p->cfg_filename = strdup(filename);\n\n    config_load_file(s, filename, config_file_loaded, s);\n}\n\nstatic void config_file_loaded(void *opaque, uint8_t *buf, int buf_len)\n{\n    VMConfigLoadState *s = opaque;\n    VirtMachineParams *p = s->vm_params;\n\n    if (virt_machine_parse_config(p, (char *)buf, buf_len) < 0)\n        exit(1);\n    \n    /* load the additional files */\n    s->file_index = 0;\n    config_additional_file_load(s);\n}\n\nstatic void config_additional_file_load(VMConfigLoadState *s)\n{\n    VirtMachineParams *p = s->vm_params;\n    while (s->file_index < VM_FILE_COUNT &&\n           p->files[s->file_index].filename == NULL) {\n        s->file_index++;\n    }\n    if (s->file_index == VM_FILE_COUNT) {\n        if (s->start_cb)\n            s->start_cb(s->opaque);\n        free(s);\n    } else {\n        char *fname;\n        \n        fname = get_file_path(p->cfg_filename,\n                              p->files[s->file_index].filename);\n        config_load_file(s, fname,\n                         config_additional_file_load_cb, s);\n        free(fname);\n    }\n}\n\nstatic void config_additional_file_load_cb(void *opaque,\n                                           uint8_t *buf, int buf_len)\n{\n    VMConfigLoadState *s = opaque;\n    VirtMachineParams *p = s->vm_params;\n\n    p->files[s->file_index].buf = malloc(buf_len);\n    memcpy(p->files[s->file_index].buf, buf, buf_len);\n    p->files[s->file_index].len = buf_len;\n\n    /* load the next files */\n    s->file_index++;\n    config_additional_file_load(s);\n}\n\nvoid vm_add_cmdline(VirtMachineParams *p, const char *cmdline)\n{\n    char *new_cmdline, *old_cmdline;\n    if (cmdline[0] == '!') {\n        new_cmdline = strdup(cmdline + 1);\n    } else {\n        old_cmdline = p->cmdline;\n        if (!old_cmdline)\n            old_cmdline = \"\";\n        new_cmdline = malloc(strlen(old_cmdline) + 1 + strlen(cmdline) + 1);\n        strcpy(new_cmdline, old_cmdline);\n        strcat(new_cmdline, \" \");\n        strcat(new_cmdline, cmdline);\n    }\n    free(p->cmdline);\n    p->cmdline = new_cmdline;\n}\n\nvoid virt_machine_free_config(VirtMachineParams *p)\n{\n    int i;\n    \n    free(p->machine_name);\n    free(p->cmdline);\n    for(i = 0; i < VM_FILE_COUNT; i++) {\n        free(p->files[i].filename);\n        free(p->files[i].buf);\n    }\n    for(i = 0; i < p->drive_count; i++) {\n        free(p->tab_drive[i].filename);\n        free(p->tab_drive[i].device);\n    }\n    for(i = 0; i < p->fs_count; i++) {\n        free(p->tab_fs[i].filename);\n        free(p->tab_fs[i].tag);\n    }\n    for(i = 0; i < p->eth_count; i++) {\n        free(p->tab_eth[i].driver);\n        free(p->tab_eth[i].ifname);\n    }\n    free(p->input_device);\n    free(p->display_device);\n    free(p->cfg_filename);\n}\n\nVirtMachine *virt_machine_init(const VirtMachineParams *p)\n{\n    const VirtMachineClass *vmc = p->vmc;\n    return vmc->virt_machine_init(p);\n}\n\nvoid virt_machine_set_defaults(VirtMachineParams *p)\n{\n    memset(p, 0, sizeof(*p));\n    p->sim_params = sim_params_init();\n}\n\nvoid virt_machine_end(VirtMachine *s)\n{\n    s->vmc->virt_machine_end(s);\n}\n"
  },
  {
    "path": "src/machine.h",
    "content": "/*\n * VM definitions\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"json.h\"\n\ntypedef struct SimParams SimParams;\n\ntypedef struct FBDevice FBDevice;\n\ntypedef void SimpleFBDrawFunc(FBDevice *fb_dev, void *opaque,\n                              int x, int y, int w, int h);\n\nstruct FBDevice {\n    /* the following is set by the device */\n    int width;\n    int height;\n    int stride; /* current stride in bytes */\n    uint8_t *fb_data; /* current pointer to the pixel data */\n    int fb_size; /* frame buffer memory size (info only) */\n    void *device_opaque;\n    void (*refresh)(struct FBDevice *fb_dev,\n                    SimpleFBDrawFunc *redraw_func, void *opaque);\n};\n\n#define MAX_DRIVE_DEVICE 4\n#define MAX_FS_DEVICE 4\n#define MAX_ETH_DEVICE 1\n\n#define VM_CONFIG_VERSION 1\n\ntypedef enum {\n    VM_FILE_BIOS,\n    VM_FILE_VGA_BIOS,\n    VM_FILE_KERNEL,\n    VM_FILE_INITRD,\n\n    VM_FILE_COUNT,\n} VMFileTypeEnum;\n\ntypedef struct {\n    char *filename;\n    uint8_t *buf;\n    int len;\n} VMFileEntry;\n\ntypedef struct {\n    char *device;\n    char *filename;\n    BlockDevice *block_dev;\n} VMDriveEntry;\n\ntypedef struct {\n    char *device;\n    char *tag; /* 9p mount tag */\n    char *filename;\n    FSDevice *fs_dev;\n} VMFSEntry;\n\ntypedef struct {\n    char *driver;\n    char *ifname;\n    EthernetDevice *net;\n} VMEthEntry;\n\ntypedef struct VirtMachineClass VirtMachineClass;\n\ntypedef struct {\n    char *cfg_filename;\n    const VirtMachineClass *vmc;\n    char *machine_name;\n    uint64_t ram_size;\n    BOOL rtc_real_time;\n    BOOL rtc_local_time;\n    char *display_device; /* NULL means no display */\n    int width, height; /* graphic width & height */\n    CharacterDevice *console;\n    VMDriveEntry tab_drive[MAX_DRIVE_DEVICE];\n    int drive_count;\n    VMFSEntry tab_fs[MAX_FS_DEVICE];\n    int fs_count;\n    VMEthEntry tab_eth[MAX_ETH_DEVICE];\n    int eth_count;\n\n    char *cmdline; /* bios or kernel command line */\n    BOOL accel_enable; /* enable acceleration (KVM) */\n    char *input_device; /* NULL means no input */\n    \n    /* kernel, bios and other auxiliary files */\n    VMFileEntry files[VM_FILE_COUNT];\n\n    /* Simulation parameters used by MARSS-RISCV */\n    SimParams *sim_params;\n} VirtMachineParams;\n\ntypedef struct VirtMachine {\n    const VirtMachineClass *vmc;\n    /* network */\n    EthernetDevice *net;\n    /* console */\n    VIRTIODevice *console_dev;\n    CharacterDevice *console;\n    /* graphics */\n    FBDevice *fb_dev;\n    /* params: Keep track to free simulator params */\n    VirtMachineParams *virt_machine_params;\n} VirtMachine;\n\nstruct VirtMachineClass {\n    const char *machine_names;\n    void (*virt_machine_set_defaults)(VirtMachineParams *p);\n    VirtMachine *(*virt_machine_init)(const VirtMachineParams *p);\n    void (*virt_machine_end)(VirtMachine *s);\n    int (*virt_machine_get_sleep_duration)(VirtMachine *s, int delay);\n    void (*virt_machine_interp)(VirtMachine *s, int max_exec_cycle);\n    BOOL (*vm_mouse_is_absolute)(VirtMachine *s);\n    void (*vm_send_mouse_event)(VirtMachine *s1, int dx, int dy, int dz,\n                                unsigned int buttons);\n    void (*vm_send_key_event)(VirtMachine *s1, BOOL is_down, uint16_t key_code);\n};\n\nextern const VirtMachineClass riscv_machine_class;\nextern const VirtMachineClass pc_machine_class;\n\nvoid __attribute__((format(printf, 1, 2))) vm_error(const char *fmt, ...);\nint vm_get_int(JSONValue obj, const char *name, int *pval);\nint vm_get_int_opt(JSONValue obj, const char *name, int *pval, int def_val);\n\nvoid virt_machine_set_defaults(VirtMachineParams *p);\nvoid virt_machine_load_config_file(VirtMachineParams *p,\n                                   const char *filename,\n                                   void (*start_cb)(void *opaque),\n                                   void *opaque);\nvoid vm_add_cmdline(VirtMachineParams *p, const char *cmdline);\nchar *get_file_path(const char *base_filename, const char *filename);\nvoid virt_machine_free_config(VirtMachineParams *p);\nVirtMachine *virt_machine_init(const VirtMachineParams *p);\nvoid virt_machine_end(VirtMachine *s);\nstatic inline int virt_machine_get_sleep_duration(VirtMachine *s, int delay)\n{\n    return s->vmc->virt_machine_get_sleep_duration(s, delay);\n}\nstatic inline void virt_machine_interp(VirtMachine *s, int max_exec_cycle)\n{\n    s->vmc->virt_machine_interp(s, max_exec_cycle);\n}\nstatic inline BOOL vm_mouse_is_absolute(VirtMachine *s)\n{\n    return s->vmc->vm_mouse_is_absolute(s);\n}\nstatic inline void vm_send_mouse_event(VirtMachine *s1, int dx, int dy, int dz,\n                                       unsigned int buttons)\n{\n    s1->vmc->vm_send_mouse_event(s1, dx, dy, dz, buttons);\n}\nstatic inline void vm_send_key_event(VirtMachine *s1, BOOL is_down, uint16_t key_code)\n{\n    s1->vmc->vm_send_key_event(s1, is_down, key_code);\n}\n\n/* gui */\nvoid sdl_refresh(VirtMachine *m);\nvoid sdl_init(int width, int height);\n\n/* simplefb.c */\ntypedef struct SimpleFBState SimpleFBState;\nSimpleFBState *simplefb_init(PhysMemoryMap *map, uint64_t phys_addr,\n                             FBDevice *fb_dev, int width, int height);\nvoid simplefb_refresh(FBDevice *fb_dev,\n                      SimpleFBDrawFunc *redraw_func, void *opaque,\n                      PhysMemoryRange *mem_range,\n                      int fb_page_count);\n\n/* vga.c */\ntypedef struct VGAState VGAState;\nVGAState *pci_vga_init(PCIBus *bus, FBDevice *fb_dev,\n                       int width, int height,\n                       const uint8_t *vga_rom_buf, int vga_rom_size);\n                      \n/* block_net.c */\nBlockDevice *block_device_init_http(const char *url,\n                                    int max_cache_size_kb,\n                                    void (*start_cb)(void *opaque),\n                                    void *start_opaque);\n\n/* riscv_machine.c */\nvoid uart_rx_data(VirtMachine *v, uint8_t *buf, int size);\nint  uart_can_rx(VirtMachine *v);\n\n"
  },
  {
    "path": "src/netinit.sh",
    "content": "#!/bin/sh\n#\n# RISCVEMU Ethernet bridge and NAT configuration (run with sudo)\n#\n# Copyright (c) 2017 Fabrice Bellard\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\n# host network interface connected to Internet (change it)\ninternet_ifname=\"enp0s20f0u1\"\n\n# setup bridge interface\nip link add br0 type bridge\n# create and add tap0 interface to bridge\nip tuntap add dev tap0 mode tap user $USER\nip link set tap0 master br0\n\nip link set dev br0 up\nip link set dev tap0 up\nifconfig br0 192.168.3.1\n\n# setup NAT to access to Internet\necho 1 > /proc/sys/net/ipv4/ip_forward\n# delete forwarding reject rule if present\n#iptables -D FORWARD 1\niptables -t nat -A POSTROUTING -o $internet_ifname -j MASQUERADE \n"
  },
  {
    "path": "src/pci.c",
    "content": "/*\n * Simple PCI bus driver\n * \n * Copyright (c) 2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <stdarg.h>\n\n#include \"cutils.h\"\n#include \"pci.h\"\n\n//#define DEBUG_CONFIG\n\ntypedef struct {\n    uint32_t size; /* 0 means no mapping defined */\n    uint8_t type;\n    uint8_t enabled; /* true if mapping is enabled */\n    void *opaque;\n    PCIBarSetFunc *bar_set;\n} PCIIORegion;\n\nstruct PCIDevice {\n    PCIBus *bus;\n    uint8_t devfn;\n    IRQSignal irq[4];\n    uint8_t config[256];\n    uint8_t next_cap_offset; /* offset of the next capability */\n    char *name; /* for debug only */\n    PCIIORegion io_regions[PCI_NUM_REGIONS];\n};\n\nstruct PCIBus {\n    int bus_num;\n    PCIDevice *device[256];\n    PhysMemoryMap *mem_map;\n    PhysMemoryMap *port_map;\n    uint32_t irq_state[4][8]; /* one bit per device */\n    IRQSignal irq[4];\n};\n\nstatic int bus_map_irq(PCIDevice *d, int irq_num)\n{\n    int slot_addend;\n    slot_addend = (d->devfn >> 3) - 1;\n    return (irq_num + slot_addend) & 3;\n}\n\nstatic void pci_device_set_irq(void *opaque, int irq_num, int level)\n{\n    PCIDevice *d = opaque;\n    PCIBus *b = d->bus;\n    uint32_t mask;\n    int i, irq_level;\n    \n    //    printf(\"%s: pci_device_seq_irq: %d %d\\n\", d->name, irq_num, level);\n    irq_num = bus_map_irq(d, irq_num);\n    mask = 1 << (d->devfn & 0x1f);\n    if (level)\n        b->irq_state[irq_num][d->devfn >> 5] |= mask;\n    else\n        b->irq_state[irq_num][d->devfn >> 5] &= ~mask;\n\n    /* compute the IRQ state */\n    mask = 0;\n    for(i = 0; i < 8; i++)\n        mask |= b->irq_state[irq_num][i];\n    irq_level = (mask != 0);\n    set_irq(&b->irq[irq_num], irq_level);\n}\n\nstatic int devfn_alloc(PCIBus *b)\n{\n    int devfn;\n    for(devfn = 0; devfn < 256; devfn += 8) {\n        if (!b->device[devfn])\n            return devfn;\n    }\n    return -1;\n}\n\n/* devfn < 0 means to allocate it */\nPCIDevice *pci_register_device(PCIBus *b, const char *name, int devfn,\n                               uint16_t vendor_id, uint16_t device_id,\n                               uint8_t revision, uint16_t class_id)\n{\n    PCIDevice *d;\n    int i;\n    \n    if (devfn < 0) {\n        devfn = devfn_alloc(b);\n        if (devfn < 0)\n            return NULL;\n    }\n    if (b->device[devfn])\n        return NULL;\n\n    d = mallocz(sizeof(PCIDevice));\n    d->bus = b;\n    d->name = strdup(name);\n    d->devfn = devfn;\n\n    put_le16(d->config + 0x00, vendor_id);\n    put_le16(d->config + 0x02, device_id);\n    d->config[0x08] = revision;\n    put_le16(d->config + 0x0a, class_id);\n    d->config[0x0e] = 0x00; /* header type */\n    d->next_cap_offset = 0x40;\n    \n    for(i = 0; i < 4; i++)\n        irq_init(&d->irq[i], pci_device_set_irq, d, i);\n    b->device[devfn] = d;\n\n    return d;\n}\n\nIRQSignal *pci_device_get_irq(PCIDevice *d, unsigned int irq_num)\n{\n    assert(irq_num < 4);\n    return &d->irq[irq_num];\n}\n\nstatic uint32_t pci_device_config_read(PCIDevice *d, uint32_t addr,\n                                       int size_log2)\n{\n    uint32_t val;\n    switch(size_log2) {\n    case 0:\n        val = *(uint8_t *)(d->config + addr);\n        break;\n    case 1:\n        /* Note: may be unaligned */\n        if (addr <= 0xfe)\n            val = get_le16(d->config + addr);\n        else\n            val = *(uint8_t *)(d->config + addr);\n        break;\n    case 2:\n        /* always aligned */\n        val = get_le32(d->config + addr);\n        break;\n    default:\n        abort();\n    }\n#ifdef DEBUG_CONFIG\n    printf(\"pci_config_read: dev=%s addr=0x%02x val=0x%x s=%d\\n\",\n           d->name, addr, val, 1 << size_log2);\n#endif\n    return val;\n}\n\nPhysMemoryMap *pci_device_get_mem_map(PCIDevice *d)\n{\n    return d->bus->mem_map;\n}\n\nPhysMemoryMap *pci_device_get_port_map(PCIDevice *d)\n{\n    return d->bus->port_map;\n}\n\nvoid pci_register_bar(PCIDevice *d, unsigned int bar_num,\n                      uint32_t size, int type,\n                      void *opaque, PCIBarSetFunc *bar_set)\n{\n    PCIIORegion *r;\n    uint32_t val, config_addr;\n    \n    assert(bar_num < PCI_NUM_REGIONS);\n    assert((size & (size - 1)) == 0); /* power of two */\n    assert(size >= 4);\n    r = &d->io_regions[bar_num];\n    assert(r->size == 0);\n    r->size = size;\n    r->type = type;\n    r->enabled = FALSE;\n    r->opaque = opaque;\n    r->bar_set = bar_set;\n    /* set the config value */\n    val = 0;\n    if (bar_num == PCI_ROM_SLOT) {\n        config_addr = 0x30;\n    } else {\n        val |= r->type;\n        config_addr = 0x10 + 4 * bar_num;\n    }\n    put_le32(&d->config[config_addr], val);\n}\n\nstatic void pci_update_mappings(PCIDevice *d)\n{\n    int cmd, i, offset;\n    uint32_t new_addr;\n    BOOL new_enabled;\n    PCIIORegion *r;\n    \n    cmd = get_le16(&d->config[PCI_COMMAND]);\n\n    for(i = 0; i < PCI_NUM_REGIONS; i++) {\n        r = &d->io_regions[i];\n        if (i == PCI_ROM_SLOT) {\n            offset = 0x30;\n        } else {\n            offset = 0x10 + i * 4;\n        }\n        new_addr = get_le32(&d->config[offset]);\n        new_enabled = FALSE;\n        if (r->size != 0) {\n            if ((r->type & PCI_ADDRESS_SPACE_IO) &&\n                (cmd & PCI_COMMAND_IO)) {\n                new_enabled = TRUE;\n            } else {\n                if (cmd & PCI_COMMAND_MEMORY) {\n                    if (i == PCI_ROM_SLOT) {\n                        new_enabled = (new_addr & 1);\n                    } else {\n                        new_enabled = TRUE;\n                    }\n                }\n            }\n        }\n        if (new_enabled) {\n            /* new address */\n            new_addr = get_le32(&d->config[offset]) & ~(r->size - 1);\n            r->bar_set(r->opaque, i, new_addr, TRUE);\n            r->enabled = TRUE;\n        } else if (r->enabled) {\n            r->bar_set(r->opaque, i, 0, FALSE);\n            r->enabled = FALSE;\n        }\n    }\n}\n\n/* return != 0 if write is not handled */\nstatic int pci_write_bar(PCIDevice *d, uint32_t addr,\n                          uint32_t val)\n{\n    PCIIORegion *r;\n    int reg;\n    \n    if (addr == 0x30)\n        reg = PCI_ROM_SLOT;\n    else\n        reg = (addr - 0x10) >> 2;\n    //    printf(\"%s: write bar addr=%x data=%x\\n\", d->name, addr, val);\n    r = &d->io_regions[reg];\n    if (r->size == 0)\n        return -1;\n    if (reg == PCI_ROM_SLOT) {\n        val = val & ((~(r->size - 1)) | 1);\n    } else {\n        val = (val & ~(r->size - 1)) | r->type;\n    }\n    put_le32(d->config + addr, val);\n    pci_update_mappings(d);\n    return 0;\n}\n\nstatic void pci_device_config_write8(PCIDevice *d, uint32_t addr,\n                                     uint32_t data)\n{\n    int can_write;\n\n    if (addr == PCI_STATUS || addr == (PCI_STATUS + 1)) {\n        /* write 1 reset bits */\n        d->config[addr] &= ~data;\n        return;\n    }\n    \n    switch(d->config[0x0e]) {\n    case 0x00:\n    case 0x80:\n        switch(addr) {\n        case 0x00:\n        case 0x01:\n        case 0x02:\n        case 0x03:\n        case 0x08:\n        case 0x09:\n        case 0x0a:\n        case 0x0b:\n        case 0x0e:\n        case 0x10 ... 0x27: /* base */\n        case 0x30 ... 0x33: /* rom */\n        case 0x3d:\n            can_write = 0;\n            break;\n        default:\n            can_write = 1;\n            break;\n        }\n        break;\n    default:\n    case 0x01:\n        switch(addr) {\n        case 0x00:\n        case 0x01:\n        case 0x02:\n        case 0x03:\n        case 0x08:\n        case 0x09:\n        case 0x0a:\n        case 0x0b:\n        case 0x0e:\n        case 0x38 ... 0x3b: /* rom */\n        case 0x3d:\n            can_write = 0;\n            break;\n        default:\n            can_write = 1;\n            break;\n        }\n        break;\n    }\n    if (can_write)\n        d->config[addr] = data;\n}\n                                  \n\nstatic void pci_device_config_write(PCIDevice *d, uint32_t addr,\n                                    uint32_t data, int size_log2)\n{\n    int size, i;\n    uint32_t addr1;\n    \n#ifdef DEBUG_CONFIG\n    printf(\"pci_config_write: dev=%s addr=0x%02x val=0x%x s=%d\\n\",\n           d->name, addr, data, 1 << size_log2);\n#endif\n    if (size_log2 == 2 &&\n        ((addr >= 0x10 && addr < 0x10 + 4 * 6) ||\n         addr == 0x30)) {\n        if (pci_write_bar(d, addr, data) == 0)\n            return;\n    }\n    size = 1 << size_log2;\n    for(i = 0; i < size; i++) {\n        addr1 = addr + i;\n        if (addr1 <= 0xff) {\n            pci_device_config_write8(d, addr1, (data >> (i * 8)) & 0xff);\n        }\n    }\n    if (PCI_COMMAND >= addr && PCI_COMMAND < addr + size) {\n        pci_update_mappings(d);\n    }\n}\n\n\nstatic void pci_data_write(PCIBus *s, uint32_t addr,\n                           uint32_t data, int size_log2)\n{\n    PCIDevice *d;\n    int bus_num, devfn, config_addr;\n    \n    bus_num = (addr >> 16) & 0xff;\n    if (bus_num != s->bus_num)\n        return;\n    devfn = (addr >> 8) & 0xff;\n    d = s->device[devfn];\n    if (!d)\n        return;\n    config_addr = addr & 0xff;\n    pci_device_config_write(d, config_addr, data, size_log2);\n}\n\nstatic const uint32_t val_ones[3] = { 0xff, 0xffff, 0xffffffff };\n\nstatic uint32_t pci_data_read(PCIBus *s, uint32_t addr, int size_log2)\n{\n    PCIDevice *d;\n    int bus_num, devfn, config_addr;\n    \n    bus_num = (addr >> 16) & 0xff;\n    if (bus_num != s->bus_num)\n        return val_ones[size_log2];\n    devfn = (addr >> 8) & 0xff;\n    d = s->device[devfn];\n    if (!d)\n        return val_ones[size_log2];\n    config_addr = addr & 0xff;\n    return pci_device_config_read(d, config_addr, size_log2);\n}\n\n/* warning: only valid for one DEVIO page. Return NULL if no memory at\n   the given address */\nuint8_t *pci_device_get_dma_ptr(PCIDevice *d, uint64_t addr, BOOL is_rw)\n{\n    return phys_mem_get_ram_ptr(d->bus->mem_map, addr, is_rw);\n}\n\nvoid pci_device_set_config8(PCIDevice *d, uint8_t addr, uint8_t val)\n{\n    d->config[addr] = val;\n}\n\nvoid pci_device_set_config16(PCIDevice *d, uint8_t addr, uint16_t val)\n{\n    put_le16(&d->config[addr], val);\n}\n\nint pci_device_get_devfn(PCIDevice *d)\n{\n    return d->devfn;\n}\n\n/* return the offset of the capability or < 0 if error. */\nint pci_add_capability(PCIDevice *d, const uint8_t *buf, int size)\n{\n    int offset;\n    \n    offset = d->next_cap_offset;\n    if ((offset + size) > 256)\n        return -1;\n    d->next_cap_offset += size;\n    d->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST;\n    memcpy(d->config + offset, buf, size);\n    d->config[offset + 1] = d->config[PCI_CAPABILITY_LIST];\n    d->config[PCI_CAPABILITY_LIST] = offset;\n    return offset;\n}\n\n/* i440FX host bridge */\n\nstruct I440FXState {\n    PCIBus *pci_bus;\n    PCIDevice *pci_dev;\n    PCIDevice *piix3_dev;\n    uint32_t config_reg;\n    uint8_t pic_irq_state[16];\n    IRQSignal *pic_irqs; /* 16 irqs */\n};\n\nstatic void i440fx_write_addr(void *opaque, uint32_t offset,\n                              uint32_t data, int size_log2)\n{\n    I440FXState *s = opaque;\n    s->config_reg = data;\n}\n\nstatic uint32_t i440fx_read_addr(void *opaque, uint32_t offset, int size_log2)\n{\n    I440FXState *s = opaque;\n    return s->config_reg;\n}\n\nstatic void i440fx_write_data(void *opaque, uint32_t offset,\n                              uint32_t data, int size_log2)\n{\n    I440FXState *s = opaque;\n    if (s->config_reg & 0x80000000) {\n        if (size_log2 == 2) {\n            /* it is simpler to assume 32 bit config accesses are\n               always aligned */\n            pci_data_write(s->pci_bus, s->config_reg & ~3, data, size_log2);\n        } else {\n            pci_data_write(s->pci_bus, s->config_reg | offset, data, size_log2);\n        }\n    }\n}\n\nstatic uint32_t i440fx_read_data(void *opaque, uint32_t offset, int size_log2)\n{\n    I440FXState *s = opaque;\n    if (!(s->config_reg & 0x80000000))\n        return val_ones[size_log2];\n    if (size_log2 == 2) {\n        /* it is simpler to assume 32 bit config accesses are\n           always aligned */\n        return pci_data_read(s->pci_bus, s->config_reg & ~3, size_log2);\n    } else {\n        return pci_data_read(s->pci_bus, s->config_reg | offset, size_log2);\n    }\n}\n\nstatic void i440fx_set_irq(void *opaque, int irq_num, int irq_level)\n{\n    I440FXState *s = opaque;\n    PCIDevice *hd = s->piix3_dev;\n    int pic_irq;\n    \n    /* map to the PIC irq (different IRQs can be mapped to the same\n       PIC irq) */\n    hd->config[0x60 + irq_num] &= ~0x80;\n    pic_irq = hd->config[0x60 + irq_num];\n    if (pic_irq < 16) {\n        if (irq_level)\n            s->pic_irq_state[pic_irq] |= 1 << irq_num;\n        else\n            s->pic_irq_state[pic_irq] &= ~(1 << irq_num);\n        set_irq(&s->pic_irqs[pic_irq], (s->pic_irq_state[pic_irq] != 0));\n    }\n}\n\nI440FXState *i440fx_init(PCIBus **pbus, int *ppiix3_devfn,\n                         PhysMemoryMap *mem_map, PhysMemoryMap *port_map,\n                         IRQSignal *pic_irqs)\n{\n    I440FXState *s;\n    PCIBus *b;\n    PCIDevice *d;\n    int i;\n    \n    s = mallocz(sizeof(*s));\n    \n    b = mallocz(sizeof(PCIBus));\n    b->bus_num = 0;\n    b->mem_map = mem_map;\n    b->port_map = port_map;\n\n    s->pic_irqs = pic_irqs;\n    for(i = 0; i < 4; i++) {\n        irq_init(&b->irq[i], i440fx_set_irq, s, i);\n    }\n    \n    cpu_register_device(port_map, 0xcf8, 1, s, i440fx_read_addr, i440fx_write_addr, \n                        DEVIO_SIZE32);\n    cpu_register_device(port_map, 0xcfc, 4, s, i440fx_read_data, i440fx_write_data, \n                        DEVIO_SIZE8 | DEVIO_SIZE16 | DEVIO_SIZE32);\n    d = pci_register_device(b, \"i440FX\", 0, 0x8086, 0x1237, 0x02, 0x0600);\n    put_le16(&d->config[PCI_SUBSYSTEM_VENDOR_ID], 0x1af4); /* Red Hat, Inc. */\n    put_le16(&d->config[PCI_SUBSYSTEM_ID], 0x1100); /* QEMU virtual machine */\n    \n    s->pci_dev = d;\n    s->pci_bus = b;\n\n    s->piix3_dev = pci_register_device(b, \"PIIX3\", 8, 0x8086, 0x7000,\n                                       0x00, 0x0601);\n    pci_device_set_config8(s->piix3_dev, 0x0e, 0x80); /* header type */\n\n    *pbus = b;\n    *ppiix3_devfn = s->piix3_dev->devfn;\n    return s;\n}\n\n/* in case no BIOS is used, map the interrupts. */\nvoid i440fx_map_interrupts(I440FXState *s, uint8_t *elcr,\n                           const uint8_t *pci_irqs)\n{\n    PCIBus *b = s->pci_bus;\n    PCIDevice *d, *hd;\n    int irq_num, pic_irq, devfn, i;\n    \n    /* set a default PCI IRQ mapping to PIC IRQs */\n    hd = s->piix3_dev;\n\n    elcr[0] = 0;\n    elcr[1] = 0;\n    for(i = 0; i < 4; i++) {\n        irq_num = pci_irqs[i];\n        hd->config[0x60 + i] = irq_num;\n        elcr[irq_num >> 3] |= (1 << (irq_num & 7));\n    }\n\n    for(devfn = 0; devfn < 256; devfn++) {\n        d = b->device[devfn];\n        if (!d)\n            continue;\n        if (d->config[PCI_INTERRUPT_PIN]) {\n            irq_num = 0;\n            irq_num = bus_map_irq(d, irq_num);\n            pic_irq = hd->config[0x60 + irq_num];\n            if (pic_irq < 16) {\n                d->config[PCI_INTERRUPT_LINE] = pic_irq;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/pci.h",
    "content": "/*\n * Simple PCI bus driver\n * \n * Copyright (c) 2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef PCI_H\n#define PCI_H\n\n#include \"iomem.h\"\n\ntypedef struct PCIBus PCIBus;\ntypedef struct PCIDevice PCIDevice;\n\n/* bar type */\n#define PCI_ADDRESS_SPACE_MEM\t\t0x00\n#define PCI_ADDRESS_SPACE_IO\t\t0x01\n#define PCI_ADDRESS_SPACE_MEM_PREFETCH\t0x08\n\n#define PCI_ROM_SLOT 6\n#define PCI_NUM_REGIONS 7\n\n/* PCI config addresses */\n#define PCI_VENDOR_ID\t\t0x00\t/* 16 bits */\n#define PCI_DEVICE_ID\t\t0x02\t/* 16 bits */\n#define PCI_COMMAND\t\t0x04\t/* 16 bits */\n#define PCI_COMMAND_IO\t\t(1 << 0)\n#define PCI_COMMAND_MEMORY\t(1 << 1)\n#define PCI_STATUS\t\t0x06\t/* 16 bits */\n#define  PCI_STATUS_CAP_LIST\t(1 << 4)\n#define PCI_CLASS_PROG\t\t0x09\n#define PCI_SUBSYSTEM_VENDOR_ID\t0x2c    /* 16 bits */\n#define PCI_SUBSYSTEM_ID\t0x2e    /* 16 bits */\n#define PCI_CAPABILITY_LIST\t0x34    /* 8 bits */\n#define PCI_INTERRUPT_LINE\t0x3c    /* 8 bits */\n#define PCI_INTERRUPT_PIN\t0x3d    /* 8 bits */\n\ntypedef void PCIBarSetFunc(void *opaque, int bar_num, uint32_t addr,\n                           BOOL enabled);\n\nPCIDevice *pci_register_device(PCIBus *b, const char *name, int devfn,\n                               uint16_t vendor_id, uint16_t device_id,\n                               uint8_t revision, uint16_t class_id);\nPhysMemoryMap *pci_device_get_mem_map(PCIDevice *d);\nPhysMemoryMap *pci_device_get_port_map(PCIDevice *d);\nvoid pci_register_bar(PCIDevice *d, unsigned int bar_num,\n                      uint32_t size, int type,\n                      void *opaque, PCIBarSetFunc *bar_set);\nIRQSignal *pci_device_get_irq(PCIDevice *d, unsigned int irq_num);\nuint8_t *pci_device_get_dma_ptr(PCIDevice *d, uint64_t addr, BOOL is_rw);\nvoid pci_device_set_config8(PCIDevice *d, uint8_t addr, uint8_t val);\nvoid pci_device_set_config16(PCIDevice *d, uint8_t addr, uint16_t val);\nint pci_device_get_devfn(PCIDevice *d);\nint pci_add_capability(PCIDevice *d, const uint8_t *buf, int size);\n\ntypedef struct I440FXState I440FXState;\n\nI440FXState *i440fx_init(PCIBus **pbus, int *ppiix3_devfn,\n                         PhysMemoryMap *mem_map, PhysMemoryMap *port_map,\n                         IRQSignal *pic_irqs);\nvoid i440fx_map_interrupts(I440FXState *s, uint8_t *elcr,\n                           const uint8_t *pci_irqs);\n\n#endif /* PCI_H */\n"
  },
  {
    "path": "src/pckbd.c",
    "content": "/*\n * QEMU PC keyboard emulation\n *\n * Copyright (c) 2003 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n\n#include \"cutils.h\"\n#include \"iomem.h\"\n#include \"ps2.h\"\n#include \"virtio.h\"\n#include \"machine.h\"\n\n/* debug PC keyboard */\n//#define DEBUG_KBD\n\n/* debug PC keyboard : only mouse */\n//#define DEBUG_MOUSE\n\n/*\tKeyboard Controller Commands */\n#define KBD_CCMD_READ_MODE\t0x20\t/* Read mode bits */\n#define KBD_CCMD_WRITE_MODE\t0x60\t/* Write mode bits */\n#define KBD_CCMD_GET_VERSION\t0xA1\t/* Get controller version */\n#define KBD_CCMD_MOUSE_DISABLE\t0xA7\t/* Disable mouse interface */\n#define KBD_CCMD_MOUSE_ENABLE\t0xA8\t/* Enable mouse interface */\n#define KBD_CCMD_TEST_MOUSE\t0xA9\t/* Mouse interface test */\n#define KBD_CCMD_SELF_TEST\t0xAA\t/* Controller self test */\n#define KBD_CCMD_KBD_TEST\t0xAB\t/* Keyboard interface test */\n#define KBD_CCMD_KBD_DISABLE\t0xAD\t/* Keyboard interface disable */\n#define KBD_CCMD_KBD_ENABLE\t0xAE\t/* Keyboard interface enable */\n#define KBD_CCMD_READ_INPORT    0xC0    /* read input port */\n#define KBD_CCMD_READ_OUTPORT\t0xD0    /* read output port */\n#define KBD_CCMD_WRITE_OUTPORT\t0xD1    /* write output port */\n#define KBD_CCMD_WRITE_OBUF\t0xD2\n#define KBD_CCMD_WRITE_AUX_OBUF\t0xD3    /* Write to output buffer as if\n\t\t\t\t\t   initiated by the auxiliary device */\n#define KBD_CCMD_WRITE_MOUSE\t0xD4\t/* Write the following byte to the mouse */\n#define KBD_CCMD_DISABLE_A20    0xDD    /* HP vectra only ? */\n#define KBD_CCMD_ENABLE_A20     0xDF    /* HP vectra only ? */\n#define KBD_CCMD_RESET\t        0xFE\n\n/* Status Register Bits */\n#define KBD_STAT_OBF \t\t0x01\t/* Keyboard output buffer full */\n#define KBD_STAT_IBF \t\t0x02\t/* Keyboard input buffer full */\n#define KBD_STAT_SELFTEST\t0x04\t/* Self test successful */\n#define KBD_STAT_CMD\t\t0x08\t/* Last write was a command write (0=data) */\n#define KBD_STAT_UNLOCKED\t0x10\t/* Zero if keyboard locked */\n#define KBD_STAT_MOUSE_OBF\t0x20\t/* Mouse output buffer full */\n#define KBD_STAT_GTO \t\t0x40\t/* General receive/xmit timeout */\n#define KBD_STAT_PERR \t\t0x80\t/* Parity error */\n\n/* Controller Mode Register Bits */\n#define KBD_MODE_KBD_INT\t0x01\t/* Keyboard data generate IRQ1 */\n#define KBD_MODE_MOUSE_INT\t0x02\t/* Mouse data generate IRQ12 */\n#define KBD_MODE_SYS \t\t0x04\t/* The system flag (?) */\n#define KBD_MODE_NO_KEYLOCK\t0x08\t/* The keylock doesn't affect the keyboard if set */\n#define KBD_MODE_DISABLE_KBD\t0x10\t/* Disable keyboard interface */\n#define KBD_MODE_DISABLE_MOUSE\t0x20\t/* Disable mouse interface */\n#define KBD_MODE_KCC \t\t0x40\t/* Scan code conversion to PC format */\n#define KBD_MODE_RFU\t\t0x80\n\n#define KBD_PENDING_KBD         1\n#define KBD_PENDING_AUX         2\n\nstruct KBDState {\n    uint8_t write_cmd; /* if non zero, write data to port 60 is expected */\n    uint8_t status;\n    uint8_t mode;\n    /* Bitmask of devices with data available.  */\n    uint8_t pending;\n    PS2KbdState *kbd;\n    PS2MouseState *mouse;\n\n    IRQSignal *irq_kbd;\n    IRQSignal *irq_mouse;\n};\n\nstatic void qemu_system_reset_request(void)\n{\n    printf(\"system_reset_request\\n\");\n    exit(1);\n    /* XXX */\n}\n\nstatic void ioport_set_a20(int val)\n{\n}\n\nstatic int ioport_get_a20(void)\n{\n    return 1;\n}\n\n/* update irq and KBD_STAT_[MOUSE_]OBF */\n/* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be\n   incorrect, but it avoids having to simulate exact delays */\nstatic void kbd_update_irq(KBDState *s)\n{\n    int irq_kbd_level, irq_mouse_level;\n\n    irq_kbd_level = 0;\n    irq_mouse_level = 0;\n    s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);\n    if (s->pending) {\n        s->status |= KBD_STAT_OBF;\n        /* kbd data takes priority over aux data.  */\n        if (s->pending == KBD_PENDING_AUX) {\n            s->status |= KBD_STAT_MOUSE_OBF;\n            if (s->mode & KBD_MODE_MOUSE_INT)\n                irq_mouse_level = 1;\n        } else {\n            if ((s->mode & KBD_MODE_KBD_INT) &&\n                !(s->mode & KBD_MODE_DISABLE_KBD))\n                irq_kbd_level = 1;\n        }\n    }\n    set_irq(s->irq_kbd, irq_kbd_level);\n    set_irq(s->irq_mouse, irq_mouse_level);\n}\n\nstatic void kbd_update_kbd_irq(void *opaque, int level)\n{\n    KBDState *s = (KBDState *)opaque;\n\n    if (level)\n        s->pending |= KBD_PENDING_KBD;\n    else\n        s->pending &= ~KBD_PENDING_KBD;\n    kbd_update_irq(s);\n}\n\nstatic void kbd_update_aux_irq(void *opaque, int level)\n{\n    KBDState *s = (KBDState *)opaque;\n\n    if (level)\n        s->pending |= KBD_PENDING_AUX;\n    else\n        s->pending &= ~KBD_PENDING_AUX;\n    kbd_update_irq(s);\n}\n\nstatic uint32_t kbd_read_status(void *opaque, uint32_t addr, int size_log2)\n{\n    KBDState *s = opaque;\n    int val;\n    val = s->status;\n#if defined(DEBUG_KBD)\n    printf(\"kbd: read status=0x%02x\\n\", val);\n#endif\n    return val;\n}\n\nstatic void kbd_queue(KBDState *s, int b, int aux)\n{\n    if (aux)\n        ps2_queue(s->mouse, b);\n    else\n        ps2_queue(s->kbd, b);\n}\n\nstatic void kbd_write_command(void *opaque, uint32_t addr, uint32_t val,\n                              int size_log2)\n{\n    KBDState *s = opaque;\n\n#if defined(DEBUG_KBD)\n    printf(\"kbd: write cmd=0x%02x\\n\", val);\n#endif\n    switch(val) {\n    case KBD_CCMD_READ_MODE:\n        kbd_queue(s, s->mode, 1);\n        break;\n    case KBD_CCMD_WRITE_MODE:\n    case KBD_CCMD_WRITE_OBUF:\n    case KBD_CCMD_WRITE_AUX_OBUF:\n    case KBD_CCMD_WRITE_MOUSE:\n    case KBD_CCMD_WRITE_OUTPORT:\n        s->write_cmd = val;\n        break;\n    case KBD_CCMD_MOUSE_DISABLE:\n        s->mode |= KBD_MODE_DISABLE_MOUSE;\n        break;\n    case KBD_CCMD_MOUSE_ENABLE:\n        s->mode &= ~KBD_MODE_DISABLE_MOUSE;\n        break;\n    case KBD_CCMD_TEST_MOUSE:\n        kbd_queue(s, 0x00, 0);\n        break;\n    case KBD_CCMD_SELF_TEST:\n        s->status |= KBD_STAT_SELFTEST;\n        kbd_queue(s, 0x55, 0);\n        break;\n    case KBD_CCMD_KBD_TEST:\n        kbd_queue(s, 0x00, 0);\n        break;\n    case KBD_CCMD_KBD_DISABLE:\n        s->mode |= KBD_MODE_DISABLE_KBD;\n        kbd_update_irq(s);\n        break;\n    case KBD_CCMD_KBD_ENABLE:\n        s->mode &= ~KBD_MODE_DISABLE_KBD;\n        kbd_update_irq(s);\n        break;\n    case KBD_CCMD_READ_INPORT:\n        kbd_queue(s, 0x00, 0);\n        break;\n    case KBD_CCMD_READ_OUTPORT:\n        /* XXX: check that */\n        val = 0x01 | (ioport_get_a20() << 1);\n        if (s->status & KBD_STAT_OBF)\n            val |= 0x10;\n        if (s->status & KBD_STAT_MOUSE_OBF)\n            val |= 0x20;\n        kbd_queue(s, val, 0);\n        break;\n    case KBD_CCMD_ENABLE_A20:\n        ioport_set_a20(1);\n        break;\n    case KBD_CCMD_DISABLE_A20:\n        ioport_set_a20(0);\n        break;\n    case KBD_CCMD_RESET:\n        qemu_system_reset_request();\n        break;\n    case 0xff:\n        /* ignore that - I don't know what is its use */\n        break;\n    default:\n        fprintf(stderr, \"qemu: unsupported keyboard cmd=0x%02x\\n\", val);\n        break;\n    }\n}\n\nstatic uint32_t kbd_read_data(void *opaque, uint32_t addr, int size_log2)\n{\n    KBDState *s = opaque;\n    uint32_t val;\n    if (s->pending == KBD_PENDING_AUX)\n        val = ps2_read_data(s->mouse);\n    else\n        val = ps2_read_data(s->kbd);\n#ifdef DEBUG_KBD\n    printf(\"kbd: read data=0x%02x\\n\", val);\n#endif\n    return val;\n}\n\nstatic void kbd_write_data(void *opaque, uint32_t addr, uint32_t val, int size_log2)\n{\n    KBDState *s = opaque;\n\n#ifdef DEBUG_KBD\n    printf(\"kbd: write data=0x%02x\\n\", val);\n#endif\n\n    switch(s->write_cmd) {\n    case 0:\n        ps2_write_keyboard(s->kbd, val);\n        break;\n    case KBD_CCMD_WRITE_MODE:\n        s->mode = val;\n        ps2_keyboard_set_translation(s->kbd, (s->mode & KBD_MODE_KCC) != 0);\n        /* ??? */\n        kbd_update_irq(s);\n        break;\n    case KBD_CCMD_WRITE_OBUF:\n        kbd_queue(s, val, 0);\n        break;\n    case KBD_CCMD_WRITE_AUX_OBUF:\n        kbd_queue(s, val, 1);\n        break;\n    case KBD_CCMD_WRITE_OUTPORT:\n        ioport_set_a20((val >> 1) & 1);\n        if (!(val & 1)) {\n            qemu_system_reset_request();\n        }\n        break;\n    case KBD_CCMD_WRITE_MOUSE:\n        ps2_write_mouse(s->mouse, val);\n        break;\n    default:\n        break;\n    }\n    s->write_cmd = 0;\n}\n\nstatic void kbd_reset(void *opaque)\n{\n    KBDState *s = opaque;\n\n    s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;\n    s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;\n}\n\nKBDState *i8042_init(PS2KbdState **pkbd,\n                     PS2MouseState **pmouse,\n                     PhysMemoryMap *port_map,\n                     IRQSignal *kbd_irq, IRQSignal *mouse_irq, uint32_t io_base)\n{\n    KBDState *s;\n    \n    s = mallocz(sizeof(*s));\n    \n    s->irq_kbd = kbd_irq;\n    s->irq_mouse = mouse_irq;\n\n    kbd_reset(s);\n    cpu_register_device(port_map, io_base, 1, s, kbd_read_data, kbd_write_data, \n                        DEVIO_SIZE8);\n    cpu_register_device(port_map, io_base + 4, 1, s, kbd_read_status, kbd_write_command, \n                        DEVIO_SIZE8);\n\n    s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);\n    s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);\n\n    *pkbd = s->kbd;\n    *pmouse = s->mouse;\n    return s;\n}\n"
  },
  {
    "path": "src/ps2.c",
    "content": "/*\n * QEMU PS/2 keyboard/mouse emulation\n *\n * Copyright (c) 2003 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n\n#include \"cutils.h\"\n#include \"iomem.h\"\n#include \"ps2.h\"\n\n/* debug PC keyboard */\n//#define DEBUG_KBD\n\n/* debug PC keyboard : only mouse */\n//#define DEBUG_MOUSE\n\n/* Keyboard Commands */\n#define KBD_CMD_SET_LEDS\t0xED\t/* Set keyboard leds */\n#define KBD_CMD_ECHO     \t0xEE\n#define KBD_CMD_GET_ID \t        0xF2\t/* get keyboard ID */\n#define KBD_CMD_SET_RATE\t0xF3\t/* Set typematic rate */\n#define KBD_CMD_ENABLE\t\t0xF4\t/* Enable scanning */\n#define KBD_CMD_RESET_DISABLE\t0xF5\t/* reset and disable scanning */\n#define KBD_CMD_RESET_ENABLE   \t0xF6    /* reset and enable scanning */\n#define KBD_CMD_RESET\t\t0xFF\t/* Reset */\n\n/* Keyboard Replies */\n#define KBD_REPLY_POR\t\t0xAA\t/* Power on reset */\n#define KBD_REPLY_ACK\t\t0xFA\t/* Command ACK */\n#define KBD_REPLY_RESEND\t0xFE\t/* Command NACK, send the cmd again */\n\n/* Mouse Commands */\n#define AUX_SET_SCALE11\t\t0xE6\t/* Set 1:1 scaling */\n#define AUX_SET_SCALE21\t\t0xE7\t/* Set 2:1 scaling */\n#define AUX_SET_RES\t\t0xE8\t/* Set resolution */\n#define AUX_GET_SCALE\t\t0xE9\t/* Get scaling factor */\n#define AUX_SET_STREAM\t\t0xEA\t/* Set stream mode */\n#define AUX_POLL\t\t0xEB\t/* Poll */\n#define AUX_RESET_WRAP\t\t0xEC\t/* Reset wrap mode */\n#define AUX_SET_WRAP\t\t0xEE\t/* Set wrap mode */\n#define AUX_SET_REMOTE\t\t0xF0\t/* Set remote mode */\n#define AUX_GET_TYPE\t\t0xF2\t/* Get type */\n#define AUX_SET_SAMPLE\t\t0xF3\t/* Set sample rate */\n#define AUX_ENABLE_DEV\t\t0xF4\t/* Enable aux device */\n#define AUX_DISABLE_DEV\t\t0xF5\t/* Disable aux device */\n#define AUX_SET_DEFAULT\t\t0xF6\n#define AUX_RESET\t\t0xFF\t/* Reset aux device */\n#define AUX_ACK\t\t\t0xFA\t/* Command byte ACK. */\n\n#define MOUSE_STATUS_REMOTE     0x40\n#define MOUSE_STATUS_ENABLED    0x20\n#define MOUSE_STATUS_SCALE21    0x10\n\n#define PS2_QUEUE_SIZE 256\n\ntypedef struct {\n    uint8_t data[PS2_QUEUE_SIZE];\n    int rptr, wptr, count;\n} PS2Queue;\n\ntypedef struct {\n    PS2Queue queue;\n    int32_t write_cmd;\n    void (*update_irq)(void *, int);\n    void *update_arg;\n} PS2State;\n\nstruct  PS2KbdState {\n    PS2State common;\n    int scan_enabled;\n    /* Qemu uses translated PC scancodes internally.  To avoid multiple\n       conversions we do the translation (if any) in the PS/2 emulation\n       not the keyboard controller.  */\n    int translate;\n};\n\nstruct PS2MouseState {\n    PS2State common;\n    uint8_t mouse_status;\n    uint8_t mouse_resolution;\n    uint8_t mouse_sample_rate;\n    uint8_t mouse_wrap;\n    uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */\n    uint8_t mouse_detect_state;\n    int mouse_dx; /* current values, needed for 'poll' mode */\n    int mouse_dy;\n    int mouse_dz;\n    uint8_t mouse_buttons;\n};\n\nvoid ps2_queue(void *opaque, int b)\n{\n    PS2State *s = (PS2State *)opaque;\n    PS2Queue *q = &s->queue;\n\n    if (q->count >= PS2_QUEUE_SIZE)\n        return;\n    q->data[q->wptr] = b;\n    if (++q->wptr == PS2_QUEUE_SIZE)\n        q->wptr = 0;\n    q->count++;\n    s->update_irq(s->update_arg, 1);\n}\n\n#define INPUT_MAKE_KEY_MIN 96\n#define INPUT_MAKE_KEY_MAX 127\n\nstatic const uint8_t linux_input_to_keycode_set1[INPUT_MAKE_KEY_MAX - INPUT_MAKE_KEY_MIN + 1] = {\n    0x1c, 0x1d, 0x35, 0x00, 0x38, 0x00, 0x47, 0x48, \n    0x49, 0x4b, 0x4d, 0x4f, 0x50, 0x51, 0x52, 0x53, \n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n    0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x5c, 0x5d, \n};\n\n/* keycode is a Linux input layer keycode. We only support the PS/2\n   keycode set 1 */\nvoid ps2_put_keycode(PS2KbdState *s, BOOL is_down, int keycode)\n{\n    if (keycode >= INPUT_MAKE_KEY_MIN) {\n        if (keycode > INPUT_MAKE_KEY_MAX)\n            return;\n        keycode = linux_input_to_keycode_set1[keycode - INPUT_MAKE_KEY_MIN];\n        if (keycode == 0)\n            return;\n        ps2_queue(&s->common, 0xe0);\n    }\n    ps2_queue(&s->common, keycode | ((!is_down) << 7));\n}\n\nuint32_t ps2_read_data(void *opaque)\n{\n    PS2State *s = (PS2State *)opaque;\n    PS2Queue *q;\n    int val, index;\n\n    q = &s->queue;\n    if (q->count == 0) {\n        /* NOTE: if no data left, we return the last keyboard one\n           (needed for EMM386) */\n        /* XXX: need a timer to do things correctly */\n        index = q->rptr - 1;\n        if (index < 0)\n            index = PS2_QUEUE_SIZE - 1;\n        val = q->data[index];\n    } else {\n        val = q->data[q->rptr];\n        if (++q->rptr == PS2_QUEUE_SIZE)\n            q->rptr = 0;\n        q->count--;\n        /* reading deasserts IRQ */\n        s->update_irq(s->update_arg, 0);\n        /* reassert IRQs if data left */\n        s->update_irq(s->update_arg, q->count != 0);\n    }\n    return val;\n}\n\nstatic void ps2_reset_keyboard(PS2KbdState *s)\n{\n    s->scan_enabled = 1;\n}\n\nvoid ps2_write_keyboard(void *opaque, int val)\n{\n    PS2KbdState *s = (PS2KbdState *)opaque;\n\n    switch(s->common.write_cmd) {\n    default:\n    case -1:\n        switch(val) {\n        case 0x00:\n            ps2_queue(&s->common, KBD_REPLY_ACK);\n            break;\n        case 0x05:\n            ps2_queue(&s->common, KBD_REPLY_RESEND);\n            break;\n        case KBD_CMD_GET_ID:\n            ps2_queue(&s->common, KBD_REPLY_ACK);\n            ps2_queue(&s->common, 0xab);\n            ps2_queue(&s->common, 0x83);\n            break;\n        case KBD_CMD_ECHO:\n            ps2_queue(&s->common, KBD_CMD_ECHO);\n            break;\n        case KBD_CMD_ENABLE:\n            s->scan_enabled = 1;\n            ps2_queue(&s->common, KBD_REPLY_ACK);\n            break;\n        case KBD_CMD_SET_LEDS:\n        case KBD_CMD_SET_RATE:\n            s->common.write_cmd = val;\n            ps2_queue(&s->common, KBD_REPLY_ACK);\n            break;\n        case KBD_CMD_RESET_DISABLE:\n            ps2_reset_keyboard(s);\n            s->scan_enabled = 0;\n            ps2_queue(&s->common, KBD_REPLY_ACK);\n            break;\n        case KBD_CMD_RESET_ENABLE:\n            ps2_reset_keyboard(s);\n            s->scan_enabled = 1;\n            ps2_queue(&s->common, KBD_REPLY_ACK);\n            break;\n        case KBD_CMD_RESET:\n            ps2_reset_keyboard(s);\n            ps2_queue(&s->common, KBD_REPLY_ACK);\n            ps2_queue(&s->common, KBD_REPLY_POR);\n            break;\n        default:\n            ps2_queue(&s->common, KBD_REPLY_ACK);\n            break;\n        }\n        break;\n    case KBD_CMD_SET_LEDS:\n        ps2_queue(&s->common, KBD_REPLY_ACK);\n        s->common.write_cmd = -1;\n        break;\n    case KBD_CMD_SET_RATE:\n        ps2_queue(&s->common, KBD_REPLY_ACK);\n        s->common.write_cmd = -1;\n        break;\n    }\n}\n\n/* Set the scancode translation mode.\n   0 = raw scancodes.\n   1 = translated scancodes (used by qemu internally).  */\n\nvoid ps2_keyboard_set_translation(void *opaque, int mode)\n{\n    PS2KbdState *s = (PS2KbdState *)opaque;\n    s->translate = mode;\n}\n\nstatic void ps2_mouse_send_packet(PS2MouseState *s)\n{\n    unsigned int b;\n    int dx1, dy1, dz1;\n\n    dx1 = s->mouse_dx;\n    dy1 = s->mouse_dy;\n    dz1 = s->mouse_dz;\n    /* XXX: increase range to 8 bits ? */\n    if (dx1 > 127)\n        dx1 = 127;\n    else if (dx1 < -127)\n        dx1 = -127;\n    if (dy1 > 127)\n        dy1 = 127;\n    else if (dy1 < -127)\n        dy1 = -127;\n    b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);\n    ps2_queue(&s->common, b);\n    ps2_queue(&s->common, dx1 & 0xff);\n    ps2_queue(&s->common, dy1 & 0xff);\n    /* extra byte for IMPS/2 or IMEX */\n    switch(s->mouse_type) {\n    default:\n        break;\n    case 3:\n        if (dz1 > 127)\n            dz1 = 127;\n        else if (dz1 < -127)\n                dz1 = -127;\n        ps2_queue(&s->common, dz1 & 0xff);\n        break;\n    case 4:\n        if (dz1 > 7)\n            dz1 = 7;\n        else if (dz1 < -7)\n            dz1 = -7;\n        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);\n        ps2_queue(&s->common, b);\n        break;\n    }\n\n    /* update deltas */\n    s->mouse_dx -= dx1;\n    s->mouse_dy -= dy1;\n    s->mouse_dz -= dz1;\n}\n\nvoid ps2_mouse_event(PS2MouseState *s,\n                     int dx, int dy, int dz, int buttons_state)\n{\n    /* check if deltas are recorded when disabled */\n    if (!(s->mouse_status & MOUSE_STATUS_ENABLED))\n        return;\n\n    s->mouse_dx += dx;\n    s->mouse_dy -= dy;\n    s->mouse_dz += dz;\n    /* XXX: SDL sometimes generates nul events: we delete them */\n    if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&\n        s->mouse_buttons == buttons_state)\n\treturn;\n    s->mouse_buttons = buttons_state;\n\n    if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&\n        (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {\n        for(;;) {\n            /* if not remote, send event. Multiple events are sent if\n               too big deltas */\n            ps2_mouse_send_packet(s);\n            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)\n                break;\n        }\n    }\n}\n\nvoid ps2_write_mouse(void *opaque, int val)\n{\n    PS2MouseState *s = (PS2MouseState *)opaque;\n#ifdef DEBUG_MOUSE\n    printf(\"kbd: write mouse 0x%02x\\n\", val);\n#endif\n    switch(s->common.write_cmd) {\n    default:\n    case -1:\n        /* mouse command */\n        if (s->mouse_wrap) {\n            if (val == AUX_RESET_WRAP) {\n                s->mouse_wrap = 0;\n                ps2_queue(&s->common, AUX_ACK);\n                return;\n            } else if (val != AUX_RESET) {\n                ps2_queue(&s->common, val);\n                return;\n            }\n        }\n        switch(val) {\n        case AUX_SET_SCALE11:\n            s->mouse_status &= ~MOUSE_STATUS_SCALE21;\n            ps2_queue(&s->common, AUX_ACK);\n            break;\n        case AUX_SET_SCALE21:\n            s->mouse_status |= MOUSE_STATUS_SCALE21;\n            ps2_queue(&s->common, AUX_ACK);\n            break;\n        case AUX_SET_STREAM:\n            s->mouse_status &= ~MOUSE_STATUS_REMOTE;\n            ps2_queue(&s->common, AUX_ACK);\n            break;\n        case AUX_SET_WRAP:\n            s->mouse_wrap = 1;\n            ps2_queue(&s->common, AUX_ACK);\n            break;\n        case AUX_SET_REMOTE:\n            s->mouse_status |= MOUSE_STATUS_REMOTE;\n            ps2_queue(&s->common, AUX_ACK);\n            break;\n        case AUX_GET_TYPE:\n            ps2_queue(&s->common, AUX_ACK);\n            ps2_queue(&s->common, s->mouse_type);\n            break;\n        case AUX_SET_RES:\n        case AUX_SET_SAMPLE:\n            s->common.write_cmd = val;\n            ps2_queue(&s->common, AUX_ACK);\n            break;\n        case AUX_GET_SCALE:\n            ps2_queue(&s->common, AUX_ACK);\n            ps2_queue(&s->common, s->mouse_status);\n            ps2_queue(&s->common, s->mouse_resolution);\n            ps2_queue(&s->common, s->mouse_sample_rate);\n            break;\n        case AUX_POLL:\n            ps2_queue(&s->common, AUX_ACK);\n            ps2_mouse_send_packet(s);\n            break;\n        case AUX_ENABLE_DEV:\n            s->mouse_status |= MOUSE_STATUS_ENABLED;\n            ps2_queue(&s->common, AUX_ACK);\n            break;\n        case AUX_DISABLE_DEV:\n            s->mouse_status &= ~MOUSE_STATUS_ENABLED;\n            ps2_queue(&s->common, AUX_ACK);\n            break;\n        case AUX_SET_DEFAULT:\n            s->mouse_sample_rate = 100;\n            s->mouse_resolution = 2;\n            s->mouse_status = 0;\n            ps2_queue(&s->common, AUX_ACK);\n            break;\n        case AUX_RESET:\n            s->mouse_sample_rate = 100;\n            s->mouse_resolution = 2;\n            s->mouse_status = 0;\n            s->mouse_type = 0;\n            ps2_queue(&s->common, AUX_ACK);\n            ps2_queue(&s->common, 0xaa);\n            ps2_queue(&s->common, s->mouse_type);\n            break;\n        default:\n            break;\n        }\n        break;\n    case AUX_SET_SAMPLE:\n        s->mouse_sample_rate = val;\n        /* detect IMPS/2 or IMEX */\n        switch(s->mouse_detect_state) {\n        default:\n        case 0:\n            if (val == 200)\n                s->mouse_detect_state = 1;\n            break;\n        case 1:\n            if (val == 100)\n                s->mouse_detect_state = 2;\n            else if (val == 200)\n                s->mouse_detect_state = 3;\n            else\n                s->mouse_detect_state = 0;\n            break;\n        case 2:\n            if (val == 80)\n                s->mouse_type = 3; /* IMPS/2 */\n            s->mouse_detect_state = 0;\n            break;\n        case 3:\n            if (val == 80)\n                s->mouse_type = 4; /* IMEX */\n            s->mouse_detect_state = 0;\n            break;\n        }\n        ps2_queue(&s->common, AUX_ACK);\n        s->common.write_cmd = -1;\n        break;\n    case AUX_SET_RES:\n        s->mouse_resolution = val;\n        ps2_queue(&s->common, AUX_ACK);\n        s->common.write_cmd = -1;\n        break;\n    }\n}\n\nstatic void ps2_reset(void *opaque)\n{\n    PS2State *s = (PS2State *)opaque;\n    PS2Queue *q;\n    s->write_cmd = -1;\n    q = &s->queue;\n    q->rptr = 0;\n    q->wptr = 0;\n    q->count = 0;\n}\n\nPS2KbdState *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)\n{\n    PS2KbdState *s = (PS2KbdState *)mallocz(sizeof(PS2KbdState));\n\n    s->common.update_irq = update_irq;\n    s->common.update_arg = update_arg;\n    ps2_reset(&s->common);\n    return s;\n}\n\nPS2MouseState *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)\n{\n    PS2MouseState *s = (PS2MouseState *)mallocz(sizeof(PS2MouseState));\n\n    s->common.update_irq = update_irq;\n    s->common.update_arg = update_arg;\n    ps2_reset(&s->common);\n    return s;\n}\n"
  },
  {
    "path": "src/ps2.h",
    "content": "/* ps2.c */\ntypedef struct PS2MouseState PS2MouseState;\ntypedef struct PS2KbdState PS2KbdState;\n\nPS2KbdState *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg);\nPS2MouseState *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg);\nvoid ps2_write_mouse(void *, int val);\nvoid ps2_write_keyboard(void *, int val);\nuint32_t ps2_read_data(void *);\nvoid ps2_queue(void *, int b);\nvoid ps2_keyboard_set_translation(void *opaque, int mode);\n\nvoid ps2_put_keycode(PS2KbdState *s, BOOL is_down, int keycode);\nvoid ps2_mouse_event(PS2MouseState *s,\n                     int dx, int dy, int dz, int buttons_state);\n\n/* vmmouse.c */\ntypedef struct VMMouseState VMMouseState;\n\nVMMouseState *vmmouse_init(PS2MouseState *ps2_mouse);\nBOOL vmmouse_is_absolute(VMMouseState *s);\nvoid vmmouse_send_mouse_event(VMMouseState *s, int x, int y, int dz,\n                              int buttons);\nvoid vmmouse_handler(VMMouseState *s, uint32_t *regs);\n\n/* pckbd.c */\n\ntypedef struct KBDState KBDState;\n\nKBDState *i8042_init(PS2KbdState **pkbd,\n                     PS2MouseState **pmouse,\n                     PhysMemoryMap *port_map,\n                     IRQSignal *kbd_irq, IRQSignal *mouse_irq,\n                     uint32_t io_base);\n"
  },
  {
    "path": "src/riscv_cpu.c",
    "content": "/*\n * RISCV CPU emulator\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <time.h>\n#include <unistd.h>\n\n#include \"cutils.h\"\n#include \"iomem.h\"\n#include \"riscv_cpu.h\"\n#include \"riscvsim/utils/sim_params.h\"\n#include \"riscvsim/memory_hierarchy/dramsim_wrapper_c_connector.h\"\n\n#ifndef MAX_XLEN\n#error MAX_XLEN must be defined\n#endif\n#ifndef CONFIG_RISCV_MAX_XLEN\n#error CONFIG_RISCV_MAX_XLEN must be defined\n#endif\n\n//#define DUMP_INVALID_MEM_ACCESS\n//#define DUMP_MMU_EXCEPTIONS\n//#define DUMP_INTERRUPTS\n//#define DUMP_INVALID_CSR\n//#define DUMP_EXCEPTIONS\n//#define DUMP_CSR\n//#define CONFIG_LOGFILE\n\n#include \"riscv_cpu_priv.h\"\n\n#if FLEN > 0\n#include \"softfp.h\"\n#endif\n\n#ifdef USE_GLOBAL_STATE\nstatic RISCVCPUState riscv_cpu_global_state;\n#endif\n#ifdef USE_GLOBAL_VARIABLES\n#define code_ptr s->__code_ptr\n#define code_end s->__code_end\n#define code_to_pc_addend s->__code_to_pc_addend\n#endif\n\n#ifdef CONFIG_LOGFILE\nstatic FILE *log_file;\n\nstatic void log_vprintf(const char *fmt, va_list ap)\n{\n    if (!log_file)\n        log_file = fopen(\"/tmp/riscemu.log\", \"wb\");\n    vfprintf(log_file, fmt, ap);\n}\n#else\nstatic void log_vprintf(const char *fmt, va_list ap)\n{\n    vprintf(fmt, ap);\n}\n#endif\n\nstatic void __attribute__((format(printf, 1, 2), unused)) log_printf(const char *fmt, ...)\n{\n    va_list ap;\n    va_start(ap, fmt);\n    log_vprintf(fmt, ap);\n    va_end(ap);\n}\n\n#if MAX_XLEN == 128\nstatic void fprint_target_ulong(FILE *f, target_ulong a)\n{\n    fprintf(f, \"%016\" PRIx64 \"%016\" PRIx64, (uint64_t)(a >> 64), (uint64_t)a);\n}\n#else\nstatic void fprint_target_ulong(FILE *f, target_ulong a)\n{\n    fprintf(f, \"%\" PR_target_ulong, a);\n}\n#endif\n\nstatic void print_target_ulong(target_ulong a)\n{\n    fprint_target_ulong(stdout, a);\n}\n\nstatic char *reg_name[32] = {\n\"zero\", \"ra\", \"sp\", \"gp\", \"tp\", \"t0\", \"t1\", \"t2\",\n\"s0\", \"s1\", \"a0\", \"a1\", \"a2\", \"a3\", \"a4\", \"a5\",\n\"a6\", \"a7\", \"s2\", \"s3\", \"s4\", \"s5\", \"s6\", \"s7\",\n\"s8\", \"s9\", \"s10\", \"s11\", \"t3\", \"t4\", \"t5\", \"t6\"\n};\n\nstatic void dump_regs(RISCVCPUState *s)\n{\n    int i, cols;\n    const char priv_str[4] = \"USHM\";\n    cols = 256 / MAX_XLEN;\n    printf(\"pc =\");\n    print_target_ulong(s->pc);\n    printf(\" \");\n    for(i = 1; i < 32; i++) {\n        printf(\"%-3s=\", reg_name[i]);\n        print_target_ulong(s->reg[i]);\n        if ((i & (cols - 1)) == (cols - 1))\n            printf(\"\\n\");\n        else\n            printf(\" \");\n    }\n    printf(\"priv=%c\", priv_str[s->priv]);\n    printf(\" mstatus=\");\n    print_target_ulong(s->mstatus);\n    printf(\" cycles=%\" PRId64, s->insn_counter);\n    printf(\"\\n\");\n#if 1\n    printf(\" mideleg=\");\n    print_target_ulong(s->mideleg);\n    printf(\" mie=\");\n    print_target_ulong(s->mie);\n    printf(\" mip=\");\n    print_target_ulong(s->mip);\n    printf(\"\\n\");\n#endif\n}\n\nstatic __attribute__((unused)) void cpu_abort(RISCVCPUState *s)\n{\n    dump_regs(s);\n    abort();\n}\n\n/* addr must be aligned. Only RAM accesses are supported */\n#define PHYS_MEM_READ_WRITE(size, uint_type) \\\nstatic __maybe_unused inline void phys_write_u ## size(RISCVCPUState *s, target_ulong addr,\\\n                                        uint_type val)                   \\\n{\\\n    PhysMemoryRange *pr = get_phys_mem_range(s->mem_map, addr);\\\n    if (!pr || !pr->is_ram)\\\n        return;\\\n    *(uint_type *)(pr->phys_mem + \\\n                 (uintptr_t)(addr - pr->addr)) = val;\\\n}\\\n\\\nstatic __maybe_unused inline uint_type phys_read_u ## size(RISCVCPUState *s, target_ulong addr) \\\n{\\\n    PhysMemoryRange *pr = get_phys_mem_range(s->mem_map, addr);\\\n    if (!pr || !pr->is_ram)\\\n        return 0;\\\n    return *(uint_type *)(pr->phys_mem + \\\n                          (uintptr_t)(addr - pr->addr));     \\\n}\n\nPHYS_MEM_READ_WRITE(8, uint8_t)\nPHYS_MEM_READ_WRITE(32, uint32_t)\nPHYS_MEM_READ_WRITE(64, uint64_t)\n\n#define PTE_V_MASK (1 << 0)\n#define PTE_U_MASK (1 << 4)\n#define PTE_A_MASK (1 << 6)\n#define PTE_D_MASK (1 << 7)\n\n#define ACCESS_READ  0\n#define ACCESS_WRITE 1\n#define ACCESS_CODE  2\n\n#define MODE_SIM_START 1\n#define MODE_SIM_STOP 2\n\n/* access = 0: read, 1 = write, 2 = code. Set the exception_pending\n   field if necessary. return 0 if OK, -1 if translation error */\nstatic int get_phys_addr(RISCVCPUState *s,\n                         target_ulong *ppaddr, target_ulong vaddr,\n                         int access)\n{\n    int mode, levels, pte_bits, pte_idx, pte_mask, pte_size_log2, xwr, priv;\n    int need_write, vaddr_shift, i, pte_addr_bits;\n    target_ulong pte_addr, pte, vaddr_mask, paddr;\n\n    if ((s->mstatus & MSTATUS_MPRV) && access != ACCESS_CODE) {\n        /* use previous priviledge */\n        priv = (s->mstatus >> MSTATUS_MPP_SHIFT) & 3;\n    } else {\n        priv = s->priv;\n    }\n\n    if (priv == PRV_M) {\n        if (s->cur_xlen < MAX_XLEN) {\n            /* truncate virtual address */\n            *ppaddr = vaddr & (((target_ulong)1 << s->cur_xlen) - 1);\n        } else {\n            *ppaddr = vaddr;\n        }\n        return 0;\n    }\n#if MAX_XLEN == 32\n    /* 32 bits */\n    mode = s->satp >> 31;\n    if (mode == 0) {\n        /* bare: no translation */\n        *ppaddr = vaddr;\n        return 0;\n    } else {\n        /* sv32 */\n        levels = 2;\n        pte_size_log2 = 2;\n        pte_addr_bits = 22;\n    }\n#else\n    mode = (s->satp >> 60) & 0xf;\n    if (mode == 0) {\n        /* bare: no translation */\n        *ppaddr = vaddr;\n        return 0;\n    } else {\n        /* sv39/sv48 */\n        levels = mode - 8 + 3;\n        pte_size_log2 = 3;\n        vaddr_shift = MAX_XLEN - (PG_SHIFT + levels * 9);\n        if ((((target_long)vaddr << vaddr_shift) >> vaddr_shift) != vaddr)\n            return -1;\n        pte_addr_bits = 44;\n    }\n#endif\n\n    /* for code page walk */\n    if (s->simcpu->simulation && (access == 2)) {\n        ++s->simcpu->stats[s->priv].ins_page_walks;\n    }\n\n    /* for load page walk */\n    if (s->simcpu->simulation && (access == 0)) {\n        ++s->simcpu->stats[s->priv].load_page_walks;\n    }\n\n    /* for store page walk */\n    if (s->simcpu->simulation && (access == 1)) {\n        ++s->simcpu->stats[s->priv].store_page_walks;\n    }\n\n    pte_addr = (s->satp & (((target_ulong)1 << pte_addr_bits) - 1)) << PG_SHIFT;\n    pte_bits = 12 - pte_size_log2;\n    pte_mask = (1 << pte_bits) - 1;\n    for(i = 0; i < levels; i++) {\n        vaddr_shift = PG_SHIFT + pte_bits * (levels - 1 - i);\n        pte_idx = (vaddr >> vaddr_shift) & pte_mask;\n        pte_addr += pte_idx << pte_size_log2;\n        if (pte_size_log2 == 2) {\n            pte = phys_read_u32(s, pte_addr);\n            if (s->simcpu->simulation) {\n                s->simcpu->mem_hierarchy->mem_controller->page_walk_delay\n                    += s->simcpu->mem_hierarchy->pte_read_delay(\n                        s->simcpu->mem_hierarchy, pte_addr, 4,\n                        s->hw_pg_tb_wlk_stage_id, s->priv);\n            }\n        }\n        else {\n            pte = phys_read_u64(s, pte_addr);\n            if (s->simcpu->simulation) {\n                s->simcpu->mem_hierarchy->mem_controller->page_walk_delay\n                    += s->simcpu->mem_hierarchy->pte_read_delay(\n                        s->simcpu->mem_hierarchy, pte_addr, 8,\n                        s->hw_pg_tb_wlk_stage_id, s->priv);\n            }\n        }\n        //printf(\"pte=0x%08\" PRIx64 \"\\n\", pte);\n        if (!(pte & PTE_V_MASK))\n            return -1; /* invalid PTE */\n        paddr = (pte >> 10) << PG_SHIFT;\n        xwr = (pte >> 1) & 7;\n        if (xwr != 0) {\n            if (xwr == 2 || xwr == 6)\n                return -1;\n            /* priviledge check */\n            if (priv == PRV_S) {\n                if ((pte & PTE_U_MASK) && !(s->mstatus & MSTATUS_SUM))\n                    return -1;\n            } else {\n                if (!(pte & PTE_U_MASK))\n                    return -1;\n            }\n            /* protection check */\n            /* MXR allows read access to execute-only pages */\n            if (s->mstatus & MSTATUS_MXR)\n                xwr |= (xwr >> 2);\n\n            if (((xwr >> access) & 1) == 0)\n                return -1;\n            need_write = !(pte & PTE_A_MASK) ||\n                (!(pte & PTE_D_MASK) && access == ACCESS_WRITE);\n            pte |= PTE_A_MASK;\n            if (access == ACCESS_WRITE)\n                pte |= PTE_D_MASK;\n            if (need_write) {\n                if (pte_size_log2 == 2) {\n                    phys_write_u32(s, pte_addr, pte);\n                    if (s->simcpu->simulation) {\n                        s->simcpu->mem_hierarchy->pte_write_delay(\n                            s->simcpu->mem_hierarchy, pte_addr, 4,\n                            s->hw_pg_tb_wlk_stage_id, s->priv);\n                    }\n                }\n                else {\n                    phys_write_u64(s, pte_addr, pte);\n                    if (s->simcpu->simulation) {\n                        s->simcpu->mem_hierarchy->pte_write_delay(\n                            s->simcpu->mem_hierarchy, pte_addr, 8,\n                            s->hw_pg_tb_wlk_stage_id, s->priv);\n                    }\n                }\n            }\n            vaddr_mask = ((target_ulong)1 << vaddr_shift) - 1;\n            *ppaddr = (vaddr & vaddr_mask) | (paddr  & ~vaddr_mask);\n            return 0;\n        } else {\n            pte_addr = paddr;\n        }\n    }\n    return -1;\n}\n\n/* return 0 if OK, != 0 if exception */\nint target_read_slow(RISCVCPUState *s, mem_uint_t *pval,\n                     target_ulong addr, int size_log2)\n{\n    int size, tlb_idx, err, al;\n    target_ulong paddr, offset;\n    uint8_t *ptr;\n    PhysMemoryRange *pr;\n    mem_uint_t ret;\n\n    /* first handle unaligned accesses */\n    size = 1 << size_log2;\n    al = addr & (size - 1);\n    if (al != 0) {\n        switch(size_log2) {\n        case 1:\n            {\n                uint8_t v0, v1;\n                err = target_read_u8(s, &v0, addr);\n                if (err)\n                    return err;\n                err = target_read_u8(s, &v1, addr + 1);\n                if (err)\n                    return err;\n                ret = v0 | (v1 << 8);\n            }\n            break;\n        case 2:\n            {\n                uint32_t v0, v1;\n                addr -= al;\n                err = target_read_u32(s, &v0, addr);\n                if (err)\n                    return err;\n                err = target_read_u32(s, &v1, addr + 4);\n                if (err)\n                    return err;\n                ret = (v0 >> (al * 8)) | (v1 << (32 - al * 8));\n            }\n            break;\n#if MLEN >= 64\n        case 3:\n            {\n                uint64_t v0, v1;\n                addr -= al;\n                err = target_read_u64(s, &v0, addr);\n                if (err)\n                    return err;\n                err = target_read_u64(s, &v1, addr + 8);\n                if (err)\n                    return err;\n                ret = (v0 >> (al * 8)) | (v1 << (64 - al * 8));\n            }\n            break;\n#endif\n#if MLEN >= 128\n        case 4:\n            {\n                uint128_t v0, v1;\n                addr -= al;\n                err = target_read_u128(s, &v0, addr);\n                if (err)\n                    return err;\n                err = target_read_u128(s, &v1, addr + 16);\n                if (err)\n                    return err;\n                ret = (v0 >> (al * 8)) | (v1 << (128 - al * 8));\n            }\n            break;\n#endif\n        default:\n            abort();\n        }\n    } else {\n        if (get_phys_addr(s, &paddr, addr, ACCESS_READ)) {\n            s->pending_tval = addr;\n            s->pending_exception = CAUSE_LOAD_PAGE_FAULT;\n            return -1;\n        }\n        pr = get_phys_mem_range(s->mem_map, paddr);\n        if (!pr) {\n#ifdef DUMP_INVALID_MEM_ACCESS\n            printf(\"target_read_slow: invalid physical address 0x\");\n            print_target_ulong(paddr);\n            printf(\"\\n\");\n#endif\n            return 0;\n        } else if (pr->is_ram) {\n            tlb_idx = (addr >> PG_SHIFT) & (TLB_SIZE - 1);\n            ptr = pr->phys_mem + (uintptr_t)(paddr - pr->addr);\n            s->tlb_read[tlb_idx].vaddr = addr & ~PG_MASK;\n            s->tlb_read[tlb_idx].mem_addend = (uintptr_t)ptr - addr;\n            s->tlb_read[tlb_idx].guest_paddr = paddr & ~PG_MASK;\n            switch(size_log2) {\n            case 0:\n                ret = *(uint8_t *)ptr;\n                break;\n            case 1:\n                ret = *(uint16_t *)ptr;\n                break;\n            case 2:\n                ret = *(uint32_t *)ptr;\n                break;\n#if MLEN >= 64\n            case 3:\n                ret = *(uint64_t *)ptr;\n                break;\n#endif\n#if MLEN >= 128\n            case 4:\n                ret = *(uint128_t *)ptr;\n                break;\n#endif\n            default:\n                abort();\n            }\n        } else {\n            s->is_device_io = 1;\n            s->data_guest_paddr = paddr;\n            offset = paddr - pr->addr;\n            if (((pr->devio_flags >> size_log2) & 1) != 0) {\n                ret = pr->read_func(pr->opaque, offset, size_log2);\n            }\n#if MLEN >= 64\n            else if ((pr->devio_flags & DEVIO_SIZE32) && size_log2 == 3) {\n                /* emulate 64 bit access */\n                ret = pr->read_func(pr->opaque, offset, 2);\n                ret |= (uint64_t)pr->read_func(pr->opaque, offset + 4, 2) << 32;\n                \n            }\n#endif\n            else {\n#ifdef DUMP_INVALID_MEM_ACCESS\n                printf(\"unsupported device read access: addr=0x\");\n                print_target_ulong(paddr);\n                printf(\" width=%d bits\\n\", 1 << (3 + size_log2));\n#endif\n                ret = 0;\n            }\n        }\n    }\n    *pval = ret;\n    return 0;\n}\n\n/* return 0 if OK, != 0 if exception */\nint target_write_slow(RISCVCPUState *s, target_ulong addr,\n                      mem_uint_t val, int size_log2)\n{\n    int size, i, tlb_idx, err;\n    target_ulong paddr, offset;\n    uint8_t *ptr;\n    PhysMemoryRange *pr;\n    \n    /* first handle unaligned accesses */\n    size = 1 << size_log2;\n    if ((addr & (size - 1)) != 0) {\n        /* XXX: should avoid modifying the memory in case of exception */\n        for(i = 0; i < size; i++) {\n            err = target_write_u8(s, addr + i, (val >> (8 * i)) & 0xff);\n            if (err)\n                return err;\n        }\n    } else {\n        if (get_phys_addr(s, &paddr, addr, ACCESS_WRITE)) {\n            s->pending_tval = addr;\n            s->pending_exception = CAUSE_STORE_PAGE_FAULT;\n            return -1;\n        }\n        pr = get_phys_mem_range(s->mem_map, paddr);\n        if (!pr) {\n#ifdef DUMP_INVALID_MEM_ACCESS\n            printf(\"target_write_slow: invalid physical address 0x\");\n            print_target_ulong(paddr);\n            printf(\"\\n\");\n#endif\n        } else if (pr->is_ram) {\n            phys_mem_set_dirty_bit(pr, paddr - pr->addr);\n            tlb_idx = (addr >> PG_SHIFT) & (TLB_SIZE - 1);\n            ptr = pr->phys_mem + (uintptr_t)(paddr - pr->addr);\n            s->tlb_write[tlb_idx].vaddr = addr & ~PG_MASK;\n            s->tlb_write[tlb_idx].mem_addend = (uintptr_t)ptr - addr;\n            s->tlb_write[tlb_idx].guest_paddr = paddr & ~PG_MASK;\n            switch(size_log2) {\n            case 0:\n                *(uint8_t *)ptr = val;\n                break;\n            case 1:\n                *(uint16_t *)ptr = val;\n                break;\n            case 2:\n                *(uint32_t *)ptr = val;\n                break;\n#if MLEN >= 64\n            case 3:\n                *(uint64_t *)ptr = val;\n                break;\n#endif\n#if MLEN >= 128\n            case 4:\n                *(uint128_t *)ptr = val;\n                break;\n#endif\n            default:\n                abort();\n            }\n        } else {\n            s->is_device_io = 1;\n            s->data_guest_paddr = paddr;\n            offset = paddr - pr->addr;\n            if (((pr->devio_flags >> size_log2) & 1) != 0) {\n                pr->write_func(pr->opaque, offset, val, size_log2);\n            }\n#if MLEN >= 64\n            else if ((pr->devio_flags & DEVIO_SIZE32) && size_log2 == 3) {\n                /* emulate 64 bit access */\n                pr->write_func(pr->opaque, offset,\n                               val & 0xffffffff, 2);\n                pr->write_func(pr->opaque, offset + 4,\n                               (val >> 32) & 0xffffffff, 2);\n            }\n#endif\n            else {\n#ifdef DUMP_INVALID_MEM_ACCESS\n                printf(\"unsupported device write access: addr=0x\");\n                print_target_ulong(paddr);\n                printf(\" width=%d bits\\n\", 1 << (3 + size_log2));\n#endif\n            }\n        }\n    }\n    return 0;\n}\n\nstruct __attribute__((packed)) unaligned_u32 {\n    uint32_t u32;\n};\n\n/* unaligned access at an address known to be a multiple of 2 */\nuint32_t get_insn32(uint8_t *ptr)\n{\n#if defined(EMSCRIPTEN)\n    return ((uint16_t *)ptr)[0] | (((uint16_t *)ptr)[1] << 16);\n#else\n    return ((struct unaligned_u32 *)ptr)->u32;\n#endif\n}\n\n/* return 0 if OK, != 0 if exception */\nno_inline __exception int target_read_insn_slow(RISCVCPUState *s,\n                                                       uint8_t **pptr,\n                                                       target_ulong addr)\n{\n    int tlb_idx;\n    target_ulong paddr;\n    uint8_t *ptr;\n    PhysMemoryRange *pr;\n    \n    if (get_phys_addr(s, &paddr, addr, ACCESS_CODE)) {\n        s->pending_tval = addr;\n        s->pending_exception = CAUSE_FETCH_PAGE_FAULT;\n        return -1;\n    }\n    pr = get_phys_mem_range(s->mem_map, paddr);\n    if (!pr || !pr->is_ram) {\n        /* XXX: we only access to execute code from RAM */\n        s->pending_tval = addr;\n        s->pending_exception = CAUSE_FAULT_FETCH;\n        return -1;\n    }\n    tlb_idx = (addr >> PG_SHIFT) & (TLB_SIZE - 1);\n    ptr = pr->phys_mem + (uintptr_t)(paddr - pr->addr);\n    s->tlb_code[tlb_idx].vaddr = addr & ~PG_MASK;\n    s->tlb_code[tlb_idx].mem_addend = (uintptr_t)ptr - addr;\n    s->tlb_code[tlb_idx].guest_paddr = paddr & ~PG_MASK;\n    *pptr = ptr;\n    return 0;\n}\n\n/* addr must be aligned */\n__exception int target_read_insn_u16(RISCVCPUState *s, uint16_t *pinsn,\n                                                   target_ulong addr)\n{\n    uint32_t tlb_idx;\n    uint8_t *ptr;\n\n    if (s->simcpu->simulation && !s->ins_tlb_lookup_accounted) {\n        ++s->simcpu->stats[s->priv].code_tlb_lookups;\n        s->ins_tlb_lookup_accounted = 1;\n    }\n\n    tlb_idx = (addr >> PG_SHIFT) & (TLB_SIZE - 1);\n    if (likely(s->tlb_code[tlb_idx].vaddr == (addr & ~PG_MASK))) {\n        ptr = (uint8_t *)(s->tlb_code[tlb_idx].mem_addend +\n                          (uintptr_t)addr);\n\n        if (s->simcpu->simulation && !s->ins_tlb_hit_accounted) {\n            ++s->simcpu->stats[s->priv].code_tlb_hits;\n            s->ins_tlb_hit_accounted = 1;\n        }\n\n    } else {\n        if (target_read_insn_slow(s, &ptr, addr))\n            return -1;\n    }\n    *pinsn = *(uint16_t *)ptr;\n    return 0;\n}\n\nstatic void tlb_init(RISCVCPUState *s)\n{\n    int i;\n\n    for (i = 0; i < s->sim_params->tlb_size; i++) {\n        s->tlb_read[i].vaddr = -1;\n        s->tlb_write[i].vaddr = -1;\n        s->tlb_code[i].vaddr = -1;\n        s->tlb_read[i].guest_paddr = -1;\n        s->tlb_write[i].guest_paddr = -1;\n        s->tlb_code[i].guest_paddr = -1;\n    }\n\n    /* Flush branch prediction unit on a tlb flush or context switch */\n    if (s->simcpu->simulation && s->sim_params->enable_bpu\n        && s->sim_params->bpu_flush_on_context_switch)\n    {\n        bpu_flush(s->simcpu->bpu);\n    }\n}\n\nstatic void tlb_flush_all(RISCVCPUState *s)\n{\n    tlb_init(s);\n}\n\nstatic void tlb_flush_vaddr(RISCVCPUState *s, target_ulong vaddr)\n{\n    tlb_flush_all(s);\n}\n\n/* XXX: inefficient but not critical as long as it is seldom used */\nstatic void glue(riscv_cpu_flush_tlb_write_range_ram,\n                 MAX_XLEN)(RISCVCPUState *s,\n                           uint8_t *ram_ptr, size_t ram_size)\n{\n    uint8_t *ptr, *ram_end;\n    int i;\n    \n    ram_end = ram_ptr + ram_size;\n    for(i = 0; i < TLB_SIZE; i++) {\n        if (s->tlb_write[i].vaddr != -1) {\n            ptr = (uint8_t *)(s->tlb_write[i].mem_addend +\n                              (uintptr_t)s->tlb_write[i].vaddr);\n            if (ptr >= ram_ptr && ptr < ram_end) {\n                s->tlb_write[i].vaddr = -1;\n            }\n        }\n    }\n}\n\n\n#define SSTATUS_MASK0 (MSTATUS_UIE | MSTATUS_SIE |       \\\n                      MSTATUS_UPIE | MSTATUS_SPIE |     \\\n                      MSTATUS_SPP | \\\n                      MSTATUS_FS | MSTATUS_XS | \\\n                      MSTATUS_SUM | MSTATUS_MXR)\n#if MAX_XLEN >= 64\n#define SSTATUS_MASK (SSTATUS_MASK0 | MSTATUS_UXL_MASK)\n#else\n#define SSTATUS_MASK SSTATUS_MASK0\n#endif\n\n\n#define MSTATUS_MASK (MSTATUS_UIE | MSTATUS_SIE | MSTATUS_MIE |      \\\n                      MSTATUS_UPIE | MSTATUS_SPIE | MSTATUS_MPIE |    \\\n                      MSTATUS_SPP | MSTATUS_MPP | \\\n                      MSTATUS_FS | \\\n                      MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_MXR)\n\n/* cycle and insn counters */\n#define COUNTEREN_MASK ((1 << 0) | (1 << 2))\n\n/* return the complete mstatus with the SD bit */\nstatic target_ulong get_mstatus(RISCVCPUState *s, target_ulong mask)\n{\n    target_ulong val;\n    BOOL sd;\n    val = s->mstatus | (s->fs << MSTATUS_FS_SHIFT);\n    val &= mask;\n    sd = ((val & MSTATUS_FS) == MSTATUS_FS) |\n        ((val & MSTATUS_XS) == MSTATUS_XS);\n    if (sd)\n        val |= (target_ulong)1 << (s->cur_xlen - 1);\n    return val;\n}\n                              \nstatic int get_base_from_xlen(int xlen)\n{\n    if (xlen == 32)\n        return 1;\n    else if (xlen == 64)\n        return 2;\n    else\n        return 3;\n}\n\nstatic void set_mstatus(RISCVCPUState *s, target_ulong val)\n{\n    target_ulong mod, mask;\n    \n    /* flush the TLBs if change of MMU config */\n    mod = s->mstatus ^ val;\n    if ((mod & (MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_MXR)) != 0 ||\n        ((s->mstatus & MSTATUS_MPRV) && (mod & MSTATUS_MPP) != 0)) {\n        tlb_flush_all(s);\n    }\n    s->fs = (val >> MSTATUS_FS_SHIFT) & 3;\n\n    mask = MSTATUS_MASK & ~MSTATUS_FS;\n#if MAX_XLEN >= 64\n    {\n        int uxl, sxl;\n        uxl = (val >> MSTATUS_UXL_SHIFT) & 3;\n        if (uxl >= 1 && uxl <= get_base_from_xlen(MAX_XLEN))\n            mask |= MSTATUS_UXL_MASK;\n        sxl = (val >> MSTATUS_UXL_SHIFT) & 3;\n        if (sxl >= 1 && sxl <= get_base_from_xlen(MAX_XLEN))\n            mask |= MSTATUS_SXL_MASK;\n    }\n#endif\n    s->mstatus = (s->mstatus & ~mask) | (val & mask);\n}\n\n/* return -1 if invalid CSR. 0 if OK. 'will_write' indicate that the\n   csr will be written after (used for CSR access check) */\nstatic int csr_read(RISCVCPUState *s, target_ulong *pval, uint32_t csr,\n                     BOOL will_write, int* run_mode)\n{\n    target_ulong val;\n\n    if (s->simcpu->simulation) {\n        s->simcpu->stats[s->priv].csr_reads++;\n    }\n    if (((csr & 0xc00) == 0xc00) && will_write)\n        return -1; /* read-only CSR */\n    if (s->priv < ((csr >> 8) & 3))\n        return -1; /* not enough priviledge */\n    \n    switch(csr) {\n#if FLEN > 0\n    case 0x001: /* fflags */\n        if (s->fs == 0)\n            return -1;\n        val = s->fflags;\n        break;\n    case 0x002: /* frm */\n        if (s->fs == 0)\n            return -1;\n        val = s->frm;\n        break;\n    case 0x003:\n        if (s->fs == 0)\n            return -1;\n        val = s->fflags | (s->frm << 5);\n        break;\n#endif\n    case 0xc00: /* ucycle */\n    case 0xc02: /* uinstret */\n        {\n            uint32_t counteren;\n            if (s->priv < PRV_M) {\n                if (s->priv < PRV_S)\n                    counteren = s->scounteren;\n                else\n                    counteren = s->mcounteren;\n                if (((counteren >> (csr & 0x1f)) & 1) == 0)\n                    goto invalid_csr;\n            }\n        }\n        val = (int64_t)s->insn_counter;\n        break;\n    case 0xc80: /* mcycleh */\n    case 0xc82: /* minstreth */\n        if (s->cur_xlen != 32)\n            goto invalid_csr;\n        {\n            uint32_t counteren;\n            if (s->priv < PRV_M) {\n                if (s->priv < PRV_S)\n                    counteren = s->scounteren;\n                else\n                    counteren = s->mcounteren;\n                if (((counteren >> (csr & 0x1f)) & 1) == 0)\n                    goto invalid_csr;\n            }\n        }\n        val = s->insn_counter >> 32;\n        break;\n        \n    case 0x100:\n        val = get_mstatus(s, SSTATUS_MASK);\n        break;\n    case 0x104: /* sie */\n        val = s->mie & s->mideleg;\n        break;\n    case 0x105:\n        val = s->stvec;\n        break;\n    case 0x106:\n        val = s->scounteren;\n        break;\n    case 0x140:\n        val = s->sscratch;\n        break;\n    case 0x141:\n        val = s->sepc;\n        break;\n    case 0x142:\n        val = s->scause;\n        break;\n    case 0x143:\n        val = s->stval;\n        break;\n    case 0x144: /* sip */\n        val = s->mip & s->mideleg;\n        break;\n    case 0x180:\n        val = s->satp;\n        break;\n    case 0x300:\n        val = get_mstatus(s, (target_ulong)-1);\n        break;\n    case 0x301:\n        val = s->misa;\n        val |= (target_ulong)s->mxl << (s->cur_xlen - 2);\n        break;\n    case 0x302:\n        val = s->medeleg;\n        break;\n    case 0x303:\n        val = s->mideleg;\n        break;\n    case 0x304:\n        val = s->mie;\n        break;\n    case 0x305:\n        val = s->mtvec;\n        break;\n    case 0x306:\n        val = s->mcounteren;\n        break;\n    case 0x340:\n        val = s->mscratch;\n        break;\n    case 0x341:\n        val = s->mepc;\n        break;\n    case 0x342:\n        val = s->mcause;\n        break;\n    case 0x343:\n        val = s->mtval;\n        break;\n    case 0x344:\n        val = s->mip;\n        break;\n    case 0xb00: /* mcycle */\n    case 0xb02: /* minstret */\n        val = (int64_t)s->insn_counter;\n        break;\n    case 0xb80: /* mcycleh */\n    case 0xb82: /* minstreth */\n        if (s->cur_xlen != 32)\n            goto invalid_csr;\n        val = s->insn_counter >> 32;\n        break;\n    case 0xf14:\n        val = s->mhartid;\n        break;\n    case 0x800: /** switch-to-simulation */\n        *run_mode = MODE_SIM_START;\n        val = 0;\n        break;\n    case 0x801: /** switch-to-emulation */\n        *run_mode = MODE_SIM_STOP;\n        val = 0;\n        break;\n    default:\n    invalid_csr:\n#ifdef DUMP_INVALID_CSR\n        /* the 'time' counter is usually emulated */\n        if (csr != 0xc01 && csr != 0xc81) {\n            printf(\"csr_read: invalid CSR=0x%x\\n\", csr);\n        }\n#endif\n        *pval = 0;\n        return -1;\n    }\n    *pval = val;\n    return 0;\n}\n\n#if FLEN > 0\nstatic void set_frm(RISCVCPUState *s, unsigned int val)\n{\n    if (val >= 5)\n        val = 0;\n    s->frm = val;\n}\n\n/* return -1 if invalid roundind mode */\nint get_insn_rm(RISCVCPUState *s, unsigned int rm)\n{\n    if (rm == 7)\n        return s->frm;\n    if (rm >= 5)\n        return -1;\n    else\n        return rm;\n}\n#endif\n\n/* return -1 if invalid CSR, 0 if OK, 1 if the interpreter loop must be\n   exited (e.g. XLEN was modified), 2 if TLBs have been flushed. */\nstatic int csr_write(RISCVCPUState *s, uint32_t csr, target_ulong val)\n{\n    target_ulong mask;\n\n    if (s->simcpu->simulation) {\n        s->simcpu->stats[s->priv].csr_writes++;\n    }\n\n#if defined(DUMP_CSR)\n    printf(\"csr_write: csr=0x%03x val=0x\", csr);\n    print_target_ulong(val);\n    printf(\"\\n\");\n#endif\n    switch(csr) {\n#if FLEN > 0\n    case 0x001: /* fflags */\n        s->fflags = val & 0x1f;\n        s->fs = 3;\n        break;\n    case 0x002: /* frm */\n        set_frm(s, val & 7);\n        s->fs = 3;\n        break;\n    case 0x003: /* fcsr */\n        set_frm(s, (val >> 5) & 7);\n        s->fflags = val & 0x1f;\n        s->fs = 3;\n        break;\n#endif\n    case 0x100: /* sstatus */\n        set_mstatus(s, (s->mstatus & ~SSTATUS_MASK) | (val & SSTATUS_MASK));\n        break;\n    case 0x104: /* sie */\n        mask = s->mideleg;\n        s->mie = (s->mie & ~mask) | (val & mask);\n        break;\n    case 0x105:\n        s->stvec = val & ~3;\n        break;\n    case 0x106:\n        s->scounteren = val & COUNTEREN_MASK;\n        break;\n    case 0x140:\n        s->sscratch = val;\n        break;\n    case 0x141:\n        s->sepc = val & ~1;\n        break;\n    case 0x142:\n        s->scause = val;\n        break;\n    case 0x143:\n        s->stval = val;\n        break;\n    case 0x144: /* sip */\n        mask = s->mideleg;\n        s->mip = (s->mip & ~mask) | (val & mask);\n        break;\n    case 0x180:\n        /* no ASID implemented */\n#if MAX_XLEN == 32\n        {\n            int new_mode;\n            new_mode = (val >> 31) & 1;\n            s->satp = (val & (((target_ulong)1 << 22) - 1)) |\n                (new_mode << 31);\n        }\n#else\n        {\n            int mode, new_mode;\n            mode = s->satp >> 60;\n            new_mode = (val >> 60) & 0xf;\n            if (new_mode == 0 || (new_mode >= 8 && new_mode <= 9))\n                mode = new_mode;\n            s->satp = (val & (((uint64_t)1 << 44) - 1)) |\n                ((uint64_t)mode << 60);\n        }\n#endif\n        tlb_flush_all(s);\n        return 2;\n        \n    case 0x300:\n        set_mstatus(s, val);\n        break;\n    case 0x301: /* misa */\n#if MAX_XLEN >= 64\n        {\n            int new_mxl;\n            new_mxl = (val >> (s->cur_xlen - 2)) & 3;\n            if (new_mxl >= 1 && new_mxl <= get_base_from_xlen(MAX_XLEN)) {\n                /* Note: misa is only modified in M level, so cur_xlen\n                   = 2^(mxl + 4) */\n                if (s->mxl != new_mxl) {\n                    s->mxl = new_mxl;\n                    s->cur_xlen = 1 << (new_mxl + 4);\n                    return 1;\n                }\n            }\n        }\n#endif\n        break;\n    case 0x302:\n        mask = (1 << (CAUSE_STORE_PAGE_FAULT + 1)) - 1;\n        s->medeleg = (s->medeleg & ~mask) | (val & mask);\n        break;\n    case 0x303:\n        mask = MIP_SSIP | MIP_STIP | MIP_SEIP;\n        s->mideleg = (s->mideleg & ~mask) | (val & mask);\n        break;\n    case 0x304:\n        mask = MIP_MSIP | MIP_MTIP | MIP_SSIP | MIP_STIP | MIP_SEIP;\n        s->mie = (s->mie & ~mask) | (val & mask);\n        break;\n    case 0x305:\n        s->mtvec = val & ~3;\n        break;\n    case 0x306:\n        s->mcounteren = val & COUNTEREN_MASK;\n        break;\n    case 0x340:\n        s->mscratch = val;\n        break;\n    case 0x341:\n        s->mepc = val & ~1;\n        break;\n    case 0x342:\n        s->mcause = val;\n        break;\n    case 0x343:\n        s->mtval = val;\n        break;\n    case 0x344:\n        mask = MIP_SSIP | MIP_STIP;\n        s->mip = (s->mip & ~mask) | (val & mask);\n        break;\n    default:\n#ifdef DUMP_INVALID_CSR\n        printf(\"csr_write: invalid CSR=0x%x\\n\", csr);\n#endif\n        return -1;\n    }\n    return 0;\n}\n\nstatic void set_priv(RISCVCPUState *s, int priv)\n{\n    if (s->priv != priv) {\n        tlb_flush_all(s);\n\n#if MAX_XLEN >= 64\n        /* change the current xlen */\n        {\n            int mxl;\n            if (priv == PRV_S)\n                mxl = (s->mstatus >> MSTATUS_SXL_SHIFT) & 3;\n            else if (priv == PRV_U)\n                mxl = (s->mstatus >> MSTATUS_UXL_SHIFT) & 3;\n            else\n                mxl = s->mxl;\n            s->cur_xlen = 1 << (4 + mxl);\n        }\n#endif\n        s->priv = priv;\n    }\n}\n\nstatic void raise_exception2(RISCVCPUState *s, uint32_t cause,\n                             target_ulong tval)\n{\n    BOOL deleg;\n    target_ulong causel, cause2;\n\n    /* Count the interrupts and exceptions in simulation mode */\n    if (s->simcpu->simulation)\n    {\n        cause2 = cause & 0x7fffffff;\n        if ((cause & CAUSE_INTERRUPT) != 0)\n        {\n            ++s->simcpu->stats[s->priv].interrupts[cause2];\n        }\n        else\n        {\n            ++s->simcpu->stats[s->priv].exceptions[cause2];\n        }\n    }\n\n#if defined(DUMP_EXCEPTIONS) || defined(DUMP_MMU_EXCEPTIONS) || defined(DUMP_INTERRUPTS)\n    {\n        int flag;\n        flag = 0;\n#ifdef DUMP_MMU_EXCEPTIONS\n        if (cause == CAUSE_FAULT_FETCH ||\n            cause == CAUSE_FAULT_LOAD ||\n            cause == CAUSE_FAULT_STORE ||\n            cause == CAUSE_FETCH_PAGE_FAULT ||\n            cause == CAUSE_LOAD_PAGE_FAULT ||\n            cause == CAUSE_STORE_PAGE_FAULT)\n            flag = 1;\n#endif\n#ifdef DUMP_INTERRUPTS\n        flag |= (cause & CAUSE_INTERRUPT) != 0;\n#endif\n#ifdef DUMP_EXCEPTIONS\n        flag = 1;\n        flag = (cause & CAUSE_INTERRUPT) == 0;\n        if (cause == CAUSE_SUPERVISOR_ECALL || cause == CAUSE_ILLEGAL_INSTRUCTION)\n            flag = 0;\n#endif\n        if (flag) {\n            log_printf(\"raise_exception: cause=0x%08x tval=0x\", cause);\n#ifdef CONFIG_LOGFILE\n            fprint_target_ulong(log_file, tval);\n#else\n            print_target_ulong(tval);\n#endif\n            log_printf(\"\\n\");\n            dump_regs(s);\n        }\n    }\n#endif\n\n    if (s->priv <= PRV_S) {\n        /* delegate the exception to the supervisor priviledge */\n        if (cause & CAUSE_INTERRUPT)\n            deleg = (s->mideleg >> (cause & (MAX_XLEN - 1))) & 1;\n        else\n            deleg = (s->medeleg >> cause) & 1;\n    } else {\n        deleg = 0;\n    }\n    \n    causel = cause & 0x7fffffff;\n    if (cause & CAUSE_INTERRUPT)\n        causel |= (target_ulong)1 << (s->cur_xlen - 1);\n    \n    if (deleg) {\n        s->scause = causel;\n        s->sepc = s->pc;\n        s->stval = tval;\n        s->mstatus = (s->mstatus & ~MSTATUS_SPIE) |\n            (((s->mstatus >> s->priv) & 1) << MSTATUS_SPIE_SHIFT);\n        s->mstatus = (s->mstatus & ~MSTATUS_SPP) |\n            (s->priv << MSTATUS_SPP_SHIFT);\n        s->mstatus &= ~MSTATUS_SIE;\n        set_priv(s, PRV_S);\n        s->pc = s->stvec;\n    } else {\n        s->mcause = causel;\n        s->mepc = s->pc;\n        s->mtval = tval;\n        s->mstatus = (s->mstatus & ~MSTATUS_MPIE) |\n            (((s->mstatus >> s->priv) & 1) << MSTATUS_MPIE_SHIFT);\n        s->mstatus = (s->mstatus & ~MSTATUS_MPP) |\n            (s->priv << MSTATUS_MPP_SHIFT);\n        s->mstatus &= ~MSTATUS_MIE;\n        set_priv(s, PRV_M);\n        s->pc = s->mtvec;\n    }\n}\n\nstatic void raise_exception(RISCVCPUState *s, uint32_t cause)\n{\n    raise_exception2(s, cause, 0);\n}\n\nstatic void handle_sret(RISCVCPUState *s)\n{\n    int spp, spie;\n    spp = (s->mstatus >> MSTATUS_SPP_SHIFT) & 1;\n    /* set the IE state to previous IE state */\n    spie = (s->mstatus >> MSTATUS_SPIE_SHIFT) & 1;\n    s->mstatus = (s->mstatus & ~(1 << spp)) |\n        (spie << spp);\n    /* set SPIE to 1 */\n    s->mstatus |= MSTATUS_SPIE;\n    /* set SPP to U */\n    s->mstatus &= ~MSTATUS_SPP;\n    set_priv(s, spp);\n    s->pc = s->sepc;\n}\n\nstatic void handle_mret(RISCVCPUState *s)\n{\n    int mpp, mpie;\n    mpp = (s->mstatus >> MSTATUS_MPP_SHIFT) & 3;\n    /* set the IE state to previous IE state */\n    mpie = (s->mstatus >> MSTATUS_MPIE_SHIFT) & 1;\n    s->mstatus = (s->mstatus & ~(1 << mpp)) |\n        (mpie << mpp);\n    /* set MPIE to 1 */\n    s->mstatus |= MSTATUS_MPIE;\n    /* set MPP to U */\n    s->mstatus &= ~MSTATUS_MPP;\n    set_priv(s, mpp);\n    s->pc = s->mepc;\n}\n\nstatic inline uint32_t get_pending_irq_mask(RISCVCPUState *s)\n{\n    uint32_t pending_ints, enabled_ints;\n\n    pending_ints = s->mip & s->mie;\n    if (pending_ints == 0)\n        return 0;\n\n    enabled_ints = 0;\n    switch(s->priv) {\n    case PRV_M:\n        if (s->mstatus & MSTATUS_MIE)\n            enabled_ints = ~s->mideleg;\n        break;\n    case PRV_S:\n        enabled_ints = ~s->mideleg;\n        if (s->mstatus & MSTATUS_SIE)\n            enabled_ints |= s->mideleg;\n        break;\n    default:\n    case PRV_U:\n        enabled_ints = -1;\n        break;\n    }\n    return pending_ints & enabled_ints;\n}\n\nstatic __exception int raise_interrupt(RISCVCPUState *s)\n{\n    uint32_t mask;\n    int irq_num;\n\n    mask = get_pending_irq_mask(s);\n    if (mask == 0)\n        return 0;\n    irq_num = ctz32(mask);\n    raise_exception(s, irq_num | CAUSE_INTERRUPT);\n    return -1;\n}\n\nstatic inline int32_t sext(int32_t val, int n)\n{\n    return (val << (32 - n)) >> (32 - n);\n}\n\nstatic inline uint32_t get_field1(uint32_t val, int src_pos, \n                                  int dst_pos, int dst_pos_max)\n{\n    int mask;\n    assert(dst_pos_max >= dst_pos);\n    mask = ((1 << (dst_pos_max - dst_pos + 1)) - 1) << dst_pos;\n    if (dst_pos >= src_pos)\n        return (val << (dst_pos - src_pos)) & mask;\n    else\n        return (val >> (src_pos - dst_pos)) & mask;\n}\n\n#define XLEN 32\n#include \"riscv_cpu_template.h\"\n\n#if MAX_XLEN >= 64\n#define XLEN 64\n#include \"riscv_cpu_template.h\"\n#endif\n\n#if MAX_XLEN >= 128\n#define XLEN 128\n#include \"riscv_cpu_template.h\"\n#endif\n\nstatic void glue(riscv_cpu_interp, MAX_XLEN)(RISCVCPUState *s, int n_cycles)\n{\n#ifdef USE_GLOBAL_STATE\n    s = &riscv_cpu_global_state;\n#endif\n    uint64_t timeout;\n\n    timeout = s->insn_counter + n_cycles;\n    while (!s->power_down_flag &&\n           (int)(timeout - s->insn_counter) > 0) {\n        n_cycles = timeout - s->insn_counter;\n        switch(s->cur_xlen) {\n        case 32:\n            riscv_cpu_interp_x32(s, n_cycles);\n            break;\n#if MAX_XLEN >= 64\n        case 64:\n            riscv_cpu_interp_x64(s, n_cycles);\n            break;\n#endif\n#if MAX_XLEN >= 128\n        case 128:\n            riscv_cpu_interp_x128(s, n_cycles);\n            break;\n#endif\n        default:\n            abort();\n        }\n    }\n}\n\n/* Note: the value is not accurate when called in riscv_cpu_interp() */\nstatic uint64_t glue(riscv_cpu_get_cycles, MAX_XLEN)(RISCVCPUState *s)\n{\n    return s->insn_counter;\n}\n\nstatic void glue(riscv_cpu_set_mip, MAX_XLEN)(RISCVCPUState *s, uint32_t mask)\n{\n    s->mip |= mask;\n    /* exit from power down if an interrupt is pending */\n    if (s->power_down_flag && (s->mip & s->mie) != 0)\n        s->power_down_flag = FALSE;\n}\n\nstatic void glue(riscv_cpu_reset_mip, MAX_XLEN)(RISCVCPUState *s, uint32_t mask)\n{\n    s->mip &= ~mask;\n}\n\nstatic uint32_t glue(riscv_cpu_get_mip, MAX_XLEN)(RISCVCPUState *s)\n{\n    return s->mip;\n}\n\nstatic BOOL glue(riscv_cpu_get_power_down, MAX_XLEN)(RISCVCPUState *s)\n{\n    return s->power_down_flag;\n}\n\nstatic RISCVCPUState *glue(riscv_cpu_init, MAX_XLEN)(PhysMemoryMap *mem_map, const SimParams *p)\n{\n    RISCVCPUState *s;\n    \n#ifdef USE_GLOBAL_STATE\n    s = &riscv_cpu_global_state;\n#else\n    s = mallocz(sizeof(*s));\n#endif\n    s->common.class_ptr = &glue(riscv_cpu_class, MAX_XLEN);\n    s->sim_params = (SimParams *)p;\n    s->mem_map = mem_map;\n    s->pc = 0x1000;\n    s->priv = PRV_M;\n    s->cur_xlen = MAX_XLEN;\n    s->mxl = get_base_from_xlen(MAX_XLEN);\n    s->mstatus = ((uint64_t)s->mxl << MSTATUS_UXL_SHIFT) |\n        ((uint64_t)s->mxl << MSTATUS_SXL_SHIFT);\n    s->misa |= MCPUID_SUPER | MCPUID_USER | MCPUID_I | MCPUID_M | MCPUID_A;\n#if FLEN >= 32\n    s->misa |= MCPUID_F;\n#endif\n#if FLEN >= 64\n    s->misa |= MCPUID_D;\n#endif\n#if FLEN >= 128\n    s->misa |= MCPUID_Q;\n#endif\n#ifdef CONFIG_EXT_C\n    s->misa |= MCPUID_C;\n#endif\n\n    s->tlb_code = (TLBEntry*) malloc(sizeof(TLBEntry) * s->sim_params->tlb_size);\n    s->tlb_read = (TLBEntry*) malloc(sizeof(TLBEntry) * s->sim_params->tlb_size);\n    s->tlb_write = (TLBEntry*) malloc(sizeof(TLBEntry) * s->sim_params->tlb_size);\n    assert(s->tlb_code);\n    assert(s->tlb_read);\n    assert(s->tlb_write);\n\n    s->simcpu = riscv_sim_cpu_init(s->sim_params, s);\n    tlb_init(s);\n\n    return s;\n}\n\nstatic void glue(riscv_cpu_end, MAX_XLEN)(RISCVCPUState *s)\n{\n    free(s->tlb_code);\n    free(s->tlb_read);\n    free(s->tlb_write);\n    riscv_sim_cpu_free(&s->simcpu);\n    free(s);\n}\n\nstatic uint32_t glue(riscv_cpu_get_misa, MAX_XLEN)(RISCVCPUState *s)\n{\n    return s->misa;\n}\n\nstatic BOOL glue(riscv_cpu_in_simulation, MAX_XLEN)(RISCVCPUState *s)\n{\n    return s->simcpu->simulation;\n}\n\nstatic uint64_t glue(riscv_cpu_in_simulation_get_mtime, MAX_XLEN)(RISCVCPUState *s)\n{\n    uint64_t scale_offset\n        = s->simcpu->params->cpu_freq_mhz / s->simcpu->params->rtc_freq_mhz;\n    return s->simcpu->temu_rtc_time_at_simstart\n           + (s->simcpu->clock / scale_offset);\n}\n\nconst RISCVCPUClass glue(riscv_cpu_class, MAX_XLEN) = {\n    glue(riscv_cpu_init, MAX_XLEN),\n    glue(riscv_cpu_end, MAX_XLEN),\n    glue(riscv_cpu_interp, MAX_XLEN),\n    glue(riscv_cpu_get_cycles, MAX_XLEN),\n    glue(riscv_cpu_set_mip, MAX_XLEN),\n    glue(riscv_cpu_reset_mip, MAX_XLEN),\n    glue(riscv_cpu_get_mip, MAX_XLEN),\n    glue(riscv_cpu_get_power_down, MAX_XLEN),\n    glue(riscv_cpu_get_misa, MAX_XLEN),\n    glue(riscv_cpu_flush_tlb_write_range_ram, MAX_XLEN),\n    glue(riscv_cpu_in_simulation, MAX_XLEN),\n    glue(riscv_cpu_in_simulation_get_mtime, MAX_XLEN),\n};\n\n//#if CONFIG_RISCV_MAX_XLEN == MAX_XLEN\nRISCVCPUState *riscv_cpu_init(PhysMemoryMap *mem_map, int max_xlen, const SimParams *p)\n{\n    const RISCVCPUClass *c;\n    switch(max_xlen) {\n        /* with emscripten we compile a single CPU */\n#if defined(EMSCRIPTEN)\n    case MAX_XLEN:\n        c = &glue(riscv_cpu_class, MAX_XLEN);\n        break;\n#else\n#if MAX_XLEN == 32\n    case 32:\n        c = &riscv_cpu_class32;\n        break;\n#endif\n#if MAX_XLEN == 64\n    case 64:\n        c = &riscv_cpu_class64;\n        break;\n#endif\n#if CONFIG_RISCV_MAX_XLEN == 128\n    case 128:\n        c = &riscv_cpu_class128;\n        break;\n#endif\n#endif /* !EMSCRIPTEN */\n    default:\n        return NULL;\n    }\n    return c->riscv_cpu_init(mem_map, p);\n}\n//#endif /* CONFIG_RISCV_MAX_XLEN == MAX_XLEN */\n"
  },
  {
    "path": "src/riscv_cpu.h",
    "content": "/*\n * RISCV CPU emulator\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef RISCV_CPU_H\n#define RISCV_CPU_H\n\n#include <stdlib.h>\n#include \"cutils.h\"\n#include \"iomem.h\"\n#include \"riscvsim/utils/sim_params.h\"\n\n#define MIP_USIP (1 << 0)\n#define MIP_SSIP (1 << 1)\n#define MIP_HSIP (1 << 2)\n#define MIP_MSIP (1 << 3)\n#define MIP_UTIP (1 << 4)\n#define MIP_STIP (1 << 5)\n#define MIP_HTIP (1 << 6)\n#define MIP_MTIP (1 << 7)\n#define MIP_UEIP (1 << 8)\n#define MIP_SEIP (1 << 9)\n#define MIP_HEIP (1 << 10)\n#define MIP_MEIP (1 << 11)\n\ntypedef struct RISCVCPUState RISCVCPUState;\n\ntypedef struct {\n    RISCVCPUState *(*riscv_cpu_init)(PhysMemoryMap *mem_map, const SimParams *p);\n    void (*riscv_cpu_end)(RISCVCPUState *s);\n    void (*riscv_cpu_interp)(RISCVCPUState *s, int n_cycles);\n    uint64_t (*riscv_cpu_get_cycles)(RISCVCPUState *s);\n    void (*riscv_cpu_set_mip)(RISCVCPUState *s, uint32_t mask);\n    void (*riscv_cpu_reset_mip)(RISCVCPUState *s, uint32_t mask);\n    uint32_t (*riscv_cpu_get_mip)(RISCVCPUState *s);\n    BOOL (*riscv_cpu_get_power_down)(RISCVCPUState *s);\n    uint32_t (*riscv_cpu_get_misa)(RISCVCPUState *s);\n    void (*riscv_cpu_flush_tlb_write_range_ram)(RISCVCPUState *s,\n                                                uint8_t *ram_ptr, size_t ram_size);\n    BOOL (*riscv_cpu_in_simulation)(RISCVCPUState *s);\n    uint64_t (*riscv_cpu_in_simulation_get_mtime)(RISCVCPUState *s);\n} RISCVCPUClass;\n\ntypedef struct {\n    const RISCVCPUClass *class_ptr;\n} RISCVCPUCommonState;\n\n\nint riscv_cpu_get_max_xlen(void);\n\nextern const RISCVCPUClass riscv_cpu_class32;\nextern const RISCVCPUClass riscv_cpu_class64;\nextern const RISCVCPUClass riscv_cpu_class128;\n\nRISCVCPUState *riscv_cpu_init(PhysMemoryMap *mem_map, int max_xlen, const SimParams *sim_params);\nstatic inline void riscv_cpu_end(RISCVCPUState *s)\n{\n    const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr;\n    c->riscv_cpu_end(s);\n}\nstatic inline void riscv_cpu_interp(RISCVCPUState *s, int n_cycles)\n{\n    const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr;\n    c->riscv_cpu_interp(s, n_cycles);\n}\nstatic inline uint64_t riscv_cpu_get_cycles(RISCVCPUState *s)\n{\n    const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr;\n    return c->riscv_cpu_get_cycles(s);\n}\nstatic inline void riscv_cpu_set_mip(RISCVCPUState *s, uint32_t mask)\n{\n    const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr;\n    c->riscv_cpu_set_mip(s, mask);\n}\nstatic inline void riscv_cpu_reset_mip(RISCVCPUState *s, uint32_t mask)\n{\n    const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr;\n    c->riscv_cpu_reset_mip(s, mask);\n}\nstatic inline uint32_t riscv_cpu_get_mip(RISCVCPUState *s)\n{\n    const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr;\n    return c->riscv_cpu_get_mip(s);\n}\nstatic inline BOOL riscv_cpu_get_power_down(RISCVCPUState *s)\n{\n    const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr;\n    return c->riscv_cpu_get_power_down(s);\n}\nstatic inline uint32_t riscv_cpu_get_misa(RISCVCPUState *s)\n{\n    const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr;\n    return c->riscv_cpu_get_misa(s);\n}\nstatic inline void riscv_cpu_flush_tlb_write_range_ram(RISCVCPUState *s,\n                                                       uint8_t *ram_ptr, size_t ram_size)\n{\n    const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr;\n    c->riscv_cpu_flush_tlb_write_range_ram(s, ram_ptr, ram_size);\n}\nstatic inline BOOL riscv_cpu_in_simulation(RISCVCPUState *s)\n{\n    const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr;\n    return c->riscv_cpu_in_simulation(s);\n}\nstatic inline uint64_t riscv_cpu_in_simulation_get_mtime(RISCVCPUState *s)\n{\n    const RISCVCPUClass *c = ((RISCVCPUCommonState *)s)->class_ptr;\n    return c->riscv_cpu_in_simulation_get_mtime(s);\n}\n#endif /* RISCV_CPU_H */\n"
  },
  {
    "path": "src/riscv_cpu_fp_template.h",
    "content": "/*\n * RISCV emulator\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#if F_SIZE == 32\n#define OPID 0\n#define F_HIGH F32_HIGH\n#elif F_SIZE == 64\n#define OPID 1\n#define F_HIGH F64_HIGH\n#elif F_SIZE == 128\n#define OPID 3\n#define F_HIGH 0\n#else\n#error unsupported F_SIZE\n#endif\n\n#define FSIGN_MASK glue(FSIGN_MASK, F_SIZE)\n\n            case (0x00 << 2) | OPID:\n                rm = get_insn_rm(s, rm);\n                if (rm < 0)\n                    goto illegal_insn;\n                s->fp_reg[rd] = glue(add_sf, F_SIZE)(s->fp_reg[rs1],\n                                         s->fp_reg[rs2],\n                                         rm, &s->fflags) | F_HIGH;\n                s->fs = 3;                                             \n                break;\n            case (0x01 << 2) | OPID:\n                rm = get_insn_rm(s, rm);\n                if (rm < 0)\n                    goto illegal_insn;\n                s->fp_reg[rd] = glue(sub_sf, F_SIZE)(s->fp_reg[rs1],\n                                               s->fp_reg[rs2],\n                                               rm, &s->fflags) | F_HIGH;\n                s->fs = 3;                                             \n                break;\n            case (0x02 << 2) | OPID:\n                rm = get_insn_rm(s, rm);\n                if (rm < 0)\n                    goto illegal_insn;\n                s->fp_reg[rd] = glue(mul_sf, F_SIZE)(s->fp_reg[rs1],\n                                               s->fp_reg[rs2],\n                                               rm, &s->fflags) | F_HIGH;\n                s->fs = 3;                                             \n                break;\n            case (0x03 << 2) | OPID:\n                rm = get_insn_rm(s, rm);\n                if (rm < 0)\n                    goto illegal_insn;\n                s->fp_reg[rd] = glue(div_sf, F_SIZE)(s->fp_reg[rs1],\n                                               s->fp_reg[rs2],\n                                               rm, &s->fflags) | F_HIGH;\n                s->fs = 3;                                             \n                break;\n            case (0x0b << 2) | OPID:\n                rm = get_insn_rm(s, rm);\n                if (rm < 0 || rs2 != 0)\n                    goto illegal_insn;\n                s->fp_reg[rd] = glue(sqrt_sf, F_SIZE)(s->fp_reg[rs1],\n                                                rm, &s->fflags) | F_HIGH;\n                s->fs = 3;                                             \n                break;\n            case (0x04 << 2) | OPID:\n                switch(rm) {\n                case 0: /* fsgnj */\n                    s->fp_reg[rd] = (s->fp_reg[rs1] & ~FSIGN_MASK) |\n                        (s->fp_reg[rs2] & FSIGN_MASK);\n                    break;\n                case 1: /* fsgnjn */\n                    s->fp_reg[rd] = (s->fp_reg[rs1] & ~FSIGN_MASK) |\n                        ((s->fp_reg[rs2] & FSIGN_MASK) ^ FSIGN_MASK);\n                    break;\n                case 2: /* fsgnjx */\n                    s->fp_reg[rd] = s->fp_reg[rs1] ^\n                        (s->fp_reg[rs2] & FSIGN_MASK);\n                    break;\n                default:\n                    goto illegal_insn;\n                }\n                s->fs = 3;                                             \n                break;\n            case (0x05 << 2) | OPID:\n                switch(rm) {\n                case 0: /* fmin */\n                    s->fp_reg[rd] = glue(min_sf, F_SIZE)(s->fp_reg[rs1],\n                                                   s->fp_reg[rs2],\n                                                   &s->fflags,\n                                                   FMINMAX_IEEE754_201X) | F_HIGH;\n                    break;\n                case 1: /* fmax */\n                    s->fp_reg[rd] = glue(max_sf, F_SIZE)(s->fp_reg[rs1],\n                                                   s->fp_reg[rs2],\n                                                   &s->fflags,\n                                                   FMINMAX_IEEE754_201X) | F_HIGH;\n                    break;\n                default:\n                    goto illegal_insn;\n                }\n                s->fs = 3;                                             \n                break;\n            case (0x18 << 2) | OPID:\n                rm = get_insn_rm(s, rm);\n                if (rm < 0)\n                    goto illegal_insn;\n                switch(rs2) {\n                case 0: /* fcvt.w.[sdq] */\n                    val = (int32_t)glue(glue(cvt_sf, F_SIZE), _i32)(s->fp_reg[rs1], rm,\n                                                          &s->fflags);\n                    break;\n                case 1: /* fcvt.wu.[sdq] */\n                    val = (int32_t)glue(glue(cvt_sf, F_SIZE), _u32)(s->fp_reg[rs1], rm,\n                                                          &s->fflags);\n                    break;\n#if XLEN >= 64\n                case 2: /* fcvt.l.[sdq] */\n                    val = (int64_t)glue(glue(cvt_sf, F_SIZE), _i64)(s->fp_reg[rs1], rm,\n                                                          &s->fflags);\n                    break;\n                case 3: /* fcvt.lu.[sdq] */\n                    val = (int64_t)glue(glue(cvt_sf, F_SIZE), _u64)(s->fp_reg[rs1], rm,\n                                                          &s->fflags);\n                    break;\n#endif\n#if XLEN >= 128\n                /* XXX: the index is not defined in the spec */\n                case 4: /* fcvt.t.[sdq] */\n                    val = glue(glue(cvt_sf, F_SIZE), _i128)(s->fp_reg[rs1], rm,\n                                                          &s->fflags);\n                    break;\n                case 5: /* fcvt.tu.[sdq] */\n                    val = glue(glue(cvt_sf, F_SIZE), _u128)(s->fp_reg[rs1], rm,\n                                                          &s->fflags);\n                    break;\n#endif\n                default:\n                    goto illegal_insn;\n                }\n                if (rd != 0)\n                    s->reg[rd] = val;\n                break;\n            case (0x14 << 2) | OPID:\n                switch(rm) {\n                case 0: /* fle */\n                    val = glue(le_sf, F_SIZE)(s->fp_reg[rs1], s->fp_reg[rs2],\n                                     &s->fflags);\n                    break;\n                case 1: /* flt */\n                    val = glue(lt_sf, F_SIZE)(s->fp_reg[rs1], s->fp_reg[rs2],\n                                     &s->fflags);\n                    break;\n                case 2: /* feq */\n                    val = glue(eq_quiet_sf, F_SIZE)(s->fp_reg[rs1], s->fp_reg[rs2],\n                                           &s->fflags);\n                    break;\n                default:\n                    goto illegal_insn;\n                }\n                if (rd != 0)\n                    s->reg[rd] = val;\n                break;\n            case (0x1a << 2) | OPID:\n                rm = get_insn_rm(s, rm);\n                if (rm < 0)\n                    goto illegal_insn;\n                switch(rs2) {\n                case 0: /* fcvt.[sdq].w */\n                    s->fp_reg[rd] = glue(cvt_i32_sf, F_SIZE)(s->reg[rs1], rm,\n                                                       &s->fflags) | F_HIGH;\n                    break;\n                case 1: /* fcvt.[sdq].wu */\n                    s->fp_reg[rd] = glue(cvt_u32_sf, F_SIZE)(s->reg[rs1], rm,\n                                                       &s->fflags) | F_HIGH;\n                    break;\n#if XLEN >= 64\n                case 2: /* fcvt.[sdq].l */\n                    s->fp_reg[rd] = glue(cvt_i64_sf, F_SIZE)(s->reg[rs1], rm,\n                                                       &s->fflags) | F_HIGH;\n                    break;\n                case 3: /* fcvt.[sdq].lu */\n                    s->fp_reg[rd] = glue(cvt_u64_sf, F_SIZE)(s->reg[rs1], rm,\n                                                            &s->fflags) | F_HIGH;\n                    break;\n#endif\n#if XLEN >= 128\n                /* XXX: the index is not defined in the spec */\n                case 4: /* fcvt.[sdq].t */\n                    s->fp_reg[rd] = glue(cvt_i128_sf, F_SIZE)(s->reg[rs1], rm,\n                                                       &s->fflags) | F_HIGH;\n                    break;\n                case 5: /* fcvt.[sdq].tu */\n                    s->fp_reg[rd] = glue(cvt_u128_sf, F_SIZE)(s->reg[rs1], rm,\n                                                            &s->fflags) | F_HIGH;\n                    break;\n#endif\n                default:\n                    goto illegal_insn;\n                }\n                s->fs = 3;\n                break;\n\n            case (0x08 << 2) | OPID:\n                rm = get_insn_rm(s, rm);\n                if (rm < 0)\n                    goto illegal_insn;\n                switch(rs2) {\n#if F_SIZE == 32 && FLEN >= 64\n                case 1: /* cvt.s.d */\n                    s->fp_reg[rd] = cvt_sf64_sf32(s->fp_reg[rs1], rm, &s->fflags) | F32_HIGH;\n                    break;\n#if FLEN >= 128\n                case 3: /* cvt.s.q */\n                    s->fp_reg[rd] = cvt_sf128_sf32(s->fp_reg[rs1], rm, &s->fflags) | F32_HIGH;\n                    break;\n#endif\n#endif /* F_SIZE == 32 */\n#if F_SIZE == 64\n                case 0: /* cvt.d.s */\n                    s->fp_reg[rd] = cvt_sf32_sf64(s->fp_reg[rs1], &s->fflags) | F64_HIGH;\n                    break;\n#if FLEN >= 128\n                case 1: /* cvt.d.q */\n                    s->fp_reg[rd] = cvt_sf128_sf64(s->fp_reg[rs1], rm, &s->fflags) | F64_HIGH;\n                    break;\n#endif\n#endif /* F_SIZE == 64 */\n#if F_SIZE == 128\n                case 0: /* cvt.q.s */\n                    s->fp_reg[rd] = cvt_sf32_sf128(s->fp_reg[rs1], &s->fflags);\n                    break;\n                case 1: /* cvt.q.d */\n                    s->fp_reg[rd] = cvt_sf64_sf128(s->fp_reg[rs1], &s->fflags);\n                    break;\n#endif /* F_SIZE == 128 */\n                    \n                default:\n                    goto illegal_insn;\n                }\n                s->fs = 3;\n                break;\n\n            case (0x1c << 2) | OPID:\n                if (rs2 != 0)\n                    goto illegal_insn;            \n                switch(rm) {\n#if F_SIZE <= XLEN\n                case 0: /* fmv.x.s */\n#if F_SIZE == 32\n                    val = (int32_t)s->fp_reg[rs1];\n#elif F_SIZE == 64\n                    val = (int64_t)s->fp_reg[rs1];\n#else\n                    val = (int128_t)s->fp_reg[rs1];\n#endif\n                    break;\n#endif /* F_SIZE <= XLEN */\n                case 1: /* fclass */\n                    val = glue(fclass_sf, F_SIZE)(s->fp_reg[rs1]);\n                    break;\n                default:\n                    goto illegal_insn;\n                }\n                if (rd != 0)\n                    s->reg[rd] = val;\n                break;\n\n#if F_SIZE <= XLEN\n            case (0x1e << 2) | OPID: /* fmv.s.x */\n                if (rs2 != 0 || rm != 0)\n                    goto illegal_insn;\n#if F_SIZE == 32\n                s->fp_reg[rd] = (int32_t)s->reg[rs1];\n#elif F_SIZE == 64\n                s->fp_reg[rd] = (int64_t)s->reg[rs1];\n#else\n                s->fp_reg[rd] = (int128_t)s->reg[rs1];\n#endif\n                s->fs = 3;\n                break;\n#endif /* F_SIZE <= XLEN */\n\n#undef F_SIZE\n#undef F_HIGH\n#undef OPID\n#undef FSIGN_MASK\n"
  },
  {
    "path": "src/riscv_cpu_priv.h",
    "content": "/*\n * RISCV CPU emulator private definitions\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef RISCV_CPU_PRIV_H\n#define RISCV_CPU_PRIV_H\n\n#include <sys/time.h>\n#include <errno.h>\n#include <stdio.h>\n#include \"riscv_cpu.h\"\n#include \"cutils.h\"\n\n#include \"riscvsim/core/riscv_sim_cpu.h\"\n#include \"riscvsim/utils/sim_params.h\"\n#include \"rtc_timer.h\"\n\n#define __exception __attribute__((warn_unused_result))\n\n#define CONFIG_EXT_C /* compressed instructions */\n\n#if defined(EMSCRIPTEN)\n#define USE_GLOBAL_STATE\n/* use local variables slows down the generated JS code */\n#define USE_GLOBAL_VARIABLES\n#endif\n\n#include \"riscv_cpu_xlen_typedefs.h\"\n\n#define CAUSE_MISALIGNED_FETCH    0x0\n#define CAUSE_FAULT_FETCH         0x1\n#define CAUSE_ILLEGAL_INSTRUCTION 0x2\n#define CAUSE_BREAKPOINT          0x3\n#define CAUSE_MISALIGNED_LOAD     0x4\n#define CAUSE_FAULT_LOAD          0x5\n#define CAUSE_MISALIGNED_STORE    0x6\n#define CAUSE_FAULT_STORE         0x7\n#define CAUSE_USER_ECALL          0x8\n#define CAUSE_SUPERVISOR_ECALL    0x9\n#define CAUSE_HYPERVISOR_ECALL    0xa\n#define CAUSE_MACHINE_ECALL       0xb\n#define CAUSE_FETCH_PAGE_FAULT    0xc\n#define CAUSE_LOAD_PAGE_FAULT     0xd\n#define CAUSE_STORE_PAGE_FAULT    0xf\n\n/* Note: converted to correct bit position at runtime */\n#define CAUSE_INTERRUPT  ((uint32_t)1 << 31) \n\n/* Only used to count interrupts during simulation */\n#define CAUSE_USER_SOFTWARE_INTERRUPT 0x0\n#define CAUSE_SUPERVISOR_SOFTWARE_INTERRUPT 0x1\n#define CAUSE_MACHINE_SOFTWARE_INTERRUPT 0x3\n#define CAUSE_USER_TIMER_INTERRUPT 0x4\n#define CAUSE_SUPERVISOR_TIMER_INTERRUPT 0x5\n#define CAUSE_MACHINE_TIMER_INTERRUPT 0x7\n#define CAUSE_USER_EXTERNAL_INTERRUPT 0x8\n#define CAUSE_SUPERVISOR_EXTERNAL_INTERRUPT 0x9\n#define CAUSE_MACHINE_EXTERNAL_INTERRUPT 0xb\n\n#define PRV_U 0\n#define PRV_S 1\n#define PRV_H 2\n#define PRV_M 3\n\n/* misa CSR */\n#define MCPUID_SUPER   (1 << ('S' - 'A'))\n#define MCPUID_USER    (1 << ('U' - 'A'))\n#define MCPUID_I       (1 << ('I' - 'A'))\n#define MCPUID_M       (1 << ('M' - 'A'))\n#define MCPUID_A       (1 << ('A' - 'A'))\n#define MCPUID_F       (1 << ('F' - 'A'))\n#define MCPUID_D       (1 << ('D' - 'A'))\n#define MCPUID_Q       (1 << ('Q' - 'A'))\n#define MCPUID_C       (1 << ('C' - 'A'))\n\n/* mstatus CSR */\n\n#define MSTATUS_SPIE_SHIFT 5\n#define MSTATUS_MPIE_SHIFT 7\n#define MSTATUS_SPP_SHIFT 8\n#define MSTATUS_MPP_SHIFT 11\n#define MSTATUS_FS_SHIFT 13\n#define MSTATUS_UXL_SHIFT 32\n#define MSTATUS_SXL_SHIFT 34\n\n#define MSTATUS_UIE (1 << 0)\n#define MSTATUS_SIE (1 << 1)\n#define MSTATUS_HIE (1 << 2)\n#define MSTATUS_MIE (1 << 3)\n#define MSTATUS_UPIE (1 << 4)\n#define MSTATUS_SPIE (1 << MSTATUS_SPIE_SHIFT)\n#define MSTATUS_HPIE (1 << 6)\n#define MSTATUS_MPIE (1 << MSTATUS_MPIE_SHIFT)\n#define MSTATUS_SPP (1 << MSTATUS_SPP_SHIFT)\n#define MSTATUS_HPP (3 << 9)\n#define MSTATUS_MPP (3 << MSTATUS_MPP_SHIFT)\n#define MSTATUS_FS (3 << MSTATUS_FS_SHIFT)\n#define MSTATUS_XS (3 << 15)\n#define MSTATUS_MPRV (1 << 17)\n#define MSTATUS_SUM (1 << 18)\n#define MSTATUS_MXR (1 << 19)\n//#define MSTATUS_TVM (1 << 20)\n//#define MSTATUS_TW (1 << 21)\n//#define MSTATUS_TSR (1 << 22)\n#define MSTATUS_UXL_MASK ((uint64_t)3 << MSTATUS_UXL_SHIFT)\n#define MSTATUS_SXL_MASK ((uint64_t)3 << MSTATUS_SXL_SHIFT)\n\n#define PG_SHIFT 12\n#define PG_MASK ((1 << PG_SHIFT) - 1)\n#define TLB_SIZE (s->sim_params->tlb_size)\n\ntypedef struct {\n    target_ulong vaddr;\n    uintptr_t mem_addend;\n    target_ulong guest_paddr;\n} TLBEntry;\n\ntypedef struct RISCVCPUState {\n    RISCVCPUCommonState common; /* must be first */\n    \n    target_ulong pc;\n    target_ulong reg[32];\n\n#ifdef USE_GLOBAL_VARIABLES\n    /* faster to use global variables with emscripten */\n    uint8_t *__code_ptr, *__code_end;\n    target_ulong __code_to_pc_addend;\n#endif\n    \n#if FLEN > 0\n    fp_uint fp_reg[32];\n    uint32_t fflags;\n    uint8_t frm;\n#endif\n    \n    uint8_t cur_xlen;  /* current XLEN value, <= MAX_XLEN */\n    uint8_t priv; /* see PRV_x */\n    uint8_t fs; /* MSTATUS_FS value */\n    uint8_t mxl; /* MXL field in MISA register */\n    \n    int32_t n_cycles; /* only used inside the CPU loop */\n    uint64_t insn_counter;\n    BOOL power_down_flag;\n    int pending_exception; /* used during MMU exception handling */\n    target_ulong pending_tval;\n    \n    /* CSRs */\n    target_ulong mstatus;\n    target_ulong mtvec;\n    target_ulong mscratch;\n    target_ulong mepc;\n    target_ulong mcause;\n    target_ulong mtval;\n    target_ulong mhartid; /* ro */\n    uint32_t misa;\n    uint32_t mie;\n    uint32_t mip;\n    uint32_t medeleg;\n    uint32_t mideleg;\n    uint32_t mcounteren;\n    \n    target_ulong stvec;\n    target_ulong sscratch;\n    target_ulong sepc;\n    target_ulong scause;\n    target_ulong stval;\n#if MAX_XLEN == 32\n    uint32_t satp;\n#else\n    uint64_t satp; /* currently 64 bit physical addresses max */\n#endif\n    uint32_t scounteren;\n\n    target_ulong load_res; /* for atomic LR/SC */\n\n    PhysMemoryMap *mem_map;\n\n    TLBEntry *tlb_read;\n    TLBEntry *tlb_write;\n    TLBEntry *tlb_code;\n\n    /* used to fetch instructions from TinyEMU memory map */\n    uint8_t *code_ptr, *code_end;\n    target_ulong code_to_pc_addend;\n\n    /* These are the physical addresses for current instruction and data memory\n     * from TinyEMU physical memory map defined in virt_machine.c. They are used\n     * for look-up into memory hierarchy by the simulated core. */\n    target_ulong code_guest_paddr;\n    target_ulong data_guest_paddr;\n\n    /* Track whether the current data memory access was a device IO or RAM IO */\n    int is_device_io;\n    int hw_pg_tb_wlk_stage_id;  /* id of the stage (FETCH, MEMORY) which initiated page table walk */\n    int ins_tlb_lookup_accounted;\n    int ins_tlb_hit_accounted;\n\n    SimParams *sim_params;\n    RTC *rtc;\n\n    /* simulated RISC-V core*/\n    RISCVSIMCPUState *simcpu;\n  } RISCVCPUState;\n\n/* Note: Below declared functions are accessed from both simulation and emulation side */\nint get_insn_rm(RISCVCPUState *s, unsigned int rm);\n\nno_inline __exception int\ntarget_read_insn_slow(RISCVCPUState *s, uint8_t **pptr, target_ulong addr);\n\n__exception int target_read_insn_u16(RISCVCPUState *s, uint16_t *pinsn,\n                                       target_ulong addr);\n\nuint32_t get_insn32(uint8_t *ptr);\n\n#define target_read_slow glue(glue(riscv, MAX_XLEN), _read_slow)\n#define target_write_slow glue(glue(riscv, MAX_XLEN), _write_slow)\n\nDLL_PUBLIC int target_read_slow(RISCVCPUState *s, mem_uint_t *pval,\n                                target_ulong addr, int size_log2);\nDLL_PUBLIC int target_write_slow(RISCVCPUState *s, target_ulong addr,\n                                 mem_uint_t val, int size_log2);\n\n/* return 0 if OK, != 0 if exception */\n#define TARGET_READ_WRITE(size, uint_type, size_log2)                          \\\n    static inline __exception int target_read_u##size(                         \\\n        RISCVCPUState *s, uint_type *pval, target_ulong addr)                  \\\n    {                                                                          \\\n        uint32_t tlb_idx;                                                      \\\n                                                                               \\\n        s->is_device_io = 0;                                                   \\\n        tlb_idx = (addr >> PG_SHIFT) & (TLB_SIZE - 1);                         \\\n        if (s->simcpu->simulation)                                             \\\n        {                                                                      \\\n            ++s->simcpu->stats[s->priv].load_tlb_lookups;                      \\\n        }                                                                      \\\n        if (likely(s->tlb_read[tlb_idx].vaddr                                  \\\n                   == (addr & ~(PG_MASK & ~((size / 8) - 1)))))                \\\n        {                                                                      \\\n            *pval = *(uint_type *)(s->tlb_read[tlb_idx].mem_addend             \\\n                                   + (uintptr_t)addr);                         \\\n            if (s->simcpu->simulation)                                         \\\n            {                                                                  \\\n                ++s->simcpu->stats[s->priv].load_tlb_hits;                     \\\n            }                                                                  \\\n        }                                                                      \\\n        else                                                                   \\\n        {                                                                      \\\n            mem_uint_t val;                                                    \\\n            int ret;                                                           \\\n            ret = target_read_slow(s, &val, addr, size_log2);                  \\\n            if (ret)                                                           \\\n                return ret;                                                    \\\n            *pval = val;                                                       \\\n        }                                                                      \\\n                                                                               \\\n        if (!s->is_device_io)                                                  \\\n        {                                                                      \\\n            s->data_guest_paddr = s->tlb_read[tlb_idx].guest_paddr             \\\n                                  + (addr - s->tlb_read[tlb_idx].vaddr);       \\\n        }                                                                      \\\n        return 0;                                                              \\\n    }                                                                          \\\n                                                                               \\\n    static inline __exception int target_write_u##size(                        \\\n        RISCVCPUState *s, target_ulong addr, uint_type val)                    \\\n    {                                                                          \\\n        uint32_t tlb_idx;                                                      \\\n                                                                               \\\n        s->is_device_io = 0;                                                   \\\n        tlb_idx = (addr >> PG_SHIFT) & (TLB_SIZE - 1);                         \\\n        if (s->simcpu->simulation)                                             \\\n        {                                                                      \\\n            ++s->simcpu->stats[s->priv].store_tlb_lookups;                     \\\n        }                                                                      \\\n        if (likely(s->tlb_write[tlb_idx].vaddr                                 \\\n                   == (addr & ~(PG_MASK & ~((size / 8) - 1)))))                \\\n        {                                                                      \\\n            *(uint_type *)(s->tlb_write[tlb_idx].mem_addend + (uintptr_t)addr) \\\n                = val;                                                         \\\n            if (s->simcpu->simulation)                                         \\\n            {                                                                  \\\n                ++s->simcpu->stats[s->priv].store_tlb_hits;                    \\\n            }                                                                  \\\n        }                                                                      \\\n        else                                                                   \\\n        {                                                                      \\\n            int ret;                                                           \\\n            ret = target_write_slow(s, addr, val, size_log2);                  \\\n            if (ret)                                                           \\\n                return ret;                                                    \\\n        }                                                                      \\\n                                                                               \\\n        if (!s->is_device_io)                                                  \\\n        {                                                                      \\\n            s->data_guest_paddr = s->tlb_write[tlb_idx].guest_paddr            \\\n                                  + (addr - s->tlb_write[tlb_idx].vaddr);      \\\n        }                                                                      \\\n        return 0;                                                              \\\n    }\n\nTARGET_READ_WRITE(8, uint8_t, 0)\nTARGET_READ_WRITE(16, uint16_t, 1)\nTARGET_READ_WRITE(32, uint32_t, 2)\n#if MLEN >= 64\nTARGET_READ_WRITE(64, uint64_t, 3)\n#endif\n#if MLEN >= 128\nTARGET_READ_WRITE(128, uint128_t, 4)\n#endif\n\n#endif /* RISCV_CPU_PRIV_H */\n"
  },
  {
    "path": "src/riscv_cpu_template.h",
    "content": "/*\n * RISCV emulator\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n * \n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#if XLEN == 32\n#define uintx_t uint32_t\n#define intx_t int32_t\n#elif XLEN == 64\n#define uintx_t uint64_t\n#define intx_t int64_t\n#elif XLEN == 128\n#define uintx_t uint128_t\n#define intx_t int128_t\n#else\n#error unsupported XLEN\n#endif\n\nstatic inline intx_t glue(div, XLEN)(intx_t a, intx_t b)\n{\n    if (b == 0) {\n        return -1;\n    } else if (a == ((intx_t)1 << (XLEN - 1)) && b == -1) {\n        return a;\n    } else {\n        return a / b;\n    }\n}\n\nstatic inline uintx_t glue(divu, XLEN)(uintx_t a, uintx_t b)\n{\n    if (b == 0) {\n        return -1;\n    } else {\n        return a / b;\n    }\n}\n\nstatic inline intx_t glue(rem, XLEN)(intx_t a, intx_t b)\n{\n    if (b == 0) {\n        return a;\n    } else if (a == ((intx_t)1 << (XLEN - 1)) && b == -1) {\n        return 0;\n    } else {\n        return a % b;\n    }\n}\n\nstatic inline uintx_t glue(remu, XLEN)(uintx_t a, uintx_t b)\n{\n    if (b == 0) {\n        return a;\n    } else {\n        return a % b;\n    }\n}\n\n#if XLEN == 32\n\nstatic inline uint32_t mulh32(int32_t a, int32_t b)\n{\n    return ((int64_t)a * (int64_t)b) >> 32;\n}\n\nstatic inline uint32_t mulhsu32(int32_t a, uint32_t b)\n{\n    return ((int64_t)a * (int64_t)b) >> 32;\n}\n\nstatic inline uint32_t mulhu32(uint32_t a, uint32_t b)\n{\n    return ((int64_t)a * (int64_t)b) >> 32;\n}\n\n#elif XLEN == 64 && defined(HAVE_INT128)\n\nstatic inline uint64_t mulh64(int64_t a, int64_t b)\n{\n    return ((int128_t)a * (int128_t)b) >> 64;\n}\n\nstatic inline uint64_t mulhsu64(int64_t a, uint64_t b)\n{\n    return ((int128_t)a * (int128_t)b) >> 64;\n}\n\nstatic inline uint64_t mulhu64(uint64_t a, uint64_t b)\n{\n    return ((int128_t)a * (int128_t)b) >> 64;\n}\n\n#else\n\n#if XLEN == 64\n#define UHALF uint32_t\n#define UHALF_LEN 32\n#elif XLEN == 128\n#define UHALF uint64_t\n#define UHALF_LEN 64\n#else\n#error unsupported XLEN\n#endif\n\nstatic uintx_t glue(mulhu, XLEN)(uintx_t a, uintx_t b)\n{\n    UHALF a0, a1, b0, b1, r2, r3;\n    uintx_t r00, r01, r10, r11, c;\n    a0 = a;\n    a1 = a >> UHALF_LEN;\n    b0 = b;\n    b1 = b >> UHALF_LEN;\n\n    r00 = (uintx_t)a0 * (uintx_t)b0;\n    r01 = (uintx_t)a0 * (uintx_t)b1;\n    r10 = (uintx_t)a1 * (uintx_t)b0;\n    r11 = (uintx_t)a1 * (uintx_t)b1;\n    \n    //    r0 = r00;\n    c = (r00 >> UHALF_LEN) + (UHALF)r01 + (UHALF)r10;\n    //    r1 = c;\n    c = (c >> UHALF_LEN) + (r01 >> UHALF_LEN) + (r10 >> UHALF_LEN) + (UHALF)r11;\n    r2 = c;\n    r3 = (c >> UHALF_LEN) + (r11 >> UHALF_LEN);\n\n    //    *plow = ((uintx_t)r1 << UHALF_LEN) | r0;\n    return ((uintx_t)r3 << UHALF_LEN) | r2;\n}\n\n#undef UHALF\n\nstatic inline uintx_t glue(mulh, XLEN)(intx_t a, intx_t b)\n{\n    uintx_t r1;\n    r1 = glue(mulhu, XLEN)(a, b);\n    if (a < 0)\n        r1 -= a;\n    if (b < 0)\n        r1 -= b;\n    return r1;\n}\n\nstatic inline uintx_t glue(mulhsu, XLEN)(intx_t a, uintx_t b)\n{\n    uintx_t r1;\n    r1 = glue(mulhu, XLEN)(a, b);\n    if (a < 0)\n        r1 -= a;\n    return r1;\n}\n\n#endif\n\n#define DUP2(F, n) F(n) F(n+1)\n#define DUP4(F, n) DUP2(F, n) DUP2(F, n + 2)\n#define DUP8(F, n) DUP4(F, n) DUP4(F, n + 4)\n#define DUP16(F, n) DUP8(F, n) DUP8(F, n + 8)\n#define DUP32(F, n) DUP16(F, n) DUP16(F, n + 16)\n\n#define C_QUADRANT(n) \\\n    case n+(0 << 2): case n+(1 << 2): case n+(2 << 2): case n+(3 << 2): \\\n    case n+(4 << 2): case n+(5 << 2): case n+(6 << 2): case n+(7 << 2): \\\n    case n+(8 << 2): case n+(9 << 2): case n+(10 << 2): case n+(11 << 2): \\\n    case n+(12 << 2): case n+(13 << 2): case n+(14 << 2): case n+(15 << 2): \\\n    case n+(16 << 2): case n+(17 << 2): case n+(18 << 2): case n+(19 << 2): \\\n    case n+(20 << 2): case n+(21 << 2): case n+(22 << 2): case n+(23 << 2): \\\n    case n+(24 << 2): case n+(25 << 2): case n+(26 << 2): case n+(27 << 2): \\\n    case n+(28 << 2): case n+(29 << 2): case n+(30 << 2): case n+(31 << 2): \n\n#define GET_PC() (target_ulong)((uintptr_t)code_ptr + code_to_pc_addend)\n#define GET_INSN_COUNTER() (insn_counter_addend - s->n_cycles)\n\n#define C_NEXT_INSN code_ptr += 2; break\n#define NEXT_INSN code_ptr += 4; break\n#define JUMP_INSN do {   \\\n        code_ptr = NULL;           \\\n        code_end = NULL;           \\\n        code_to_pc_addend = s->pc; \\\n        goto jump_insn;            \\\n    } while (0)\n\nstatic void no_inline glue(riscv_cpu_interp_x, XLEN)(RISCVCPUState *s,\n                                                   int n_cycles1)\n{\n    uint32_t opcode, insn, rd, rs1, rs2, funct3;\n    int32_t imm, cond, err;\n    int run_mode = 0;\n    int sim_exit_status;\n    target_ulong addr, val, val2;\n#ifndef USE_GLOBAL_VARIABLES\n    uint8_t *code_ptr, *code_end;\n    target_ulong code_to_pc_addend;\n#endif\n    uint64_t insn_counter_addend;\n#if FLEN > 0\n    uint32_t rs3;\n    int32_t rm;\n#endif\n\n    if (n_cycles1 == 0)\n        return;\n    insn_counter_addend = s->insn_counter + n_cycles1;\n    s->n_cycles = n_cycles1;\n\n    /* check pending interrupts */\n    if (unlikely((s->mip & s->mie) != 0)) {\n        if (raise_interrupt(s)) {\n            s->n_cycles--; \n            goto done_interp;\n        }\n    }\n\n    s->pending_exception = -1;\n    /* Note: we assume NULL is represented as a zero number */\n    code_ptr = NULL;\n    code_end = NULL;\n    code_to_pc_addend = s->pc;\n\n    if (s->simcpu->simulation)\n    {\n        /* Prepare the simulation context */\n        s->code_ptr = code_ptr;\n        s->code_end = code_end;\n        s->code_to_pc_addend = code_to_pc_addend;\n\n        /* Switch to simulation */\n        sim_exit_status = riscv_sim_cpu_switch_to_cpu_simulation(s->simcpu);\n\n        /* Exit from simulation due to an exception */\n        code_ptr = NULL;\n        code_end = NULL;\n\n        /* Set PC to the instruction which caused exception */\n        code_to_pc_addend = s->simcpu->exception->pc;\n        // s->pc = s->sim_epc;\n\n        /* Process exception and replay the instruction in the emulator (only\n         * the complex opcodes, illegal opcodes and timer) */\n        switch (sim_exit_status)\n        {\n            case SIM_ILLEGAL_OPCODE_EXCEPTION:\n            {\n                /* Illegal opcode */\n                if (s->simcpu->params->do_sim_trace)\n                {\n                    sim_trace_exception(s->simcpu->trace, s->simcpu->clock,\n                                        s->priv, s->simcpu->exception);\n                }\n                goto illegal_insn;\n                break;\n            }\n\n            case SIM_COMPLEX_OPCODE_EXCEPTION:\n            {\n                /* Includes SYSTEM opcode instructions (eg, ecall,ebreak) which\n                 * we simulate.in a single cycle  */\n                s->simcpu->return_to_sim = TRUE;\n                ++s->simcpu->icount;\n                ++s->simcpu->stats[s->priv].ins_simulated;\n\n                /* For counting system opcode instructions, because stats for\n                 * instruction types are updated in commit stage and we don't\n                 * allow system instruction to commit in pipeline, we commit\n                 * them here */\n                ++s->simcpu->stats[s->priv].ins_emulated;\n\n                /* Add the latency for system instructions */\n                s->simcpu->clock += s->simcpu->params->system_insn_latency;\n                s->simcpu->stats[s->simcpu->emu_cpu_state->priv].cycles += s->simcpu->params->system_insn_latency;\n\n                if (s->simcpu->params->do_sim_trace)\n                {\n                    sim_trace_exception(s->simcpu->trace, s->simcpu->clock,\n                                        s->priv, s->simcpu->exception);\n                }\n                break;\n            }\n\n            case SIM_TEMU_TIMEOUT_EXCEPTION:\n            {\n                /* We executed all the n_cycles instructions for this interval,\n                 * and now we must exit to virt_machine_run() to receive\n                 * interrupts. */\n                sim_assert((s->n_cycles == 0),\n                           \"error: %s at line %d in %s(): %s\", __FILE__,\n                           __LINE__, __func__, \"sim timeout exception \"\n                                               \"generated even though timeout \"\n                                               \"interval not completed\");\n\n                if (s->simcpu->params->do_sim_trace)\n                {\n                    sim_trace_exception(s->simcpu->trace, s->simcpu->clock,\n                                        s->priv, s->simcpu->exception);\n                }\n                break;\n            }\n\n            case SIM_MMU_EXCEPTION:\n            {\n                if (s->simcpu->params->do_sim_trace)\n                {\n                    sim_trace_exception(s->simcpu->trace, s->simcpu->clock,\n                                        s->priv, s->simcpu->exception);\n                }\n                /* Directly go to mmu_exception as TLB lookup is finished on\n                 * simulation side and the relevant exception cause (page fault,\n                 * invalid access) has already been set */\n                goto mmu_exception;\n                break;\n            }\n\n            case SIM_ICOUNT_COMPLETE_EXCEPTION:\n            {\n                /* Simulated user specified sim_emulate_after_icount instructions,\n                 * now switch to emulation mode */\n                riscv_sim_cpu_stop(s->simcpu, s->pc);\n                break;\n            }\n\n            default:\n                fprintf(stderr, \"%s\\n\", \"Invalid exception cause\");\n                exit(1);\n        }\n    }\n\n    /* we use a single execution loop to keep a simple control flow\n       for emscripten */\n    for(;;) {\n        if (unlikely(code_ptr >= code_end)) {\n            uint32_t tlb_idx;\n            uint16_t insn_high;\n            target_ulong addr;\n            uint8_t *ptr;\n            \n            s->pc = GET_PC();\n            /* we test n_cycles only between blocks so that timer\n               interrupts only happen between the blocks. It is\n               important to reduce the translated code size. */\n            if (unlikely(s->n_cycles <= 0))\n                goto the_end;\n\n            /* check pending interrupts */\n            if (unlikely((s->mip & s->mie) != 0)) {\n                if (raise_interrupt(s)) {\n                    s->n_cycles--; \n                    goto the_end;\n                }\n            }\n    \n            addr = s->pc;\n            tlb_idx = (addr >> PG_SHIFT) & (TLB_SIZE - 1);\n            if (likely(s->tlb_code[tlb_idx].vaddr == (addr & ~PG_MASK))) {\n                /* TLB match */ \n                ptr = (uint8_t *)(s->tlb_code[tlb_idx].mem_addend +\n                                  (uintptr_t)addr);\n            } else {\n                if (unlikely(target_read_insn_slow(s, &ptr, addr)))\n                    goto mmu_exception;\n            }\n            code_ptr = ptr;\n            code_end = ptr + (PG_MASK - 1 - (addr & PG_MASK));\n            code_to_pc_addend = addr - (uintptr_t)code_ptr;\n            if (unlikely(code_ptr >= code_end)) {\n                /* instruction is potentially half way between two\n                   pages ? */\n                insn = *(uint16_t *)code_ptr;\n                if ((insn & 3) == 3) {\n                    /* instruction is half way between two pages */\n                    if (unlikely(target_read_insn_u16(s, &insn_high, addr + 2)))\n                        goto mmu_exception;\n                    insn |= insn_high << 16;\n                }\n            } else {\n                insn = get_insn32(code_ptr);\n            }\n        } else {\n            /* fast path */\n            insn = get_insn32(code_ptr);\n        }\n        s->n_cycles--;\n#if 0\n        if (1) {\n#ifdef CONFIG_LOGFILE\n            log_printf(\"pc=0x\"); fprint_target_ulong(log_file, GET_PC()); log_printf(\" insn=%08x\\n\", insn);\n            fflush(log_file);\n#else\n            printf(\"pc=0x\"); print_target_ulong(GET_PC()); printf(\" insn=%08x\\n\", insn);\n            //            dump_regs(s);\n#endif\n        }\n#endif\n        opcode = insn & 0x7f;\n        rd = (insn >> 7) & 0x1f;\n        rs1 = (insn >> 15) & 0x1f;\n        rs2 = (insn >> 20) & 0x1f;\n        switch(opcode) {\n#ifdef CONFIG_EXT_C\n        C_QUADRANT(0)\n            funct3 = (insn >> 13) & 7;\n            rd = ((insn >> 2) & 7) | 8;\n            switch(funct3) {\n            case 0: /* c.addi4spn */\n                imm = get_field1(insn, 11, 4, 5) |\n                    get_field1(insn, 7, 6, 9) |\n                    get_field1(insn, 6, 2, 2) |\n                    get_field1(insn, 5, 3, 3);\n                if (imm == 0)\n                    goto illegal_insn;\n                s->reg[rd] = (intx_t)(s->reg[2] + imm);\n                break;\n#if XLEN >= 128\n            case 1: /* c.lq */\n                imm = get_field1(insn, 11, 4, 5) |\n                    get_field1(insn, 10, 8, 8) |\n                    get_field1(insn, 5, 6, 7);\n                rs1 = ((insn >> 7) & 7) | 8;\n                addr = (intx_t)(s->reg[rs1] + imm);\n                if (target_read_u128(s, &val, addr))\n                    goto mmu_exception;\n                s->reg[rd] = val;\n                break;\n#elif FLEN >= 64\n            case 1: /* c.fld */\n                {\n                    uint64_t rval;\n                    if (s->fs == 0)\n                        goto illegal_insn;\n                    imm = get_field1(insn, 10, 3, 5) |\n                        get_field1(insn, 5, 6, 7);\n                    rs1 = ((insn >> 7) & 7) | 8;\n                    addr = (intx_t)(s->reg[rs1] + imm);\n                    if (target_read_u64(s, &rval, addr))\n                        goto mmu_exception;\n                    s->fp_reg[rd] = rval | F64_HIGH;\n                    s->fs = 3;\n                }\n                break;\n#endif\n            case 2: /* c.lw */\n                {\n                    uint32_t rval;\n                    imm = get_field1(insn, 10, 3, 5) |\n                        get_field1(insn, 6, 2, 2) |\n                        get_field1(insn, 5, 6, 6);\n                    rs1 = ((insn >> 7) & 7) | 8;\n                    addr = (intx_t)(s->reg[rs1] + imm);\n                    if (target_read_u32(s, &rval, addr))\n                        goto mmu_exception;\n                    s->reg[rd] = (int32_t)rval;\n                }\n                break;\n#if XLEN >= 64\n            case 3: /* c.ld */\n                {\n                    uint64_t rval;\n                    imm = get_field1(insn, 10, 3, 5) |\n                        get_field1(insn, 5, 6, 7);\n                    rs1 = ((insn >> 7) & 7) | 8;\n                    addr = (intx_t)(s->reg[rs1] + imm);\n                    if (target_read_u64(s, &rval, addr))\n                        goto mmu_exception;\n                    s->reg[rd] = (int64_t)rval;\n                }\n                break;\n#elif FLEN >= 32\n            case 3: /* c.flw */\n                {\n                    uint32_t rval;\n                    if (s->fs == 0)\n                        goto illegal_insn;\n                    imm = get_field1(insn, 10, 3, 5) |\n                        get_field1(insn, 6, 2, 2) |\n                        get_field1(insn, 5, 6, 6);\n                    rs1 = ((insn >> 7) & 7) | 8;\n                    addr = (intx_t)(s->reg[rs1] + imm);\n                    if (target_read_u32(s, &rval, addr))\n                        goto mmu_exception;\n                    s->fp_reg[rd] = rval | F32_HIGH;\n                    s->fs = 3;\n                }\n                break;\n#endif\n#if XLEN >= 128\n            case 5: /* c.sq */\n                imm = get_field1(insn, 11, 4, 5) |\n                    get_field1(insn, 10, 8, 8) |\n                    get_field1(insn, 5, 6, 7);\n                rs1 = ((insn >> 7) & 7) | 8;\n                addr = (intx_t)(s->reg[rs1] + imm);\n                val = s->reg[rd];\n                if (target_write_u128(s, addr, val))\n                    goto mmu_exception;\n                break;\n#elif FLEN >= 64\n            case 5: /* c.fsd */\n                if (s->fs == 0)\n                    goto illegal_insn;\n                imm = get_field1(insn, 10, 3, 5) |\n                    get_field1(insn, 5, 6, 7);\n                rs1 = ((insn >> 7) & 7) | 8;\n                addr = (intx_t)(s->reg[rs1] + imm);\n                if (target_write_u64(s, addr, s->fp_reg[rd]))\n                    goto mmu_exception;\n                break;\n#endif\n            case 6: /* c.sw */\n                imm = get_field1(insn, 10, 3, 5) |\n                    get_field1(insn, 6, 2, 2) |\n                    get_field1(insn, 5, 6, 6);\n                rs1 = ((insn >> 7) & 7) | 8;\n                addr = (intx_t)(s->reg[rs1] + imm);\n                val = s->reg[rd];\n                if (target_write_u32(s, addr, val))\n                    goto mmu_exception;\n                break;\n#if XLEN >= 64\n            case 7: /* c.sd */\n                imm = get_field1(insn, 10, 3, 5) |\n                    get_field1(insn, 5, 6, 7);\n                rs1 = ((insn >> 7) & 7) | 8;\n                addr = (intx_t)(s->reg[rs1] + imm);\n                val = s->reg[rd];\n                if (target_write_u64(s, addr, val))\n                    goto mmu_exception;\n                break;\n#elif FLEN >= 32\n            case 7: /* c.fsw */\n                if (s->fs == 0)\n                    goto illegal_insn;\n                imm = get_field1(insn, 10, 3, 5) |\n                    get_field1(insn, 6, 2, 2) |\n                    get_field1(insn, 5, 6, 6);\n                rs1 = ((insn >> 7) & 7) | 8;\n                addr = (intx_t)(s->reg[rs1] + imm);\n                if (target_write_u32(s, addr, s->fp_reg[rd]))\n                    goto mmu_exception;\n                break;\n#endif\n            default:\n                goto illegal_insn;\n            }\n            C_NEXT_INSN;\n        C_QUADRANT(1)\n            funct3 = (insn >> 13) & 7;\n            switch(funct3) {\n            case 0: /* c.addi/c.nop */\n                if (rd != 0) {\n                    imm = sext(get_field1(insn, 12, 5, 5) |\n                               get_field1(insn, 2, 0, 4), 6);\n                    s->reg[rd] = (intx_t)(s->reg[rd] + imm);\n                }\n                break;\n#if XLEN == 32\n            case 1: /* c.jal */\n                imm = sext(get_field1(insn, 12, 11, 11) | \n                           get_field1(insn, 11, 4, 4) |\n                           get_field1(insn, 9, 8, 9) |\n                           get_field1(insn, 8, 10, 10) |\n                           get_field1(insn, 7, 6, 6) |\n                           get_field1(insn, 6, 7, 7) |\n                           get_field1(insn, 3, 1, 3) |\n                           get_field1(insn, 2, 5, 5), 12);\n                s->reg[1] = GET_PC() + 2;\n                s->pc = (intx_t)(GET_PC() + imm);\n                JUMP_INSN;\n#else\n            case 1: /* c.addiw */\n                if (rd != 0) {\n                    imm = sext(get_field1(insn, 12, 5, 5) |\n                               get_field1(insn, 2, 0, 4), 6);\n                    s->reg[rd] = (int32_t)(s->reg[rd] + imm);\n                }\n                break;\n#endif\n            case 2: /* c.li */\n                if (rd != 0) {\n                    imm = sext(get_field1(insn, 12, 5, 5) |\n                               get_field1(insn, 2, 0, 4), 6);\n                    s->reg[rd] = imm;\n                }\n                break;\n            case 3:\n                if (rd == 2) {\n                    /* c.addi16sp */\n                    imm = sext(get_field1(insn, 12, 9, 9) |\n                               get_field1(insn, 6, 4, 4) |\n                               get_field1(insn, 5, 6, 6) |\n                               get_field1(insn, 3, 7, 8) |\n                               get_field1(insn, 2, 5, 5), 10);\n                    if (imm == 0)\n                        goto illegal_insn;\n                    s->reg[2] = (intx_t)(s->reg[2] + imm);\n                } else if (rd != 0) {\n                    /* c.lui */\n                    imm = sext(get_field1(insn, 12, 17, 17) |\n                               get_field1(insn, 2, 12, 16), 18);\n                    s->reg[rd] = imm;\n                }\n                break;\n            case 4: \n                funct3 = (insn >> 10) & 3;\n                rd = ((insn >> 7) & 7) | 8;\n                switch(funct3) {\n                case 0: /* c.srli */ \n                case 1: /* c.srai */ \n                    imm = get_field1(insn, 12, 5, 5) |\n                        get_field1(insn, 2, 0, 4);\n#if XLEN == 32\n                    if (imm & 0x20)\n                        goto illegal_insn;\n#elif XLEN == 128\n                    if (imm == 0)\n                        imm = 64;\n                    else if (imm >= 32)\n                        imm = 128 - imm;\n#endif\n                    if (funct3 == 0)\n                        s->reg[rd] = (intx_t)((uintx_t)s->reg[rd] >> imm);\n                    else\n                        s->reg[rd] = (intx_t)s->reg[rd] >> imm;\n                    \n                    break;\n                case 2: /* c.andi */\n                    imm = sext(get_field1(insn, 12, 5, 5) |\n                               get_field1(insn, 2, 0, 4), 6);\n                    s->reg[rd] &= imm;\n                    break;\n                case 3: \n                    rs2 = ((insn >> 2) & 7) | 8;\n                    funct3 = ((insn >> 5) & 3) | ((insn >> (12 - 2)) & 4);\n                    switch(funct3) {\n                    case 0: /* c.sub */\n                        s->reg[rd] = (intx_t)(s->reg[rd] - s->reg[rs2]);\n                        break;\n                    case 1: /* c.xor */\n                        s->reg[rd] = s->reg[rd] ^ s->reg[rs2];\n                        break;\n                    case 2: /* c.or */\n                        s->reg[rd] = s->reg[rd] | s->reg[rs2];\n                        break;\n                    case 3: /* c.and */\n                        s->reg[rd] = s->reg[rd] & s->reg[rs2];\n                        break;\n#if XLEN >= 64\n                    case 4: /* c.subw */\n                        s->reg[rd] = (int32_t)(s->reg[rd] - s->reg[rs2]);\n                        break;\n                    case 5: /* c.addw */\n                        s->reg[rd] = (int32_t)(s->reg[rd] + s->reg[rs2]);\n                        break;\n#endif\n                    default:\n                        goto illegal_insn;\n                    }\n                    break;\n                }\n                break;\n            case 5: /* c.j */\n                imm = sext(get_field1(insn, 12, 11, 11) | \n                           get_field1(insn, 11, 4, 4) |\n                           get_field1(insn, 9, 8, 9) |\n                           get_field1(insn, 8, 10, 10) |\n                           get_field1(insn, 7, 6, 6) |\n                           get_field1(insn, 6, 7, 7) |\n                           get_field1(insn, 3, 1, 3) |\n                           get_field1(insn, 2, 5, 5), 12);\n                s->pc = (intx_t)(GET_PC() + imm);\n                JUMP_INSN;\n            case 6: /* c.beqz */\n                rs1 = ((insn >> 7) & 7) | 8;\n                imm = sext(get_field1(insn, 12, 8, 8) | \n                           get_field1(insn, 10, 3, 4) |\n                           get_field1(insn, 5, 6, 7) |\n                           get_field1(insn, 3, 1, 2) |\n                           get_field1(insn, 2, 5, 5), 9);\n                if (s->reg[rs1] == 0) {\n                    s->pc = (intx_t)(GET_PC() + imm);\n                    JUMP_INSN;\n                }\n                break;\n            case 7: /* c.bnez */\n                rs1 = ((insn >> 7) & 7) | 8;\n                imm = sext(get_field1(insn, 12, 8, 8) | \n                           get_field1(insn, 10, 3, 4) |\n                           get_field1(insn, 5, 6, 7) |\n                           get_field1(insn, 3, 1, 2) |\n                           get_field1(insn, 2, 5, 5), 9);\n                if (s->reg[rs1] != 0) {\n                    s->pc = (intx_t)(GET_PC() + imm);\n                    JUMP_INSN;\n                }\n                break;\n            default:\n                goto illegal_insn;\n            }\n            C_NEXT_INSN;\n        C_QUADRANT(2)\n            funct3 = (insn >> 13) & 7;\n            rs2 = (insn >> 2) & 0x1f;\n            switch(funct3) {\n            case 0: /* c.slli */\n                imm = get_field1(insn, 12, 5, 5) | rs2;\n#if XLEN == 32\n                if (imm & 0x20)\n                    goto illegal_insn;\n#elif XLEN == 128\n                if (imm == 0)\n                    imm = 64;\n#endif\n                if (rd != 0)\n                    s->reg[rd] = (intx_t)(s->reg[rd] << imm);\n                break;\n#if XLEN == 128\n            case 1: /* c.lqsp */\n                imm = get_field1(insn, 12, 5, 5) |\n                    (rs2 & (1 << 4)) |\n                    get_field1(insn, 2, 6, 9);\n                addr = (intx_t)(s->reg[2] + imm);\n                if (target_read_u128(s, &val, addr))\n                    goto mmu_exception;\n                if (rd != 0)\n                    s->reg[rd] = val;\n                break;\n#elif FLEN >= 64\n            case 1: /* c.fldsp */\n                {\n                    uint64_t rval;\n                    if (s->fs == 0)\n                        goto illegal_insn;\n                    imm = get_field1(insn, 12, 5, 5) |\n                        (rs2 & (3 << 3)) |\n                        get_field1(insn, 2, 6, 8);\n                    addr = (intx_t)(s->reg[2] + imm);\n                    if (target_read_u64(s, &rval, addr))\n                        goto mmu_exception;\n                    s->fp_reg[rd] = rval | F64_HIGH;\n                    s->fs = 3;\n                }\n                break;\n#endif\n            case 2: /* c.lwsp */\n                {\n                    uint32_t rval;\n                    imm = get_field1(insn, 12, 5, 5) |\n                        (rs2 & (7 << 2)) |\n                        get_field1(insn, 2, 6, 7);\n                    addr = (intx_t)(s->reg[2] + imm);\n                    if (target_read_u32(s, &rval, addr))\n                        goto mmu_exception;\n                    if (rd != 0)\n                        s->reg[rd] = (int32_t)rval;\n                }\n                break;\n#if XLEN >= 64\n            case 3: /* c.ldsp */\n                {\n                    uint64_t rval;\n                    imm = get_field1(insn, 12, 5, 5) |\n                        (rs2 & (3 << 3)) |\n                        get_field1(insn, 2, 6, 8);\n                    addr = (intx_t)(s->reg[2] + imm);\n                    if (target_read_u64(s, &rval, addr))\n                        goto mmu_exception;\n                    if (rd != 0)\n                        s->reg[rd] = (int64_t)rval;\n                }\n                break;\n#elif FLEN >= 32\n            case 3: /* c.flwsp */\n                {\n                    uint32_t rval;\n                    if (s->fs == 0)\n                        goto illegal_insn;\n                    imm = get_field1(insn, 12, 5, 5) |\n                        (rs2 & (7 << 2)) |\n                        get_field1(insn, 2, 6, 7);\n                    addr = (intx_t)(s->reg[2] + imm);\n                    if (target_read_u32(s, &rval, addr))\n                        goto mmu_exception;\n                    s->fp_reg[rd] = rval | F32_HIGH;\n                    s->fs = 3;\n                }\n                break;\n#endif\n            case 4:\n                if (((insn >> 12) & 1) == 0) {\n                    if (rs2 == 0) {\n                        /* c.jr */\n                        if (rd == 0)\n                            goto illegal_insn;\n                        s->pc = s->reg[rd] & ~1;\n                        JUMP_INSN;\n                    } else {\n                        /* c.mv */\n                        if (rd != 0)\n                            s->reg[rd] = s->reg[rs2];\n                    }\n                } else {\n                    if (rs2 == 0) {\n                        if (rd == 0) {\n                            /* c.ebreak */\n                            s->pending_exception = CAUSE_BREAKPOINT;\n                            goto exception;\n                        } else {\n                            /* c.jalr */\n                            val = GET_PC() + 2;\n                            s->pc = s->reg[rd] & ~1;\n                            s->reg[1] = val;\n                            JUMP_INSN;\n                        }\n                    } else {\n                        if (rd != 0) {\n                            s->reg[rd] = (intx_t)(s->reg[rd] + s->reg[rs2]);\n                        }\n                    }\n                }\n                break;\n#if XLEN == 128\n            case 5: /* c.sqsp */\n                imm = get_field1(insn, 10, 3, 5) |\n                    get_field1(insn, 7, 6, 8);\n                addr = (intx_t)(s->reg[2] + imm);\n                if (target_write_u128(s, addr, s->reg[rs2]))\n                    goto mmu_exception;\n                break;\n#elif FLEN >= 64\n            case 5: /* c.fsdsp */\n                if (s->fs == 0)\n                    goto illegal_insn;\n                imm = get_field1(insn, 10, 3, 5) |\n                    get_field1(insn, 7, 6, 8);\n                addr = (intx_t)(s->reg[2] + imm);\n                if (target_write_u64(s, addr, s->fp_reg[rs2]))\n                    goto mmu_exception;\n                break;\n#endif \n            case 6: /* c.swsp */\n                imm = get_field1(insn, 9, 2, 5) |\n                    get_field1(insn, 7, 6, 7);\n                addr = (intx_t)(s->reg[2] + imm);\n                if (target_write_u32(s, addr, s->reg[rs2]))\n                    goto mmu_exception;\n                break;\n#if XLEN >= 64\n            case 7: /* c.sdsp */\n                imm = get_field1(insn, 10, 3, 5) |\n                    get_field1(insn, 7, 6, 8);\n                addr = (intx_t)(s->reg[2] + imm);\n                if (target_write_u64(s, addr, s->reg[rs2]))\n                    goto mmu_exception;\n                break;\n#elif FLEN >= 32\n            case 7: /* c.swsp */\n                if (s->fs == 0)\n                    goto illegal_insn;\n                imm = get_field1(insn, 9, 2, 5) |\n                    get_field1(insn, 7, 6, 7);\n                addr = (intx_t)(s->reg[2] + imm);\n                if (target_write_u32(s, addr, s->fp_reg[rs2]))\n                    goto mmu_exception;\n                break;\n#endif\n            default:\n                goto illegal_insn;\n            }\n            C_NEXT_INSN;\n#endif /* CONFIG_EXT_C */\n\n        case 0x37: /* lui */\n            if (rd != 0)\n                s->reg[rd] = (int32_t)(insn & 0xfffff000);\n            NEXT_INSN;\n        case 0x17: /* auipc */\n            if (rd != 0)\n                s->reg[rd] = (intx_t)(GET_PC() + (int32_t)(insn & 0xfffff000));\n            NEXT_INSN;\n        case 0x6f: /* jal */\n            imm = ((insn >> (31 - 20)) & (1 << 20)) |\n                ((insn >> (21 - 1)) & 0x7fe) |\n                ((insn >> (20 - 11)) & (1 << 11)) |\n                (insn & 0xff000);\n            imm = (imm << 11) >> 11;\n            if (rd != 0)\n                s->reg[rd] = GET_PC() + 4;\n            s->pc = (intx_t)(GET_PC() + imm);\n            JUMP_INSN;\n        case 0x67: /* jalr */\n            imm = (int32_t)insn >> 20;\n            val = GET_PC() + 4;\n            s->pc = (intx_t)(s->reg[rs1] + imm) & ~1;\n            if (rd != 0)\n                s->reg[rd] = val;\n            JUMP_INSN;\n        case 0x63:\n            funct3 = (insn >> 12) & 7;\n            switch(funct3 >> 1) {\n            case 0: /* beq/bne */\n                cond = (s->reg[rs1] == s->reg[rs2]);\n                break;\n            case 2: /* blt/bge */\n                cond = ((target_long)s->reg[rs1] < (target_long)s->reg[rs2]);\n                break;\n            case 3: /* bltu/bgeu */\n                cond = (s->reg[rs1] < s->reg[rs2]);\n                break;\n            default:\n                goto illegal_insn;\n            }\n            cond ^= (funct3 & 1);\n            if (cond) {\n                imm = ((insn >> (31 - 12)) & (1 << 12)) |\n                    ((insn >> (25 - 5)) & 0x7e0) |\n                    ((insn >> (8 - 1)) & 0x1e) |\n                    ((insn << (11 - 7)) & (1 << 11));\n                imm = (imm << 19) >> 19;\n                s->pc = (intx_t)(GET_PC() + imm);\n                JUMP_INSN;\n            }\n            NEXT_INSN;\n        case 0x03: /* load */\n            funct3 = (insn >> 12) & 7;\n            imm = (int32_t)insn >> 20;\n            addr = s->reg[rs1] + imm;\n            switch(funct3) {\n            case 0: /* lb */\n                {\n                    uint8_t rval;\n                    if (target_read_u8(s, &rval, addr))\n                        goto mmu_exception;\n                    val = (int8_t)rval;\n                }\n                break;\n            case 1: /* lh */\n                {\n                    uint16_t rval;\n                    if (target_read_u16(s, &rval, addr))\n                        goto mmu_exception;\n                    val = (int16_t)rval;\n                }\n                break;\n            case 2: /* lw */\n                {\n                    uint32_t rval;\n                    if (target_read_u32(s, &rval, addr))\n                        goto mmu_exception;\n                    val = (int32_t)rval;\n                }\n                break;\n            case 4: /* lbu */\n                {\n                    uint8_t rval;\n                    if (target_read_u8(s, &rval, addr))\n                        goto mmu_exception;\n                    val = rval;\n                }\n                break;\n            case 5: /* lhu */\n                {\n                    uint16_t rval;\n                    if (target_read_u16(s, &rval, addr))\n                        goto mmu_exception;\n                    val = rval;\n                }\n                break;\n#if XLEN >= 64\n            case 3: /* ld */\n                {\n                    uint64_t rval;\n                    if (target_read_u64(s, &rval, addr))\n                        goto mmu_exception;\n                    val = (int64_t)rval;\n                }\n                break;\n            case 6: /* lwu */\n                {\n                    uint32_t rval;\n                    if (target_read_u32(s, &rval, addr))\n                        goto mmu_exception;\n                    val = rval;\n                }\n                break;\n#endif\n#if XLEN >= 128\n            case 7: /* ldu */\n                {\n                    uint64_t rval;\n                    if (target_read_u64(s, &rval, addr))\n                        goto mmu_exception;\n                    val = rval;\n                }\n                break;\n#endif\n            default:\n                goto illegal_insn;\n            }\n            if (rd != 0)\n                s->reg[rd] = val;\n            NEXT_INSN;\n        case 0x23: /* store */\n            funct3 = (insn >> 12) & 7;\n            imm = rd | ((insn >> (25 - 5)) & 0xfe0);\n            imm = (imm << 20) >> 20;\n            addr = s->reg[rs1] + imm;\n            val = s->reg[rs2];\n            switch(funct3) {\n            case 0: /* sb */\n                if (target_write_u8(s, addr, val))\n                    goto mmu_exception;\n                break;\n            case 1: /* sh */\n                if (target_write_u16(s, addr, val))\n                    goto mmu_exception;\n                break;\n            case 2: /* sw */\n                if (target_write_u32(s, addr, val))\n                    goto mmu_exception;\n                break;\n#if XLEN >= 64\n            case 3: /* sd */\n                if (target_write_u64(s, addr, val))\n                    goto mmu_exception;\n                break;\n#endif\n#if XLEN >= 128\n            case 4: /* sq */\n                if (target_write_u128(s, addr, val))\n                    goto mmu_exception;\n                break;\n#endif\n            default:\n                goto illegal_insn;\n            }\n            NEXT_INSN;\n        case 0x13:\n            funct3 = (insn >> 12) & 7;\n            imm = (int32_t)insn >> 20;\n            switch(funct3) {\n            case 0: /* addi */\n                val = (intx_t)(s->reg[rs1] + imm);\n                break;\n            case 1: /* slli */\n                if ((imm & ~(XLEN - 1)) != 0)\n                    goto illegal_insn;\n                val = (intx_t)(s->reg[rs1] << (imm & (XLEN - 1)));\n                break;\n            case 2: /* slti */\n                val = (target_long)s->reg[rs1] < (target_long)imm;\n                break;\n            case 3: /* sltiu */\n                val = s->reg[rs1] < (target_ulong)imm;\n                break;\n            case 4: /* xori */\n                val = s->reg[rs1] ^ imm;\n                break;\n            case 5: /* srli/srai */\n                if ((imm & ~((XLEN - 1) | 0x400)) != 0)\n                    goto illegal_insn;\n                if (imm & 0x400)\n                    val = (intx_t)s->reg[rs1] >> (imm & (XLEN - 1));\n                else\n                    val = (intx_t)((uintx_t)s->reg[rs1] >> (imm & (XLEN - 1)));\n                break;\n            case 6: /* ori */\n                val = s->reg[rs1] | imm;\n                break;\n            default:\n            case 7: /* andi */\n                val = s->reg[rs1] & imm;\n                break;\n            }\n            if (rd != 0)\n                s->reg[rd] = val;\n            NEXT_INSN;\n#if XLEN >= 64\n        case 0x1b:/* OP-IMM-32 */\n            funct3 = (insn >> 12) & 7;\n            imm = (int32_t)insn >> 20;\n            val = s->reg[rs1];\n            switch(funct3) {\n            case 0: /* addiw */\n                val = (int32_t)(val + imm);\n                break;\n            case 1: /* slliw */\n                if ((imm & ~31) != 0)\n                    goto illegal_insn;\n                val = (int32_t)(val << (imm & 31));\n                break;\n            case 5: /* srliw/sraiw */\n                if ((imm & ~(31 | 0x400)) != 0)\n                    goto illegal_insn;\n                if (imm & 0x400)\n                    val = (int32_t)val >> (imm & 31);\n                else\n                    val = (int32_t)((uint32_t)val >> (imm & 31));\n                break;\n            default:\n                goto illegal_insn;\n            }\n            if (rd != 0)\n                s->reg[rd] = val;\n            NEXT_INSN;\n#endif\n#if XLEN >= 128\n        case 0x5b: /* OP-IMM-64 */\n            funct3 = (insn >> 12) & 7;\n            imm = (int32_t)insn >> 20;\n            val = s->reg[rs1];\n            switch(funct3) {\n            case 0: /* addid */\n                val = (int64_t)(val + imm);\n                break;\n            case 1: /* sllid */\n                if ((imm & ~63) != 0)\n                    goto illegal_insn;\n                val = (int64_t)(val << (imm & 63));\n                break;\n            case 5: /* srlid/sraid */\n                if ((imm & ~(63 | 0x400)) != 0)\n                    goto illegal_insn;\n                if (imm & 0x400)\n                    val = (int64_t)val >> (imm & 63);\n                else\n                    val = (int64_t)((uint64_t)val >> (imm & 63));\n                break;\n            default:\n                goto illegal_insn;\n            }\n            if (rd != 0)\n                s->reg[rd] = val;\n            NEXT_INSN;\n#endif\n        case 0x33:\n            imm = insn >> 25;\n            val = s->reg[rs1];\n            val2 = s->reg[rs2];\n            if (imm == 1) {\n                funct3 = (insn >> 12) & 7;\n                switch(funct3) {\n                case 0: /* mul */\n                    val = (intx_t)((intx_t)val * (intx_t)val2);\n                    break;\n                case 1: /* mulh */\n                    val = (intx_t)glue(mulh, XLEN)(val, val2);\n                    break;\n                case 2:/* mulhsu */\n                    val = (intx_t)glue(mulhsu, XLEN)(val, val2);\n                    break;\n                case 3:/* mulhu */\n                    val = (intx_t)glue(mulhu, XLEN)(val, val2);\n                    break;\n                case 4:/* div */\n                    val = glue(div, XLEN)(val, val2);\n                    break;\n                case 5:/* divu */\n                    val = (intx_t)glue(divu, XLEN)(val, val2);\n                    break;\n                case 6:/* rem */\n                    val = glue(rem, XLEN)(val, val2);\n                    break;\n                case 7:/* remu */\n                    val = (intx_t)glue(remu, XLEN)(val, val2);\n                    break;\n                default:\n                    goto illegal_insn;\n                }\n            } else {\n                if (imm & ~0x20)\n                    goto illegal_insn;\n                funct3 = ((insn >> 12) & 7) | ((insn >> (30 - 3)) & (1 << 3));\n                switch(funct3) {\n                case 0: /* add */\n                    val = (intx_t)(val + val2);\n                    break;\n                case 0 | 8: /* sub */\n                    val = (intx_t)(val - val2);\n                    break;\n                case 1: /* sll */\n                    val = (intx_t)(val << (val2 & (XLEN - 1)));\n                    break;\n                case 2: /* slt */\n                    val = (target_long)val < (target_long)val2;\n                    break;\n                case 3: /* sltu */\n                    val = val < val2;\n                    break;\n                case 4: /* xor */\n                    val = val ^ val2;\n                    break;\n                case 5: /* srl */\n                    val = (intx_t)((uintx_t)val >> (val2 & (XLEN - 1)));\n                    break;\n                case 5 | 8: /* sra */\n                    val = (intx_t)val >> (val2 & (XLEN - 1));\n                    break;\n                case 6: /* or */\n                    val = val | val2;\n                    break;\n                case 7: /* and */\n                    val = val & val2;\n                    break;\n                default:\n                    goto illegal_insn;\n                }\n            }\n            if (rd != 0)\n                s->reg[rd] = val;\n            NEXT_INSN;\n#if XLEN >= 64\n        case 0x3b: /* OP-32 */\n            imm = insn >> 25;\n            val = s->reg[rs1];\n            val2 = s->reg[rs2];\n            if (imm == 1) {\n                funct3 = (insn >> 12) & 7;\n                switch(funct3) {\n                case 0: /* mulw */\n                    val = (int32_t)((int32_t)val * (int32_t)val2);\n                    break;\n                case 4:/* divw */\n                    val = div32(val, val2);\n                    break;\n                case 5:/* divuw */\n                    val = (int32_t)divu32(val, val2);\n                    break;\n                case 6:/* remw */\n                    val = rem32(val, val2);\n                    break;\n                case 7:/* remuw */\n                    val = (int32_t)remu32(val, val2);\n                    break;\n                default:\n                    goto illegal_insn;\n                }\n            } else {\n                if (imm & ~0x20)\n                    goto illegal_insn;\n                funct3 = ((insn >> 12) & 7) | ((insn >> (30 - 3)) & (1 << 3));\n                switch(funct3) {\n                case 0: /* addw */\n                    val = (int32_t)(val + val2);\n                    break;\n                case 0 | 8: /* subw */\n                    val = (int32_t)(val - val2);\n                    break;\n                case 1: /* sllw */\n                    val = (int32_t)((uint32_t)val << (val2 & 31));\n                    break;\n                case 5: /* srlw */\n                    val = (int32_t)((uint32_t)val >> (val2 & 31));\n                    break;\n                case 5 | 8: /* sraw */\n                    val = (int32_t)val >> (val2 & 31);\n                    break;\n                default:\n                    goto illegal_insn;\n                }\n            }\n            if (rd != 0)\n                s->reg[rd] = val;\n            NEXT_INSN;\n#endif\n#if XLEN >= 128\n        case 0x7b: /* OP-64 */\n            imm = insn >> 25;\n            val = s->reg[rs1];\n            val2 = s->reg[rs2];\n            if (imm == 1) {\n                funct3 = (insn >> 12) & 7;\n                switch(funct3) {\n                case 0: /* muld */\n                    val = (int64_t)((int64_t)val * (int64_t)val2);\n                    break;\n                case 4:/* divd */\n                    val = div64(val, val2);\n                    break;\n                case 5:/* divud */\n                    val = (int64_t)divu64(val, val2);\n                    break;\n                case 6:/* remd */\n                    val = rem64(val, val2);\n                    break;\n                case 7:/* remud */\n                    val = (int64_t)remu64(val, val2);\n                    break;\n                default:\n                    goto illegal_insn;\n                }\n            } else {\n                if (imm & ~0x20)\n                    goto illegal_insn;\n                funct3 = ((insn >> 12) & 7) | ((insn >> (30 - 3)) & (1 << 3));\n                switch(funct3) {\n                case 0: /* addd */\n                    val = (int64_t)(val + val2);\n                    break;\n                case 0 | 8: /* subd */\n                    val = (int64_t)(val - val2);\n                    break;\n                case 1: /* slld */\n                    val = (int64_t)((uint64_t)val << (val2 & 63));\n                    break;\n                case 5: /* srld */\n                    val = (int64_t)((uint64_t)val >> (val2 & 63));\n                    break;\n                case 5 | 8: /* srad */\n                    val = (int64_t)val >> (val2 & 63);\n                    break;\n                default:\n                    goto illegal_insn;\n                }\n            }\n            if (rd != 0)\n                s->reg[rd] = val;\n            NEXT_INSN;\n#endif\n        case 0x73:\n            funct3 = (insn >> 12) & 7;\n            imm = insn >> 20;\n            if (funct3 & 4)\n                val = rs1;\n            else\n                val = s->reg[rs1];\n            funct3 &= 3;\n            switch(funct3) {\n            case 1: /* csrrw */\n                s->insn_counter = GET_INSN_COUNTER();\n                if (csr_read(s, &val2, imm, TRUE, &run_mode))\n                    goto illegal_insn;\n                val2 = (intx_t)val2;\n                err = csr_write(s, imm, val);\n                if (err < 0)\n                    goto illegal_insn;\n                if (rd != 0)\n                    s->reg[rd] = val2;\n                if (err > 0) {\n                    s->pc = GET_PC() + 4;\n                    if (err == 2)\n                        JUMP_INSN;\n                    else\n                        goto done_interp;\n                }\n                break;\n            case 2: /* csrrs */\n            case 3: /* csrrc */\n                s->insn_counter = GET_INSN_COUNTER();\n                if (csr_read(s, &val2, imm, (rs1 != 0), &run_mode))\n                    goto illegal_insn;\n                val2 = (intx_t)val2;\n                switch (run_mode) {\n                    case MODE_SIM_START: {\n                        riscv_sim_cpu_start(s->simcpu, GET_PC() + 4);\n                        s->pc = GET_PC() + 4;\n                        goto the_end;\n                    }\n                    case MODE_SIM_STOP: {\n                        riscv_sim_cpu_stop(s->simcpu, GET_PC());\n                        s->pc = GET_PC() + 4;\n                        goto the_end;\n                    }\n                    default:\n                        break;\n                }\n                if (rs1 != 0) {\n                    if (funct3 == 2)\n                        val = val2 | val;\n                    else\n                        val = val2 & ~val;\n                    err = csr_write(s, imm, val);\n                    if (err < 0)\n                        goto illegal_insn;\n                } else {\n                    err = 0;\n                }\n                if (rd != 0)\n                    s->reg[rd] = val2;\n                if (err > 0) {\n                    s->pc = GET_PC() + 4;\n                    if (err == 2)\n                        JUMP_INSN;\n                    else\n                        goto done_interp;\n                }\n                break;\n            case 0:\n                switch(imm) {\n                case 0x000: /* ecall */\n                    if (insn & 0x000fff80)\n                        goto illegal_insn;\n                    s->pending_exception = CAUSE_USER_ECALL + s->priv;\n                    goto exception;\n                case 0x001: /* ebreak */\n                    if (insn & 0x000fff80)\n                        goto illegal_insn;\n                    s->pending_exception = CAUSE_BREAKPOINT;\n                    goto exception;\n                case 0x102: /* sret */\n                    {\n                        if (insn & 0x000fff80)\n                            goto illegal_insn;\n                        if (s->priv < PRV_S)\n                            goto illegal_insn;\n                        s->pc = GET_PC();\n                        handle_sret(s);\n                        goto done_interp;\n                    }\n                    break;\n                case 0x302: /* mret */\n                    {\n                        if (insn & 0x000fff80)\n                            goto illegal_insn;\n                        if (s->priv < PRV_M)\n                            goto illegal_insn;\n                        s->pc = GET_PC();\n                        handle_mret(s);\n                        goto done_interp;\n                    }\n                    break;\n                case 0x105: /* wfi */\n                    if (insn & 0x00007f80)\n                        goto illegal_insn;\n                    if (s->priv == PRV_U)\n                        goto illegal_insn;\n                    /* go to power down if no enabled interrupts are\n                       pending */\n                    if ((s->mip & s->mie) == 0) {\n                        s->power_down_flag = TRUE;\n                        s->pc = GET_PC() + 4;\n                        goto done_interp;\n                    }\n                    break;\n                default:\n                    if ((imm >> 5) == 0x09) {\n                        /* sfence.vma */\n                        if (insn & 0x00007f80)\n                            goto illegal_insn;\n                        if (s->priv == PRV_U)\n                            goto illegal_insn;\n                        if (rs1 == 0) {\n                            tlb_flush_all(s);\n                        } else {\n                            tlb_flush_vaddr(s, s->reg[rs1]);\n                        }\n                        /* the current code TLB may have been flushed */\n                        s->pc = GET_PC() + 4;\n                        JUMP_INSN;\n                    } else {\n                        goto illegal_insn;\n                    }\n                    break;\n                }\n                break;\n            default:\n                goto illegal_insn;\n            }\n            NEXT_INSN;\n        case 0x0f: /* misc-mem */\n            funct3 = (insn >> 12) & 7;\n            switch(funct3) {\n            case 0: /* fence */\n                if (insn & 0xf00fff80)\n                    goto illegal_insn;\n                break;\n            case 1: /* fence.i */\n                if (insn != 0x0000100f)\n                    goto illegal_insn;\n                break;\n#if XLEN >= 128\n            case 2: /* lq */\n                imm = (int32_t)insn >> 20;\n                addr = s->reg[rs1] + imm;\n                if (target_read_u128(s, &val, addr))\n                    goto mmu_exception;\n                if (rd != 0)\n                    s->reg[rd] = val;\n                break;\n#endif\n            default:\n                goto illegal_insn;\n            }\n            NEXT_INSN;\n        case 0x2f:\n            funct3 = (insn >> 12) & 7;\n#define OP_A(size)                                                      \\\n            {                                                           \\\n                uint ## size ##_t rval;                                 \\\n                                                                        \\\n                addr = s->reg[rs1];                                     \\\n                funct3 = insn >> 27;                                    \\\n                switch(funct3) {                                        \\\n                case 2: /* lr.w */                                      \\\n                    if (rs2 != 0)                                       \\\n                        goto illegal_insn;                              \\\n                    if (target_read_u ## size(s, &rval, addr))          \\\n                        goto mmu_exception;                             \\\n                    val = (int## size ## _t)rval;                       \\\n                    s->load_res = addr;                                 \\\n                    break;                                              \\\n                case 3: /* sc.w */                                      \\\n                    if (s->load_res == addr) {                          \\\n                        if (target_write_u ## size(s, addr, s->reg[rs2])) \\\n                            goto mmu_exception;                         \\\n                        val = 0;                                        \\\n                    } else {                                            \\\n                        val = 1;                                        \\\n                    }                                                   \\\n                    break;                                              \\\n                case 1: /* amiswap.w */                                 \\\n                case 0: /* amoadd.w */                                  \\\n                case 4: /* amoxor.w */                                  \\\n                case 0xc: /* amoand.w */                                \\\n                case 0x8: /* amoor.w */                                 \\\n                case 0x10: /* amomin.w */                               \\\n                case 0x14: /* amomax.w */                               \\\n                case 0x18: /* amominu.w */                              \\\n                case 0x1c: /* amomaxu.w */                              \\\n                    if (target_read_u ## size(s, &rval, addr))          \\\n                        goto mmu_exception;                             \\\n                    val = (int## size ## _t)rval;                       \\\n                    val2 = s->reg[rs2];                                 \\\n                    switch(funct3) {                                    \\\n                    case 1: /* amiswap.w */                             \\\n                        break;                                          \\\n                    case 0: /* amoadd.w */                              \\\n                        val2 = (int## size ## _t)(val + val2);          \\\n                        break;                                          \\\n                    case 4: /* amoxor.w */                              \\\n                        val2 = (int## size ## _t)(val ^ val2);          \\\n                        break;                                          \\\n                    case 0xc: /* amoand.w */                            \\\n                        val2 = (int## size ## _t)(val & val2);          \\\n                        break;                                          \\\n                    case 0x8: /* amoor.w */                             \\\n                        val2 = (int## size ## _t)(val | val2);          \\\n                        break;                                          \\\n                    case 0x10: /* amomin.w */                           \\\n                        if ((int## size ## _t)val < (int## size ## _t)val2) \\\n                            val2 = (int## size ## _t)val;               \\\n                        break;                                          \\\n                    case 0x14: /* amomax.w */                           \\\n                        if ((int## size ## _t)val > (int## size ## _t)val2) \\\n                            val2 = (int## size ## _t)val;               \\\n                        break;                                          \\\n                    case 0x18: /* amominu.w */                          \\\n                        if ((uint## size ## _t)val < (uint## size ## _t)val2) \\\n                            val2 = (int## size ## _t)val;               \\\n                        break;                                          \\\n                    case 0x1c: /* amomaxu.w */                          \\\n                        if ((uint## size ## _t)val > (uint## size ## _t)val2) \\\n                            val2 = (int## size ## _t)val;               \\\n                        break;                                          \\\n                    default:                                            \\\n                        goto illegal_insn;                              \\\n                    }                                                   \\\n                    if (target_write_u ## size(s, addr, val2))          \\\n                        goto mmu_exception;                             \\\n                    break;                                              \\\n                default:                                                \\\n                    goto illegal_insn;                                  \\\n                }                                                       \\\n            }\n\n            switch(funct3) {\n            case 2:\n                OP_A(32);\n                break;\n#if XLEN >= 64\n            case 3:\n                OP_A(64);\n                break;\n#endif\n#if XLEN >= 128\n            case 4:\n                OP_A(128);\n                break;\n#endif\n            default:\n                goto illegal_insn;\n            }\n            if (rd != 0)\n                s->reg[rd] = val;\n            NEXT_INSN;\n#if FLEN > 0\n            /* FPU */\n        case 0x07: /* fp load */\n            if (s->fs == 0)\n                goto illegal_insn;\n            funct3 = (insn >> 12) & 7;\n            imm = (int32_t)insn >> 20;\n            addr = s->reg[rs1] + imm;\n            switch(funct3) {\n            case 2: /* flw */\n                {\n                    uint32_t rval;\n                    if (target_read_u32(s, &rval, addr))\n                        goto mmu_exception;\n                    s->fp_reg[rd] = rval | F32_HIGH;\n                }\n                break;\n#if FLEN >= 64\n            case 3: /* fld */\n                {\n                    uint64_t rval;\n                    if (target_read_u64(s, &rval, addr))\n                        goto mmu_exception;\n                    s->fp_reg[rd] = rval | F64_HIGH;\n                }\n                break;\n#endif \n#if FLEN >= 128\n            case 4: /* flq */\n                {\n                    uint128_t rval;\n                    if (target_read_u128(s, &rval, addr))\n                        goto mmu_exception;\n                    s->fp_reg[rd] = rval;\n                }\n                break;\n#endif\n            default:\n                goto illegal_insn;\n            }\n            s->fs = 3;\n            NEXT_INSN;\n        case 0x27: /* fp store */\n            if (s->fs == 0)\n                goto illegal_insn;\n            funct3 = (insn >> 12) & 7;\n            imm = rd | ((insn >> (25 - 5)) & 0xfe0);\n            imm = (imm << 20) >> 20;\n            addr = s->reg[rs1] + imm;\n            switch(funct3) {\n            case 2: /* fsw */\n                if (target_write_u32(s, addr, s->fp_reg[rs2]))\n                    goto mmu_exception;\n                break;\n#if FLEN >= 64\n            case 3: /* fsd */\n                if (target_write_u64(s, addr, s->fp_reg[rs2]))\n                    goto mmu_exception;\n                break;\n#endif\n#if FLEN >= 128\n            case 4: /* fsq */\n                if (target_write_u128(s, addr, s->fp_reg[rs2]))\n                    goto mmu_exception;\n                break;\n#endif\n            default:\n                goto illegal_insn;\n            }\n            NEXT_INSN;\n        case 0x43: /* fmadd */\n            if (s->fs == 0)\n                goto illegal_insn;\n            funct3 = (insn >> 25) & 3;\n            rs3 = insn >> 27;\n            rm = get_insn_rm(s, (insn >> 12) & 7);\n            if (rm < 0)\n                goto illegal_insn;\n            switch(funct3) {\n            case 0:\n                s->fp_reg[rd] = fma_sf32(s->fp_reg[rs1], s->fp_reg[rs2],\n                                         s->fp_reg[rs3], rm, &s->fflags) | F32_HIGH;\n                break;\n#if FLEN >= 64\n            case 1:\n                s->fp_reg[rd] = fma_sf64(s->fp_reg[rs1], s->fp_reg[rs2],\n                                         s->fp_reg[rs3], rm, &s->fflags) | F64_HIGH;\n                break;\n#endif\n#if FLEN >= 128\n            case 3:\n                s->fp_reg[rd] = fma_sf128(s->fp_reg[rs1], s->fp_reg[rs2],\n                                          s->fp_reg[rs3], rm, &s->fflags);\n                break;\n#endif\n            default:\n                goto illegal_insn;\n            }\n            s->fs = 3;\n            NEXT_INSN;\n        case 0x47: /* fmsub */\n            if (s->fs == 0)\n                goto illegal_insn;\n            funct3 = (insn >> 25) & 3;\n            rs3 = insn >> 27;\n            rm = get_insn_rm(s, (insn >> 12) & 7);\n            if (rm < 0)\n                goto illegal_insn;\n            switch(funct3) {\n            case 0:\n                s->fp_reg[rd] = fma_sf32(s->fp_reg[rs1],\n                                         s->fp_reg[rs2],\n                                         s->fp_reg[rs3] ^ FSIGN_MASK32,\n                                         rm, &s->fflags) | F32_HIGH;\n                break;\n#if FLEN >= 64\n            case 1:\n                s->fp_reg[rd] = fma_sf64(s->fp_reg[rs1],\n                                         s->fp_reg[rs2],\n                                         s->fp_reg[rs3] ^ FSIGN_MASK64,\n                                         rm, &s->fflags) | F64_HIGH;\n                break;\n#endif\n#if FLEN >= 128\n            case 3:\n                s->fp_reg[rd] = fma_sf128(s->fp_reg[rs1],\n                                          s->fp_reg[rs2],\n                                          s->fp_reg[rs3] ^ FSIGN_MASK128,\n                                          rm, &s->fflags);\n                break;\n#endif\n            default:\n                goto illegal_insn;\n            }\n            s->fs = 3;\n            NEXT_INSN;\n        case 0x4b: /* fnmsub */\n            if (s->fs == 0)\n                goto illegal_insn;\n            funct3 = (insn >> 25) & 3;\n            rs3 = insn >> 27;\n            rm = get_insn_rm(s, (insn >> 12) & 7);\n            if (rm < 0)\n                goto illegal_insn;\n            switch(funct3) {\n            case 0:\n                s->fp_reg[rd] = fma_sf32(s->fp_reg[rs1] ^ FSIGN_MASK32,\n                                         s->fp_reg[rs2],\n                                         s->fp_reg[rs3],\n                                         rm, &s->fflags) | F32_HIGH;\n                break;\n#if FLEN >= 64\n            case 1:\n                s->fp_reg[rd] = fma_sf64(s->fp_reg[rs1] ^ FSIGN_MASK64,\n                                         s->fp_reg[rs2],\n                                         s->fp_reg[rs3],\n                                         rm, &s->fflags) | F64_HIGH;\n                break;\n#endif\n#if FLEN >= 128\n            case 3:\n                s->fp_reg[rd] = fma_sf128(s->fp_reg[rs1] ^ FSIGN_MASK128,\n                                          s->fp_reg[rs2],\n                                          s->fp_reg[rs3],\n                                          rm, &s->fflags);\n                break;\n#endif\n            default:\n                goto illegal_insn;\n            }\n            s->fs = 3;\n            NEXT_INSN;\n        case 0x4f: /* fnmadd */\n            if (s->fs == 0)\n                goto illegal_insn;\n            funct3 = (insn >> 25) & 3;\n            rs3 = insn >> 27;\n            rm = get_insn_rm(s, (insn >> 12) & 7);\n            if (rm < 0)\n                goto illegal_insn;\n            switch(funct3) {\n            case 0:\n                s->fp_reg[rd] = fma_sf32(s->fp_reg[rs1] ^ FSIGN_MASK32,\n                                         s->fp_reg[rs2],\n                                         s->fp_reg[rs3] ^ FSIGN_MASK32,\n                                         rm, &s->fflags) | F32_HIGH;\n                break;\n#if FLEN >= 64\n            case 1:\n                s->fp_reg[rd] = fma_sf64(s->fp_reg[rs1] ^ FSIGN_MASK64,\n                                         s->fp_reg[rs2],\n                                         s->fp_reg[rs3] ^ FSIGN_MASK64,\n                                         rm, &s->fflags) | F64_HIGH;\n                break;\n#endif\n#if FLEN >= 128\n            case 3:\n                s->fp_reg[rd] = fma_sf128(s->fp_reg[rs1] ^ FSIGN_MASK128,\n                                          s->fp_reg[rs2],\n                                          s->fp_reg[rs3] ^ FSIGN_MASK128,\n                                          rm, &s->fflags);\n                break;\n#endif\n            default:\n                goto illegal_insn;\n            }\n            s->fs = 3;\n            NEXT_INSN;\n        case 0x53:\n            if (s->fs == 0)\n                goto illegal_insn;\n            imm = insn >> 25;\n            rm = (insn >> 12) & 7;\n            switch(imm) {\n\n#define F_SIZE 32\n#include \"riscv_cpu_fp_template.h\"\n#if FLEN >= 64\n#define F_SIZE 64\n#include \"riscv_cpu_fp_template.h\"\n#endif\n#if FLEN >= 128\n#define F_SIZE 128\n#include \"riscv_cpu_fp_template.h\"\n#endif\n\n            default:\n                goto illegal_insn;\n            }\n            NEXT_INSN;\n#endif\n        default:\n            goto illegal_insn;\n        }\n        /* update PC for next instruction */\n    jump_insn: ;\n\n        /* Return to simulation as complex opcode emulation is complete */\n        if (s->simcpu->return_to_sim)\n        {\n            s->simcpu->return_to_sim = FALSE;\n            s->pc = GET_PC();\n            goto the_end;\n        }\n\n        /* Control should never reach here during simulation */\n        if (s->simcpu->simulation)\n        {\n            sim_assert(\n                (0), \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n                __func__,\n                \"non-complex opcode instruction emulated during simulation\");\n        }\n\n    } /* end of main loop */\n illegal_insn:\n    s->pending_exception = CAUSE_ILLEGAL_INSTRUCTION;\n    s->pending_tval = insn;\n mmu_exception:\n exception:\n    s->pc = GET_PC();\n    if (s->pending_exception >= 0) {\n        /* Note: the idea is that one exception counts for one cycle. */\n        s->n_cycles--; \n        raise_exception2(s, s->pending_exception, s->pending_tval);\n    }\n    /* we exit because XLEN may have changed */\n done_interp:\nthe_end:\n    s->insn_counter = GET_INSN_COUNTER();\n#if 0\n    printf(\"done interp %lx int=%x mstatus=%lx prv=%d\\n\",\n           (uint64_t)s->insn_counter, s->mip & s->mie, (uint64_t)s->mstatus,\n           s->priv);\n#endif\n}\n\n#undef uintx_t\n#undef intx_t\n#undef XLEN\n#undef OP_A\n"
  },
  {
    "path": "src/riscv_cpu_xlen_typedefs.h",
    "content": "#ifndef _RISCV_CPU_XLEN_TYPEDEFS_\n#define _RISCV_CPU_XLEN_TYPEDEFS_\n\n#ifndef FLEN\n#if MAX_XLEN == 128\n#define FLEN 128\n#else\n#define FLEN 64\n#endif\n#endif /* !FLEN */\n\n#if MAX_XLEN == 32\ntypedef uint32_t target_ulong;\ntypedef int32_t target_long;\n#define PR_target_ulong \"08x\"\n#elif MAX_XLEN == 64\ntypedef uint64_t target_ulong;\ntypedef int64_t target_long;\n#define PR_target_ulong \"016\" PRIx64\n#elif MAX_XLEN == 128\ntypedef uint128_t target_ulong;\ntypedef int128_t target_long;\n#define PR_target_ulong \"016\" PRIx64 /* XXX */\n#else\n#error unsupported MAX_XLEN\n#endif\n\n/* FLEN is the floating point register width */\n#if FLEN > 0\n#if FLEN == 32\ntypedef uint32_t fp_uint;\n#define F32_HIGH 0\n#elif FLEN == 64\ntypedef uint64_t fp_uint;\n#define F32_HIGH ((fp_uint)-1 << 32)\n#define F64_HIGH 0\n#elif FLEN == 128\ntypedef uint128_t fp_uint;\n#define F32_HIGH ((fp_uint)-1 << 32)\n#define F64_HIGH ((fp_uint)-1 << 64)\n#else\n#error unsupported FLEN\n#endif\n#endif\n\n/* MLEN is the maximum memory access width */\n#if MAX_XLEN <= 32 && FLEN <= 32\n#define MLEN 32\n#elif MAX_XLEN <= 64 && FLEN <= 64\n#define MLEN 64\n#else\n#define MLEN 128\n#endif\n\n#if MLEN == 32\ntypedef uint32_t mem_uint_t;\n#elif MLEN == 64\ntypedef uint64_t mem_uint_t;\n#elif MLEN == 128\ntypedef uint128_t mem_uint_t;\n#else\n#unsupported MLEN\n#endif\n\n#endif"
  },
  {
    "path": "src/riscv_machine.c",
    "content": "/*\n * RISCV machine\n * \n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <unistd.h>\n#include <time.h>\n\n#include \"cutils.h\"\n#include \"iomem.h\"\n#include \"riscv_cpu.h\"\n#include \"virtio.h\"\n#include \"machine.h\"\n#include \"riscvsim/utils/sim_params.h\"\n#include \"rtc_timer.h\"\n#include \"riscv_cpu_priv.h\"\n\n#define UART_RX_BUFSIZE 16\n\n/* RISCV machine */\n\ntypedef struct RISCVMachine {\n    VirtMachine common;\n    PhysMemoryMap *mem_map;\n    int max_xlen;\n    RISCVCPUState *cpu_state;\n    uint64_t ram_size;\n    /* RTC */\n    BOOL rtc_real_time;\n    RTC *rtc;\n    uint64_t timecmp;\n    /* PLIC */\n    uint32_t plic_pending_irq, plic_served_irq;\n    IRQSignal plic_irq[32]; /* IRQ 0 is not used */\n    /* HTIF */\n    uint64_t htif_tohost, htif_fromhost;\n    /* UART */\n    uint8_t uart_dll;\n    uint8_t uart_dlm;\n    uint8_t uart_ier;\n    uint8_t uart_fcr;\n    uint8_t uart_lcr;\n    uint8_t uart_mcr;\n    uint8_t uart_scr;\n    uint8_t uart_rx_pending, uart_tx_pending;\n    int     uart_rx_head, uart_rx_tail;\n    uint8_t uart_rx_buf[UART_RX_BUFSIZE];\n#if defined(UART_OUT_DEBUG)\n    int     uart_pos;\n#endif\n\n    VIRTIODevice *keyboard_dev;\n    VIRTIODevice *mouse_dev;\n\n    int virtio_count;\n} RISCVMachine;\n\n#define LOW_RAM_SIZE   0x00010000 /* 64KB */\n#define RAM_BASE_ADDR  0x80000000\n#define CLINT_BASE_ADDR 0x02000000\n#define CLINT_SIZE      0x000c0000\n#define HTIF_BASE_ADDR 0x40008000\n#define IDE_BASE_ADDR  0x40009000\n#define UART_BASE_ADDR 0x4000A000\n#define UART_IRQ       1\n#define VIRTIO_BASE_ADDR 0x40010000\n#define VIRTIO_SIZE      0x1000\n#define VIRTIO_IRQ       2\n#define PLIC_BASE_ADDR 0x40100000\n#define PLIC_SIZE      0x00400000\n#define FRAMEBUFFER_BASE_ADDR 0x41000000\n\n\n/***************************   RTC   ***************************/\n\n#define RTC_FREQ 10000000\n#define RTC_FREQ_DIV 16 /* arbitrary, relative to CPU freq to have a\n                           10 MHz frequency */\n\nstatic uint64_t rtc_get_time(RISCVMachine *m)\n{\n    uint64_t val;\n    if (m->rtc_real_time) {\n        if (riscv_cpu_in_simulation(m->cpu_state)) {\n            val = riscv_cpu_in_simulation_get_mtime(m->cpu_state);\n        } else {\n            val = rtc_get_elasped_time(m->rtc);\n        }\n    } else {\n        val = riscv_cpu_get_cycles(m->cpu_state) / RTC_FREQ_DIV;\n    }\n    //    printf(\"rtc_time=%\" PRId64 \"\\n\", val);\n    return val;\n}\n\n\n/***************************   UART   ***************************/\n\n#define UART_REG_DATA  0 /* (DLAB=0) RBR=rx buffer / THR=tx holding */\n                         /* (DLAB=1) DLL=divisor latch (lsbyte) */\n#define UART_REG_IER   1 /* (DLAB=0) interrupt enable (bit 0=rx avail, 1=tx empty,\n                                     2=rx line status, 3=modem status) */\n                         /* (DLAB=1) DLM=divisor latch (msbyte) */\n#define UART_REG_IIR   2 /* (read)  interrupt id/cause */\n#define UART_REG_FCR   2 /* (write) FIFO control */\n#define UART_REG_LCR   3 /* line control (bit 7=DLAB) */\n#define UART_REG_MCR   4 /* modem control */\n#define UART_REG_LSR   5 /* line status (bit 0=rx avail, 5=tx buf empty, 6=tx empty/done) */\n#define UART_REG_MSR   6 /* modem status */\n#define UART_REG_SCR   7 /* scratch */\n\n#define UART_LCR_DLAB  0x80\n\nstatic void uart_set_irq(RISCVMachine *s)\n{\n    int pending = (s->uart_rx_pending && (s->uart_ier & 0x01) != 0)\n                || (s->uart_tx_pending && (s->uart_ier & 0x02) != 0);\n    set_irq(&s->plic_irq[UART_IRQ], pending);\n}\n\nstatic uint32_t uart_read(void *opaque, uint32_t offset, int size_log2)\n{\n    RISCVMachine *s = (RISCVMachine *)opaque;\n    uint32_t val;\n\n    assert(size_log2 == 0);\n    switch(offset) {\n\n    case UART_REG_DATA:\n        if (s->uart_lcr & UART_LCR_DLAB)\n            val = s->uart_dll;\n        else if (s->uart_rx_head != s->uart_rx_tail)    /* data to read? */\n        {\n            val = s->uart_rx_buf[s->uart_rx_head];\n            s->uart_rx_head = (s->uart_rx_head + 1) % UART_RX_BUFSIZE;\n            if (s->uart_rx_head == s->uart_rx_tail)     /* now empty? */\n            {\n                s->uart_rx_pending = 0;\n                uart_set_irq(s);\n            }\n        }\n        else\n            val = 0;\n        break;\n\n    case UART_REG_IER:\n        val = (s->uart_lcr & UART_LCR_DLAB) ? s->uart_dlm : s->uart_ier;\n        break;\n\n    case UART_REG_LCR:\n        val = s->uart_lcr;\n        break;\n\n    case UART_REG_IIR:\n        val = ((s->uart_fcr & 0x01) ? 0xC0 : 0x00)\n            | (s->uart_rx_pending ? ((s->uart_fcr & 0xC0) ? 0x0C : 0x04) : s->uart_tx_pending ? 0x02 : 0x01);\n        s->uart_rx_pending = 0;\n        s->uart_tx_pending = 0;\n        uart_set_irq(s);\n        break;\n\n    case UART_REG_MCR:\n        val = s->uart_mcr;\n        break;\n\n    case UART_REG_LSR:\n        val = 0x60 | s->uart_rx_pending;        /* tx always ready/empty */\n        break;\n\n    case UART_REG_MSR:\n        val = 0xB0;                             /* report CTS, DSR, DCD as asserted */\n        break;\n\n    case UART_REG_SCR:\n        val = s->uart_scr;\n        break;\n\n    default:\n        val = 0;\n        break;\n\n    }\n    return val;\n}\n\nstatic inline void console_write_char(RISCVMachine *s, uint8_t c)\n{\n    s->common.console->write_data(s->common.console->opaque, &c, 1);\n}\n\n#if defined(UART_OUT_DEBUG)\nstatic void console_write_string(RISCVMachine *s, char *str)\n{\n    while (*str)\n        console_write_char(s, (uint8_t)*str++);\n}\n#endif\n\nstatic void uart_write(void *opaque, uint32_t offset, uint32_t val,\n                       int size_log2)\n{\n    RISCVMachine *s = (RISCVMachine *)opaque;\n\n    assert(size_log2 == 0);\n    switch(offset) {\n    case UART_REG_DATA:\n        if (s->uart_lcr & UART_LCR_DLAB)\n            s->uart_dll = val;\n        else\n        {\n#if defined(UART_OUT_DEBUG)\n            if (s->uart_pos == 0)\n                console_write_string(s, \"uart: \");\n            if (val == '\\n')\n                s->uart_pos = 0;\n            else\n                s->uart_pos++;\n#endif\n            console_write_char(s, val);\n            s->uart_tx_pending = 1;\n            uart_set_irq(s);\n        }\n        break;\n    case UART_REG_IER:\n        if (s->uart_lcr & UART_LCR_DLAB)\n            s->uart_dlm = val;\n        else\n        {\n            s->uart_ier = val;\n            uart_set_irq(s);\n        }\n        break;\n    case UART_REG_LCR:\n        s->uart_lcr = val;\n        break;\n    case UART_REG_FCR:\n        s->uart_fcr = val;\n        break;\n    case UART_REG_MCR:\n        s->uart_mcr = (val & 0xF);      /* loop not implemented */\n        break;\n    case UART_REG_SCR:\n        s->uart_scr = val;\n        break;\n    default:\n        break;\n    }\n}\n\n/*  Returns the number of bytes that can be received.  */\nint  uart_can_rx(VirtMachine *v)\n{\n    RISCVMachine *s = (RISCVMachine *)v;\n\n    return (s->uart_rx_head + UART_RX_BUFSIZE-1 - s->uart_rx_tail) % UART_RX_BUFSIZE;\n}\n\n/*  Called when user types on console.  */\nvoid uart_rx_data(VirtMachine *v, uint8_t *buf, int size)\n{\n    RISCVMachine *s = (RISCVMachine *)v;\n\n    for (; size > 0; size--)\n    {\n        int tail = s->uart_rx_tail;\n        int newtail = (tail + 1) % UART_RX_BUFSIZE;\n        if (newtail == s->uart_rx_head)\n            return;             /* buffer full, characters lost */\n        s->uart_rx_buf[tail] = *buf++;\n        s->uart_rx_tail = newtail;\n        s->uart_rx_pending = 1; /* data ready */\n        uart_set_irq(s);\n    }\n}\n\n\n/***************************   HTIF   ***************************/\n\nstatic uint32_t htif_read(void *opaque, uint32_t offset,\n                          int size_log2)\n{\n    RISCVMachine *s = opaque;\n    uint32_t val;\n\n    assert(size_log2 == 2);\n    switch(offset) {\n    case 0:\n        val = s->htif_tohost;\n        break;\n    case 4:\n        val = s->htif_tohost >> 32;\n        break;\n    case 8:\n        val = s->htif_fromhost;\n        break;\n    case 12:\n        val = s->htif_fromhost >> 32;\n        break;\n    default:\n        val = 0;\n        break;\n    }\n    return val;\n}\n\nstatic void htif_handle_cmd(RISCVMachine *s)\n{\n    uint32_t device, cmd;\n\n    device = s->htif_tohost >> 56;\n    cmd = (s->htif_tohost >> 48) & 0xff;\n    if (s->htif_tohost == 1) {\n        /* shuthost */\n        printf(\"\\nPower off.\\n\");\n        exit(0);\n    } else if (device == 1 && cmd == 1) {\n        console_write_char(s, s->htif_tohost & 0xff);\n        s->htif_tohost = 0;\n        s->htif_fromhost = ((uint64_t)device << 56) | ((uint64_t)cmd << 48);\n    } else if (device == 1 && cmd == 0) {\n        /* request keyboard interrupt */\n        s->htif_tohost = 0;\n    } else {\n        printf(\"HTIF: unsupported tohost=0x%016\" PRIx64 \"\\n\", s->htif_tohost);\n    }\n}\n\nstatic void htif_write(void *opaque, uint32_t offset, uint32_t val,\n                       int size_log2)\n{\n    RISCVMachine *s = opaque;\n\n    assert(size_log2 == 2);\n    switch(offset) {\n    case 0:\n        s->htif_tohost = (s->htif_tohost & ~0xffffffff) | val;\n        break;\n    case 4:\n        s->htif_tohost = (s->htif_tohost & 0xffffffff) | ((uint64_t)val << 32);\n        htif_handle_cmd(s);\n        break;\n    case 8:\n        s->htif_fromhost = (s->htif_fromhost & ~0xffffffff) | val;\n        break;\n    case 12:\n        s->htif_fromhost = (s->htif_fromhost & 0xffffffff) |\n            (uint64_t)val << 32;\n        break;\n    default:\n        break;\n    }\n}\n\n#if 0\nstatic void htif_poll(RISCVMachine *s)\n{\n    uint8_t buf[1];\n    int ret;\n\n    if (s->htif_fromhost == 0) {\n        ret = s->console->read_data(s->console->opaque, buf, 1);\n        if (ret == 1) {\n            s->htif_fromhost = ((uint64_t)1 << 56) | ((uint64_t)0 << 48) |\n                buf[0];\n        }\n    }\n}\n#endif\n\n\n/***************************   CLINT   ***************************/\n\nstatic uint32_t clint_read(void *opaque, uint32_t offset, int size_log2)\n{\n    RISCVMachine *m = opaque;\n    uint32_t val;\n\n    assert(size_log2 == 2);\n    switch(offset) {\n    case 0xbff8:\n        val = rtc_get_time(m);\n        break;\n    case 0xbffc:\n        val = rtc_get_time(m) >> 32;\n        break;\n    case 0x4000:\n        val = m->timecmp;\n        break;\n    case 0x4004:\n        val = m->timecmp >> 32;\n        break;\n    default:\n        val = 0;\n        break;\n    }\n    return val;\n}\n \nstatic void clint_write(void *opaque, uint32_t offset, uint32_t val,\n                      int size_log2)\n{\n    RISCVMachine *m = opaque;\n\n    assert(size_log2 == 2);\n    switch(offset) {\n    case 0x4000:\n        m->timecmp = (m->timecmp & ~0xffffffff) | val;\n        riscv_cpu_reset_mip(m->cpu_state, MIP_MTIP);\n        break;\n    case 0x4004:\n        m->timecmp = (m->timecmp & 0xffffffff) | ((uint64_t)val << 32);\n        riscv_cpu_reset_mip(m->cpu_state, MIP_MTIP);\n        break;\n    default:\n        break;\n    }\n}\n\n\n/***************************   PLIC   ***************************/\n\nstatic void plic_update_mip(RISCVMachine *s)\n{\n    RISCVCPUState *cpu = s->cpu_state;\n    uint32_t mask;\n    mask = s->plic_pending_irq & ~s->plic_served_irq;\n    if (mask) {\n        riscv_cpu_set_mip(cpu, MIP_MEIP | MIP_SEIP);\n    } else {\n        riscv_cpu_reset_mip(cpu, MIP_MEIP | MIP_SEIP);\n    }\n}\n\n#define PLIC_HART_BASE 0x200000\n#define PLIC_HART_SIZE 0x1000\n\nstatic uint32_t plic_read(void *opaque, uint32_t offset, int size_log2)\n{\n    RISCVMachine *s = opaque;\n    uint32_t val, mask;\n    int i;\n    assert(size_log2 == 2);\n    switch(offset) {\n    case PLIC_HART_BASE:\n        val = 0;\n        break;\n    case PLIC_HART_BASE + 4:\n        mask = s->plic_pending_irq & ~s->plic_served_irq;\n        if (mask != 0) {\n            i = ctz32(mask);\n            s->plic_served_irq |= 1 << i;\n            plic_update_mip(s);\n            val = i + 1;\n        } else {\n            val = 0;\n        }\n        break;\n    default:\n        val = 0;\n        break;\n    }\n    return val;\n}\n\nstatic void plic_write(void *opaque, uint32_t offset, uint32_t val,\n                       int size_log2)\n{\n    RISCVMachine *s = opaque;\n    \n    assert(size_log2 == 2);\n    switch(offset) {\n    case PLIC_HART_BASE + 4:\n        val--;\n        if (val < 32) {\n            s->plic_served_irq &= ~(1 << val);\n            plic_update_mip(s);\n        }\n        break;\n    default:\n        break;\n    }\n}\n\nstatic void plic_set_irq(void *opaque, int irq_num, int state)\n{\n    RISCVMachine *s = opaque;\n    uint32_t mask;\n\n    mask = 1 << (irq_num - 1);\n    if (state) \n        s->plic_pending_irq |= mask;\n    else\n        s->plic_pending_irq &= ~mask;\n    plic_update_mip(s);\n}\n\n\n/***************************   MISC   ***************************/\nstatic uint8_t *get_ram_ptr(RISCVMachine *s, uint64_t paddr, BOOL is_rw)\n{\n    return phys_mem_get_ram_ptr(s->mem_map, paddr, is_rw);\n}\n\n\n/***************************   FDT   ***************************/\n\n/* FDT machine description */\n\n#define FDT_MAGIC\t0xd00dfeed\n#define FDT_VERSION\t17\n\nstruct fdt_header {\n    uint32_t magic;\n    uint32_t totalsize;\n    uint32_t off_dt_struct;\n    uint32_t off_dt_strings;\n    uint32_t off_mem_rsvmap;\n    uint32_t version;\n    uint32_t last_comp_version; /* <= 17 */\n    uint32_t boot_cpuid_phys;\n    uint32_t size_dt_strings;\n    uint32_t size_dt_struct;\n};\n\nstruct fdt_reserve_entry {\n       uint64_t address;\n       uint64_t size;\n};\n\n#define FDT_BEGIN_NODE\t1\n#define FDT_END_NODE\t2\n#define FDT_PROP\t3\n#define FDT_NOP\t\t4\n#define FDT_END\t\t9\n\ntypedef struct {\n    uint32_t *tab;\n    int tab_len;\n    int tab_size;\n    int open_node_count;\n    \n    char *string_table;\n    int string_table_len;\n    int string_table_size;\n} FDTState;\n\nstatic FDTState *fdt_init(void)\n{\n    FDTState *s;\n    s = mallocz(sizeof(*s));\n    return s;\n}\n\nstatic void fdt_alloc_len(FDTState *s, int len)\n{\n    int new_size;\n    if (unlikely(len > s->tab_size)) {\n        new_size = max_int(len, s->tab_size * 3 / 2);\n        s->tab = realloc(s->tab, new_size * sizeof(uint32_t));\n        s->tab_size = new_size;\n    }\n}\n\nstatic void fdt_put32(FDTState *s, int v)\n{\n    fdt_alloc_len(s, s->tab_len + 1);\n    s->tab[s->tab_len++] = cpu_to_be32(v);\n}\n\n/* the data is zero padded */\nstatic void fdt_put_data(FDTState *s, const uint8_t *data, int len)\n{\n    int len1;\n    \n    len1 = (len + 3) / 4;\n    fdt_alloc_len(s, s->tab_len + len1);\n    memcpy(s->tab + s->tab_len, data, len);\n    memset((uint8_t *)(s->tab + s->tab_len) + len, 0, -len & 3);\n    s->tab_len += len1;\n}\n\nstatic void fdt_begin_node(FDTState *s, const char *name)\n{\n    fdt_put32(s, FDT_BEGIN_NODE);\n    fdt_put_data(s, (uint8_t *)name, strlen(name) + 1);\n    s->open_node_count++;\n}\n\nstatic void fdt_begin_node_num(FDTState *s, const char *name, uint64_t n)\n{\n    char buf[256];\n    snprintf(buf, sizeof(buf), \"%s@%\" PRIx64, name, n);\n    fdt_begin_node(s, buf);\n}\n\nstatic void fdt_end_node(FDTState *s)\n{\n    fdt_put32(s, FDT_END_NODE);\n    s->open_node_count--;\n}\n\nstatic int fdt_get_string_offset(FDTState *s, const char *name)\n{\n    int pos, new_size, name_size, new_len;\n\n    pos = 0;\n    while (pos < s->string_table_len) {\n        if (!strcmp(s->string_table + pos, name))\n            return pos;\n        pos += strlen(s->string_table + pos) + 1;\n    }\n    /* add a new string */\n    name_size = strlen(name) + 1;\n    new_len = s->string_table_len + name_size;\n    if (new_len > s->string_table_size) {\n        new_size = max_int(new_len, s->string_table_size * 3 / 2);\n        s->string_table = realloc(s->string_table, new_size);\n        s->string_table_size = new_size;\n    }\n    pos = s->string_table_len;\n    memcpy(s->string_table + pos, name, name_size);\n    s->string_table_len = new_len;\n    return pos;\n}\n\nstatic void fdt_prop(FDTState *s, const char *prop_name,\n                     const void *data, int data_len)\n{\n    fdt_put32(s, FDT_PROP);\n    fdt_put32(s, data_len);\n    fdt_put32(s, fdt_get_string_offset(s, prop_name));\n    fdt_put_data(s, data, data_len);\n}\n\nstatic void fdt_prop_tab_u32(FDTState *s, const char *prop_name,\n                             uint32_t *tab, int tab_len)\n{\n    int i;\n    fdt_put32(s, FDT_PROP);\n    fdt_put32(s, tab_len * sizeof(uint32_t));\n    fdt_put32(s, fdt_get_string_offset(s, prop_name));\n    for(i = 0; i < tab_len; i++)\n        fdt_put32(s, tab[i]);\n}\n\nstatic void fdt_prop_u32(FDTState *s, const char *prop_name, uint32_t val)\n{\n    fdt_prop_tab_u32(s, prop_name, &val, 1);\n}\n\nstatic void fdt_prop_tab_u64(FDTState *s, const char *prop_name,\n                             uint64_t v0)\n{\n    uint32_t tab[2];\n    tab[0] = v0 >> 32;\n    tab[1] = v0;\n    fdt_prop_tab_u32(s, prop_name, tab, 2);\n}\n\nstatic void fdt_prop_tab_u64_2(FDTState *s, const char *prop_name,\n                               uint64_t v0, uint64_t v1)\n{\n    uint32_t tab[4];\n    tab[0] = v0 >> 32;\n    tab[1] = v0;\n    tab[2] = v1 >> 32;\n    tab[3] = v1;\n    fdt_prop_tab_u32(s, prop_name, tab, 4);\n}\n\nstatic void fdt_prop_str(FDTState *s, const char *prop_name,\n                         const char *str)\n{\n    fdt_prop(s, prop_name, str, strlen(str) + 1);\n}\n\n/* NULL terminated string list */\nstatic void fdt_prop_tab_str(FDTState *s, const char *prop_name,\n                             ...)\n{\n    va_list ap;\n    int size, str_size;\n    char *ptr, *tab;\n\n    va_start(ap, prop_name);\n    size = 0;\n    for(;;) {\n        ptr = va_arg(ap, char *);\n        if (!ptr)\n            break;\n        str_size = strlen(ptr) + 1;\n        size += str_size;\n    }\n    va_end(ap);\n    \n    tab = malloc(size);\n    va_start(ap, prop_name);\n    size = 0;\n    for(;;) {\n        ptr = va_arg(ap, char *);\n        if (!ptr)\n            break;\n        str_size = strlen(ptr) + 1;\n        memcpy(tab + size, ptr, str_size);\n        size += str_size;\n    }\n    va_end(ap);\n    \n    fdt_prop(s, prop_name, tab, size);\n    free(tab);\n}\n\n/* write the FDT to 'dst1'. return the FDT size in bytes */\nint fdt_output(FDTState *s, uint8_t *dst)\n{\n    struct fdt_header *h;\n    struct fdt_reserve_entry *re;\n    int dt_struct_size;\n    int dt_strings_size;\n    int pos;\n\n    assert(s->open_node_count == 0);\n    \n    fdt_put32(s, FDT_END);\n    \n    dt_struct_size = s->tab_len * sizeof(uint32_t);\n    dt_strings_size = s->string_table_len;\n\n    h = (struct fdt_header *)dst;\n    h->magic = cpu_to_be32(FDT_MAGIC);\n    h->version = cpu_to_be32(FDT_VERSION);\n    h->last_comp_version = cpu_to_be32(16);\n    h->boot_cpuid_phys = cpu_to_be32(0);\n    h->size_dt_strings = cpu_to_be32(dt_strings_size);\n    h->size_dt_struct = cpu_to_be32(dt_struct_size);\n\n    pos = sizeof(struct fdt_header);\n\n    h->off_dt_struct = cpu_to_be32(pos);\n    memcpy(dst + pos, s->tab, dt_struct_size);\n    pos += dt_struct_size;\n\n    /* align to 8 */\n    while ((pos & 7) != 0) {\n        dst[pos++] = 0;\n    }\n    h->off_mem_rsvmap = cpu_to_be32(pos);\n    re = (struct fdt_reserve_entry *)(dst + pos);\n    re->address = 0; /* no reserved entry */\n    re->size = 0;\n    pos += sizeof(struct fdt_reserve_entry);\n\n    h->off_dt_strings = cpu_to_be32(pos);\n    memcpy(dst + pos, s->string_table, dt_strings_size);\n    pos += dt_strings_size;\n\n    /* align to 8, just in case */\n    while ((pos & 7) != 0) {\n        dst[pos++] = 0;\n    }\n\n    h->totalsize = cpu_to_be32(pos);\n    return pos;\n}\n\nvoid fdt_end(FDTState *s)\n{\n    free(s->tab);\n    free(s->string_table);\n    free(s);\n}\n\nstatic int riscv_build_fdt(RISCVMachine *m, uint8_t *dst,\n                           uint64_t kernel_start, uint64_t kernel_size,\n                           uint64_t initrd_start, uint64_t initrd_size,\n                           const char *cmd_line)\n{\n    FDTState *s;\n    int size, max_xlen, i, cur_phandle, intc_phandle, plic_phandle;\n    char isa_string[128], *q;\n    uint32_t misa;\n    uint32_t tab[4];\n    FBDevice *fb_dev;\n    \n    s = fdt_init();\n\n    cur_phandle = 1;\n    \n    fdt_begin_node(s, \"\");\n    fdt_prop_u32(s, \"#address-cells\", 2);\n    fdt_prop_u32(s, \"#size-cells\", 2);\n    fdt_prop_str(s, \"compatible\", \"ucbbar,riscvemu-bar_dev\");\n    fdt_prop_str(s, \"model\", \"ucbbar,riscvemu-bare\");\n\n    /* CPU list */\n    fdt_begin_node(s, \"cpus\");\n    fdt_prop_u32(s, \"#address-cells\", 1);\n    fdt_prop_u32(s, \"#size-cells\", 0);\n    fdt_prop_u32(s, \"timebase-frequency\", m->rtc->freq);\n\n    /* cpu */\n    fdt_begin_node_num(s, \"cpu\", 0);\n    fdt_prop_str(s, \"device_type\", \"cpu\");\n    fdt_prop_u32(s, \"reg\", 0);\n    fdt_prop_str(s, \"status\", \"okay\");\n    fdt_prop_str(s, \"compatible\", \"riscv\");\n\n    max_xlen = m->max_xlen;\n    misa = riscv_cpu_get_misa(m->cpu_state);\n    q = isa_string;\n    q += snprintf(isa_string, sizeof(isa_string), \"rv%d\", max_xlen);\n    for(i = 0; i < 26; i++) {\n        if (misa & (1 << i))\n            *q++ = 'a' + i;\n    }\n    *q = '\\0';\n    fdt_prop_str(s, \"riscv,isa\", isa_string);\n    \n    fdt_prop_str(s, \"mmu-type\", max_xlen <= 32 ? \"riscv,sv32\" : \"riscv,sv48\");\n    fdt_prop_u32(s, \"clock-frequency\", (m->common.virt_machine_params->sim_params->cpu_freq_mhz * 1000000));\n\n    fdt_begin_node(s, \"interrupt-controller\");\n    fdt_prop_u32(s, \"#interrupt-cells\", 1);\n    fdt_prop(s, \"interrupt-controller\", NULL, 0);\n    fdt_prop_str(s, \"compatible\", \"riscv,cpu-intc\");\n    intc_phandle = cur_phandle++;\n    fdt_prop_u32(s, \"phandle\", intc_phandle);\n    fdt_end_node(s); /* interrupt-controller */\n    \n    fdt_end_node(s); /* cpu */\n    \n    fdt_end_node(s); /* cpus */\n\n    fdt_begin_node_num(s, \"memory\", RAM_BASE_ADDR);\n    fdt_prop_str(s, \"device_type\", \"memory\");\n    tab[0] = (uint64_t)RAM_BASE_ADDR >> 32;\n    tab[1] = RAM_BASE_ADDR;\n    tab[2] = m->ram_size >> 32;\n    tab[3] = m->ram_size;\n    fdt_prop_tab_u32(s, \"reg\", tab, 4);\n    \n    fdt_end_node(s); /* memory */\n    \n    fdt_begin_node(s, \"soc\");\n    fdt_prop_u32(s, \"#address-cells\", 2);\n    fdt_prop_u32(s, \"#size-cells\", 2);\n    fdt_prop_tab_str(s, \"compatible\",\n                     \"ucbbar,riscvemu-bar-soc\", \"simple-bus\", NULL);\n    fdt_prop(s, \"ranges\", NULL, 0);\n\n    fdt_begin_node_num(s, \"clint\", CLINT_BASE_ADDR);\n    fdt_prop_str(s, \"compatible\", \"riscv,clint0\");\n\n    tab[0] = intc_phandle;\n    tab[1] = 3; /* M IPI irq */\n    tab[2] = intc_phandle;\n    tab[3] = 7; /* M timer irq */\n    fdt_prop_tab_u32(s, \"interrupts-extended\", tab, 4);\n\n    fdt_prop_tab_u64_2(s, \"reg\", CLINT_BASE_ADDR, CLINT_SIZE);\n    \n    fdt_end_node(s); /* clint */\n\n    fdt_begin_node_num(s, \"plic\", PLIC_BASE_ADDR);\n    fdt_prop_u32(s, \"#interrupt-cells\", 1);\n    fdt_prop(s, \"interrupt-controller\", NULL, 0);\n    fdt_prop_str(s, \"compatible\", \"riscv,plic0\");\n    fdt_prop_u32(s, \"riscv,ndev\", 31);\n    fdt_prop_tab_u64_2(s, \"reg\", PLIC_BASE_ADDR, PLIC_SIZE);\n\n    tab[0] = intc_phandle;\n    tab[1] = 9; /* S ext irq */\n    tab[2] = intc_phandle;\n    tab[3] = 11; /* M ext irq */\n    fdt_prop_tab_u32(s, \"interrupts-extended\", tab, 4);\n\n    plic_phandle = cur_phandle++;\n    fdt_prop_u32(s, \"phandle\", plic_phandle);\n\n    fdt_end_node(s); /* plic */\n    \n    for(i = 0; i < m->virtio_count; i++) {\n        fdt_begin_node_num(s, \"virtio\", VIRTIO_BASE_ADDR + i * VIRTIO_SIZE);\n        fdt_prop_str(s, \"compatible\", \"virtio,mmio\");\n        fdt_prop_tab_u64_2(s, \"reg\", VIRTIO_BASE_ADDR + i * VIRTIO_SIZE,\n                           VIRTIO_SIZE);\n        tab[0] = plic_phandle;\n        tab[1] = VIRTIO_IRQ + i;\n        fdt_prop_tab_u32(s, \"interrupts-extended\", tab, 2);\n        fdt_end_node(s); /* virtio */\n    }\n\n    fb_dev = m->common.fb_dev;\n    if (fb_dev) {\n        fdt_begin_node_num(s, \"framebuffer\", FRAMEBUFFER_BASE_ADDR);\n        fdt_prop_str(s, \"compatible\", \"simple-framebuffer\");\n        fdt_prop_tab_u64_2(s, \"reg\", FRAMEBUFFER_BASE_ADDR, fb_dev->fb_size);\n        fdt_prop_u32(s, \"width\", fb_dev->width);\n        fdt_prop_u32(s, \"height\", fb_dev->height);\n        fdt_prop_u32(s, \"stride\", fb_dev->stride);\n        fdt_prop_str(s, \"format\", \"a8r8g8b8\");\n        fdt_end_node(s); /* framebuffer */\n    }\n    \n    fdt_end_node(s); /* soc */\n\n    fdt_begin_node(s, \"chosen\");\n    fdt_prop_str(s, \"bootargs\", cmd_line ? cmd_line : \"\");\n    if (kernel_size > 0) {\n        fdt_prop_tab_u64(s, \"riscv,kernel-start\", kernel_start);\n        fdt_prop_tab_u64(s, \"riscv,kernel-end\", kernel_start + kernel_size);\n    }\n    if (initrd_size > 0) {\n        fdt_prop_tab_u64(s, \"linux,initrd-start\", initrd_start);\n        fdt_prop_tab_u64(s, \"linux,initrd-end\", initrd_start + initrd_size);\n    }\n    \n\n    fdt_end_node(s); /* chosen */\n\n    /* UART */\n    fdt_begin_node_num(s, \"uart\", UART_BASE_ADDR);\n    tab[0] = plic_phandle;\n    tab[1] = UART_IRQ;\n    fdt_prop_tab_u32(s, \"interrupts-extended\", tab, 2);\n    //fdt_prop_u32(s, \"interrupts\", 0);\n    //fdt_prop_u32(s, \"interrupt-parent\", 0);\n    fdt_prop_u32(s, \"clock-frequency\", 384000);\n    fdt_prop_tab_u64_2(s, \"reg\", UART_BASE_ADDR, 0x100);\n    fdt_prop_str(s, \"compatible\", \"ns16550a\");\n    fdt_end_node(s); /* uart */\n\n#if 0   /* requires a mechanism to get the BBL's tohost and fromhost variable non-standard addresses */\n    /* HTIF */\n    fdt_begin_node(s, \"htif\");\n    fdt_prop_str(s, \"compatible\", \"ucb,htif0\");\n    fdt_end_node(s); /* htif */\n#endif\n\n    fdt_end_node(s); /* / */\n\n    size = fdt_output(s, dst);\n#if 0\n    {\n        FILE *f;\n        f = fopen(\"/tmp/riscvemu.dtb\", \"wb\");\n        fwrite(dst, 1, size, f);\n        fclose(f);\n    }\n#endif\n    fdt_end(s);\n    return size;\n}\n\n\n/***************************   MISC   ***************************/\nstatic void copy_kernel(RISCVMachine *s, const uint8_t *buf, int buf_len,\n                        const char *cmd_line)\n{\n    uint32_t fdt_addr;\n    uint8_t *ram_ptr;\n    uint32_t *q;\n\n    if (buf_len > s->ram_size) {\n        vm_error(\"Kernel too big\\n\");\n        exit(1);\n    }\n\n    ram_ptr = get_ram_ptr(s, RAM_BASE_ADDR, TRUE);\n    memcpy(ram_ptr, buf, buf_len);\n\n    ram_ptr = get_ram_ptr(s, 0, TRUE);\n\n    fdt_addr = 0x1000 + 8 * 8;\n\n    riscv_build_fdt(s, ram_ptr + fdt_addr, 0, 0, 0, 0, cmd_line);\n\n    /* jump_addr = 0x80000000 */\n\n    q = (uint32_t *)(ram_ptr + 0x1000);\n    q[0] = 0x297 + 0x80000000 - 0x1000; /* auipc t0, jump_addr */\n    q[1] = 0x597; /* auipc a1, dtb */\n    q[2] = 0x58593 + ((fdt_addr - 4) << 20); /* addi a1, a1, dtb */\n    q[3] = 0xf1402573; /* csrr a0, mhartid */\n    q[4] = 0x00028067; /* jalr zero, t0, jump_addr */\n}\n\nstatic void copy_bios(RISCVMachine *s, const uint8_t *buf, int buf_len,\n                      const uint8_t *kernel_buf, int kernel_buf_len,\n                      const uint8_t *initrd_buf, int initrd_buf_len,\n                      const char *cmd_line)\n{\n    uint32_t fdt_addr, align, kernel_base, initrd_base;\n    uint8_t *ram_ptr;\n    uint32_t *q;\n\n    if (buf_len > s->ram_size) {\n        vm_error(\"BIOS too big\\n\");\n        exit(1);\n    }\n\n    ram_ptr = get_ram_ptr(s, RAM_BASE_ADDR, TRUE);\n    memcpy(ram_ptr, buf, buf_len);\n\n    kernel_base = 0;\n    if (kernel_buf_len > 0) {\n        /* copy the kernel if present */\n        if (s->max_xlen == 32)\n            align = 4 << 20; /* 4 MB page align */\n        else\n            align = 2 << 20; /* 2 MB page align */\n        kernel_base = (buf_len + align - 1) & ~(align - 1);\n        memcpy(ram_ptr + kernel_base, kernel_buf, kernel_buf_len);\n        if (kernel_buf_len + kernel_base > s->ram_size) {\n            vm_error(\"kernel too big\");\n            exit(1);\n        }\n    }\n\n    initrd_base = 0;\n    if (initrd_buf_len > 0) {\n        /* same allocation as QEMU */\n        initrd_base = s->ram_size / 2;\n        if (initrd_base > (128 << 20))\n            initrd_base = 128 << 20;\n        memcpy(ram_ptr + initrd_base, initrd_buf, initrd_buf_len);\n        if (initrd_buf_len + initrd_base > s->ram_size) {\n            vm_error(\"initrd too big\");\n            exit(1);\n        }\n    }\n    \n    ram_ptr = get_ram_ptr(s, 0, TRUE);\n    \n    fdt_addr = 0x1000 + 8 * 8;\n\n    riscv_build_fdt(s, ram_ptr + fdt_addr,\n                    RAM_BASE_ADDR + kernel_base, kernel_buf_len,\n                    RAM_BASE_ADDR + initrd_base, initrd_buf_len,\n                    cmd_line);\n\n    /* jump_addr = 0x80000000 */\n    \n    q = (uint32_t *)(ram_ptr + 0x1000);\n    q[0] = 0x297 + 0x80000000 - 0x1000; /* auipc t0, jump_addr */\n    q[1] = 0x597; /* auipc a1, dtb */\n    q[2] = 0x58593 + ((fdt_addr - 4) << 20); /* addi a1, a1, dtb */\n    q[3] = 0xf1402573; /* csrr a0, mhartid */\n    q[4] = 0x00028067; /* jalr zero, t0, jump_addr */\n}\n\nstatic void riscv_flush_tlb_write_range(void *opaque, uint8_t *ram_addr,\n                                        size_t ram_size)\n{\n    RISCVMachine *s = opaque;\n    riscv_cpu_flush_tlb_write_range_ram(s->cpu_state, ram_addr, ram_size);\n}\n\nstatic void riscv_machine_set_defaults(VirtMachineParams *p)\n{\n}\n\nstatic VirtMachine *riscv_machine_init(const VirtMachineParams *p)\n{\n    RISCVMachine *s;\n    VIRTIODevice *blk_dev;\n    int irq_num, i, max_xlen, ram_flags;\n    VIRTIOBusDef vbus_s, *vbus = &vbus_s;\n\n\n    if (!strcmp(p->machine_name, \"riscv32\")) {\n        max_xlen = 32;\n    } else if (!strcmp(p->machine_name, \"riscv64\")) {\n        max_xlen = 64;\n    } else if (!strcmp(p->machine_name, \"riscv128\")) {\n        max_xlen = 128;\n    } else {\n        vm_error(\"unsupported machine: %s\\n\", p->machine_name);\n        return NULL;\n    }\n    \n    s = mallocz(sizeof(*s));\n    s->common.vmc = p->vmc;\n    s->ram_size = p->ram_size;\n    s->max_xlen = max_xlen;\n    s->mem_map = phys_mem_map_init();\n    /* needed to handle the RAM dirty bits */\n    s->mem_map->opaque = s;\n    s->mem_map->flush_tlb_write_range = riscv_flush_tlb_write_range;\n\n    s->common.virt_machine_params = (VirtMachineParams *)p;\n\n    /* Validate all the simulation parameters before initializing core */\n    sim_params_validate(p->sim_params);\n\n    s->cpu_state = riscv_cpu_init(s->mem_map, max_xlen, p->sim_params);\n    if (!s->cpu_state) {\n        vm_error(\"unsupported max_xlen=%d\\n\", max_xlen);\n        /* XXX: should free resources */\n        return NULL;\n    }\n    /* RAM */\n    ram_flags = 0;\n    cpu_register_ram(s->mem_map, RAM_BASE_ADDR, p->ram_size, ram_flags);\n    cpu_register_ram(s->mem_map, 0x00000000, LOW_RAM_SIZE, 0);\n    s->rtc_real_time = p->rtc_real_time;\n    s->rtc = rtc_init(p->sim_params->rtc_freq_mhz * 1000000);\n    s->cpu_state->rtc = s->rtc;\n\n    cpu_register_device(s->mem_map, CLINT_BASE_ADDR, CLINT_SIZE, s,\n                        clint_read, clint_write, DEVIO_SIZE32);\n    cpu_register_device(s->mem_map, PLIC_BASE_ADDR, PLIC_SIZE, s,\n                        plic_read, plic_write, DEVIO_SIZE32);\n    for(i = 1; i < 32; i++) {\n        irq_init(&s->plic_irq[i], plic_set_irq, s, i);\n    }\n\n    cpu_register_device(s->mem_map, UART_BASE_ADDR, 16,\n                        s, uart_read, uart_write, DEVIO_SIZE8);\n    cpu_register_device(s->mem_map, HTIF_BASE_ADDR, 16,\n                        s, htif_read, htif_write, DEVIO_SIZE32);\n    s->common.console = p->console;\n\n    memset(vbus, 0, sizeof(*vbus));\n    vbus->mem_map = s->mem_map;\n    vbus->addr = VIRTIO_BASE_ADDR;\n    irq_num = VIRTIO_IRQ;\n    \n    /* virtio console */\n    if (p->console) {\n        vbus->irq = &s->plic_irq[irq_num];\n        s->common.console_dev = virtio_console_init(vbus, p->console);\n        vbus->addr += VIRTIO_SIZE;\n        irq_num++;\n        s->virtio_count++;\n    }\n    \n    /* virtio net device */\n    for(i = 0; i < p->eth_count; i++) {\n        vbus->irq = &s->plic_irq[irq_num];\n        virtio_net_init(vbus, p->tab_eth[i].net);\n        s->common.net = p->tab_eth[i].net;\n        vbus->addr += VIRTIO_SIZE;\n        irq_num++;\n        s->virtio_count++;\n    }\n\n    /* virtio block device */\n    for(i = 0; i < p->drive_count; i++) {\n        vbus->irq = &s->plic_irq[irq_num];\n        blk_dev = virtio_block_init(vbus, p->tab_drive[i].block_dev);\n        (void)blk_dev;\n        vbus->addr += VIRTIO_SIZE;\n        irq_num++;\n        s->virtio_count++;\n    }\n\n    /* virtio filesystem */\n    for(i = 0; i < p->fs_count; i++) {\n        VIRTIODevice *fs_dev;\n        vbus->irq = &s->plic_irq[irq_num];\n        fs_dev = virtio_9p_init(vbus, p->tab_fs[i].fs_dev,\n                                p->tab_fs[i].tag);\n        (void)fs_dev;\n        //        virtio_set_debug(fs_dev, VIRTIO_DEBUG_9P);\n        vbus->addr += VIRTIO_SIZE;\n        irq_num++;\n        s->virtio_count++;\n    }\n\n    if (p->display_device) {\n        FBDevice *fb_dev;\n        fb_dev = mallocz(sizeof(*fb_dev));\n        s->common.fb_dev = fb_dev;\n        if (!strcmp(p->display_device, \"simplefb\")) {\n            simplefb_init(s->mem_map,\n                          FRAMEBUFFER_BASE_ADDR,\n                          fb_dev,\n                          p->width, p->height);\n            \n        } else {\n            vm_error(\"unsupported display device: %s\\n\", p->display_device);\n            exit(1);\n        }\n    }\n\n    if (p->input_device) {\n        if (!strcmp(p->input_device, \"virtio\")) {\n            vbus->irq = &s->plic_irq[irq_num];\n            s->keyboard_dev = virtio_input_init(vbus,\n                                                VIRTIO_INPUT_TYPE_KEYBOARD);\n            vbus->addr += VIRTIO_SIZE;\n            irq_num++;\n            s->virtio_count++;\n\n            vbus->irq = &s->plic_irq[irq_num];\n            s->mouse_dev = virtio_input_init(vbus,\n                                             VIRTIO_INPUT_TYPE_TABLET);\n            vbus->addr += VIRTIO_SIZE;\n            irq_num++;\n            s->virtio_count++;\n        } else {\n            vm_error(\"unsupported input device: %s\\n\", p->input_device);\n            exit(1);\n        }\n    }\n    \n    if (!p->files[VM_FILE_BIOS].buf) {\n        vm_error(\"No bios found\");\n    }\n\n    if (p->files[VM_FILE_KERNEL].buf|| p->files[VM_FILE_INITRD].buf) {\n        copy_bios(s, p->files[VM_FILE_BIOS].buf, p->files[VM_FILE_BIOS].len,\n                  p->files[VM_FILE_KERNEL].buf, p->files[VM_FILE_KERNEL].len,\n                  p->files[VM_FILE_INITRD].buf, p->files[VM_FILE_INITRD].len,\n                  p->cmdline);\n    } else{\n        copy_kernel(s, p->files[VM_FILE_BIOS].buf, p->files[VM_FILE_BIOS].len,\n                p->cmdline);\n    }\n\n    /* We are booting TinyEMU in simulation mode */\n    if (p->sim_params->start_in_sim)\n    {\n        riscv_sim_cpu_start(s->cpu_state->simcpu, s->cpu_state->simcpu->pc);\n    }\n\n    return (VirtMachine *)s;\n}\n\nstatic void riscv_machine_end(VirtMachine *s1)\n{\n    RISCVMachine *s = (RISCVMachine *)s1;\n    /* XXX: stop all */\n\n    riscv_cpu_end(s->cpu_state);\n    rtc_free(&s->rtc);\n    sim_params_free(s->common.virt_machine_params->sim_params);\n    phys_mem_map_end(s->mem_map);\n    free(s);\n}\n\n/* in ms */\nstatic int riscv_machine_get_sleep_duration(VirtMachine *s1, int delay)\n{\n    RISCVMachine *m = (RISCVMachine *)s1;\n    RISCVCPUState *s = m->cpu_state;\n    int64_t delay1;\n    \n    /* wait for an event: the only asynchronous event is the RTC timer */\n    if (!(riscv_cpu_get_mip(s) & MIP_MTIP)) {\n        delay1 = m->timecmp - rtc_get_time(m);\n        if (delay1 <= 0) {\n            riscv_cpu_set_mip(s, MIP_MTIP);\n            delay = 0;\n        } else {\n            /* convert delay to ms */\n            delay1 = delay1 / (m->rtc->freq / 1000);\n            if (delay1 < delay)\n                delay = delay1;\n        }\n    }\n    if (!riscv_cpu_get_power_down(s))\n        delay = 0;\n    return delay;\n}\n\nstatic void riscv_machine_interp(VirtMachine *s1, int max_exec_cycle)\n{\n    RISCVMachine *s = (RISCVMachine *)s1;\n    riscv_cpu_interp(s->cpu_state, max_exec_cycle);\n}\n\nstatic void riscv_vm_send_key_event(VirtMachine *s1, BOOL is_down,\n                                    uint16_t key_code)\n{\n    RISCVMachine *s = (RISCVMachine *)s1;\n    if (s->keyboard_dev) {\n        virtio_input_send_key_event(s->keyboard_dev, is_down, key_code);\n    }\n}\n\nstatic BOOL riscv_vm_mouse_is_absolute(VirtMachine *s)\n{\n    return TRUE;\n}\n\nstatic void riscv_vm_send_mouse_event(VirtMachine *s1, int dx, int dy, int dz,\n                                      unsigned int buttons)\n{\n    RISCVMachine *s = (RISCVMachine *)s1;\n    if (s->mouse_dev) {\n        virtio_input_send_mouse_event(s->mouse_dev, dx, dy, dz, buttons);\n    }\n}\n\nconst VirtMachineClass riscv_machine_class = {\n    \"riscv32,riscv64,riscv128\",\n    riscv_machine_set_defaults,\n    riscv_machine_init,\n    riscv_machine_end,\n    riscv_machine_get_sleep_duration,\n    riscv_machine_interp,\n    riscv_vm_mouse_is_absolute,\n    riscv_vm_send_mouse_event,\n    riscv_vm_send_key_event,\n};\n"
  },
  {
    "path": "src/riscvsim/bpu/adaptive_predictor.c",
    "content": "/**\n * Adaptive Predictor\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <math.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"adaptive_predictor.h\"\n#include \"../utils/sim_log.h\"\n\n#define GAG 0x0\n#define GAP 0x1\n#define PAG 0x2\n#define PAP 0x3\n\nconst char *ap_type_str[] = {\"GAG\", \"GAP\", \"PAG\", \"PAP\"};\nconst char *ap_alias_func_type_str[] = {\"XOR\", \"AND\", \"NONE\"};\n\n#define UPDATE_GHR(ghr, bits, pred) (GET_INDEX((((ghr) << 1) | (pred)), (bits)))\n\n#define PRED_NOT_TAKEN 0x0\n#define PRED_TAKEN 0x1\n\nstatic uint32_t\nxor_aliasing_func(const AdaptivePredictor *a, uint32_t hr, target_ulong pc)\n{\n    return GET_INDEX(hr ^ pc, a->hreg_bits);\n}\n\nstatic uint32_t\nand_aliasing_func(const AdaptivePredictor *a, uint32_t hr, target_ulong pc)\n{\n    return GET_INDEX(hr & pc, a->hreg_bits);\n}\n\nstatic uint32_t\nnone_aliasing_func(const AdaptivePredictor *a, uint32_t hr, target_ulong pc)\n{\n    return GET_INDEX(hr, a->hreg_bits);\n}\n\nstatic void\nupdate_two_bit_counter(int *ctr, int pred)\n{\n    if (pred)\n    {\n        if ((*ctr >= 0) && (*ctr < 3))\n        {\n            (*ctr)++;\n        }\n    }\n    else\n    {\n        if ((*ctr >= 1) && (*ctr <= 3))\n        {\n            (*ctr)--;\n        }\n    }\n}\n\n/* Returns BPU_HIT if given pc is present in GHT */\nstatic int\nadaptive_predictor_ght_probe(const AdaptivePredictor *a, target_ulong pc)\n{\n    int index = GET_INDEX(pc >> 1, a->ght_index_bits);\n\n    if (a->ght[index].pc == pc)\n    {\n        return BPU_HIT;\n    }\n\n    return BPU_MISS;\n}\n\n/* Returns BPU_HIT if given pc is present in PHT */\nstatic int\nadaptive_predictor_pht_probe(const AdaptivePredictor *a, target_ulong pc)\n{\n    int index = GET_INDEX(pc >> 1, a->pht_index_bits);\n\n    if (a->pht[index].pc == pc)\n    {\n        return BPU_HIT;\n    }\n\n    return BPU_MISS;\n}\n\nstatic void\nadaptive_predictor_log_config(const AdaptivePredictor *a)\n{\n    sim_log_event_to_file(sim_log, \"%s\", \"Setting up adaptive predictor\");\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"type\", ap_type_str[a->type]);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"ght_size\", a->ght_size);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"pht_size\", a->pht_size);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"ght_index_bits\", a->ght_index_bits);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"pht_index_bits\", a->pht_index_bits);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"history_bits\", a->hreg_bits);\n\n    if (a->type == GAG)\n    {\n        sim_log_param_to_file(sim_log, \"%s: %s\", \"alias_func_type\",\n                      ap_alias_func_type_str[a->alias_func_type]);\n    }\n}\n\n/**\n * Based on the adaptive predictor scheme, probe either GHT\n * or PHT or both.\n */\nint\nadaptive_predictor_probe(const AdaptivePredictor *a, target_ulong pc)\n{\n    switch (a->type)\n    {\n        case GAG:\n        {\n            return BPU_HIT;\n        }\n        case GAP:\n        {\n            return adaptive_predictor_pht_probe(a, pc);\n        }\n        case PAG:\n        {\n            return adaptive_predictor_ght_probe(a, pc);\n        }\n        case PAP:\n        {\n            return (adaptive_predictor_ght_probe(a, pc)\n                    && adaptive_predictor_pht_probe(a, pc));\n        }\n    }\n\n    sim_assert((0), \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n               __func__, \"invalid adaptive predictor type\");\n    return 0;\n}\n\n/**\n * Based on the adaptive predictor scheme, return the\n * prediction.\n */\nint\nadaptive_predictor_get_prediction(const AdaptivePredictor *a, target_ulong pc)\n{\n    int l1_index;\n    int l2_index;\n    uint32_t ghr;\n\n    switch (a->type)\n    {\n        case GAG:\n        {\n            ghr = GET_INDEX(a->ght[0].ghr, a->hreg_bits);\n\n            /* Apply aliasing function for Gshare and Gselect */\n            ghr = a->pfn_ap_aliasing_func(a, ghr, pc >> 2);\n            if (a->pht[0].ctr[ghr] > 1)\n            {\n                return 1;\n            }\n            return 0;\n        }\n        case GAP:\n        {\n            ghr = GET_INDEX(a->ght[0].ghr, a->hreg_bits);\n            l2_index = GET_INDEX(pc >> 1, a->pht_index_bits);\n            if (a->pht[l2_index].ctr[ghr] > 1)\n            {\n                return 1;\n            }\n            return 0;\n        }\n        case PAG:\n        {\n            l1_index = GET_INDEX(pc >> 1, a->ght_index_bits);\n            ghr = GET_INDEX(a->ght[l1_index].ghr, a->hreg_bits);\n            if (a->pht[0].ctr[ghr] > 1)\n            {\n                return 1;\n            }\n            return 0;\n        }\n        case PAP:\n        {\n            l1_index = GET_INDEX(pc >> 1, a->ght_index_bits);\n            l2_index = GET_INDEX(pc >> 1, a->pht_index_bits);\n            ghr = GET_INDEX(a->ght[l1_index].ghr, a->hreg_bits);\n            if (a->pht[l2_index].ctr[ghr] > 1)\n            {\n                return 1;\n            }\n            return 0;\n        }\n    }\n\n    assert(0);\n    return 0;\n}\n\n/**\n * Based on the adaptive predictor scheme, allocate the entries in GHT or\n * PHT or both.\n *\n * History register in the allocated GHT entry is set to 0.\n * 2-bit saturating counter array in the allocated PHT entry get default values\n * of 0 (strongly not taken).\n */\nvoid\nadaptive_predictor_add(AdaptivePredictor *a, target_ulong pc)\n{\n    int l1_index;\n    int l2_index;\n\n    switch (a->type)\n    {\n        case GAG:\n        {\n            break;\n        }\n        case GAP:\n        {\n            l2_index = GET_INDEX(pc >> 1, a->pht_index_bits);\n            a->pht[l2_index].pc = pc;\n            memset(a->pht[l2_index].ctr, 0, sizeof(int) * (1 << a->hreg_bits));\n            break;\n        }\n        case PAG:\n        {\n            l1_index = GET_INDEX(pc >> 1, a->ght_index_bits);\n            a->ght[l1_index].pc = pc;\n            a->ght[l1_index].ghr = 0;\n            break;\n        }\n        case PAP:\n        {\n            l1_index = GET_INDEX(pc >> 1, a->ght_index_bits);\n            l2_index = GET_INDEX(pc >> 1, a->pht_index_bits);\n            a->ght[l1_index].pc = pc;\n            a->ght[l1_index].ghr = 0;\n            a->pht[l2_index].pc = pc;\n            memset(a->pht[l2_index].ctr, 0, sizeof(int) * (1 << a->hreg_bits));\n            break;\n        }\n    }\n}\n\n/**\n * Based on the adaptive predictor scheme, update the entries in GHT or\n * PHT or both. First update the 2-bit saturating counter in PHT and then\n * update history register in GHT. Update to history register is performed\n * by left-shifting the current branch outcome into its previous value.\n */\nvoid\nadaptive_predictor_update(AdaptivePredictor *a, target_ulong pc, int pred)\n{\n    int l1_index;\n    int l2_index;\n    uint32_t ghr;\n\n    switch (a->type)\n    {\n        case GAG:\n        {\n            ghr = GET_INDEX(a->ght[0].ghr, a->hreg_bits);\n\n            /* Apply aliasing function for Gshare and Gselect */\n            ghr = a->pfn_ap_aliasing_func(a, ghr, pc >> 2);\n            update_two_bit_counter(&a->pht[0].ctr[ghr], pred);\n            a->ght[0].ghr = UPDATE_GHR(a->ght[0].ghr, a->hreg_bits, pred);\n            break;\n        }\n        case GAP:\n        {\n            ghr = GET_INDEX(a->ght[0].ghr, a->hreg_bits);\n            l2_index = GET_INDEX(pc >> 1, a->pht_index_bits);\n            update_two_bit_counter(&a->pht[l2_index].ctr[ghr], pred);\n            a->ght[0].ghr = UPDATE_GHR(a->ght[0].ghr, a->hreg_bits, pred);\n            break;\n        }\n        case PAG:\n        {\n            l1_index = GET_INDEX(pc >> 1, a->ght_index_bits);\n            ghr = GET_INDEX(a->ght[l1_index].ghr, a->hreg_bits);\n            update_two_bit_counter(&a->pht[0].ctr[ghr], pred);\n            a->ght[l1_index].ghr\n                = UPDATE_GHR(a->ght[l1_index].ghr, a->hreg_bits, pred);\n            break;\n        }\n        case PAP:\n        {\n            l1_index = GET_INDEX(pc >> 1, a->ght_index_bits);\n            ghr = GET_INDEX(a->ght[l1_index].ghr, a->hreg_bits);\n            l2_index = GET_INDEX(pc >> 1, a->pht_index_bits);\n            update_two_bit_counter(&a->pht[l2_index].ctr[ghr], pred);\n            a->ght[l1_index].ghr\n                = UPDATE_GHR(a->ght[l1_index].ghr, a->hreg_bits, pred);\n            break;\n        }\n    }\n}\n\nvoid\nadaptive_predictor_flush(AdaptivePredictor *a)\n{\n    int i;\n\n    memset(a->ght, 0, a->ght_size * sizeof(GHTEntry));\n    for (i = 0; i < a->pht_size; ++i)\n    {\n        a->pht[i].pc = 0;\n        memset(a->pht[i].ctr, 0, sizeof(int) * (1 << a->hreg_bits));\n    }\n}\n\nAdaptivePredictor *\nadaptive_predictor_init(const SimParams *p)\n{\n    int i;\n    AdaptivePredictor *a;\n\n    a = (AdaptivePredictor *)calloc(1, sizeof(AdaptivePredictor));\n    assert(a);\n\n    /* Create GHT */\n    a->ght = (GHTEntry *)malloc(sizeof(GHTEntry) * p->bpu_ght_size);\n    assert(a->ght);\n    a->ght_size = p->bpu_ght_size;\n    a->ght_index_bits = GET_NUM_BITS(p->bpu_ght_size);\n    a->hreg_bits = p->bpu_history_bits;\n    memset(a->ght, 0, a->ght_size * sizeof(GHTEntry));\n\n    /* Create PHT */\n    a->pht = (PHTEntry *)malloc(sizeof(PHTEntry) * p->bpu_pht_size);\n    assert(a->pht);\n    a->pht_size = p->bpu_pht_size;\n    a->pht_index_bits = GET_NUM_BITS(p->bpu_pht_size);\n    memset(a->pht, 0, a->pht_size * sizeof(PHTEntry));\n    for (i = 0; i < a->pht_size; ++i)\n    {\n        a->pht[i].ctr = (int *)malloc(sizeof(int) * (1 << a->hreg_bits));\n        assert(a->pht[i].ctr);\n        memset(a->pht[i].ctr, 0, sizeof(int) * (1 << a->hreg_bits));\n    }\n    a->alias_func_type = p->bpu_aliasing_func_type;\n    a->pfn_ap_aliasing_func = NULL;\n    /* Set prediction scheme */\n    if ((a->ght_size == 1) && (a->pht_size == 1))\n    {\n        a->type = GAG;\n\n        /* For GAg based scheme, setup aliasing function to be used (For Gshare\n         * and Gselect predictors) */\n        switch (p->bpu_aliasing_func_type)\n        {\n            case BPU_ALIAS_FUNC_XOR:\n            {\n                a->pfn_ap_aliasing_func = &xor_aliasing_func;\n                break;\n            }\n            case BPU_ALIAS_FUNC_AND:\n            {\n                a->pfn_ap_aliasing_func = &and_aliasing_func;\n                break;\n            }\n            case BPU_ALIAS_FUNC_NONE:\n            {\n                a->pfn_ap_aliasing_func = &none_aliasing_func;\n                break;\n            }\n        }\n    }\n\n    if ((a->ght_size == 1) && (a->pht_size > 1))\n    {\n        a->type = GAP;\n    }\n    if ((a->ght_size > 1) && (a->pht_size == 1))\n    {\n        a->type = PAG;\n    }\n    if ((a->ght_size > 1) && (a->pht_size > 1))\n    {\n        a->type = PAP;\n    }\n\n    adaptive_predictor_log_config(a);\n    return a;\n}\n\nvoid\nadaptive_predictor_free(AdaptivePredictor **a)\n{\n    int i;\n\n    for (i = 0; i < (*a)->pht_size; ++i)\n    {\n        free((*a)->pht[i].ctr);\n        (*a)->pht[i].ctr = NULL;\n    }\n    free((*a)->pht);\n    (*a)->pht = NULL;\n    free((*a)->ght);\n    (*a)->ght = NULL;\n    free(*a);\n    *a = NULL;\n}"
  },
  {
    "path": "src/riscvsim/bpu/adaptive_predictor.h",
    "content": "/**\n * Adaptive Predictor\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _ADAPTIVE_PREDICTOR_H_\n#define _ADAPTIVE_PREDICTOR_H_\n\n#include \"../riscv_sim_typedefs.h\"\n#include \"../utils/sim_params.h\"\n\n/* Adaptive Predictor Level 1: Global History Table (GHT) Entry */\ntypedef struct GHTEntry\n{\n    target_ulong pc; /* Virtual address of the branch */\n    uint32_t ghr;    /* History register */\n} GHTEntry;\n\n/* Adaptive Predictor Level 2: Pattern History Table (PHT) Entry */\ntypedef struct PHTEntry\n{\n    target_ulong pc; /* Virtual address of the branch */\n    int *ctr;        /* Array of 2-bit saturating counters */\n} PHTEntry;\n\ntypedef struct AdaptivePredictor\n{\n    GHTEntry *ght;           /* GHT */\n    PHTEntry *pht;           /* PHT */\n    int ght_size;            /* Number of entries in GHT */\n    int pht_size;            /* Number of entries in PHT */\n    uint32_t ght_index_bits; /* Number of lowest bits of PC required to index\n                                into GHT */\n    uint32_t pht_index_bits; /* Number of lowest bits of PC required to index\n                                into PHT */\n\n    /* Number of bits in history register present in GHT entry */\n    uint32_t hreg_bits;\n\n    /* Type of adaptive predictor scheme used (GAg, GAp, PAg, PAp), based on\n     * ght_size and pht_size*/\n    int type;\n\n    /* Type of aliasing function (and, xor or none) to apply for GAg based\n     * schemes */\n    int alias_func_type;\n    uint32_t (*pfn_ap_aliasing_func)(const struct AdaptivePredictor *a,\n                                     uint32_t hr, target_ulong pc);\n} AdaptivePredictor;\n\nAdaptivePredictor *adaptive_predictor_init(const SimParams *p);\nvoid adaptive_predictor_free(AdaptivePredictor **a);\nvoid adaptive_predictor_add(AdaptivePredictor *a, target_ulong pc);\nvoid adaptive_predictor_update(AdaptivePredictor *a, target_ulong pc, int pred);\nvoid adaptive_predictor_flush(AdaptivePredictor *a);\nint adaptive_predictor_probe(const AdaptivePredictor *a, target_ulong pc);\nint adaptive_predictor_get_prediction(const AdaptivePredictor *a,\n                                      target_ulong pc);\n#endif\n"
  },
  {
    "path": "src/riscvsim/bpu/bht.c",
    "content": "/**\n * Branch History Table\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <math.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../riscv_sim_macros.h\"\n#include \"../utils/sim_log.h\"\n#include \"bht.h\"\n\nstatic void\nbht_log_config(const Bht *b)\n{\n    sim_log_event_to_file(sim_log, \"%s\", \"Setting up branch history table (bht)\");\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"size\", b->bht_size);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"index_bits\", b->bht_index_bits);\n}\n\nstatic void\nupdate_two_bit_counter(int *ctr, int pred)\n{\n    if (pred)\n    {\n        if ((*ctr >= 0) && (*ctr < 3))\n        {\n            (*ctr)++;\n        }\n    }\n    else\n    {\n        if ((*ctr >= 1) && (*ctr <= 3))\n        {\n            (*ctr)--;\n        }\n    }\n}\n\nint\nbht_get_prediction(const Bht *b, target_ulong pc)\n{\n    int idx;\n\n    idx = GET_INDEX(pc, b->bht_index_bits);\n    return b->bht_entry[idx].pred;\n}\n\nvoid\nbht_add(Bht *b, target_ulong pc)\n{\n    int idx;\n\n    /* In case of bimodal predictor, set the 2-bit saturating counter to 1\n     * (Not taken) */\n    idx = GET_INDEX(pc, b->bht_index_bits);\n    b->bht_entry[idx].pred = 1;\n}\n\nvoid\nbht_update(Bht *b, target_ulong pc, int pred)\n{\n    int idx;\n\n    idx = GET_INDEX(pc, b->bht_index_bits);\n    update_two_bit_counter(&b->bht_entry[idx].pred, pred);\n}\n\nvoid\nbht_flush(Bht *b)\n{\n    int i;\n\n    for (i = 0; i < b->bht_size; ++i)\n    {\n        b->bht_entry[i].pred = 1;\n    }\n}\n\nBht *\nbht_init(const SimParams *p)\n{\n    Bht *b;\n\n    b = calloc(1, sizeof(Bht));\n    assert(b);\n\n    b->bht_size = p->bht_size;\n    b->bht_entry = calloc(b->bht_size, sizeof(BhtEntry));\n    assert(b->bht_entry);\n\n    b->bht_index_bits = GET_NUM_BITS(b->bht_size);\n    bht_log_config(b);\n    return b;\n}\n\nvoid\nbht_free(Bht **b)\n{\n    free((*b)->bht_entry);\n    (*b)->bht_entry = NULL;\n    free(*b);\n    *b = NULL;\n}\n"
  },
  {
    "path": "src/riscvsim/bpu/bht.h",
    "content": "/**\n * Branch History Table\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _BHT_H_\n#define _BHT_H_\n\n#include \"../riscv_sim_typedefs.h\"\n#include \"../utils/sim_params.h\"\n\ntypedef struct BhtEntry\n{\n    int pred;\n} BhtEntry;\n\ntypedef struct Bht\n{\n    BhtEntry *bht_entry;\n    int bht_index_bits;\n    int bht_size;\n} Bht;\n\nBht *bht_init(const SimParams *p);\nint bht_get_prediction(const Bht *b, target_ulong pc);\nvoid bht_add(Bht *b, target_ulong pc);\nvoid bht_update(Bht *b, target_ulong pc, int pred);\nvoid bht_flush(Bht *b);\nvoid bht_free(Bht **b);\n#endif\n"
  },
  {
    "path": "src/riscvsim/bpu/bpu.c",
    "content": "/**\n * Branch Prediction Unit\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"bpu.h\"\n#include \"../utils/sim_log.h\"\n\nvoid\nbpu_flush(BranchPredUnit *u)\n{\n    btb_flush(u->btb);\n\n    switch (u->bpu_type)\n    {\n        case BPU_TYPE_BIMODAL:\n        {\n            bht_flush(u->bht);\n            break;\n        }\n\n        case BPU_TYPE_ADAPTIVE:\n        {\n            adaptive_predictor_flush(u->ap);\n            break;\n        }\n    }\n\n    if (u->ras)\n    {\n        ras_flush(u->ras);\n    }\n}\n\n/* Probes the BPU for given pc. */\nvoid\nbpu_probe(BranchPredUnit *u, target_ulong pc, BPUResponsePkt *p, int priv)\n{\n    /* Check if the PC is present in BTB */\n    p->btb_probe_status = btb_probe(u->btb, pc, &p->btb_entry);\n    ++(u->stats[priv].btb_probes);\n\n    if (p->btb_probe_status == BPU_HIT)\n    {\n        ++(u->stats[priv].btb_hits);\n    }\n\n    switch (u->bpu_type)\n    {\n        case BPU_TYPE_BIMODAL:\n        {\n            p->ap_probe_status = BPU_HIT;\n            break;\n        }\n\n        case BPU_TYPE_ADAPTIVE:\n        {\n            p->ap_probe_status = adaptive_predictor_probe(u->ap, pc);\n\n            if (p->btb_probe_status == BPU_HIT)\n            {\n                /* If the PC present in BTB is a unconditional branch, mark\n                 * ap_probe_status as HIT */\n                if (p->btb_entry->type == BRANCH_UNCOND)\n                {\n                    p->ap_probe_status = BPU_HIT;\n                }\n            }\n            break;\n        }\n    }\n\n    p->bpu_probe_status = p->btb_probe_status & p->ap_probe_status;\n}\n\n/**\n * Returns the target address for this pc. Predictions for conditional branches\n * are checked before returning the target address. If prediction is\n * taken,target address is returned, else 0 is returned.\n */\ntarget_ulong\nbpu_get_target(BranchPredUnit *u, target_ulong pc, BtbEntry *btb_entry)\n{\n    switch (btb_entry->type)\n    {\n        case BRANCH_UNCOND:\n        {\n            /* No need to check prediction for unconditional branches, so\n               directly return target address. */\n            return btb_entry->target;\n        }\n\n        case BRANCH_COND:\n        {\n            /* Must check prediction for conditional branches, so if prediction\n               is taken return the target address, else return 0. */\n            switch (u->bpu_type)\n            {\n                case BPU_TYPE_BIMODAL:\n                {\n                    if (bht_get_prediction(u->bht, pc) > 1)\n                    {\n                        return btb_entry->target;\n                    }\n                    break;\n                }\n\n                case BPU_TYPE_ADAPTIVE:\n                {\n                    if (adaptive_predictor_get_prediction(u->ap, pc))\n                    {\n                        return btb_entry->target;\n                    }\n                    break;\n                }\n            }\n            break;\n        }\n    }\n\n    /* BPU Hit, but prediction is not-taken */\n    return 0;\n}\n\nvoid\nbpu_add(BranchPredUnit *u, target_ulong pc, int type, BPUResponsePkt *p,\n        int priv, int fret)\n{\n    /* All the branches are allocated BTB entry */\n    if (!p->btb_probe_status)\n    {\n        /* If using return address stack, don't add function returns to BTB */\n        if (u->ras && fret)\n        {\n            return;\n        }\n\n        btb_add(u->btb, pc, type);\n        ++(u->stats[priv].btb_inserts);\n    }\n\n    switch (u->bpu_type)\n    {\n        case BPU_TYPE_BIMODAL:\n        {\n            if (type == BRANCH_COND)\n            {\n                bht_add(u->bht, pc);\n            }\n            break;\n        }\n\n        case BPU_TYPE_ADAPTIVE:\n        {\n            /* If BPU is using adaptive predictor, then PC must also be added in\n             * adaptive predictor structures, but only for conditional branches\n             */\n            if ((type == BRANCH_COND) && !p->ap_probe_status)\n            {\n                adaptive_predictor_add(u->ap, pc);\n            }\n            break;\n        }\n    }\n}\n\nvoid\nbpu_update(BranchPredUnit *u, target_ulong pc, target_ulong target, int pred,\n           int type, BPUResponsePkt *p, int priv)\n{\n    if (p->btb_probe_status)\n    {\n        btb_update(p->btb_entry, target, type);\n        ++(u->stats[priv].btb_updates);\n    }\n\n    switch (u->bpu_type)\n    {\n        case BPU_TYPE_BIMODAL:\n        {\n            if (type == BRANCH_COND)\n            {\n                bht_update(u->bht, pc, pred);\n            }\n            break;\n        }\n\n        case BPU_TYPE_ADAPTIVE:\n        {\n            /* If BPU is using adaptive predictor, adaptive predictor structures\n             * must be also be updated, but only for conditional branches */\n            if ((type == BRANCH_COND) && p->ap_probe_status)\n            {\n                adaptive_predictor_update(u->ap, pc, pred);\n            }\n            break;\n        }\n    }\n}\n\nBranchPredUnit *\nbpu_init(const SimParams *p, SimStats *s)\n{\n    BranchPredUnit *u;\n\n    u = (BranchPredUnit *)calloc(1, sizeof(BranchPredUnit));\n    assert(u);\n    u->btb = NULL;\n    u->bht = NULL;\n    u->ap = NULL;\n    u->ras = NULL;\n    u->stats = s;\n    u->btb = btb_init(p);\n    u->bpu_type = p->bpu_type;\n\n    switch (u->bpu_type)\n    {\n        case BPU_TYPE_BIMODAL:\n        {\n            u->bht = bht_init(p);\n            break;\n        }\n\n        case BPU_TYPE_ADAPTIVE:\n        {\n            u->ap = adaptive_predictor_init(p);\n            break;\n        }\n    }\n\n    if (p->ras_size)\n    {\n        u->ras = ras_init(p);\n    }\n\n    return u;\n}\n\nvoid\nbpu_free(BranchPredUnit **u)\n{\n    btb_free(&(*u)->btb);\n\n    switch ((*u)->bpu_type)\n    {\n        case BPU_TYPE_BIMODAL:\n        {\n            bht_free(&(*u)->bht);\n            break;\n        }\n\n        case BPU_TYPE_ADAPTIVE:\n        {\n            adaptive_predictor_free(&(*u)->ap);\n            break;\n        }\n    }\n\n    if ((*u)->ras)\n    {\n        ras_free(&(*u)->ras);\n    }\n\n    free(*u);\n    *u = NULL;\n}"
  },
  {
    "path": "src/riscvsim/bpu/bpu.h",
    "content": "/**\n * Branch Prediction Unit\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _BRANCH_PRED_UNIT_H_\n#define _BRANCH_PRED_UNIT_H_\n\n#include <assert.h>\n#include <inttypes.h>\n#include <math.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../riscv_sim_typedefs.h\"\n#include \"../utils/sim_params.h\"\n#include \"../utils/sim_stats.h\"\n#include \"adaptive_predictor.h\"\n#include \"bht.h\"\n#include \"btb.h\"\n#include \"ras.h\"\n\ntypedef struct BPUResponsePkt\n{\n    int btb_probe_status;\n    int ap_probe_status;\n    int bpu_probe_status;\n    BtbEntry *btb_entry;\n} BPUResponsePkt;\n\ntypedef struct BranchPredUnit\n{\n    BranchTargetBuffer *btb;\n    Bht *bht;\n    Ras *ras;\n    AdaptivePredictor *ap;\n    SimStats *stats;\n\n    /* Predictor type: bimodal or adaptive */\n    int bpu_type;\n} BranchPredUnit;\n\nBranchPredUnit *bpu_init(const SimParams *p, SimStats *s);\ntarget_ulong bpu_get_target(BranchPredUnit *u, target_ulong pc,\n                            BtbEntry *btb_entry);\nvoid bpu_probe(BranchPredUnit *u, target_ulong pc, BPUResponsePkt *p, int priv);\nvoid bpu_add(BranchPredUnit *u, target_ulong pc, int type, BPUResponsePkt *p,\n             int priv, int fret);\nvoid bpu_update(BranchPredUnit *u, target_ulong pc, target_ulong target,\n                int pred, int type, BPUResponsePkt *p, int priv);\nvoid bpu_flush(BranchPredUnit *u);\nvoid bpu_free(BranchPredUnit **u);\n#endif\n"
  },
  {
    "path": "src/riscvsim/bpu/btb.c",
    "content": "/**\n * Branch Target Buffer\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <math.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../utils/sim_log.h\"\n#include \"btb.h\"\n\nstatic void\nbtb_log_config(const BranchTargetBuffer *b)\n{\n    sim_log_event_to_file(sim_log, \"%s\", \"Setting up branch target buffer (BTB)\");\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"size\", b->size);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"sets\", b->sets);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"set_bits\", b->set_bits);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"ways\", b->ways);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"evict_policy\",\n                  evict_policy_str[b->evict_policy->type]);\n}\n\nvoid\nbtb_flush(BranchTargetBuffer *b)\n{\n    int i;\n\n    b->evict_policy->reset(b->evict_policy);\n    for (i = 0; i < b->sets; ++i)\n    {\n        memset((void *)b->data[i], 0, b->ways * sizeof(BtbEntry));\n    }\n}\n\n/**\n * Returns BPU_HIT if the given pc is present in the BTB and assign address of\n * the BTB entry containing this PC to the out parameter (btb_entry), else\n * return BPU_MISS\n */\nint\nbtb_probe(BranchTargetBuffer *b, target_ulong pc, BtbEntry **btb_entry)\n{\n    int j;\n    int set_addr = GET_SET_ADDR(pc >> 1, b->set_bits);\n\n    *btb_entry = NULL;\n\n    for (j = 0; j < b->ways; ++j)\n    {\n        if (b->data[set_addr][j].pc == pc)\n        {\n            /* BTB Hit */\n            b->evict_policy->use(b->evict_policy, set_addr, j);\n            *btb_entry = &(b->data[set_addr][j]);\n            return BPU_HIT;\n        }\n    }\n\n    /* BTB Miss */\n    return BPU_MISS;\n}\n\n/**\n * Allocates an entry for the given pc in BTB, after evicting\n * the entry in it's place. This is done from the decode stage\n * of the pipeline.\n */\nvoid\nbtb_add(BranchTargetBuffer *b, target_ulong pc, int type)\n{\n    int set_addr = GET_SET_ADDR(pc >> 1, b->set_bits);\n    int pos = b->evict_policy->evict(b->evict_policy, set_addr);\n\n    // assert(pos >= 0 && pos < b->ways);\n    b->data[set_addr][pos].pc = pc;\n    b->data[set_addr][pos].target = 0;\n    b->data[set_addr][pos].type = type;\n    b->evict_policy->use(b->evict_policy, set_addr, pos);\n}\n\n/**\n * Updates entry for the given pc in BTB with the target address and\n * the branch outcome. This is done from the memory stage of the pipeline,\n * where the branches are resolved.\n */\nvoid\nbtb_update(BtbEntry *btb_entry, target_ulong target, int type)\n{\n    btb_entry->target = target;\n    btb_entry->type = type;\n}\n\nBranchTargetBuffer *\nbtb_init(const SimParams *p)\n{\n    int i;\n    BranchTargetBuffer *b;\n\n    b = (BranchTargetBuffer *)calloc(1, sizeof(BranchTargetBuffer));\n    assert(b);\n    b->size = p->btb_size;\n    b->sets = b->size / p->btb_ways;\n    b->ways = p->btb_ways;\n    b->set_bits = GET_NUM_BITS(b->sets);\n    b->evict_policy\n        = evict_policy_create(b->sets, b->ways, p->btb_eviction_policy);\n    b->data = (BtbEntry **)calloc(b->sets, sizeof(BtbEntry *));\n    assert(b->data);\n    for (i = 0; i < b->sets; ++i)\n    {\n        b->data[i] = (BtbEntry *)calloc(b->ways, sizeof(BtbEntry));\n        assert(b->data[i]);\n    }\n    btb_log_config(b);\n    return b;\n}\n\nvoid\nbtb_free(BranchTargetBuffer **b)\n{\n    int i;\n\n    for (i = 0; i < (*b)->sets; ++i)\n    {\n        free((*b)->data[i]);\n        (*b)->data[i] = NULL;\n    }\n    free((*b)->data);\n    (*b)->data = NULL;\n    evict_policy_free(&(*b)->evict_policy);\n    free(*b);\n    *b = NULL;\n}"
  },
  {
    "path": "src/riscvsim/bpu/btb.h",
    "content": "/**\n * Branch Target Buffer\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _BRANCH_TARGET_BUFFER_H_\n#define _BRANCH_TARGET_BUFFER_H_\n\n#include \"../riscv_sim_typedefs.h\"\n#include \"../utils/evict_policy.h\"\n#include \"../utils/sim_params.h\"\n\ntypedef struct BtbEntry\n{\n    target_ulong pc;     /* Virtual address of this branch */\n    target_ulong target; /* Target of this branch */\n    int type;            /* Type of branch, BRANCH_COND or BRANCH_UNCOND */\n} BtbEntry;\n\ntypedef struct BranchTargetBuffer\n{\n    BtbEntry **data;\n    int size;          /* Number of entries in BTB */\n    int sets;          /* Number of BTB sets */\n    uint32_t set_bits; /* Number of bit required to index into a set */\n    int ways;          /* Number of ways in each set */\n    EvictPolicy *evict_policy;\n} BranchTargetBuffer;\n\nBranchTargetBuffer *btb_init(const SimParams *p);\nint btb_probe(BranchTargetBuffer *b, target_ulong pc, BtbEntry **btb_entry);\nvoid btb_add(BranchTargetBuffer *b, target_ulong pc, int type);\nvoid btb_update(BtbEntry *btb_entry, target_ulong target, int type);\nvoid btb_free(BranchTargetBuffer **b);\nvoid btb_flush(BranchTargetBuffer *b);\nvoid btb_free(BranchTargetBuffer **b);\n#endif\n"
  },
  {
    "path": "src/riscvsim/bpu/ras.c",
    "content": "/**\n * Return address stack\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdlib.h>\n\n#include \"../utils/sim_log.h\"\n#include \"ras.h\"\n\nstatic void\nras_log_config(const Ras *ras)\n{\n    sim_log_event_to_file(sim_log, \"%s\", \"Setting up return address stack (RAS)\");\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"size\", ras->max_size);\n}\n\nvoid\nras_flush(Ras *ras)\n{\n    ras->cur_size = 0;\n    ras->sptop = ras->max_size - 1;\n    ras->spfill = 0;\n    ras->empty_reg = 0;\n}\n\nint\nras_empty(const Ras *ras)\n{\n    return (!ras->cur_size);\n}\n\nvoid\nras_push(Ras *ras, target_ulong pc)\n{\n    ras->entry[ras->spfill] = pc;\n    ras->sptop = ras->spfill;\n    ras->spfill++;\n    ras->cur_size++;\n\n    /* Overflow */\n    if (ras->spfill >= ras->max_size)\n    {\n        ras->spfill = 0;\n    }\n}\n\ntarget_ulong\nras_pop(Ras *ras)\n{\n    target_ulong ret_addr;\n\n    if (ras_empty(ras))\n    {\n        /* For empty RAS, return the last popped address in RAS empty register*/\n        return ras->empty_reg;\n    }\n\n    ret_addr = ras->entry[ras->sptop];\n    ras->spfill = ras->sptop;\n    ras->sptop--;\n    ras->cur_size--;\n\n    /* Underflow */\n    if (ras->sptop < 0)\n    {\n        ras->sptop = ras->max_size - 1;\n    }\n\n    /* save pop address into empty register */\n    ras->empty_reg = ret_addr;\n    return ret_addr;\n}\n\nRas *\nras_init(const SimParams *p)\n{\n    Ras *r;\n\n    r = calloc(1, sizeof(Ras));\n    assert(r);\n\n    r->entry = calloc(p->ras_size, sizeof(target_ulong));\n    assert(r->entry);\n\n    r->max_size = p->ras_size;\n    ras_flush(r);\n    ras_log_config(r);\n    return r;\n}\n\nvoid\nras_free(Ras **ras)\n{\n    free((*ras)->entry);\n    (*ras)->entry = NULL;\n\n    free(*ras);\n    *ras = NULL;\n}"
  },
  {
    "path": "src/riscvsim/bpu/ras.h",
    "content": "/**\n * Return address stack\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _RAS_H_\n#define _RAS_H_\n\n#include \"../riscv_sim_macros.h\"\n#include \"../riscv_sim_typedefs.h\"\n#include \"../utils/sim_params.h\"\n\ntypedef struct Ras\n{\n    int sptop;\n    int spfill;\n    int cur_size;\n    int max_size;\n    target_ulong empty_reg;\n    target_ulong *entry;\n} Ras;\n\nRas *ras_init(const SimParams *p);\ntarget_ulong ras_pop(Ras *ras);\nint ras_empty(const Ras *ras);\nvoid ras_push(Ras *ras, target_ulong pc);\nvoid ras_flush(Ras *ras);\nvoid ras_free(Ras **ras);\n#endif\n"
  },
  {
    "path": "src/riscvsim/core/inorder.c",
    "content": "/**\n * Contains top-level routines to manage the in-order core\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/time.h>\n\n#include \"../../cutils.h\"\n#include \"../../riscv_cpu_priv.h\"\n#include \"../utils/circular_queue.h\"\n#include \"../utils/sim_log.h\"\n#include \"inorder.h\"\n#include \"riscv_sim_cpu.h\"\n\nstatic void\nin_core_log_config(const INCore *core)\n{\n    sim_log_event_to_file(sim_log, \"%s\", \"Setting up in-order RISC-V core\");\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"core_id\", core->simcpu->core_id);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"core_name\",\n                  core->simcpu->params->core_name);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"core_type\",\n                  core_type_str[core->simcpu->params->core_type]);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"num_cpu_stages\",\n                  core->simcpu->params->num_cpu_stages);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"num_data_fwd_buses\", NUM_FWD_BUS);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"ex_to_mem_selector_queue_size\",\n                  INCORE_EX_TO_MEM_QUEUE_SIZE);\n}\n\nINCore *\nin_core_init(const SimParams *p, struct RISCVSIMCPUState *simcpu)\n{\n    INCore *core;\n\n    core = calloc(1, sizeof(INCore));\n    assert(core);\n\n    /* Create execution units */\n    core->ialu = (CPUStage *)calloc(p->num_alu_stages, sizeof(CPUStage));\n    assert(core->ialu);\n\n    core->imul = (CPUStage *)calloc(p->num_mul_stages, sizeof(CPUStage));\n    assert(core->imul);\n\n    core->idiv = (CPUStage *)calloc(p->num_div_stages, sizeof(CPUStage));\n    assert(core->idiv);\n\n    core->fpu_fma = (CPUStage *)calloc(p->num_fpu_fma_stages, sizeof(CPUStage));\n    assert(core->fpu_fma);\n\n    /* Create FU to Memory selection queue */\n    cq_init(&core->ex_to_mem_queue.cq, INCORE_EX_TO_MEM_QUEUE_SIZE);\n    memset((void *)core->ex_to_mem_queue.data, 0,\n           sizeof(uint64_t) * INCORE_EX_TO_MEM_QUEUE_SIZE);\n\n    /* Set pointer to 5 or 6 stage run() function */\n    switch (p->num_cpu_stages)\n    {\n        case 5:\n        {\n            core->pfn_incore_run_internal = &in_core_run_5_stage;\n            break;\n        }\n        case 6:\n        {\n            core->pfn_incore_run_internal = &in_core_run_6_stage;\n            break;\n        }\n    }\n\n    core->simcpu = simcpu;\n    in_core_log_config(core);\n    return core;\n}\n\nvoid\nin_core_reset(void *core_type)\n{\n    int i;\n    INCore *core;\n\n    core = (INCore *)core_type;\n\n    /* Reset stages */\n    cpu_stage_flush(&core->pcgen);\n    cpu_stage_flush(&core->fetch);\n    cpu_stage_flush(&core->decode);\n    cpu_stage_flush(&core->memory);\n    cpu_stage_flush(&core->commit);\n\n    /* To start fetching */\n    core->pcgen.has_data = TRUE;\n\n    /* Reset register valid bits */\n    for (i = 0; i < NUM_INT_REG; ++i)\n    {\n        core->int_reg_status[i] = TRUE;\n    }\n\n    for (i = 0; i < NUM_FP_REG; ++i)\n    {\n        core->fp_reg_status[i] = TRUE;\n    }\n\n    /* Reset execution units */\n    cpu_stage_flush_pipe(core->ialu, core->simcpu->params->num_alu_stages);\n    cpu_stage_flush_pipe(core->imul, core->simcpu->params->num_mul_stages);\n    cpu_stage_flush_pipe(core->idiv, core->simcpu->params->num_div_stages);\n    cpu_stage_flush_pipe(core->fpu_fma,\n                         core->simcpu->params->num_fpu_fma_stages);\n    cpu_stage_flush(&core->fpu_alu);\n\n    /* Reset EX to Memory queue */\n    core->ins_dispatch_id = 0;\n    cq_reset(&core->ex_to_mem_queue.cq);\n\n    /* Reset Data FWD latches */\n    memset((void *)core->fwd_latch, 0, sizeof(DataFWDLatch) * NUM_FWD_BUS);\n}\n\nvoid\nin_core_free(void *core_type)\n{\n    INCore *core;\n\n    core = (INCore *)(*(INCore **)core_type);\n    free(core->fpu_fma);\n    core->fpu_fma = NULL;\n    free(core->idiv);\n    core->idiv = NULL;\n    free(core->imul);\n    core->imul = NULL;\n    free(core->ialu);\n    core->ialu = NULL;\n    free(core);\n}\n\nstatic int\nin_core_pipeline_drained(const INCore *core)\n{\n    int i;\n    RISCVSIMCPUState *simcpu = core->simcpu;\n\n    if (core->pcgen.has_data || core->fetch.has_data || core->decode.has_data\n        || core->fpu_alu.has_data || core->memory.has_data\n        || core->commit.has_data)\n    {\n        return PIPELINE_NOT_DRAINED;\n    }\n\n    for (i = 0; i < simcpu->params->num_alu_stages; ++i)\n    {\n        if (core->ialu[i].has_data)\n        {\n            return PIPELINE_NOT_DRAINED;\n        }\n    }\n\n    for (i = 0; i < simcpu->params->num_mul_stages; ++i)\n    {\n        if (core->imul[i].has_data)\n        {\n            return PIPELINE_NOT_DRAINED;\n        }\n    }\n\n    for (i = 0; i < simcpu->params->num_div_stages; ++i)\n    {\n        if (core->idiv[i].has_data)\n        {\n            return PIPELINE_NOT_DRAINED;\n        }\n    }\n\n    for (i = 0; i < simcpu->params->num_fpu_fma_stages; ++i)\n    {\n        if (core->fpu_fma[i].has_data)\n        {\n            return PIPELINE_NOT_DRAINED;\n        }\n    }\n\n    return PIPELINE_DRAINED;\n}\n\nint\nin_core_run(void *core_type)\n{\n    INCore *core = (INCore *)core_type;\n    RISCVCPUState *s = core->simcpu->emu_cpu_state;\n\n    while (1)\n    {\n        /* Advance DRAM clock */\n        mem_controller_clock(s->simcpu->mem_hierarchy->mem_controller);\n\n        /* For 5-stage pipeline calls in_core_run_5_stage(), For 6-stage\n         * pipeline calls in_core_run_6_stage() */\n        if (core->pfn_incore_run_internal(core))\n        {\n            return s->simcpu->exception->cause;\n        }\n\n        /* If an exception occurred and pipeline is drained, safely exit from\n         * simulation */\n        if (s->simcpu->exception->pending && in_core_pipeline_drained(core))\n        {\n            return s->simcpu->exception->cause;\n        }\n\n        /* Advance simulation cycle */\n        ++s->simcpu->clock;\n        ++s->simcpu->stats[s->priv].cycles;\n    }\n}\n\nint\nin_core_run_6_stage(INCore *core)\n{\n    if (in_core_commit(core))\n    {\n        /* Timeout */\n        return -1;\n    }\n\n    in_core_memory(core);\n    in_core_execute_all(core);\n    in_core_decode(core);\n\n    /* After the instruction in decode reads forwarded value, clear\n     * forwarding latches. This keeps the data on forwarding latches valid\n     * for exactly one cycle */\n    memset((void *)core->fwd_latch, 0, sizeof(DataFWDLatch) * NUM_FWD_BUS);\n    in_core_fetch(core);\n    in_core_pcgen(core);\n    return 0;\n}\n\nint\nin_core_run_5_stage(INCore *core)\n{\n    if (in_core_commit(core))\n    {\n        /* Timeout */\n        return -1;\n    }\n\n    in_core_memory(core);\n    in_core_execute_all(core);\n    in_core_decode(core);\n\n    /* After the instruction in decode reads forwarded value, clear\n     * forwarding latches. This keeps the data on forwarding latches valid\n     * for exactly one cycle */\n    memset((void *)core->fwd_latch, 0, sizeof(DataFWDLatch) * NUM_FWD_BUS);\n    in_core_pcgen(core);\n    in_core_fetch(core);\n    return 0;\n}"
  },
  {
    "path": "src/riscvsim/core/inorder.h",
    "content": "/**\n * In-order core\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _INORDER_H_\n#define _INORDER_H_\n\n#include \"../bpu/bpu.h\"\n#include \"../utils/circular_queue.h\"\n#include \"../utils/cpu_latches.h\"\n#include \"../utils/sim_params.h\"\n\n/* Forward declare */\nstruct RISCVSIMCPUState;\n\n/* Every instruction issued from the decode stage is assigned a unique\n * sequential ID known as ins_dispatch_id. This ID is appended to\n * ex_to_mem_queue. This ID (returned from the ex_to_mem_queue top) is used by\n * memory stage to select the earliest instruction in sequence when multiple\n * functional units (if parallel FUs enabled) try to send their respective\n * instructions to the memory stage in the same cycle  */\ntypedef struct ExToMemQueue\n{\n    CQ cq;\n    uint64_t data[INCORE_EX_TO_MEM_QUEUE_SIZE];\n} ExToMemQueue;\n\ntypedef struct DataFWDLatch\n{\n    uint64_t buffer;\n    int rd;\n    int valid;\n    int fp_dest;\n    int int_dest;\n} DataFWDLatch;\n\ntypedef struct INCore\n{\n    /*----------  In-order pipeline stages   ----------*/\n    CPUStage pcgen;\n    CPUStage fetch;\n    CPUStage decode;\n    CPUStage memory;\n    CPUStage commit;\n\n    /*----------  Register valid bits  ----------*/\n    uint32_t int_reg_status[NUM_INT_REG];\n    uint32_t fp_reg_status[NUM_FP_REG];\n\n    /*----------  Forwarding buses  ----------*/\n    DataFWDLatch fwd_latch[NUM_FWD_BUS];\n\n    /*----------  EX to Mem Queue  ----------*/\n    ExToMemQueue ex_to_mem_queue;\n\n    /*----------  Execution units/EX stage ----------*/\n    CPUStage *ialu;\n    CPUStage *imul;\n    CPUStage *idiv;\n    CPUStage *fpu_fma;\n    CPUStage fpu_alu;\n\n    /*----------  Pointer to 5 or 6 stage run() function  ----------*/\n    int (*pfn_incore_run_internal)(struct INCore *core);\n\n    uint64_t ins_dispatch_id;\n\n    struct RISCVSIMCPUState *simcpu; /* Pointer to parent */\n} INCore;\n\n/*---------- In-order core top-level functions  ----------*/\nINCore *in_core_init(const SimParams *p, struct RISCVSIMCPUState *simcpu);\nvoid in_core_reset(void *core_type);\nvoid in_core_free(void *core_type);\nint in_core_run(void *core_type);\n\n/*----------  In-order core stages  ----------*/\nvoid in_core_pcgen(INCore *core);\nvoid in_core_fetch(INCore *core);\nvoid in_core_decode(INCore *core);\nvoid in_core_execute_all(INCore *core);\nvoid in_core_memory(INCore *core);\nint in_core_commit(INCore *core);\nint in_core_run_5_stage(INCore *core);\nint in_core_run_6_stage(INCore *core);\n#endif\n"
  },
  {
    "path": "src/riscvsim/core/inorder_backend.c",
    "content": "/**\n * In-order Pipeline Back-end Stages: execute, memory and commit\n *\n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../../riscv_cpu_priv.h\"\n#include \"../memory_hierarchy/memory_controller.h\"\n#include \"../utils/circular_queue.h\"\n#include \"inorder.h\"\n#include \"riscv_sim_cpu.h\"\n\n/*=================================================\n=            Instruction Execute Stage            =\n=================================================*/\n\nstatic CPUStage *\nget_next_exec_pipe_stage(const INCore *core, int cur_stage_id, int fu_type)\n{\n    CPUStage *stage = NULL;\n\n    switch (fu_type)\n    {\n        case FU_ALU:\n        {\n            stage = &core->ialu[cur_stage_id + 1];\n            break;\n        }\n        case FU_MUL:\n        {\n            stage = &core->imul[cur_stage_id + 1];\n            break;\n        }\n        case FU_DIV:\n        {\n            stage = &core->idiv[cur_stage_id + 1];\n            break;\n        }\n        case FU_FPU_FMA:\n        {\n            stage = &core->fpu_fma[cur_stage_id + 1];\n            break;\n        }\n    }\n    return stage;\n}\n\nstatic void\nexec_insn_and_invalidate_rd(RISCVCPUState *s, INCore *core, InstructionLatch *e,\n                            int fu_type)\n{\n    if (e->ins.has_dest)\n    {\n        if (e->ins.rd != 0)\n        {\n            core->int_reg_status[e->ins.rd] = FALSE;\n        }\n    }\n    else if (e->ins.has_fp_dest)\n    {\n        core->fp_reg_status[e->ins.rd] = FALSE;\n    }\n\n    e->elasped_clock_cycles = 1;\n    e->ins.rm = get_insn_rm(s, (e->ins.binary >> 12) & 7);\n    execute_riscv_instruction(&e->ins, &s->fflags);\n    ++s->simcpu->stats[s->priv].fu_access[fu_type];\n}\n\nstatic void\nfwd_data_from_ex_to_decode(INCore *core, InstructionLatch *e, int fu_type)\n{\n    if (!e->data_fwd_done\n        && !(e->ins.is_load || e->ins.is_store || e->ins.is_atomic)\n        && !e->keep_dest_busy\n        && ((e->ins.has_dest && e->ins.rd != 0) || e->ins.has_fp_dest))\n    {\n        core->fwd_latch[fu_type].rd = e->ins.rd;\n        core->fwd_latch[fu_type].buffer = e->ins.buffer;\n        core->fwd_latch[fu_type].int_dest = e->ins.has_dest;\n        core->fwd_latch[fu_type].fp_dest = e->ins.has_fp_dest;\n        core->fwd_latch[fu_type].valid = TRUE;\n        e->data_fwd_done = TRUE;\n    }\n}\n\nstatic void\npush_insn_from_ex_to_mem(INCore *core, InstructionLatch *e, CPUStage *stage)\n{\n    if (core->ex_to_mem_queue.data[cq_front(&core->ex_to_mem_queue.cq)]\n        == e->ins_dispatch_id)\n    {\n        if (!core->memory.has_data)\n        {\n            cq_dequeue(&core->ex_to_mem_queue.cq);\n            e->elasped_clock_cycles = 0;\n            e->data_fwd_done = FALSE;\n            stage->stage_exec_done = FALSE;\n            core->memory = *stage;\n            cpu_stage_flush(stage);\n        }\n    }\n}\n\nstatic void\nin_core_execute_non_pipe(INCore *core, int fu_type, CPUStage *stage)\n{\n    RISCVCPUState *s;\n    InstructionLatch *e;\n\n    s = core->simcpu->emu_cpu_state;\n    if (stage->has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool, stage->insn_latch_index);\n        ++s->simcpu->stats[s->priv].exec_unit_delay;\n        if (!stage->stage_exec_done)\n        {\n            exec_insn_and_invalidate_rd(s, core, e, fu_type);\n            e->max_clock_cycles\n                = set_max_clock_cycles_for_non_pipe_fu(s, fu_type, e);\n\n            sim_assert((e->max_clock_cycles),\n                       \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n                       __func__,\n                       \"max_clock_cycles execution latency for an instruction \"\n                       \"must be non_zero\");\n\n            stage->stage_exec_done = TRUE;\n        }\n\n        if (e->elasped_clock_cycles == e->max_clock_cycles)\n        {\n            fwd_data_from_ex_to_decode(core, e, fu_type);\n            push_insn_from_ex_to_mem(core, e, stage);\n        }\n        else\n        {\n            e->elasped_clock_cycles++;\n        }\n    }\n}\n\nstatic void\nin_core_execute_pipe(INCore *core, int cur_stage_id, int fu_type,\n                     CPUStage *stage, int max_clock_cycles, int max_stage_id)\n{\n    CPUStage *next;\n    RISCVCPUState *s;\n    InstructionLatch *e;\n\n    s = core->simcpu->emu_cpu_state;\n    if (stage->has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool, stage->insn_latch_index);\n        ++s->simcpu->stats[s->priv].exec_unit_delay;\n        if (!stage->stage_exec_done)\n        {\n            exec_insn_and_invalidate_rd(s, core, e, fu_type);\n            stage->stage_exec_done = TRUE;\n        }\n\n        if (e->elasped_clock_cycles == max_clock_cycles)\n        {\n            /* Instruction is in the last stage of FU */\n            if (cur_stage_id == max_stage_id)\n            {\n                fwd_data_from_ex_to_decode(core, e, fu_type);\n                push_insn_from_ex_to_mem(core, e, stage);\n            }\n            else\n            {\n                /* Pass the instruction into next stage for this FU */\n                next = get_next_exec_pipe_stage(core, cur_stage_id, fu_type);\n                if (!next->has_data)\n                {\n                    e->elasped_clock_cycles = 1;\n                    *next = *stage;\n                    cpu_stage_flush(stage);\n                }\n            }\n        }\n        else\n        {\n            e->elasped_clock_cycles++;\n        }\n    }\n}\n\nvoid\nin_core_execute_all(INCore *core)\n{\n    int i;\n\n    for (i = core->simcpu->params->num_fpu_fma_stages - 1; i >= 0; i--)\n    {\n        in_core_execute_pipe(core, i, FU_FPU_FMA, &core->fpu_fma[i],\n                             core->simcpu->params->fpu_fma_stage_latency[i],\n                             core->simcpu->params->num_fpu_fma_stages - 1);\n    }\n    in_core_execute_non_pipe(core, FU_FPU_ALU, &core->fpu_alu);\n    for (i = core->simcpu->params->num_div_stages - 1; i >= 0; i--)\n    {\n        in_core_execute_pipe(core, i, FU_DIV, &core->idiv[i],\n                             core->simcpu->params->div_stage_latency[i],\n                             core->simcpu->params->num_div_stages - 1);\n    }\n    for (i = core->simcpu->params->num_mul_stages - 1; i >= 0; i--)\n    {\n        in_core_execute_pipe(core, i, FU_MUL, &core->imul[i],\n                             core->simcpu->params->mul_stage_latency[i],\n                             core->simcpu->params->num_mul_stages - 1);\n    }\n    for (i = core->simcpu->params->num_alu_stages - 1; i >= 0; i--)\n    {\n        in_core_execute_pipe(core, i, FU_ALU, &core->ialu[i],\n                             core->simcpu->params->alu_stage_latency[i],\n                             core->simcpu->params->num_alu_stages - 1);\n    }\n}\n\n/*=====  End of Instruction Execute  ======*/\n\n/*==========================================\n=            Instruction Memory            =\n==========================================*/\nstatic void\nflush_fu_stage(INCore *core, CPUStage *fu, int stages)\n{\n    int i;\n    InstructionLatch *e;\n\n    for (i = 0; i < stages; ++i)\n    {\n        if (fu[i].has_data)\n        {\n            /* Reset the valid bits for INT, and FP destination registers on the\n             * speculated path */\n            e = get_insn_latch(core->simcpu->insn_latch_pool,\n                               fu[i].insn_latch_index);\n\n            if (e->ins.has_dest)\n            {\n                core->int_reg_status[e->ins.rd] = TRUE;\n            }\n            else if (e->ins.has_fp_dest)\n            {\n                core->fp_reg_status[e->ins.rd] = TRUE;\n            }\n        }\n        cpu_stage_flush(&fu[i]);\n    }\n}\n\nstatic void\nflush_speculated_cpu_state(INCore *core, InstructionLatch *e)\n{\n    int i;\n    RISCVCPUState *s = core->simcpu->emu_cpu_state;\n\n    /* Send target PC to pcgen */\n    s->code_ptr = NULL;\n    s->code_end = NULL;\n    s->code_to_pc_addend = e->branch_target;\n\n    /* Keep track of this branch to resume at this target, in case the timeout\n     * happens after this branch commits */\n    e->is_branch_taken = TRUE;\n    e->branch_target = e->branch_target;\n\n    /* Flush all the preceding stages */\n    cpu_stage_flush(&core->pcgen);\n    cpu_stage_flush(&core->fetch);\n    cpu_stage_flush(&core->decode);\n\n    /* Flush all the functional unit and reset rd valid bit */\n    flush_fu_stage(core, core->ialu, s->simcpu->params->num_alu_stages);\n    flush_fu_stage(core, core->imul, s->simcpu->params->num_mul_stages);\n    flush_fu_stage(core, core->idiv, s->simcpu->params->num_div_stages);\n    flush_fu_stage(core, &core->fpu_alu, 1);\n    flush_fu_stage(core, core->fpu_fma, s->simcpu->params->num_fpu_fma_stages);\n\n    /* Reset FU to MEM selector queue */\n    cq_reset(&core->ex_to_mem_queue.cq);\n\n    /* Flush FWD latches */\n    memset((void *)core->fwd_latch, 0, sizeof(DataFWDLatch) * NUM_FWD_BUS);\n\n    /* Flush memory controller queues on flush */\n    mem_controller_reset(s->simcpu->mem_hierarchy->mem_controller);\n\n    /* To start fetching */\n    core->pcgen.has_data = TRUE;\n\n    /* To start fetching target instruction from next cycle */\n    core->simcpu->skip_fetch_cycle = TRUE;\n\n    /* Reset exception on speculated path */\n    s->simcpu->exception->pending = FALSE;\n\n    /* Reset all the insn_latch_pool entries allocated on the speculated path */\n    for (i = 0; i < INSN_LATCH_POOL_SIZE; ++i)\n    {\n        if ((i != core->memory.insn_latch_index)\n            && (i != core->commit.insn_latch_index))\n        {\n            s->simcpu->insn_latch_pool[i].status = INSN_LATCH_FREE;\n        }\n    }\n}\n\nvoid\nin_core_memory(INCore *core)\n{\n    InstructionLatch *e;\n    RISCVCPUState *s;\n\n    s = core->simcpu->emu_cpu_state;\n    if (core->memory.has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool,\n                           core->memory.insn_latch_index);\n        if (!core->memory.stage_exec_done)\n        {\n            /* elasped_clock_cycles: number of CPU cycles spent by this\n             * instruction in the memory stage so far */\n            e->elasped_clock_cycles = 1;\n\n            /* Set default total number of CPU cycles required for this\n             * instruction in the memory stage. Note: This is the default\n             * latency for non-memory instructions */\n            e->max_clock_cycles = 1;\n\n            if (e->ins.is_load || e->ins.is_store || e->ins.is_atomic)\n            {\n                mem_cpu_stage_exec(s, e);\n            }\n            else if (e->ins.is_branch)\n            {\n                if (s->simcpu->bpu_execute_stage_handler(s, e))\n                {\n                    flush_speculated_cpu_state(core, e);\n                }\n            }\n\n            core->memory.stage_exec_done = TRUE;\n        }\n\n        if (e->elasped_clock_cycles == e->max_clock_cycles)\n        {\n            /* Simulation of cache lookup delay for data/instruction and\n             * page-table entries is complete at this point. Now request the\n             * memory controller to start simulating the delay for any DRAM\n             * requests generated by this cache lookup */\n            if (s->simcpu->mem_hierarchy->mem_controller\n                    ->backend_mem_access_queue.cur_size\n                && !e->cache_lookup_complete_signal_sent)\n            {\n                mem_controller_cache_lookup_complete_signal(\n                    s->simcpu->mem_hierarchy->mem_controller,\n                    &s->simcpu->mem_hierarchy->mem_controller\n                         ->backend_mem_access_queue);\n                e->cache_lookup_complete_signal_sent = TRUE;\n            }\n\n            if ((e->ins.is_load || e->ins.is_store || e->ins.is_atomic))\n            {\n                /* Wait on memory controller callback for any pending memory\n                 * accesses */\n                if (s->simcpu->mem_hierarchy->mem_controller\n                        ->backend_mem_access_queue.cur_size)\n                {\n                    ++s->simcpu->stats[s->priv].data_mem_delay;\n                    return;\n                }\n            }\n\n            /* MMU exception */\n            if (e->ins.exception)\n            {\n                sim_exception_set(s->simcpu->exception, e);\n                cpu_stage_flush(&core->pcgen);\n                cpu_stage_flush(&core->fetch);\n                cpu_stage_flush(&core->decode);\n                cpu_stage_flush(&core->memory);\n                cpu_stage_flush_pipe(core->ialu,\n                                     s->simcpu->params->num_alu_stages);\n                cpu_stage_flush_pipe(core->imul,\n                                     s->simcpu->params->num_mul_stages);\n                cpu_stage_flush_pipe(core->idiv,\n                                     s->simcpu->params->num_div_stages);\n                cpu_stage_flush_pipe(&core->fpu_alu, 1);\n                cpu_stage_flush_pipe(core->fpu_fma,\n                                     s->simcpu->params->num_fpu_fma_stages);\n                return;\n            }\n\n            /* Push the data read by loads/atomics on forwarding bus*/\n            if (!e->ins.exception && !e->data_fwd_done && !e->keep_dest_busy\n                && ((e->ins.has_dest && e->ins.rd != 0) || e->ins.has_fp_dest))\n            {\n                core->fwd_latch[NUM_FWD_BUS - 1].rd = e->ins.rd;\n                core->fwd_latch[NUM_FWD_BUS - 1].buffer = e->ins.buffer;\n                core->fwd_latch[NUM_FWD_BUS - 1].int_dest = e->ins.has_dest;\n                core->fwd_latch[NUM_FWD_BUS - 1].fp_dest = e->ins.has_fp_dest;\n                core->fwd_latch[NUM_FWD_BUS - 1].valid = TRUE;\n                e->data_fwd_done = TRUE;\n            }\n\n            /* If the commit stage is available, send this instruction to commit\n             * stage, else stall memory stage */\n            if (!core->commit.has_data)\n            {\n                s->simcpu->mem_hierarchy->mem_controller\n                    ->backend_mem_access_queue.cur_idx\n                    = 0;\n                core->memory.stage_exec_done = FALSE;\n                e->max_clock_cycles = 0;\n                e->elasped_clock_cycles = 0;\n                e->data_fwd_done = FALSE;\n                core->commit = core->memory;\n                cpu_stage_flush(&core->memory);\n            }\n        }\n        else\n        {\n            e->elasped_clock_cycles++;\n        }\n    }\n}\n\n/*=====  End of Instruction Memory  ======*/\n\n/*================================================\n=            Instruction Commit Stage            =\n================================================*/\n\nint\nin_core_commit(INCore *core)\n{\n    InstructionLatch *e;\n    RISCVCPUState *s;\n\n    s = core->simcpu->emu_cpu_state;\n    if (core->commit.has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool,\n                           core->commit.insn_latch_index);\n\n        if (e->ins.has_dest)\n        {\n            /* Update the integer register if rd is not x0 */\n            if (e->ins.rd)\n            {\n                update_arch_reg_int(s, e);\n\n                /* If keep_dest_busy is TRUE, there is following instruction\n                 * writing to the same rd (WAW). So let that instruction make\n                 * the destination valid when it commits */\n                if (!e->keep_dest_busy)\n                {\n                    core->int_reg_status[e->ins.rd] = TRUE;\n                }\n            }\n        }\n        else if (e->ins.has_fp_dest)\n        {\n            update_arch_reg_fp(s, e);\n            if (!e->keep_dest_busy)\n            {\n                core->fp_reg_status[e->ins.rd] = TRUE;\n            }\n        }\n\n        update_insn_commit_stats(s, e);\n\n        if (s->simcpu->params->do_sim_trace)\n        {\n            sim_trace_commit(s->simcpu->trace, s->simcpu->clock, s->priv, e);\n        }\n\n        if (s->sim_params->enable_stats_display)\n        {\n            write_stats_to_stats_display_shm(s->simcpu);\n        }\n\n        /* Commit success */\n        e->status = INSN_LATCH_FREE;\n        cpu_stage_flush(&core->commit);\n\n        /* Check for user specified sim_emulate_after_icount instructions */\n        if (s->sim_params->sim_emulate_after_icount\n            && (s->simcpu->icount >= s->sim_params->sim_emulate_after_icount))\n        {\n            e->ins.exception_cause = SIM_ICOUNT_COMPLETE_EXCEPTION;\n            sim_exception_set(s->simcpu->exception, e);\n            return -1;\n        }\n\n        /* Check for timeout */\n        if ((--s->n_cycles) == 0)\n        {\n            e->ins.exception_cause = SIM_TEMU_TIMEOUT_EXCEPTION;\n            sim_exception_set(s->simcpu->exception, e);\n            return -1;\n        }\n    }\n    return 0;\n}\n/*=====  End of Instruction Commit Stage  ======*/"
  },
  {
    "path": "src/riscvsim/core/inorder_frontend.c",
    "content": "/*\n * In-order Pipeline Front-end Stages: pcgen, fetch and decode\n *\n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"inorder.h\"\n#include \"../../riscv_cpu_priv.h\"\n#include \"../bpu/bpu.h\"\n#include \"../utils/circular_queue.h\"\n#include \"riscv_sim_cpu.h\"\n\n/*===========================================\n=            PC Generation Stage            =\n===========================================*/\n\nvoid\nin_core_pcgen(INCore *core)\n{\n    InstructionLatch *e;\n    RISCVCPUState *s;\n\n    s = core->simcpu->emu_cpu_state;\n    if (core->pcgen.has_data)\n    {\n        if (!core->pcgen.stage_exec_done)\n        {\n            if (core->simcpu->skip_fetch_cycle)\n            {\n                /* This is a branch miss prediction redirect, so skip this cycle\n                 * and fetch this new target from next cycle */\n                core->simcpu->skip_fetch_cycle = FALSE;\n                ++core->simcpu->stats[s->priv].pipeline_flush;\n                return;\n            }\n\n            /* Calculate current PC*/\n            s->simcpu->pc\n                = (target_ulong)((uintptr_t)s->code_ptr + s->code_to_pc_addend);\n\n            /* Allocate a latch for this instruction from insn_latch_pool */\n            e = insn_latch_allocate(s->simcpu->insn_latch_pool);\n\n            /* Setup the allocated latch */\n            e->ins_dispatch_id = core->ins_dispatch_id++;\n            e->ins.pc = s->simcpu->pc;\n            e->ins.create_str = s->sim_params->create_ins_str;\n\n            /* Store latch index in the stage and the actual decoded instruction\n             * info is stored in this insn_latch_pool entry.\n             * NOTE: This avoids copying of whole decoded instruction info when\n             * instruction flows to next stage */\n            core->pcgen.insn_latch_index = e->insn_latch_index;\n            core->pcgen.stage_exec_done = TRUE;\n        }\n\n        /* If next stage is free, pass this instruction to the next stage, else\n         * stall */\n        if (!core->fetch.has_data)\n        {\n            core->pcgen.stage_exec_done = FALSE;\n            core->fetch = core->pcgen;\n            core->pcgen.insn_latch_index = -1;\n        }\n    }\n}\n\n/*=====  End of PC Generation Stage  ======*/\n\n/*===============================================\n=            Instruction Fetch Stage            =\n===============================================*/\n\nvoid\nin_core_fetch(INCore *core)\n{\n    InstructionLatch *e;\n    RISCVCPUState *s;\n\n    s = core->simcpu->emu_cpu_state;\n    if (core->fetch.has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool,\n                           core->fetch.insn_latch_index);\n        if (!core->fetch.stage_exec_done)\n        {\n            fetch_cpu_stage_exec(s, e);\n            if (e->ins.exception)\n            {\n                /* Stop pcgen stage and save exception context */\n                cpu_stage_flush(&core->pcgen);\n                sim_exception_set(s->simcpu->exception, e);\n            }\n            core->fetch.stage_exec_done = TRUE;\n        }\n        else\n        {\n            e = get_insn_latch(s->simcpu->insn_latch_pool,\n                               core->fetch.insn_latch_index);\n        }\n\n        if (e->elasped_clock_cycles == e->max_clock_cycles)\n        {\n            /* Simulation of cache lookup delay for data/instruction and\n             * page-table entries is complete at this point. Now request the\n             * memory controller to start simulating the delay for any DRAM\n             * requests generated by this cache lookup */\n            if (s->simcpu->mem_hierarchy->mem_controller\n                    ->frontend_mem_access_queue.cur_size\n                && !e->cache_lookup_complete_signal_sent)\n            {\n                mem_controller_cache_lookup_complete_signal(\n                    s->simcpu->mem_hierarchy->mem_controller,\n                    &s->simcpu->mem_hierarchy->mem_controller\n                         ->frontend_mem_access_queue);\n                e->cache_lookup_complete_signal_sent =  TRUE;\n            }\n\n            /* Wait on memory controller callback for any pending memory\n             * accesses */\n            if (!s->simcpu->mem_hierarchy->mem_controller\n                     ->frontend_mem_access_queue.cur_size)\n            {\n                /* Stop fetching new instructions on a MMU exception */\n                if (e->ins.exception)\n                {\n                    cpu_stage_flush(&core->fetch);\n                }\n                else\n                {\n                    /* No MMU exception, it is safe to pass instruction to\n                     * decode stage */\n                    if (!core->decode.has_data)\n                    {\n                        s->simcpu->mem_hierarchy->mem_controller\n                            ->frontend_mem_access_queue.cur_idx\n                            = 0;\n\n                        core->fetch.stage_exec_done = FALSE;\n                        e->max_clock_cycles = 0;\n                        e->elasped_clock_cycles = 0;\n                        core->decode = core->fetch;\n                        cpu_stage_flush(&core->fetch);\n                    }\n                }\n            }\n            else\n            {\n                ++s->simcpu->stats[s->priv].insn_mem_delay;\n            }\n        }\n        else\n        {\n            e->elasped_clock_cycles++;\n        }\n    }\n}\n\n/*=====  End of Instruction Fetch Stage  ======*/\n\n/*================================================\n=            Instruction Decode Stage            =\n================================================*/\n\nstatic void\nread_int_operand(const INCore *core, int has_src, int *read_rs, int rs,\n                 uint64_t *buffer, int *reg_file_read_done)\n{\n    int i;\n\n    if (has_src && !(*read_rs))\n    {\n        if (!core->int_reg_status[rs])\n        {\n            for (i = 0; i < NUM_FWD_BUS; ++i)\n            {\n                if (core->fwd_latch[i].valid && core->fwd_latch[i].int_dest\n                    && (core->fwd_latch[i].rd == rs))\n                {\n                    *buffer = (target_ulong)core->fwd_latch[i].buffer;\n                    *read_rs = TRUE;\n                    break;\n                }\n            }\n        }\n        else\n        {\n            *buffer = (target_ulong)core->simcpu->emu_cpu_state->reg[rs];\n            *read_rs = TRUE;\n            *reg_file_read_done = TRUE;\n        }\n    }\n}\n\nstatic void\nread_fp_operand(const INCore *core, int has_src, int *read_rs, int rs,\n                uint64_t *buffer, int *reg_file_read_done)\n{\n    int i;\n\n    if (has_src && !(*read_rs))\n    {\n        if (!core->fp_reg_status[rs])\n        {\n            /* Floating point execution units start from ID 3 onwards */\n            for (i = 3; i < NUM_FWD_BUS; ++i)\n            {\n                if (core->fwd_latch[i].valid && core->fwd_latch[i].fp_dest\n                    && (core->fwd_latch[i].rd == rs))\n                {\n                    *buffer = core->fwd_latch[i].buffer;\n                    *read_rs = TRUE;\n                    break;\n                }\n            }\n        }\n        else\n        {\n            *buffer = core->simcpu->emu_cpu_state->fp_reg[rs];\n            *read_rs = TRUE;\n            *reg_file_read_done = TRUE;\n        }\n    }\n}\n\nstatic void\nset_waw_lock_int_dest(RISCVCPUState *s, CPUStage *stage, int rd)\n{\n    InstructionLatch *e;\n\n    if (stage->has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool, stage->insn_latch_index);\n        if (e->ins.has_dest && (e->ins.rd == rd))\n        {\n            e->keep_dest_busy = TRUE;\n        }\n    }\n}\n\nstatic void\nset_waw_lock_fp_dest(RISCVCPUState *s, CPUStage *stage, int rd)\n{\n    InstructionLatch *e;\n\n    if (stage->has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool, stage->insn_latch_index);\n        if (e->ins.has_fp_dest && (e->ins.rd == rd))\n        {\n            e->keep_dest_busy = TRUE;\n        }\n    }\n}\n\nstatic int\nexecute_stage_busy(const INCore *core, int *busy_stage_id)\n{\n    int i;\n\n    for (i = 0; i < core->simcpu->params->num_alu_stages; ++i)\n    {\n        if (core->ialu[i].has_data)\n        {\n            *busy_stage_id = FU_ALU;\n            return TRUE;\n        }\n    }\n\n    for (i = 0; i < core->simcpu->params->num_mul_stages; ++i)\n    {\n        if (core->imul[i].has_data)\n        {\n            *busy_stage_id = FU_MUL;\n            return TRUE;\n        }\n    }\n\n    for (i = 0; i < core->simcpu->params->num_div_stages; ++i)\n    {\n        if (core->idiv[i].has_data)\n        {\n            *busy_stage_id = FU_DIV;\n            return TRUE;\n        }\n    }\n\n    for (i = 0; i < core->simcpu->params->num_fpu_fma_stages; ++i)\n    {\n        if (core->fpu_fma[i].has_data)\n        {\n            *busy_stage_id = FU_FPU_FMA;\n            return TRUE;\n        }\n    }\n\n    if (core->fpu_alu.has_data)\n    {\n        *busy_stage_id = FU_FPU_ALU;\n        return TRUE;\n    }\n\n    /* All the functional units are free */\n    return FALSE;\n}\n\nstatic int\ntarget_fu_pipelined(const INCore *core, int fu_type)\n{\n    int num_stages = 1;\n\n    switch (fu_type)\n    {\n        case FU_ALU:\n        {\n            num_stages = core->simcpu->params->num_alu_stages;\n            break;\n        }\n        case FU_MUL:\n        {\n            num_stages = core->simcpu->params->num_mul_stages;\n            break;\n        }\n        case FU_DIV:\n        {\n            num_stages = core->simcpu->params->num_div_stages;\n            break;\n        }\n        case FU_FPU_ALU:\n        {\n            break;\n        }\n        case FU_FPU_FMA:\n        {\n            num_stages = core->simcpu->params->num_fpu_fma_stages;\n            break;\n        }\n    }\n\n    if (num_stages > 1)\n    {\n        return TRUE;\n    }\n\n    return FALSE;\n}\n\nvoid\nin_core_decode(INCore *core)\n{\n    int i;\n    InstructionLatch *e;\n    RISCVCPUState *s;\n    int ins_issue_index;\n    int busy_stage_id = -1;\n    int read_int_rf = 0;\n    int read_fp_rf = 0;\n\n    s = core->simcpu->emu_cpu_state;\n    if (core->decode.has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool,\n                           core->decode.insn_latch_index);\n        if (!core->decode.stage_exec_done)\n        {\n            if (!e->is_decoded)\n            {\n                decode_cpu_stage_exec(s, e);\n                if (s->simcpu->bpu_decode_stage_handler(s, e))\n                {\n                    /* RAS has redirected the control flow, so flush */\n                    cpu_stage_flush_free_insn_latch(&core->fetch,\n                                                    s->simcpu->insn_latch_pool);\n                    cpu_stage_flush_free_insn_latch(&core->pcgen,\n                                                    s->simcpu->insn_latch_pool);\n                    core->pcgen.has_data = TRUE;\n                }\n                e->is_decoded = TRUE;\n            }\n\n            /* Handle exception caused during decoding */\n            if (unlikely(e->ins.exception))\n            {\n                sim_exception_set(s->simcpu->exception, e);\n                cpu_stage_flush(&core->pcgen);\n                cpu_stage_flush(&core->fetch);\n                cpu_stage_flush(&core->decode);\n                return;\n            }\n\n            /* Read integer operands */\n            read_int_operand(core, e->ins.has_src1, &e->read_rs1, e->ins.rs1,\n                             &e->ins.rs1_val, &read_int_rf);\n            read_int_operand(core, e->ins.has_src2, &e->read_rs2, e->ins.rs2,\n                             &e->ins.rs2_val, &read_int_rf);\n\n            /* Read floating-point operands */\n            read_fp_operand(core, e->ins.has_fp_src1, &e->read_rs1, e->ins.rs1,\n                            &e->ins.rs1_val, &read_fp_rf);\n            read_fp_operand(core, e->ins.has_fp_src2, &e->read_rs2, e->ins.rs2,\n                            &e->ins.rs2_val, &read_fp_rf);\n            read_fp_operand(core, e->ins.has_fp_src3, &e->read_rs3, e->ins.rs3,\n                            &e->ins.rs3_val, &read_fp_rf);\n\n            /* Stall if any of the source register value is not available */\n            if (((e->ins.has_src1 || e->ins.has_fp_src1) && !e->read_rs1)\n                || ((e->ins.has_src2 || e->ins.has_fp_src2) && !e->read_rs2)\n                || (e->ins.has_fp_src3 && !e->read_rs3))\n            {\n                goto exit_decode;\n            }\n\n            /**\n             * Check if any of the issued instructions are writing to the same\n             * register (WAW hazard) and keep the destination busy until WAW\n             * hazard is resolved.\n             */\n            if (e->ins.has_dest)\n            {\n                if (!core->int_reg_status[e->ins.rd])\n                {\n                    set_waw_lock_int_dest(s, &core->commit, e->ins.rd);\n                    set_waw_lock_int_dest(s, &core->memory, e->ins.rd);\n                    set_waw_lock_int_dest(s, &core->fpu_alu, e->ins.rd);\n                    for (i = s->simcpu->params->num_div_stages - 1; i >= 0; i--)\n                    {\n                        set_waw_lock_int_dest(s, &core->idiv[i], e->ins.rd);\n                    }\n                    for (i = s->simcpu->params->num_mul_stages - 1; i >= 0; i--)\n                    {\n                        set_waw_lock_int_dest(s, &core->imul[i], e->ins.rd);\n                    }\n                    for (i = s->simcpu->params->num_alu_stages - 1; i >= 0; i--)\n                    {\n                        set_waw_lock_int_dest(s, &core->ialu[i], e->ins.rd);\n                    }\n                }\n            }\n\n            if (e->ins.has_fp_dest)\n            {\n                if (!core->fp_reg_status[e->ins.rd])\n                {\n                    set_waw_lock_fp_dest(s, &core->commit, e->ins.rd);\n                    set_waw_lock_fp_dest(s, &core->memory, e->ins.rd);\n                    for (i = s->simcpu->params->num_fpu_fma_stages - 1; i >= 0;\n                         i--)\n                    {\n                        set_waw_lock_fp_dest(s, &core->fpu_fma[i], e->ins.rd);\n                    }\n                    set_waw_lock_fp_dest(s, &core->fpu_alu, e->ins.rd);\n                }\n            }\n\n            core->decode.stage_exec_done = TRUE;\n        }\n\n        if (!core->simcpu->params->enable_parallel_fu\n            && execute_stage_busy(core, &busy_stage_id))\n        {\n            if (!(target_fu_pipelined(core, e->ins.fu_type)\n                  && (e->ins.fu_type == busy_stage_id)))\n            {\n                goto exit_decode;\n            }\n        }\n\n        /* Decoding is complete and all the resources are acquired. If the\n         * required FU is free, issue the instruction to the appropriate FU,\n         * else stall */\n        switch (e->ins.fu_type)\n        {\n            case FU_ALU:\n                if (!core->ialu[0].has_data)\n                {\n                    core->decode.stage_exec_done = FALSE;\n                    core->ialu[0] = core->decode;\n                }\n                else\n                {\n                    goto exit_decode;\n                }\n                break;\n            case FU_MUL:\n                if (!core->imul[0].has_data)\n                {\n                    core->decode.stage_exec_done = FALSE;\n                    core->imul[0] = core->decode;\n                }\n                else\n                {\n                    goto exit_decode;\n                }\n                break;\n            case FU_DIV:\n                if (!core->idiv[0].has_data)\n                {\n                    core->decode.stage_exec_done = FALSE;\n                    core->idiv[0] = core->decode;\n                }\n                else\n                {\n                    goto exit_decode;\n                }\n                break;\n            case FU_FPU_ALU:\n                if (!core->fpu_alu.has_data)\n                {\n                    core->decode.stage_exec_done = FALSE;\n                    core->fpu_alu = core->decode;\n                }\n                else\n                {\n                    goto exit_decode;\n                }\n                break;\n            case FU_FPU_FMA:\n                if (!core->fpu_fma[0].has_data)\n                {\n                    core->decode.stage_exec_done = FALSE;\n                    core->fpu_fma[0] = core->decode;\n                }\n                else\n                {\n                    goto exit_decode;\n                }\n                break;\n        }\n\n        /* Add sequence number of this instruction to memory selection queue */\n        ins_issue_index = cq_enqueue(&core->ex_to_mem_queue.cq);\n\n        sim_assert((ins_issue_index != -1), \"error: %s at line %d in %s(): %s\",\n                   __FILE__, __LINE__, __func__,\n                   \"EX stage to MEM stage instruction selector queue full\");\n\n        core->ex_to_mem_queue.data[ins_issue_index] = e->ins_dispatch_id;\n        cpu_stage_flush(&core->decode);\n    }\nexit_decode:\n    if (read_int_rf)\n    {\n        s->simcpu->stats[s->priv].int_regfile_reads++;\n    }\n\n    if (read_fp_rf)\n    {\n        s->simcpu->stats[s->priv].fp_regfile_reads++;\n    }\n}\n\n/*=====  End of Instruction Decode Stage  ======*/"
  },
  {
    "path": "src/riscvsim/core/ooo.c",
    "content": "/**\n * Out Of Order Core Top Level Functions\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n\n#include \"../../cutils.h\"\n#include \"../../riscv_cpu_priv.h\"\n#include \"../utils/circular_queue.h\"\n#include \"../utils/sim_log.h\"\n#include \"ooo.h\"\n#include \"riscv_sim_cpu.h\"\n\nstatic void\noo_core_log_config(const OOCore *core)\n{\n    sim_log_event_to_file(sim_log, \"%s\", \"Setting up out-of-order RISC-V core\");\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"core_id\", core->simcpu->core_id);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"core_name\",\n                  core->simcpu->params->core_name);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"core_type\",\n                  core_type_str[core->simcpu->params->core_type]);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"rob_size\",\n                  core->simcpu->params->rob_size);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"rob_commit_ports\",\n                  core->simcpu->params->rob_commit_ports);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"iq_size\", core->simcpu->params->iq_size);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"iq_issue_ports\",\n                  core->simcpu->params->iq_issue_ports);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"lsq_size\",\n                  core->simcpu->params->lsq_size);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"int_rename_table_size\", NUM_INT_REG);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"fp_rename_table_size\", NUM_FP_REG);\n}\n\nOOCore *\noo_core_init(const SimParams *p, struct RISCVSIMCPUState *simcpu)\n{\n    OOCore *core;\n\n    core = calloc(1, sizeof(OOCore));\n    assert(core);\n\n    /* Create ROB */\n    cq_init(&core->rob.cq, p->rob_size);\n    core->rob.entries = (ROBEntry *)calloc(p->rob_size, sizeof(ROBEntry));\n    assert(core->rob.entries);\n\n    /* Create LSQ */\n    cq_init(&core->lsq.cq, p->lsq_size);\n    core->lsq.entries = (LSQEntry *)calloc(p->lsq_size, sizeof(LSQEntry));\n    assert(core->lsq.entries);\n\n    /* Create Rename tables */\n    core->int_rat\n        = (RenameTableEntry *)calloc(NUM_INT_REG, sizeof(RenameTableEntry));\n    core->fp_rat\n        = (RenameTableEntry *)calloc(NUM_FP_REG, sizeof(RenameTableEntry));\n\n    /* Create IQ */\n    core->iq = (IssueQueueEntry *)calloc(p->iq_size, sizeof(IssueQueueEntry));\n\n    /* Create execution units */\n    core->ialu = (CPUStage *)calloc(p->num_alu_stages, sizeof(CPUStage));\n    assert(core->ialu);\n\n    core->imul = (CPUStage *)calloc(p->num_mul_stages, sizeof(CPUStage));\n    assert(core->imul);\n\n    core->idiv = (CPUStage *)calloc(p->num_div_stages, sizeof(CPUStage));\n    assert(core->idiv);\n\n    core->fpu_fma = (CPUStage *)calloc(p->num_fpu_fma_stages, sizeof(CPUStage));\n    assert(core->fpu_fma);\n\n    core->simcpu = simcpu;\n    oo_core_log_config(core);\n    return core;\n}\n\nvoid\noo_core_reset(void *core_type)\n{\n    int i;\n    OOCore *core;\n\n    core = (OOCore *)core_type;\n\n    core->ins_dispatch_id = 0;\n\n    /* Reset front-end stages */\n    cpu_stage_flush(&core->fetch);\n    cpu_stage_flush(&core->decode);\n    cpu_stage_flush(&core->dispatch);\n\n    /* Flush LSU */\n    cpu_stage_flush(&core->lsu);\n\n    /* To start fetching */\n    core->fetch.has_data = TRUE;\n\n    /* Reset rename tables */\n    for (i = 0; i < NUM_INT_REG; ++i)\n    {\n        core->int_rat[i].rob_idx = -1;\n        core->int_rat[i].read_from_rob = FALSE;\n    }\n\n    for (i = 0; i < NUM_FP_REG; ++i)\n    {\n        core->fp_rat[i].rob_idx = -1;\n        core->fp_rat[i].read_from_rob = FALSE;\n    }\n\n    cq_reset(&core->rob.cq);\n    cq_reset(&core->lsq.cq);\n    iq_reset(core->iq, core->simcpu->params->iq_size);\n\n    /* Reset execution units */\n    cpu_stage_flush_pipe(core->ialu, core->simcpu->params->num_alu_stages);\n    cpu_stage_flush_pipe(core->imul, core->simcpu->params->num_mul_stages);\n    cpu_stage_flush_pipe(core->idiv, core->simcpu->params->num_div_stages);\n    cpu_stage_flush_pipe(core->fpu_fma,\n                         core->simcpu->params->num_fpu_fma_stages);\n    cpu_stage_flush(&core->fpu_alu);\n}\n\nvoid\niq_reset(IssueQueueEntry *iq_entry, int size)\n{\n    int i;\n\n    for (i = 0; i < size; ++i)\n    {\n        iq_entry[i].valid = FALSE;\n        iq_entry[i].ready = FALSE;\n        iq_entry[i].e = NULL;\n    }\n}\n\nint\niq_full(const IssueQueueEntry *iq, int size)\n{\n    int i;\n\n    for (i = 0; i < size; ++i)\n    {\n        if (iq[i].valid == FALSE)\n        {\n            return FALSE;\n        }\n    }\n\n    return TRUE;\n}\n\nint\niq_get_free_entry(const IssueQueueEntry *iq, int size)\n{\n    int i;\n\n    for (i = 0; i < size; ++i)\n    {\n        if (iq[i].valid == FALSE)\n        {\n            return i;\n        }\n    }\n\n    sim_assert((0), \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n               __func__,\n               \"iq_get_free_entry() is called only when IQ is not full\");\n    return 0;\n}\n\nvoid\noo_core_free(void *core_type)\n{\n    OOCore *core;\n\n    core = (OOCore *)(*((OOCore **)core_type));\n    free(core->int_rat);\n    core->int_rat = NULL;\n    free(core->fp_rat);\n    core->fp_rat = NULL;\n    free(core->rob.entries);\n    core->rob.entries = NULL;\n    free(core->lsq.entries);\n    core->lsq.entries = NULL;\n    free(core->iq);\n    core->iq = NULL;\n    free(core->ialu);\n    core->ialu = NULL;\n    free(core->imul);\n    core->imul = NULL;\n    free(core->idiv);\n    core->idiv = NULL;\n    free(core->fpu_fma);\n    core->fpu_fma = NULL;\n    free(core);\n}\n\nint\noo_core_run(void *core_type)\n{\n    OOCore *core;\n\n    core = (OOCore *)core_type;\n    while (1)\n    {\n        /* Advance DRAM clock */\n        mem_controller_clock(core->simcpu->mem_hierarchy->mem_controller);\n\n        if (oo_core_rob_commit(core))\n        {\n            return core->simcpu->emu_cpu_state->simcpu->exception->cause;\n        }\n\n        oo_core_lsq(core);\n        oo_core_lsu(core);\n\n        /* Call lsq again to mark ROB entries as complete for memory\n         * instructions which completed in a single cycle */\n        oo_core_lsq(core);\n\n        oo_core_execute_all(core);\n        oo_core_issue(core);\n        oo_core_dispatch(core);\n        oo_core_decode(core);\n        oo_core_fetch(core);\n\n        /* Advance CPU clock */\n        ++core->simcpu->clock;\n        ++core->simcpu->stats[core->simcpu->emu_cpu_state->priv].cycles;\n    }\n}\n\n/** Optimize */\n/** When trying to read operand from ROB index, this checks whether the given\n * ROB index is already committed  */\nint\nrob_entry_committed(const ROB *rob, int src_idx, int current_idx)\n{\n    if (rob->cq.rear >= rob->cq.front)\n    {\n        if ((src_idx >= rob->cq.front) && (src_idx < current_idx))\n        {\n            return FALSE;\n        }\n    }\n    else\n    {\n        if ((current_idx >= rob->cq.front) && (current_idx < rob->cq.max_size)\n            && (src_idx >= rob->cq.front) && (src_idx < rob->cq.max_size)\n            && (src_idx < current_idx))\n        {\n            return FALSE;\n        }\n        if ((current_idx >= 0) && (current_idx <= rob->cq.rear)\n            && (((src_idx >= rob->cq.front) && (src_idx < rob->cq.max_size))\n                || (src_idx < current_idx)))\n        {\n            return FALSE;\n        }\n    }\n    return TRUE;\n}\n\nvoid\nread_int_operand_from_rob_slot(const OOCore *core, int arch_src,\n                               int src_rob_idx, int current_rob_idx,\n                               uint64_t *buffer, int *read_flag)\n{\n    ROBEntry *rbe;\n\n    sim_assert((src_rob_idx != current_rob_idx),\n               \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__, __func__,\n               \"cur_rob_idx trying to read operand value from self\");\n\n    if (rob_entry_committed(&core->rob, src_rob_idx, current_rob_idx))\n    {\n        /* ROB entry we are trying to read from is committed, so read value from\n         * register file */\n        *buffer = core->simcpu->emu_cpu_state->reg[arch_src];\n        *read_flag = TRUE;\n    }\n    else\n    {\n        /* ROB entry we are trying to read from is not yet committed*/\n        rbe = &core->rob.entries[src_rob_idx];\n        if (rbe->ready && !rbe->e->ins.exception && rbe->e->ins.has_dest\n            && (rbe->e->ins.rd == arch_src))\n        {\n            *buffer = rbe->e->ins.buffer;\n            *read_flag = TRUE;\n        }\n    }\n}\n\nvoid\nread_fp_operand_from_rob_slot(const OOCore *core, int arch_src, int src_rob_idx,\n                              int current_rob_idx, uint64_t *buffer,\n                              int *read_flag)\n{\n    ROBEntry *rbe;\n\n    sim_assert((src_rob_idx != current_rob_idx),\n               \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__, __func__,\n               \"cur_rob_idx trying to read operand value from self\");\n\n    if (rob_entry_committed(&core->rob, src_rob_idx, current_rob_idx))\n    {\n        /* ROB entry we are trying to read from is committed, so read value from\n         * register file */\n        *buffer = core->simcpu->emu_cpu_state->fp_reg[arch_src];\n        *read_flag = TRUE;\n    }\n    else\n    {\n        /* ROB entry we are trying to read from is not yet committed*/\n        rbe = &core->rob.entries[src_rob_idx];\n        if (rbe->ready & !rbe->e->ins.exception && rbe->e->ins.has_fp_dest\n            && (rbe->e->ins.rd == arch_src))\n        {\n            *buffer = rbe->e->ins.buffer;\n            *read_flag = TRUE;\n        }\n    }\n}"
  },
  {
    "path": "src/riscvsim/core/ooo.h",
    "content": "/**\n * Out of order core\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _OOO_H_\n#define _OOO_H_\n\n#include \"../utils/circular_queue.h\"\n#include \"../utils/cpu_latches.h\"\n#include \"../utils/sim_params.h\"\n\n/* Forward declare */\nstruct RISCVSIMCPUState;\n\ntypedef struct IssueQueueEntry\n{\n    int valid;\n    int ready;\n    InstructionLatch *e;\n} IssueQueueEntry;\n\ntypedef struct ROBEntry\n{\n    int ready;\n    InstructionLatch *e;\n} ROBEntry;\n\ntypedef struct ReOrderBuffer\n{\n    CQ cq;\n    ROBEntry *entries;\n} ROB;\n\ntypedef struct LSQEntry\n{\n    int ready;\n    int mem_request_sent;\n    int mem_request_complete;\n    InstructionLatch *e;\n} LSQEntry;\n\ntypedef struct LSQ\n{\n    CQ cq;\n    LSQEntry *entries;\n} LSQ;\n\ntypedef struct RenameTableEntry\n{\n    int read_from_rob;\n    int rob_idx;\n} RenameTableEntry;\n\ntypedef struct OOCore\n{\n    /*----------  Front-end stages  ----------*/\n    CPUStage fetch;\n    CPUStage decode;\n    CPUStage dispatch;\n\n    /*----------  Rename Tables  ----------*/\n    RenameTableEntry *int_rat;\n    RenameTableEntry *fp_rat;\n\n    ROB rob; /* Reorder buffer */\n    LSQ lsq; /* Load-Store Queue */\n\n    /*----------  Issue Queues  ----------*/\n    IssueQueueEntry *iq;\n\n    /*----------  Execution units  ----------*/\n    CPUStage *ialu;    /* INT ALU */\n    CPUStage *imul;    /* INT Multiplier */\n    CPUStage *idiv;    /* INT Divider */\n    CPUStage *fpu_fma; /* FP Fused Multiply Add */\n\n    CPUStage fpu_alu; /* FP ALU */\n\n    /*----------  Memory Stage  ----------*/\n    CPUStage lsu; /* Load-Store Unit unit, works with LSQ */\n\n    /* Dispatch ID for instruction */\n    uint64_t ins_dispatch_id; /* Support for speculative execution */\n\n    struct RISCVSIMCPUState *simcpu; /* Pointer to parent */\n} OOCore;\n\n/*----------  Out of order core top-level functions  ----------*/\nOOCore *oo_core_init(const SimParams *p, struct RISCVSIMCPUState *simcpu);\nvoid oo_core_reset(void *core_type);\nvoid oo_core_free(void *core_type);\nint oo_core_run(void *core_type);\n\n/*----------  Out of order stages  ----------*/\nint oo_core_rob_commit(OOCore *core);\nvoid oo_core_lsq(OOCore *core);\nvoid oo_core_lsu(OOCore *core);\nvoid oo_core_execute_all(OOCore *core);\nvoid oo_core_issue(OOCore *core);\nvoid oo_core_dispatch(OOCore *core);\nvoid oo_core_decode(OOCore *core);\nvoid oo_core_fetch(OOCore *core);\n\n/*----------  Out of order core utility functions  ----------*/\nvoid oo_process_branch(OOCore *core, InstructionLatch *e);\n\nvoid iq_reset(IssueQueueEntry *iq_entry, int size);\nint iq_full(const IssueQueueEntry *iq, int size);\nint iq_get_free_entry(const IssueQueueEntry *iq, int size);\nvoid read_int_operand_from_rob_slot(const OOCore *core, int asrc, int psrc,\n                                    int current_rob_idx, uint64_t *buffer,\n                                    int *read_flag);\nvoid read_fp_operand_from_rob_slot(const OOCore *core, int asrc, int psrc,\n                                   int current_rob_idx, uint64_t *buffer,\n                                   int *read_flag);\nint rob_entry_committed(const ROB *rob, int src_idx, int current_idx);\n#endif\n"
  },
  {
    "path": "src/riscvsim/core/ooo_backend.c",
    "content": "/**\n * Out of order core back-end stages : issue, execute, rob-commit\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdio.h>\n\n#include \"../../riscv_cpu_priv.h\"\n#include \"../utils/circular_queue.h\"\n#include \"ooo.h\"\n#include \"riscv_sim_cpu.h\"\n\n/*===============================================\n=            Instruction Issue Stage            =\n===============================================*/\n\nstatic int\nissue_ins_to_exec_unit(OOCore *core, InstructionLatch *e)\n{\n    CPUStage *fu;\n\n    switch (e->ins.fu_type)\n    {\n        case FU_ALU:\n        {\n            fu = &core->ialu[0];\n            break;\n        }\n        case FU_MUL:\n        {\n            fu = &core->imul[0];\n            break;\n        }\n        case FU_DIV:\n        {\n            fu = &core->idiv[0];\n            break;\n        }\n        case FU_FPU_ALU:\n        {\n            fu = &core->fpu_alu;\n            break;\n        }\n        case FU_FPU_FMA:\n        {\n            fu = &core->fpu_fma[0];\n            break;\n        }\n        default:\n        {\n            sim_assert((0), \"error: %s at line %d in %s(): %s\", __FILE__,\n                       __LINE__, __func__, \"invalid functional unit ID\");\n        }\n    }\n\n    if (!fu->has_data)\n    {\n        fu->has_data = TRUE;\n        fu->stage_exec_done = FALSE;\n        fu->insn_latch_index = e->insn_latch_index;\n        return 0;\n    }\n\n    /* FU busy */\n    return -1;\n}\n\nstatic void\nread_int_operand(const OOCore *core, int has_src, int *read_src, int arch_src,\n                 int phy_src, int current_rob_idx, uint64_t *buffer)\n{\n    if (has_src && !(*read_src))\n    {\n        read_int_operand_from_rob_slot(core, arch_src, phy_src, current_rob_idx,\n                                       buffer, read_src);\n    }\n}\n\nstatic void\nread_fp_operand(const OOCore *core, int has_src, int *read_src, int arch_src,\n                int phy_src, int current_rob_idx, uint64_t *buffer)\n{\n    if (has_src && !(*read_src))\n    {\n        read_fp_operand_from_rob_slot(core, arch_src, phy_src, current_rob_idx,\n                                      buffer, read_src);\n    }\n}\n\nstatic int\nissue_instruction(OOCore *core, IssueQueueEntry *iqe, InstructionLatch *e)\n{\n    if (!issue_ins_to_exec_unit(core, e))\n    {\n        /* Instruction issued, deallocate IQ entry */\n        iqe->valid = FALSE;\n        iqe->ready = FALSE;\n        iqe->e = NULL;\n\n        return TRUE;\n    }\n\n    /* Issue failed */\n    return FALSE;\n}\n\nstatic void\nprocess_iq(OOCore *core, IssueQueueEntry *iq, int iq_size, int max_issue_ports)\n{\n    int i;\n    InstructionLatch *e;\n    IssueQueueEntry *iqe;\n    int current_issue_count = 0;\n\n    for (i = 0; (i < iq_size) && (current_issue_count < max_issue_ports); ++i)\n    {\n        iqe = &iq[i];\n        e = iqe->e;\n\n        if (iqe->valid == TRUE)\n        {\n            /* Entry is ready to issue */\n            if (iqe->ready)\n            {\n                if (issue_instruction(core, iqe, e))\n                {\n                    current_issue_count++;\n                }\n                continue;\n            }\n            else\n            {\n                /* IQ entry not ready, try to read sources */\n                read_int_operand(core, e->ins.has_src1, &e->read_rs1,\n                                 e->ins.rs1, e->ins.prs1, e->rob_idx,\n                                 &e->ins.rs1_val);\n                read_int_operand(core, e->ins.has_src2, &e->read_rs2,\n                                 e->ins.rs2, e->ins.prs2, e->rob_idx,\n                                 &e->ins.rs2_val);\n                read_fp_operand(core, e->ins.has_fp_src1, &e->read_rs1,\n                                e->ins.rs1, e->ins.prs1, e->rob_idx,\n                                &e->ins.rs1_val);\n                read_fp_operand(core, e->ins.has_fp_src2, &e->read_rs2,\n                                e->ins.rs2, e->ins.prs2, e->rob_idx,\n                                &e->ins.rs2_val);\n                read_fp_operand(core, e->ins.has_fp_src3, &e->read_rs3,\n                                e->ins.rs3, e->ins.prs3, e->rob_idx,\n                                &e->ins.rs3_val);\n\n                if (e->read_rs1 && e->read_rs2 && e->read_rs3)\n                {\n                    iqe->ready = TRUE;\n                }\n            }\n\n            /* Try to issue instruction again after reading the sources */\n            if (iqe->ready)\n            {\n                if (issue_instruction(core, iqe, e))\n                {\n                    current_issue_count++;\n                }\n                continue;\n            }\n        }\n    }\n}\n\nvoid\noo_core_issue(OOCore *core)\n{\n    process_iq(core, core->iq, core->simcpu->params->iq_size,\n               core->simcpu->params->iq_issue_ports);\n}\n\n/*=====  End of Instruction Issue Stage  ======*/\n\n/*===================================================\n=            Instruction Execution Stage            =\n===================================================*/\nstatic CPUStage *\nget_next_exec_pipe_stage(const OOCore *core, int cur_stage_id, int fu_type)\n{\n    CPUStage *stage = NULL;\n\n    switch (fu_type)\n    {\n        case FU_ALU:\n        {\n            stage = &core->ialu[cur_stage_id + 1];\n            break;\n        }\n        case FU_MUL:\n        {\n            stage = &core->imul[cur_stage_id + 1];\n            break;\n        }\n        case FU_DIV:\n        {\n            stage = &core->idiv[cur_stage_id + 1];\n            break;\n        }\n        case FU_FPU_FMA:\n        {\n            stage = &core->fpu_fma[cur_stage_id + 1];\n            break;\n        }\n    }\n    return stage;\n}\n\nstatic void\noo_core_execute_non_pipe(OOCore *core, int fu_type, CPUStage *stage)\n{\n    InstructionLatch *e;\n    RISCVCPUState *s = core->simcpu->emu_cpu_state;\n\n    if (stage->has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool, stage->insn_latch_index);\n        if (!stage->stage_exec_done)\n        {\n            e->ins.rm = get_insn_rm(s, (e->ins.binary >> 12) & 7);\n            execute_riscv_instruction(&e->ins, &s->fflags);\n\n            /* Update FU stats */\n            ++s->simcpu->stats[s->priv].fu_access[fu_type];\n\n            /* elasped_clock_cycles: number of CPU cycles spent by this instruction\n             * in execute stage so far */\n            e->elasped_clock_cycles = 1;\n            e->max_clock_cycles = set_max_clock_cycles_for_non_pipe_fu(s, fu_type, e);\n\n            sim_assert((e->max_clock_cycles),\n                       \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n                       __func__,\n                       \"max_clock_cycles execution latency for an instruction \"\n                       \"must be non_zero\");\n\n            stage->stage_exec_done = TRUE;\n        }\n\n        /* If the latency is completed and next stage is free, pass this\n         * instruction to the next stage, else stall */\n        if (e->elasped_clock_cycles == e->max_clock_cycles)\n        {\n            if (e->ins.is_load || e->ins.is_store || e->ins.is_atomic)\n            {\n                /* Inform the LSQ entry that address is calculated */\n                core->lsq.entries[e->lsq_idx].ready = TRUE;\n            }\n            else\n            {\n                if (e->ins.is_branch)\n                {\n                    if (!e->branch_processed)\n                    {\n                        oo_process_branch(core, e);\n                    }\n                }\n\n                if (e->ins.has_dest || e->ins.has_fp_dest)\n                {\n                    core->rob.entries[e->rob_idx].ready = TRUE;\n                }\n            }\n\n            /* Execution complete */\n            e->max_clock_cycles = 0;\n            e->elasped_clock_cycles = 0;\n            cpu_stage_flush(stage);\n        }\n        else\n        {\n            e->elasped_clock_cycles++;\n        }\n    }\n}\n\nstatic void\noo_core_execute_pipe(OOCore *core, int cur_stage_id, int fu_type, CPUStage *stage,\n                int max_clock_cycles, int max_stage_id)\n{\n    InstructionLatch *e;\n    CPUStage *next;\n    RISCVCPUState *s = core->simcpu->emu_cpu_state;\n\n    if (stage->has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool, stage->insn_latch_index);\n        if (!stage->stage_exec_done)\n        {\n            e->ins.rm = get_insn_rm(s, (e->ins.binary >> 12) & 7);\n            execute_riscv_instruction(&e->ins, &s->fflags);\n\n            /* Update FU stats */\n            ++s->simcpu->stats[s->priv].fu_access[fu_type];\n\n            /* elasped_clock_cycles: number of CPU cycles spent by this instruction\n             * in execute stage so far */\n            e->elasped_clock_cycles = 1;\n            stage->stage_exec_done = TRUE;\n        }\n\n        /* If the latency is completed and next stage is free, pass this\n         * instruction to the next stage, else stall */\n        if (e->elasped_clock_cycles == max_clock_cycles)\n        {\n            /* Instruction is in last stage of FU*/\n            if (cur_stage_id == max_stage_id)\n            {\n                if (e->ins.is_load || e->ins.is_store || e->ins.is_atomic)\n                {\n                    /* Inform the LSQ entry that address is calculated */\n                    core->lsq.entries[e->lsq_idx].ready = TRUE;\n                }\n                else\n                {\n                    if (e->ins.is_branch)\n                    {\n                        if (!e->branch_processed)\n                        {\n                            oo_process_branch(core, e);\n                        }\n                    }\n\n                    if (e->ins.has_dest || e->ins.has_fp_dest)\n                    {\n                        core->rob.entries[e->rob_idx].ready = TRUE;\n                    }\n                }\n\n                /* Execution complete */\n                e->max_clock_cycles = 0;\n                e->elasped_clock_cycles = 0;\n                cpu_stage_flush(stage);\n            }\n            else\n            {\n                /* Pass the instruction into next stage for this FU */\n                next = get_next_exec_pipe_stage(core, cur_stage_id, fu_type);\n                if (!next->has_data)\n                {\n                    e->elasped_clock_cycles = 1;\n                    *next = *stage;\n                    cpu_stage_flush(stage);\n                }\n            }\n        }\n        else\n        {\n            e->elasped_clock_cycles++;\n        }\n    }\n}\n\nvoid\noo_core_execute_all(OOCore *core)\n{\n    int i;\n\n    for (i = core->simcpu->params->num_fpu_fma_stages - 1; i >= 0; i--)\n    {\n        oo_core_execute_pipe(core, i, FU_FPU_FMA, &core->fpu_fma[i],\n                        core->simcpu->params->fpu_fma_stage_latency[i],\n                        core->simcpu->params->num_fpu_fma_stages - 1);\n    }\n    oo_core_execute_non_pipe(core, FU_FPU_ALU, &core->fpu_alu);\n    for (i = core->simcpu->params->num_div_stages - 1; i >= 0; i--)\n    {\n        oo_core_execute_pipe(core, i, FU_DIV, &core->idiv[i],\n                        core->simcpu->params->div_stage_latency[i],\n                        core->simcpu->params->num_div_stages - 1);\n    }\n    for (i = core->simcpu->params->num_mul_stages - 1; i >= 0; i--)\n    {\n        oo_core_execute_pipe(core, i, FU_MUL, &core->imul[i],\n                        core->simcpu->params->mul_stage_latency[i],\n                        core->simcpu->params->num_mul_stages - 1);\n    }\n    for (i = core->simcpu->params->num_alu_stages - 1; i >= 0; i--)\n    {\n        oo_core_execute_pipe(core, i, FU_ALU, &core->ialu[i],\n                        core->simcpu->params->alu_stage_latency[i],\n                        core->simcpu->params->num_alu_stages - 1);\n    }\n}\n\n/*=====  End of Instruction Execution Stage  ======*/\n\n/*========================================\n=            ROB Commit Stage            =\n========================================*/\n\nstatic int\nrob_can_commit(const ROB *rob)\n{\n    if (!cq_empty(&rob->cq) && (rob->entries[cq_front(&rob->cq)].ready))\n    {\n        return TRUE;\n    }\n\n    return FALSE;\n}\n\nint\noo_core_rob_commit(OOCore *core)\n{\n    InstructionLatch *e;\n    ROBEntry *rbe;\n    RISCVCPUState *s;\n    int commits = 0;\n\n    s = core->simcpu->emu_cpu_state;\n    while (rob_can_commit(&core->rob))\n    {\n        rbe = &core->rob.entries[cq_front(&core->rob.cq)];\n        e = rbe->e;\n\n        sim_assert((rbe->ready), \"error: %s at line %d in %s(): %s\", __FILE__,\n                   __LINE__, __func__,\n                   \"rob entry to be committed is not ready to commit\");\n\n        if (e->ins.exception)\n        {\n            sim_exception_set(s->simcpu->exception, e);\n            return -1;\n        }\n        else\n        {\n            if (e->ins.has_dest)\n            {\n                if (e->ins.rd)\n                {\n                    update_arch_reg_int(s, e);\n\n                    if (core->int_rat[e->ins.rd].rob_idx == e->rob_idx)\n                    {\n                        core->int_rat[e->ins.rd].read_from_rob = FALSE;\n                        core->int_rat[e->ins.rd].rob_idx = -1;\n                    }\n                }\n            }\n            else if (e->ins.has_fp_dest)\n            {\n                update_arch_reg_fp(s, e);\n\n                if (core->fp_rat[e->ins.rd].rob_idx == e->rob_idx)\n                {\n                    core->fp_rat[e->ins.rd].read_from_rob = FALSE;\n                    core->fp_rat[e->ins.rd].rob_idx = -1;\n                }\n            }\n\n            update_insn_commit_stats(s, e);\n\n            /* Dump commit trace if trace mode enabled */\n            if (s->simcpu->params->do_sim_trace)\n            {\n                sim_trace_commit(s->simcpu->trace,\n                                               s->simcpu->clock, s->priv, e);\n            }\n\n            if (s->sim_params->enable_stats_display)\n            {\n                write_stats_to_stats_display_shm(s->simcpu);\n            }\n\n            /* Free up insn_latch_pool entry */\n            e->status = INSN_LATCH_FREE;\n\n            /* All the dependent instructions will have to lookup ARF for\n             * operand value */\n            rbe->ready = FALSE;\n\n            /* Deallocate ROB entry */\n            cq_dequeue(&core->rob.cq);\n\n            /* Check for user specified sim_emulate_after_icount instructions */\n            if (s->sim_params->sim_emulate_after_icount\n                && (s->simcpu->icount >= s->sim_params->sim_emulate_after_icount))\n            {\n                e->ins.exception_cause = SIM_ICOUNT_COMPLETE_EXCEPTION;\n                sim_exception_set(s->simcpu->exception, e);\n                return -1;\n            }\n\n            /* Check for timeout */\n            if ((--s->n_cycles) == 0)\n            {\n                e->ins.exception_cause = SIM_TEMU_TIMEOUT_EXCEPTION;\n                sim_exception_set(s->simcpu->exception, e);\n                return -1;\n            }\n\n            commits++;\n            if (commits == core->simcpu->params->rob_commit_ports)\n            {\n                break;\n            }\n        }\n    }\n\n    return 0;\n}\n/*=====  End of ROB Commit Stage  ======*/\n"
  },
  {
    "path": "src/riscvsim/core/ooo_branch.c",
    "content": "/**\n * Out of order core Back-end: Branch Handling\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"ooo.h\"\n#include \"../../riscv_cpu_priv.h\"\n#include \"../utils/circular_queue.h\"\n#include \"riscv_sim_cpu.h\"\n\nstatic void\nrestore_cpu_frontend(OOCore *core, const InstructionLatch *e)\n{\n    RISCVCPUState *s;\n\n    s = core->simcpu->emu_cpu_state;\n\n    /* Flush front-end stages */\n    cpu_stage_flush_free_insn_latch(&core->fetch, s->simcpu->insn_latch_pool);\n    cpu_stage_flush_free_insn_latch(&core->decode, s->simcpu->insn_latch_pool);\n    cpu_stage_flush_free_insn_latch(&core->dispatch,\n                                    s->simcpu->insn_latch_pool);\n\n    /* Invalidate the entries added to mem_request_queue on the speculated path */\n    mem_controller_invalidate_mem_request_queue_entries(\n        s->simcpu->mem_hierarchy->mem_controller,\n        &s->simcpu->mem_hierarchy->mem_controller->frontend_mem_access_queue);\n\n    /* Flush the memory transactions added by fetch stage */\n    mem_controller_reset_cpu_stage_queue(\n        &s->simcpu->mem_hierarchy->mem_controller->frontend_mem_access_queue);\n\n    /* Set the new target address into fetch and enable fetch unit to start\n     * fetching from the target */\n    s->code_ptr = NULL;\n    s->code_end = NULL;\n    s->code_to_pc_addend = e->branch_target;\n    core->fetch.has_data = TRUE;\n\n    /* To start fetching target instruction from next cycle */\n    core->simcpu->skip_fetch_cycle = TRUE;\n}\n\nstatic int\nrob_entry_committed_after_rollback(const ROB *rob, int src_idx)\n{\n    if (rob->cq.rear >= rob->cq.front)\n    {\n        if ((src_idx >= rob->cq.front) && (src_idx <= rob->cq.rear))\n        {\n            return FALSE;\n        }\n    }\n    else\n    {\n        if (((src_idx >= rob->cq.front) && (src_idx < rob->cq.max_size))\n            || ((src_idx >= 0) && (src_idx <= rob->cq.rear)))\n        {\n            return FALSE;\n        }\n    }\n    return TRUE;\n}\n\nstatic void\nrestore_rob_entry(OOCore *core, ROBEntry *rbe, uint64_t tag)\n{\n    InstructionLatch *e;\n\n    e = rbe->e;\n    if (e->ins_dispatch_id > tag)\n    {\n        if (e->ins.has_dest && e->ins.rd)\n        {\n            core->int_rat[e->ins.rd].rob_idx = e->ins.old_pdest;\n            core->int_rat[e->ins.rd].read_from_rob = TRUE;\n            if (e->ins.old_pdest == -1)\n            {\n                core->int_rat[e->ins.rd].read_from_rob = FALSE;\n            }\n\n            sim_assert((core->int_rat[e->ins.rd].rob_idx != e->rob_idx),\n                       \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n                       __func__, \"rob entry rollback failure\");\n        }\n        else if (e->ins.has_fp_dest)\n        {\n            core->fp_rat[e->ins.rd].rob_idx = e->ins.old_pdest;\n            core->fp_rat[e->ins.rd].read_from_rob = TRUE;\n            if (e->ins.old_pdest == -1)\n            {\n                core->fp_rat[e->ins.rd].read_from_rob = FALSE;\n            }\n\n            sim_assert((core->fp_rat[e->ins.rd].rob_idx != e->rob_idx),\n                       \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n                       __func__, \"rob entry rollback failure\");\n        }\n        /* Free up latch */\n        e->status = INSN_LATCH_FREE;\n    }\n}\n\n/* TODO: Can be optimized */\nstatic void\nrestore_rob(OOCore *core, InstructionLatch *e, uint64_t tag)\n{\n    int i;\n\n    if (core->rob.cq.rear >= core->rob.cq.front)\n    {\n        for (i = core->rob.cq.rear; i >= core->rob.cq.front; i--)\n        {\n            restore_rob_entry(core, &core->rob.entries[i], tag);\n        }\n    }\n    else\n    {\n        /* ROB is wrapped around */\n        for (i = core->rob.cq.rear; i >= 0; i--)\n        {\n            restore_rob_entry(core, &core->rob.entries[i], tag);\n        }\n\n        for (i = core->rob.cq.max_size - 1; i >= core->rob.cq.front; i--)\n        {\n            restore_rob_entry(core, &core->rob.entries[i], tag);\n        }\n    }\n\n    /* Flush all the ROB entries till this branch */\n    cq_set_rear(&core->rob.cq, e->rob_idx);\n\n    sim_assert(\n        (e == core->rob.entries[core->rob.cq.rear].e),\n        \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__, __func__,\n        \"rob tail should point to the entry of the miss-predicted branch\");\n}\n\nstatic void\nrestore_iq(IssueQueueEntry *iq, int size, uint64_t tag)\n{\n    int i;\n\n    for (i = 0; i < size; ++i)\n    {\n        if (iq[i].valid && (iq[i].e->ins_dispatch_id > tag))\n        {\n            iq[i].valid = FALSE;\n        }\n    }\n}\n\nstatic void\nrestore_fu(CPUStage *fu, int stages, uint64_t tag,\n           InstructionLatch *insn_latch_pool)\n{\n    int i;\n    InstructionLatch *e;\n\n    for (i = 0; i < stages; ++i)\n    {\n        if (fu[i].has_data)\n        {\n            e = &insn_latch_pool[fu[i].insn_latch_index];\n            if (e->ins_dispatch_id > tag)\n            {\n                cpu_stage_flush_free_insn_latch(&fu[i], insn_latch_pool);\n            }\n        }\n    }\n}\n\nstatic void\nrestore_lsu(OOCore *core, uint64_t tag)\n{\n    InstructionLatch *e;\n\n    if (core->lsu.has_data)\n    {\n        e = &core->simcpu->insn_latch_pool[core->lsu.insn_latch_index];\n        if (e->ins_dispatch_id > tag)\n        {\n            cpu_stage_flush_free_insn_latch(&core->lsu,\n                                            core->simcpu->insn_latch_pool);\n\n            /* Flush memory controller queues on flush */\n            mem_controller_reset(core->simcpu->mem_hierarchy->mem_controller);\n        }\n    }\n}\n\nstatic int\nis_lsq_entry_speculated(const LSQEntry *lsqe, uint64_t tag)\n{\n    if (lsqe->e->ins_dispatch_id > tag)\n    {\n        return TRUE;\n    }\n    return FALSE;\n}\n\nstatic void\nrestore_lsq(OOCore *core, uint64_t tag)\n{\n    int i;\n    LSQEntry *lsqe;\n\n    if (!cq_empty(&core->lsq.cq))\n    {\n        lsqe = &core->lsq.entries[cq_front(&core->lsq.cq)];\n\n        /* Memory instruction on LSQ front is on miss-predicted path */\n        if (lsqe->e->ins_dispatch_id > tag)\n        {\n            /* Flush entire LSQ since all the LSQ entries are along the\n             * speculated path */\n            cq_reset(&core->lsq.cq);\n        }\n        else\n        {\n            if (core->lsq.cq.rear >= core->lsq.cq.front)\n            {\n                for (i = core->lsq.cq.front; i <= core->lsq.cq.rear; i++)\n                {\n                    if (is_lsq_entry_speculated(&core->lsq.entries[i], tag))\n                    {\n                        cq_set_rear(&core->lsq.cq, i - 1);\n                        return;\n                    }\n                }\n            }\n            else\n            {\n                /* LSQ is wrapped around */\n                for (i = core->lsq.cq.front; i < core->lsq.cq.max_size; i++)\n                {\n                    if (is_lsq_entry_speculated(&core->lsq.entries[i], tag))\n                    {\n                        cq_set_rear(&core->lsq.cq, i - 1);\n                        return;\n                    }\n                }\n\n                for (i = 0; i <= core->lsq.cq.rear; i++)\n                {\n                    if (is_lsq_entry_speculated(&core->lsq.entries[i], tag))\n                    {\n                        if (i == 0)\n                        {\n                            cq_set_rear(&core->lsq.cq,\n                                        core->lsq.cq.max_size - 1);\n                        }\n                        else\n                        {\n                            cq_set_rear(&core->lsq.cq, i - 1);\n                        }\n                        return;\n                    }\n                }\n            }\n        }\n    }\n}\n\n/* After the rollback of miss speculated instructions, fix the rename table\n * entries pointing to restored physical registers which are already committed\n */\nstatic void\nfix_rename_tables(OOCore *core, RenameTableEntry *rat, int num_regs)\n{\n    int i;\n\n    for (i = 0; i < num_regs; ++i)\n    {\n        if (rat[i].read_from_rob)\n        {\n            sim_assert((rat[i].rob_idx != -1),\n                       \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n                       __func__, \"rename table entry should point to a valid \"\n                                 \"rob entry if READ_FROM_ROB bit is set\");\n\n            if (rob_entry_committed_after_rollback(&core->rob, rat[i].rob_idx))\n            {\n                rat[i].rob_idx = -1;\n                rat[i].read_from_rob = FALSE;\n            }\n        }\n    }\n}\n\nstatic void\nreallocate_active_insn_latch_pool_entries(OOCore *core)\n{\n    int i;\n\n    /* Set the insn_latch_pool entry status for active instructions as allocated\n     */\n    if (core->rob.cq.rear >= core->rob.cq.front)\n    {\n        for (i = core->rob.cq.front; i <= core->rob.cq.rear; ++i)\n        {\n            core->rob.entries[i].e->status = INSN_LATCH_ALLOCATED;\n        }\n    }\n    else\n    {\n        for (i = core->rob.cq.front; i < core->rob.cq.max_size; ++i)\n        {\n            core->rob.entries[i].e->status = INSN_LATCH_ALLOCATED;\n        }\n        for (i = 0; i <= core->rob.cq.rear; ++i)\n        {\n            core->rob.entries[i].e->status = INSN_LATCH_ALLOCATED;\n        }\n    }\n}\n\nstatic void\nrollback_speculated_cpu_state(OOCore *core, InstructionLatch *e)\n{\n    restore_cpu_frontend(core, e);\n    restore_rob(core, e, e->ins_dispatch_id);\n    restore_iq(core->iq, core->simcpu->params->iq_size, e->ins_dispatch_id);\n    restore_fu(core->ialu, core->simcpu->params->num_alu_stages,\n               e->ins_dispatch_id, core->simcpu->insn_latch_pool);\n    restore_fu(core->imul, core->simcpu->params->num_mul_stages,\n               e->ins_dispatch_id, core->simcpu->insn_latch_pool);\n    restore_fu(core->idiv, core->simcpu->params->num_div_stages,\n               e->ins_dispatch_id, core->simcpu->insn_latch_pool);\n    restore_fu(&core->fpu_alu, 1, e->ins_dispatch_id,\n               core->simcpu->insn_latch_pool);\n    restore_fu(core->fpu_fma, core->simcpu->params->num_fpu_fma_stages,\n               e->ins_dispatch_id, core->simcpu->insn_latch_pool);\n    restore_lsq(core, e->ins_dispatch_id);\n    restore_lsu(core, e->ins_dispatch_id);\n    fix_rename_tables(core, core->int_rat, NUM_INT_REG);\n    fix_rename_tables(core, core->fp_rat, NUM_FP_REG);\n    reset_insn_latch_pool(core->simcpu->insn_latch_pool);\n    reallocate_active_insn_latch_pool_entries(core);\n}\n\nvoid\noo_process_branch(OOCore *core, InstructionLatch *e)\n{\n    e->mispredict = core->simcpu->bpu_execute_stage_handler(\n        core->simcpu->emu_cpu_state, e);\n\n    if (e->mispredict)\n    {\n        rollback_speculated_cpu_state(core, e);\n    }\n\n    switch (e->ins.branch_type)\n    {\n        case BRANCH_COND:\n        {\n            core->rob.entries[e->rob_idx].ready = TRUE;\n            break;\n        }\n        case BRANCH_UNCOND:\n        {\n            if (!e->ins.has_dest)\n            {\n                core->rob.entries[e->rob_idx].ready = TRUE;\n            }\n            break;\n        }\n    }\n\n    e->branch_processed = TRUE;\n}\n"
  },
  {
    "path": "src/riscvsim/core/ooo_frontend.c",
    "content": "/**\n * Out of order core front-end stages: fetch, decode, dispatch\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"ooo.h\"\n#include \"../../riscv_cpu_priv.h\"\n#include \"../utils/circular_queue.h\"\n#include \"riscv_sim_cpu.h\"\n\n/*===============================================\n=            Instruction Fetch Stage            =\n===============================================*/\n\nvoid\noo_core_fetch(OOCore *core)\n{\n    InstructionLatch *e;\n    RISCVCPUState *s;\n\n    s = core->simcpu->emu_cpu_state;\n    if (core->fetch.has_data)\n    {\n        if (!core->fetch.stage_exec_done)\n        {\n            if (core->simcpu->skip_fetch_cycle)\n            {\n                /* This is a branch miss prediction redirect, so skip this cycle\n                 * and fetch this new target from next cycle */\n                core->simcpu->skip_fetch_cycle = FALSE;\n                ++core->simcpu->stats[s->priv].pipeline_flush;\n                return;\n            }\n\n            /* Calculate current PC*/\n            s->simcpu->pc\n                = (target_ulong)((uintptr_t)s->code_ptr + s->code_to_pc_addend);\n\n            e = insn_latch_allocate(s->simcpu->insn_latch_pool);\n\n            /* Setup the allocated latch */\n            e->ins.pc = s->simcpu->pc;\n            e->ins.create_str = s->sim_params->create_ins_str;\n\n            /* Store latch index in the stage and the actual decoded instruction\n             * info is stored in this latch entry. This avoids copying of whole\n             * decoded instruction info when instruction flows to next stage */\n            core->fetch.insn_latch_index = e->insn_latch_index;\n\n            fetch_cpu_stage_exec(s, e);\n            core->fetch.stage_exec_done = TRUE;\n        }\n        else\n        {\n            e = get_insn_latch(s->simcpu->insn_latch_pool, core->fetch.insn_latch_index);\n        }\n\n        if (e->elasped_clock_cycles == e->max_clock_cycles)\n        {\n            /* Simulation of cache lookup delay for data/instruction and\n             * page-table entries is complete at this point. Now request the\n             * memory controller to start simulating the delay for any DRAM\n             * requests generated by this cache lookup */\n            if (s->simcpu->mem_hierarchy->mem_controller\n                    ->frontend_mem_access_queue.cur_size\n                && !e->cache_lookup_complete_signal_sent)\n            {\n                mem_controller_cache_lookup_complete_signal(\n                    s->simcpu->mem_hierarchy->mem_controller,\n                    &s->simcpu->mem_hierarchy->mem_controller\n                         ->frontend_mem_access_queue);\n                e->cache_lookup_complete_signal_sent = TRUE;\n            }\n\n            /* Wait on memory controller callback for any pending memory\n             * accesses */\n            if (!s->simcpu->mem_hierarchy->mem_controller\n                     ->frontend_mem_access_queue.cur_size)\n            {\n                /* If the next stage is available, send this instruction to next\n                   stage, else stall fetch */\n                if (!core->decode.has_data)\n                {\n                    s->simcpu->mem_hierarchy->mem_controller->frontend_mem_access_queue\n                        .cur_idx\n                        = 0;\n\n                    core->fetch.stage_exec_done = FALSE;\n                    e->max_clock_cycles = 0;\n                    e->elasped_clock_cycles = 0;\n                    core->decode = core->fetch;\n                    core->fetch.insn_latch_index = -1;\n\n                    /* Stop fetching new instructions on a MMU exception */\n                    if (e->ins.exception)\n                    {\n                        cpu_stage_flush(&core->fetch);\n                    }\n                }\n            }\n            else\n            {\n                ++s->simcpu->stats[s->priv].insn_mem_delay;\n            }\n        }\n        else\n        {\n            e->elasped_clock_cycles++;\n        }\n    }\n}\n\n/*=====  End of Instruction Fetch Stage  ======*/\n\n/*================================================\n=            Instruction Decode Stage            =\n================================================*/\n\nvoid\noo_core_decode(OOCore *core)\n{\n    InstructionLatch *e;\n    RISCVCPUState *s;\n\n    s = core->simcpu->emu_cpu_state;\n    if (core->decode.has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool, core->decode.insn_latch_index);\n\n        if (!core->decode.stage_exec_done)\n        {\n            if (!e->ins.exception && !e->is_decoded)\n            {\n                decode_cpu_stage_exec(s, e);\n                if (s->simcpu->bpu_decode_stage_handler(s, e))\n                {\n                    cpu_stage_flush_free_insn_latch(&core->fetch, s->simcpu->insn_latch_pool);\n                    core->fetch.has_data = TRUE;\n                }\n                e->is_decoded = TRUE;\n            }\n\n            /* Handle exception caused during decoding */\n            if (unlikely(e->ins.exception))\n            {\n                cpu_stage_flush(&core->fetch);\n            }\n\n            core->decode.stage_exec_done = TRUE;\n        }\n\n        if (!core->dispatch.has_data)\n        {\n            core->decode.stage_exec_done = FALSE;\n            core->dispatch = core->decode;\n            cpu_stage_flush(&core->decode);\n        }\n    }\n}\n\n/*=====  End of Instruction Decode Stage  ======*/\n\n/*==================================================\n=            Instruction Dispatch Stage            =\n==================================================*/\n\nstatic void\nrob_entry_create(ROB *rob, InstructionLatch *e, int rob_entry_status)\n{\n    int rob_idx;\n\n    rob_idx = cq_enqueue(&rob->cq);\n    e->rob_idx = rob_idx;\n    rob->entries[rob_idx].ready = rob_entry_status;\n    rob->entries[rob_idx].e = e;\n}\n\nstatic void\niq_entry_create(IssueQueueEntry *iq, int iq_size, InstructionLatch *e)\n{\n    int iq_idx;\n\n    iq_idx = iq_get_free_entry(iq, iq_size);\n    e->iq_idx = iq_idx;\n    iq[iq_idx].valid = TRUE;\n    iq[iq_idx].ready = FALSE;\n    iq[iq_idx].e = e;\n}\n\nstatic void\nlsq_entry_create(LSQ *lsq, InstructionLatch *e)\n{\n    int lsq_idx;\n\n    lsq_idx = cq_enqueue(&lsq->cq);\n    e->lsq_idx = lsq_idx;\n    lsq->entries[lsq_idx].ready = FALSE;\n    lsq->entries[lsq_idx].mem_request_sent = FALSE;\n    lsq->entries[lsq_idx].mem_request_complete = FALSE;\n    lsq->entries[lsq_idx].e = e;\n}\n\nstatic void\nupdate_rd_rat_mapping(OOCore *core, InstructionLatch *e)\n{\n    /* INT destination */\n    if (e->ins.has_dest)\n    {\n        if (e->ins.rd)\n        {\n            e->ins.old_pdest = core->int_rat[e->ins.rd].rob_idx;\n            core->int_rat[e->ins.rd].read_from_rob = TRUE;\n            core->int_rat[e->ins.rd].rob_idx = e->rob_idx;\n\n            sim_assert((e->ins.old_pdest != core->int_rat[e->ins.rd].rob_idx),\n                       \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n                       __func__, \"rename failure on destination register\");\n        }\n    }\n    else if (e->ins.has_fp_dest)\n    {\n        e->ins.old_pdest = core->fp_rat[e->ins.rd].rob_idx;\n        core->fp_rat[e->ins.rd].read_from_rob = TRUE;\n        core->fp_rat[e->ins.rd].rob_idx = e->rob_idx;\n\n        sim_assert((e->ins.old_pdest != core->fp_rat[e->ins.rd].rob_idx),\n                   \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n                   __func__, \"rename failure on destination register\");\n    }\n}\n\nstatic int\nstall_insn_dispatch(const OOCore *core, const InstructionLatch *e)\n{\n    /* Before dispatching atomic instruction, make sure that all the prior\n     * instructions are committed */\n    if (e->ins.is_atomic && !cq_empty(&core->rob.cq))\n    {\n        return TRUE;\n    }\n\n    if (cq_full(&core->rob.cq) || iq_full(core->iq, core->simcpu->params->iq_size)\n        || ((e->ins.is_load || e->ins.is_store || e->ins.is_atomic)\n            && cq_full(&core->lsq.cq)))\n    {\n        return TRUE;\n    }\n\n    /* Ready to dispatch */\n    return FALSE;\n}\n\nstatic void\ndo_insn_rename_and_read_reg_file(OOCore *core, InstructionLatch *e)\n{\n    if (e->ins.has_src1)\n    {\n        if (core->int_rat[e->ins.rs1].read_from_rob)\n        {\n            e->ins.prs1 = core->int_rat[e->ins.rs1].rob_idx;\n            sim_assert((e->ins.prs1 != -1), \"error: %s at line %d in %s(): %s\",\n                       __FILE__, __LINE__, __func__,\n                       \"rename table entry should point to a valid \"\n                       \"rob entry if READ_FROM_ROB bit is set\");\n        }\n        else\n        {\n            e->ins.rs1_val = core->simcpu->emu_cpu_state->reg[e->ins.rs1];\n            e->read_rs1 = TRUE;\n        }\n    }\n    else if (e->ins.has_fp_src1)\n    {\n        if (core->fp_rat[e->ins.rs1].read_from_rob)\n        {\n            e->ins.prs1 = core->fp_rat[e->ins.rs1].rob_idx;\n            sim_assert((e->ins.prs1 != -1), \"error: %s at line %d in %s(): %s\",\n                       __FILE__, __LINE__, __func__,\n                       \"rename table entry should point to a valid \"\n                       \"rob entry if READ_FROM_ROB bit is set\");\n        }\n        else\n        {\n            e->ins.rs1_val = core->simcpu->emu_cpu_state->fp_reg[e->ins.rs1];\n            e->read_rs1 = TRUE;\n        }\n    }\n    else\n    {\n        /* Do this, so that this instruction won't wait for rs1,\n         * while in IQ */\n        e->read_rs1 = TRUE;\n    }\n\n    if (e->ins.has_src2)\n    {\n        if (core->int_rat[e->ins.rs2].read_from_rob)\n        {\n            e->ins.prs2 = core->int_rat[e->ins.rs2].rob_idx;\n            sim_assert((e->ins.prs2 != -1), \"error: %s at line %d in %s(): %s\",\n                       __FILE__, __LINE__, __func__,\n                       \"rename table entry should point to a valid \"\n                       \"rob entry if READ_FROM_ROB bit is set\");\n        }\n        else\n        {\n            e->ins.rs2_val = core->simcpu->emu_cpu_state->reg[e->ins.rs2];\n            e->read_rs2 = TRUE;\n        }\n    }\n    else if (e->ins.has_fp_src2)\n    {\n        if (core->fp_rat[e->ins.rs2].read_from_rob)\n        {\n            e->ins.prs2 = core->fp_rat[e->ins.rs2].rob_idx;\n            sim_assert((e->ins.prs2 != -1), \"error: %s at line %d in %s(): %s\",\n                       __FILE__, __LINE__, __func__,\n                       \"rename table entry should point to a valid \"\n                       \"rob entry if READ_FROM_ROB bit is set\");\n        }\n        else\n        {\n            e->ins.rs2_val = core->simcpu->emu_cpu_state->fp_reg[e->ins.rs2];\n            e->read_rs2 = TRUE;\n        }\n    }\n    else\n    {\n        e->read_rs2 = TRUE;\n    }\n\n    /* Only FP-FMA instructions have rs3 */\n    if (e->ins.has_fp_src3)\n    {\n        if (core->fp_rat[e->ins.rs3].read_from_rob)\n        {\n            e->ins.prs3 = core->fp_rat[e->ins.rs3].rob_idx;\n            sim_assert((e->ins.prs3 != -1), \"error: %s at line %d in %s(): %s\",\n                       __FILE__, __LINE__, __func__,\n                       \"rename table entry should point to a valid \"\n                       \"rob entry if READ_FROM_ROB bit is set\");\n        }\n        else\n        {\n            e->ins.rs3_val = core->simcpu->emu_cpu_state->fp_reg[e->ins.rs3];\n            e->read_rs3 = TRUE;\n        }\n    }\n    else\n    {\n        e->read_rs3 = TRUE;\n    }\n}\n\nvoid\noo_core_dispatch(OOCore *core)\n{\n    InstructionLatch *e;\n    RISCVCPUState *s;\n\n    s = core->simcpu->emu_cpu_state;\n    if (core->dispatch.has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool, core->dispatch.insn_latch_index);\n        if (!core->dispatch.stage_exec_done)\n        {\n            /* If this instruction has caused an exception, only create ROB\n             * entry for this instruction and let ROB handle this exception */\n            if (e->ins.exception)\n            {\n                if (cq_full(&core->rob.cq))\n                {\n                    /* Stall */\n                    return;\n                }\n\n                /* Mark ROB entry valid so that its processed immediately once\n                 * it becomes ROB top */\n                rob_entry_create(&core->rob, e, TRUE);\n            }\n            else\n            {\n                if (stall_insn_dispatch(core, e))\n                {\n                    return;\n                }\n                do_insn_rename_and_read_reg_file(core, e);\n                rob_entry_create(&core->rob, e, FALSE);\n                iq_entry_create(core->iq, s->simcpu->params->iq_size, e);\n                if (e->ins.is_load || e->ins.is_store || e->ins.is_atomic)\n                {\n                    lsq_entry_create(&core->lsq, e);\n                }\n                update_rd_rat_mapping(core, e);\n            }\n            e->ins_dispatch_id = core->ins_dispatch_id++;\n            cpu_stage_flush(&core->dispatch);\n        }\n    }\n}\n/*=====  End of Instruction Dispatch Stage  ======*/\n"
  },
  {
    "path": "src/riscvsim/core/ooo_lsu.c",
    "content": "/**\n * Out of order core Load Store Unit\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"ooo.h\"\n#include \"../../riscv_cpu_priv.h\"\n#include \"../utils/circular_queue.h\"\n#include \"riscv_sim_cpu.h\"\n\nvoid\noo_core_lsu(OOCore *core)\n{\n    InstructionLatch *e;\n    RISCVCPUState *s = core->simcpu->emu_cpu_state;\n\n    if (core->lsu.has_data)\n    {\n        e = get_insn_latch(s->simcpu->insn_latch_pool,\n                           core->lsu.insn_latch_index);\n        if (!core->lsu.stage_exec_done)\n        {\n            /* elasped_clock_cycles: number of CPU cycles spent by this\n             * instruction in memory stage so far */\n            e->elasped_clock_cycles = 1;\n            mem_cpu_stage_exec(s, e);\n            core->lsu.stage_exec_done = TRUE;\n        }\n\n        if (e->elasped_clock_cycles == e->max_clock_cycles)\n        {\n            /* Simulation of cache lookup delay for data/instruction and\n             * page-table entries is complete at this point. Now request the\n             * memory controller to start simulating the delay for any DRAM\n             * requests generated by this cache lookup */\n            if (s->simcpu->mem_hierarchy->mem_controller\n                    ->backend_mem_access_queue.cur_size\n                && !e->cache_lookup_complete_signal_sent)\n            {\n                mem_controller_cache_lookup_complete_signal(\n                    s->simcpu->mem_hierarchy->mem_controller,\n                    &s->simcpu->mem_hierarchy->mem_controller\n                         ->backend_mem_access_queue);\n                e->cache_lookup_complete_signal_sent = TRUE;\n            }\n\n            /* Number of CPU cycles spent by this instruction in memory stage\n             * equals memory access delay for this instruction */\n            if (!s->simcpu->mem_hierarchy->mem_controller\n                     ->backend_mem_access_queue.cur_size)\n            {\n                s->simcpu->mem_hierarchy->mem_controller\n                    ->backend_mem_access_queue.cur_idx\n                    = 0;\n                core->lsq.entries[e->lsq_idx].mem_request_complete = TRUE;\n                cpu_stage_flush(&core->lsu);\n            }\n            else\n            {\n                ++s->simcpu->stats[s->priv].data_mem_delay;\n            }\n        }\n        else\n        {\n            e->elasped_clock_cycles++;\n        }\n    }\n}\n\nstatic void\nprocess_lsq_entry_load(OOCore *core, LSQEntry *lsqe)\n{\n    InstructionLatch *e;\n\n    e = lsqe->e;\n    if (!lsqe->mem_request_sent)\n    {\n        if (!core->lsu.has_data)\n        {\n            /* Send request from LSQ top to LSU */\n            core->lsu.has_data = TRUE;\n            core->lsu.stage_exec_done = FALSE;\n            core->lsu.insn_latch_index = e->insn_latch_index;\n            lsqe->mem_request_sent = TRUE;\n        }\n    }\n    else\n    {\n        /* Request was sent, waiting for memory access to complete */\n        if (lsqe->mem_request_complete)\n        {\n            if (e->ins.exception)\n            {\n                /* MMU exception occurred, mark ROB entry valid */\n                core->rob.entries[e->rob_idx].ready = TRUE;\n\n                /* Stop fetching */\n                cpu_stage_flush(&core->fetch);\n                cpu_stage_flush(&core->decode);\n                cpu_stage_flush(&core->dispatch);\n            }\n            else\n            {\n                if (e->ins.has_dest || e->ins.has_fp_dest)\n                {\n                    core->rob.entries[e->rob_idx].ready = TRUE;\n                }\n            }\n            cq_dequeue(&core->lsq.cq);\n        }\n    }\n}\n\nstatic void\nprocess_lsq_entry_store(OOCore *core, LSQEntry *lsqe)\n{\n    InstructionLatch *e;\n    ROBEntry *rbe;\n\n    e = lsqe->e;\n\n    /* Extract ROB top */\n    rbe = &core->rob.entries[cq_front(&core->rob.cq)];\n\n    if (rbe->e->ins.pc == lsqe->e->ins.pc)\n    {\n        if (!lsqe->mem_request_sent)\n        {\n            if (!core->lsu.has_data)\n            {\n                /* Send request from LSQ top to LSU */\n                core->lsu.has_data = TRUE;\n                core->lsu.stage_exec_done = FALSE;\n                core->lsu.insn_latch_index = e->insn_latch_index;\n                lsqe->mem_request_sent = TRUE;\n            }\n        }\n        else\n        {\n            /* Request was sent, waiting for memory access to\n             * complete */\n            if (lsqe->mem_request_complete)\n            {\n                if (e->ins.exception)\n                {\n                    /* Stop fetching */\n                    cpu_stage_flush(&core->fetch);\n                    cpu_stage_flush(&core->decode);\n                    cpu_stage_flush(&core->dispatch);\n                }\n\n                /* Store is complete, remove its LSQ entry */\n                cq_dequeue(&core->lsq.cq);\n\n                /* Mark ROB entry valid */\n                core->rob.entries[e->rob_idx].ready = TRUE;\n            }\n        }\n    }\n}\n\nvoid\noo_core_lsq(OOCore *core)\n{\n    InstructionLatch *e;\n    LSQEntry *lsqe;\n\n    if (!cq_empty(&core->lsq.cq))\n    {\n        lsqe = &core->lsq.entries[cq_front(&core->lsq.cq)];\n        e = lsqe->e;\n\n        if (lsqe->ready == TRUE)\n        {\n            if (e->ins.is_load || e->ins.is_atomic)\n            {\n                process_lsq_entry_load(core, lsqe);\n            }\n            else if (e->ins.is_store)\n            {\n                process_lsq_entry_store(core, lsqe);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/riscvsim/core/riscv_sim_cpu.c",
    "content": "/**\n * RISCV Simulated CPU State\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <fcntl.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <time.h>\n#include <unistd.h>\n\n#include \"../../riscv_cpu_priv.h\"\n#include \"../memory_hierarchy/dramsim_wrapper_c_connector.h\"\n#include \"../memory_hierarchy/ramulator_wrapper_c_connector.h\"\n#include \"../utils/sim_log.h\"\n#include \"../utils/sim_stats.h\"\n#include \"inorder.h\"\n#include \"ooo.h\"\n#include \"riscv_sim_cpu.h\"\n#include \"../../rtc_timer.h\"\n\n#define WRITE_STATS_TO_SHM_CLOCK_CYCLES_INTERVAL 500000\n#define GET_TIME(time) clock_gettime(CLOCK_MONOTONIC, &time)\n#define GET_TIMER_DIFF(start, end)                                             \\\n    (1000000000L * (end.tv_sec - start.tv_sec) + end.tv_nsec - start.tv_nsec)\n\nstatic void\nbpu_enabled_fetch_stage_handler(struct RISCVCPUState *s, InstructionLatch *e)\n{\n    target_ulong bpu_target;\n\n    bpu_target = 0;\n    bpu_probe(s->simcpu->bpu, e->ins.pc, &e->bpu_resp_pkt, s->priv);\n    if (e->bpu_resp_pkt.bpu_probe_status)\n    {\n        bpu_target = bpu_get_target(s->simcpu->bpu, e->ins.pc,\n                                    e->bpu_resp_pkt.btb_entry);\n\n        /* Non-zero target means branch is taken, according to the prediction,\n         * so set the predicted address into pcgen unit */\n        if (bpu_target)\n        {\n            s->code_ptr = NULL;\n            s->code_end = NULL;\n            s->code_to_pc_addend = bpu_target;\n        }\n    }\n\n    /* Keep track of the predicted address and probe status, to correct\n     * miss-prediction later */\n    e->predicted_target = bpu_target;\n}\n\nstatic void\nbpu_disabled_fetch_stage_handler(struct RISCVCPUState *s, InstructionLatch *e)\n{\n    /* In the absence of BPU, no actions required */\n    return;\n}\n\nstatic int\nbpu_enabled_decode_stage_handler(struct RISCVCPUState *s, InstructionLatch *e)\n{\n    target_ulong ras_target = 0;\n\n    /* If return address stack is enabled */\n    if (s->simcpu->params->ras_size)\n    {\n        if (e->ins.is_func_call)\n        {\n            ras_push(\n                s->simcpu->bpu->ras,\n                ((e->ins.binary & 3) == 3 ? e->ins.pc + 4 : e->ins.pc + 2));\n        }\n\n        if (e->ins.is_func_ret)\n        {\n            ras_target = ras_pop(s->simcpu->bpu->ras);\n\n            /* Start fetch from address returned by RAS if non-zero */\n            if (ras_target)\n            {\n                s->code_ptr = NULL;\n                s->code_end = NULL;\n                s->code_to_pc_addend = ras_target;\n                e->predicted_target = ras_target;\n\n                /* Invalidate the entries added to mem_request_queue on the speculated path */\n                mem_controller_invalidate_mem_request_queue_entries(\n                    s->simcpu->mem_hierarchy->mem_controller,\n                    &s->simcpu->mem_hierarchy->mem_controller\n                         ->frontend_mem_access_queue);\n\n                mem_controller_reset_cpu_stage_queue(\n                    &s->simcpu->mem_hierarchy->mem_controller\n                         ->frontend_mem_access_queue);\n\n                /* Start fetching the target from next cycle */\n                s->simcpu->skip_fetch_cycle = TRUE;\n\n                /* Signal the calling stage to flush previous stages */\n                return TRUE;\n            }\n        }\n    }\n\n    /* No flush required because no redirect by RAS */\n    return FALSE;\n}\n\nstatic int\nbpu_disabled_decode_stage_handler(struct RISCVCPUState *s, InstructionLatch *e)\n{\n    return FALSE;\n}\n\n/* Handles conditional branches with branch prediction enabled, probes the BPU\n * and updates the entry if BPU hit, corrects the control-flow in the case of\n * direction miss-prediction */\nstatic int\nbpu_enabled_conditional_branch_handler(RISCVCPUState *s, InstructionLatch *e)\n{\n    target_ulong restore_pc;\n    int pred = 0;\n    int mispredict = FALSE;\n    RISCVSIMCPUState *simcpu = s->simcpu;\n\n    bpu_probe(simcpu->bpu, e->ins.pc, &e->bpu_resp_pkt, s->priv);\n\n    if (e->ins.cond)\n    {\n        /* Branch is resolved to be taken*/\n        pred = TRUE;\n        if (!e->predicted_target)\n        {\n            ++simcpu->stats[s->priv].bpu_cond_incorrect;\n            e->branch_target = e->ins.target;\n            mispredict = TRUE;\n        }\n        else\n        {\n            sim_assert((e->predicted_target == e->ins.target),\n                       \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n                       __func__, \"predicted branch target should be equal to \"\n                                 \"the computed branch target on correct \"\n                                 \"prediction\");\n\n            e->is_pred_correct = TRUE;\n            e->branch_target = e->predicted_target;\n            ++simcpu->stats[s->priv].bpu_cond_correct;\n        }\n        e->is_branch_taken = TRUE;\n    }\n    else\n    {\n        /* Branch resolved to be not-taken */\n        if (e->predicted_target)\n        {\n            /* Miss-prediction occurred, flush the pipeline, repair\n               the control flow */\n            restore_pc\n                = ((e->ins.binary & 3) != 3) ? e->ins.pc + 2 : e->ins.pc + 4;\n            ++simcpu->stats[s->priv].bpu_cond_incorrect;\n            e->branch_target = restore_pc;\n            mispredict = TRUE;\n        }\n        else\n        {\n            /* Correct Prediction */\n            e->is_pred_correct = TRUE;\n            ++simcpu->stats[s->priv].bpu_cond_correct;\n        }\n        e->is_branch_taken = FALSE;\n    }\n\n    /* Update BPU if hit, else skip the update */\n    bpu_update(simcpu->bpu, e->ins.pc, e->ins.target, pred, BRANCH_COND,\n               &e->bpu_resp_pkt, s->priv);\n\n    return mispredict;\n}\n\n/* Handles unconditional branches with branch prediction enabled, probes the BPU\n * and updates the entry if BPU hit, corrects the control-flow in the case of\n * target miss-prediction */\nstatic int\nbpu_enabled_unconditional_branch_handler(RISCVCPUState *s, InstructionLatch *e)\n{\n    RISCVSIMCPUState *simcpu = s->simcpu;\n    int type = BRANCH_UNCOND;\n    int mispredict = FALSE;\n    bpu_probe(simcpu->bpu, e->ins.pc, &e->bpu_resp_pkt, s->priv);\n\n    /* Update BPU if hit, else skip the update */\n    bpu_update(simcpu->bpu, e->ins.pc, e->ins.target, TRUE, type,\n               &e->bpu_resp_pkt, s->priv);\n\n    if (e->predicted_target == e->ins.target)\n    {\n        /* Prediction Success */\n        e->is_pred_correct = TRUE;\n\n        /* Keep track of this branch to resume at this target, in case\n           the timeout happens after this branch commits */\n        e->branch_target = e->predicted_target;\n        ++simcpu->stats[s->priv].bpu_uncond_correct;\n    }\n    else\n    {\n        /* Target Miss-prediction */\n        ++simcpu->stats[s->priv].bpu_uncond_incorrect;\n        e->branch_target = e->ins.target;\n        mispredict = TRUE;\n    }\n\n    e->is_branch_taken = TRUE;\n    return mispredict;\n}\n\nstatic int\nbpu_enabled_execute_stage_handler(struct RISCVCPUState *s, InstructionLatch *e)\n{\n    /* Add the branch PC into BPU structures if probe during fetch results in\n     * miss */\n    if (!e->bpu_resp_pkt.bpu_probe_status)\n    {\n        bpu_add(s->simcpu->bpu, e->ins.pc, e->ins.branch_type, &e->bpu_resp_pkt,\n                s->priv, e->ins.is_func_ret);\n    }\n\n    switch (e->ins.branch_type)\n    {\n        case BRANCH_UNCOND:\n        {\n            return bpu_enabled_unconditional_branch_handler(s, e);\n        }\n        case BRANCH_COND:\n        {\n            return bpu_enabled_conditional_branch_handler(s, e);\n        }\n    }\n\n    return 0;\n}\n\nstatic int\nbpu_disabled_execute_stage_handler(struct RISCVCPUState *s, InstructionLatch *e)\n{\n    int mispredict = FALSE;\n\n    switch (e->ins.branch_type)\n    {\n        case BRANCH_UNCOND:\n        {\n            e->is_branch_taken = TRUE;\n            e->branch_target = e->ins.target;\n            mispredict = TRUE;\n            break;\n        }\n        case BRANCH_COND:\n        {\n            if (e->ins.cond)\n            {\n                e->is_branch_taken = TRUE;\n                e->branch_target = e->ins.target;\n                mispredict = TRUE;\n            }\n            break;\n        }\n    }\n\n    return mispredict;\n}\n\nstatic void\ncopy_cache_stats_to_global_stats(RISCVSIMCPUState *simcpu)\n{\n    int i;\n    const CacheStats *cache_stats;\n\n    /* Update cache stats */\n    if (simcpu->params->enable_l1_caches)\n    {\n        for (i = 0; i < NUM_MAX_PRV_LEVELS; ++i)\n        {\n            cache_stats = cache_get_stats(simcpu->mem_hierarchy->icache);\n            simcpu->stats[i].icache_read = cache_stats[i].total_read_cnt;\n            simcpu->stats[i].icache_read_miss = cache_stats[i].read_miss_cnt;\n\n            cache_stats = cache_get_stats(simcpu->mem_hierarchy->dcache);\n            simcpu->stats[i].dcache_read = cache_stats[i].total_read_cnt;\n            simcpu->stats[i].dcache_read_miss = cache_stats[i].read_miss_cnt;\n            simcpu->stats[i].dcache_write = cache_stats[i].total_write_cnt;\n            simcpu->stats[i].dcache_write_miss = cache_stats[i].write_miss_cnt;\n\n            if (simcpu->params->enable_l2_cache)\n            {\n                cache_stats = cache_get_stats(simcpu->mem_hierarchy->l2_cache);\n                simcpu->stats[i].l2_cache_read = cache_stats[i].total_read_cnt;\n                simcpu->stats[i].l2_cache_read_miss\n                    = cache_stats[i].read_miss_cnt;\n                simcpu->stats[i].l2_cache_write\n                    = cache_stats[i].total_write_cnt;\n                simcpu->stats[i].l2_cache_write_miss\n                    = cache_stats[i].write_miss_cnt;\n            }\n        }\n    }\n}\n\n/* Setup shared memory to dump stats, read by sim-stats-display tool */\nstatic void\nsetup_stats_shm(RISCVSIMCPUState *simcpu)\n{\n    int stats_shm_fd;\n\n    stats_shm_fd\n        = shm_open(simcpu->params->sim_stats_shm_name, O_RDWR | O_CREAT, ALL_RW_PERMS);\n    if (stats_shm_fd < 0)\n    {\n        fprintf(stderr,\n                \"error: cannot create marss-stats-shm %s, terminating\\n\",\n                simcpu->params->sim_stats_shm_name);\n        exit(1);\n    }\n\n    if (ftruncate(stats_shm_fd, NUM_MAX_PRV_LEVELS * sizeof(SimStats)) < 0)\n    {\n        fprintf(stderr,\n                \"error: cannot resize marss-stats-shm %s, terminating\\n\",\n                simcpu->params->sim_stats_shm_name);\n        close(stats_shm_fd);\n        exit(1);\n    }\n\n    simcpu->stats_shm_ptr = NULL;\n    if ((simcpu->stats_shm_ptr = (SimStats *)mmap(\n             NULL, NUM_MAX_PRV_LEVELS * sizeof(SimStats),\n             PROT_READ | PROT_WRITE, MAP_SHARED, stats_shm_fd, 0))\n        == MAP_FAILED)\n    {\n        fprintf(stderr, \"error: cannot mmap shm %s, terminating\",\n                simcpu->params->sim_stats_shm_name);\n        close(stats_shm_fd);\n        exit(1);\n    }\n\n    memset(simcpu->stats_shm_ptr, 0, NUM_MAX_PRV_LEVELS * sizeof(SimStats));\n    sim_log_event_to_file(sim_log, \"%s\", \"Setting up shared memory to write stats\");\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"posix shared memory name\", simcpu->params->sim_stats_shm_name);\n}\n\nstatic void\nprint_performance_summary(RISCVSIMCPUState *simcpu, uint64_t sim_time)\n{\n    int i;\n\n    sim_log_event(sim_log, \"%s\", \"Performance Summary:\");\n\n    for (i = 0; i < NUM_MAX_PRV_LEVELS; ++i)\n    {\n        sim_log_param(sim_log, \"%s-mode-commits: %lu\", cpu_mode_str[i],\n                      simcpu->stats[i].ins_simulated);\n        sim_log_param(sim_log, \"%s-mode-cycles: %lu\", cpu_mode_str[i],\n                      simcpu->stats[i].cycles);\n        sim_log_param(sim_log, \"%s-mode-ipc: %.4lf\", cpu_mode_str[i],\n                      (double)simcpu->stats[i].ins_simulated\n                          / (double)simcpu->stats[i].cycles);\n    }\n\n    sim_log_param(sim_log, \"total-commits: %lu\", simcpu->icount);\n    sim_log_param(sim_log, \"total-cycles: %lu\", simcpu->clock);\n    sim_log_param(sim_log, \"total-ipc: %.4lf\",\n                  (double)simcpu->icount / (double)simcpu->clock);\n    sim_log_param(sim_log, \"simulation-time: %lu milliseconds\", sim_time);\n    sim_log_param(sim_log, \"total-commits-per-millisecond: %lu\",\n                  simcpu->icount / sim_time);\n}\n\nvoid\nupdate_arch_reg_int(RISCVCPUState *s, InstructionLatch *e)\n{\n    if (e->ins.rd)\n    {\n        s->reg[e->ins.rd] = e->ins.buffer;\n        ++s->simcpu->stats[s->priv].int_regfile_writes;\n    }\n}\n\nvoid\nupdate_arch_reg_fp(RISCVCPUState *s, InstructionLatch *e)\n{\n    if (e->ins.f32_mask)\n    {\n        e->ins.buffer |= F32_HIGH;\n    }\n    else if (e->ins.f64_mask)\n    {\n        e->ins.buffer |= F64_HIGH;\n    }\n    s->fp_reg[e->ins.rd] = e->ins.buffer;\n    if (e->ins.set_fs)\n    {\n        s->fs = 3;\n    }\n    ++s->simcpu->stats[s->priv].fp_regfile_writes;\n}\n\nvoid\nupdate_insn_commit_stats(RISCVCPUState *s, InstructionLatch *e)\n{\n    ++s->simcpu->icount;\n    ++s->simcpu->stats[s->priv].ins_simulated;\n    ++s->simcpu->stats[s->priv].ins_type[e->ins.type];\n\n    if ((e->ins.type == INS_TYPE_COND_BRANCH) && e->is_branch_taken)\n    {\n        ++s->simcpu->stats[s->priv].ins_cond_branch_taken;\n    }\n\n    if (e->ins.is_load)\n    {\n        switch (e->ins.bytes_to_rw)\n        {\n            case 1:\n            {\n                ++s->simcpu->stats[s->priv].ins_type[INS_TYPE_LOAD_BYTE];\n                break;\n            }\n\n            case 2:\n            {\n                ++s->simcpu->stats[s->priv].ins_type[INS_TYPE_LOAD_HALF_WORD];\n                break;\n            }\n\n            case 4:\n            {\n                ++s->simcpu->stats[s->priv].ins_type[INS_TYPE_LOAD_WORD];\n                break;\n            }\n\n            case 8:\n            {\n                ++s->simcpu->stats[s->priv].ins_type[INS_TYPE_LOAD_DOUBLE_WORD];\n                break;\n            }\n        }\n    }\n}\n\nvoid\nwrite_stats_to_stats_display_shm(RISCVSIMCPUState *simcpu)\n{\n    if ((simcpu->clock % WRITE_STATS_TO_SHM_CLOCK_CYCLES_INTERVAL) == 0)\n    {\n        /* Since cache stats are stored separately inside the Cache structure,\n         * they have to be copied to global stats structure before writing stats\n         * to shared memory. */\n        copy_cache_stats_to_global_stats(simcpu);\n        memcpy(simcpu->stats_shm_ptr, simcpu->stats,\n               NUM_MAX_PRV_LEVELS * sizeof(SimStats));\n    }\n}\n\nint\nset_max_clock_cycles_for_non_pipe_fu(RISCVCPUState *s, int fu_type,\n                                     InstructionLatch *e)\n{\n    switch (fu_type)\n    {\n        case FU_FPU_ALU:\n        {\n            return s->simcpu->params->fpu_alu_latency[e->ins.fpu_alu_type];\n        }\n    }\n\n    /* Default */\n    return 1;\n}\n\n/* Read the instruction from TinyEMU memory map into the instruction latch */\nvoid\nfetch_cpu_stage_exec(RISCVCPUState *s, InstructionLatch *e)\n{\n    e->max_clock_cycles = 1;\n    e->cache_lookup_complete_signal_sent = FALSE;\n    s->hw_pg_tb_wlk_stage_id = FETCH;\n    s->ins_tlb_lookup_accounted = FALSE;\n    s->ins_tlb_hit_accounted = FALSE;\n\n    /* Reset page walk delay before fetching current instruction. This is the\n     * cache hierarchy lookup delay for page table entries, on a TLB miss */\n    s->simcpu->mem_hierarchy->mem_controller->page_walk_delay = 0;\n\n    /* elasped_clock_cycles: number of CPU cycles spent by this instruction\n     * in fetch stage so far */\n    e->elasped_clock_cycles = 1;\n    s->simcpu->mem_hierarchy->mem_controller->frontend_mem_access_queue.cur_size\n        = 0;\n\n    /* Fetch instruction from TinyEMU memory map */\n    if (s->simcpu->temu_mem_map_wrapper->read_insn(s, e))\n    {\n        /* This instruction has raised a page fault exception during\n         * fetch */\n        e->ins.exception = TRUE;\n        e->ins.exception_cause = SIM_MMU_EXCEPTION;\n    }\n    else\n    {\n        /* max_clock_cycles: Number of CPU cycles required for TLB and Cache\n         * look-up */\n        e->max_clock_cycles\n            = s->simcpu->mem_hierarchy->mem_controller->page_walk_delay\n              + s->simcpu->mem_hierarchy->insn_read_delay(\n                    s->simcpu->mem_hierarchy, s->code_guest_paddr, 4, FETCH,\n                    s->priv);\n\n        sim_assert((e->max_clock_cycles), \"error: %s at line %d in %s(): %s\",\n                   __FILE__, __LINE__, __func__,\n                   \"max_clock_cycles execution latency for an instruction \"\n                   \"must be non_zero\");\n\n        /* Increment PC for the next instruction */\n        if (3 == (e->ins.binary & 3))\n        {\n            s->code_ptr = s->code_ptr + 4;\n            s->code_guest_paddr = s->code_guest_paddr + 4;\n        }\n        else\n        {\n            /* For compressed */\n            s->code_ptr = s->code_ptr + 2;\n            s->code_guest_paddr = s->code_guest_paddr + 2;\n        }\n\n        /* Probe the branch predictor */\n        s->simcpu->bpu_fetch_stage_handler(s, e);\n\n        ++s->simcpu->stats[s->priv].ins_fetch;\n    }\n}\n\nvoid\ndecode_cpu_stage_exec(RISCVCPUState *s, InstructionLatch *e)\n{\n    /* For decoding floating point instructions */\n    e->ins.current_fs = s->fs;\n    e->ins.rm = get_insn_rm(s, (e->ins.binary >> 12) & 7);\n\n    /* Decode the instruction */\n    decode_riscv_binary(&e->ins, e->ins.binary);\n}\n\n/* Read/Write data to/from TinyEMU memory map into the instruction latch and set\n * latency in clock cycles for the access */\nvoid\nmem_cpu_stage_exec(RISCVCPUState *s, InstructionLatch *e)\n{\n    e->max_clock_cycles = 1;\n    e->cache_lookup_complete_signal_sent = FALSE;\n    s->hw_pg_tb_wlk_stage_id = MEMORY;\n\n    /* Reset page walk delay before executing current memory instruction. This\n     * is the cache hierarchy lookup delay for page table entries, on a TLB miss */\n    s->simcpu->mem_hierarchy->mem_controller->page_walk_delay = 0;\n\n    if (s->simcpu->temu_mem_map_wrapper->exec_load_store_atomic(s, e))\n    {\n        /* This load, store or atomic instruction raised a page\n         * fault exception */\n        e->ins.exception = TRUE;\n        e->ins.exception_cause = SIM_MMU_EXCEPTION;\n    }\n    else\n    {\n        /* Memory access was successful, no page fault, so calculate the memory\n         * access latency */\n        e->max_clock_cycles\n            = s->simcpu->mem_hierarchy->mem_controller->page_walk_delay;\n\n        if (s->is_device_io || !s->data_guest_paddr)\n        {\n            /* This was a non RAM access, probably a device, so set\n             * max_clock_cycles to 1 */\n            e->max_clock_cycles += 1;\n        }\n        else\n        {\n            /* RAM access */\n            if ((e->ins.is_load || e->ins.is_atomic_load))\n            {\n                e->max_clock_cycles\n                    += s->simcpu->mem_hierarchy->data_read_delay(\n                        s->simcpu->mem_hierarchy, s->data_guest_paddr,\n                        e->ins.bytes_to_rw, MEMORY, s->priv);\n\n                /* Load for non-word quantities such as byte or half word take\n                 * an extra cycle */\n                if (e->ins.bytes_to_rw < 4)\n                {\n                    e->max_clock_cycles += 1;\n                }\n            }\n\n            if ((e->ins.is_store || e->ins.is_atomic_store))\n            {\n                e->max_clock_cycles += 1;\n                s->simcpu->mem_hierarchy->data_write_delay(\n                    s->simcpu->mem_hierarchy, s->data_guest_paddr,\n                    e->ins.bytes_to_rw, MEMORY, s->priv);\n            }\n        }\n\n        sim_assert((e->max_clock_cycles), \"error: %s at line %d in %s(): %s\",\n                   __FILE__, __LINE__, __func__,\n                   \"max_clock_cycles execution latency for an instruction \"\n                   \"must be non_zero\");\n    }\n}\n\nvoid\nriscv_sim_cpu_start(RISCVSIMCPUState *simcpu, target_ulong pc)\n{\n    if (!simcpu->simulation)\n    {\n        simcpu->simulation = TRUE;\n        simcpu->clock = 0;\n        simcpu->icount = 0;\n\n        sim_stats_reset(simcpu->stats);\n        GET_TIME(simcpu->sim_start_time);\n\n        simcpu->temu_rtc_time_at_simstart\n            = rtc_get_elasped_time(simcpu->emu_cpu_state->rtc);\n\n        /* Reset BPU at every new simulation run */\n        if (simcpu->params->enable_bpu && simcpu->params->flush_bpu_on_simstart)\n        {\n            bpu_flush(simcpu->bpu);\n        }\n\n        /* Reset Caches at every new simulation run */\n        if (simcpu->params->enable_l1_caches)\n        {\n            cache_reset_stats(simcpu->mem_hierarchy->icache);\n            cache_reset_stats(simcpu->mem_hierarchy->dcache);\n\n            if (simcpu->params->flush_sim_mem_on_simstart)\n            {\n                cache_flush(simcpu->mem_hierarchy->icache);\n                cache_flush(simcpu->mem_hierarchy->dcache);\n            }\n\n            if (simcpu->params->enable_l2_cache)\n            {\n                cache_reset_stats(simcpu->mem_hierarchy->l2_cache);\n\n                if (simcpu->params->flush_sim_mem_on_simstart)\n                {\n                    cache_flush(simcpu->mem_hierarchy->l2_cache);\n                }\n            }\n        }\n\n        /* Reset DRAMs at every new simulation run */\n        switch (simcpu->mem_hierarchy->mem_controller->dram_model_type)\n        {\n            case MEM_MODEL_BASE:\n            {\n                break;\n            }\n            case MEM_MODEL_DRAMSIM:\n            {\n                dramsim_wrapper_destroy();\n                dramsim_wrapper_init(simcpu->params->dramsim_config_file,\n                                     simcpu->params->sim_file_path);\n                break;\n            }\n            case MEM_MODEL_RAMULATOR:\n            {\n                break;\n            }\n        }\n\n        /* Open trace file if running in trace mode */\n        if (simcpu->params->do_sim_trace)\n        {\n            simcpu->params->create_ins_str = TRUE;\n            sim_log_event(sim_log, \"Starting simulation trace \"\n                                   \"at pc = 0x%\" PR_target_ulong \" in file: %s\",\n                          pc, simcpu->params->sim_trace_file);\n            sim_trace_start(simcpu->trace, simcpu->params->sim_trace_file);\n        }\n\n        sim_log_event(sim_log, \"Switching to full-system simulation \"\n                               \"mode at pc = 0x%\" PR_target_ulong,\n                      pc);\n    }\n}\n\nvoid\nriscv_sim_cpu_stop(RISCVSIMCPUState *simcpu, target_ulong pc)\n{\n    char *timestamp;\n    uint64_t sim_time;\n\n    if (simcpu->simulation)\n    {\n        simcpu->simulation = FALSE;\n        GET_TIME(simcpu->sim_end_time);\n        sim_time = GET_TIMER_DIFF(simcpu->sim_start_time, simcpu->sim_end_time)\n                   / 1000000;\n\n        print_performance_summary(simcpu, sim_time);\n\n        timestamp\n            = sim_log_get_current_timestamp(simcpu->params->sim_file_prefix);\n\n        switch (simcpu->mem_hierarchy->mem_controller->dram_model_type)\n        {\n            case MEM_MODEL_BASE:\n            {\n                break;\n            }\n            case MEM_MODEL_DRAMSIM:\n            {\n                dramsim_wrapper_print_stats(timestamp);\n                sim_log_event(\n                    sim_log,\n                    \"Saved dramsim3 statistics in %s/dramsim3_%s.json\",\n                    simcpu->params->sim_file_path, timestamp);\n                break;\n            }\n            case MEM_MODEL_RAMULATOR:\n            {\n                ramulator_wrapper_finish();\n                ramulator_wrapper_print_stats(simcpu->params->sim_file_path,\n                                              timestamp);\n                sim_log_event(\n                    sim_log,\n                    \"Saved ramulator statistics in %s/ramulator_%s.stats\",\n                    simcpu->params->sim_file_path, timestamp);\n                break;\n            }\n        }\n\n        if (simcpu->params->do_sim_trace)\n        {\n            sim_trace_stop(simcpu->trace);\n            sim_log_event(sim_log, \"Saved simulation trace in %s\",\n                          simcpu->params->sim_trace_file);\n        }\n\n        copy_cache_stats_to_global_stats(simcpu);\n        sim_stats_print_to_file(simcpu->stats, simcpu->params->sim_file_path,\n                                sim_time, timestamp);\n\n        sim_log_event(sim_log, \"Switching to emulation mode \"\n                               \"mode at pc = 0x%\" PR_target_ulong,\n                      pc);\n\n        free(timestamp);\n    }\n}\n\nvoid\nriscv_sim_cpu_reset(RISCVSIMCPUState *simcpu)\n{\n    simcpu->exception->pending = FALSE;\n    simcpu->skip_fetch_cycle = FALSE;\n    reset_insn_latch_pool(simcpu->insn_latch_pool);\n    mem_controller_reset(simcpu->mem_hierarchy->mem_controller);\n    simcpu->core_reset(simcpu->core);\n}\n\nint\nriscv_sim_cpu_switch_to_cpu_simulation(RISCVSIMCPUState *simcpu)\n{\n    int sim_exit_status;\n\n    riscv_sim_cpu_reset(simcpu);\n    sim_exit_status = simcpu->core_run(simcpu->core);\n\n    /* Every-time we exit to TinyEMU emulation loop, simulated CPU pipeline has\n     * been flushed and drained  */\n    ++simcpu->stats[simcpu->emu_cpu_state->priv].pipeline_flush;\n\n    return sim_exit_status;\n}\n\nRISCVSIMCPUState *\nriscv_sim_cpu_init(const SimParams *p, struct RISCVCPUState *s)\n{\n    RISCVSIMCPUState *simcpu;\n\n    simcpu = calloc(1, sizeof(RISCVSIMCPUState));\n    assert(simcpu);\n\n    simcpu->emu_cpu_state = s;\n    simcpu->pc = 0x1000;\n    simcpu->clock = 0;\n    simcpu->params = (SimParams *)p;\n    simcpu->return_to_sim = FALSE;\n\n    simcpu->stats = (SimStats *)calloc(NUM_MAX_PRV_LEVELS, sizeof(SimStats));\n    assert(simcpu->stats != NULL);\n\n    simcpu->insn_latch_pool = (InstructionLatch *)calloc(\n        INSN_LATCH_POOL_SIZE, sizeof(InstructionLatch));\n    assert(simcpu->insn_latch_pool);\n\n    sim_params_log_options(p);\n\n    switch (p->core_type)\n    {\n        case CORE_TYPE_INCORE:\n        {\n            simcpu->core = (void *)in_core_init(simcpu->params, simcpu);\n            simcpu->core_reset = in_core_reset;\n            simcpu->core_run = in_core_run;\n            simcpu->core_free = in_core_free;\n            break;\n        }\n        case CORE_TYPE_OOCORE:\n        {\n            simcpu->core = (void *)oo_core_init(simcpu->params, simcpu);\n            simcpu->core_reset = oo_core_reset;\n            simcpu->core_run = oo_core_run;\n            simcpu->core_free = oo_core_free;\n            break;\n        }\n    }\n\n    sim_params_log_exec_unit_config(p);\n\n    simcpu->mem_hierarchy = memory_hierarchy_init(simcpu->params, sim_log);\n\n    /* Seed for random eviction, if used in BPU and caches */\n    srand(time(NULL));\n\n    if (p->enable_bpu)\n    {\n        simcpu->bpu = bpu_init(p, simcpu->stats);\n        simcpu->bpu_fetch_stage_handler = &bpu_enabled_fetch_stage_handler;\n        simcpu->bpu_decode_stage_handler = &bpu_enabled_decode_stage_handler;\n        simcpu->bpu_execute_stage_handler = &bpu_enabled_execute_stage_handler;\n    }\n    else\n    {\n        simcpu->bpu_fetch_stage_handler = &bpu_disabled_fetch_stage_handler;\n        simcpu->bpu_decode_stage_handler = &bpu_disabled_decode_stage_handler;\n        simcpu->bpu_execute_stage_handler = &bpu_disabled_execute_stage_handler;\n    }\n\n    simcpu->temu_mem_map_wrapper = temu_mem_map_wrapper_init();\n    simcpu->exception = sim_exception_init();\n    simcpu->trace = sim_trace_init();\n\n    if (p->enable_stats_display)\n    {\n        setup_stats_shm(simcpu);\n    }\n\n    sim_assert((sim_file_path_valid(p->sim_file_path)),\n               \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__, __func__,\n               \"top-level stats directory not found\");\n    return simcpu;\n}\n\nvoid\nriscv_sim_cpu_free(RISCVSIMCPUState **simcpu)\n{\n    free((*simcpu)->stats);\n    (*simcpu)->stats = NULL;\n\n    free((*simcpu)->insn_latch_pool);\n    (*simcpu)->insn_latch_pool = NULL;\n\n    memory_hierarchy_free(&((*simcpu)->mem_hierarchy));\n\n    if ((*simcpu)->params->enable_bpu)\n    {\n        bpu_free(&((*simcpu)->bpu));\n    }\n\n    (*simcpu)->core_free(&(*simcpu)->core);\n    temu_mem_map_wrapper_free(&(*simcpu)->temu_mem_map_wrapper);\n    sim_exception_free(&(*simcpu)->exception);\n    sim_trace_free(&(*simcpu)->trace);\n    free(*simcpu);\n}\n"
  },
  {
    "path": "src/riscvsim/core/riscv_sim_cpu.h",
    "content": "/**\n * RISCV Simulated CPU State\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _RISCV_SIM_CPU_H_\n#define _RISCV_SIM_CPU_H_\n\n#include <time.h>\n\n#include \"../bpu/bpu.h\"\n#include \"../memory_hierarchy/memory_hierarchy.h\"\n#include \"../memory_hierarchy/temu_mem_map_wrapper.h\"\n#include \"../riscv_sim_typedefs.h\"\n#include \"../utils/cpu_latches.h\"\n#include \"../utils/sim_exception.h\"\n#include \"../utils/sim_params.h\"\n#include \"../utils/sim_stats.h\"\n#include \"../utils/sim_trace.h\"\n\n/* Forward declare */\nstruct RISCVCPUState;\n\ntypedef struct RISCVSIMCPUState\n{\n    int core_id;     /* Core ID */\n    target_ulong pc; /* Next PC to fetch from */\n    uint64_t clock;  /* Clock cycles elapsed since simulation start  */\n    uint64_t icount; /* Total instructions committed in simulation mode */\n    uint64_t\n        temu_rtc_time_at_simstart; /* To save TinyEMU's emulated mtime value\n                                      before switching to simulation mode.\n                                      During simulation, mtime increase as\n                                      (temu_rtc_time_at_simstart + clock) */\n    int skip_fetch_cycle;\n\n    /* Simulator maintains a pool of free instruction latches known as\n     * insn_latch_pool. Every instruction fetched into the pipeline is allocated\n     * a instruction latch from this pool. The pointer of this latch is passed\n     * across the pipeline stages when the instruction advances through the\n     * pipeline. When the instruction commits, the latch is added back to the\n     * pool for reuse by following instructions. */\n    InstructionLatch *insn_latch_pool;\n\n    SimStats *stats;\n    SimParams *params;\n    BranchPredUnit *bpu;\n\n    /* Memory hierarchy to simulate the delays We do not model the actual data\n     * in the hierarchy for simplicity, but just the addresses for simulating\n     * the delays.*/\n    MemoryHierarchy *mem_hierarchy;\n\n    /* Wrapper over TinyEMU memory map used by the simulator to fetch\n     * instructions and read/write data (loads, stores and atomics) from the\n     * emulated guest physical memory */\n    TemuMemMapWrapper *temu_mem_map_wrapper;\n\n    /* If an exception occurs, simulator sets the exception object, which is\n     * used by TinyEMU helper functions to set up CPU context */\n    SimException *exception;\n\n    /* For generating simulation trace */\n    SimTrace *trace;\n\n    /* Pointer to shared memory area to write stats, which is read by\n     * sim-stats-display tool */\n    SimStats *stats_shm_ptr;\n\n    /* Used to enable/disable simulation mode, measure simulation time */\n    int simulation;\n    int return_to_sim;\n    struct timespec sim_start_time;\n    struct timespec sim_end_time;\n\n    /* BPU handler routines when BPU is enabled or disabled */\n    void (*bpu_fetch_stage_handler)(struct RISCVCPUState *, InstructionLatch *);\n    int (*bpu_decode_stage_handler)(struct RISCVCPUState *, InstructionLatch *);\n    int (*bpu_execute_stage_handler)(struct RISCVCPUState *,\n                                     InstructionLatch *);\n\n    struct RISCVCPUState *emu_cpu_state; /* Pointer to emulated CPU state */\n\n    /*----------  Set based on core type: in-order or out-of-order  ----------*/\n    void *core;\n    void (*core_reset)(void *core);\n    void (*core_free)(void *core);\n    int (*core_run)(void *core);\n} RISCVSIMCPUState;\n\nRISCVSIMCPUState *riscv_sim_cpu_init(const SimParams *p,\n                                     struct RISCVCPUState *s);\nint riscv_sim_cpu_switch_to_cpu_simulation(RISCVSIMCPUState *simcpu);\nvoid riscv_sim_cpu_start(RISCVSIMCPUState *simcpu, target_ulong pc);\nvoid riscv_sim_cpu_stop(RISCVSIMCPUState *simcpu, target_ulong pc);\nvoid riscv_sim_cpu_reset(RISCVSIMCPUState *simcpu);\nvoid riscv_sim_cpu_free(RISCVSIMCPUState **simcpu);\n\nint get_data_mem_access_latency(struct RISCVCPUState *s, InstructionLatch *e);\nvoid fetch_cpu_stage_exec(struct RISCVCPUState *s, InstructionLatch *e);\nvoid mem_cpu_stage_exec(struct RISCVCPUState *s, InstructionLatch *e);\nvoid decode_cpu_stage_exec(struct RISCVCPUState *s, InstructionLatch *e);\nvoid update_arch_reg_int(struct RISCVCPUState *s, InstructionLatch *e);\nvoid update_arch_reg_fp(struct RISCVCPUState *s, InstructionLatch *e);\nvoid update_insn_commit_stats(struct RISCVCPUState *s, InstructionLatch *e);\nvoid write_stats_to_stats_display_shm(RISCVSIMCPUState *simcpu);\nint set_max_clock_cycles_for_non_pipe_fu(struct RISCVCPUState *s, int fu_type,\n                                         InstructionLatch *e);\n#endif\n"
  },
  {
    "path": "src/riscvsim/decoder/fp_decode_template.h",
    "content": "/*\n * Decode Logic for Floating Point Arithmetics\n *\n * Copyright (c) 2016 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#if F_SIZE == 32\n#define OPID 0\n#elif F_SIZE == 64\n#define OPID 1\n#elif F_SIZE == 128\n#define OPID 3\n#else\n#error unsupported F_SIZE\n#endif\n\ncase (0x00 << 2) | OPID: /* fadd */\ncase (0x01 << 2) | OPID: /* fsub */\ncase (0x02 << 2) | OPID: /* fmul */\ncase (0x03 << 2) | OPID: /* fdiv */\n{\n    if (ins->rm < 0)\n        goto exception;\n    ins->set_fs = TRUE;\n    ins->has_fp_src1 = TRUE;\n    ins->has_fp_src2 = TRUE;\n    ins->has_fp_dest = TRUE;\n    break;\n}\n\ncase (0x0b << 2) | OPID: /* fsqrt */\n{\n    if (ins->rm < 0)\n        goto exception;\n    ins->set_fs = TRUE;\n    ins->has_fp_src1 = TRUE;\n    ins->has_fp_dest = TRUE;\n    break;\n}\n\ncase (0x04 << 2) | OPID: /* sign inject */\n{\n    ins->set_fs = TRUE;\n    ins->has_fp_src1 = TRUE;\n    ins->has_fp_src2 = TRUE;\n    ins->has_fp_dest = TRUE;\n    break;\n}\n\ncase (0x05 << 2) | OPID: /* fmin-fmax */\n{\n    ins->set_fs = TRUE;\n    ins->has_fp_src1 = TRUE;\n    ins->has_fp_src2 = TRUE;\n    ins->has_fp_dest = TRUE;\n    break;\n}\n\ncase (0x18 << 2) | OPID: /* f-convert */\n{\n    if (ins->rm < 0)\n        goto exception;\n    ins->has_fp_src1 = TRUE;\n    ins->has_dest = TRUE;\n    break;\n}\n\ncase (0x14 << 2) | OPID: /* floating point comparisons */\n{\n    ins->has_dest = TRUE;\n    ins->has_fp_src1 = TRUE;\n    ins->has_fp_src2 = TRUE;\n    break;\n}\n\ncase (0x1a << 2) | OPID: /* floating point convert int-fp */\n{\n    if (ins->rm < 0)\n        goto exception;\n    ins->set_fs = TRUE;\n    ins->has_fp_dest = TRUE;\n    ins->has_src1 = TRUE;\n    break;\n}\n\ncase (0x08 << 2) | OPID: /* floating point convert */\n{\n    if (ins->rm < 0)\n        goto exception;\n    ins->set_fs = TRUE;\n    ins->has_fp_dest = TRUE;\n    ins->has_fp_src1 = TRUE;\n    break;\n}\n\ncase (0x1c << 2) | OPID: /* floating point move fp-int*/\n{\n    if (ins->rs2 != 0)\n        goto exception;\n    ins->has_dest = TRUE;\n    ins->has_fp_src1 = TRUE;\n    break;\n}\n\n#if F_SIZE <= BIT_SIZE\ncase (0x1e << 2) | OPID: /* fmv.s.x */\n{\n    if ((ins->rs2 != 0) || (ins->rm != 0))\n        goto exception;\n    ins->has_fp_dest = TRUE;\n    ins->has_src1 = TRUE;\n    break;\n}\n#endif /* F_SIZE <= BIT_SIZE */\n\n#undef F_SIZE\n#undef OPID\n"
  },
  {
    "path": "src/riscvsim/decoder/fp_execute_template.h",
    "content": "/*\n * Execute Logic for Floating Point Arithmetics\n *\n * Copyright (c) 2016 Fabrice Bellard\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#if F_SIZE == 32\n#define OPID 0\n#define F_HIGH F32_HIGH\n#elif F_SIZE == 64\n#define OPID 1\n#define F_HIGH F64_HIGH\n#elif F_SIZE == 128\n#define OPID 3\n#define F_HIGH 0\n#else\n#error unsupported F_SIZE\n#endif\n\n#define FSIGN_MASK simglue(FSIGN_MASK, F_SIZE)\n\ncase (0x00 << 2) | OPID: /* fadd */\n    i->fpu_alu_type = FU_FPU_ALU_FADD;\n    i->buffer = simglue(add_sf, F_SIZE)(i->rs1_val, i->rs2_val,\n                                        (RoundingModeEnum)rm, fflags)\n                | F_HIGH;\n    i->type = INS_TYPE_FP_ADD;\n    break;\n\ncase (0x01 << 2) | OPID: /* fsub */\n    i->fpu_alu_type = FU_FPU_ALU_FSUB;\n    i->buffer = simglue(sub_sf, F_SIZE)(i->rs1_val, i->rs2_val,\n                                        (RoundingModeEnum)rm, fflags)\n                | F_HIGH;\n    break;\n\ncase (0x02 << 2) | OPID: /* fmul */\n    i->fpu_alu_type = FU_FPU_ALU_FMUL;\n    i->buffer = simglue(mul_sf, F_SIZE)(i->rs1_val, i->rs2_val,\n                                        (RoundingModeEnum)rm, fflags)\n                | F_HIGH;\n    i->type = INS_TYPE_FP_MUL;\n    break;\n\ncase (0x03 << 2) | OPID: /* fdiv */\n    i->fpu_alu_type = FU_FPU_ALU_FDIV;\n    i->buffer = simglue(div_sf, F_SIZE)(i->rs1_val, i->rs2_val,\n                                        (RoundingModeEnum)rm, fflags)\n                | F_HIGH;\n    i->type = INS_TYPE_FP_DIV_SQRT;\n    break;\n\ncase (0x0b << 2) | OPID: /* fsqrt */\n    i->fpu_alu_type = FU_FPU_ALU_FSQRT;\n    i->buffer\n        = simglue(sqrt_sf, F_SIZE)(i->rs1_val, (RoundingModeEnum)rm, fflags)\n          | F_HIGH;\n    i->type = INS_TYPE_FP_DIV_SQRT;\n    break;\n\ncase (0x04 << 2) | OPID: /* sign inject */\n    i->fpu_alu_type = FU_FPU_ALU_FSGNJ;\n    switch (rm)\n    {\n        case 0: /* fsgnj */\n            i->buffer = (i->rs1_val & ~FSIGN_MASK) | (i->rs2_val & FSIGN_MASK);\n            break;\n        case 1: /* fsgnjn */\n            i->buffer = (i->rs1_val & ~FSIGN_MASK)\n                        | ((i->rs2_val & FSIGN_MASK) ^ FSIGN_MASK);\n            break;\n        case 2: /* fsgnjx */\n            i->buffer = i->rs1_val ^ (i->rs2_val & FSIGN_MASK);\n            break;\n    }\n    break;\n\ncase (0x05 << 2) | OPID:\n    switch (rm)\n    {\n        case 0: /* fmin */\n            i->fpu_alu_type = FU_FPU_ALU_FMIN;\n            i->buffer = simglue(min_sf, F_SIZE)(i->rs1_val, i->rs2_val, fflags,\n                                                FMINMAX_IEEE754_201X)\n                        | F_HIGH;\n            break;\n        case 1: /* fmax */\n            i->fpu_alu_type = FU_FPU_ALU_FMAX;\n            i->buffer = simglue(max_sf, F_SIZE)(i->rs1_val, i->rs2_val, fflags,\n                                                FMINMAX_IEEE754_201X)\n                        | F_HIGH;\n            break;\n    }\n    break;\n\ncase (0x18 << 2) | OPID: /* f-convert */\n    i->fpu_alu_type = FU_FPU_ALU_FCVT;\n    switch (i->rs2)\n    {\n        case 0: /* fcvt.w.[sdq] */\n            i->buffer = (int32_t)simglue(simglue(cvt_sf, F_SIZE), _i32)(\n                i->rs1_val, (RoundingModeEnum)rm, fflags);\n            break;\n        case 1: /* fcvt.wu.[sdq] */\n            i->buffer = (int32_t)simglue(simglue(cvt_sf, F_SIZE), _u32)(\n                i->rs1_val, (RoundingModeEnum)rm, fflags);\n            break;\n#if BIT_SIZE >= 64\n        case 2: /* fcvt.l.[sdq] */\n            i->buffer = (int64_t)simglue(simglue(cvt_sf, F_SIZE), _i64)(\n                i->rs1_val, (RoundingModeEnum)rm, fflags);\n            break;\n        case 3: /* fcvt.lu.[sdq] */\n            i->buffer = (int64_t)simglue(simglue(cvt_sf, F_SIZE), _u64)(\n                i->rs1_val, (RoundingModeEnum)rm, fflags);\n            break;\n#endif\n    }\n    break;\n\ncase (0x14 << 2) | OPID:\n    switch (rm)\n    {\n        case 0: /* fle */\n            i->fpu_alu_type = FU_FPU_ALU_FLE;\n            i->buffer = simglue(le_sf, F_SIZE)(i->rs1_val, i->rs2_val, fflags);\n            break;\n        case 1: /* flt */\n            i->fpu_alu_type = FU_FPU_ALU_FLT;\n            i->buffer = simglue(lt_sf, F_SIZE)(i->rs1_val, i->rs2_val, fflags);\n            break;\n        case 2: /* feq */\n            i->fpu_alu_type = FU_FPU_ALU_FEQ;\n            i->buffer\n                = simglue(eq_quiet_sf, F_SIZE)(i->rs1_val, i->rs2_val, fflags);\n            break;\n    }\n    break;\n\ncase (0x1a << 2) | OPID:\n    i->fpu_alu_type = FU_FPU_ALU_FCVT;\n    switch (i->rs2)\n    {\n        case 0: /* fcvt.[sdq].w */\n            i->buffer = simglue(cvt_i32_sf, F_SIZE)(\n                            i->rs1_val, (RoundingModeEnum)rm, fflags)\n                        | F_HIGH;\n            break;\n        case 1: /* fcvt.[sdq].wu */\n            i->buffer = simglue(cvt_u32_sf, F_SIZE)(\n                            i->rs1_val, (RoundingModeEnum)rm, fflags)\n                        | F_HIGH;\n            break;\n#if BIT_SIZE >= 64\n        case 2: /* fcvt.[sdq].l */\n            i->buffer = simglue(cvt_i64_sf, F_SIZE)(\n                            i->rs1_val, (RoundingModeEnum)rm, fflags)\n                        | F_HIGH;\n            break;\n        case 3: /* fcvt.[sdq].lu */\n            i->buffer = simglue(cvt_u64_sf, F_SIZE)(\n                            i->rs1_val, (RoundingModeEnum)rm, fflags)\n                        | F_HIGH;\n            break;\n#endif\n    }\n    break;\n\ncase (0x08 << 2) | OPID:\n    i->fpu_alu_type = FU_FPU_ALU_CVT;\n    switch (i->rs2)\n    {\n#if F_SIZE == 32 && FLEN >= 64\n        case 1: /* cvt.s.d */\n            i->buffer = cvt_sf64_sf32(i->rs1_val, (RoundingModeEnum)rm, fflags)\n                        | F32_HIGH;\n            break;\n#endif /* F_SIZE == 32 */\n#if F_SIZE == 64\n        case 0: /* cvt.d.s */\n            i->buffer = cvt_sf32_sf64(i->rs1_val, fflags) | F64_HIGH;\n            break;\n#endif /* F_SIZE == 64 */\n    }\n    break;\n\ncase (0x1c << 2) | OPID:\n    i->fpu_alu_type = FU_FPU_ALU_FMV;\n    switch (rm)\n    {\n#if F_SIZE <= BIT_SIZE\n        case 0: /* fmv.x.s */\n#if F_SIZE == 32\n            i->buffer = (int32_t)i->rs1_val;\n#elif F_SIZE == 64\n            i->buffer = (int64_t)i->rs1_val;\n#else\n            i->buffer = (int128_t)i->rs1_val;\n#endif\n            break;\n#endif          /* F_SIZE <= BIT_SIZE */\n        case 1: /* fclass */\n            i->fpu_alu_type = FU_FPU_ALU_FCLASS;\n            i->buffer = simglue(fclass_sf, F_SIZE)(i->rs1_val);\n            break;\n    }\n    break;\n\n#if F_SIZE <= BIT_SIZE\ncase (0x1e << 2) | OPID: /* fmv.s.x */\n    i->fpu_alu_type = FU_FPU_ALU_FMV;\n#if F_SIZE == 32\n    i->buffer = (int32_t)i->rs1_val;\n#elif F_SIZE == 64\n    i->buffer = (int64_t)i->rs1_val;\n#else\n    i->buffer = (int128_t)i->rs1_val;\n#endif\n    break;\n#endif /* F_SIZE <= BIT_SIZE */\n\n#undef F_SIZE\n#undef F_HIGH\n#undef OPID\n#undef FSIGN_MASK\n"
  },
  {
    "path": "src/riscvsim/decoder/fp_string_generator_template.h",
    "content": "/*\n * Instruction String Generation Logic for Floating Point Arithmetics\n *\n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#if F_SIZE == 32\n#define OPID 0\n#define F_HIGH F32_HIGH\n#elif F_SIZE == 64\n#define OPID 1\n#define F_HIGH F64_HIGH\n#elif F_SIZE == 128\n#define OPID 3\n#define F_HIGH 0\n#else\n#error unsupported F_SIZE\n#endif\n\ncase (0x00 << 2) | OPID: /* fadd */\n{\n    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fadd%s %s,%s,%s\",\n             get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd], fp_reg[i->rs1],\n             fp_reg[i->rs2]);\n    break;\n}\n\ncase (0x01 << 2) | OPID: /* fsub */\n{\n    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fsub%s %s,%s,%s\",\n             get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd], fp_reg[i->rs1],\n             fp_reg[i->rs2]);\n    break;\n}\n\ncase (0x02 << 2) | OPID: /* fmul */\n{\n    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fmul%s %s,%s,%s\",\n             get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd], fp_reg[i->rs1],\n             fp_reg[i->rs2]);\n    break;\n}\n\ncase (0x03 << 2) | OPID: /* fdiv */\n{\n    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fdiv%s %s,%s,%s\",\n             get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd], fp_reg[i->rs1],\n             fp_reg[i->rs2]);\n    break;\n}\n\ncase (0x0b << 2) | OPID: /* fsqrt */\n{\n    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fsqrt%s %s,%s\",\n             get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd], fp_reg[i->rs1]);\n    break;\n}\n\ncase (0x04 << 2) | OPID: /* sign inject */\n{\n    switch (rm)\n    {\n        case 0: /* fsgnj */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fsgnj%s %s,%s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd],\n                     fp_reg[i->rs1], fp_reg[i->rs2]);\n            break;\n        }\n        case 1: /* fsgnjn */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fsgnjn%s %s,%s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd],\n                     fp_reg[i->rs1], fp_reg[i->rs2]);\n            break;\n        }\n        case 2: /* fsgnjx */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fsgnjx%s %s,%s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd],\n                     fp_reg[i->rs1], fp_reg[i->rs2]);\n            break;\n        }\n    }\n    break;\n}\n\ncase (0x05 << 2) | OPID:\n{\n    switch (rm)\n    {\n        case 0: /* fmin */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fmin%s %s,%s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd],\n                     fp_reg[i->rs1], fp_reg[i->rs2]);\n            break;\n        }\n        case 1: /* fmax */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fmax%s %s,%s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd],\n                     fp_reg[i->rs1], fp_reg[i->rs2]);\n            break;\n        }\n    }\n    break;\n}\n\ncase (0x18 << 2) | OPID: /* f-convert */\n{\n    switch (i->rs2)\n    {\n        case 0: /* fcvt.w.[sdq] */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fcvt.w%s %s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], reg[i->rd],\n                     fp_reg[i->rs1]);\n            break;\n        }\n        case 1: /* fcvt.wu.[sdq] */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fcvt.wu%s %s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], reg[i->rd],\n                     fp_reg[i->rs1]);\n            break;\n        }\n#if BIT_SIZE >= 64\n        case 2: /* fcvt.l.[sdq] */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fcvt.l%s %s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], reg[i->rd],\n                     fp_reg[i->rs1]);\n            break;\n        }\n        case 3: /* fcvt.lu.[sdq] */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fcvt.lu%s %s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], reg[i->rd],\n                     fp_reg[i->rs1]);\n            break;\n        }\n#endif\n    }\n    break;\n}\n\ncase (0x14 << 2) | OPID:\n{\n    switch (rm)\n    {\n        case 0: /* fle */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fle%s %s,%s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], reg[i->rd], fp_reg[i->rs1],\n                     fp_reg[i->rs2]);\n            break;\n        }\n        case 1: /* flt */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"flt%s %s,%s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], reg[i->rd], fp_reg[i->rs1],\n                     fp_reg[i->rs2]);\n            break;\n        }\n        case 2: /* feq */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"feq%s %s,%s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], reg[i->rd], fp_reg[i->rs1],\n                     fp_reg[i->rs2]);\n            break;\n        }\n    }\n    break;\n}\n\ncase (0x1a << 2) | OPID:\n{\n    switch (i->rs2)\n    {\n        case 0: /* fcvt.[sdq].w */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fcvt%s.w %s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd],\n                     reg[i->rs1]);\n            break;\n        }\n        case 1: /* fcvt.[sdq].wu */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fcvt%s.wu %s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd],\n                     reg[i->rs1]);\n            break;\n        }\n#if BIT_SIZE >= 64\n        case 2: /* fcvt.[sdq].l */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fcvt%s.l %s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd],\n                     reg[i->rs1]);\n            break;\n        }\n        case 3: /* fcvt.[sdq].lu */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fcvt%s.lu %s,%s\",\n                     get_flen_suffix[(F_SIZE / 32)], fp_reg[i->rd],\n                     reg[i->rs1]);\n            break;\n        }\n#endif\n    }\n    break;\n}\n\ncase (0x08 << 2) | OPID:\n{\n    switch (i->rs2)\n    {\n#if F_SIZE == 32 && FLEN >= 64\n        case 1: /* cvt.s.d */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"cvt.s.d %s,%s\",\n                     fp_reg[i->rd], fp_reg[i->rs1]);\n            break;\n        }\n#endif /* F_SIZE == 32 */\n#if F_SIZE == 64\n        case 0: /* cvt.d.s */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"cvt.d.s %s,%s\",\n                     fp_reg[i->rd], fp_reg[i->rs1]);\n            break;\n        }\n#endif /* F_SIZE == 64 */\n    }\n    break;\n}\n\ncase (0x1c << 2) | OPID:\n{\n    switch (rm)\n    {\n#if F_SIZE <= BIT_SIZE\n        case 0: /* fmv.x.s */\n        {\n#if F_SIZE == 32\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fmv.x.s %s,%s\",\n                     reg[i->rd], fp_reg[i->rs1]);\n#elif F_SIZE == 64\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fmv.x.d %s,%s\",\n                     reg[i->rd], fp_reg[i->rs1]);\n#else\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fmv.x.q %s,%s\",\n                     reg[i->rd], fp_reg[i->rs1]);\n#endif\n            break;\n        }\n#endif          /* F_SIZE <= BIT_SIZE */\n        case 1: /* fclass */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fclass%s %s,%s\",\n                     get_flen_suffix[(F_SIZE) / 32], reg[i->rd],\n                     fp_reg[i->rs1]);\n            break;\n        }\n    }\n    break;\n}\n\n#if F_SIZE <= BIT_SIZE\ncase (0x1e << 2) | OPID: /* fmv.s.x */\n{\n#if F_SIZE == 32\n    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fmv.s.x %s,%s\", fp_reg[i->rd],\n             reg[i->rs1]);\n#elif F_SIZE == 64\n    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fmv.s.x %s,%s\", fp_reg[i->rd],\n             reg[i->rs1]);\n#else\n    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fmv.s.x %s,%s\", fp_reg[i->rd],\n             reg[i->rs1]);\n#endif\n    break;\n}\n#endif /* F_SIZE <= BIT_SIZE */\n\n#undef F_SIZE\n#undef F_HIGH\n#undef OPID\n#undef FSIGN_MASK\n"
  },
  {
    "path": "src/riscvsim/decoder/riscv_instruction.h",
    "content": "/**\n * RISC-V Instruction\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _RISCV_INSTRUCTION_H_\n#define _RISCV_INSTRUCTION_H_\n\n#include <inttypes.h>\n\n#include \"../riscv_sim_typedefs.h\"\n\ntypedef struct RVInstruction\n{\n    target_ulong pc;\n\n    /* 32-bit or 16-bit instruction */\n    uint32_t binary;\n\n    /* Compressed instruction quadrant number */\n    uint32_t quad;\n\n    /* Instruction function selectors */\n    int32_t major_opcode;\n    int32_t funct3;\n    int32_t funct4;\n    int32_t funct5;\n    int32_t funct7;\n\n    /* Decoded register addresses */\n    uint32_t rd;\n    uint32_t rs1;\n    uint32_t rs2;\n    uint32_t rs3;\n\n    /* Physical register addresses */\n    int old_pdest;\n    int pdest;\n    int prs1;\n    int prs2;\n    int prs3;\n\n    /* Decoded sign extended immediate values */\n    int32_t imm;\n\n    /* Rounding Mode, used by floating Point */\n    uint32_t rm;\n\n    /* Instruction string */\n    char str[RISCV_INS_STR_MAX_LENGTH];\n    int create_str;\n\n    int has_src1;\n    int has_src2;\n    int has_dest;\n\n    int has_fp_dest;\n    int has_fp_src1;\n    int has_fp_src2;\n    int has_fp_src3;\n    int f32_mask;\n    int f64_mask;\n    int set_fs;\n    int current_fs;\n\n    int is_atomic;\n    int is_atomic_load;\n    int is_atomic_store;\n    int is_atomic_operate;\n\n    int is_load;\n    int is_store;\n    int bytes_to_rw;\n    int is_unsigned;\n    target_ulong mem_addr;\n\n    int is_branch;\n    int branch_type;\n    int32_t cond;\n    target_ulong target;\n\n    int fu_type;\n    int fpu_alu_type;\n    int is_system;\n    int is_func_call;\n    int is_func_ret;\n\n    uint64_t buffer;\n    uint64_t rs1_val;\n    uint64_t rs2_val;\n    uint64_t rs3_val;\n\n    int exception;\n    int exception_cause;\n\n    /* for updating performance counters */\n    int type;\n    int data_class;\n} RVInstruction;\n\n/* Decode RISC-V instruction in binary format and fill the decoded information\n * in RVInstruction struct */\nvoid decode_riscv_binary(RVInstruction *, uint32_t);\nvoid generate_riscv_instruction_string(RVInstruction *i);\nvoid execute_riscv_instruction(RVInstruction *i, uint32_t *fflags);\n#endif /* End RVInstruction */\n"
  },
  {
    "path": "src/riscvsim/decoder/riscv_isa_decoder.c",
    "content": "/**\n * RISC-V Instruction Decoding Logic\n *\n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../../cutils.h\"\n#include \"../riscv_sim_typedefs.h\"\n#include \"riscv_instruction.h\"\n\nstatic inline int32_t\nsextc(int32_t val, int n)\n{\n    return (val << (32 - n)) >> (32 - n);\n}\n\nstatic inline uint32_t\ncget_field1(uint32_t val, int src_pos, int dst_pos, int dst_pos_max)\n{\n    int mask;\n    assert(dst_pos_max >= dst_pos);\n    mask = ((1 << (dst_pos_max - dst_pos + 1)) - 1) << dst_pos;\n    if (dst_pos >= src_pos)\n        return (val << (dst_pos - src_pos)) & mask;\n    else\n        return (val >> (src_pos - dst_pos)) & mask;\n}\n\nstatic void\ndecode_compressed_q0(struct RVInstruction *ins)\n{\n    uint32_t insn, rd, rs1, rs2, funct3, quad;\n    int32_t imm;\n\n    insn = ins->binary;\n    funct3 = (insn >> 13) & 7;\n    rd = ((insn >> 2) & 7) | 8;\n    rs2 = rd;\n    quad = C_QUADRANT0;\n    switch (funct3)\n    {\n        case 0: /* c.addi4spn */\n        {\n            ins->has_dest = TRUE;\n            ins->has_src1 = TRUE;\n            rs1 = 2;\n            imm = cget_field1(insn, 11, 4, 5) | cget_field1(insn, 7, 6, 9)\n                  | cget_field1(insn, 6, 2, 2) | cget_field1(insn, 5, 3, 3);\n            if (imm == 0)\n                goto illegal_insn;\n            break;\n        }\n#if SIM_FLEN >= 64\n        case 1: /* c.fld */\n        {\n            if (ins->current_fs == 0)\n                goto illegal_insn;\n            ins->is_load = TRUE;\n            ins->has_fp_dest = TRUE;\n            ins->has_src1 = TRUE;\n            ins->bytes_to_rw = 8;\n            ins->f64_mask = TRUE;\n            ins->set_fs = TRUE;\n            ins->type = INS_TYPE_FP_LOAD;\n            imm = cget_field1(insn, 10, 3, 5) | cget_field1(insn, 5, 6, 7);\n            rs1 = ((insn >> 7) & 7) | 8;\n            break;\n        }\n#endif\n        case 2: /* c.lw */\n        {\n            ins->is_load = TRUE;\n            ins->has_dest = TRUE;\n            ins->has_src1 = TRUE;\n            ins->bytes_to_rw = 4;\n            ins->type = INS_TYPE_LOAD;\n            imm = cget_field1(insn, 10, 3, 5) | cget_field1(insn, 6, 2, 2)\n                  | cget_field1(insn, 5, 6, 6);\n            rs1 = ((insn >> 7) & 7) | 8;\n            break;\n        }\n#if defined(RV64)\n        case 3: /* c.ld */\n        {\n            ins->is_load = TRUE;\n            ins->has_dest = TRUE;\n            ins->has_src1 = TRUE;\n            ins->bytes_to_rw = 8;\n            ins->type = INS_TYPE_LOAD;\n            imm = cget_field1(insn, 10, 3, 5) | cget_field1(insn, 5, 6, 7);\n            rs1 = ((insn >> 7) & 7) | 8;\n            break;\n        }\n#elif SIM_FLEN >= 32\n        case 3: /* c.flw */\n        {\n            ins->is_load = TRUE;\n            ins->has_fp_dest = TRUE;\n            ins->has_src1 = TRUE;\n            ins->bytes_to_rw = 4;\n            ins->f32_mask = TRUE;\n            ins->set_fs = TRUE;\n            ins->type = INS_TYPE_FP_LOAD;\n            imm = cget_field1(insn, 10, 3, 5) | cget_field1(insn, 6, 2, 2)\n                  | cget_field1(insn, 5, 6, 6);\n            rs1 = ((insn >> 7) & 7) | 8;\n            break;\n        }\n#endif\n#if SIM_FLEN >= 64\n        case 5: /* c.fsd */\n        {\n            ins->is_store = TRUE;\n            ins->has_src1 = TRUE;\n            ins->has_fp_src2 = TRUE;\n            ins->bytes_to_rw = 8;\n            ins->type = INS_TYPE_FP_STORE;\n            imm = cget_field1(insn, 10, 3, 5) | cget_field1(insn, 5, 6, 7);\n            rs1 = ((insn >> 7) & 7) | 8;\n            break;\n        }\n#endif\n        case 6: /* c.sw */\n        {\n            ins->is_store = TRUE;\n            ins->has_src1 = TRUE;\n            ins->has_src2 = TRUE;\n            ins->bytes_to_rw = 4;\n            ins->type = INS_TYPE_STORE;\n            imm = cget_field1(insn, 10, 3, 5) | cget_field1(insn, 6, 2, 2)\n                  | cget_field1(insn, 5, 6, 6);\n            rs1 = ((insn >> 7) & 7) | 8;\n            break;\n        }\n#if defined(RV64)\n        case 7: /* c.sd */\n        {\n            ins->is_store = TRUE;\n            ins->has_src1 = TRUE;\n            ins->has_src2 = TRUE;\n            ins->bytes_to_rw = 8;\n            ins->type = INS_TYPE_STORE;\n            imm = cget_field1(insn, 10, 3, 5) | cget_field1(insn, 5, 6, 7);\n            rs1 = ((insn >> 7) & 7) | 8;\n            break;\n        }\n#elif SIM_FLEN >= 32\n        case 7: /* c.fsw */\n        {\n            ins->is_store = TRUE;\n            ins->has_src1 = TRUE;\n            ins->has_fp_src2 = TRUE;\n            ins->bytes_to_rw = 4;\n            ins->type = INS_TYPE_FP_STORE;\n            imm = cget_field1(insn, 10, 3, 5) | cget_field1(insn, 6, 2, 2)\n                  | cget_field1(insn, 5, 6, 6);\n            rs1 = ((insn >> 7) & 7) | 8;\n            break;\n        }\n#endif\n        default:\n            goto illegal_insn;\n    }\n    ins->rd = rd;\n    ins->rs1 = rs1;\n    ins->rs2 = rs2;\n    ins->funct3 = funct3;\n    ins->imm = imm;\n    ins->quad = quad;\n    return;\nillegal_insn:\n    ins->exception = TRUE;\n    ins->exception_cause = SIM_ILLEGAL_OPCODE_EXCEPTION;\n}\n\nstatic void\ndecode_compressed_q1(struct RVInstruction *ins)\n{\n    uint32_t insn, rd, rs1, rs2 = 0, funct3, funct4 = 0, funct5 = 0, quad;\n    int32_t imm = 0;\n\n    insn = ins->binary;\n    funct3 = (insn >> 13) & 7;\n    rd = (insn >> 7) & 0x1f;\n    rs1 = rd;\n    quad = C_QUADRANT1;\n    switch (funct3)\n    {\n        case 0: /* c.addi/c.nop */\n        {\n            ins->has_dest = TRUE;\n            ins->has_src1 = TRUE;\n            imm = sextc(\n                cget_field1(insn, 12, 5, 5) | cget_field1(insn, 2, 0, 4), 6);\n            break;\n        }\n#if defined(RV32)\n        case 1: /* c.jal */\n        {\n            ins->has_dest = TRUE;\n            ins->is_branch = TRUE;\n            ins->branch_type = BRANCH_UNCOND;\n            ins->type = INS_TYPE_JAL;\n            rd = 1;\n            imm = sextc(\n                cget_field1(insn, 12, 11, 11) | cget_field1(insn, 11, 4, 4)\n                    | cget_field1(insn, 9, 8, 9) | cget_field1(insn, 8, 10, 10)\n                    | cget_field1(insn, 7, 6, 6) | cget_field1(insn, 6, 7, 7)\n                    | cget_field1(insn, 3, 1, 3) | cget_field1(insn, 2, 5, 5),\n                12);\n            ins->is_func_call = TRUE;\n            break;\n        }\n#elif defined(RV64)\n        case 1: /* c.addiw */\n        {\n            ins->has_dest = TRUE;\n            ins->has_src1 = TRUE;\n            imm = sextc(\n                cget_field1(insn, 12, 5, 5) | cget_field1(insn, 2, 0, 4), 6);\n            break;\n        }\n#endif\n        case 2: /* c.li */\n        {\n            ins->has_dest = TRUE;\n            imm = sextc(\n                cget_field1(insn, 12, 5, 5) | cget_field1(insn, 2, 0, 4), 6);\n            break;\n        }\n        case 3:\n        {\n            if (rd == 2)\n            {\n                /* c.addi16sp */\n                ins->has_dest = TRUE;\n                ins->has_src1 = TRUE;\n                rd = 2;\n                rs1 = rd;\n                imm = sextc(cget_field1(insn, 12, 9, 9)\n                                | cget_field1(insn, 6, 4, 4)\n                                | cget_field1(insn, 5, 6, 6)\n                                | cget_field1(insn, 3, 7, 8)\n                                | cget_field1(insn, 2, 5, 5),\n                            10);\n                if (imm == 0)\n                    goto illegal_insn;\n            }\n            else if (rd != 0)\n            {\n                /* c.lui */\n                ins->has_dest = TRUE;\n                imm = sextc(cget_field1(insn, 12, 17, 17)\n                                | cget_field1(insn, 2, 12, 16),\n                            18);\n            }\n            break;\n        }\n        case 4:\n        {\n            ins->has_dest = TRUE;\n            ins->has_src1 = TRUE;\n            funct4 = (insn >> 10) & 3;\n            rd = ((insn >> 7) & 7) | 8;\n            rs1 = rd;\n            switch (funct4)\n            {\n                case 0: /* c.srli */\n                case 1: /* c.srai */\n                    imm = cget_field1(insn, 12, 5, 5)\n                          | cget_field1(insn, 2, 0, 4);\n#if defined(RV32)\n                    if (imm & 0x20)\n                        goto illegal_insn;\n#endif\n                    break;\n                case 2: /* c.andi */\n                    imm = sextc(cget_field1(insn, 12, 5, 5)\n                                    | cget_field1(insn, 2, 0, 4),\n                                6);\n                    break;\n                case 3:\n                    rs2 = ((insn >> 2) & 7) | 8;\n                    ins->has_src2 = TRUE;\n                    funct5 = ((insn >> 5) & 3) | ((insn >> (12 - 2)) & 4);\n                    switch (funct5)\n                    {\n                        case 0: /* c.sub */\n                        case 1: /* c.xor */\n                        case 2: /* c.or */\n                        case 3: /* c.and */\n#if defined(RV64)\n                        case 4: /* c.subw */\n                        case 5: /* c.addw */\n#endif\n                            break;\n                        default:\n                            goto illegal_insn;\n                    }\n                    break;\n            }\n            break;\n        }\n        case 5: /* c.j */\n        {\n            ins->is_branch = TRUE;\n            ins->branch_type = BRANCH_UNCOND;\n            ins->type = INS_TYPE_JAL;\n            imm = sextc(\n                cget_field1(insn, 12, 11, 11) | cget_field1(insn, 11, 4, 4)\n                    | cget_field1(insn, 9, 8, 9) | cget_field1(insn, 8, 10, 10)\n                    | cget_field1(insn, 7, 6, 6) | cget_field1(insn, 6, 7, 7)\n                    | cget_field1(insn, 3, 1, 3) | cget_field1(insn, 2, 5, 5),\n                12);\n            break;\n        }\n        case 6: /* c.beqz */\n        {\n            ins->is_branch = TRUE;\n            ins->branch_type = BRANCH_COND;\n            ins->type = INS_TYPE_COND_BRANCH;\n            ins->has_src1 = TRUE;\n            rs1 = ((insn >> 7) & 7) | 8;\n            rs2 = 0;\n            imm = sextc(\n                cget_field1(insn, 12, 8, 8) | cget_field1(insn, 10, 3, 4)\n                    | cget_field1(insn, 5, 6, 7) | cget_field1(insn, 3, 1, 2)\n                    | cget_field1(insn, 2, 5, 5),\n                9);\n            break;\n        }\n        case 7: /* c.bnez */\n        {\n            ins->is_branch = TRUE;\n            ins->branch_type = BRANCH_COND;\n            ins->type = INS_TYPE_COND_BRANCH;\n            ins->has_src1 = TRUE;\n            rs1 = ((insn >> 7) & 7) | 8;\n            rs2 = 0;\n            imm = sextc(\n                cget_field1(insn, 12, 8, 8) | cget_field1(insn, 10, 3, 4)\n                    | cget_field1(insn, 5, 6, 7) | cget_field1(insn, 3, 1, 2)\n                    | cget_field1(insn, 2, 5, 5),\n                9);\n            break;\n        }\n        default:\n        {\n            goto illegal_insn;\n        }\n    }\n    ins->rd = rd;\n    ins->rs1 = rs1;\n    ins->rs2 = rs2;\n    ins->imm = imm;\n    ins->quad = quad;\n    ins->funct3 = funct3;\n    ins->funct4 = funct4;\n    ins->funct5 = funct5;\n    return;\nillegal_insn:\n    ins->exception = TRUE;\n    ins->exception_cause = SIM_ILLEGAL_OPCODE_EXCEPTION;\n}\n\nstatic void\ndecode_compressed_q2(struct RVInstruction *ins)\n{\n    uint32_t insn, rd, rs1, rs2, funct3, quad;\n    int32_t imm = 0;\n\n    insn = ins->binary;\n    quad = C_QUADRANT2;\n    funct3 = (insn >> 13) & 7;\n    rd = (insn >> 7) & 0x1f;\n    rs1 = rd;\n    rs2 = (insn >> 2) & 0x1f;\n    switch (funct3)\n    {\n        case 0: /* c.slli */\n        {\n            ins->has_dest = TRUE;\n            ins->has_src1 = TRUE;\n            rs1 = rd;\n            imm = cget_field1(insn, 12, 5, 5) | rs2;\n#if XLEN == 32\n            if (imm & 0x20)\n                goto illegal_insn;\n#endif\n            break;\n        }\n#if SIM_FLEN >= 64\n        case 1: /* c.fldsp */\n        {\n            ins->is_load = TRUE;\n            ins->has_fp_dest = TRUE;\n            ins->has_src1 = TRUE;\n            ins->bytes_to_rw = 8;\n            ins->f64_mask = TRUE;\n            ins->set_fs = TRUE;\n            ins->type = INS_TYPE_FP_LOAD;\n            rs1 = 2;\n            imm = cget_field1(insn, 12, 5, 5) | (rs2 & (3 << 3))\n                  | cget_field1(insn, 2, 6, 8);\n            break;\n        }\n#endif\n        case 2: /* c.lwsp */\n        {\n            ins->is_load = TRUE;\n            ins->bytes_to_rw = 4;\n            ins->has_dest = TRUE;\n            ins->has_src1 = TRUE;\n            ins->type = INS_TYPE_LOAD;\n            rs1 = 2;\n            imm = cget_field1(insn, 12, 5, 5) | (rs2 & (7 << 2))\n                  | cget_field1(insn, 2, 6, 7);\n            break;\n        }\n#if defined(RV64)\n        case 3: /* c.ldsp */\n        {\n            ins->is_load = TRUE;\n            ins->bytes_to_rw = 8;\n            ins->has_dest = TRUE;\n            ins->has_src1 = TRUE;\n            ins->type = INS_TYPE_LOAD;\n            rs1 = 2;\n            imm = cget_field1(insn, 12, 5, 5) | (rs2 & (3 << 3))\n                  | cget_field1(insn, 2, 6, 8);\n            break;\n        }\n#elif SIM_FLEN >= 32\n        case 3: /* c.flwsp */\n        {\n            ins->is_load = TRUE;\n            ins->has_fp_dest = TRUE;\n            ins->has_src1 = TRUE;\n            ins->bytes_to_rw = 4;\n            ins->f32_mask = TRUE;\n            ins->set_fs = TRUE;\n            ins->type = INS_TYPE_FP_LOAD;\n            rs1 = 2;\n            imm = cget_field1(insn, 12, 5, 5) | (rs2 & (7 << 2))\n                  | cget_field1(insn, 2, 6, 7);\n            break;\n        }\n#endif\n        case 4:\n        {\n            if (((insn >> 12) & 1) == 0)\n            {\n                if (rs2 == 0)\n                {\n                    /* c.jr */\n                    ins->is_branch = TRUE;\n                    ins->branch_type = BRANCH_UNCOND;\n                    ins->type = INS_TYPE_JALR;\n                    ins->has_src1 = TRUE;\n                    if (rd == 0)\n                        goto illegal_insn;\n                    if (rs1 == 1)\n                    {\n                        ins->is_func_ret = TRUE;\n                    }\n                }\n                else\n                {\n                    /* c.mv */\n                    ins->has_dest = TRUE;\n                    ins->has_src2 = TRUE;\n                }\n            }\n            else\n            {\n                if (rs2 == 0)\n                {\n                    if (rd == 0)\n                    {\n                        /* c.ebreak */\n                        ins->exception = TRUE;\n                        ins->exception_cause = SIM_COMPLEX_OPCODE_EXCEPTION;\n                        ins->type = INS_TYPE_SYSTEM;\n                    }\n                    else\n                    {\n                        /* c.jalr */\n                        ins->is_branch = TRUE;\n                        ins->branch_type = BRANCH_UNCOND;\n                        ins->type = INS_TYPE_JALR;\n                        ins->has_dest = TRUE;\n                        ins->has_src1 = TRUE;\n                        rd = 1;\n                        ins->is_func_call = TRUE;\n                    }\n                }\n                else\n                {\n                    /* c.add */\n                    ins->has_dest = TRUE;\n                    ins->has_src1 = TRUE;\n                    ins->has_src2 = TRUE;\n                }\n            }\n            break;\n        }\n#if SIM_FLEN >= 64\n        case 5: /* c.fsdsp */\n        {\n            ins->is_store = TRUE;\n            ins->has_src1 = TRUE;\n            ins->has_fp_src2 = TRUE;\n            ins->bytes_to_rw = 8;\n            ins->type = INS_TYPE_FP_STORE;\n            rs1 = 2;\n            imm = cget_field1(insn, 10, 3, 5) | cget_field1(insn, 7, 6, 8);\n            break;\n        }\n#endif\n        case 6: /* c.swsp */\n        {\n            ins->is_store = TRUE;\n            ins->bytes_to_rw = 4;\n            ins->has_src1 = TRUE;\n            ins->has_src2 = TRUE;\n            ins->type = INS_TYPE_STORE;\n            rs1 = 2;\n            imm = cget_field1(insn, 9, 2, 5) | cget_field1(insn, 7, 6, 7);\n            break;\n        }\n#if defined(RV64)\n        case 7: /* c.sdsp */\n        {\n            ins->is_store = TRUE;\n            ins->bytes_to_rw = 8;\n            ins->has_src1 = TRUE;\n            ins->has_src2 = TRUE;\n            ins->type = INS_TYPE_STORE;\n            rs1 = 2;\n            imm = cget_field1(insn, 10, 3, 5) | cget_field1(insn, 7, 6, 8);\n            break;\n        }\n#elif SIM_FLEN >= 32\n        case 7: /* c.fswsp */\n        {\n            ins->is_store = TRUE;\n            ins->has_src1 = TRUE;\n            ins->has_fp_src2 = TRUE;\n            ins->bytes_to_rw = 4;\n            ins->type = INS_TYPE_FP_STORE;\n            rs1 = 2;\n            imm = cget_field1(insn, 9, 2, 5) | cget_field1(insn, 7, 6, 7);\n            break;\n        }\n#endif\n        default:\n        {\n            goto illegal_insn;\n        }\n    }\n    ins->rd = rd;\n    ins->rs1 = rs1;\n    ins->rs2 = rs2;\n    ins->imm = imm;\n    ins->quad = quad;\n    ins->funct3 = funct3;\n    return;\nillegal_insn:\n    ins->exception = TRUE;\n    ins->exception_cause = SIM_ILLEGAL_OPCODE_EXCEPTION;\n}\n\nstatic void\ndecode_compressed_type(struct RVInstruction *ins)\n{\n    int quad = ins->binary & 3;\n    switch (quad)\n    {\n        case C_QUADRANT0:\n        {\n            decode_compressed_q0(ins);\n            break;\n        }\n        case C_QUADRANT1:\n        {\n            decode_compressed_q1(ins);\n            break;\n        }\n        case C_QUADRANT2:\n        {\n            decode_compressed_q2(ins);\n            break;\n        }\n        default:\n        {\n            exit(1);\n        }\n    }\n}\n\nstatic void\nset_op_fu(RVInstruction *i)\n{\n    uint32_t funct3;\n    uint32_t insn = i->binary;\n    int32_t imm = insn >> 25;\n    if (imm == 1)\n    {\n        funct3 = (insn >> 12) & 7;\n        switch (funct3)\n        {\n            case 0: /* mul */\n            case 1: /* mulh */\n            case 2: /* mulhsu */\n            case 3: /* mulhu */\n                i->fu_type = FU_MUL;\n                i->type = INS_TYPE_INT_MUL;\n                break;\n            case 4: /* div */\n            case 5: /* divu */\n            case 6: /* rem */\n            case 7: /* remu */\n                i->fu_type = FU_DIV;\n                i->type = INS_TYPE_INT_DIV;\n                break;\n        }\n    }\n}\n\nstatic int\nchk_op_imm_exceptions(RVInstruction *i, uint32_t bit_size)\n{\n    uint32_t funct3 = (i->binary >> 12) & 7;\n\n    switch (funct3)\n    {\n        case 1: /* slli */\n            if ((i->imm & ~(bit_size - 1)) != 0)\n            {\n                return -1;\n            }\n            break;\n        case 5: /* srli/srai */\n            if ((i->imm & ~((bit_size - 1) | 0x400)) != 0)\n            {\n                return -1;\n            }\n    }\n    return 0;\n}\n\nstatic int\nchk_op_exceptions(RVInstruction *i)\n{\n    int32_t imm = i->binary >> 25;\n\n    if (imm != 1)\n    {\n        if (imm & ~0x20)\n        {\n            return -1;\n        }\n    }\n    return 0;\n}\n\n/**\n * @param  Encoded 32-bit instruction binary\n * @return Decoded RVInstruction\n */\nvoid\ndecode_riscv_binary(struct RVInstruction *ins, uint32_t insn)\n{\n    ins->binary = insn;\n    ins->fu_type = FU_ALU;\n    ins->data_class = INS_CLASS_INT;\n    ins->type = INS_TYPE_ARITMETIC;\n    if ((ins->binary & 3) != 3)\n    {\n        /* Compressed Instruction */\n        decode_compressed_type(ins);\n    }\n    else\n    {\n        /* 32-bit Instruction */\n        ins->major_opcode = insn & 0x7f;\n        ins->funct3 = (insn >> 12) & 7;\n        ins->funct7 = (ins->binary & 0xfe000000) >> 25;\n        ins->rd = (insn >> 7) & 0x1f;\n        ins->rs1 = (insn >> 15) & 0x1f;\n        ins->rs2 = (insn >> 20) & 0x1f;\n        switch (ins->major_opcode)\n        {\n            case LOAD_MASK:\n            {\n                ins->is_load = TRUE;\n                ins->has_src1 = TRUE;\n                ins->has_dest = TRUE;\n                ins->imm = (int32_t)insn >> 20;\n                ins->type = INS_TYPE_LOAD;\n                switch (ins->funct3)\n                {\n                    case 0x0: /* lb */\n                    {\n                        ins->bytes_to_rw = 1;\n                        break;\n                    }\n                    case 0x1: /* lh */\n                    {\n                        ins->bytes_to_rw = 2;\n                        break;\n                    }\n                    case 0x2: /* lw */\n                    {\n                        ins->bytes_to_rw = 4;\n                        break;\n                    }\n#if defined(RV64)\n                    case 0x3: /* ld */\n                    {\n                        ins->bytes_to_rw = 8;\n                        break;\n                    }\n#endif\n                    case 0x4: /* lbu */\n                    {\n                        ins->bytes_to_rw = 1;\n                        ins->is_unsigned = TRUE;\n                        break;\n                    }\n                    case 0x5: /* lhu */\n                    {\n                        ins->bytes_to_rw = 2;\n                        ins->is_unsigned = TRUE;\n                        break;\n                    }\n                    case 0x6: /* lwu */\n                    {\n                        ins->bytes_to_rw = 4;\n                        ins->is_unsigned = TRUE;\n                        break;\n                    }\n                }\n                break;\n            }\n            case OP_IMM_MASK:\n            case OP_IMM_32_MASK:\n            {\n                if (ins->major_opcode == OP_IMM_MASK)\n                {\n                    if (chk_op_imm_exceptions(ins, BIT_SIZE))\n                    {\n                        goto exception;\n                    }\n                }\n                else\n                {\n                    if (chk_op_imm_exceptions(ins, 32))\n                    {\n                        goto exception;\n                    }\n                }\n\n                ins->has_src1 = TRUE;\n                ins->has_dest = TRUE;\n                ins->imm = (int32_t)insn >> 20;\n                break;\n            }\n            case OP_MASK:\n            case OP_MASK_32:\n            {\n                if (chk_op_exceptions(ins))\n                {\n                    goto exception;\n                }\n\n                ins->has_src1 = TRUE;\n                ins->has_src2 = TRUE;\n                ins->has_dest = TRUE;\n                /* set the functional units for mul and div */\n                set_op_fu(ins);\n                break;\n            }\n            case LUI_MASK:\n            case AUIPC_MASK:\n            {\n                ins->has_dest = TRUE;\n                ins->imm = (int32_t)(insn & 0xfffff000);\n                break;\n            }\n            case STORE_MASK:\n            {\n                ins->is_store = TRUE;\n                ins->has_src1 = TRUE;\n                ins->has_src2 = TRUE;\n                ins->imm = ins->rd | ((insn >> (25 - 5)) & 0xfe0);\n                ins->imm = (ins->imm << 20) >> 20;\n                ins->type = INS_TYPE_STORE;\n                switch (ins->funct3)\n                {\n                    case 0x0: /* sb */\n                    {\n                        ins->bytes_to_rw = 1;\n                        break;\n                    }\n                    case 0x1: /* sh */\n                    {\n                        ins->bytes_to_rw = 2;\n                        break;\n                    }\n                    case 0x2: /* sw */\n                    {\n                        ins->bytes_to_rw = 4;\n                        break;\n                    }\n#if defined(RV64)\n                    case 0x3: /* sd */\n                    {\n                        ins->bytes_to_rw = 8;\n                        break;\n                    }\n#endif\n                }\n                break;\n            }\n            case CSR_MASK:\n            {\n                ins->is_system = TRUE;\n                ins->exception = TRUE;\n                ins->type = INS_TYPE_SYSTEM;\n\n                /* Complex Opcode */\n                ins->exception_cause = SIM_COMPLEX_OPCODE_EXCEPTION;\n                break;\n            }\n            case FENCE_MASK:\n            {\n                ins->is_system = TRUE;\n                ins->exception = TRUE;\n                ins->type = INS_TYPE_SYSTEM;\n\n                /* Complex Opcode */\n                ins->exception_cause = SIM_COMPLEX_OPCODE_EXCEPTION;\n                break;\n            }\n\n            case JAL_MASK:\n            {\n                ins->is_branch = TRUE;\n                ins->branch_type = BRANCH_UNCOND;\n                ins->has_dest = TRUE;\n                ins->imm = ((insn >> (31 - 20)) & (1 << 20))\n                           | ((insn >> (21 - 1)) & 0x7fe)\n                           | ((insn >> (20 - 11)) & (1 << 11))\n                           | (insn & 0xff000);\n                ins->imm = (ins->imm << 11) >> 11;\n                ins->type = INS_TYPE_JAL;\n                if (ins->rd == 1)\n                {\n                    ins->is_func_call = TRUE;\n                }\n                break;\n            }\n            case JALR_MASK:\n            {\n                ins->is_branch = TRUE;\n                ins->branch_type = BRANCH_UNCOND;\n                ins->has_src1 = TRUE;\n                ins->has_dest = TRUE;\n                ins->imm = (int32_t)insn >> 20;\n                ins->type = INS_TYPE_JALR;\n                if (ins->rd == 1)\n                {\n                    ins->is_func_call = TRUE;\n                }\n                if (ins->rs1 == 1)\n                {\n                    ins->is_func_ret = TRUE;\n                }\n                break;\n            }\n            case BRANCH_MASK:\n            {\n                ins->is_branch = TRUE;\n                ins->branch_type = BRANCH_COND;\n                ins->has_src1 = TRUE;\n                ins->has_src2 = TRUE;\n                ins->imm = ((insn >> (31 - 12)) & (1 << 12))\n                           | ((insn >> (25 - 5)) & 0x7e0)\n                           | ((insn >> (8 - 1)) & 0x1e)\n                           | ((insn << (11 - 7)) & (1 << 11));\n                ins->imm = (ins->imm << 19) >> 19;\n                ins->type = INS_TYPE_COND_BRANCH;\n                break;\n            }\n            case ATOMIC_MASK:\n            {\n                uint32_t funct3;\n\n                ins->is_atomic = TRUE;\n                ins->has_dest = TRUE;\n                ins->type = INS_TYPE_ATOMIC;\n                funct3 = (insn >> 12) & 7;\n                switch (funct3)\n                {\n                    case 2:\n#if BIT_SIZE >= 64\n                    case 3:\n#endif\n                    {\n                        funct3 = ins->binary >> 27;\n                        switch (funct3)\n                        {\n                            case 2: /* lr.w */\n                            {\n                                if (ins->rs2 != 0)\n                                    goto exception;\n                                ins->has_src1 = TRUE;\n                                ins->is_atomic_load = TRUE;\n                                ins->bytes_to_rw = sizeof(target_ulong);\n                                break;\n                            }\n                            case 3: /* sc.w */\n                            {\n                                ins->has_src1 = TRUE;\n                                ins->has_src2 = TRUE;\n                                ins->is_atomic_store = TRUE;\n                                ins->bytes_to_rw = sizeof(target_ulong);\n                                break;\n                            }\n                            case 1:    /* amiswap.w */\n                            case 0:    /* amoadd.w */\n                            case 4:    /* amoxor.w */\n                            case 0xc:  /* amoand.w */\n                            case 0x8:  /* amoor.w */\n                            case 0x10: /* amomin.w */\n                            case 0x14: /* amomax.w */\n                            case 0x18: /* amominu.w */\n                            case 0x1c: /* amomaxu.w */\n                            {\n                                ins->has_src1 = TRUE;\n                                ins->has_src2 = TRUE;\n                                ins->is_atomic_operate = TRUE;\n                                ins->is_atomic_load = TRUE;\n                                ins->is_atomic_store = TRUE;\n                                ins->bytes_to_rw = sizeof(target_ulong);\n                                break;\n                            }\n                            default:\n                                goto exception;\n                        }\n                        break;\n                    }\n                    default:\n                        goto exception;\n                }\n                break;\n            }\n            case FLOAD_MASK:\n            {\n                if (ins->current_fs == 0)\n                {\n                    goto exception;\n                }\n                ins->is_load = TRUE;\n                ins->has_fp_dest = TRUE;\n                ins->has_src1 = TRUE;\n                ins->set_fs = TRUE;\n                ins->imm = (int32_t)insn >> 20;\n                ins->type = INS_TYPE_FP_LOAD;\n                switch (ins->funct3)\n                {\n                    case 2: /* flw */\n                    {\n                        ins->bytes_to_rw = 4;\n                        ins->f32_mask = TRUE;\n                    }\n                    break;\n#if SIM_FLEN >= 64\n                    case 3: /* fld */\n                    {\n                        ins->bytes_to_rw = 8;\n                        ins->f64_mask = TRUE;\n                    }\n                    break;\n#endif\n                }\n                break;\n            }\n            case FSTORE_MASK:\n            {\n                if (ins->current_fs == 0)\n                {\n                    goto exception;\n                }\n                ins->is_store = TRUE;\n                ins->has_src1 = TRUE;\n                ins->has_fp_src2 = TRUE;\n                ins->imm = ins->rd | ((insn >> (25 - 5)) & 0xfe0);\n                ins->imm = (ins->imm << 20) >> 20;\n                ins->type = INS_TYPE_FP_STORE;\n                switch (ins->funct3)\n                {\n                    case 2: /* fsw */\n                        ins->bytes_to_rw = 4;\n                        break;\n#if SIM_FLEN >= 64\n                    case 3: /* fsd */\n#endif\n                        ins->bytes_to_rw = 8;\n                        break;\n                }\n                break;\n            }\n            case FMADD_MASK:\n            {\n                if ((ins->current_fs == 0) || (ins->rm < 0))\n                {\n                    goto exception;\n                }\n                ins->data_class = INS_CLASS_FP;\n                ins->fu_type = FU_FPU_FMA;\n                ins->type = INS_TYPE_FP_FMA;\n                ins->has_fp_dest = TRUE;\n                ins->has_fp_src1 = TRUE;\n                ins->has_fp_src2 = TRUE;\n                ins->has_fp_src3 = TRUE;\n                ins->set_fs = TRUE;\n                ins->funct3 = (ins->binary >> 25) & 3;\n                ins->rs3 = ins->binary >> 27;\n                break;\n            }\n            case FMSUB_MASK:\n            {\n                if ((ins->current_fs == 0) || (ins->rm < 0))\n                {\n                    goto exception;\n                }\n                ins->data_class = INS_CLASS_FP;\n                ins->fu_type = FU_FPU_FMA;\n                ins->type = INS_TYPE_FP_FMA;\n                ins->has_fp_dest = TRUE;\n                ins->has_fp_src1 = TRUE;\n                ins->has_fp_src2 = TRUE;\n                ins->has_fp_src3 = TRUE;\n                ins->set_fs = TRUE;\n                ins->funct3 = (ins->binary >> 25) & 3;\n                ins->rs3 = ins->binary >> 27;\n                break;\n            }\n            case FNMSUB_MASK:\n            {\n                if ((ins->current_fs == 0) || (ins->rm < 0))\n                {\n                    goto exception;\n                }\n                ins->data_class = INS_CLASS_FP;\n                ins->fu_type = FU_FPU_FMA;\n                ins->type = INS_TYPE_FP_FMA;\n                ins->has_fp_dest = TRUE;\n                ins->has_fp_src1 = TRUE;\n                ins->has_fp_src2 = TRUE;\n                ins->has_fp_src3 = TRUE;\n                ins->set_fs = TRUE;\n                ins->funct3 = (ins->binary >> 25) & 3;\n                ins->rs3 = ins->binary >> 27;\n                break;\n            }\n            case FNMADD_MASK:\n            {\n                if ((ins->current_fs == 0) || (ins->rm < 0))\n                {\n                    goto exception;\n                }\n                ins->data_class = INS_CLASS_FP;\n                ins->fu_type = FU_FPU_FMA;\n                ins->type = INS_TYPE_FP_FMA;\n                ins->has_fp_dest = TRUE;\n                ins->has_fp_src1 = TRUE;\n                ins->has_fp_src2 = TRUE;\n                ins->has_fp_src3 = TRUE;\n                ins->set_fs = TRUE;\n                ins->funct3 = (ins->binary >> 25) & 3;\n                ins->rs3 = ins->binary >> 27;\n                break;\n            }\n            case F_ARITHMETIC_MASK:\n            {\n                if (ins->current_fs == 0)\n                {\n                    goto exception;\n                }\n                ins->data_class = INS_CLASS_FP;\n                ins->fu_type = FU_FPU_ALU;\n                ins->rm = ins->funct3;\n                ins->type = INS_TYPE_FP_MISC;\n                switch (ins->funct7)\n                {\n#define F_SIZE 32\n#include \"fp_decode_template.h\"\n#if SIM_FLEN >= 64\n#define F_SIZE 64\n#include \"fp_decode_template.h\"\n#endif\n                    default:\n                        goto exception;\n                }\n                break;\n            }\n            default:\n            {\n                goto exception;\n            }\n        }\n    }\n\n    /* Generate instruction string */\n    if (ins->create_str)\n    {\n        generate_riscv_instruction_string(ins);\n    }\n    return;\nexception:\n    ins->exception = TRUE;\n    ins->exception_cause = SIM_ILLEGAL_OPCODE_EXCEPTION;\n}"
  },
  {
    "path": "src/riscvsim/decoder/riscv_isa_execute.c",
    "content": "/**\n * RISCV Instruction Execution Logic\n *\n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../../riscv_cpu_priv.h\"\n#include \"../../softfp.h\"\n#include \"../riscv_sim_typedefs.h\"\n#include \"riscv_instruction.h\"\n\n#define xsimglue(x, y) x##y\n#define simglue(x, y) xsimglue(x, y)\n\nstatic inline target_long simglue(div, BIT_SIZE)(target_long a, target_long b)\n{\n    if (b == 0)\n    {\n        return -1;\n    }\n    else if (a == ((target_long)1 << (BIT_SIZE - 1)) && b == -1)\n    {\n        return a;\n    }\n    else\n    {\n        return a / b;\n    }\n}\n\nstatic inline target_ulong simglue(divu, BIT_SIZE)(target_ulong a,\n                                                   target_ulong b)\n{\n    if (b == 0)\n    {\n        return -1;\n    }\n    else\n    {\n        return a / b;\n    }\n}\n\nstatic inline target_long simglue(rem, BIT_SIZE)(target_long a, target_long b)\n{\n    if (b == 0)\n    {\n        return a;\n    }\n    else if (a == ((target_long)1 << (BIT_SIZE - 1)) && b == -1)\n    {\n        return 0;\n    }\n    else\n    {\n        return a % b;\n    }\n}\n\nstatic inline target_ulong simglue(remu, BIT_SIZE)(target_ulong a,\n                                                   target_ulong b)\n{\n    if (b == 0)\n    {\n        return a;\n    }\n    else\n    {\n        return a % b;\n    }\n}\n\n#if BIT_SIZE == 32\n\nstatic inline uint32_t\nmulh32(int32_t a, int32_t b)\n{\n    return ((int64_t)a * (int64_t)b) >> 32;\n}\n\nstatic inline uint32_t\nmulhsu32(int32_t a, uint32_t b)\n{\n    return ((int64_t)a * (int64_t)b) >> 32;\n}\n\nstatic inline uint32_t\nmulhu32(uint32_t a, uint32_t b)\n{\n    return ((int64_t)a * (int64_t)b) >> 32;\n}\n\n#elif BIT_SIZE == 64 && defined(HAVE_INT128)\n\nstatic inline uint64_t\nmulh64(int64_t a, int64_t b)\n{\n    return ((int128_t)a * (int128_t)b) >> 64;\n}\n\nstatic inline uint64_t\nmulhsu64(int64_t a, uint64_t b)\n{\n    return ((int128_t)a * (int128_t)b) >> 64;\n}\n\nstatic inline uint64_t\nmulhu64(uint64_t a, uint64_t b)\n{\n    return ((int128_t)a * (int128_t)b) >> 64;\n}\n\n#else\n\n#if BIT_SIZE == 64\n#define UHALF uint32_t\n#define UHALF_LEN 32\n#elif BIT_SIZE == 128\n#define UHALF uint64_t\n#define UHALF_LEN 64\n#else\n#error unsupported BIT_SIZE\n#endif\n\nstatic target_ulong simglue(mulhu, BIT_SIZE)(target_ulong a, target_ulong b)\n{\n    UHALF a0, a1, b0, b1, r2, r3;\n    target_ulong r00, r01, r10, r11, c;\n    a0 = a;\n    a1 = a >> UHALF_LEN;\n    b0 = b;\n    b1 = b >> UHALF_LEN;\n\n    r00 = (target_ulong)a0 * (target_ulong)b0;\n    r01 = (target_ulong)a0 * (target_ulong)b1;\n    r10 = (target_ulong)a1 * (target_ulong)b0;\n    r11 = (target_ulong)a1 * (target_ulong)b1;\n\n    //    r0 = r00;\n    c = (r00 >> UHALF_LEN) + (UHALF)r01 + (UHALF)r10;\n    //    r1 = c;\n    c = (c >> UHALF_LEN) + (r01 >> UHALF_LEN) + (r10 >> UHALF_LEN) + (UHALF)r11;\n    r2 = c;\n    r3 = (c >> UHALF_LEN) + (r11 >> UHALF_LEN);\n\n    //    *plow = ((target_ulong)r1 << UHALF_LEN) | r0;\n    return ((target_ulong)r3 << UHALF_LEN) | r2;\n}\n\n#undef UHALF\n\nstatic inline target_ulong simglue(mulh, BIT_SIZE)(target_long a, target_long b)\n{\n    target_ulong r1;\n    r1 = simglue(mulhu, BIT_SIZE)(a, b);\n    if (a < 0)\n        r1 -= a;\n    if (b < 0)\n        r1 -= b;\n    return r1;\n}\n\nstatic inline target_ulong simglue(mulhsu, BIT_SIZE)(target_long a,\n                                                     target_ulong b)\n{\n    target_ulong r1;\n    r1 = simglue(mulhu, BIT_SIZE)(a, b);\n    if (a < 0)\n        r1 -= a;\n    return r1;\n}\n#endif\n\nstatic void\nexecute_op_imm(RVInstruction *i)\n{\n    uint32_t insn = i->binary;\n    uint32_t funct3 = (insn >> 12) & 7;\n\n    switch (funct3)\n    {\n        case 0: /* addi */\n            i->buffer = (target_long)(i->rs1_val + i->imm);\n            break;\n        case 1: /* slli */\n            i->buffer = (target_long)(i->rs1_val << (i->imm & (BIT_SIZE - 1)));\n            break;\n        case 2: /* slti */\n            i->buffer = (target_long)i->rs1_val < (target_long)i->imm;\n            break;\n        case 3: /* sltiu */\n            i->buffer = i->rs1_val < (target_ulong)i->imm;\n            break;\n        case 4: /* xori */\n            i->buffer = i->rs1_val ^ i->imm;\n            break;\n        case 5: /* srli/srai */\n            if (i->imm & 0x400)\n                i->buffer\n                    = (target_long)i->rs1_val >> (i->imm & (BIT_SIZE - 1));\n            else\n                i->buffer = (target_long)((target_ulong)i->rs1_val\n                                          >> (i->imm & (BIT_SIZE - 1)));\n            break;\n        case 6: /* ori */\n            i->buffer = i->rs1_val | i->imm;\n            break;\n        case 7: /* andi */\n            i->buffer = i->rs1_val & i->imm;\n            break;\n    }\n    return;\n}\n\nstatic void\nexecute_op_imm_32(RVInstruction *i)\n{\n    uint32_t funct3 = (i->binary >> 12) & 7;\n\n    switch (funct3)\n    {\n        case 0: /* addiw */\n            i->buffer = (int32_t)(i->rs1_val + i->imm);\n            break;\n        case 1: /* slliw */\n            i->buffer = (int32_t)(i->rs1_val << (i->imm & 31));\n            break;\n        case 5: /* srliw/sraiw */\n            if (i->imm & 0x400)\n                i->buffer = (int32_t)i->rs1_val >> (i->imm & 31);\n            else\n                i->buffer = (int32_t)((uint32_t)i->rs1_val >> (i->imm & 31));\n            break;\n    }\n    return;\n}\n\nstatic void\nexecute_op(RVInstruction *i)\n{\n    uint32_t funct3;\n    uint32_t insn = i->binary;\n    int32_t imm = insn >> 25;\n\n    if (imm == 1)\n    {\n        funct3 = (insn >> 12) & 7;\n        switch (funct3)\n        {\n            case 0: /* mul */\n                i->buffer = (target_long)((target_long)i->rs1_val\n                                          * (target_long)i->rs2_val);\n                break;\n            case 1: /* mulh */\n                i->buffer = (target_long)simglue(mulh, BIT_SIZE)(i->rs1_val,\n                                                                 i->rs2_val);\n                break;\n            case 2: /* mulhsu */\n                i->buffer = (target_long)simglue(mulhsu, BIT_SIZE)(i->rs1_val,\n                                                                   i->rs2_val);\n                break;\n            case 3: /* mulhu */\n                i->buffer = (target_long)simglue(mulhu, BIT_SIZE)(i->rs1_val,\n                                                                  i->rs2_val);\n                break;\n            case 4: /* div */\n                i->buffer = simglue(div, BIT_SIZE)(i->rs1_val, i->rs2_val);\n                break;\n            case 5: /* divu */\n                i->buffer = (target_long)simglue(divu, BIT_SIZE)(i->rs1_val,\n                                                                 i->rs2_val);\n                break;\n            case 6: /* rem */\n                i->buffer = simglue(rem, BIT_SIZE)(i->rs1_val, i->rs2_val);\n                break;\n            case 7: /* remu */\n                i->buffer = (target_long)simglue(remu, BIT_SIZE)(i->rs1_val,\n                                                                 i->rs2_val);\n                break;\n        }\n    }\n    else\n    {\n        funct3 = ((insn >> 12) & 7) | ((insn >> (30 - 3)) & (1 << 3));\n        switch (funct3)\n        {\n            case 0: /* add */\n                i->buffer = (target_long)(i->rs1_val + i->rs2_val);\n                break;\n            case 0 | 8: /* sub */\n                i->buffer = (target_long)(i->rs1_val - i->rs2_val);\n                break;\n            case 1: /* sll */\n                i->buffer = (target_long)(i->rs1_val\n                                          << (i->rs2_val & (BIT_SIZE - 1)));\n                break;\n            case 2: /* slt */\n                i->buffer = (target_long)i->rs1_val < (target_long)i->rs2_val;\n                break;\n            case 3: /* sltu */\n                i->buffer = i->rs1_val < i->rs2_val;\n                break;\n            case 4: /* xor */\n                i->buffer = i->rs1_val ^ i->rs2_val;\n                break;\n            case 5: /* srl */\n                i->buffer = (target_long)((target_ulong)i->rs1_val\n                                          >> (i->rs2_val & (BIT_SIZE - 1)));\n                break;\n            case 5 | 8: /* sra */\n                i->buffer\n                    = (target_long)i->rs1_val >> (i->rs2_val & (BIT_SIZE - 1));\n                break;\n            case 6: /* or */\n                i->buffer = i->rs1_val | i->rs2_val;\n                break;\n            case 7: /* and */\n                i->buffer = i->rs1_val & i->rs2_val;\n                break;\n        }\n    }\n    return;\n}\n\nstatic void\nexecute_op_32(RVInstruction *i)\n{\n    uint32_t insn = i->binary;\n    int32_t imm = insn >> 25;\n    uint32_t funct3;\n\n    if (imm == 1)\n    {\n        funct3 = (insn >> 12) & 7;\n        switch (funct3)\n        {\n            case 0: /* mulw */\n                i->buffer\n                    = (int32_t)((int32_t)i->rs1_val * (int32_t)i->rs2_val);\n                break;\n            case 4: /* divw */\n                i->buffer = simglue(div, BIT_SIZE)(i->rs1_val, i->rs2_val);\n                break;\n            case 5: /* divuw */\n                i->buffer\n                    = (int32_t)simglue(divu, BIT_SIZE)(i->rs1_val, i->rs2_val);\n                break;\n            case 6: /* remw */\n                i->buffer = simglue(rem, BIT_SIZE)(i->rs1_val, i->rs2_val);\n                break;\n            case 7: /* remuw */\n                i->buffer\n                    = (int32_t)simglue(remu, BIT_SIZE)(i->rs1_val, i->rs2_val);\n                break;\n        }\n    }\n    else\n    {\n        funct3 = ((insn >> 12) & 7) | ((insn >> (30 - 3)) & (1 << 3));\n        switch (funct3)\n        {\n            case 0: /* addw */\n                i->buffer = (int32_t)(i->rs1_val + i->rs2_val);\n                break;\n            case 0 | 8: /* subw */\n                i->buffer = (int32_t)(i->rs1_val - i->rs2_val);\n                break;\n            case 1: /* sllw */\n                i->buffer\n                    = (int32_t)((uint32_t)i->rs1_val << (i->rs2_val & 31));\n                break;\n            case 5: /* srlw */\n                i->buffer\n                    = (int32_t)((uint32_t)i->rs1_val >> (i->rs2_val & 31));\n                break;\n            case 5 | 8: /* sraw */\n                i->buffer = (int32_t)i->rs1_val >> (i->rs2_val & 31);\n                break;\n        }\n    }\n    return;\n}\n\nstatic void\nexecute_type_b(RVInstruction *i)\n{\n    uint32_t insn = i->binary;\n    uint32_t funct3 = (insn >> 12) & 7;\n    int32_t cond = -1;\n\n    switch (funct3 >> 1)\n    {\n        case 0: /* beq/bne */\n            cond = (i->rs1_val == i->rs2_val);\n            break;\n        case 2: /* blt/bge */\n            cond = ((target_long)i->rs1_val < (target_long)i->rs2_val);\n            break;\n        case 3: /* bltu/bgeu */\n            cond = (i->rs1_val < i->rs2_val);\n            break;\n    }\n    cond ^= (funct3 & 1);\n    i->cond = cond;\n    i->target = i->pc + i->imm;\n    return;\n}\n\nstatic void\nexecute_ext_c_q0(RVInstruction *i)\n{\n    switch (i->funct3)\n    {\n        case 0: /* c.addi4spn */\n        {\n            i->buffer = (target_long)(i->rs1_val + i->imm);\n        }\n        break;\n#if SIM_FLEN >= 64\n        case 1: /* c.fld */\n        {\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n        }\n        break;\n#endif\n        case 2: /* c.lw */\n        {\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n        }\n        break;\n#if defined(RV64)\n        case 3: /* c.ld */\n        {\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n        }\n        break;\n#elif SIM_FLEN >= 32\n        case 3: /* c.flw */\n        {\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n        }\n        break;\n#endif\n#if SIM_FLEN >= 64\n        case 5: /* c.fsd */\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n            break;\n#endif\n        case 6: /* c.sw */\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n            break;\n#if defined(RV64)\n        case 7: /* c.sd */\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n            break;\n#elif SIM_FLEN >= 32\n        case 7: /* c.fsw */\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n            break;\n#endif\n    }\n    return;\n}\n\nstatic void\nexecute_ext_c_q1(RVInstruction *i)\n{\n    switch (i->funct3)\n    {\n        case 0: /* c.addi/c.nop */\n            i->buffer = (target_long)(i->rs1_val + i->imm);\n            break;\n#if defined(RV32)\n        case 1: /* c.jal */\n            i->buffer = (target_ulong)(i->pc + 2);\n            i->target = (target_long)(i->pc + i->imm);\n            break;\n#elif defined(RV64)\n        case 1: /* c.addiw */\n            i->buffer = (int32_t)(i->rs1_val + i->imm);\n            break;\n#endif\n        case 2: /* c.li */\n            i->buffer = i->imm;\n            break;\n        case 3:\n            if (i->rd == 2)\n            {\n                /* c.addi16sp */\n                i->buffer = (target_long)(i->rs1_val + i->imm);\n            }\n            else if (i->rd != 0)\n            {\n                /* c.lui */\n                i->buffer = i->imm;\n            }\n            break;\n        case 4:\n            switch (i->funct4)\n            {\n                case 0: /* c.srli */\n                case 1: /* c.srai */\n                    if (i->funct4 == 0)\n                    {\n                        i->buffer\n                            = (target_long)((target_ulong)i->rs1_val >> i->imm);\n                    }\n                    else\n                    {\n                        i->buffer = (target_long)i->rs1_val >> i->imm;\n                    }\n                    break;\n                case 2: /* c.andi */\n                    i->buffer = (target_long)i->rs1_val & i->imm;\n                    break;\n                case 3:\n                    switch (i->funct5)\n                    {\n                        case 0: /* c.sub */\n                            i->buffer = (target_long)(i->rs1_val - i->rs2_val);\n                            break;\n                        case 1: /* c.xor */\n                            i->buffer = (i->rs1_val ^ i->rs2_val);\n                            break;\n                        case 2: /* c.or */\n                            i->buffer = (i->rs1_val | i->rs2_val);\n                            break;\n                        case 3: /* c.and */\n                            i->buffer = (i->rs1_val & i->rs2_val);\n                            break;\n#if defined(RV64)\n                        case 4: /* c.subw */\n                            i->buffer = (int32_t)(i->rs1_val - i->rs2_val);\n                            break;\n                        case 5: /* c.addw */\n                            i->buffer = (int32_t)(i->rs1_val + i->rs2_val);\n                            break;\n#endif\n                    }\n                    break;\n            }\n            break;\n        case 5: /* c.j */\n        {\n            i->target = (target_ulong)(i->pc + i->imm);\n        }\n        break;\n        case 6: /* c.beqz */\n        {\n            i->cond = (i->rs1_val == 0);\n            i->target = (target_ulong)(i->pc + i->imm);\n        }\n        break;\n        case 7: /* c.bnez */\n        {\n            i->cond = (i->rs1_val != 0);\n            i->target = (target_ulong)(i->pc + i->imm);\n        }\n        break;\n    }\n    return;\n}\n\nstatic void\nexecute_ext_c_q2(RVInstruction *i)\n{\n    uint32_t insn = i->binary;\n\n    switch (i->funct3)\n    {\n        case 0: /* c.slli */\n            i->buffer = (target_long)(i->rs1_val << i->imm);\n            break;\n#if SIM_FLEN >= 64\n        case 1: /* c.fldsp */\n        {\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n        }\n        break;\n#endif\n        case 2: /* c.lwsp */\n        {\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n        }\n        break;\n#if defined(RV64)\n        case 3: /* c.ldsp */\n        {\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n        }\n        break;\n#elif SIM_FLEN >= 32\n        case 3: /* c.flwsp */\n        {\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n        }\n        break;\n#endif\n        case 4:\n            if (((insn >> 12) & 1) == 0)\n            {\n                if (i->rs2 == 0)\n                {\n                    /* c.jr */\n                    i->target = (i->rs1_val & ~1);\n                }\n                else\n                {\n                    /* c.mv */\n                    i->buffer = i->rs2_val;\n                }\n            }\n            else\n            {\n                if (i->rs2 == 0)\n                {\n                    if (i->rd == 0)\n                    {\n                        /* c.ebreak */\n                    }\n                    else\n                    {\n                        /* c.jalr */\n                        i->buffer = i->pc + 2;\n                        i->target = i->rs1_val & ~1;\n                    }\n                }\n                else\n                {\n                    /** c.add */\n                    i->buffer = (target_long)(i->rs1_val + i->rs2_val);\n                }\n            }\n            break;\n#if SIM_FLEN >= 64\n        case 5: /* c.fsdsp */\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n            break;\n#endif\n        case 6: /* c.swsp */\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n            break;\n#if defined(RV64)\n        case 7: /* c.sdsp */\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n            break;\n#elif SIM_FLEN >= 32\n        case 7: /* c.fswsp */\n            i->mem_addr = (target_long)(i->rs1_val + i->imm);\n            break;\n#endif\n    }\n    return;\n}\n\nstatic void\nexecute_ext_c_path(RVInstruction *i)\n{\n    switch (i->quad)\n    {\n        case 0:\n        {\n            execute_ext_c_q0(i);\n            break;\n        }\n        case 1:\n        {\n            execute_ext_c_q1(i);\n            break;\n        }\n        case 2:\n        {\n            execute_ext_c_q2(i);\n            break;\n        }\n    }\n}\n\nvoid\nexecute_riscv_instruction(RVInstruction *i, uint32_t *fflags)\n{\n    int32_t rm;\n\n    /* For 16-bit compressed instructions */\n    if ((i->binary & 3) != 3)\n    {\n        execute_ext_c_path(i);\n        return;\n    }\n\n    /* For 32-bit integer and floating point instructions */\n    switch (i->major_opcode)\n    {\n\n        case OP_IMM_MASK:\n        {\n            execute_op_imm(i);\n            break;\n        }\n\n        case OP_IMM_32_MASK:\n        {\n            execute_op_imm_32(i);\n            break;\n        }\n\n        case OP_MASK:\n        {\n            execute_op(i);\n            break;\n        }\n\n        case OP_MASK_32:\n        {\n            execute_op_32(i);\n            break;\n        }\n\n        case LUI_MASK:\n        {\n            i->buffer = i->imm;\n            break;\n        }\n\n        case AUIPC_MASK:\n        {\n            i->buffer = (target_long)(i->pc + i->imm);\n            break;\n        }\n\n        case LOAD_MASK:\n        {\n            i->mem_addr = i->rs1_val + i->imm;\n            break;\n        }\n        case STORE_MASK:\n        {\n            i->mem_addr = i->rs1_val + i->imm;\n            break;\n        }\n\n        case JAL_MASK:\n        {\n            i->buffer = i->pc + 4;\n            i->target = i->pc + i->imm;\n            break;\n        }\n\n        case JALR_MASK:\n        {\n            i->buffer = i->pc + 4;\n            i->target = i->rs1_val + i->imm;\n            break;\n        }\n\n        case BRANCH_MASK:\n        {\n            execute_type_b(i);\n            break;\n        }\n\n        case ATOMIC_MASK:\n        {\n            i->mem_addr = i->rs1_val;\n            break;\n        }\n\n        case FLOAD_MASK:\n        {\n            i->mem_addr = i->rs1_val + i->imm;\n            break;\n        }\n\n        case FSTORE_MASK:\n        {\n            i->mem_addr = i->rs1_val + i->imm;\n            break;\n        }\n\n        case 0x43:\n        { /* fmadd */\n            rm = i->rm;\n            switch (i->funct3)\n            {\n                case 0:\n                {\n                    i->buffer = fma_sf32(i->rs1_val, i->rs2_val, i->rs3_val,\n                                         (RoundingModeEnum)rm, fflags)\n                                | F32_HIGH;\n                    break;\n                }\n                case 1:\n                {\n                    i->buffer = fma_sf64(i->rs1_val, i->rs2_val, i->rs3_val,\n                                         (RoundingModeEnum)rm, fflags)\n                                | F64_HIGH;\n                    break;\n                }\n            }\n            break;\n        }\n\n        case 0x47:\n        { /* fmsub*/\n            rm = i->rm;\n            switch (i->funct3)\n            {\n                case 0:\n                {\n                    i->buffer = fma_sf32(i->rs1_val, i->rs2_val,\n                                         i->rs3_val ^ FSIGN_MASK32,\n                                         (RoundingModeEnum)rm, fflags)\n                                | F32_HIGH;\n                    break;\n                }\n                case 1:\n                {\n                    i->buffer = fma_sf64(i->rs1_val, i->rs2_val,\n                                         i->rs3_val ^ FSIGN_MASK64,\n                                         (RoundingModeEnum)rm, fflags)\n                                | F64_HIGH;\n                }\n                break;\n            }\n            break;\n        }\n\n        case 0x4b:\n        { /* fnmsub */\n            rm = i->rm;\n            switch (i->funct3)\n            {\n                case 0:\n                {\n                    i->buffer\n                        = fma_sf32(i->rs1_val ^ FSIGN_MASK32, i->rs2_val,\n                                   i->rs3_val, (RoundingModeEnum)rm, fflags)\n                          | F32_HIGH;\n                    break;\n                }\n\n                case 1:\n                {\n                    i->buffer\n                        = fma_sf64(i->rs1_val ^ FSIGN_MASK64, i->rs2_val,\n                                   i->rs3_val, (RoundingModeEnum)rm, fflags)\n                          | F64_HIGH;\n                    break;\n                }\n            }\n            break;\n        }\n\n        case 0x4f:\n        { /* fmadd */\n            rm = i->rm;\n            switch (i->funct3)\n            {\n                case 0:\n                {\n                    i->buffer = fma_sf32(i->rs1_val ^ FSIGN_MASK32, i->rs2_val,\n                                         i->rs3_val ^ FSIGN_MASK32,\n                                         (RoundingModeEnum)rm, fflags)\n                                | F32_HIGH;\n                    break;\n                }\n                case 1:\n                {\n                    i->buffer = fma_sf64(i->rs1_val ^ FSIGN_MASK64, i->rs2_val,\n                                         i->rs3_val ^ FSIGN_MASK64,\n                                         (RoundingModeEnum)rm, fflags)\n                                | F64_HIGH;\n                    break;\n                }\n            }\n            break;\n        }\n\n        case F_ARITHMETIC_MASK:\n        {\n            rm = i->rm;\n            switch (i->funct7)\n            {\n#define F_SIZE 32\n#include \"fp_execute_template.h\"\n#if SIM_FLEN >= 64\n#define F_SIZE 64\n#include \"fp_execute_template.h\"\n#endif\n            }\n            break;\n        }\n    }\n}"
  },
  {
    "path": "src/riscvsim/decoder/riscv_isa_string_generator.c",
    "content": "/**\n * RISCV Instruction String Generator\n *\n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"riscv_instruction.h\"\n\nstatic const char reg[][6] = {\n    \"zero\", // x0\n    \"ra\",   // x1\n    \"sp\",   // x2\n    \"gp\",   // x3\n    \"tp\",   // x4\n    \"t0\",   // x5\n    \"t1\",   // x6\n    \"t2\",   // x7\n    \"s0\",   // x8\n    \"s1\",   // x9\n    \"a0\",   // x10\n    \"a1\",   // x11\n    \"a2\",   // x12\n    \"a3\",   // x13\n    \"a4\",   // x14\n    \"a5\",   // x15\n    \"a6\",   // x16\n    \"a7\",   // x17\n    \"s2\",   // x18\n    \"s3\",   // x19\n    \"s4\",   // x20\n    \"s5\",   // x21\n    \"s6\",   // x22\n    \"s7\",   // x23\n    \"s8\",   // x24\n    \"s9\",   // x25\n    \"s10\",  // x26\n    \"s11\",  // x27\n    \"t3\",   // x28\n    \"t4\",   // x29\n    \"t5\",   // x30\n    \"t6\"    // x31\n};\n\nstatic const char fp_reg[][6] = {\n    \"ft0\",  // fp0\n    \"ft1\",  // fp1\n    \"ft2\",  // fp2\n    \"ft3\",  // fp3\n    \"ft4\",  // fp4\n    \"ft5\",  // fp5\n    \"ft6\",  // fp6\n    \"ft7\",  // fp7\n    \"fs0\",  // fp8\n    \"fs1\",  // fp9\n    \"fa0\",  // fp10\n    \"fa1\",  // fp11\n    \"fa2\",  // fp12\n    \"fa3\",  // fp13\n    \"fa4\",  // fp14\n    \"fa5\",  // fp15\n    \"fa6\",  // fp16\n    \"fa7\",  // fp17\n    \"fs2\",  // fp18\n    \"fs3\",  // fp19\n    \"fs4\",  // fp20\n    \"fs5\",  // fp21\n    \"fs6\",  // fp22\n    \"fs7\",  // fp23\n    \"fs8\",  // fp24\n    \"fs9\",  // fp25\n    \"fs10\", // fp26\n    \"fs11\", // fp27\n    \"ft8\",  // fp28\n    \"ft9\",  // fp29\n    \"ft10\", // fp30\n    \"ft11\"  // fp31\n};\n\ntypedef struct CsrName\n{\n    int i;\n    const char *name;\n    int n;\n} CsrName;\n\nstatic const CsrName csr_names[] = {\n    {0x300,\"mstatus\"},   {0x100,\"sstatus\"}, {0x000,\"ustatus\"}, {0x200,\"vsstatus\"}, {0x600,\"hstatus\"},\n    {0x301,\"misa\"},\n    {0x302,\"medeleg\"},   {0x102,\"sedeleg\"},                                        {0x602,\"hedeleg\"},\n    {0x303,\"mideleg\"},   {0x103,\"sideleg\"},                                        {0x603,\"hideleg\"},\n    {0x304,\"mie\"},       {0x104,\"sie\"},     {0x004,\"uie\"},     {0x204,\"vsie\"},\n    {0x305,\"mtvec\"},     {0x105,\"stvec\"},   {0x005,\"utvec\"},   {0x204,\"vstvec\"},\n    {0x306,\"mcounteren\"},{0x106,\"scounteren\"},                                     {0x606,\"hcounteren\"},\n    {0x340,\"mscratch\"},  {0x140,\"sscratch\"},{0x040,\"uscratch\"},{0x204,\"vsscratch\"},\n    {0x341,\"mepc\"},      {0x141,\"sepc\"},    {0x041,\"uepc\"},    {0x204,\"vsepc\"},\n    {0x342,\"mcause\"},    {0x142,\"scause\"},  {0x042,\"ucause\"},  {0x204,\"vscause\"},\n    {0x343,\"mtval\"},     {0x143,\"stval\"},   {0x043,\"utval\"},   {0x204,\"vstval\"},\n    {0x344,\"mip\"},       {0x144,\"sip\"},     {0x044,\"uip\"},     {0x204,\"vsip\"},\n                         {0x180,\"satp\"},                       {0x280,\"vsatp\"},    {0x680,\"hgatp\"},\n    {0xF11,\"mvendorid\"},\n    {0xF12,\"marchid\"},\n    {0xF13,\"mimpid\"},\n    {0xF14,\"mhartid\"},\n    {0x3A0,\"pmpcfg%d\",3},\n    {0x3B0,\"pmpaddr%d\",15},\n    {0x001,\"fflags\"}, {0x002,\"frm\"}, {0x003,\"fcsr\"},\n\n    {0xB00,\"mcycle\"},    {0xC00,\"cycle\"},\n    {0xB80,\"mcycleh\"},   {0xC80,\"cycleh\"},\n                         {0xC01,\"time\"},\n                         {0xC81,\"timeh\"},\n    {0xB02,\"minstret\"},  {0xC02,\"instret\"},\n    {0xB82,\"minstreth\"}, {0xC82,\"instreth\"},\n    {0xB00,\"mhpmcounter%d\",31},  {0xC00,\"hpmcounter%d\",31},\n    {0xB80,\"mhpmcounter%dh\",31}, {0xC80,\"hpmcounter%dh\",31},\n    {0x320,\"mcountinhibit\"},\n    {0x320,\"mhpmevent%d\",31},\n    {0x7A0,\"tselect\"},  {0x7A1,\"mcontrol\"},  {0x7A2,\"tdata2\"},   {0x7A3,\"textra\"},\n    {0x7A4,\"tinfo\"},    {0x7A5,\"tcontrol\"},  {0x7A8,\"mcontext\"}, {0x7AA,\"scontext\"},\n    {0x7B0,\"dcsr\"},     {0x7B1,\"dpc\"},       {0x7B2,\"dscratch%d\",1},\n    {0,0,0}\n};\n\nstatic const char size_suffix[8][3] = {\"b\", \"h\", \"w\", \"d\", \"q\", \"5\", \"6\", \"7\"};\nstatic const char *const aqrl_suffix[4] = {\"\", \".rl\", \".aq\", \".aqrl\"};\nstatic const char get_flen_suffix[][3] = {\"\", \".s\", \".d\"};\n\nstatic void\nset_op_imm_str(RVInstruction *i)\n{\n    switch (i->funct3)\n    {\n        case 0: /* addi */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"addi %s,%s,%d\",\n                     reg[i->rd], reg[i->rs1], i->imm);\n            break;\n        }\n        case 1: /* slli */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"slli %s,%s,%d\",\n                     reg[i->rd], reg[i->rs1], i->imm);\n            break;\n        }\n        case 2: /* slti */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"slti %s,%s,%d\",\n                     reg[i->rd], reg[i->rs1], i->imm);\n            break;\n        }\n        case 3: /* sltiu */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"sltiu %s,%s,%d\",\n                     reg[i->rd], reg[i->rs1], i->imm);\n            break;\n        }\n        case 4: /* xori */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"xori %s,%s,%d\",\n                     reg[i->rd], reg[i->rs1], i->imm);\n            break;\n        }\n        case 5: /* srli/srai */\n        {\n            if (i->imm & 0x400)\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"srai %s,%s,%d\",\n                         reg[i->rd], reg[i->rs1], i->imm);\n            }\n            else\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"srli %s,%s,%d\",\n                         reg[i->rd], reg[i->rs1], i->imm);\n            }\n            break;\n        }\n        case 6: /* ori */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"ori %s,%s,%d\",\n                     reg[i->rd], reg[i->rs1], i->imm);\n            break;\n        }\n        case 7: /* andi */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"andi %s,%s,%d\",\n                     reg[i->rd], reg[i->rs1], i->imm);\n            break;\n        }\n    }\n}\n\nstatic void\nset_op_imm_32_str(RVInstruction *i)\n{\n    switch (i->funct3)\n    {\n        case 0: /* addiw */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"addiw %s,%s,%d\",\n                     reg[i->rd], reg[i->rs1], i->imm);\n            break;\n        }\n        case 1: /* slliw */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"slliw %s,%s,%d\",\n                     reg[i->rd], reg[i->rs1], i->imm);\n            break;\n        }\n        case 5: /* srliw/sraiw */\n        {\n            if (i->imm & 0x400)\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"sraiw %s,%s,%d\",\n                         reg[i->rd], reg[i->rs1], i->imm);\n            }\n            else\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"srliw %s,%s,%d\",\n                         reg[i->rd], reg[i->rs1], i->imm);\n            }\n            break;\n        }\n    }\n}\n\nstatic void\nset_op_str(RVInstruction *i)\n{\n    uint32_t funct3;\n    uint32_t insn = i->binary;\n    int32_t imm = insn >> 25;\n\n    if (imm == 1)\n    {\n        funct3 = (insn >> 12) & 7;\n        switch (funct3)\n        {\n            case 0: /* mul */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"mul %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 1: /* mulh */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"mulh %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 2: /* mulhsu */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"mulhsu %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 3: /* mulhu */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"mulhu %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 4: /* div */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"div %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 5: /* divu */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"divu %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 6: /* rem */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"rem %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 7: /* remu */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"remu %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n        }\n    }\n    else\n    {\n        funct3 = ((insn >> 12) & 7) | ((insn >> (30 - 3)) & (1 << 3));\n        switch (funct3)\n        {\n            case 0: /* add */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"add %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 0 | 8: /* sub */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"sub %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 1: /* sll */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"sll %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 2: /* slt */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"slt %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 3: /* sltu */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"sltu %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 4: /* xor */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"xor %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 5: /* srl */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"srl %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 5 | 8: /* sra */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"sra %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 6: /* or */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"or %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 7: /* and */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"and %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n        }\n    }\n}\n\nstatic void\nset_op_32_str(RVInstruction *i)\n{\n    uint32_t insn = i->binary;\n    int32_t imm = insn >> 25;\n    uint32_t funct3;\n\n    if (imm == 1)\n    {\n        funct3 = (insn >> 12) & 7;\n        switch (funct3)\n        {\n            case 0: /* mulw */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"mulw %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 4: /* divw */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"divw %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 5: /* divuw */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"divuw %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 6: /* remw */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"remw %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 7: /* remuw */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"remuw %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n        }\n    }\n    else\n    {\n        funct3 = ((insn >> 12) & 7) | ((insn >> (30 - 3)) & (1 << 3));\n        switch (funct3)\n        {\n            case 0: /* addw */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"addw %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 0 | 8: /* subw */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"subw %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 1: /* sllw */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"sllw %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 5: /* srlw */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"srlw %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n            case 5 | 8: /* sraw */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"sraw %s,%s,%s\",\n                         reg[i->rd], reg[i->rs1], reg[i->rs2]);\n                break;\n            }\n        }\n    }\n}\n\nstatic void\nset_branch_str(RVInstruction *i)\n{\n    const char *const branches[8]\n        = {\"beq\", \"bne\", 0, 0, \"blt\", \"bge\", \"bltu\", \"bgeu\"};\n    const char *s;\n\n    if (i->funct3 < 8)\n    {\n        s = branches[i->funct3];\n        if (s != 0)\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"%s %s,%s,%d\", s,\n                     reg[i->rs1], reg[i->rs2], i->imm);\n        }\n    }\n}\n\nstatic void\nset_ext_c_q0_str(RVInstruction *i)\n{\n    switch (i->funct3)\n    {\n        case 0: /* c.addi4spn */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.addi4spn %s,%s,%d\",\n                     reg[i->rd], reg[i->rs1], i->imm);\n        }\n        break;\n#if SIM_FLEN >= 64\n        case 1: /* c.fld */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.fld %s,%d(%s)\",\n                     fp_reg[i->rd], i->imm, reg[i->rs1]);\n        }\n        break;\n#endif\n        case 2: /* c.lw */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.lw %s,%d(%s)\",\n                     reg[i->rd], i->imm, reg[i->rs1]);\n        }\n        break;\n#if defined(RV64)\n        case 3: /* c.ld */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.ld %s,%d(%s)\",\n                     reg[i->rd], i->imm, reg[i->rs1]);\n        }\n        break;\n#elif SIM_FLEN >= 32\n        case 3: /* c.flw */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.flw %s,%d(%s)\",\n                     fp_reg[i->rd], i->imm, reg[i->rs1]);\n        }\n        break;\n#endif\n#if SIM_FLEN >= 64\n        case 5: /* c.fsd */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.fsd %s,%d(%s)\",\n                     fp_reg[i->rs2], i->imm, reg[i->rs1]);\n            break;\n        }\n#endif\n        case 6: /* c.sw */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.sw %s,%d(%s)\",\n                     reg[i->rs2], i->imm, reg[i->rs1]);\n            break;\n        }\n#if defined(RV64)\n        case 7: /* c.sd */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.sd %s,%d(%s)\",\n                     reg[i->rs2], i->imm, reg[i->rs1]);\n            break;\n        }\n#elif SIM_FLEN >= 32\n        case 7: /* c.fsw */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.fsw %s,%d(%s)\",\n                     fp_reg[i->rs2], i->imm, reg[i->rs1]);\n            break;\n        }\n#endif\n    }\n}\n\nstatic void\nset_ext_c_q1_str(RVInstruction *i)\n{\n    switch (i->funct3)\n    {\n        case 0: /* c.addi/c.nop */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.addi %s,%d\",\n                     reg[i->rd], i->imm);\n            break;\n        }\n#if defined(RV32)\n        case 1: /* c.jal */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.jal %d\", i->imm);\n            break;\n        }\n#elif defined(RV64)\n        case 1: /* c.addiw */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.addiw %s,%d\",\n                     reg[i->rd], i->imm);\n            break;\n        }\n#endif\n        case 2: /* c.li */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.li %s,%d\", reg[i->rd],\n                     i->imm);\n            break;\n        }\n        case 3:\n        {\n            if (i->rd == 2)\n            {\n                /* c.addi16sp */\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.addi16sp %s,%d\",\n                         reg[i->rd], i->imm);\n            }\n            else if (i->rd != 0)\n            {\n                /* c.lui */\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.lui %s,%d\",\n                         reg[i->rd], i->imm);\n            }\n            break;\n        }\n        case 4:\n        {\n            switch (i->funct4)\n            {\n                case 0: /* c.srli */\n                case 1: /* c.srai */\n                {\n                    if (i->funct4 == 0)\n                    {\n                        snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                                 \"c.srli %s,%d\", reg[i->rd], i->imm);\n                    }\n                    else\n                    {\n                        snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                                 \"c.srai %s,%d\", reg[i->rd], i->imm);\n                    }\n                    break;\n                }\n                case 2: /* c.andi */\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.andi %s,%d\",\n                             reg[i->rd], i->imm);\n                    break;\n                }\n                case 3:\n                {\n                    switch (i->funct5)\n                    {\n                        case 0: /* c.sub */\n                        {\n                            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                                     \"c.sub %s,%s\", reg[i->rd], reg[i->rs2]);\n                            break;\n                        }\n                        case 1: /* c.xor */\n                        {\n                            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                                     \"c.xor %s,%s\", reg[i->rd], reg[i->rs2]);\n                            break;\n                        }\n                        case 2: /* c.or */\n                        {\n                            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                                     \"c.or %s,%s\", reg[i->rd], reg[i->rs2]);\n                            break;\n                        }\n                        case 3: /* c.and */\n                        {\n                            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                                     \"c.and %s,%s\", reg[i->rd], reg[i->rs2]);\n                            break;\n                        }\n#if defined(RV64)\n                        case 4: /* c.subw */\n                        {\n                            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                                     \"c.subw %s,%s\", reg[i->rd], reg[i->rs2]);\n                            break;\n                        }\n                        case 5: /* c.addw */\n                        {\n                            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                                     \"c.addw %s,%s\", reg[i->rd], reg[i->rs2]);\n                            break;\n                        }\n#endif\n                    }\n                    break;\n                }\n            }\n            break;\n        }\n        case 5: /* c.j */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.j %d\", i->imm);\n            break;\n        }\n        case 6: /* c.beqz */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.beqz %s,%d\",\n                     reg[i->rs1], i->imm);\n            break;\n        }\n        case 7: /* c.bnez */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.bnez %s,%d\",\n                     reg[i->rs1], i->imm);\n            break;\n        }\n    }\n}\n\nstatic void\nset_ext_c_q2_str(RVInstruction *i)\n{\n    uint32_t insn = i->binary;\n\n    switch (i->funct3)\n    {\n        case 0: /* c.slli */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.slli %s,%d\",\n                     reg[i->rd], i->imm);\n            break;\n        }\n#if SIM_FLEN >= 64\n        case 1: /* c.fldsp */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.fldsp %s,%d(sp)\",\n                     fp_reg[i->rd], i->imm);\n            break;\n        }\n#endif\n        case 2: /* c.lwsp */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.lwsp %s,%d(sp)\",\n                     reg[i->rd], i->imm);\n            break;\n        }\n#if defined(RV64)\n        case 3: /* c.ldsp */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.ldsp %s,%d(sp)\",\n                     reg[i->rd], i->imm);\n            break;\n        }\n#elif SIM_FLEN >= 32\n        case 3: /* c.flwsp */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.flwsp %s,%d(sp)\",\n                     fp_reg[i->rd], i->imm);\n        }\n        break;\n#endif\n        case 4:\n        {\n            if (((insn >> 12) & 1) == 0)\n            {\n                if (i->rs2 == 0)\n                {\n                    /* c.jr */\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.jr %s\",\n                             reg[i->rs1]);\n                }\n                else\n                {\n                    /* c.mv */\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.mv %s,%s\",\n                             reg[i->rd], reg[i->rs2]);\n                }\n            }\n            else\n            {\n                if (i->rs2 == 0)\n                {\n                    if (i->rd == 0)\n                    {\n                        /* c.ebreak */\n                        snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.break\");\n                    }\n                    else\n                    {\n                        /* c.jalr */\n                        snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.jalr %s\",\n                                 reg[i->rs1]);\n                    }\n                }\n                else\n                {\n                    /* c.add */\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.add %s,%s\",\n                             reg[i->rd], reg[i->rs2]);\n                }\n            }\n            break;\n        }\n#if SIM_FLEN >= 64\n        case 5: /* c.fsdsp */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.fsdsp %s,%d(sp)\",\n                     fp_reg[i->rs2], i->imm);\n            break;\n        }\n#endif\n        case 6: /* c.swsp */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.swsp %s,%d(sp)\",\n                     reg[i->rs2], i->imm);\n            break;\n        }\n#if defined(RV64)\n        case 7: /* c.sdsp */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.sdsp %s,%d(sp)\",\n                     reg[i->rs2], i->imm);\n            break;\n        }\n#elif SIM_FLEN >= 32\n        case 7: /* c.fswsp */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"c.fswsp %s,%d(sp)\",\n                     fp_reg[i->rs2], i->imm);\n            break;\n        }\n#endif\n    }\n}\n\nstatic void\nset_ext_c_str(RVInstruction *i)\n{\n    switch (i->quad)\n    {\n        case 0:\n        {\n            set_ext_c_q0_str(i);\n            break;\n        }\n        case 1:\n        {\n            set_ext_c_q1_str(i);\n            break;\n        }\n        case 2:\n        {\n            set_ext_c_q2_str(i);\n            break;\n        }\n    }\n}\n\nstatic void\nset_load_str(RVInstruction *i)\n{\n    const char *name;\n\n    switch (i->bytes_to_rw)\n    {\n        case 1:\n        {\n            name = \"lb\";\n            break;\n        }\n        case 2:\n        {\n            name = \"lh\";\n            break;\n        }\n        case 4:\n        {\n            name = \"lw\";\n            break;\n        }\n        case 8:\n        {\n            name = \"ld\";\n            break;\n        }\n        default:\n        {\n            return;\n        }\n    }\n\n    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"%s%s %s,%d(%s)\", name,\n             (i->is_unsigned ? \"u\" : \"\"), reg[i->rd], i->imm, reg[i->rs1]);\n}\n\nstatic void\nset_store_str(RVInstruction *i)\n{\n    const char *name;\n\n    switch (i->bytes_to_rw)\n    {\n        case 1:\n        {\n            name = \"sb\";\n            break;\n        }\n        case 2:\n        {\n            name = \"sh\";\n            break;\n        }\n        case 4:\n        {\n            name = \"sw\";\n            break;\n        }\n        case 8:\n        {\n            name = \"sd\";\n            break;\n        }\n        default:\n        {\n            return;\n        }\n    }\n\n    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"%s %s,%d(%s)\", name,\n             reg[i->rs2], i->imm, reg[i->rs1]);\n}\n\nstatic void\nset_csr_str(RVInstruction *i)\n{\n    const CsrName *csr;\n    const char *name;\n    char cname[20];\n    int32_t imm;\n    uint32_t funct3;\n    int has_imm;\n\n    funct3 = (i->binary >> 12) & 7;\n    imm = i->binary >> 20;\n    has_imm = (funct3 & 4);\n    funct3 &= 3;\n\n    switch (funct3)\n    {\n        case 1:\n        {\n            name = \"csrrw\";\n            break;\n        }\n        case 2:\n        {\n            name = \"csrrs\";\n            break;\n        }\n        case 3:\n        {\n            name = \"csrrc\";\n            break;\n        }\n        case 0:\n        {\n            switch (imm)\n            {\n                case 0x000: /* ecall */\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"ecall\");\n                    break;\n                }\n                case 0x001: /* ebreak */\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"ebreak\");\n                    break;\n                }\n                case 0x102: /* sret */\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"sret\");\n                    break;\n                }\n                case 0x302: /* mret */\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"mret\");\n                    break;\n                }\n                case 0x105: /* wfi */\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"wfi\");\n                    break;\n                }\n                default:\n                {\n                    if ((imm >> 5) == 0x09)\n                    {\n                        /* sfence.vma */\n                        snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                                 \"sfence.vma\");\n                    }\n                    break;\n                }\n            }\n            return;\n        }\n    }\n\n    for (csr = csr_names; csr->i != 0 || csr->name != 0; csr++)\n    {\n        if ((imm & ~csr->n) == csr->i)\n            break;\n    }\n\n    if (csr->name != 0)\n    {\n        snprintf(cname, sizeof(cname), csr->name, (imm & csr->n));\n        if (has_imm)\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"%si %s,%s,%d\", name,\n                     reg[i->rd], cname, i->rs1);\n        }\n        else\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"%s %s,%s,%s\", name,\n                     reg[i->rd], cname, reg[i->rs1]);\n        }\n    }\n}\n\nstatic void\nset_fence_str(RVInstruction *i)\n{\n    switch (i->funct3)\n    {\n        case 0: /* fence */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fence\");\n            break;\n        }\n        case 1: /* fence.i */\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fence.i\");\n            break;\n        }\n    }\n}\n\nvoid\ngenerate_riscv_instruction_string(RVInstruction *i)\n{\n    int32_t rm;\n\n    /* For 16-bit compressed instructions */\n    if ((i->binary & 3) != 3)\n    {\n        set_ext_c_str(i);\n        return;\n    }\n\n    /* For 32-bit integer and floating point instructions */\n    switch (i->major_opcode)\n    {\n\n        case OP_IMM_MASK:\n        {\n            set_op_imm_str(i);\n            break;\n        }\n\n        case OP_IMM_32_MASK:\n        {\n            set_op_imm_32_str(i);\n            break;\n        }\n\n        case OP_MASK:\n        {\n            set_op_str(i);\n            break;\n        }\n\n        case OP_MASK_32:\n        {\n            set_op_32_str(i);\n            break;\n        }\n\n        case LUI_MASK:\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"lui %s,0x%x\",\n                     reg[i->rd], i->imm);\n            break;\n        }\n\n        case AUIPC_MASK:\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"auipc %s,%d\",\n                     reg[i->rd], i->imm);\n            break;\n        }\n\n        case LOAD_MASK:\n        {\n            set_load_str(i);\n            break;\n        }\n        case STORE_MASK:\n        {\n            set_store_str(i);\n            break;\n        }\n\n        case JAL_MASK:\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"jal %s,%d\", reg[i->rd],\n                     i->imm);\n            break;\n        }\n\n        case JALR_MASK:\n        {\n            snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"jalr %s,%s,%d\",\n                     reg[i->rd], reg[i->rs1], i->imm);\n            break;\n        }\n\n        case BRANCH_MASK:\n        {\n            set_branch_str(i);\n            break;\n        }\n\n        case ATOMIC_MASK:\n        {\n            uint32_t funct7 = (i->binary >> 27) & 0x1F;\n            const char *size = size_suffix[(i->binary >> 12) & 7];\n            const char *aqrl = aqrl_suffix[(i->binary >> 25) & 3];\n            if (funct7 == 2) /* lr.[wd] */\n            {\n                snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"lr.%s%s %s,(%s)\",\n                         size, aqrl, reg[i->rd], reg[i->rs1]);\n            }\n            else\n            {\n                const char *const names[32]\n                    = {\"amoadd\",  \"amoswap\", 0, \"sc\", \"amoxor\",  0, 0, 0,\n                       \"amoor\",   0,         0, 0,    \"amoand\",  0, 0, 0,\n                       \"amomin\",  0,         0, 0,    \"amomax\",  0, 0, 0,\n                       \"amominu\", 0,         0, 0,    \"amomaxu\", 0, 0, 0};\n                const char *name = names[funct7];\n                if (name != 0)\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                             \"%s.%s%s %s,%s,(%s)\", name, size, aqrl, reg[i->rd],\n                             reg[i->rs2], reg[i->rs1]);\n                }\n            }\n            break;\n        }\n\n        case CSR_MASK:\n        {\n            set_csr_str(i);\n            break;\n        }\n\n        case FENCE_MASK:\n        {\n            set_fence_str(i);\n            break;\n        }\n\n        case FLOAD_MASK:\n        {\n            switch (i->funct3)\n            {\n                case 2: /* flw */\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"flw %s,%d(%s)\",\n                             fp_reg[i->rd], i->imm, reg[i->rs1]);\n                    break;\n                }\n#if SIM_FLEN >= 64\n                case 3: /* fld */\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fld %s,%d(%s)\",\n                             fp_reg[i->rd], i->imm, reg[i->rs1]);\n                    break;\n                }\n#endif\n            }\n            break;\n        }\n\n        case FSTORE_MASK:\n        {\n            switch (i->funct3)\n            {\n                case 2: /* fsw */\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fsw %s,%d(%s)\",\n                             fp_reg[i->rs2], i->imm, reg[i->rs1]);\n                    break;\n                }\n#if SIM_FLEN >= 64\n                case 3: /* fsd */\n#endif\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH, \"fsd %s,%d(%s)\",\n                             fp_reg[i->rs2], i->imm, reg[i->rs1]);\n                }\n                break;\n            }\n            break;\n        }\n\n        case 0x43:\n        { /* fmadd */\n            rm = i->rm;\n            switch (i->funct3)\n            {\n                case 0:\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                             \"fmadd.s %s,%s,%s,%s\", fp_reg[i->rd],\n                             fp_reg[i->rs1], fp_reg[i->rs2], fp_reg[i->rs3]);\n                    break;\n                }\n                case 1:\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                             \"fmadd.d %s,%s,%s,%s\", fp_reg[i->rd],\n                             fp_reg[i->rs1], fp_reg[i->rs2], fp_reg[i->rs3]);\n                    break;\n                }\n            }\n            break;\n        }\n\n        case 0x47:\n        { /* fmsub*/\n            rm = i->rm;\n            switch (i->funct3)\n            {\n                case 0:\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                             \"fmsub.s %s,%s,%s,%s\", fp_reg[i->rd],\n                             fp_reg[i->rs1], fp_reg[i->rs2], fp_reg[i->rs3]);\n                    break;\n                }\n                case 1:\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                             \"fmsub.d %s,%s,%s,%s\", fp_reg[i->rd],\n                             fp_reg[i->rs1], fp_reg[i->rs2], fp_reg[i->rs3]);\n                }\n                break;\n            }\n            break;\n        }\n\n        case 0x4b:\n        { /* fnmsub */\n            rm = i->rm;\n            switch (i->funct3)\n            {\n                case 0:\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                             \"fnmsub.s %s,%s,%s,%s\", fp_reg[i->rd],\n                             fp_reg[i->rs1], fp_reg[i->rs2], fp_reg[i->rs3]);\n                    break;\n                }\n\n                case 1:\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                             \"fnmsub.d %s,%s,%s,%s\", fp_reg[i->rd],\n                             fp_reg[i->rs1], fp_reg[i->rs2], fp_reg[i->rs3]);\n                    break;\n                }\n            }\n            break;\n        }\n\n        case 0x4f:\n        { /* fnmadd */\n            rm = i->rm;\n            switch (i->funct3)\n            {\n                case 0:\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                             \"fnmadd.s %s,%s,%s,%s\", fp_reg[i->rd],\n                             fp_reg[i->rs1], fp_reg[i->rs2], fp_reg[i->rs3]);\n                    break;\n                }\n                case 1:\n                {\n                    snprintf(i->str, RISCV_INS_STR_MAX_LENGTH,\n                             \"fnmadd.d %s,%s,%s,%s\", fp_reg[i->rd],\n                             fp_reg[i->rs1], fp_reg[i->rs2], fp_reg[i->rs3]);\n                    break;\n                }\n            }\n            break;\n        }\n\n        case F_ARITHMETIC_MASK:\n        {\n            rm = i->rm;\n            switch (i->funct7)\n            {\n#define F_SIZE 32\n#include \"fp_string_generator_template.h\"\n#if SIM_FLEN >= 64\n#define F_SIZE 64\n#include \"fp_string_generator_template.h\"\n#endif\n            }\n            break;\n        }\n    }\n}\n"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/cache.c",
    "content": "/**\n * Caches\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <math.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../utils/sim_log.h\"\n#include \"cache.h\"\n\nstatic void\nupdate_tag_address(const Cache *c, uint32_t *pset, CacheBlk **pblk,\n                   target_ulong *ptag, target_ulong *paddr,\n                   int *pbytes_to_access, int available_bytes)\n{\n    /* Update pbytes_to_access to account for the available_bytes already\n     * accessed */\n    *pbytes_to_access = *pbytes_to_access - available_bytes;\n\n    /* Calculate set, tag and physical address to access remaining bytes not\n     * present in the current cache line */\n    *pset = (*pset + 1) % c->num_sets;\n    *pblk = c->blk[*pset];\n    *ptag = (*ptag + 1) % c->max_tag_val;\n    *paddr = *ptag << c->word_bits;\n}\n\nstatic int\nread_data_internal(const Cache *c, target_ulong paddr, int bytes_to_read,\n                   void *p_mem_access_info, int priv)\n{\n    /* Read from next-level cache if present, otherwise from memory */\n    if (NULL != c->next_level_cache)\n    {\n        return cache_read(c->next_level_cache, paddr, bytes_to_read,\n                          p_mem_access_info, priv);\n    }\n\n    return mem_controller_create_mem_request(c->mem_controller, paddr,\n                                             bytes_to_read, MEM_ACCESS_READ,\n                                             p_mem_access_info);\n}\n\nstatic int\nread_allocate_handler(const Cache *c, target_ulong paddr, int bytes_to_read,\n                      int set, void *p_mem_access_info, int priv)\n{\n    target_ulong tag;\n    int latency = 0;\n\n    CacheBlk *blk = c->blk[set];\n    /* Select victim using the set policy */\n    int victim = c->evict_policy->evict(c->evict_policy, set);\n\n    /* As we want to allocate complete line, bytes_to_read = cache line width in\n     * bytes and paddr is the address of the zeroth byte in the cache line */\n    paddr = paddr & c->tag_bits_mask;\n    bytes_to_read = (WORD_SIZE * c->max_words_per_blk);\n    tag = paddr >> (c->word_bits);\n\n    /* Handle victim eviction according to set policy */\n    latency += (*c->pfn_victim_evict_handler)(c, &(blk[victim]), set, victim,\n                                              p_mem_access_info, priv);\n\n    /* Read the line contents into the cache line selected as victim and adjust\n     * the latency accordingly */\n    latency\n        += read_data_internal(c, paddr, bytes_to_read, p_mem_access_info, priv);\n\n    blk[victim].tag = tag;\n    blk[victim].status = Valid;\n\n    /* Update the status bits used for victim selection policy */\n    c->evict_policy->use(c->evict_policy, set, victim);\n\n    return latency;\n}\n\nstatic int\nread_no_allocate_handler(const Cache *c, target_ulong paddr, int bytes_to_read,\n                         int set, void *p_mem_access_info, int priv)\n{\n    /* Read the line contents and adjust the latency accordingly */\n    return read_data_internal(c, paddr, bytes_to_read, p_mem_access_info, priv);\n}\n\nint\ncache_read(const Cache *c, target_ulong paddr, int bytes_to_read,\n           void *p_mem_access_info, int priv)\n{\n    int i;\n    uint32_t start_byte = (paddr & ((1 << c->word_bits) - 1));\n    uint32_t set = (paddr >> c->word_bits) & ((1 << c->set_bits) - 1);\n    target_ulong tag = paddr >> (c->word_bits);\n    int latency = c->read_latency;\n    int available_bytes = 0;\n    int cache_miss_updated = 0;\n    CacheBlk *blk = c->blk[set];\n\n    c->stats[priv].total_read_cnt++;\n\n    while (bytes_to_read > 0)\n    {\n        for (i = 0; i < c->num_ways; ++i)\n        {\n            if ((blk[i].tag == tag) && (blk[i].status == Valid))\n            {\n                /* Tag-match: Physical address is present in the cache */\n                c->evict_policy->use(c->evict_policy, set, i);\n\n                if ((start_byte + bytes_to_read)\n                    <= (c->max_words_per_blk * WORD_SIZE))\n                {\n                    /* All required bytes are present in the cache */\n                    return latency;\n                }\n\n                /* Required bytes are possibly split across 2 cache lines */\n                /* Calculate the bytes available to read in the current cache\n                 * line */\n                available_bytes\n                    = ((c->max_words_per_blk * WORD_SIZE) - start_byte);\n\n                /* Adjust the remaining bytes to read, tag, set and physical\n                 * address */\n                update_tag_address(c, &set, &blk, &tag, &paddr, &bytes_to_read,\n                                   available_bytes);\n                break;\n            }\n        }\n\n        if (i < c->num_ways)\n        {\n            /* It means above loop was broken because required bytes were not\n             * found in the same cache line. So, start looking again for new tag\n             * and address */\n            continue;\n        }\n\n        if (!cache_miss_updated)\n        {\n            c->stats[priv].read_miss_cnt++;\n            cache_miss_updated = 1;\n        }\n\n        if ((start_byte + bytes_to_read) <= (c->max_words_per_blk * WORD_SIZE))\n        {\n            /* All remaining bytes can be allocated in the same line */\n            latency += (*c->pfn_read_alloc_handler)(\n                c, paddr, bytes_to_read, set, p_mem_access_info, priv);\n            break;\n        }\n        else\n        {\n            /* All remaining bytes can not be allocated in the same line */\n            available_bytes = ((c->max_words_per_blk * WORD_SIZE) - start_byte);\n\n            /* Read the required line contents and allocate the cache line using\n             * set policy */\n            latency += (*c->pfn_read_alloc_handler)(\n                c, paddr, available_bytes, set, p_mem_access_info, priv);\n\n            /* Adjust the remaining bytes to read, tag, set and physical\n             * address */\n            update_tag_address(c, &set, &blk, &tag, &paddr, &bytes_to_read,\n                               available_bytes);\n            continue;\n        }\n    }\n\n    return latency;\n}\n\nstatic int\nwriteback_handler(const Cache *c, target_ulong paddr, int bytes_to_write,\n                  int set, int way, void *p_mem_access_info, int priv)\n{\n    /* Just update dirty bit and status bits, no need to write to next cache */\n    CacheBlk *blk = c->blk[set];\n    blk[way].dirty = Dirty;\n    c->evict_policy->use(c->evict_policy, set, way);\n    return 0;\n}\n\nstatic int\nwritethrough_handler(const Cache *c, target_ulong paddr, int bytes_to_write,\n                     int set, int way, void *p_mem_access_info, int priv)\n{\n    /* Update the dirty bit and status bits */\n    CacheBlk *blk = c->blk[set];\n    blk[way].dirty = Dirty;\n    c->evict_policy->use(c->evict_policy, set, way);\n\n    /* Propagate write to next-level cache if available, memory otherwise */\n    if (NULL != c->next_level_cache)\n    {\n        return cache_write(c->next_level_cache, paddr, bytes_to_write,\n                           p_mem_access_info, priv);\n    }\n\n    return mem_controller_create_mem_request(c->mem_controller, paddr,\n                                             bytes_to_write, MEM_ACCESS_WRITE,\n                                             p_mem_access_info);\n}\n\nstatic int\nwrite_allocate_handler(const Cache *c, target_ulong paddr, int bytes_to_write,\n                       int set, void *p_mem_access_info, int priv)\n{\n    int latency = 0;\n    CacheBlk *blk = c->blk[set];\n\n    /* As we want to allocate complete line, bytes_to_read = cache line width in\n     * bytes and paddr is the address of the zeroth byte in the cache line */\n    int bytes_to_read = (WORD_SIZE * c->max_words_per_blk);\n\n    /* Zero out the word bits to create address of first byte in the cache line\n     * as we have to read contents for the whole cache line */\n    target_ulong new_paddr = paddr & c->tag_bits_mask;\n    target_ulong tag = paddr >> (c->word_bits);\n\n    /* Select victim using the set policy */\n    int victim = c->evict_policy->evict(c->evict_policy, set);\n    /* Handle victim eviction according to set policy */\n    latency += (*c->pfn_victim_evict_handler)(c, &(blk[victim]), set, victim,\n                                              p_mem_access_info, priv);\n\n    /* Read the line contents into the cache line selected as victim and adjust\n     * the latency accordingly */\n    latency += read_data_internal(c, new_paddr, bytes_to_read,\n                                  p_mem_access_info, priv);\n\n    blk[victim].tag = tag;\n    blk[victim].status = Valid;\n\n    /* Handle the cache write using underlying write policy */\n    latency += (*c->pfn_write_handler)(c, paddr, bytes_to_write, set, victim,\n                                       p_mem_access_info, priv);\n\n    return latency;\n}\n\nstatic int\nwrite_no_allocate_handler(const Cache *c, target_ulong paddr,\n                          int bytes_to_write, int set, void *p_mem_access_info,\n                          int priv)\n{\n    /* Do not allocate cache line but propagate write to next-level cache if\n     * available, memory otherwise */\n    if (NULL != c->next_level_cache)\n    {\n        return cache_write(c->next_level_cache, paddr, bytes_to_write,\n                           p_mem_access_info, priv);\n    }\n\n    return mem_controller_create_mem_request(c->mem_controller, paddr,\n                                             bytes_to_write, MEM_ACCESS_WRITE,\n                                             p_mem_access_info);\n}\n\nstatic int\nwriteback_victim_evict_handler(const Cache *c, CacheBlk *pBlk, int set, int way,\n                               void *p_mem_access_info, int priv)\n{\n    int latency = 0;\n\n    if (NULL != pBlk)\n    {\n        /* If the cache line contents are dirty, write to next level cache if\n         * present, otherwise write to memory */\n        if (Valid == pBlk->status && Dirty == pBlk->dirty)\n        {\n            if (NULL != c->next_level_cache)\n            {\n                latency += cache_write(c->next_level_cache,\n                                       (pBlk->tag << c->word_bits),\n                                       (WORD_SIZE * c->max_words_per_blk),\n                                       p_mem_access_info, priv);\n            }\n            else\n            {\n                latency += mem_controller_create_mem_request(\n                    c->mem_controller, pBlk->tag << c->word_bits,\n                    (WORD_SIZE * c->max_words_per_blk), MEM_ACCESS_WRITE,\n                    p_mem_access_info);\n            }\n        }\n        memset(pBlk, 0, sizeof(CacheBlk));\n    }\n\n    return latency;\n}\n\nstatic int\nwritethrough_victim_evict_handler(const Cache *c, CacheBlk *pBlk, int set,\n                                  int way, void *p_mem_access_info, int priv)\n{\n    /* No need to write to next level cache or memory as we have already written\n     * it */\n    memset(pBlk, 0, sizeof(CacheBlk));\n    return 0;\n}\n\nint\ncache_write(const Cache *c, target_ulong paddr, int bytes_to_write,\n            void *p_mem_access_info, int priv)\n{\n    int i;\n    uint32_t start_byte = (paddr & ((1 << c->word_bits) - 1));\n    uint32_t set = (paddr >> c->word_bits) & ((1 << c->set_bits) - 1);\n    target_ulong tag = paddr >> (c->word_bits);\n    int latency = c->write_latency;\n    int available_bytes = 0;\n    int cache_miss_updated = 0;\n    CacheBlk *blk = c->blk[set];\n\n    c->stats[priv].total_write_cnt++;\n\n    while (bytes_to_write > 0)\n    {\n        for (i = 0; i < c->num_ways; ++i)\n        {\n            if ((blk[i].tag == tag) && (blk[i].status == Valid))\n            {\n                /* Tag-match: Physical address is present in the cache */\n                if ((start_byte + bytes_to_write)\n                    <= (c->max_words_per_blk * WORD_SIZE))\n                {\n                    /* All required bytes are present in the cache */\n                    latency += (*c->pfn_write_handler)(c, paddr, bytes_to_write,\n                                                       set, i,\n                                                       p_mem_access_info, priv);\n                    return latency;\n                }\n\n                /* Required bytes are possibly split across 2 cache lines */\n                available_bytes\n                    = ((c->max_words_per_blk * WORD_SIZE) - start_byte);\n\n                /* Write the cache line with the bytes_to_write set to actual\n                 * bytes found in this cache line */\n                latency += (*c->pfn_write_handler)(\n                    c, paddr, available_bytes, set, i, p_mem_access_info, priv);\n\n                /* Adjust the remaining bytes to write */\n                update_tag_address(c, &set, &blk, &tag, &paddr, &bytes_to_write,\n                                   available_bytes);\n                break;\n            }\n        }\n\n        if (i < c->num_ways)\n        {\n            /* It means above loop was broken because required bytes were not\n             * found in the same cache line. So, start looking again for new tag\n             * and address */\n            continue;\n        }\n\n        /* Cache Write Miss */\n        if (!cache_miss_updated)\n        {\n            c->stats[priv].write_miss_cnt++;\n            cache_miss_updated = 1;\n        }\n\n        /* Call write allocator function */\n        if ((start_byte + bytes_to_write) <= (c->max_words_per_blk * WORD_SIZE))\n        {\n            latency += (*c->pfn_write_alloc_handler)(\n                c, paddr, bytes_to_write, set, p_mem_access_info, priv);\n            break;\n        }\n        else\n        {\n            available_bytes = ((c->max_words_per_blk * WORD_SIZE) - start_byte);\n\n            /* Write the cache line with the bytes_to_write set to actual bytes\n             * found in this cache line and adjust the latency */\n            latency += (*c->pfn_write_alloc_handler)(\n                c, paddr, ((c->max_words_per_blk * WORD_SIZE) - start_byte),\n                set, p_mem_access_info, priv);\n\n            /* Adjust the remaining bytes to write */\n            update_tag_address(c, &set, &blk, &tag, &paddr, &bytes_to_write,\n                               available_bytes);\n            continue;\n        }\n    }\n\n    return latency;\n}\n\nvoid\ncache_flush(Cache *c)\n{\n    int i;\n\n    c->evict_policy->reset(c->evict_policy);\n\n    for (i = 0; i < c->num_sets; ++i)\n    {\n        memset((void *)c->blk[i], 0, sizeof(CacheBlk) * c->num_ways);\n    }\n}\n\nconst CacheStats *\ncache_get_stats(const Cache *c)\n{\n    return (const CacheStats *)(c->stats);\n}\n\nvoid\ncache_reset_stats(Cache *c)\n{\n    memset((void *)c->stats, 0, NUM_MAX_PRV_LEVELS * sizeof(CacheStats));\n}\n\nstatic void\ncache_log_config(const Cache *c)\n{\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"level\", c->level);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"num_blks\", c->num_blks);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"num_ways\", c->num_ways);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"num_sets\", c->num_sets);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"set_bits\", c->set_bits);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"tag_bits\", c->tag_bits);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"max_words_per_blk\", c->max_words_per_blk);\n    sim_log_param_to_file(sim_log, \"%s: %d bytes\", \"word_size\", WORD_SIZE);\n    sim_log_param_to_file(sim_log, \"%s: %d bytes\", \"line_size\", (WORD_SIZE * c->max_words_per_blk));\n    sim_log_param_to_file(sim_log, \"%s: %d KB\", \"total_size\", c->size);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"evict_policy\", evict_policy_str[c->evict_policy->type]);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"read_alloc_policy\", cache_ra_str[c->cache_read_alloc_policy]);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"write_alloc_policy\", cache_wa_str[c->cache_write_alloc_policy]);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"write_policy\", cache_wp_str[c->cache_write_policy]);\n    sim_log_param_to_file(sim_log, \"%s: %d cycle(s)\", \"read_latency\", c->read_latency);\n    sim_log_param_to_file(sim_log, \"%s: %d cycle(s)\", \"write_latency\", c->write_latency);\n}\n\nstatic int\nget_num_cache_blks(int size_kb, int cache_line_size)\n{\n    return (int)((size_kb * 1024) / cache_line_size);\n}\n\nCache *\ncache_init(CacheTypes type, CacheLevels level, int size_kb, int cache_line_size,\n           uint32_t ways, int read_latency, int write_latency,\n           Cache *next_level_cache, int words_per_blk, int evict_policy,\n           CacheWritePolicy write_policy,\n           CacheReadAllocPolicy read_alloc_policy,\n           CacheWriteAllocPolicy write_alloc_policy,\n           MemoryController *mem_controller)\n{\n    int i;\n    uint32_t blks = get_num_cache_blks(size_kb, cache_line_size);\n    Cache *c = (Cache *)malloc(sizeof(Cache));\n\n    c->type = type;\n    c->level = level;\n    c->num_blks = blks;\n    c->num_ways = ways;\n    c->num_sets = (blks / ways);\n\n    /* Allocate memory for all cache line pointers */\n    c->blk = (CacheBlk **)calloc(c->num_sets, sizeof(CacheBlk *));\n    assert(c->blk);\n\n    /* Allocate memory for cache blocks */\n    for (i = 0; i < c->num_sets; ++i)\n    {\n        c->blk[i] = (CacheBlk *)calloc(c->num_ways, sizeof(CacheBlk));\n        assert(c->blk[i]);\n    }\n\n    c->max_words_per_blk = words_per_blk;\n\n    /* No. of bits required to represent byte offset within the cache line */\n    c->word_bits = GET_NUM_BITS(WORD_SIZE * c->max_words_per_blk);\n    /* No. of bits required to represent target set in the physical address */\n    c->set_bits = GET_NUM_BITS(c->num_sets);\n\n    /* Size of cache in KBs */\n    c->size = (c->num_blks * c->max_words_per_blk * WORD_SIZE) / 1024;\n\n    /* Included set bits again in the tag bits */\n    c->tag_bits = (sizeof(target_ulong) * 8) - c->word_bits;\n    c->tag_bits_mask = (target_ulong)(pow(2, sizeof(target_ulong) * 8) - 1)\n                       << c->word_bits;\n    c->max_tag_val = (1 << c->tag_bits);\n\n    c->read_latency = read_latency;\n    c->write_latency = write_latency;\n    c->mem_controller = mem_controller;\n\n    c->next_level_cache = next_level_cache;\n    if (NULL == c->next_level_cache)\n    {\n        assert(c->mem_controller);\n    }\n\n    c->stats = (CacheStats *)calloc(NUM_MAX_PRV_LEVELS, sizeof(CacheStats));\n    assert(c->stats);\n\n    c->evict_policy\n        = evict_policy_create(c->num_sets, c->num_ways, evict_policy);\n    c->cache_write_policy = write_policy;\n    c->cache_read_alloc_policy = read_alloc_policy;\n    c->cache_write_alloc_policy = write_alloc_policy;\n\n    /* Set write policy handler function pointer */\n    switch (write_policy)\n    {\n        case WriteBack:\n        {\n            c->pfn_write_handler = &writeback_handler;\n            c->pfn_victim_evict_handler = &writeback_victim_evict_handler;\n            break;\n        }\n\n        case WriteThrough:\n        {\n            c->pfn_write_handler = &writethrough_handler;\n            c->pfn_victim_evict_handler = &writethrough_victim_evict_handler;\n            break;\n        }\n    }\n\n    /* Set cache line allocation handler function pointer on read-miss */\n    switch (read_alloc_policy)\n    {\n        case ReadAllocate:\n        {\n            c->pfn_read_alloc_handler = &read_allocate_handler;\n            break;\n        }\n\n        case ReadNoAllocate:\n        {\n            c->pfn_read_alloc_handler = &read_no_allocate_handler;\n            break;\n        }\n    }\n\n    /* Set cache line allocation handler function pointer on write-miss */\n    switch (write_alloc_policy)\n    {\n        case WriteAllocate:\n        {\n            c->pfn_write_alloc_handler = &write_allocate_handler;\n            break;\n        }\n\n        case WriteNoAllocate:\n        {\n            c->pfn_write_alloc_handler = &write_no_allocate_handler;\n            break;\n        }\n    }\n\n    cache_log_config(c);\n    return c;\n}\n\nvoid\ncache_free(Cache **c)\n{\n    int i;\n\n    for (i = 0; i < (*c)->num_sets; ++i)\n    {\n        free((*c)->blk[i]);\n        (*c)->blk[i] = NULL;\n    }\n    free((*c)->blk);\n    (*c)->blk = NULL;\n    free((*c)->stats);\n    (*c)->stats = NULL;\n    evict_policy_free(&(*c)->evict_policy);\n    free(*c);\n    *c = NULL;\n}"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/cache.h",
    "content": "/**\n * Caches\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _CACHE_H_\n#define _CACHE_H_\n\n#include \"../riscv_sim_typedefs.h\"\n#include \"../utils/evict_policy.h\"\n#include \"../utils/sim_params.h\"\n#include \"memory_controller.h\"\n\n/* Word size in the target architecture */\n#define WORD_SIZE (sizeof(target_ulong))\n\nstruct CacheBlk;\nstruct Cache;\n\ntypedef int (*PFN_GET_VICTIM_INDEX)(const struct Cache *c, int set);\ntypedef int (*PFN_READ_ALLOC_HANDLER)(const struct Cache *c, target_ulong paddr,\n                                      int bytes_to_read, int set,\n                                      void *p_mem_access_info, int priv);\ntypedef int (*PFN_WRITE_HANDLER)(const struct Cache *c, target_ulong paddr,\n                                 int bytes_to_write, int set, int way,\n                                 void *p_mem_access_info, int priv);\ntypedef int (*PFN_WRITE_ALLOC_HANDLER)(const struct Cache *c,\n                                       target_ulong paddr, int bytes_to_write,\n                                       int set, void *p_mem_access_info,\n                                       int priv);\ntypedef int (*PFN_VICTIM_EVICTION_HANDLER)(const struct Cache *c,\n                                           struct CacheBlk *pBlk, int set,\n                                           int way, void *p_mem_access_info,\n                                           int priv);\n\n/* Cache types */\ntypedef enum CacheTypes {\n    InstructionCache = 0x1,\n    DataCache = 0x2,\n    SharedCache = 0x3,\n} CacheTypes;\n\n/* Cache Levels, add levels as required */\ntypedef enum CacheLevels {\n    L1 = 0x1,\n    L2 = 0x2,\n    L3 = 0x3,\n} CacheLevels;\n\n/* Status of the cache block */\ntypedef enum BlockStatus {\n    Unused = 0x0,\n    Valid = 0x1,\n} BlockStatus;\n\n/* Block status, used if WriteBack policy is set */\ntypedef enum BlockDirtyStatus { NonDirty = 0x0, Dirty = 0x1 } BlockDirtyStatus;\n\n/* Cache line allocate policy on write-miss */\ntypedef enum CacheWriteAllocPolicy {\n    WriteAllocate = 0x0,\n    WriteNoAllocate = 0x1,\n} CacheWriteAllocPolicy;\n\n/* Cache line allocate policy on read-miss */\ntypedef enum CacheReadAllocPolicy {\n    ReadAllocate = 0x0,\n    ReadNoAllocate = 0x1,\n} CacheReadAllocPolicy;\n\n/* Cache write policy */\ntypedef enum CacheWritePolicy {\n    WriteBack = 0x0,\n    WriteThrough = 0x1,\n} CacheWritePolicy;\n\n/* Statistical counters for cache */\ntypedef struct CacheStats\n{\n    uint64_t total_read_cnt;\n    uint64_t total_write_cnt;\n    uint64_t read_miss_cnt;\n    uint64_t write_miss_cnt;\n} CacheStats;\n\n/* Single cache line */\ntypedef struct CacheBlk\n{\n    uint8_t status;\n    uint8_t dirty;\n    target_ulong tag;\n} CacheBlk;\n\n/* Cache object storing cache blocks, status bits and policies to be used */\n\n/* Cache hierarchy model consists of two levels of physically indexed,\n * physically tagged blocking caches. Level-1 caches include a separate\n * instruction and data cache, whereas Level-2 consists of an optional unified\n * cache. The cache accesses are non-pipelined and follow a non-inclusive\n * non-exclusive design, meaning the contents of the lower level cache are\n * neither strictly inclusive nor exclusive of the higher-level cache. L2 cache\n * can be accessed in parallel by split L1 caches.*/\ntypedef struct Cache\n{\n    int level;\n    int type;\n\n    int num_ways;\n    int num_blks;\n    int num_sets;\n    int tag_bits;\n    int set_bits;\n    int word_bits;\n    uint64_t size;\n\n    int max_words_per_blk;\n    target_ulong max_tag_val;\n\n    target_ulong tag_bits_mask;\n    int read_latency;\n    int write_latency;\n\n    CacheWritePolicy cache_write_policy;\n    CacheReadAllocPolicy cache_read_alloc_policy;\n    CacheWriteAllocPolicy cache_write_alloc_policy;\n\n    MemoryController *mem_controller;\n\n    /* Function pointer respective to\n       eviction policy used(LRU/Random) */\n    PFN_GET_VICTIM_INDEX pfn_get_victim_index;\n    /* Function pointer respective cache line allocation policy\n       used on read-miss(Read-Allocate/Read-No-Allocate) */\n    PFN_READ_ALLOC_HANDLER pfn_read_alloc_handler;\n    /* Function pointer respective to write\n       policy used(write-back/write-through) */\n    PFN_WRITE_HANDLER pfn_write_handler;\n    /* Function pointer respective cache line allocation policy\n       used on write-miss(Read-Allocate/Read-No-Allocate) */\n    PFN_WRITE_ALLOC_HANDLER pfn_write_alloc_handler;\n    /* Function pointer respective to eviction policy\n       used(Write-Allocate/Write-No-Allocate) */\n    PFN_VICTIM_EVICTION_HANDLER pfn_victim_evict_handler;\n\n    CacheBlk **blk;\n\n    /* Pointer to the next level cache, if NULL it means it is the last level\n     * cache (LLC) */\n    struct Cache *next_level_cache;\n    CacheStats *stats;\n    EvictPolicy *evict_policy;\n} Cache;\n\nCache *cache_init(CacheTypes type, CacheLevels level, int size_kb,\n                  int cache_line_size, uint32_t ways, int read_latency,\n                  int write_latency, Cache *next_level_cache, int words_per_blk,\n                  int evict_policy, CacheWritePolicy write_policy,\n                  CacheReadAllocPolicy read_alloc_policy,\n                  CacheWriteAllocPolicy write_alloc_policy,\n                  MemoryController *mem_controller);\nvoid cache_flush(struct Cache *c);\nvoid cache_reset_stats(struct Cache *c);\nconst CacheStats *cache_get_stats(const struct Cache *c);\nint cache_read(const struct Cache *c, target_ulong paddr, int bytes_to_read,\n               void *p_mem_access_info, int priv);\nint cache_write(const struct Cache *c, target_ulong paddr, int bytes_to_read,\n                void *p_mem_access_info, int priv);\nvoid cache_free(Cache **c);\n#endif\n"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/dram.c",
    "content": "/**\n * DRAM model\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../utils/sim_log.h\"\n#include \"dram.h\"\n#include \"dramsim_wrapper_c_connector.h\"\n#include \"ramulator_wrapper_c_connector.h\"\n\nstatic void\ndram_log_config(const Dram *d, const SimParams *p)\n{\n    sim_log_event_to_file(sim_log, \"%s\", \"Setting up base dram\");\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"dram_model_type\",\n                          dram_model_type_str[p->dram_model_type]);\n    switch (p->dram_model_type)\n    {\n        case MEM_MODEL_BASE:\n        {\n            sim_log_param_to_file(sim_log, \"%s: %d cycle(s)\",\n                                  \"mem_access_latency\", d->mem_access_latency);\n            break;\n        }\n        case MEM_MODEL_DRAMSIM:\n        {\n            sim_log_param_to_file(sim_log, \"%s: %s)\", \"config_file\",\n                                  p->dramsim_config_file);\n            sim_log_param_to_file(sim_log, \"%s: %s\", \"output-directory\",\n                                  p->sim_file_path);\n            break;\n        }\n        case MEM_MODEL_RAMULATOR:\n        {\n            sim_log_param_to_file(sim_log, \"%s: %s)\", \"config_file\",\n                                  p->ramulator_config_file);\n            sim_log_param_to_file(sim_log, \"%s: %s\", \"output-directory\",\n                                  p->sim_file_path);\n            break;\n        }\n    }\n}\n\n/* Base DRAM model keeps track of the physical page number of the latest\n * request processed. Any subsequent accesses to the same physical page\n * occupies a lower delay, which is roughly 60 percent of the fixed\n * mem_access_latency. */\nstatic int\nbase_dram_model_get_max_clock_cycles(Dram *d, PendingMemAccessEntry *e)\n{\n    uint64_t current_page_num;\n    int max_clock_cycles = d->mem_access_latency;\n\n    /* Remove page offset to get current page number, page size is always 4KB */\n    current_page_num = e->addr >> 12;\n\n    if (d->last_accessed_page_num == current_page_num)\n    {\n        /* Page hit */\n        max_clock_cycles *= 0.6;\n    }\n    else\n    {\n        /* Page miss */\n        d->last_accessed_page_num = current_page_num;\n    }\n\n    return max_clock_cycles;\n}\n\n#define DRAMSIM3_RAM_BASE_ADDR 0x0\n#define TINYEMU_RAM_BASE_ADDR 0x80000000\n\n/* In TinyEMU, physical memory from 0x0 to 0x80000000 is allocated for the\n * TinyEMU devices. Guest RAM starts from address  0x80000000. Hence all the\n * physical addresses obtained after TLB lookup for guest RAM are above\n * 0x80000000. So before sending the address to DRAMsim3/ramulator (which starts\n * from 0x0), convert the given address. */\nstatic target_ulong\nget_tinyemu_ram_addr_from_zero(target_ulong tinyemu_ram_addr)\n{\n    target_ulong offset;\n\n    if (tinyemu_ram_addr >= TINYEMU_RAM_BASE_ADDR)\n    {\n        offset = tinyemu_ram_addr - TINYEMU_RAM_BASE_ADDR;\n        tinyemu_ram_addr = DRAMSIM3_RAM_BASE_ADDR + offset;\n    }\n\n    return tinyemu_ram_addr;\n}\n\nstatic int\ndramsim_get_max_clock_cycles(Dram *d, PendingMemAccessEntry *e)\n{\n    int max_clock_cycles;\n    target_ulong ram_addr = get_tinyemu_ram_addr_from_zero(e->addr);\n    max_clock_cycles = dramsim_wrapper_get_max_clock_cycles(e);\n\n    if (max_clock_cycles >= 1000)\n    {\n        sim_log_event(sim_log,\n                      \"possible dramsim3 block detected, callback for physical \"\n                      \"addr 0x% \" TARGET_ULONG_HEX \" received after %d cycle(s)\",\n                      ram_addr, max_clock_cycles);\n    }\n\n    return max_clock_cycles;\n}\n\nstatic int\nramulator_get_max_clock_cycles(Dram *d, PendingMemAccessEntry *e)\n{\n    int max_clock_cycles = 0;\n    target_ulong ram_addr = get_tinyemu_ram_addr_from_zero(e->addr);\n\n    max_clock_cycles = ramulator_wrapper_get_max_clock_cycles(e);\n\n    if (max_clock_cycles >= 1000)\n    {\n        sim_log_event(\n            sim_log, \"possible ramulator block detected, callback for physical \"\n                     \"addr 0x% \" TARGET_ULONG_HEX \" received after %d cycle(s)\",\n            ram_addr, max_clock_cycles);\n    }\n\n    return max_clock_cycles;\n}\n\nstatic void\nread_complete_callback(target_ulong addr, StageMemAccessQueue *f,\n                       StageMemAccessQueue *b)\n{\n    int i;\n\n    for (i = 0; i < f->cur_idx; ++i)\n    {\n        if ((f->entry[i].valid) && (f->entry[i].addr == addr)\n            && (f->entry[i].type == MEM_ACCESS_READ))\n        {\n            f->entry[i].valid = FALSE;\n            --f->cur_size;\n            return;\n        }\n    }\n\n    for (i = 0; i < b->cur_idx; ++i)\n    {\n        if ((b->entry[i].valid) && (b->entry[i].addr == addr)\n            && (b->entry[i].type == MEM_ACCESS_READ))\n        {\n            b->entry[i].valid = FALSE;\n            --b->cur_size;\n            return;\n        }\n    }\n}\n\nstatic void\nwrite_complete_callback(target_ulong addr, StageMemAccessQueue *f,\n                        StageMemAccessQueue *b)\n{\n    int i;\n\n    for (i = 0; i < f->cur_idx; ++i)\n    {\n        if ((f->entry[i].valid) && (f->entry[i].addr == addr)\n            && (f->entry[i].type == MEM_ACCESS_WRITE))\n        {\n            f->entry[i].valid = FALSE;\n            --f->cur_size;\n            return;\n        }\n    }\n\n    for (i = 0; i < b->cur_idx; ++i)\n    {\n        if ((b->entry[i].valid) && (b->entry[i].addr == addr)\n            && (b->entry[i].type == MEM_ACCESS_WRITE))\n        {\n            b->entry[i].valid = FALSE;\n            --b->cur_size;\n            return;\n        }\n    }\n}\n\nint\ndram_can_accept_request(const Dram *d)\n{\n    return !d->mem_access_active;\n}\n\nvoid\ndram_send_request(Dram *d, PendingMemAccessEntry *e)\n{\n    d->max_clock_cycles = d->get_max_clock_cycles_for_request(d, e);\n    assert(d->max_clock_cycles);\n\n    /* To model latency between LLC and Memory controller */\n    if (e->type == MEM_ACCESS_READ)\n    {\n        d->max_clock_cycles += (2 * LLC_TO_MEM_CONTROLLER_DELAY);\n    }\n    else if (e->type == MEM_ACCESS_WRITE)\n    {\n        /* One way delay LLC - Memory Controller */\n        d->max_clock_cycles += LLC_TO_MEM_CONTROLLER_DELAY;\n    }\n\n    /* Send a write complete callback to the calling pipeline stage as\n     * we don't want the pipeline stage to wait for write to complete.\n     * But, simulate this write delay asynchronously via the memory\n     * controller */\n    if (e->type == MEM_ACCESS_WRITE)\n    {\n        write_complete_callback(e->addr, d->frontend_mem_access_queue,\n                                d->backend_mem_access_queue);\n    }\n\n    d->active_mem_request = e;\n    d->mem_access_active = TRUE;\n    d->elasped_clock_cycles = 1;\n}\n\nint\ndram_clock(Dram *d)\n{\n    if (d->mem_access_active)\n    {\n        if (d->elasped_clock_cycles == d->max_clock_cycles)\n        {\n            d->mem_access_active = FALSE;\n            d->max_clock_cycles = 0;\n            d->elasped_clock_cycles = 0;\n\n            if (d->active_mem_request->type == MEM_ACCESS_READ)\n            {\n                read_complete_callback(d->active_mem_request->addr,\n                                       d->frontend_mem_access_queue,\n                                       d->backend_mem_access_queue);\n            }\n\n            d->active_mem_request->valid = FALSE;\n            return TRUE;\n        }\n        else\n        {\n            d->elasped_clock_cycles++;\n        }\n    }\n\n    return FALSE;\n}\n\nvoid\ndram_reset(Dram *d)\n{\n    d->elasped_clock_cycles = 0;\n    d->max_clock_cycles = 0;\n    d->mem_access_active = FALSE;\n    d->active_mem_request = NULL;\n\n    /* For base DRAM model */\n    d->last_accessed_page_num = 0;\n}\n\nDram *\ndram_create(const SimParams *p, StageMemAccessQueue *f,\n                 StageMemAccessQueue *b)\n{\n    Dram *d;\n\n    d = calloc(1, sizeof(Dram));\n    assert(d);\n\n    d->mem_access_latency = p->mem_access_latency;\n    d->frontend_mem_access_queue = f;\n    d->backend_mem_access_queue = b;\n\n    d->dram_model_type = p->dram_model_type;\n\n    switch (d->dram_model_type)\n    {\n        case MEM_MODEL_BASE:\n        {\n            d->get_max_clock_cycles_for_request\n                = &base_dram_model_get_max_clock_cycles;\n            break;\n        }\n        case MEM_MODEL_DRAMSIM:\n        {\n            dramsim_wrapper_init(p->dramsim_config_file, p->sim_file_path);\n            d->get_max_clock_cycles_for_request = &dramsim_get_max_clock_cycles;\n            break;\n        }\n        case MEM_MODEL_RAMULATOR:\n        {\n            ramulator_wrapper_init(p->ramulator_config_file,\n                                   p->cache_line_size);\n            d->get_max_clock_cycles_for_request\n                = &ramulator_get_max_clock_cycles;\n            break;\n        }\n    }\n\n    dram_reset(d);\n    dram_log_config(d, p);\n    return d;\n}\n\nvoid\ndram_free(Dram **d)\n{\n    switch ((*d)->dram_model_type)\n    {\n        case MEM_MODEL_BASE:\n        {\n            break;\n        }\n        case MEM_MODEL_DRAMSIM:\n        {\n            dramsim_wrapper_destroy();\n            break;\n        }\n        case MEM_MODEL_RAMULATOR:\n        {\n            ramulator_wrapper_destroy();\n            break;\n        }\n    }\n    free(*d);\n}\n"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/dram.h",
    "content": "/**\n * DRAM model\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _BASE_DRAM_H_\n#define _BASE_DRAM_H_\n\n#include \"../../cutils.h\"\n#include \"../riscv_sim_typedefs.h\"\n#include \"../utils/sim_params.h\"\n#include \"memory_controller_utils.h\"\n\ntypedef struct Dram\n{\n    /* Type of DRAM model: base or dramsim3 */\n    int dram_model_type;\n\n    /* Requests are processed sequentially, one at a time, from the head of\n     * mem_req_queue. Processing solely involves simulating a latency in CPU\n     * cycles (known as max_clock_cycles). After simulating the latency, the\n     * stall on the waiting CPU pipeline stage is removed, and the current entry\n     * is dequeued from mem_req_queue. Below parameters keep track of the\n     * current request in progress. */\n    int mem_access_active;\n    int elasped_clock_cycles;\n    int max_clock_cycles;\n    PendingMemAccessEntry *active_mem_request;\n\n    /* These queues are used to control the stall on fetch and memory CPU\n     * pipeline stages */\n    StageMemAccessQueue *frontend_mem_access_queue;\n    StageMemAccessQueue *backend_mem_access_queue;\n\n    /* Set based on type of DRAM model used: base or dramsim */\n    int (*get_max_clock_cycles_for_request)(struct Dram *d,\n                                            PendingMemAccessEntry *e);\n\n    /* Following parameters are used by base DRAM model */\n    uint64_t last_accessed_page_num;\n\n    /* Fixed configurable latency in CPU cycles used by the base DRAM model */\n    int mem_access_latency;\n} Dram;\n\nDram *dram_create(const SimParams *p, StageMemAccessQueue *f,\n                  StageMemAccessQueue *b);\nint dram_can_accept_request(const Dram *d);\nint dram_clock(Dram *d);\nvoid dram_reset(Dram *d);\nvoid dram_send_request(Dram *d, PendingMemAccessEntry *e);\nvoid dram_free(Dram **d);\n#endif /* _BASE_DRAM_H_ */\n"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/dramsim_wrapper.cpp",
    "content": "/**\n * DRAMSim3 CPP wrapper\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <cstdio>\n#include <string>\n\n#include \"../../cutils.h\"\n#include \"dramsim_wrapper.h\"\n\ndramsim_wrapper::dramsim_wrapper(const char *config_file,\n                                 const char *output_dir)\n    : read_cb(std::bind(&dramsim_wrapper::read_complete, this,\n                        std::placeholders::_1)),\n      write_cb(std::bind(&dramsim_wrapper::write_complete, this,\n                         std::placeholders::_1))\n{\n    dramsim = GetMemorySystem(std::string(config_file), std::string(output_dir),\n                              read_cb, write_cb);\n}\n\ndramsim_wrapper::~dramsim_wrapper()\n{\n    delete dramsim;\n}\n\nvoid\ndramsim_wrapper::read_complete(uint64_t addr)\n{\n    auto it = mem_addr_cb_status.find(addr);\n    assert(it != mem_addr_cb_status.end());\n    it->second = true;\n}\n\nvoid\ndramsim_wrapper::write_complete(uint64_t addr)\n{\n    auto it = mem_addr_cb_status.find(addr);\n    assert(it != mem_addr_cb_status.end());\n    it->second = true;\n}\n\nbool\ndramsim_wrapper::access_complete()\n{\n    auto it = mem_addr_cb_status.begin();\n\n    while (it != mem_addr_cb_status.end())\n    {\n        if (it->second == false)\n        {\n            return false;\n        }\n        it++;\n    }\n\n    return true;\n}\n\nbool\ndramsim_wrapper::can_add_transaction(target_ulong addr, bool isWrite)\n{\n    return dramsim->WillAcceptTransaction(addr, isWrite);\n}\n\nbool\ndramsim_wrapper::add_transaction(target_ulong addr, bool isWrite)\n{\n    return dramsim->AddTransaction(addr, isWrite);\n}\n\nint\ndramsim_wrapper::get_max_clock_cycles(PendingMemAccessEntry *e)\n{\n    int bytes_accessed = 0;\n    int clock_cycles_elasped = 0;\n    target_ulong addr;\n\n    mem_addr_cb_status.clear();\n\n    /* Split the entire request size into MEM_BUS_WIDTH sized parts, and query\n     * latency for each of the part separately */\n    while (bytes_accessed < e->access_size_bytes)\n    {\n        addr = e->addr + bytes_accessed;\n        mem_addr_cb_status.insert(std::pair<target_ulong, bool>(addr, false));\n        assert(add_transaction(addr, (bool)e->type));\n        bytes_accessed += MEM_BUS_WIDTH;\n    }\n\n    while (!access_complete())\n    {\n        dramsim->ClockTick();\n        clock_cycles_elasped++;\n    }\n\n    return clock_cycles_elasped;\n}\n\nvoid\ndramsim_wrapper::print_stats(const char *timestamp)\n{\n    dramsim->PrintStats(timestamp);\n}\n\nvoid\ndramsim_wrapper::reset_stats()\n{\n    dramsim->ResetStats();\n}\n\nint\ndramsim_wrapper::get_burst_size()\n{\n    return (dramsim->GetBusBits() * (dramsim->GetBurstLength() / 8));\n}"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/dramsim_wrapper.h",
    "content": "/**\n * DRAMSim3 CPP wrapper\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _DRAMSIM_WRAPPER_H_\n#define _DRAMSIM_WRAPPER_H_\n\n#include <cstdint>\n#include <functional>\n#include <map>\n\n#include \"../riscv_sim_typedefs.h\"\n#include \"memory_controller_utils.h\"\n#include <memory_system.h>\n\nusing namespace dramsim3;\n\nclass dramsim_wrapper\n{\n  public:\n    dramsim_wrapper();\n    dramsim_wrapper(const char *config_file, const char *output_dir);\n    ~dramsim_wrapper();\n    bool can_add_transaction(target_ulong addr, bool isWrite);\n    bool add_transaction(target_ulong addr, bool isWrite);\n    int get_max_clock_cycles(PendingMemAccessEntry *e);\n    void reset_stats();\n    void print_stats(const char* timestamp);\n    int get_burst_size();\n    void read_complete(uint64_t);\n    void write_complete(uint64_t);\n    bool access_complete();\n\n    /* We split the cache-line address into MEM_BUS_WIDTH sized parts, so this map\n     * keeps track of callbacks for each of this part */\n    std::map<target_ulong, bool> mem_addr_cb_status;\n\n    MemorySystem *dramsim;\n    std::function<void(uint64_t)> read_cb;\n    std::function<void(uint64_t)> write_cb;\n};\n#endif\n"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/dramsim_wrapper_c_connector.cpp",
    "content": "/**\n * DRAMSim3 wrapper C connector\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <cstdlib>\n\n#include \"dramsim_wrapper.h\"\n#include \"dramsim_wrapper_c_connector.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nstatic dramsim_wrapper *dramsim_wrapper_obj = NULL;\n\nvoid\ndramsim_wrapper_init(const char *config_file, const char *output_dir)\n{\n    if (dramsim_wrapper_obj == NULL)\n    {\n        dramsim_wrapper_obj = new dramsim_wrapper(config_file, output_dir);\n    }\n}\n\nvoid\ndramsim_wrapper_destroy()\n{\n    delete dramsim_wrapper_obj;\n    dramsim_wrapper_obj = NULL;\n}\n\nint\ndramsim_wrapper_can_add_transaction(target_ulong addr, int isWrite)\n{\n    return dramsim_wrapper_obj->can_add_transaction(addr, (bool)isWrite);\n}\n\nint\ndramsim_wrapper_add_transaction(target_ulong addr, int isWrite)\n{\n    return dramsim_wrapper_obj->add_transaction(addr, (bool)isWrite);\n}\n\nint\ndramsim_wrapper_get_max_clock_cycles(PendingMemAccessEntry *e)\n{\n    return dramsim_wrapper_obj->get_max_clock_cycles(e);\n}\n\nvoid\ndramsim_wrapper_print_stats(const char* timestamp)\n{\n    dramsim_wrapper_obj->print_stats(timestamp);\n}\n\nvoid\ndramsim_wrapper_reset_stats()\n{\n    dramsim_wrapper_obj->reset_stats();\n}\n\nint\ndramsim_get_burst_size()\n{\n    return dramsim_wrapper_obj->get_burst_size();\n}\n\n#ifdef __cplusplus\n}\n#endif"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/dramsim_wrapper_c_connector.h",
    "content": "/**\n * DRAMSim3 wrapper C connector\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _DRAMSIM_WRAPPER_C_CONNECTOR_H_\n#define _DRAMSIM_WRAPPER_C_CONNECTOR_H_\n\n#include <inttypes.h>\n\n#include \"../riscv_sim_typedefs.h\"\n#include \"memory_controller_utils.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nvoid dramsim_wrapper_init(const char *config_file, const char *output_dir);\nvoid dramsim_wrapper_destroy();\nint dramsim_wrapper_can_add_transaction(target_ulong addr, int isWrite);\nint dramsim_wrapper_add_transaction(target_ulong addr, int isWrite);\nint dramsim_wrapper_get_max_clock_cycles(PendingMemAccessEntry *e);\nvoid dramsim_wrapper_print_stats(const char *timestamp);\nvoid dramsim_wrapper_reset_stats();\nint dramsim_get_burst_size();\n\n#ifdef __cplusplus\n}\n#endif\n#endif"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/memory_controller.c",
    "content": "/**\n * Memory Controller\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../utils/circular_queue.h\"\n#include \"../utils/sim_log.h\"\n#include \"dramsim_wrapper_c_connector.h\"\n#include \"memory_controller.h\"\n\nstatic void\nmem_controller_log_config(const MemoryController *m)\n{\n    sim_log_event_to_file(sim_log, \"%s\", \"Setting up memory controller\");\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"burst_length\", m->burst_length);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"fetch_cpu_stage_queue_size\", FRONTEND_MEM_ACCESS_QUEUE_SIZE);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"mem_cpu_stage_queue_size\", BACKEND_MEM_ACCESS_QUEUE_SIZE);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"global_mem_request_queue_size\", MEM_REQUEST_QUEUE_SIZE);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"dram_model_type\", dram_model_type_str[m->dram_model_type]);\n}\n\nvoid\nmem_controller_reset(MemoryController *m)\n{\n    /* Invalidate the entries added to mem_request_queue on the speculated path */\n    mem_controller_invalidate_mem_request_queue_entries(\n        m, &m->frontend_mem_access_queue);\n    mem_controller_invalidate_mem_request_queue_entries(\n        m, &m->backend_mem_access_queue);\n    mem_controller_reset_cpu_stage_queue(&m->frontend_mem_access_queue);\n    mem_controller_reset_cpu_stage_queue(&m->backend_mem_access_queue);\n    mem_controller_reset_mem_request_queue(m);\n    dram_reset(m->dram);\n}\n\nvoid\nmem_controller_set_burst_length(MemoryController *m, int burst_length)\n{\n    m->burst_length = burst_length;\n}\n\nvoid\nmem_controller_reset_cpu_stage_queue(StageMemAccessQueue *q)\n{\n    q->cur_idx = 0;\n    q->cur_size = 0;\n}\n\nvoid\nmem_controller_reset_mem_request_queue(MemoryController *m)\n{\n    cq_reset(&m->mem_request_queue.cq);\n}\n\nstatic void\nfill_memory_request_entry(MemoryController *m, PendingMemAccessEntry *e, target_ulong paddr,\n                          MemAccessType type, int is_pte)\n{\n    e->addr = paddr;\n    e->type = type;\n    e->req_pte = is_pte;\n    e->valid = TRUE;\n    e->access_size_bytes = m->burst_length;\n\n    /* Don't start simulating DRAM access delay until cache lookup delay is\n     * simulated */\n    e->start_access = FALSE;\n}\n\nint\nmem_controller_create_mem_request(MemoryController *m, target_ulong paddr,\n                                  int bytes_to_access, MemAccessType type,\n                                  void *p_mem_access_info)\n{\n    target_ulong start_offset;\n    int index, source_cpu_stage_id;\n\n    source_cpu_stage_id = *(int *)p_mem_access_info;\n\n    /*  Align the address for this access to the burst_length */\n    start_offset = paddr % m->burst_length;\n    if (0 != start_offset)\n    {\n        bytes_to_access += start_offset;\n        paddr -= start_offset;\n    }\n\n    while (bytes_to_access > 0)\n    {\n        switch (source_cpu_stage_id)\n        {\n            case FETCH:\n            {\n                fill_memory_request_entry(\n                    m, &m->frontend_mem_access_queue\n                            .entry[m->frontend_mem_access_queue.cur_idx],\n                    paddr, type, FALSE);\n                ++m->frontend_mem_access_queue.cur_idx;\n                ++m->frontend_mem_access_queue.cur_size;\n                break;\n            }\n            case MEMORY:\n            {\n                fill_memory_request_entry(\n                    m, &m->backend_mem_access_queue\n                            .entry[m->backend_mem_access_queue.cur_idx],\n                    paddr, type, FALSE);\n                ++m->backend_mem_access_queue.cur_idx;\n                ++m->backend_mem_access_queue.cur_size;\n                break;\n            }\n            default:\n            {\n                sim_assert(\n                    (0), \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n                    __func__,\n                    \"memory access generated by incorrect pipeline stage\");\n            }\n        }\n\n        /* Add requests to the mem_request_queue */\n        index = cq_enqueue(&m->mem_request_queue.cq);\n\n        sim_assert((index != -1), \"error: %s at line %d in %s(): %s\", __FILE__,\n                   __LINE__, __func__, \"memory request queue is full\");\n\n        fill_memory_request_entry(m, &m->mem_request_queue.entry[index], paddr,\n                                  type, FALSE);\n\n        /* Calculate remaining transactions for this access */\n        bytes_to_access -= m->burst_length;\n        paddr += m->burst_length;\n    }\n\n    return 0;\n}\n\nvoid\nmem_controller_clock(MemoryController *m)\n{\n    PendingMemAccessEntry *e;\n\n    if (dram_can_accept_request(m->dram))\n    {\n        if (!cq_empty(&m->mem_request_queue.cq))\n        {\n            e = &m->mem_request_queue.entry[cq_front(&m->mem_request_queue.cq)];\n            if (e->valid)\n            {\n                if (e->start_access)\n                {\n                    dram_send_request(m->dram, e);\n                }\n            }\n            else\n            {\n                /* This entry was on miss speculated path, so it was flushed by\n                 * the CPU pipeline stage */\n                cq_dequeue(&m->mem_request_queue.cq);\n            }\n        }\n    }\n\n    if (dram_clock(m->dram))\n    {\n        cq_dequeue(&m->mem_request_queue.cq);\n    }\n}\n\nMemoryController *\nmem_controller_init(const SimParams *p)\n{\n    MemoryController *m;\n\n    m = (MemoryController *)calloc(1, sizeof(MemoryController));\n    assert(m);\n    m->burst_length = p->burst_length;\n    m->dram_model_type = p->dram_model_type;\n\n    m->frontend_mem_access_queue.max_size = FRONTEND_MEM_ACCESS_QUEUE_SIZE;\n    m->frontend_mem_access_queue.entry = (PendingMemAccessEntry *)calloc(\n        m->frontend_mem_access_queue.max_size, sizeof(PendingMemAccessEntry));\n    assert(m->frontend_mem_access_queue.entry);\n\n    m->backend_mem_access_queue.max_size = BACKEND_MEM_ACCESS_QUEUE_SIZE;\n    m->backend_mem_access_queue.entry = (PendingMemAccessEntry *)calloc(\n        m->backend_mem_access_queue.max_size, sizeof(PendingMemAccessEntry));\n    assert(m->backend_mem_access_queue.entry);\n\n    cq_init(&m->mem_request_queue.cq, MEM_REQUEST_QUEUE_SIZE);\n    memset((void *)m->mem_request_queue.entry, 0,\n           sizeof(PendingMemAccessEntry) * MEM_REQUEST_QUEUE_SIZE);\n\n    m->dram = dram_create(p, &m->frontend_mem_access_queue,\n                          &m->backend_mem_access_queue);\n\n    switch (m->dram_model_type)\n    {\n        case MEM_MODEL_BASE:\n        {\n            mem_controller_set_burst_length(m, p->burst_length);\n            break;\n        }\n        case MEM_MODEL_DRAMSIM:\n        {\n            mem_controller_set_burst_length(m, dramsim_get_burst_size());\n            break;\n        }\n        case MEM_MODEL_RAMULATOR:\n        {\n            mem_controller_set_burst_length(m, p->burst_length);\n            break;\n        }\n        default:\n        {\n            sim_assert((0), \"error: %s at line %d in %s(): %s\", __FILE__,\n                       __LINE__, __func__, \"invalid memory model\");\n        }\n    }\n    mem_controller_log_config(m);\n    return m;\n}\n\nvoid\nmem_controller_free(MemoryController **m)\n{\n    dram_free(&(*m)->dram);\n    free((*m)->backend_mem_access_queue.entry);\n    (*m)->backend_mem_access_queue.entry = NULL;\n    free((*m)->frontend_mem_access_queue.entry);\n    (*m)->frontend_mem_access_queue.entry = NULL;\n    free(*m);\n    *m = NULL;\n}\n\nvoid\nmem_controller_cache_lookup_complete_signal(MemoryController *m,\n                                            StageMemAccessQueue *stage_queue)\n{\n    int i, j;\n    target_ulong addr;\n\n    for (j = 0; j < stage_queue->cur_idx; ++j)\n    {\n        addr = stage_queue->entry[j].addr;\n\n        if (!cq_empty(&m->mem_request_queue.cq))\n        {\n            if (m->mem_request_queue.cq.rear >= m->mem_request_queue.cq.front)\n            {\n                for (i = m->mem_request_queue.cq.front;\n                     i <= m->mem_request_queue.cq.rear; i++)\n                {\n                    if (m->mem_request_queue.entry[i].addr == addr)\n                    {\n                        m->mem_request_queue.entry[i].start_access = TRUE;\n                    }\n                }\n            }\n            else\n            {\n                for (i = m->mem_request_queue.cq.front;\n                     i < m->mem_request_queue.cq.max_size; i++)\n                {\n                    if (m->mem_request_queue.entry[i].addr == addr)\n                    {\n                        m->mem_request_queue.entry[i].start_access = TRUE;\n                    }\n                }\n\n                for (i = 0; i <= m->mem_request_queue.cq.rear; i++)\n                {\n                    if (m->mem_request_queue.entry[i].addr == addr)\n                    {\n                        m->mem_request_queue.entry[i].start_access = TRUE;\n                    }\n                }\n            }\n        }\n    }\n}\n\nvoid\nmem_controller_invalidate_mem_request_queue_entries(\n    MemoryController *m, StageMemAccessQueue *stage_queue)\n{\n    int i, j;\n    target_ulong addr;\n\n    for (j = 0; j < stage_queue->cur_idx; ++j)\n    {\n        addr = stage_queue->entry[j].addr;\n\n        if (!cq_empty(&m->mem_request_queue.cq))\n        {\n            if (m->mem_request_queue.cq.rear >= m->mem_request_queue.cq.front)\n            {\n                for (i = m->mem_request_queue.cq.front;\n                     i <= m->mem_request_queue.cq.rear; i++)\n                {\n                    if (m->mem_request_queue.entry[i].addr == addr)\n                    {\n                        m->mem_request_queue.entry[i].valid = FALSE;\n                    }\n                }\n            }\n            else\n            {\n                for (i = m->mem_request_queue.cq.front;\n                     i < m->mem_request_queue.cq.max_size; i++)\n                {\n                    if (m->mem_request_queue.entry[i].addr == addr)\n                    {\n                        m->mem_request_queue.entry[i].valid = FALSE;\n                    }\n                }\n\n                for (i = 0; i <= m->mem_request_queue.cq.rear; i++)\n                {\n                    if (m->mem_request_queue.entry[i].addr == addr)\n                    {\n                        m->mem_request_queue.entry[i].valid = FALSE;\n                    }\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/memory_controller.h",
    "content": "/**\n * Memory Controller\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _MEMORY_CONTROLLER_H_\n#define _MEMORY_CONTROLLER_H_\n\n#include <math.h>\n\n#include \"../../cutils.h\"\n#include \"../riscv_sim_typedefs.h\"\n#include \"../utils/circular_queue.h\"\n#include \"../utils/sim_params.h\"\n#include \"dram.h\"\n#include \"memory_controller_utils.h\"\n\n#define FRONTEND_MEM_ACCESS_QUEUE_SIZE 64\n#define BACKEND_MEM_ACCESS_QUEUE_SIZE 64\n#define MEM_REQUEST_QUEUE_SIZE 64\n\ntypedef struct MemRequestQueue\n{\n    CQ cq;\n    PendingMemAccessEntry entry[MEM_REQUEST_QUEUE_SIZE];\n} MemRequestQueue;\n\ntypedef struct MemoryController\n{\n    /* Type of DRAM model: base or dramsim3 */\n    int dram_model_type;\n\n    /* Memory controller burst length in bytes (or cache line size) */\n    int burst_length;\n\n    /* These queues are used to control the stall on fetch and memory CPU\n     * pipeline stages */\n    StageMemAccessQueue frontend_mem_access_queue;\n    StageMemAccessQueue backend_mem_access_queue;\n\n    /* A single FIFO queue known as mem_request_queue comprising all the pending\n     * memory access requests */\n    MemRequestQueue mem_request_queue;\n\n    /* To keep track of cache lookup cycle(s) for reading/writing page table\n     * entries during hardware page walk */\n    int page_walk_delay;\n    Dram *dram;\n} MemoryController;\n\nMemoryController *mem_controller_init(const SimParams *p);\nvoid mem_controller_free(MemoryController **m);\nvoid mem_controller_reset(MemoryController *m);\nvoid mem_controller_clock(MemoryController *m);\nvoid mem_controller_reset_cpu_stage_queue(StageMemAccessQueue *q);\nvoid mem_controller_reset_mem_request_queue(MemoryController *m);\nvoid mem_controller_set_burst_length(MemoryController *m, int burst_length);\nint mem_controller_create_mem_request(MemoryController *m, target_ulong paddr,\n                                      int bytes_to_access,\n                                      MemAccessType op_type,\n                                      void *p_mem_access_info);\nvoid mem_controller_cache_lookup_complete_signal(MemoryController *m,\n                                            StageMemAccessQueue *stage_queue);\nvoid mem_controller_invalidate_mem_request_queue_entries(\n    MemoryController *m, StageMemAccessQueue *stage_queue);\n#endif\n"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/memory_controller_utils.h",
    "content": "/**\n * Memory controller utilities\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _MEM_CONTROLLER_UTILS_H_\n#define _MEM_CONTROLLER_UTILS_H_\n\n#include \"../riscv_sim_typedefs.h\"\n\n#define MEM_BUS_WIDTH 8               /* bytes */\n#define LLC_TO_MEM_CONTROLLER_DELAY 3 /* cycles, one-way delay */\n\n/* Memory operation type */\ntypedef enum MemAccessType {\n    MEM_ACCESS_READ = 0x0,\n    MEM_ACCESS_WRITE = 0x1,\n} MemAccessType;\n\ntypedef struct PendingMemAccessEntry\n{\n    int valid;\n    int start_access;\n    int access_size_bytes;\n    target_ulong addr;\n    target_ulong req_addr;\n    target_ulong req_pte;\n    int stage_queue_index;\n    int stage_queue_type;\n    MemAccessType type;\n} PendingMemAccessEntry;\n\ntypedef struct StageMemAccessQueue\n{\n    int cur_idx;\n    int max_size;\n    int cur_size;\n    PendingMemAccessEntry *entry;\n} StageMemAccessQueue;\n#endif\n"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/memory_hierarchy.c",
    "content": "/**\n * Memory Hierarchy\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n#include \"dramsim_wrapper_c_connector.h\"\n#include \"memory_hierarchy.h\"\n\nstatic int\nmem_hierarchy_cache_disabled_read(MemoryHierarchy *mem_hierarchy,\n                                  target_ulong paddr, int bytes, int stage_id,\n                                  int priv)\n{\n    mem_controller_create_mem_request(mem_hierarchy->mem_controller, paddr,\n                                      bytes, MEM_ACCESS_READ,\n                                      (void *)&stage_id);\n    return 1;\n}\n\nstatic int\nmem_hierarchy_cache_disabled_write(MemoryHierarchy *mem_hierarchy,\n                                   target_ulong paddr, int bytes, int stage_id,\n                                   int priv)\n{\n    mem_controller_create_mem_request(mem_hierarchy->mem_controller, paddr,\n                                      bytes, MEM_ACCESS_WRITE,\n                                      (void *)&stage_id);\n    return 1;\n}\n\nstatic int\nmem_hierarchy_icache_read(MemoryHierarchy *mem_hierarchy, target_ulong paddr,\n                          int bytes, int stage_id, int priv)\n{\n    return cache_read(mem_hierarchy->icache, paddr, bytes, (void *)&stage_id,\n                      priv);\n}\n\nstatic int\nmem_hierarchy_dcache_read(MemoryHierarchy *mem_hierarchy, target_ulong paddr,\n                          int bytes, int stage_id, int priv)\n{\n    return cache_read(mem_hierarchy->dcache, paddr, bytes, (void *)&stage_id,\n                      priv);\n}\n\nstatic int\nmem_hierarchy_dcache_write(MemoryHierarchy *mem_hierarchy, target_ulong paddr,\n                           int bytes, int stage_id, int priv)\n{\n    return cache_write(mem_hierarchy->dcache, paddr, bytes, (void *)&stage_id,\n                       priv);\n}\n\nstatic int\nmem_hierarchy_pte_read_cache(MemoryHierarchy *mem_hierarchy,\n                              target_ulong paddr, int bytes, int stage_id,\n                              int priv)\n{\n    return cache_read(mem_hierarchy->page_walk_cache, paddr, bytes, (void *)&stage_id,\n                      priv);\n}\n\nstatic int\nmem_hierarchy_pte_write_cache(MemoryHierarchy *mem_hierarchy, target_ulong paddr,\n                        int bytes, int stage_id, int priv)\n{\n    return cache_write(mem_hierarchy->page_walk_cache, paddr, bytes, (void *)&stage_id,\n                       priv);\n}\n\nstatic void\nmem_hierarchy_set_page_walk_cache(MemoryHierarchy *m, const SimParams *p)\n{\n    m->page_walk_cache = NULL;\n    sim_log_event_to_file(sim_log, \"%s\",\n                          \"no caches found, setting page_walk_cache to NULL\");\n\n    if (p->enable_l1_caches)\n    {\n        /* If L1 caches are enabled, page walk is simulated via L1-data cache */\n        m->page_walk_cache = m->dcache;\n        sim_log_event_to_file(\n            sim_log, \"%s\",\n            \"found l1-data cache, setting page_walk_cache to dcache\");\n    }\n}\n\nMemoryHierarchy *\nmemory_hierarchy_init(const SimParams *p, SimLog *log)\n{\n    int words_per_cache_line;\n    MemoryHierarchy *mem_hierarchy;\n\n    mem_hierarchy = (MemoryHierarchy *)calloc(1, sizeof(MemoryHierarchy));\n    assert(mem_hierarchy);\n    mem_hierarchy->p = (SimParams *)p;\n\n    /* Setup memory controller */\n    mem_hierarchy->mem_controller = mem_controller_init(p);\n\n    /* Setup caches */\n    if (p->enable_l1_caches)\n    {\n        words_per_cache_line = p->cache_line_size /  sizeof(target_ulong);\n        mem_hierarchy->cache_line_size = p->cache_line_size;\n\n        /* If caches are enabled, set burst length to cache line size */\n        mem_controller_set_burst_length(mem_hierarchy->mem_controller,\n                                        mem_hierarchy->cache_line_size);\n\n        /* If DRAMSim3 memory model is used, its burst length must be equal to\n         * cache line size */\n        if (mem_hierarchy->mem_controller->dram_model_type == MEM_MODEL_DRAMSIM)\n        {\n            sim_assert((mem_hierarchy->mem_controller->burst_length\n                        == dramsim_get_burst_size()),\n                       \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n                       __func__, \"DRAMSim3 burst length must be equal to \"\n                                 \"MARSS-RISCV cache line size or CPU memory \"\n                                 \"controller burst length\");\n        }\n\n        if (p->enable_l2_cache)\n        {\n            sim_log_event_to_file(log, \"%s\", \"Setting up L2-cache\");\n            mem_hierarchy->l2_cache = cache_init(\n                SharedCache, L2, p->l2_shared_cache_size,\n                mem_hierarchy->cache_line_size, p->l2_shared_cache_ways,\n                p->l2_shared_cache_read_latency,\n                p->l2_shared_cache_write_latency, NULL, words_per_cache_line,\n                p->l2_shared_cache_evict,\n                (CacheWritePolicy)p->cache_write_policy,\n                (CacheReadAllocPolicy)p->cache_read_allocate_policy,\n                (CacheWriteAllocPolicy)p->cache_write_allocate_policy,\n                mem_hierarchy->mem_controller);\n        }\n\n        sim_log_event_to_file(log, \"%s\", \"Setting up L1-instruction cache\");\n        mem_hierarchy->icache = cache_init(\n            InstructionCache, L1, p->l1_code_cache_size,\n            mem_hierarchy->cache_line_size, p->l1_code_cache_ways,\n            p->l1_code_cache_read_latency, 1, mem_hierarchy->l2_cache,\n            words_per_cache_line, p->l1_code_cache_evict,\n            (CacheWritePolicy)p->cache_write_policy,\n            (CacheReadAllocPolicy)p->cache_read_allocate_policy,\n            (CacheWriteAllocPolicy)p->cache_write_allocate_policy,\n            mem_hierarchy->mem_controller);\n\n        sim_log_event_to_file(log, \"%s\", \"Setting up L1-data cache\");\n        mem_hierarchy->dcache = cache_init(\n            DataCache, L1, p->l1_data_cache_size,\n            mem_hierarchy->cache_line_size, p->l1_data_cache_ways,\n            p->l1_data_cache_read_latency, p->l1_data_cache_write_latency,\n            mem_hierarchy->l2_cache, words_per_cache_line,\n            p->l1_data_cache_evict, (CacheWritePolicy)p->cache_write_policy,\n            (CacheReadAllocPolicy)p->cache_read_allocate_policy,\n            (CacheWriteAllocPolicy)p->cache_write_allocate_policy,\n            mem_hierarchy->mem_controller);\n    }\n\n    mem_hierarchy_set_page_walk_cache(mem_hierarchy, p);\n\n    if (mem_hierarchy->page_walk_cache)\n    {\n        mem_hierarchy->pte_read_delay = &mem_hierarchy_pte_read_cache;\n        mem_hierarchy->pte_write_delay = &mem_hierarchy_pte_write_cache;\n    }\n    else\n    {\n        mem_hierarchy->pte_read_delay = &mem_hierarchy_cache_disabled_read;\n        mem_hierarchy->pte_write_delay = &mem_hierarchy_cache_disabled_write;\n    }\n\n    if (p->enable_l1_caches)\n    {\n        mem_hierarchy->insn_read_delay = &mem_hierarchy_icache_read;\n        mem_hierarchy->data_read_delay = &mem_hierarchy_dcache_read;\n        mem_hierarchy->data_write_delay = &mem_hierarchy_dcache_write;\n    }\n    else\n    {\n        mem_hierarchy->insn_read_delay = &mem_hierarchy_cache_disabled_read;\n        mem_hierarchy->data_read_delay = &mem_hierarchy_cache_disabled_read;\n        mem_hierarchy->data_write_delay = &mem_hierarchy_cache_disabled_write;\n    }\n\n    return mem_hierarchy;\n}\n\nvoid\nmemory_hierarchy_free(MemoryHierarchy **mem_hierarchy)\n{\n    if ((*mem_hierarchy)->p->enable_l1_caches)\n    {\n        if ((*mem_hierarchy)->l2_cache)\n        {\n            cache_free(&(*mem_hierarchy)->l2_cache);\n        }\n        cache_free(&(*mem_hierarchy)->dcache);\n        cache_free(&(*mem_hierarchy)->icache);\n    }\n\n    mem_controller_free(&(*mem_hierarchy)->mem_controller);\n\n    free(*mem_hierarchy);\n    *mem_hierarchy = NULL;\n}"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/memory_hierarchy.h",
    "content": "/**\n * Memory Hierarchy\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _MemoryHierarchy_H_\n#define _MemoryHierarchy_H_\n\n#include \"../riscv_sim_typedefs.h\"\n#include \"../utils/sim_log.h\"\n#include \"../utils/sim_params.h\"\n#include \"cache.h\"\n#include \"memory_controller.h\"\n\n/* Memory hierarchy to simulate the delays, We do not model the actual data\n * in the hierarchy for simplicity, but just the addresses for simulating\n * the delays.*/\ntypedef struct MemoryHierarchy\n{\n    MemoryController *mem_controller;\n    Cache *icache;\n    Cache *dcache;\n    Cache *l2_cache;\n    Cache *page_walk_cache;\n    SimParams *p;\n\n    /* If caches are enabled */\n    int cache_line_size;\n\n    /* Pointers are set based on whether caches are enabled or disabled */\n    int (*insn_read_delay)(struct MemoryHierarchy *mmu, target_ulong paddr,\n                           int bytes, int cpu_stage_id, int priv);\n    int (*data_read_delay)(struct MemoryHierarchy *mmu, target_ulong paddr,\n                           int bytes, int cpu_stage_id, int priv);\n    int (*data_write_delay)(struct MemoryHierarchy *mmu, target_ulong paddr,\n                            int bytes, int cpu_stage_id, int priv);\n\n    /* Page table entries read/write delays are simulated via Data Cache, if\n     * found, else directly sent to memory */\n    int (*pte_read_delay)(struct MemoryHierarchy *mmu, target_ulong paddr,\n                          int bytes, int cpu_stage_id, int priv);\n    int (*pte_write_delay)(struct MemoryHierarchy *mmu, target_ulong paddr,\n                               int bytes, int cpu_stage_id, int priv);\n} MemoryHierarchy;\n\nMemoryHierarchy *memory_hierarchy_init(const SimParams *p, SimLog *log);\nvoid memory_hierarchy_free(MemoryHierarchy **mmu);\n#endif\n"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/ramulator_wrapper.cpp",
    "content": "/**\n * Ramulator CPP wrapper\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"ramulator_wrapper.h\"\n#include \"memory_controller_utils.h\"\n\n#include <unistd.h>\n\nramulator_wrapper::ramulator_wrapper(const char *config_file,\n                                     int cache_line_size)\n    : read_cb_func(std::bind(&ramulator_wrapper::read_complete, this,\n                             std::placeholders::_1)),\n      write_cb_func(std::bind(&ramulator_wrapper::write_complete, this,\n                              std::placeholders::_1))\n\n{\n    Config configs(config_file);\n    configs.set_core_num(1);\n    gem5_wrapper = new Gem5Wrapper(configs, cache_line_size);\n}\n\nramulator_wrapper::~ramulator_wrapper()\n{\n    delete gem5_wrapper;\n}\n\nvoid\nramulator_wrapper::finish()\n{\n    gem5_wrapper->finish();\n}\n\nvoid\nramulator_wrapper::read_complete(ramulator::Request &req)\n{\n    auto it = mem_addr_cb_status.find(req.addr);\n    assert(it != mem_addr_cb_status.end());\n    it->second = true;\n}\n\nvoid\nramulator_wrapper::write_complete(ramulator::Request &req)\n{\n    auto it = mem_addr_cb_status.find(req.addr);\n    assert(it != mem_addr_cb_status.end());\n    it->second = true;\n}\n\nbool\nramulator_wrapper::access_complete()\n{\n    auto it = mem_addr_cb_status.begin();\n\n    while (it != mem_addr_cb_status.end())\n    {\n        if (it->second == false)\n        {\n            return false;\n        }\n        it++;\n    }\n\n    return true;\n}\n\nbool\nramulator_wrapper::add_transaction(target_ulong addr, bool isWrite)\n{\n    bool request_sent = false;\n\n    if (isWrite)\n    {\n        ramulator::Request req((long)addr, ramulator::Request::Type::WRITE,\n                               write_cb_func);\n        request_sent = gem5_wrapper->send(req);\n    }\n    else\n    {\n        ramulator::Request req(addr, ramulator::Request::Type::READ,\n                               read_cb_func);\n        request_sent = gem5_wrapper->send(req);\n    }\n\n    return request_sent;\n}\n\nint\nramulator_wrapper::get_max_clock_cycles(PendingMemAccessEntry *e)\n{\n    int bytes_accessed = 0;\n    int clock_cycles_elasped = 0;\n    target_ulong addr;\n\n    mem_addr_cb_status.clear();\n\n    /* Split the entire request size into MEM_BUS_WIDTH sized parts, and query\n     * latency for each of the part separately */\n    while (bytes_accessed < e->access_size_bytes)\n    {\n        addr = e->addr + bytes_accessed;\n        mem_addr_cb_status.insert(std::pair<target_ulong, bool>(addr, false));\n        assert(add_transaction(addr, (bool)e->type));\n        bytes_accessed += MEM_BUS_WIDTH;\n    }\n\n    while (!access_complete())\n    {\n        gem5_wrapper->tick();\n        clock_cycles_elasped++;\n    }\n\n    return clock_cycles_elasped;\n}\n\nvoid\nramulator_wrapper::print_stats(const char *stats_dir, const char *timestamp)\n{\n    gem5_wrapper->print_stats(stats_dir, timestamp);\n}\n"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/ramulator_wrapper.h",
    "content": "/**\n * Ramulator CPP wrapper\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _RAMULATOR_WRAPPER_H_\n#define _RAMULATOR_WRAPPER_H_\n\n#include \"../riscv_sim_typedefs.h\"\n#include \"memory_controller_utils.h\"\n\n#include <Gem5Wrapper.h>\n#include <Request.h>\n#include <map>\n\nusing namespace ramulator;\n\nclass ramulator_wrapper\n{\n  public:\n    ramulator_wrapper();\n    ramulator_wrapper(const char *config_file, int cache_line_size);\n    ~ramulator_wrapper();\n    bool add_transaction(target_ulong addr, bool isWrite);\n    int get_max_clock_cycles(PendingMemAccessEntry *e);\n    bool access_complete();\n    void write_complete(ramulator::Request &req);\n    void read_complete(ramulator::Request &req);\n    void finish();\n    void print_stats(const char *stats_dir, const char *timestamp);\n\n    /* We split the cache-line address into MEM_BUS_WIDTH sized parts, so this map\n     * keeps track of callbacks for each of this part */\n    std::map<target_ulong, bool> mem_addr_cb_status;\n\n    std::function<void(ramulator::Request &)> read_cb_func;\n    std::function<void(ramulator::Request &)> write_cb_func;\n    Gem5Wrapper *gem5_wrapper;\n};\n#endif"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/ramulator_wrapper_c_connector.cpp",
    "content": "/**\n * Ramulator wrapper C connector\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"ramulator_wrapper.h\"\n#include \"ramulator_wrapper_c_connector.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nstatic ramulator_wrapper *ramulator_wrapper_obj = NULL;\n\nvoid\nramulator_wrapper_init(const char *config_file, int cache_line_size)\n{\n    if (ramulator_wrapper_obj == NULL)\n    {\n        ramulator_wrapper_obj\n            = new ramulator_wrapper(config_file, cache_line_size);\n    }\n}\n\nvoid\nramulator_wrapper_destroy()\n{\n    delete ramulator_wrapper_obj;\n    ramulator_wrapper_obj = NULL;\n}\n\nvoid\nramulator_wrapper_finish()\n{\n    ramulator_wrapper_obj->finish();\n}\n\nint\nramulator_wrapper_add_transaction(target_ulong addr, int isWrite)\n{\n    return (int)ramulator_wrapper_obj->add_transaction(addr, (bool)isWrite);\n}\n\nint\nramulator_wrapper_get_max_clock_cycles(PendingMemAccessEntry *e)\n{\n    return ramulator_wrapper_obj->get_max_clock_cycles(e);\n}\n\nvoid\nramulator_wrapper_print_stats(const char *stats_dir, const char *timestamp)\n{\n    ramulator_wrapper_obj->print_stats(stats_dir, timestamp);\n}\n\n#ifdef __cplusplus\n}\n#endif"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/ramulator_wrapper_c_connector.h",
    "content": "/**\n * Ramulator wrapper C connector\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _RAMULATOR_WRAPPER_C_CONNECTOR_H_\n#define _RAMULATOR_WRAPPER_C_CONNECTOR_H_\n\n#include <inttypes.h>\n\n#include \"../riscv_sim_typedefs.h\"\n#include \"memory_controller_utils.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nvoid ramulator_wrapper_init(const char *config_file, int cache_line_size);\nvoid ramulator_wrapper_destroy();\nvoid ramulator_wrapper_finish();\nvoid ramulator_wrapper_print_stats(const char* stats_dir, const char* timestamp);\nint ramulator_wrapper_add_transaction(target_ulong addr, int isWrite);\nint ramulator_wrapper_get_max_clock_cycles(PendingMemAccessEntry *e);\n\n#ifdef __cplusplus\n}\n#endif\n#endif"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/temu_mem_map_wrapper.c",
    "content": "/**\n * TinyEMU memory map wrapper\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"temu_mem_map_wrapper.h\"\n#include \"../../riscv_cpu_priv.h\"\n\n#define MEMORY_OP_A(size)                                                      \\\n    {                                                                          \\\n        uint##size##_t rval;                                                   \\\n        target_ulong addr = e->ins.mem_addr;                                   \\\n        uint32_t funct3 = e->ins.binary >> 27;                                 \\\n        switch (funct3)                                                        \\\n        {                                                                      \\\n            case 2: /* lr.w */                                                 \\\n                if (target_read_u##size(s, &rval, addr))                       \\\n                    goto mmu_exception;                                        \\\n                val = (int##size##_t)rval;                                     \\\n                s->load_res = e->ins.mem_addr;                                 \\\n                break;                                                         \\\n            case 3: /* sc.w */                                                 \\\n                if (s->load_res == addr)                                       \\\n                {                                                              \\\n                    if (target_write_u##size(s, addr, e->ins.rs2_val))         \\\n                        goto mmu_exception;                                    \\\n                    val = 0;                                                   \\\n                }                                                              \\\n                else                                                           \\\n                {                                                              \\\n                    val = 1;                                                   \\\n                }                                                              \\\n                break;                                                         \\\n            case 1:    /* amiswap.w */                                         \\\n            case 0:    /* amoadd.w */                                          \\\n            case 4:    /* amoxor.w */                                          \\\n            case 0xc:  /* amoand.w */                                          \\\n            case 0x8:  /* amoor.w */                                           \\\n            case 0x10: /* amomin.w */                                          \\\n            case 0x14: /* amomax.w */                                          \\\n            case 0x18: /* amominu.w */                                         \\\n            case 0x1c: /* amomaxu.w */                                         \\\n                if (target_read_u##size(s, &rval, addr))                       \\\n                {                                                              \\\n                    goto mmu_exception;                                        \\\n                }                                                              \\\n                val = (int##size##_t)rval;                                     \\\n                val2 = e->ins.rs2_val;                                         \\\n                switch (funct3)                                                \\\n                {                                                              \\\n                    case 1: /* amiswap.w */                                    \\\n                        break;                                                 \\\n                    case 0: /* amoadd.w */                                     \\\n                        val2 = (int##size##_t)(val + val2);                    \\\n                        break;                                                 \\\n                    case 4: /* amoxor.w */                                     \\\n                        val2 = (int##size##_t)(val ^ val2);                    \\\n                        break;                                                 \\\n                    case 0xc: /* amoand.w */                                   \\\n                        val2 = (int##size##_t)(val & val2);                    \\\n                        break;                                                 \\\n                    case 0x8: /* amoor.w */                                    \\\n                        val2 = (int##size##_t)(val | val2);                    \\\n                        break;                                                 \\\n                    case 0x10: /* amomin.w */                                  \\\n                        if ((int##size##_t)val < (int##size##_t)val2)          \\\n                            val2 = (int##size##_t)val;                         \\\n                        break;                                                 \\\n                    case 0x14: /* amomax.w */                                  \\\n                        if ((int##size##_t)val > (int##size##_t)val2)          \\\n                            val2 = (int##size##_t)val;                         \\\n                        break;                                                 \\\n                    case 0x18: /* amominu.w */                                 \\\n                        if ((uint##size##_t)val < (uint##size##_t)val2)        \\\n                            val2 = (int##size##_t)val;                         \\\n                        break;                                                 \\\n                    case 0x1c: /* amomaxu.w */                                 \\\n                        if ((uint##size##_t)val > (uint##size##_t)val2)        \\\n                            val2 = (int##size##_t)val;                         \\\n                        break;                                                 \\\n                }                                                              \\\n                if (target_write_u##size(s, addr, val2))                       \\\n                {                                                              \\\n                    goto mmu_exception;                                        \\\n                }                                                              \\\n                break;                                                         \\\n        }                                                                      \\\n    }\n\nstatic int\ntemu_exec_atomic_insn(RISCVCPUState *s, InstructionLatch *e)\n{\n    target_ulong val = 0, val2 = 0;\n\n    switch (e->ins.funct3)\n    {\n        case 2:\n            MEMORY_OP_A(32);\n            break;\n#if BIT_SIZE >= 64\n        case 3:\n            MEMORY_OP_A(64);\n            break;\n#endif\n    }\n    e->ins.buffer = val;\n    return 0;\nmmu_exception:\n    return -1;\n}\n\nstatic int\ntemu_exec_load_store_insn(RISCVCPUState *s, InstructionLatch *e)\n{\n    target_ulong addr = e->ins.mem_addr;\n\n    /* TLB lookup in target_read/write functions will fill this variable with\n     * the guest data physical address for this memory access */\n    s->data_guest_paddr = 0;\n\n    if (e->ins.is_load)\n    {\n        switch (e->ins.bytes_to_rw)\n        {\n            case 1:\n            {\n                uint8_t rval;\n                if (target_read_u8(s, &rval, addr))\n                    goto mmu_exception;\n                if (e->ins.is_unsigned)\n                {\n                    e->ins.buffer = rval;\n                }\n                else\n                {\n                    e->ins.buffer = (int8_t)rval;\n                }\n                break;\n            }\n\n            case 2:\n            {\n                uint16_t rval;\n                if (target_read_u16(s, &rval, addr))\n                    goto mmu_exception;\n                if (e->ins.is_unsigned)\n                {\n                    e->ins.buffer = rval;\n                }\n                else\n                {\n                    e->ins.buffer = (int16_t)rval;\n                }\n                break;\n            }\n\n            case 4:\n            {\n                uint32_t rval;\n                if (target_read_u32(s, &rval, addr))\n                    goto mmu_exception;\n                if (e->ins.is_unsigned)\n                {\n                    e->ins.buffer = rval;\n                }\n                else\n                {\n                    e->ins.buffer = (int32_t)rval;\n                }\n                break;\n            }\n\n            case 8:\n            {\n                uint64_t rval;\n                if (target_read_u64(s, &rval, addr))\n                    goto mmu_exception;\n                if (e->ins.is_unsigned)\n                {\n                    e->ins.buffer = rval;\n                }\n                else\n                {\n                    e->ins.buffer = (int64_t)rval;\n                }\n                break;\n            }\n        }\n    }\n    else if (e->ins.is_store)\n    {\n        switch (e->ins.bytes_to_rw)\n        {\n            case 1:\n            {\n                if (target_write_u8(s, addr, e->ins.rs2_val))\n                    goto mmu_exception;\n                break;\n            }\n\n            case 2:\n            {\n                if (target_write_u16(s, addr, e->ins.rs2_val))\n                    goto mmu_exception;\n                break;\n            }\n\n            case 4:\n            {\n                if (target_write_u32(s, addr, e->ins.rs2_val))\n                    goto mmu_exception;\n                break;\n            }\n\n            case 8:\n            {\n                if (target_write_u64(s, addr, e->ins.rs2_val))\n                    goto mmu_exception;\n                break;\n            }\n        }\n    }\n    else if (e->ins.is_atomic)\n    {\n        if (temu_exec_atomic_insn(s, e))\n        {\n            goto mmu_exception;\n        }\n    }\n    return 0;\nmmu_exception:\n    return -1;\n}\n\nstatic int\ntemu_read_insn(RISCVCPUState *s, InstructionLatch *e)\n{\n    RISCVSIMCPUState *simcpu = s->simcpu;\n\n    if (unlikely(s->code_ptr >= s->code_end))\n    {\n        uint32_t tlb_idx;\n        uint16_t insn_high;\n        uint8_t *ptr;\n        target_ulong addr = simcpu->pc;\n\n        ++simcpu->stats[s->priv].code_tlb_lookups;\n\n        /* TLB Lookup */\n        tlb_idx = (addr >> PG_SHIFT) & (TLB_SIZE - 1);\n        if (likely(s->tlb_code[tlb_idx].vaddr == (addr & ~PG_MASK)))\n        {\n            /* TLB match */\n            ptr = (uint8_t *)(s->tlb_code[tlb_idx].mem_addend\n                              + (uintptr_t)addr);\n            ++simcpu->stats[s->priv].code_tlb_hits;\n        }\n        else\n        {\n            if (unlikely(target_read_insn_slow(s, &ptr, addr)))\n                goto mmu_exception;\n        }\n\n        s->code_ptr = ptr;\n        s->code_end = ptr + (PG_MASK - 1 - (addr & PG_MASK));\n        s->code_to_pc_addend = addr - (uintptr_t)s->code_ptr;\n\n        s->code_guest_paddr = s->tlb_code[tlb_idx].guest_paddr\n                              + (addr - s->tlb_code[tlb_idx].vaddr);\n\n        if (unlikely(s->code_ptr >= s->code_end))\n        {\n            /* Instruction is potentially half way between two pages ? */\n            e->ins.binary = *(uint16_t *)(s->code_ptr);\n            if ((e->ins.binary & 3) == 3)\n            {\n                /* Instruction is half way between two pages */\n                if (unlikely(target_read_insn_u16(s, &insn_high, addr + 2)))\n                    goto mmu_exception;\n                e->ins.binary |= insn_high << 16;\n            }\n        }\n        else\n        {\n            e->ins.binary = get_insn32(s->code_ptr);\n        }\n    }\n    else\n    {\n        /* Fast path */\n        e->ins.binary = get_insn32(s->code_ptr);\n    }\n    return 0;\nmmu_exception:\n    return -1;\n}\n\nTemuMemMapWrapper *\ntemu_mem_map_wrapper_init()\n{\n    TemuMemMapWrapper *t;\n\n    t = calloc(1, sizeof(TemuMemMapWrapper));\n    assert(t);\n\n    t->read_insn = &temu_read_insn;\n    t->exec_load_store_atomic = &temu_exec_load_store_insn;\n\n    return t;\n}\n\nvoid\ntemu_mem_map_wrapper_free(TemuMemMapWrapper **t)\n{\n    free(*t);\n    *t = NULL;\n}"
  },
  {
    "path": "src/riscvsim/memory_hierarchy/temu_mem_map_wrapper.h",
    "content": "/**\n * TinyEMU memory map wrapper\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _TEMU_MEM_MAP_WRAPPER_H_\n#define _TEMU_MEM_MAP_WRAPPER_H_\n\n#include \"../utils/cpu_latches.h\"\n\nstruct RISCVCPUState;\n\n/* Wrapper over TinyEMU memory map used by the simulator to fetch instructions\n * and read/write data (loads, stores and atomics) from the emulated guest\n * physical memory */\ntypedef struct TemuMemMapWrapper\n{\n    int (*read_insn)(struct RISCVCPUState *s, InstructionLatch *e);\n    int (*exec_load_store_atomic)(struct RISCVCPUState *s, InstructionLatch *e);\n} TemuMemMapWrapper;\n\nTemuMemMapWrapper *temu_mem_map_wrapper_init();\nvoid temu_mem_map_wrapper_free(TemuMemMapWrapper **t);\n#endif\n"
  },
  {
    "path": "src/riscvsim/riscv_sim_macros.h",
    "content": "/**\n * Global typedefs and macros used by MARSS-RISCV\n *\n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _RISCV_SIM_MACROS_H_\n#define _RISCV_SIM_MACROS_H_\n\n#define SIM_PROG_TITLE \"MARSS-RISCV: Micro-Architectural System Simulator for RISC-V\"\n\n/* Type of Functional Units */\n#define FU_ALU 0x0\n#define FU_MUL 0x1\n#define FU_DIV 0x2\n#define FU_FPU_ALU 0x3\n#define FU_FPU_FMA 0x4\n#define NUM_MAX_FU 5\n\n/* Type of Branch instructions */\n#define BRANCH_UNCOND 0x0\n#define BRANCH_COND 0x1\n#define BRANCH_FUNC_CALL 0x2\n#define BRANCH_FUNC_RET 0x3\n\n/* Extension C Quadrants */\n#define C_QUADRANT0 0\n#define C_QUADRANT1 1\n#define C_QUADRANT2 2\n\n/* Major Opcodes */\n#define OP_IMM_MASK 0x13\n#define OP_IMM_32_MASK 0x1b\n#define OP_MASK 0x33\n#define OP_MASK_32 0x3b\n#define LUI_MASK 0x37\n#define AUIPC_MASK 0x17\n#define JAL_MASK 0x6f\n#define JALR_MASK 0x67\n#define BRANCH_MASK 0x63\n#define LOAD_MASK 0x3\n#define STORE_MASK 0x23\n#define FENCE_MASK 0xf\n#define CSR_MASK 0x73\n#define ATOMIC_MASK 0x2F\n\n/* Floating Point Instructions */\n#define FLOAD_MASK 0x07\n#define FSTORE_MASK 0x27\n#define FMADD_MASK 0x43\n#define FMSUB_MASK 0x47\n#define FNMSUB_MASK 0x4B\n#define FNMADD_MASK 0x4F\n#define F_ARITHMETIC_MASK 0x53\n\n/* Used as stage IDs for in-order pipeline */\n#define PCGEN 0x0\n#define FETCH 0x1\n#define DECODE 0x2\n#define MEMORY 0x3\n#define COMMIT 0x4\n\n#define NUM_CPU_STAGES 5 /* Excluding the functional units which are allocated separately */\n#define NUM_INT_REG 32\n#define NUM_FP_REG 32\n#define NUM_FU 5 /* ALU, MUL, DIV, FP ALU, FP FMA */\n#define NUM_FWD_BUS 6 /* Total 6 forwarding buses, 5 for functional units  and 1 for memory stage */\n#define INCORE_EX_TO_MEM_QUEUE_SIZE 16\n#define SPEC_REG_STATE_ENTRY 128\n\n#define RISCV_INS_STR_MAX_LENGTH 64\n\n/* NOTE: Max size of instruction latch pool, must always be greater than ROB\n * size */\n#define INSN_LATCH_POOL_SIZE 128\n#define INSN_LATCH_FREE 0x0\n#define INSN_LATCH_ALLOCATED 0x1\n\n/* Used to check pipeline drain status in case of exception inside simulator */\n#define PIPELINE_NOT_DRAINED 0\n#define PIPELINE_DRAINED 1\n\n#define NUM_MAX_PRV_LEVELS 4\n\n/* Used for updating performance counters */\n\n#define NUM_MAX_INS_TYPES 21\n#define INS_TYPE_LOAD 0x0\n#define INS_TYPE_STORE 0x1\n#define INS_TYPE_ATOMIC 0x2\n#define INS_TYPE_SYSTEM 0x3\n#define INS_TYPE_ARITMETIC 0x4\n#define INS_TYPE_COND_BRANCH 0x5\n#define INS_TYPE_JAL 0x6\n#define INS_TYPE_JALR 0x7\n#define INS_TYPE_INT_MUL 0x8\n#define INS_TYPE_INT_DIV 0x9\n#define INS_TYPE_FP_LOAD 0xa\n#define INS_TYPE_FP_STORE 0xb\n#define INS_TYPE_FP_ADD 0xc\n#define INS_TYPE_FP_MUL 0xd\n#define INS_TYPE_FP_FMA 0xe\n#define INS_TYPE_FP_DIV_SQRT 0xf\n#define INS_TYPE_FP_MISC 0x10\n#define INS_TYPE_LOAD_BYTE 0x11\n#define INS_TYPE_LOAD_HALF_WORD 0x12\n#define INS_TYPE_LOAD_WORD 0x13\n#define INS_TYPE_LOAD_DOUBLE_WORD 0x14\n\n#define INS_CLASS_INT 0x11\n#define INS_CLASS_FP 0x12\n\n/* For Branch prediction unit */\n#define BPU_MISS 0x0\n#define BPU_HIT 0x1\n\n#define SET_BIT(x, bit) ((x) |= (1LL << (bit)))\n#define GET_BIT(x, bit) (((x) >> (bit)) & 1)\n#define BITMASK(x) ((1LL << (x))- 1LL)\n#define GET_NUM_BITS(x) ceil(log2((x)))\n\n#define GET_INDEX(x, bits) ((x) & BITMASK(bits))\n#define GET_SET_ADDR(pc, bits) (GET_INDEX((pc), (bits)))\n#define PRINT_INIT_MSG(str) fprintf(stderr, \" \\x1B[32m*\\x1B[0m \" str \"...\\n\")\n#define PRINT_PROG_TITLE_MSG(str) fprintf(stderr, \"\\x1B[32m\\x1B[0m \" str \"\\n\\n\")\n\n/* For exception handling during simulation */\n#define SIM_ILLEGAL_OPCODE_EXCEPTION 0x1\n#define SIM_COMPLEX_OPCODE_EXCEPTION 0x2\n#define SIM_TEMU_TIMEOUT_EXCEPTION 0x3\n#define SIM_MMU_EXCEPTION 0x4\n#define SIM_ICOUNT_COMPLETE_EXCEPTION 0x5\n\n/* Instruction types processed by FPU ALU. This is used to set the latencies. */\n#define FU_FPU_ALU_FADD 0x0\n#define FU_FPU_ALU_FSUB 0x1\n#define FU_FPU_ALU_FMUL 0x2\n#define FU_FPU_ALU_FDIV 0x3\n#define FU_FPU_ALU_FSQRT 0x4\n#define FU_FPU_ALU_FSGNJ 0x5\n#define FU_FPU_ALU_FMIN 0x6\n#define FU_FPU_ALU_FMAX 0x7\n#define FU_FPU_ALU_FEQ 0x8\n#define FU_FPU_ALU_FLT 0x9\n#define FU_FPU_ALU_FLE 0xa\n#define FU_FPU_ALU_FCVT 0xb\n#define FU_FPU_ALU_CVT 0xc\n#define FU_FPU_ALU_FMV 0xd\n#define FU_FPU_ALU_FCLASS 0xe\n#define MAX_FU_FPU_ALU_TYPES 15\n\n/* Eviction policies for set associative data structures */\n#define EVICT_POLICY_RANDOM 0x0\n#define EVICT_POLICY_BIT_PLRU 0x1\n\n#endif\n"
  },
  {
    "path": "src/riscvsim/riscv_sim_typedefs.h",
    "content": "/**\n * Global typedefs and macros used by MARSS-RISCV\n *\n * Copyright (c) 2016-2017 Fabrice Bellard\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _RISCV_SIM_TYPEDEFS_H_\n#define _RISCV_SIM_TYPEDEFS_H_\n\n#include <inttypes.h>\n\n#if MAX_XLEN == 32\n#define RV32\n#define BIT_SIZE 32\n#elif MAX_XLEN  == 64\n#define RV64\n#define BIT_SIZE 64\n#endif\n\n#define SIM_FLEN 64\n\n#if BIT_SIZE == 32\ntypedef int32_t target_long;\ntypedef uint32_t target_ulong;\n#define TARGET_ULONG_FMT PRIu32\n#define TARGET_LONG_FMT PRId32\n#define TARGET_ULONG_SCN SCNu32\n#define TARGET_LONG_SCN SCNd32\n#define TARGET_ULONG_HEX PRIx32\n\n#elif BIT_SIZE == 64\ntypedef int64_t target_long;\ntypedef uint64_t target_ulong;\n#define TARGET_ULONG_FMT PRIu64\n#define TARGET_LONG_FMT PRId64\n#define TARGET_ULONG_SCN SCNu64\n#define TARGET_LONG_SCN SCNd64\n#define TARGET_ULONG_HEX PRIx64\n\n#endif // BIT_SIZE == 64\n\n#include \"riscv_sim_macros.h\"\n\n#endif\n"
  },
  {
    "path": "src/riscvsim/utils/circular_queue.c",
    "content": "/**\n * Generic Circular Queue\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"circular_queue.h\"\n\nvoid\ncq_init(CQ *p, int max_size_val)\n{\n    p->front = -1;\n    p->rear = -1;\n    p->max_size = max_size_val;\n}\n\nint\ncq_enqueue(CQ *p)\n{\n    if (cq_full(p))\n    {\n        /* Queue full */\n        return -1;\n    }\n    else if (cq_empty(p))\n    {\n        /* Empty Queue, insert first element */\n        p->front = 0;\n        p->rear = 0;\n        return p->front;\n    }\n    else if ((p->rear == (p->max_size - 1)) && (p->front != 0))\n    {\n        /* Wrap around */\n        p->rear = 0;\n        return p->rear;\n    }\n    else\n    {\n        (p->rear)++;\n        return p->rear;\n    }\n}\n\nint\ncq_dequeue(CQ *p)\n{\n    int old_front;\n\n    if (cq_empty(p))\n    {\n        /* Empty Queue */\n        return -1;\n    }\n\n    old_front = p->front;\n\n    if (p->front == p->rear)\n    {\n        /* Remove the only element in the queue */\n        p->front = -1;\n        p->rear = -1;\n    }\n    else if (p->front == (p->max_size - 1))\n    {\n        /* Wrap around */\n        p->front = 0;\n    }\n    else\n    {\n        (p->front)++;\n    }\n\n    return old_front;\n}\n\nint\ncq_empty(const CQ *p)\n{\n    if (p->front == -1)\n    {\n        return 1;\n    }\n    return 0;\n}\n\nint\ncq_full(const CQ *p)\n{\n    if ((p->front == 0 && (p->rear == (p->max_size - 1)))\n        || ((p->max_size > 1)\n            && (p->rear == ((p->front - 1) % (p->max_size - 1)))))\n    {\n        return 1;\n    }\n    return 0;\n}\n\nvoid\ncq_reset(CQ *p)\n{\n    p->front = -1;\n    p->rear = -1;\n}\n\nint\ncq_front(const CQ *p)\n{\n    return p->front;\n}\n\nint\ncq_rear(const CQ *p)\n{\n    return p->rear;\n}\n\nvoid\ncq_set_rear(CQ *p, int rear)\n{\n    p->rear = rear;\n}"
  },
  {
    "path": "src/riscvsim/utils/circular_queue.h",
    "content": "/**\n * Generic Circular Queue\n *\n * Interface for generic type circular queue, which only adjusts front and rear\n * indexes. The user maintains data separately.\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _CIRCULAR_QUEUE_H_\n#define _CIRCULAR_QUEUE_H_\n\ntypedef struct CircularQueue\n{\n    int front;\n    int rear;\n    int max_size;\n} CQ;\n\nvoid cq_init(CQ *p, int max_size_val);\nvoid cq_reset(CQ *p);\nint cq_enqueue(CQ *p);\nint cq_dequeue(CQ *p);\nint cq_empty(const CQ *p);\nint cq_full(const CQ *p);\nint cq_front(const CQ *p);\nint cq_rear(const CQ *p);\nvoid cq_set_rear(CQ *p, int rear);\n#endif\n"
  },
  {
    "path": "src/riscvsim/utils/cpu_latches.c",
    "content": "/**\n * Set of data structures such as latches used by simulated core pipeline\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdlib.h>\n\n#include \"../../cutils.h\"\n#include \"../riscv_sim_macros.h\"\n#include \"cpu_latches.h\"\n#include \"sim_log.h\"\n\nvoid\ncpu_stage_flush(CPUStage *stage)\n{\n    stage->has_data = FALSE;\n    stage->insn_latch_index = -1;\n    stage->stage_exec_done = FALSE;\n}\n\nvoid\ncpu_stage_flush_pipe(CPUStage *stage, int num_stages)\n{\n    int i;\n\n    for (i = 0; i < num_stages; ++i)\n    {\n        cpu_stage_flush(&stage[i]);\n    }\n}\n\nvoid\ncpu_stage_flush_free_insn_latch(CPUStage *stage,\n                                InstructionLatch *insn_latch_pool)\n{\n    if (stage->insn_latch_index != -1)\n    {\n        insn_latch_pool[stage->insn_latch_index].status = INSN_LATCH_FREE;\n    }\n    cpu_stage_flush(stage);\n}\n\nstatic int\nget_free_insn_latch(const InstructionLatch *insn_latch_pool)\n{\n    int i;\n\n    for (i = 0; i < INSN_LATCH_POOL_SIZE; ++i)\n    {\n        if (insn_latch_pool[i].status == INSN_LATCH_FREE)\n        {\n            return i;\n        }\n    }\n\n    return -1;\n}\n\nvoid\nreset_insn_latch_pool(InstructionLatch *insn_latch_pool)\n{\n    int i;\n\n    /* Add all the latches back to latch pool */\n    for (i = 0; i < INSN_LATCH_POOL_SIZE; ++i)\n    {\n        insn_latch_pool[i].status = INSN_LATCH_FREE;\n    }\n}\n\nInstructionLatch *\ninsn_latch_allocate(InstructionLatch *insn_latch_pool)\n{\n    InstructionLatch *e;\n    int insn_latch_index;\n\n    insn_latch_index = get_free_insn_latch(insn_latch_pool);\n\n    sim_assert(\n        (insn_latch_index != -1), \"error: %s at line %d in %s(): %s\", __FILE__,\n        __LINE__, __func__,\n        \"failed to allocate instruction latch from instruction latch pool\");\n\n    e = &insn_latch_pool[insn_latch_index];\n    memset((void *)e, 0, sizeof(InstructionLatch));\n    e->status = INSN_LATCH_ALLOCATED;\n    e->insn_latch_index = insn_latch_index;\n    return e;\n}\n\nInstructionLatch *\nget_insn_latch(InstructionLatch *insn_latch_pool, int index)\n{\n    return (&insn_latch_pool[index]);\n}"
  },
  {
    "path": "src/riscvsim/utils/cpu_latches.h",
    "content": "/**\n * Set of data structures such as latches used by simulated core pipeline\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _CPU_LATCHES_H_\n#define _CPU_LATCHES_H_\n\n#include \"../bpu/bpu.h\"\n#include \"../decoder/riscv_instruction.h\"\n\n/* Instruction latch acts as a place holder for single instruction and keeps\n * complete information concerning it. This information is updated as the\n * instruction passes through the pipeline. This information includes status\n * flags, PC, decoded fields, latency in CPU cycles, operands values, the result\n * produced, memory address, branch status, exception status, etc. */\ntypedef struct InstructionLatch\n{\n    int status;\n    int insn_latch_index;\n    int is_decoded;\n    struct RVInstruction ins;\n    int max_clock_cycles;\n    int elasped_clock_cycles;\n    int cache_lookup_complete_signal_sent;\n\n    int data_fwd_done;\n    int read_rs1;\n    int read_rs2;\n    int read_rs3;\n    int keep_dest_busy;\n\n    int renamed;\n    int rob_idx;\n    int iq_idx;\n    int lsq_idx;\n\n    int branch_processed;\n    int mispredict;\n    int is_branch_taken;\n    int is_pred_correct;\n    target_ulong branch_target;\n    target_ulong predicted_target;\n    BPUResponsePkt bpu_resp_pkt;\n\n    uint64_t ins_dispatch_id;\n} InstructionLatch;\n\ntypedef struct CPUStage\n{\n    int has_data;\n    int stage_exec_done;\n    int insn_latch_index;\n} CPUStage;\n\nvoid cpu_stage_flush(CPUStage *stage);\nvoid cpu_stage_flush_pipe(CPUStage *stage, int num_stages);\nvoid cpu_stage_flush_free_insn_latch(CPUStage *stage,\n                                     InstructionLatch *insn_latch_pool);\n\nInstructionLatch *insn_latch_allocate(InstructionLatch *insn_latch_pool);\nInstructionLatch *get_insn_latch(InstructionLatch *insn_latch_pool,\n                                 int index);\nvoid reset_insn_latch_pool(InstructionLatch *e);\n#endif\n"
  },
  {
    "path": "src/riscvsim/utils/evict_policy.c",
    "content": "/**\n * Eviction policy wrapper for set associative data structures\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <math.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../riscv_sim_macros.h\"\n#include \"evict_policy.h\"\n#include \"sim_log.h\"\n#include \"sim_params.h\"\n\nstatic void\nbit_plru_use(EvictPolicy *p, int set, int way)\n{\n    if (p->num_ways == 1)\n    {\n        return;\n    }\n\n    /* Set MRU bit for this way in this set to 1 */\n    SET_BIT(p->sets[set], way);\n\n    /* Whenever the last remaining 0 bit of a set's status bits is set to 1, all\n     * other bits are reset to 0. */\n    if (p->sets[set] == BITMASK(p->num_ways))\n    {\n        p->sets[set] = 0;\n        SET_BIT(p->sets[set], way);\n    }\n}\n\nstatic int\nbit_plru_evict(EvictPolicy *p, int set)\n{\n    int i = 0;\n    uint64_t current_set = p->sets[set];\n\n    if (p->num_ways == 1)\n    {\n        return 0;\n    }\n\n    /* Return the first way address whose MRU bit is set to 0 */\n    for (i = 0; i < p->num_ways; i++)\n    {\n        if (GET_BIT(current_set, i) == 0)\n        {\n            return i;\n        }\n    }\n\n    sim_assert((0), \"error: %s at line %d in %s(): %s\", __FILE__, __LINE__,\n               __func__, \"for bit-plru eviction, there should be at least one \"\n                         \"way open for eviction\");\n}\n\nstatic void\nrandom_use(EvictPolicy *p, int set, int way)\n{\n    return;\n}\n\nstatic int\nrandom_evict(EvictPolicy *p, int set)\n{\n    return rand() % p->num_ways;\n}\n\nstatic void\nevict_policy_reset(EvictPolicy *p)\n{\n    memset((void *)p->sets, 0, p->num_sets * sizeof(uint64_t));\n}\n\nEvictPolicy *\nevict_policy_create(int sets, int ways, int policy_type)\n{\n    EvictPolicy *p;\n\n    p = calloc(1, sizeof(EvictPolicy));\n    assert(p);\n\n    p->num_sets = sets;\n    p->num_ways = ways;\n    p->type = policy_type;\n\n    p->sets = calloc(p->num_sets, sizeof(uint64_t));\n    assert(p->sets);\n\n    switch (p->type)\n    {\n        case EVICT_POLICY_RANDOM:\n        {\n            p->use = &random_use;\n            p->evict = &random_evict;\n            break;\n        }\n        case EVICT_POLICY_BIT_PLRU:\n        {\n            p->use = &bit_plru_use;\n            p->evict = &bit_plru_evict;\n            break;\n        }\n        default:\n        {\n            break;\n        }\n    }\n\n    p->reset = &evict_policy_reset;\n    return p;\n}\n\nvoid\nevict_policy_free(EvictPolicy **p)\n{\n    free((*p)->sets);\n    free(*p);\n}\n"
  },
  {
    "path": "src/riscvsim/utils/evict_policy.h",
    "content": "/**\n * Eviction policy wrapper for set associative data structures\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _EVICT_POLICY_H_\n#define _EVICT_POLICY_H_\n\n#include <inttypes.h>\n\ntypedef struct EvictPolicy\n{\n    int type;\n    int num_sets;\n    int num_ways;\n\n    /* MRU bit map for all the ways in a set */\n    uint64_t *sets;\n\n    /* This pointers are set according to eviction policy used */\n    void (*reset)(struct EvictPolicy *p);\n    void (*use)(struct EvictPolicy *p, int set, int way);\n    int (*evict)(struct EvictPolicy *p, int set);\n} EvictPolicy;\n\nEvictPolicy *evict_policy_create(int sets, int ways, int policy_type);\nvoid evict_policy_free(EvictPolicy **);\n#endif /* _EVICT_POLICY_H_ */\n"
  },
  {
    "path": "src/riscvsim/utils/sim_exception.c",
    "content": "/**\n * Exception context setup during simulation\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdlib.h>\n\n#include \"../../cutils.h\"\n#include \"sim_exception.h\"\n\nvoid\nsim_exception_set(SimException *s, const InstructionLatch *e)\n{\n    s->pending = TRUE;\n    s->cause = e->ins.exception_cause;\n\n    switch (s->cause)\n    {\n        case SIM_ILLEGAL_OPCODE_EXCEPTION:\n        case SIM_COMPLEX_OPCODE_EXCEPTION:\n        case SIM_MMU_EXCEPTION:\n        {\n            s->pc = e->ins.pc;\n            s->insn = e->ins.binary;\n            strncpy(s->insn_str, e->ins.str, RISCV_INS_STR_MAX_LENGTH);\n            s->insn_str[RISCV_INS_STR_MAX_LENGTH - 1] = '\\0';\n            break;\n        }\n\n        case SIM_TEMU_TIMEOUT_EXCEPTION:\n        case SIM_ICOUNT_COMPLETE_EXCEPTION:\n        {\n            /* In case if the committed instruction was a branch, after\n             * processing the timer, we must resume at this branch's target if\n             * it was taken */\n            if (unlikely(e->ins.is_branch && e->is_branch_taken))\n            {\n                s->pc = e->branch_target;\n            }\n            else\n            {\n                /* Else resume at next PC in sequence */\n                if ((e->ins.binary & 3) != 3)\n                {\n                    /* Current instruction is compressed */\n                    s->pc = e->ins.pc + 2;\n                }\n                else\n                {\n                    s->pc = e->ins.pc + 4;\n                }\n            }\n            break;\n        }\n    }\n}\n\nSimException *\nsim_exception_init()\n{\n    SimException *s;\n\n    s = calloc(1, sizeof(SimException));\n    assert(s);\n    return s;\n}\n\nvoid\nsim_exception_free(SimException **s)\n{\n    free(*s);\n    *s = NULL;\n}"
  },
  {
    "path": "src/riscvsim/utils/sim_exception.h",
    "content": "/**\n * Exception context setup during simulation\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _SIM_EXCEPTION_H_\n#define _SIM_EXCEPTION_H_\n#include <inttypes.h>\n\n#include \"../riscv_sim_macros.h\"\n#include \"cpu_latches.h\"\n\ntypedef struct SimException\n{\n    int pending;\n    int cause;\n    int cpu_stage;\n    target_ulong pc;\n    uint32_t insn;\n    char insn_str[RISCV_INS_STR_MAX_LENGTH];\n} SimException;\n\nSimException *sim_exception_init();\nvoid sim_exception_set(SimException *s, const InstructionLatch *e);\nvoid sim_exception_free(SimException **s);\n#endif\n"
  },
  {
    "path": "src/riscvsim/utils/sim_log.c",
    "content": "/**\n * Simulation Log Generator Utility\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <time.h>\n\n#include \"sim_log.h\"\n\nSimLog *sim_log;\n\nSimLog *\nsim_log_init(const char *filename)\n{\n    SimLog *s;\n    s = calloc(1, sizeof(SimLog));\n    assert(s);\n    s->log_fp = fopen(filename, \"w\");\n    return s;\n}\n\nvoid\nsim_log_event_to_terminal(const char *fmt, ...)\n{\n    va_list args;\n    va_start(args, fmt);\n    assert(fprintf(stderr, \"%s \", \"* (marss-riscv):\") != 0);\n    assert(vfprintf(stderr, fmt, args) != 0);\n    assert(fprintf(stderr, \"%s\\n\", \"\") != 0);\n    fflush(stderr);\n    va_end(args);\n}\n\nvoid\nsim_log_event_to_file(SimLog *s, const char *fmt, ...)\n{\n    va_list args;\n    va_start(args, fmt);\n    assert(fprintf(s->log_fp, \"%s \", \"* (marss-riscv):\") != 0);\n    assert(vfprintf(s->log_fp, fmt, args) != 0);\n    assert(fprintf(s->log_fp, \"%s\\n\", \"\") != 0);\n    fflush(s->log_fp);\n    va_end(args);\n}\n\nvoid\nsim_log_param_to_file(SimLog *s, const char *fmt, ...)\n{\n    va_list args;\n    va_start(args, fmt);\n    assert(fprintf(s->log_fp, \"\\t%s \", \"*\") != 0);\n    assert(vfprintf(s->log_fp, fmt, args) != 0);\n    assert(fprintf(s->log_fp, \"%s\\n\", \"\") != 0);\n    fflush(s->log_fp);\n    va_end(args);\n}\n\n/* This logs event both to stderr and log file */\nvoid\nsim_log_event(SimLog *s, const char *fmt, ...)\n{\n    va_list args, args1;\n    va_copy(args, args1);\n\n    /* Add log to terminal */\n    va_start(args, fmt);\n    assert(fprintf(stderr, \"%s \", \"* (marss-riscv):\") != 0);\n    assert(vfprintf(stderr, fmt, args) != 0);\n    assert(fprintf(stderr, \"%s\\n\", \"\") != 0);\n    fflush(stderr);\n    va_end(args);\n\n    /* Add log to file */\n    va_start(args1, fmt);\n    assert(fprintf(s->log_fp, \"%s \", \"* (marss-riscv):\") != 0);\n    assert(vfprintf(s->log_fp, fmt, args1) != 0);\n    assert(fprintf(s->log_fp, \"%s\\n\", \"\") != 0);\n    fflush(s->log_fp);\n    va_end(args1);\n}\n\n/* This logs parameter both to stderr and log file */\nvoid\nsim_log_param(SimLog *s, const char *fmt, ...)\n{\n    va_list args, args1;\n    va_copy(args, args1);\n\n    /* Add log to terminal */\n    va_start(args, fmt);\n    assert(fprintf(stderr, \"\\t%s \", \"*\") != 0);\n    assert(vfprintf(stderr, fmt, args) != 0);\n    assert(fprintf(stderr, \"%s\\n\", \"\") != 0);\n    fflush(stderr);\n    va_end(args);\n\n    va_start(args1, fmt);\n    assert(fprintf(s->log_fp, \"\\t%s \", \"*\") != 0);\n    assert(vfprintf(s->log_fp, fmt, args1) != 0);\n    assert(fprintf(s->log_fp, \"%s\\n\", \"\") != 0);\n    fflush(s->log_fp);\n    va_end(args1);\n}\n\nvoid\nsim_log_free(SimLog **s)\n{\n    fclose((*s)->log_fp);\n    free(*s);\n    *s = NULL;\n}\n\nchar *\nsim_log_get_current_timestamp(const char* sim_file_prefix)\n{\n    time_t rawtime;\n    char *p, *timestamp = calloc(1024, sizeof(char));\n    assert(timestamp);\n\n    /* Generate current time-stamp */\n    time(&rawtime);\n    sprintf(timestamp, \"%s_%s\", sim_file_prefix, ctime(&rawtime));\n\n    /* Replace ' ', '\\n' and ':' from time-stamp with '_' */\n    p = timestamp;\n    for (; *p; ++p)\n    {\n        if (*p == ' ')\n            *p = '_';\n\n        if (*p == '\\n')\n            *p = '_';\n\n        if (*p == ':')\n            *p = '_';\n    }\n\n    return timestamp;\n}"
  },
  {
    "path": "src/riscvsim/utils/sim_log.h",
    "content": "/**\n * Simulation Log Generator Utility\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _SIM_LOG_H_\n#define _SIM_LOG_H_\n\n#include <inttypes.h>\n#include <stdarg.h>\n#include <stdio.h>\n\n#define sim_assert(cond, fmt, ...)                                             \\\n    do                                                                         \\\n    {                                                                          \\\n        if (!(cond))                                                           \\\n        {                                                                      \\\n            sim_log_event(sim_log, fmt, __VA_ARGS__);                          \\\n            abort();                                                           \\\n        }                                                                      \\\n    } while (0)\n\ntypedef struct SimLog\n{\n    FILE *log_fp;\n} SimLog;\n\nextern SimLog *sim_log;\n\nSimLog *sim_log_init(const char *filename);\nvoid sim_log_event_to_terminal(const char *fmt, ...);\nvoid sim_log_event(SimLog *s, const char *fmt, ...);\nvoid sim_log_param(SimLog *s, const char *fmt, ...);\nvoid sim_log_event_to_file(SimLog *s, const char *fmt, ...);\nvoid sim_log_param_to_file(SimLog *s, const char *fmt, ...);\nchar *sim_log_get_current_timestamp(const char* sim_file_prefix);\nvoid sim_log_free(SimLog **s);\n#endif\n"
  },
  {
    "path": "src/riscvsim/utils/sim_params.c",
    "content": "/*\n * Simulation Parameters\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../utils/sim_log.h\"\n#include \"sim_params.h\"\n\n/* Max length for comma separated latency string for FU stages specified in\n * TinyEMU configuration file */\n#define LATENCY_STRING_MAX_LENGTH 256\n\nconst char *core_type_str[] = {\"in-order\", \"out-of-order\"};\nconst char *sim_param_status[] = {\"false\", \"true\"};\nconst char *evict_policy_str[] = {\"random\", \"bit-plru\"};\nconst char *cache_ra_str[] = {\"true\", \"false\"};\nconst char *cache_wa_str[] = {\"true\", \"false\"};\nconst char *cache_wp_str[] = {\"writeback\", \"writethrough\"};\nconst char *bpu_type_str[] = {\"bimodal\", \"adaptive\"};\nconst char *bpu_aliasing_func_type_str[] = {\"xor\", \"and\", \"none\"};\nconst char *dram_model_type_str[] = {\"base\", \"dramsim3\", \"ramulator\"};\nconst char *cpu_mode_str[] = {\"user\", \"supervisor\", \"hypervisor\", \"machine\"};\n\nvoid\nsim_params_log_options(const SimParams *p)\n{\n    sim_log_event_to_file(sim_log, \"%s\", \"Setting up TinyEMU options\");\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"code_tlb_size\", p->tlb_size);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"load_tlb_size\", p->tlb_size);\n    sim_log_param_to_file(sim_log, \"%s: %d\", \"store_tlb_size\", p->tlb_size);\n    sim_log_param_to_file(sim_log, \"%s: %d MB\", \"guest_ram_size\",\n                          p->guest_ram_size);\n\n    sim_log_event_to_file(sim_log, \"%s\", \"Setting up simulation options\");\n    if (p->start_in_sim)\n    {\n        sim_log_param_to_file(sim_log, \"%s\", \"-simstart\");\n    }\n\n    if (p->enable_stats_display)\n    {\n        sim_log_param_to_file(sim_log, \"%s\", \"-sim-stats-display\");\n        sim_log_param_to_file(sim_log, \"%s: %s\", \"-sim-stats-shm-name\",\n                              p->sim_stats_shm_name);\n    }\n\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"-sim_file_path\",\n                          p->sim_file_path);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"-sim-file-prefix\",\n                          p->sim_file_prefix);\n\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"-sim-log-file\", p->sim_log_file);\n\n    if (p->do_sim_trace)\n    {\n        sim_log_param_to_file(sim_log, \"%s\", \"-sim-trace\");\n        sim_log_param_to_file(sim_log, \"%s: %s\", \"-sim-trace-file\",\n                              p->sim_trace_file);\n    }\n\n    if (p->flush_sim_mem_on_simstart)\n    {\n        sim_log_param_to_file(sim_log, \"%s\", \"-sim-flush-mem\");\n    }\n\n    if (p->flush_bpu_on_simstart)\n    {\n        sim_log_param_to_file(sim_log, \"%s\", \"-sim-flush-bpu\");\n    }\n\n    if (p->sim_emulate_after_icount)\n    {\n        sim_log_param_to_file(sim_log, \"%s %lu\", \"-sim-emulate-after-icount\",\n                              p->sim_emulate_after_icount);\n    }\n\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"core_type\",\n                          core_type_str[p->core_type]);\n    sim_log_param_to_file(sim_log, \"%s: %lu MHz\", \"rtc_freq_mhz\", p->rtc_freq_mhz);\n    sim_log_param_to_file(sim_log, \"%s: %lu MHz\", \"cpu_freq_mhz\", p->cpu_freq_mhz);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"enable_bpu\",\n                          sim_param_status[p->enable_bpu]);\n    if (p->enable_bpu)\n    {\n        sim_log_param_to_file(sim_log, \"%s: %s\", \"bpu_type\",\n                              bpu_type_str[p->bpu_type]);\n        sim_log_param_to_file(sim_log, \"%s: %s\", \"bpu_flush_on_context_switch\",\n                              sim_param_status[p->bpu_flush_on_context_switch]);\n    }\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"enable_l1_caches\",\n                          sim_param_status[p->enable_l1_caches]);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"enable_l2_cache\",\n                          sim_param_status[p->enable_l2_cache]);\n    sim_log_param_to_file(sim_log, \"%s: %s\", \"dram_model_type\",\n                          dram_model_type_str[p->dram_model_type]);\n}\n\nstatic void\nsim_params_set_defaults(SimParams *p)\n{\n    int i;\n\n    p->core_name = strdup(DEF_CORE_NAME);\n    assert(p->core_name);\n\n    p->core_type = DEF_CORE_TYPE;\n    p->sim_file_path = strdup(DEF_SIM_FILE_PATH);\n    assert(p->sim_file_path);\n\n    p->sim_file_prefix = strdup(DEF_SIM_FILE_PREFIX);\n    assert(p->sim_file_prefix);\n\n    p->sim_trace_file = strdup(DEF_SIM_TRACE_FILE);\n    assert(p->sim_trace_file);\n\n    p->sim_log_file = strdup(DEF_SIM_LOG_FILE);\n    assert(p->sim_log_file);\n\n    p->sim_stats_shm_name = strdup(DEF_SIM_STATS_SHM_NAME);\n    assert(p->sim_stats_shm_name);\n\n    p->start_in_sim = DEF_START_SIM;\n    p->enable_stats_display = DEF_STATS_DISPLAY;\n    p->create_ins_str = DEF_CREATE_INS_STR;\n\n    p->num_cpu_stages = DEF_NUM_STAGES;\n    p->enable_parallel_fu = DEF_ENABLE_PARALLEL_FU;\n\n    p->iq_size = DEF_IQ_SIZE;\n    p->iq_issue_ports = DEF_IQ_ISSUE_PORTS;\n    p->rob_size = DEF_ROB_SIZE;\n    p->lsq_size = DEF_LSQ_SIZE;\n\n    p->num_alu_stages = DEF_NUM_ALU_STAGES;\n    p->alu_stage_latency = (int *)malloc(sizeof(int) * p->num_alu_stages);\n    assert(p->alu_stage_latency);\n    for (i = 0; i < p->num_alu_stages; ++i)\n    {\n        p->alu_stage_latency[i] = DEF_STAGE_LATENCY;\n    }\n\n    p->num_mul_stages = DEF_NUM_MUL_STAGES;\n    p->mul_stage_latency = (int *)malloc(sizeof(int) * p->num_mul_stages);\n    assert(p->mul_stage_latency);\n    for (i = 0; i < p->num_mul_stages; ++i)\n    {\n        p->mul_stage_latency[i] = DEF_STAGE_LATENCY;\n    }\n\n    p->num_div_stages = DEF_NUM_DIV_STAGES;\n    p->div_stage_latency = (int *)malloc(sizeof(int) * p->num_div_stages);\n    assert(p->div_stage_latency);\n    for (i = 0; i < p->num_div_stages; ++i)\n    {\n        p->div_stage_latency[i] = DEF_STAGE_LATENCY;\n    }\n\n    p->num_fpu_alu_stages = DEF_NUM_FPU_ALU_STAGES;\n    p->fpu_alu_latency[FU_FPU_ALU_FADD] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FSUB] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FMUL] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FDIV] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FSQRT] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FSGNJ] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FMIN] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FMAX] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FEQ] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FLT] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FLE] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FCVT] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_CVT] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FMV] = DEF_STAGE_LATENCY;\n    p->fpu_alu_latency[FU_FPU_ALU_FCLASS] = DEF_STAGE_LATENCY;\n\n    p->num_fpu_fma_stages = DEF_NUM_FPU_FMA_STAGES;\n    p->fpu_fma_stage_latency\n        = (int *)malloc(sizeof(int) * p->num_fpu_fma_stages);\n    assert(p->fpu_fma_stage_latency);\n    for (i = 0; i < p->num_fpu_fma_stages; ++i)\n    {\n        p->fpu_fma_stage_latency[i] = DEF_STAGE_LATENCY;\n    }\n\n    p->enable_bpu = DEF_ENABLE_BPU;\n    p->btb_size = DEF_BTB_SIZE;\n    p->btb_ways = DEF_BTB_WAYS;\n    p->bht_size = DEF_BHT_SIZE;\n    p->ras_size = DEF_RAS_SIZE;\n    p->bpu_type = DEF_BPU_TYPE;\n    p->bpu_ght_size = DEF_GHT_SIZE;\n    p->bpu_pht_size = DEF_PHT_SIZE;\n    p->bpu_history_bits = DEF_HISTORY_BITS;\n    p->bpu_aliasing_func_type = DEF_BPU_ALIAS_FUNC;\n    p->btb_eviction_policy = DEF_BTB_EVICT_POLICY;\n    p->flush_bpu_on_simstart = DEF_FLUSH_BPU_ON_SIMSTART;\n\n    p->enable_l1_caches = DEF_ENABLE_L1_CACHE;\n    p->l1_code_cache_read_latency = DEF_L1_CODE_CACHE_READ_LATENCY;\n    p->l1_code_cache_size = DEF_L1_CODE_CACHE_SIZE;\n    p->l1_code_cache_ways = DEF_L1_CODE_CACHE_WAYS;\n    p->l1_code_cache_evict = DEF_L1_CODE_CACHE_EVICT;\n    p->l1_data_cache_read_latency = DEF_L1_DATA_CACHE_READ_LATENCY;\n    p->l1_data_cache_write_latency = DEF_L1_DATA_CACHE_WRITE_LATENCY;\n    p->l1_data_cache_size = DEF_L1_DATA_CACHE_SIZE;\n    p->l1_data_cache_ways = DEF_L1_DATA_CACHE_WAYS;\n    p->l1_data_cache_evict = DEF_L1_DATA_CACHE_EVICT;\n\n    p->enable_l2_cache = DEF_ENABLE_L2_CACHE;\n    p->l2_shared_cache_read_latency = DEF_L2_CACHE_READ_LATENCY;\n    p->l2_shared_cache_write_latency = DEF_L2_CACHE_WRITE_LATENCY;\n    p->l2_shared_cache_size = DEF_L2_CACHE_SIZE;\n    p->l2_shared_cache_ways = DEF_L2_CACHE_WAYS;\n    p->l2_shared_cache_evict = DEF_L2_CACHE_EVICT;\n\n    p->cache_line_size = DEF_CACHE_LINE_SIZE;\n    p->cache_read_allocate_policy = DEF_CACHE_READ_ALLOC_POLICY;\n    p->cache_write_allocate_policy = DEF_CACHE_WRITE_ALLOC_POLICY;\n    p->cache_write_policy = DEF_CACHE_WRITE_POLICY;\n\n    p->tlb_size = DEF_TLB_SIZE;\n    p->dram_model_type = DEF_MEM_MODEL;\n    p->burst_length = DEF_DRAM_BURST_SIZE;\n    p->flush_sim_mem_on_simstart = DEF_FLUSH_SIM_MEM_ON_SIMSTART;\n\n    p->mem_access_latency = DEF_MEM_ACCESS_LATENCY;\n\n    p->dramsim_config_file = strdup(DEF_DRAMSIM_CONFIG_FILE);\n    assert(p->dramsim_config_file);\n\n    p->ramulator_config_file = strdup(DEF_RAMULATOR_CONFIG_FILE);\n    assert(p->ramulator_config_file);\n\n    p->sim_emulate_after_icount = DEF_SIM_EMULATE_AFTER_ICOUNT;\n    p->system_insn_latency = DEF_STAGE_LATENCY;\n    p->bpu_flush_on_context_switch = DEF_BPU_FLUSH_ON_CONTEXT_SWITCH;\n    p->rtc_freq_mhz = DEF_RTC_FREQ_MHZ;\n    p->cpu_freq_mhz = DEF_CPU_FREQ_MHZ;\n}\n\nstatic int\nis_power_of_two(int value)\n{\n    return ((value > 0) && ((value & (value - 1)) == 0));\n}\n\nstatic void\nvalidate_param(const char *param_name, int has_range, int min, int max,\n               int current)\n{\n    if (has_range)\n    {\n        sim_assert((current >= min && current <= max),\n                   \"error: %s at line %d in %s(): error validating \"\n                   \"param - %s must be either %d or %d\",\n                   __FILE__, __LINE__, __func__, param_name, min, max);\n    }\n    else\n    {\n        sim_assert((current >= min),\n                   \"error: %s at line %d in %s(): error validating \"\n                   \"param - %s must have a minimum value of %d\",\n                   __FILE__, __LINE__, __func__, param_name, min);\n    }\n}\n\nstatic void\nvalidate_param_p2(const char *param_name, int val)\n{\n    sim_assert((is_power_of_two(val)),\n               \"error: %s at line %d in %s(): error validating param - %s \"\n               \"must be a power of 2\",\n               __FILE__, __LINE__, __func__, param_name);\n}\n\nvoid\nsim_params_validate(SimParams *p)\n{\n    int i;\n    char trace_file_name[1024];\n\n    validate_param(\"start_in_sim\", 1, 0, 1, p->start_in_sim);\n    validate_param(\"enable_stats_display\", 1, 0, 1, p->enable_stats_display);\n\n    if (strcmp(p->core_name, \"incore\") == 0)\n    {\n        validate_param(\"num_cpu_stages\", 1, 5, 6, p->num_cpu_stages);\n    }\n    else if (strcmp(p->core_name, \"oocore\") == 0)\n    {\n        validate_param(\"iq_size\", 0, 1, 2048, p->iq_size);\n        validate_param(\"iq_issue_ports\", 0, 1, 2048, p->iq_issue_ports);\n        validate_param(\"rob_size\", 0, 1, 2048, p->rob_size);\n        validate_param(\"lsq_size\", 0, 1, 2048, p->lsq_size);\n    }\n\n    validate_param(\"rtc_freq_mhz\", 1, 1, 1000, p->rtc_freq_mhz);\n\n    /* Validate FU config */\n    validate_param(\"num_alu_stages\", 0, 1, 2048, p->num_alu_stages);\n\n    for (i = 0; i < p->num_alu_stages; ++i)\n    {\n        validate_param(\"alu_stage_latency\", 0, 1, 2048,\n                       p->alu_stage_latency[i]);\n    }\n\n    validate_param(\"num_mul_stages\", 0, 1, 2048, p->num_mul_stages);\n    for (i = 0; i < p->num_mul_stages; ++i)\n    {\n        validate_param(\"mul_stage_latency\", 0, 1, 2048,\n                       p->mul_stage_latency[i]);\n    }\n\n    validate_param(\"num_div_stages\", 0, 1, 2048, p->num_div_stages);\n    for (i = 0; i < p->num_div_stages; ++i)\n    {\n        validate_param(\"div_stage_latency\", 0, 1, 2048,\n                       p->div_stage_latency[i]);\n    }\n\n    validate_param(\"num_fpu_alu_stages\", 0, 1, 2048, p->num_fpu_alu_stages);\n    validate_param(\"fadd\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FADD]);\n    validate_param(\"fsub\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FSUB]);\n    validate_param(\"fmul\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FMUL]);\n    validate_param(\"fdiv\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FDIV]);\n    validate_param(\"fsqrt\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FSQRT]);\n    validate_param(\"fsgnj\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FSGNJ]);\n    validate_param(\"fmin\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FMIN]);\n    validate_param(\"fmax\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FMAX]);\n    validate_param(\"feq\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FEQ]);\n    validate_param(\"flt\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FLT]);\n    validate_param(\"fle\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FLE]);\n    validate_param(\"fcvt\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FCVT]);\n    validate_param(\"cvt\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_CVT]);\n    validate_param(\"fmv\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FMV]);\n    validate_param(\"fclass\", 0, 1, 2048, p->fpu_alu_latency[FU_FPU_ALU_FCLASS]);\n\n    validate_param(\"num_fpu_fma_stages\", 0, 1, 2048, p->num_fpu_fma_stages);\n    for (i = 0; i < p->num_fpu_fma_stages; ++i)\n    {\n        validate_param(\"fpu_fma_stage_latency\", 0, 1, 2048,\n                       p->fpu_fma_stage_latency[i]);\n    }\n\n    validate_param(\"system_insn_latency\", 0, 1, 2048, p->system_insn_latency);\n\n    /* Validate BPU config */\n    validate_param(\"enable_bpu\", 1, 0, 1, p->enable_bpu);\n    if (p->enable_bpu)\n    {\n        validate_param_p2(\"btb_size\", p->btb_size);\n        validate_param(\"btb_ways\", 0, 1, 2048, p->btb_ways);\n        validate_param(\"bpu_type\", 1, 0, 1, p->bpu_type);\n        validate_param(\"bpu_flush_on_context_switch\", 1, 0, 1,\n                       p->bpu_flush_on_context_switch);\n\n        switch (p->bpu_type)\n        {\n            case BPU_TYPE_BIMODAL:\n            {\n                validate_param_p2(\"bht_size\", p->bht_size);\n                break;\n            }\n\n            case BPU_TYPE_ADAPTIVE:\n            {\n                validate_param_p2(\"bpu_ght_size\", p->bpu_ght_size);\n                validate_param_p2(\"bpu_pht_size\", p->bpu_pht_size);\n                validate_param(\"bpu_history_bits\", 0, 1, 2048,\n                               p->bpu_history_bits);\n                break;\n            }\n        }\n    }\n\n    /* Validate caches */\n    validate_param(\"enable_l1_caches\", 1, 0, 1, p->enable_l1_caches);\n\n    if (p->enable_l1_caches)\n    {\n        validate_param(\"l1_code_cache_read_latency\", 0, 1, 2048,\n                       p->l1_code_cache_read_latency);\n        validate_param(\"l1_code_cache_size\", 0, 1, 2048, p->l1_code_cache_size);\n        validate_param(\"l1_code_cache_ways\", 0, 1, 2048, p->l1_code_cache_ways);\n        validate_param(\"l1_code_cache_evict\", 1, 0, 1, p->l1_code_cache_evict);\n\n        validate_param(\"l1_data_cache_read_latency\", 0, 1, 2048,\n                       p->l1_data_cache_read_latency);\n        validate_param(\"l1_data_cache_write_latency\", 0, 1, 2048,\n                       p->l1_data_cache_write_latency);\n        validate_param(\"l1_data_cache_size\", 0, 1, 2048, p->l1_data_cache_size);\n        validate_param(\"l1_data_cache_ways\", 0, 1, 2048, p->l1_data_cache_ways);\n        validate_param(\"l1_data_cache_evict\", 1, 0, 1, p->l1_data_cache_evict);\n\n        validate_param_p2(\"cache_line_size\", p->cache_line_size);\n        validate_param(\"cache_read_allocate_policy\", 1, 0, 1,\n                       p->cache_read_allocate_policy);\n        validate_param(\"cache_write_allocate_policy\", 1, 0, 1,\n                       p->cache_write_allocate_policy);\n        validate_param(\"cache_write_policy\", 1, 0, 1, p->cache_write_policy);\n\n        validate_param(\"enable_l2_cache\", 1, 0, 1, p->enable_l2_cache);\n\n        if (p->enable_l2_cache)\n        {\n            validate_param(\"l2_shared_cache_read_latency\", 0, 1, 2048,\n                           p->l2_shared_cache_read_latency);\n            validate_param(\"l2_shared_cache_write_latency\", 0, 1, 2048,\n                           p->l2_shared_cache_write_latency);\n            validate_param(\"l2_shared_cache_size\", 0, 1, 2048,\n                           p->l2_shared_cache_size);\n            validate_param(\"l2_shared_cache_ways\", 0, 1, 2048,\n                           p->l2_shared_cache_ways);\n            validate_param(\"l2_shared_cache_evict\", 1, 0, 1,\n                           p->l2_shared_cache_evict);\n        }\n    }\n\n    validate_param(\"tlb_size\", 0, 1, 2048, p->tlb_size);\n    validate_param(\"burst_length\", 0, 1, 2048, (int)p->burst_length);\n    validate_param(\"mem_access_latency\", 0, 1, 2048, p->mem_access_latency);\n\n    /* Create full trace file name */\n    strcpy(trace_file_name, p->sim_file_path);\n    strcat(trace_file_name, \"/\");\n    strcat(trace_file_name, p->sim_file_prefix);\n    strcat(trace_file_name, \".trace\");\n\n    free(p->sim_trace_file);\n    p->sim_trace_file = strdup(trace_file_name);\n}\n\nstatic void\nparse_stage_latency_str(int **dest, int max_stage_count, char *str)\n{\n    int pos;\n    char *ptr;\n\n    /* Re-allocate default allocated latency array with the new size parsed from\n     * config file */\n    *dest = (int *)realloc((*dest), max_stage_count * sizeof(int));\n    assert(*dest);\n\n    pos = 0;\n    ptr = strtok(str, \",\");\n    while (ptr != NULL)\n    {\n        (*dest)[pos++] = atoi(ptr);\n        ptr = strtok(NULL, \",\");\n        if (pos >= max_stage_count)\n        {\n            break;\n        }\n    }\n\n    /* if latency string is shorter than max_stage_count, we must exit */\n    sim_assert((pos == max_stage_count),\n               \"error: %s at line %d in %s(): latency string %s does \"\n               \"not specify all the latencies\",\n               __FILE__, __LINE__, __func__, str);\n}\n\nstatic void\nlog_default_param_int(const char *obj, const char *param, int val)\n{\n    sim_log_event(sim_log, \"parsing config file: %s object not found, \"\n                           \"selecting default value(s) for %s.%s -> %d\",\n                  obj, obj, param, val);\n}\n\nstatic void\nlog_default_param_str(const char *obj, const char *param, const char *val)\n{\n    sim_log_event(sim_log, \"parsing config file: %s object not found, \"\n                           \"selecting default value(s) for %s.%s -> %s\",\n                  obj, obj, param, val);\n}\n\nvoid\nsim_params_parse(SimParams *p, JSONValue cfg)\n{\n    char buf1[256];\n    const char *tag_name, *str;\n    JSONValue core_obj, obj, obj1;\n    char stage_latency_str[LATENCY_STRING_MAX_LENGTH];\n\n    snprintf(buf1, sizeof(buf1), \"%s\", \"core\");\n    core_obj = json_object_get(cfg, buf1);\n\n    if (json_is_undefined(core_obj))\n    {\n        log_default_param_str(buf1, \"\", \"\");\n    }\n\n    /* Parse simulation options */\n    tag_name = \"name\";\n    if (vm_get_str(core_obj, tag_name, &str) < 0)\n    {\n        log_default_param_str(buf1, tag_name, p->core_name);\n    }\n    else\n    {\n        free(p->core_name);\n        p->core_name = strdup(str);\n    }\n\n    tag_name = \"type\";\n    if (vm_get_str(core_obj, tag_name, &str) < 0)\n    {\n        log_default_param_str(buf1, tag_name, core_type_str[p->core_type]);\n    }\n    else\n    {\n        if (strcmp(str, \"incore\") == 0)\n        {\n            p->core_type = CORE_TYPE_INCORE;\n        }\n        else if (strcmp(str, \"oocore\") == 0)\n        {\n            p->core_type = CORE_TYPE_OOCORE;\n        }\n    }\n\n    tag_name = \"rtc_freq_mhz\";\n    if (vm_get_int(core_obj, tag_name, &p->rtc_freq_mhz) < 0)\n    {\n        log_default_param_int(buf1, tag_name, p->rtc_freq_mhz);\n    }\n\n    tag_name = \"cpu_freq_mhz\";\n    if (vm_get_int(core_obj, tag_name, &p->cpu_freq_mhz) < 0)\n    {\n        log_default_param_int(buf1, tag_name, p->cpu_freq_mhz);\n    }\n\n    if (p->core_type == CORE_TYPE_INCORE)\n    {\n        snprintf(buf1, sizeof(buf1), \"%s\", \"incore\");\n        obj1 = json_object_get(core_obj, buf1);\n\n        if (json_is_undefined(obj1))\n        {\n            log_default_param_str(buf1, \"\", \"\");\n        }\n\n        tag_name = \"num_cpu_stages\";\n        if (vm_get_int(obj1, tag_name, &p->num_cpu_stages) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->num_cpu_stages);\n        }\n    }\n    else if (p->core_type == CORE_TYPE_OOCORE)\n    {\n        snprintf(buf1, sizeof(buf1), \"%s\", \"oocore\");\n        obj1 = json_object_get(core_obj, buf1);\n\n        if (json_is_undefined(obj1))\n        {\n            log_default_param_str(buf1, \"\", \"\");\n        }\n\n        tag_name = \"iq_size\";\n        if (vm_get_int(obj1, tag_name, &p->iq_size) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->iq_size);\n        }\n\n        tag_name = \"iq_issue_ports\";\n        if (vm_get_int(obj1, tag_name, &p->iq_issue_ports) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->iq_issue_ports);\n        }\n\n        tag_name = \"rob_size\";\n        if (vm_get_int(obj1, tag_name, &p->rob_size) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->rob_size);\n        }\n\n        tag_name = \"rob_commit_ports\";\n        if (vm_get_int(obj1, tag_name, &p->rob_commit_ports) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->rob_commit_ports);\n        }\n\n        tag_name = \"lsq_size\";\n        if (vm_get_int(obj1, tag_name, &p->lsq_size) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->lsq_size);\n        }\n    }\n\n    snprintf(buf1, sizeof(buf1), \"%s\", \"functional_units\");\n    obj = json_object_get(core_obj, buf1);\n\n    if (json_is_undefined(obj))\n    {\n        log_default_param_str(buf1, \"\", \"\");\n    }\n\n    tag_name = \"num_alu_stages\";\n    if (vm_get_int(obj, tag_name, &p->num_alu_stages) < 0)\n    {\n        log_default_param_int(buf1, tag_name, p->num_alu_stages);\n    }\n\n    tag_name = \"alu_stage_latency\";\n    if (vm_get_str(obj, tag_name, &str) < 0)\n    {\n        log_default_param_int(buf1, tag_name, DEF_STAGE_LATENCY);\n    }\n    else\n    {\n        strncpy(stage_latency_str, str, LATENCY_STRING_MAX_LENGTH - 1);\n        stage_latency_str[LATENCY_STRING_MAX_LENGTH - 1] = '\\0';\n        parse_stage_latency_str(&p->alu_stage_latency, p->num_alu_stages,\n                                stage_latency_str);\n    }\n\n    tag_name = \"num_mul_stages\";\n    if (vm_get_int(obj, tag_name, &p->num_mul_stages) < 0)\n    {\n        log_default_param_int(buf1, tag_name, p->num_mul_stages);\n    }\n\n    tag_name = \"mul_stage_latency\";\n    if (vm_get_str(obj, tag_name, &str) < 0)\n    {\n        log_default_param_int(buf1, tag_name, DEF_STAGE_LATENCY);\n    }\n    else\n    {\n        strncpy(stage_latency_str, str, LATENCY_STRING_MAX_LENGTH - 1);\n        stage_latency_str[LATENCY_STRING_MAX_LENGTH - 1] = '\\0';\n        parse_stage_latency_str(&p->mul_stage_latency, p->num_mul_stages,\n                                stage_latency_str);\n    }\n\n    tag_name = \"num_div_stages\";\n    if (vm_get_int(obj, tag_name, &p->num_div_stages) < 0)\n    {\n        log_default_param_int(buf1, tag_name, p->num_div_stages);\n    }\n\n    tag_name = \"div_stage_latency\";\n    if (vm_get_str(obj, tag_name, &str) < 0)\n    {\n        log_default_param_int(buf1, tag_name, DEF_STAGE_LATENCY);\n    }\n    else\n    {\n        strncpy(stage_latency_str, str, LATENCY_STRING_MAX_LENGTH - 1);\n        stage_latency_str[LATENCY_STRING_MAX_LENGTH - 1] = '\\0';\n        parse_stage_latency_str(&p->div_stage_latency, p->num_div_stages,\n                                stage_latency_str);\n    }\n\n    tag_name = \"num_fpu_fma_stages\";\n    if (vm_get_int(obj, tag_name, &p->num_fpu_fma_stages) < 0)\n    {\n        log_default_param_int(buf1, tag_name, p->num_fpu_fma_stages);\n    }\n\n    tag_name = \"fpu_fma_stage_latency\";\n    if (vm_get_str(obj, tag_name, &str) < 0)\n    {\n        log_default_param_int(buf1, tag_name, DEF_STAGE_LATENCY);\n    }\n    else\n    {\n        strncpy(stage_latency_str, str, LATENCY_STRING_MAX_LENGTH - 1);\n        stage_latency_str[LATENCY_STRING_MAX_LENGTH - 1] = '\\0';\n        parse_stage_latency_str(&p->fpu_fma_stage_latency,\n                                p->num_fpu_fma_stages, stage_latency_str);\n    }\n\n    tag_name = \"system_insn_latency\";\n    if (vm_get_int(obj, tag_name, &p->system_insn_latency) < 0)\n    {\n        log_default_param_int(buf1, tag_name, p->system_insn_latency);\n    }\n\n    snprintf(buf1, sizeof(buf1), \"%s\", \"fpu_alu_stage_latency\");\n    obj1 = json_object_get(obj, buf1);\n\n    if (json_is_undefined(obj1))\n    {\n        log_default_param_str(buf1, \"\", \"\");\n    }\n\n    tag_name = \"fadd\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FADD]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FADD]);\n    }\n\n    tag_name = \"fsub\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FSUB]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FSUB]);\n    }\n\n    tag_name = \"fmul\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FMUL]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FMUL]);\n    }\n\n    tag_name = \"fdiv\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FDIV]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FDIV]);\n    }\n\n    tag_name = \"fsqrt\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FSQRT]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FSQRT]);\n    }\n\n    tag_name = \"fsgnj\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FSGNJ]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FSGNJ]);\n    }\n\n    tag_name = \"fmin\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FMIN]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FMIN]);\n    }\n\n    tag_name = \"fmax\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FMAX]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FMAX]);\n    }\n\n    tag_name = \"feq\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FEQ]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FEQ]);\n    }\n\n    tag_name = \"flt\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FLT]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FLT]);\n    }\n\n    tag_name = \"fle\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FLE]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FLE]);\n    }\n\n    tag_name = \"fcvt\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FCVT]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FCVT]);\n    }\n\n    tag_name = \"cvt\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_CVT]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_CVT]);\n    }\n\n    tag_name = \"fmv\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FMV]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FMV]);\n    }\n\n    tag_name = \"fclass\";\n    if (vm_get_int(obj1, tag_name, &p->fpu_alu_latency[FU_FPU_ALU_FCLASS]) < 0)\n    {\n        log_default_param_int(buf1, tag_name,\n                              p->fpu_alu_latency[FU_FPU_ALU_FCLASS]);\n    }\n\n    /* BPU */\n    snprintf(buf1, sizeof(buf1), \"%s\", \"bpu\");\n    obj = json_object_get(core_obj, buf1);\n\n    if (json_is_undefined(obj))\n    {\n        log_default_param_str(buf1, \"\", \"\");\n    }\n\n    tag_name = \"enable\";\n    if (vm_get_str(obj, tag_name, &str) < 0)\n    {\n        log_default_param_str(buf1, tag_name, sim_param_status[p->enable_bpu]);\n    }\n    else\n    {\n        if (strcmp(str, \"false\") == 0)\n        {\n            p->enable_bpu = DISABLE;\n        }\n        else if (strcmp(str, \"true\") == 0)\n        {\n            p->enable_bpu = ENABLE;\n        }\n        else\n        {\n            sim_assert((0), \"error: %s at line %d in %s(): error parsing \"\n                            \"param - %s->%s has invalid value\",\n                       __FILE__, __LINE__, __func__, buf1, tag_name);\n        }\n    }\n\n    tag_name = \"flush_on_context_switch\";\n    if (vm_get_str(obj, tag_name, &str) < 0)\n    {\n        log_default_param_str(buf1, tag_name,\n                              sim_param_status[p->bpu_flush_on_context_switch]);\n    }\n    else\n    {\n        if (strcmp(str, \"false\") == 0)\n        {\n            p->bpu_flush_on_context_switch = DISABLE;\n        }\n        else if (strcmp(str, \"true\") == 0)\n        {\n            p->bpu_flush_on_context_switch = ENABLE;\n        }\n        else\n        {\n            sim_assert((0), \"error: %s at line %d in %s(): error parsing \"\n                            \"param - %s->%s has invalid value\",\n                       __FILE__, __LINE__, __func__, buf1, tag_name);\n        }\n    }\n\n    if (p->enable_bpu == ENABLE)\n    {\n        snprintf(buf1, sizeof(buf1), \"%s\", \"btb\");\n        obj1 = json_object_get(obj, buf1);\n\n        if (json_is_undefined(obj1))\n        {\n            log_default_param_str(buf1, \"\", \"\");\n        }\n\n        tag_name = \"size\";\n        if (vm_get_int(obj1, tag_name, &p->btb_size) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->btb_size);\n        }\n\n        tag_name = \"ways\";\n        if (vm_get_int(obj1, tag_name, &p->btb_ways) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->btb_ways);\n        }\n\n        tag_name = \"eviction_policy\";\n        if (vm_get_str(obj1, tag_name, &str) < 0)\n        {\n            log_default_param_str(buf1, tag_name,\n                                  evict_policy_str[p->btb_eviction_policy]);\n        }\n        else\n        {\n            if (strcmp(str, \"random\") == 0)\n            {\n                p->btb_eviction_policy = EVICT_POLICY_RANDOM;\n            }\n            else if (strcmp(str, \"lru\") == 0)\n            {\n                p->btb_eviction_policy = EVICT_POLICY_BIT_PLRU;\n            }\n            else\n            {\n                sim_assert((0), \"error: %s at line %d in %s(): error parsing \"\n                                \"param - %s->%s has invalid value\",\n                           __FILE__, __LINE__, __func__, buf1, tag_name);\n            }\n        }\n\n        tag_name = \"bpu_type\";\n        if (vm_get_str(obj, tag_name, &str) < 0)\n        {\n            log_default_param_str(buf1, tag_name, bpu_type_str[p->bpu_type]);\n        }\n        else\n        {\n            if (strcmp(str, \"bimodal\") == 0)\n            {\n                p->bpu_type = BPU_TYPE_BIMODAL;\n            }\n            else if (strcmp(str, \"adaptive\") == 0)\n            {\n                p->bpu_type = BPU_TYPE_ADAPTIVE;\n            }\n            else\n            {\n                sim_assert((0), \"error: %s at line %d in %s(): error parsing \"\n                                \"param - %s->%s has invalid value\",\n                           __FILE__, __LINE__, __func__, buf1, tag_name);\n            }\n        }\n\n        switch (p->bpu_type)\n        {\n            case BPU_TYPE_BIMODAL:\n            {\n                snprintf(buf1, sizeof(buf1), \"%s\", \"bimodal\");\n                obj1 = json_object_get(obj, buf1);\n\n                if (json_is_undefined(obj1))\n                {\n                    log_default_param_str(buf1, \"\", \"\");\n                }\n\n                tag_name = \"bht_size\";\n                if (vm_get_int(obj1, tag_name, &p->bht_size) < 0)\n                {\n                    log_default_param_int(buf1, tag_name, p->bht_size);\n                }\n                break;\n            }\n\n            case BPU_TYPE_ADAPTIVE:\n            {\n                snprintf(buf1, sizeof(buf1), \"%s\", \"adaptive\");\n                obj1 = json_object_get(obj, buf1);\n\n                if (json_is_undefined(obj1))\n                {\n                    log_default_param_str(buf1, \"\", \"\");\n                }\n\n                tag_name = \"ght_size\";\n                if (vm_get_int(obj1, tag_name, &p->bpu_ght_size) < 0)\n                {\n                    log_default_param_int(buf1, tag_name, p->bpu_ght_size);\n                }\n\n                tag_name = \"pht_size\";\n                if (vm_get_int(obj1, tag_name, &p->bpu_pht_size) < 0)\n                {\n                    log_default_param_int(buf1, tag_name, p->bpu_pht_size);\n                }\n\n                tag_name = \"history_bits\";\n                if (vm_get_int(obj1, tag_name, &p->bpu_history_bits) < 0)\n                {\n                    log_default_param_int(buf1, tag_name, p->bpu_history_bits);\n                }\n\n                if ((p->bpu_ght_size == 1) && (p->bpu_pht_size == 1))\n                {\n                    tag_name = \"aliasing_func_type\";\n                    if (vm_get_str(obj1, tag_name, &str) < 0)\n                    {\n                        log_default_param_str(buf1, tag_name,\n                                              bpu_aliasing_func_type_str\n                                                  [p->bpu_aliasing_func_type]);\n                    }\n                    else\n                    {\n                        if (strcmp(str, \"xor\") == 0)\n                        {\n                            p->bpu_aliasing_func_type = BPU_ALIAS_FUNC_XOR;\n                        }\n                        else if (strcmp(str, \"and\") == 0)\n                        {\n                            p->bpu_aliasing_func_type = BPU_ALIAS_FUNC_AND;\n                        }\n                        else if (strcmp(str, \"none\") == 0)\n                        {\n                            p->bpu_aliasing_func_type = BPU_ALIAS_FUNC_NONE;\n                        }\n                        else\n                        {\n                            sim_assert(\n                                (0),\n                                \"error: %s at line %d in %s(): error parsing \"\n                                \"param - %s->%s has invalid value\",\n                                __FILE__, __LINE__, __func__, buf1, tag_name);\n                        }\n                    }\n                }\n                break;\n            }\n        }\n\n        tag_name = \"ras_size\";\n        if (vm_get_int(obj, tag_name, &p->ras_size) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->ras_size);\n        }\n    }\n\n    snprintf(buf1, sizeof(buf1), \"%s\", \"caches\");\n    obj1 = json_object_get(core_obj, buf1);\n\n    if (json_is_undefined(obj1))\n    {\n        log_default_param_str(buf1, \"\", \"\");\n    }\n\n    /* L1 Caches */\n    tag_name = \"enable_l1_caches\";\n    if (vm_get_str(obj1, tag_name, &str) < 0)\n    {\n        log_default_param_str(buf1, tag_name,\n                              sim_param_status[p->enable_l1_caches]);\n    }\n    else\n    {\n        if (strcmp(str, \"false\") == 0)\n        {\n            p->enable_l1_caches = DISABLE;\n        }\n        else if (strcmp(str, \"true\") == 0)\n        {\n            p->enable_l1_caches = ENABLE;\n        }\n        else\n        {\n            sim_assert((0), \"error: %s at line %d in %s(): error parsing \"\n                            \"param - %s->%s has invalid value\",\n                       __FILE__, __LINE__, __func__, buf1, tag_name);\n        }\n    }\n\n    if (p->enable_l1_caches)\n    {\n        snprintf(buf1, sizeof(buf1), \"%s\", \"icache\");\n        obj = json_object_get(obj1, buf1);\n\n        if (json_is_undefined(obj))\n        {\n            log_default_param_str(buf1, \"\", \"\");\n        }\n\n        tag_name = \"latency\";\n        if (vm_get_int(obj, tag_name, &p->l1_code_cache_read_latency) < 0)\n        {\n            log_default_param_int(buf1, tag_name,\n                                  p->l1_code_cache_read_latency);\n        }\n\n        tag_name = \"size\";\n        if (vm_get_int(obj, tag_name, &p->l1_code_cache_size) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->l1_code_cache_size);\n        }\n\n        tag_name = \"ways\";\n        if (vm_get_int(obj, tag_name, &p->l1_code_cache_ways) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->l1_code_cache_ways);\n        }\n\n        tag_name = \"eviction\";\n        if (vm_get_str(obj, tag_name, &str) < 0)\n        {\n            log_default_param_str(buf1, tag_name,\n                                  evict_policy_str[p->l1_code_cache_evict]);\n        }\n        else\n        {\n            if (strcmp(str, \"lru\") == 0)\n            {\n                p->l1_code_cache_evict = EVICT_POLICY_BIT_PLRU;\n            }\n            else if (strcmp(str, \"random\") == 0)\n            {\n                p->l1_code_cache_evict = EVICT_POLICY_RANDOM;\n            }\n            else\n            {\n                sim_assert((0), \"error: %s at line %d in %s(): error parsing \"\n                                \"param - %s->%s has invalid value\",\n                           __FILE__, __LINE__, __func__, buf1, tag_name);\n            }\n        }\n\n        snprintf(buf1, sizeof(buf1), \"%s\", \"dcache\");\n        obj = json_object_get(obj1, buf1);\n\n        if (json_is_undefined(obj))\n        {\n            log_default_param_str(buf1, \"\", \"\");\n        }\n\n        tag_name = \"latency\";\n        if (vm_get_int(obj, tag_name, &p->l1_data_cache_read_latency) < 0)\n        {\n            log_default_param_int(buf1, tag_name,\n                                  p->l1_data_cache_read_latency);\n        }\n\n        tag_name = \"size\";\n        if (vm_get_int(obj, tag_name, &p->l1_data_cache_size) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->l1_data_cache_size);\n        }\n\n        tag_name = \"ways\";\n        if (vm_get_int(obj, tag_name, &p->l1_data_cache_ways) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->l1_data_cache_ways);\n        }\n\n        tag_name = \"eviction\";\n        if (vm_get_str(obj, tag_name, &str) < 0)\n        {\n            log_default_param_str(buf1, tag_name,\n                                  evict_policy_str[p->l1_data_cache_evict]);\n        }\n        else\n        {\n            if (strcmp(str, \"lru\") == 0)\n            {\n                p->l1_data_cache_evict = EVICT_POLICY_BIT_PLRU;\n            }\n            else if (strcmp(str, \"random\") == 0)\n            {\n                p->l1_data_cache_evict = EVICT_POLICY_RANDOM;\n            }\n            else\n            {\n                sim_assert((0), \"error: %s at line %d in %s(): error parsing \"\n                                \"param - %s->%s has invalid value\",\n                           __FILE__, __LINE__, __func__, buf1, tag_name);\n            }\n        }\n\n        tag_name = \"line_size\";\n        if (vm_get_int(obj1, tag_name, &p->cache_line_size) < 0)\n        {\n            log_default_param_int(buf1, tag_name, p->cache_line_size);\n        }\n\n        tag_name = \"allocate_on_write_miss\";\n        if (vm_get_str(obj1, tag_name, &str) < 0)\n        {\n            log_default_param_str(buf1, tag_name,\n                                  cache_wa_str[p->cache_write_allocate_policy]);\n        }\n        else\n        {\n            if (strcmp(str, \"true\") == 0)\n            {\n                p->cache_write_allocate_policy = CACHE_WRITE_ALLOC;\n            }\n            else if (strcmp(str, \"false\") == 0)\n            {\n                p->cache_write_allocate_policy = CACHE_WRITE_NO_ALLOC;\n            }\n            else\n            {\n                sim_assert((0), \"error: %s at line %d in %s(): error parsing \"\n                                \"param - %s->%s has invalid value\",\n                           __FILE__, __LINE__, __func__, buf1, tag_name);\n            }\n        }\n\n        tag_name = \"write_policy\";\n        if (vm_get_str(obj1, tag_name, &str) < 0)\n        {\n            log_default_param_str(buf1, tag_name,\n                                  cache_wp_str[p->cache_write_policy]);\n        }\n        else\n        {\n            if (strcmp(str, \"writeback\") == 0)\n            {\n                p->cache_write_policy = CACHE_WRITEBACK;\n            }\n            else if (strcmp(str, \"writethrough\") == 0)\n            {\n                p->cache_write_policy = CACHE_WRITETHROUGH;\n            }\n            else\n            {\n                sim_assert((0), \"error: %s at line %d in %s(): error parsing \"\n                                \"param - %s->%s has invalid value\",\n                           __FILE__, __LINE__, __func__, buf1, tag_name);\n            }\n        }\n\n        snprintf(buf1, sizeof(buf1), \"%s\", \"l2_shared_cache\");\n        obj = json_object_get(obj1, buf1);\n\n        if (json_is_undefined(obj))\n        {\n            log_default_param_str(buf1, \"\", \"\");\n        }\n\n        tag_name = \"enable\";\n        if (vm_get_str(obj, tag_name, &str) < 0)\n        {\n            log_default_param_str(buf1, tag_name,\n                                  sim_param_status[p->enable_l2_cache]);\n        }\n        else\n        {\n            if (strcmp(str, \"false\") == 0)\n            {\n                p->enable_l2_cache = DISABLE;\n            }\n            else if (strcmp(str, \"true\") == 0)\n            {\n                p->enable_l2_cache = ENABLE;\n            }\n            else\n            {\n                sim_assert((0), \"error: %s at line %d in %s(): error parsing \"\n                                \"param - %s->%s has invalid value\",\n                           __FILE__, __LINE__, __func__, buf1, tag_name);\n            }\n        }\n\n        if (p->enable_l2_cache)\n        {\n            tag_name = \"latency\";\n            if (vm_get_int(obj, tag_name, &p->l2_shared_cache_read_latency) < 0)\n            {\n                log_default_param_int(buf1, tag_name,\n                                      p->l2_shared_cache_read_latency);\n            }\n\n            tag_name = \"size\";\n            if (vm_get_int(obj, tag_name, &p->l2_shared_cache_size) < 0)\n            {\n                log_default_param_int(buf1, tag_name, p->l2_shared_cache_size);\n            }\n\n            tag_name = \"ways\";\n            if (vm_get_int(obj, tag_name, &p->l2_shared_cache_ways) < 0)\n            {\n                log_default_param_int(buf1, tag_name, p->l2_shared_cache_ways);\n            }\n\n            tag_name = \"eviction\";\n            if (vm_get_str(obj, tag_name, &str) < 0)\n            {\n                log_default_param_str(\n                    buf1, tag_name, evict_policy_str[p->l2_shared_cache_evict]);\n            }\n            else\n            {\n                if (strcmp(str, \"lru\") == 0)\n                {\n                    p->l2_shared_cache_evict = EVICT_POLICY_BIT_PLRU;\n                }\n                else if (strcmp(str, \"random\") == 0)\n                {\n                    p->l2_shared_cache_evict = EVICT_POLICY_RANDOM;\n                }\n                else\n                {\n                    sim_assert((0),\n                               \"error: %s at line %d in %s(): error parsing \"\n                               \"param - %s->%s has invalid value\",\n                               __FILE__, __LINE__, __func__, buf1, tag_name);\n                }\n            }\n        }\n    }\n\n    snprintf(buf1, sizeof(buf1), \"%s\", \"memory\");\n    obj1 = json_object_get(cfg, buf1);\n\n    if (json_is_undefined(obj1))\n    {\n        log_default_param_str(buf1, \"\", \"\");\n    }\n\n    tag_name = \"tlb_size\";\n    if (vm_get_int(obj1, tag_name, &p->tlb_size) < 0)\n    {\n        log_default_param_int(buf1, tag_name, p->tlb_size);\n    }\n\n    tag_name = \"burst_length\";\n    if (vm_get_int(obj1, tag_name, (int *)&p->burst_length) < 0)\n    {\n        log_default_param_int(buf1, tag_name, p->burst_length);\n    }\n\n    switch (p->dram_model_type)\n    {\n        case MEM_MODEL_BASE:\n        {\n            snprintf(buf1, sizeof(buf1), \"%s\", \"base_dram_model\");\n            obj = json_object_get(obj1, buf1);\n\n            if (json_is_undefined(obj))\n            {\n                log_default_param_str(buf1, \"\", \"\");\n            }\n\n            tag_name = \"mem_access_latency\";\n            if (vm_get_int(obj, tag_name, &p->mem_access_latency) < 0)\n            {\n                log_default_param_int(buf1, tag_name, p->mem_access_latency);\n            }\n            break;\n        }\n        case MEM_MODEL_DRAMSIM:\n        {\n            snprintf(buf1, sizeof(buf1), \"%s\", \"dramsim3\");\n            obj = json_object_get(obj1, buf1);\n\n            if (json_is_undefined(obj))\n            {\n                log_default_param_str(buf1, \"\", \"\");\n            }\n\n            tag_name = \"config_file\";\n            if (vm_get_str(obj, tag_name, &str) < 0)\n            {\n                log_default_param_str(buf1, tag_name, p->dramsim_config_file);\n            }\n            else\n            {\n                free(p->dramsim_config_file);\n                p->dramsim_config_file = strdup(str);\n            }\n            break;\n        }\n        case MEM_MODEL_RAMULATOR:\n        {\n            snprintf(buf1, sizeof(buf1), \"%s\", \"ramulator\");\n            obj = json_object_get(obj1, buf1);\n\n            if (json_is_undefined(obj))\n            {\n                log_default_param_str(buf1, \"\", \"\");\n            }\n\n            tag_name = \"config_file\";\n            if (vm_get_str(obj, tag_name, &str) < 0)\n            {\n                log_default_param_str(buf1, tag_name, p->ramulator_config_file);\n            }\n            else\n            {\n                free(p->ramulator_config_file);\n                p->ramulator_config_file = strdup(str);\n            }\n            break;\n        }\n        default:\n        {\n            sim_assert((0),\n                       \"error: %s at line %d in %s(): invalid memory model\",\n                       __FILE__, __LINE__, __func__);\n        }\n    }\n}\n\nstatic void\nsim_param_log_exec_unit_param(const char *fu_num_stage_name, int num_stages,\n                              int *latencies)\n{\n    int i;\n\n    sim_log_param_to_file(sim_log, \"num_%s_stages: %d\", fu_num_stage_name,\n                          num_stages);\n    for (i = 0; i < num_stages; ++i)\n    {\n        sim_log_param_to_file(sim_log, \"%s_stage_%d: %d cycle(s)\",\n                              fu_num_stage_name, i, latencies[i]);\n    }\n}\n\nvoid\nsim_params_log_exec_unit_config(const SimParams *p)\n{\n    sim_log_event_to_file(sim_log, \"%s\", \"Setting up functional units\");\n    sim_param_log_exec_unit_param(\"int_alu\", p->num_alu_stages,\n                                  p->alu_stage_latency);\n    sim_param_log_exec_unit_param(\"int_mul\", p->num_mul_stages,\n                                  p->mul_stage_latency);\n    sim_param_log_exec_unit_param(\"int_div\", p->num_div_stages,\n                                  p->div_stage_latency);\n    sim_param_log_exec_unit_param(\"fpu_fma\", p->num_fpu_fma_stages,\n                                  p->fpu_fma_stage_latency);\n    sim_log_param_to_file(sim_log, \"num_%s_stages: %d\", \"fpu_alu\",\n                          p->num_fpu_alu_stages);\n    sim_log_param_to_file(sim_log, \"%s latency: %d\", \"fpu_alu\",\n                          p->num_fpu_alu_stages);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"fadd\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FADD]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"fsub\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FSUB]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"fmul\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FMUL]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"fdiv\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FDIV]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"fsqrt\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FSQRT]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"fsgnj\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FSGNJ]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"fmin\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FMIN]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"fmax\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FMAX]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"feq\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FEQ]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"flt\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FLT]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"fle\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FLE]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"fcvt\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FCVT]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"cvt\",\n                          p->fpu_alu_latency[FU_FPU_ALU_CVT]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"fmv\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FMV]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d cycle(s)\", \"fclass\",\n                          p->fpu_alu_latency[FU_FPU_ALU_FCLASS]);\n    sim_log_param_to_file(sim_log, \"%s latency: %d\", \"system_insn_latency\",\n                          p->system_insn_latency);\n}\n\nSimParams *\nsim_params_init()\n{\n    SimParams *p;\n\n    p = calloc(1, sizeof(SimParams));\n    assert(p);\n    sim_params_set_defaults(p);\n    return p;\n}\n\nvoid\nsim_params_free(SimParams *p)\n{\n    free(p->alu_stage_latency);\n    p->alu_stage_latency = NULL;\n    free(p->mul_stage_latency);\n    p->mul_stage_latency = NULL;\n    free(p->div_stage_latency);\n    p->div_stage_latency = NULL;\n    free(p->fpu_fma_stage_latency);\n    p->fpu_fma_stage_latency = NULL;\n\n    free(p->sim_file_prefix);\n    p->sim_file_prefix = NULL;\n\n    free(p->sim_trace_file);\n    p->sim_trace_file = NULL;\n\n    free(p->sim_log_file);\n    p->sim_log_file = NULL;\n\n    free(p->sim_file_path);\n    p->sim_file_path = NULL;\n\n    free(p->core_name);\n    p->core_name = NULL;\n\n    free(p->dramsim_config_file);\n    p->dramsim_config_file = NULL;\n\n    free(p->ramulator_config_file);\n    p->ramulator_config_file = NULL;\n\n    free(p->sim_stats_shm_name);\n    p->sim_stats_shm_name = NULL;\n\n    free(p);\n}"
  },
  {
    "path": "src/riscvsim/utils/sim_params.h",
    "content": "/*\n * Simulation Parameters\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _SIM_PARAMS_STATS_H_\n#define _SIM_PARAMS_STATS_H_\n\n#include <fcntl.h>\n#include <inttypes.h>\n#include <linux/limits.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n\n#include \"../../json.h\"\n#include \"../riscv_sim_macros.h\"\n\n/* Used for creating shared memory for writing stats */\n#define ALL_RW_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWGRP)\n\nenum SIM_PARAM_STATUS\n{\n    DISABLE,\n    ENABLE\n};\n\nenum CORE_TYPE\n{\n    CORE_TYPE_INCORE,\n    CORE_TYPE_OOCORE\n};\n\nenum BPU_TYPE\n{\n    BPU_TYPE_BIMODAL,\n    BPU_TYPE_ADAPTIVE\n};\n\nenum CACHE_READ_ALLOC_POLICY\n{\n    CACHE_READ_ALLOC,\n    CACHE_READ_NO_ALLOC\n};\n\nenum CACHE_WRITE_ALLOC_POLICY\n{\n    CACHE_WRITE_ALLOC,\n    CACHE_WRITE_NO_ALLOC\n};\n\nenum CACHE_WRITE_POLICY\n{\n    CACHE_WRITEBACK,\n    CACHE_WRITETHROUGH,\n};\n\nenum BPU_ALIAS_FUNC\n{\n    BPU_ALIAS_FUNC_XOR,\n    BPU_ALIAS_FUNC_AND,\n    BPU_ALIAS_FUNC_NONE\n};\n\nenum MEM_MODEL_TYPE\n{\n    MEM_MODEL_BASE,\n    MEM_MODEL_DRAMSIM,\n    MEM_MODEL_RAMULATOR,\n};\n\n/* Default values for simulation parameters */\n#define DEF_CORE_NAME \"default-riscv-core\"\n#define DEF_CORE_TYPE CORE_TYPE_INCORE\n#define DEF_START_SIM 0\n#define DEF_STATS_DISPLAY 0\n#define DEF_DO_SIM_TRACE DISABLE\n#define DEF_CREATE_INS_STR 0\n#define DEF_SIM_FILE_PATH \".\"\n#define DEF_SIM_FILE_PREFIX \"sim\"\n#define DEF_SIM_TRACE_FILE DEF_SIM_FILE_PREFIX\".trace\"\n#define DEF_SIM_LOG_FILE DEF_SIM_FILE_PREFIX\".log\"\n#define DEF_SIM_STATS_SHM_NAME DEF_SIM_FILE_PREFIX\"-shm\"\n\n#define DEF_NUM_STAGES 6\n#define DEF_ENABLE_PARALLEL_FU DISABLE\n\n#define DEF_IQ_SIZE 16\n#define DEF_IQ_ISSUE_PORTS 2\n#define DEF_ROB_SIZE 64\n#define DEF_ROB_COMMIT_PORTS 1\n#define DEF_LSQ_SIZE 16\n\n#define DEF_NUM_ALU_STAGES 1\n#define DEF_NUM_MUL_STAGES 1\n#define DEF_NUM_DIV_STAGES 1\n#define DEF_NUM_FPU_ALU_STAGES 1\n#define DEF_NUM_FPU_FMA_STAGES 1\n#define DEF_STAGE_LATENCY 1\n\n#define DEF_ENABLE_BPU ENABLE\n#define DEF_BPU_FLUSH_ON_CONTEXT_SWITCH DISABLE\n#define DEF_BTB_SIZE 512\n#define DEF_BTB_WAYS 2\n#define DEF_BHT_SIZE 256\n#define DEF_RAS_SIZE 6\n#define DEF_GHT_SIZE 1\n#define DEF_PHT_SIZE 1\n#define DEF_HISTORY_BITS 2\n#define DEF_BPU_ALIAS_FUNC BPU_ALIAS_FUNC_NONE\n#define DEF_BTB_EVICT_POLICY EVICT_POLICY_RANDOM\n#define DEF_BPU_TYPE BPU_TYPE_BIMODAL\n#define DEF_FLUSH_BPU_ON_SIMSTART DISABLE\n\n#define DEF_ENABLE_L1_CACHE ENABLE\n#define DEF_L1_CODE_CACHE_READ_LATENCY 1\n#define DEF_L1_CODE_CACHE_SIZE 32\n#define DEF_L1_CODE_CACHE_WAYS 4\n#define DEF_L1_CODE_CACHE_EVICT EVICT_POLICY_RANDOM\n\n#define DEF_L1_DATA_CACHE_READ_LATENCY 1\n#define DEF_L1_DATA_CACHE_WRITE_LATENCY 1\n#define DEF_L1_DATA_CACHE_SIZE 32\n#define DEF_L1_DATA_CACHE_WAYS 4\n#define DEF_L1_DATA_CACHE_EVICT EVICT_POLICY_RANDOM\n\n#define DEF_ENABLE_L2_CACHE ENABLE\n#define DEF_L2_CACHE_READ_LATENCY 1\n#define DEF_L2_CACHE_WRITE_LATENCY 1\n#define DEF_L2_CACHE_SIZE 256\n#define DEF_L2_CACHE_WAYS 16\n#define DEF_L2_CACHE_EVICT EVICT_POLICY_RANDOM\n\n#define DEF_CACHE_READ_ALLOC_POLICY CACHE_READ_ALLOC\n#define DEF_CACHE_WRITE_ALLOC_POLICY CACHE_WRITE_ALLOC\n#define DEF_CACHE_WRITE_POLICY CACHE_WRITEBACK\n#define DEF_CACHE_LINE_SIZE 64\n\n#define DEF_TLB_SIZE 32\n#define DEF_DRAM_BURST_SIZE 32\n#define DEF_FLUSH_SIM_MEM_ON_SIMSTART DISABLE\n#define DEF_MEM_MODEL MEM_MODEL_BASE\n\n#define DEF_MEM_ACCESS_LATENCY 46\n\n#define DEF_DRAMSIM_CONFIG_FILE \"DRAMsim3/configs/DDR4_4Gb_x16_2400.ini\"\n#define DEF_RAMULATOR_CONFIG_FILE \"ramulator/configs/DDR4-config.cfg\"\n\n#define DEF_SIM_EMULATE_AFTER_ICOUNT 0\n\n#define DEF_RTC_FREQ_MHZ 10\n#define DEF_CPU_FREQ_MHZ 1000\n\nextern const char *core_type_str[];\nextern const char *sim_param_status[];\nextern const char *evict_policy_str[];\nextern const char *cache_ra_str[];\nextern const char *cache_wa_str[];\nextern const char *cache_wp_str[];\nextern const char *bpu_type_str[];\nextern const char *bpu_aliasing_func_type_str[];\nextern const char *dram_model_type_str[];\nextern const char *cpu_mode_str[];\n\ntypedef struct SimParams\n{\n    /* Core Params */\n    char *core_name;\n    int core_type;\n    int start_in_sim;\n    int enable_stats_display;\n    int create_ins_str;\n    int do_sim_trace;\n    char *sim_trace_file;\n    char *sim_file_path;\n    char *sim_file_prefix;\n    char *sim_log_file;\n\n    /* Name of the POSIX shared memory to write stats */\n    char *sim_stats_shm_name;\n\n    /* In-order core */\n    int num_cpu_stages;\n    int enable_parallel_fu;\n\n    /* Out-of-order core */\n    int iq_size;\n    int iq_issue_ports;\n    int rob_size;\n    int rob_commit_ports;\n    int lsq_size;\n\n    /* FU Latencies in CPU cycles */\n    int num_alu_stages;\n    int *alu_stage_latency;\n\n    int num_mul_stages;\n    int *mul_stage_latency;\n\n    int num_div_stages;\n    int *div_stage_latency;\n\n    int num_fpu_alu_stages;\n    int fpu_alu_latency[MAX_FU_FPU_ALU_TYPES];\n\n    int num_fpu_fma_stages;\n    int *fpu_fma_stage_latency;\n\n    /* BPU */\n    int enable_bpu;\n    int bpu_flush_on_context_switch;\n    int btb_size;\n    int btb_ways;\n    int bht_size;\n    int ras_size;\n    int bpu_type;\n    int bpu_ght_size;\n    int bpu_pht_size;\n    int bpu_history_bits;\n    int bpu_aliasing_func_type;\n    int btb_eviction_policy;\n    int flush_bpu_on_simstart;\n\n    /* L1 Caches */\n    int enable_l1_caches;\n    int l1_code_cache_read_latency;\n    int l1_code_cache_size;\n    int l1_code_cache_ways;\n    int l1_code_cache_evict;\n    int l1_data_cache_read_latency;\n    int l1_data_cache_write_latency;\n    int l1_data_cache_size;\n    int l1_data_cache_ways;\n    int l1_data_cache_evict;\n\n    /* L2 Caches */\n    int enable_l2_cache;\n    int l2_shared_cache_read_latency;\n    int l2_shared_cache_write_latency;\n    int l2_shared_cache_size;\n    int l2_shared_cache_ways;\n    int l2_shared_cache_evict;\n\n    /* Common cache parameters */\n    int cache_line_size;\n    int cache_read_allocate_policy;\n    int cache_write_allocate_policy;\n    int cache_write_policy;\n\n    /* TLB and DRAM Params */\n    int flush_sim_mem_on_simstart;\n    uint64_t guest_ram_size;\n    int tlb_size;\n    int dram_model_type;\n    int burst_length;\n    int mem_access_latency;\n\n    /* DRAMSim3 Params */\n    char *dramsim_config_file;\n\n    /* Ramulator Params */\n    char *ramulator_config_file;\n\n    uint64_t sim_emulate_after_icount;\n    int system_insn_latency;\n    int rtc_freq_mhz;\n    int cpu_freq_mhz;\n} SimParams;\n\nSimParams *sim_params_init();\nvoid sim_params_parse(SimParams *p, JSONValue cfg);\nvoid sim_params_log_options(const SimParams *p);\nvoid sim_params_log_exec_unit_config(const SimParams *p);\nvoid sim_params_validate(SimParams *p);\nvoid sim_params_free(SimParams *p);\n#endif\n"
  },
  {
    "path": "src/riscvsim/utils/sim_stats.c",
    "content": "/*\n * Simulation Statistics\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n\n#include \"../../riscv_cpu_priv.h\"\n#include \"sim_log.h\"\n#include \"sim_stats.h\"\n\n#define SIM_STAT_PRINT_TO_FILE_HEADER(fp)                                      \\\n    do                                                                         \\\n    {                                                                          \\\n        fprintf(fp, \"%s,%s,%s,%s,%s,%s\\n\", \"stat-name\", \"user\", \"supervisor\",  \\\n                \"hypervisor\", \"machine\", \"total\");                             \\\n    } while (0)\n\n#define SIM_STAT_PRINT_TO_FILE(fp, stats, name, attr)                          \\\n    do                                                                         \\\n    {                                                                          \\\n        fprintf(                                                               \\\n            fp, \"%s,%lu,%lu,%lu,%lu,%lu\\n\", name, stats[0].attr,               \\\n            stats[1].attr, stats[2].attr, stats[3].attr,                       \\\n            (stats[0].attr + stats[1].attr + stats[2].attr + stats[3].attr));  \\\n    } while (0)\n\n#define SIM_STAT_PRINT_HEADER_TO_TERMINAL(fp)                                  \\\n    do                                                                         \\\n    {                                                                          \\\n        fprintf(fp, \"%-30s %-18s %-18s %-18s %-18s %-18s\\n\", \"stat-name\",      \\\n                \"user\", \"supervisor\", \"hypervisor\", \"machine\", \"total\");       \\\n    } while (0)\n\n#define SIM_STAT_PRINT_TO_TERMINAL(fp, stats, name, attr)                      \\\n    do                                                                         \\\n    {                                                                          \\\n        fprintf(                                                               \\\n            fp, \"%-30s %-18lu %-18lu %-18lu %-18lu %-18lu\\n\", name,            \\\n            stats[0].attr, stats[1].attr, stats[2].attr, stats[3].attr,        \\\n            (stats[0].attr + stats[1].attr + stats[2].attr + stats[3].attr));  \\\n    } while (0)\n\nvoid\nsim_stats_print_to_file(const SimStats *s, const char *pathname,\n                        uint64_t sim_time_milli_sec, const char *timestamp)\n{\n    FILE *fp;\n    char *filename;\n    char buffer[1024];\n\n    /* Generate stats filename with format: prefix_timestamp.csv */\n    sprintf(buffer, \"%s.csv\", timestamp);\n\n    filename = (char *)malloc(strlen(pathname) + strlen(buffer) + 2);\n    assert(filename);\n\n    strcpy(filename, pathname);\n    strcat(filename, \"/\");\n    strcat(filename, buffer);\n\n    fp = fopen(filename, \"w\");\n    assert(fp);\n\n    SIM_STAT_PRINT_TO_FILE_HEADER(fp);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"cycles\", cycles);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"commits\", ins_simulated);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"ins_fetch\", ins_fetch);\n\n    /* Add simulation time required on host machine to stats file, but only the\n     * total time */\n    fprintf(fp, \"%s,%lu,%lu,%lu,%lu,%lu\\n\", \"sim_time_milli_sec\", (uint64_t)0,\n            (uint64_t)0, (uint64_t)0, (uint64_t)0, sim_time_milli_sec);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"insn_mem_delay\", insn_mem_delay);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"data_mem_delay\", data_mem_delay);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"exec_unit_delay\", exec_unit_delay);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"load_insn\", ins_type[INS_TYPE_LOAD]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"store_insn\", ins_type[INS_TYPE_STORE]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"atomic_insn\", ins_type[INS_TYPE_ATOMIC]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"system_insn\", ins_emulated);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"aritmetic_insn\",\n                           ins_type[INS_TYPE_ARITMETIC]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"cond_branches\",\n                           ins_type[INS_TYPE_COND_BRANCH]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"jal_insn\", ins_type[INS_TYPE_JAL]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"jalr_insn\", ins_type[INS_TYPE_JALR]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"int_mul_insn\", ins_type[INS_TYPE_INT_MUL]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"int_div_insn\", ins_type[INS_TYPE_INT_DIV]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fp_load_insn\", ins_type[INS_TYPE_FP_LOAD]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fp_store_insn\", ins_type[INS_TYPE_FP_STORE]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fp_add_insn\", ins_type[INS_TYPE_FP_ADD]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fp_mul_insn\", ins_type[INS_TYPE_FP_MUL]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fp_fma_insn\", ins_type[INS_TYPE_FP_FMA]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fp_div_sqrt_insn\",\n                           ins_type[INS_TYPE_FP_DIV_SQRT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fp_misc_insn\", ins_type[INS_TYPE_FP_MISC]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"load_byte_insn\",\n                           ins_type[INS_TYPE_LOAD_BYTE]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"load_half_word_insn\",\n                           ins_type[INS_TYPE_LOAD_HALF_WORD]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"load_word_insn\",\n                           ins_type[INS_TYPE_LOAD_WORD]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"load_double_word_insn\",\n                           ins_type[INS_TYPE_LOAD_DOUBLE_WORD]);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"itlb_reads\", code_tlb_lookups);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"itlb_hits\", code_tlb_hits);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"load_tlb_reads\", load_tlb_lookups);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"load_tlb_hits\", load_tlb_hits);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"store_tlb_reads\", store_tlb_lookups);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"store_tlb_hits\", store_tlb_hits);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"cond_branches_taken\", ins_cond_branch_taken);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"cond_branches_pred_correct\",\n                           bpu_cond_correct);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"cond_branches_pred_incorrect\",\n                           bpu_cond_incorrect);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"uncond_branches_pred_correct\",\n                           bpu_uncond_correct);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"uncond_branches_pred_incorrect\",\n                           bpu_uncond_incorrect);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"btb_reads\", btb_probes);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"btb_hits\", btb_hits);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"btb_inserts\", btb_inserts);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"btb_updates\", btb_updates);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"int_regfile_reads\", int_regfile_reads);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"int_regfile_writes\", int_regfile_writes);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fp_regfile_reads\", fp_regfile_reads);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fp_regfile_writes\", fp_regfile_writes);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"csr_reads\", csr_reads);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"csr_writes\", csr_writes);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fu_alu_accesses\", fu_access[FU_ALU]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fu_mul_accesses\", fu_access[FU_MUL]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fu_div_accesses\", fu_access[FU_DIV]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fu_fpu_alu_accesses\", fu_access[FU_FPU_ALU]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fu_fpu_fma_accesses\", fu_access[FU_FPU_FMA]);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"ins_page_walks\", ins_page_walks);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"load_page_walks\", load_page_walks);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"store_page_walks\", store_page_walks);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"misaligned_fetch\", exceptions[CAUSE_MISALIGNED_FETCH]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fault_fetch\", exceptions[CAUSE_FAULT_FETCH]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"illegal_instruction\", exceptions[CAUSE_ILLEGAL_INSTRUCTION]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"breakpoint\", exceptions[CAUSE_BREAKPOINT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"misaligned_load\", exceptions[CAUSE_MISALIGNED_LOAD]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fault_load\", exceptions[CAUSE_FAULT_LOAD]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"misaligned_store\", exceptions[CAUSE_MISALIGNED_STORE]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fault_store\", exceptions[CAUSE_FAULT_STORE]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"user_ecall\", exceptions[CAUSE_USER_ECALL]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"supervisor_ecall\", exceptions[CAUSE_SUPERVISOR_ECALL]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"hypervisor_ecall\", exceptions[CAUSE_HYPERVISOR_ECALL]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"machine_ecall\", exceptions[CAUSE_MACHINE_ECALL]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"fetch_page_fault\", exceptions[CAUSE_FETCH_PAGE_FAULT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"load_page_fault\", exceptions[CAUSE_LOAD_PAGE_FAULT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"store_page_fault\", exceptions[CAUSE_STORE_PAGE_FAULT]);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"user_software_interrupt\", interrupts[CAUSE_USER_SOFTWARE_INTERRUPT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"supervisor_software_interrupt\", interrupts[CAUSE_SUPERVISOR_SOFTWARE_INTERRUPT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"machine_software_interrupt\", interrupts[CAUSE_MACHINE_SOFTWARE_INTERRUPT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"user_timer_interrupt\", interrupts[CAUSE_USER_TIMER_INTERRUPT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"supervisor_timer_interrupt\", interrupts[CAUSE_SUPERVISOR_TIMER_INTERRUPT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"machine_timer_interrupt\", interrupts[CAUSE_MACHINE_TIMER_INTERRUPT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"user_external_interrupt\", interrupts[CAUSE_USER_EXTERNAL_INTERRUPT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"supervisor_external_interrupt\", interrupts[CAUSE_SUPERVISOR_EXTERNAL_INTERRUPT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"machine_external_interrupt\", interrupts[CAUSE_MACHINE_EXTERNAL_INTERRUPT]);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"pipeline_flush\", pipeline_flush);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"L1_icache_reads\", icache_read);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"L1_icache_read_misses\", icache_read_miss);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"L1_dcache_reads\", dcache_read);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"L1_dcache_read_misses\", dcache_read_miss);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"L1_dcache_writes\", dcache_write);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"L1_dcache_write_misses\", dcache_write_miss);\n\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"L2_cache_reads\", l2_cache_read);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"L2_cache_read_misses\", l2_cache_read_miss);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"L2_cache_writes\", l2_cache_write);\n    SIM_STAT_PRINT_TO_FILE(fp, s, \"L2_cache_write_misses\", l2_cache_write_miss);\n\n    fclose(fp);\n    sim_log_event(sim_log, \"Saved simulation stats in %s\", filename);\n    free(filename);\n}\n\nvoid\nsim_stats_reset(SimStats *s)\n{\n    memset((void *)s, 0, NUM_MAX_PRV_LEVELS * sizeof(SimStats));\n}\n\nint\nsim_file_path_valid(const char *path)\n{\n    struct stat sb;\n    return ((stat(path, &sb) == 0) && S_ISDIR(sb.st_mode));\n}\n"
  },
  {
    "path": "src/riscvsim/utils/sim_stats.h",
    "content": "/*\n * Simulation Statistics\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _SIM_STATS_H_\n#define _SIM_STATS_H_\n\n#include <inttypes.h>\n\n#include \"../riscv_sim_macros.h\"\n\ntypedef struct SimStats\n{\n    /* General Stats */\n    uint64_t cycles;\n    uint64_t insn_mem_delay;\n    uint64_t data_mem_delay;\n    uint64_t exec_unit_delay;\n\n    /* Instruction Stats */\n    uint64_t ins_fetch;\n    uint64_t ins_simulated;\n    uint64_t ins_emulated;\n\n    uint64_t ins_type[NUM_MAX_INS_TYPES];\n    uint64_t ins_cond_branch_taken;\n\n    /* Register Access */\n    uint64_t csr_reads;\n    uint64_t csr_writes;\n    uint64_t fp_regfile_reads;\n    uint64_t fp_regfile_writes;\n    uint64_t int_regfile_reads;\n    uint64_t int_regfile_writes;\n\n    /* FU_Access */\n    uint64_t fu_access[NUM_MAX_FU];\n\n    /* BPU */\n    uint64_t btb_probes;\n    uint64_t btb_hits;\n    uint64_t btb_updates;\n    uint64_t btb_inserts;\n\n    uint64_t bpu_cond_correct;\n    uint64_t bpu_cond_incorrect;\n    uint64_t bpu_uncond_correct;\n    uint64_t bpu_uncond_incorrect;\n\n    /* TLB stats */\n    uint64_t code_tlb_lookups;\n    uint64_t code_tlb_hits;\n\n    uint64_t load_tlb_lookups;\n    uint64_t load_tlb_hits;\n\n    uint64_t store_tlb_lookups;\n    uint64_t store_tlb_hits;\n\n    uint64_t ins_page_walks;\n    uint64_t load_page_walks;\n    uint64_t store_page_walks;\n\n    /* Cache Stats */\n    uint64_t icache_read;\n    uint64_t icache_read_miss;\n    uint64_t dcache_read;\n    uint64_t dcache_write;\n    uint64_t dcache_read_miss;\n    uint64_t dcache_write_miss;\n    uint64_t l2_cache_read;\n    uint64_t l2_cache_write;\n    uint64_t l2_cache_read_miss;\n    uint64_t l2_cache_write_miss;\n\n    /* Exceptions */\n    uint64_t interrupts[24];\n    uint64_t exceptions[24];\n    uint64_t pipeline_flush;\n} SimStats;\n\n/* Performance counters are printed to file in CSV format when simulation\n * completes */\nvoid sim_stats_print_to_file(const SimStats *s, const char *pathname,\n                             uint64_t sim_time_milli_sec,\n                             const char *timestamp);\n\n/* Performance counters are printed on stderr in a tabular format when\n * simulation completes */\nvoid sim_stats_print_to_terminal(const SimStats *s);\nvoid sim_stats_reset(SimStats *s);\nint sim_file_path_valid(const char *path);\n#endif\n"
  },
  {
    "path": "src/riscvsim/utils/sim_trace.c",
    "content": "/**\n * Simulation Trace Generator Utility\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdlib.h>\n\n#include \"sim_trace.h\"\n\nvoid\nsim_trace_start(SimTrace *s, const char *filename)\n{\n    s->trace_fp = fopen(filename, \"w\");\n    assert(s->trace_fp);\n}\n\nvoid\nsim_trace_stop(SimTrace *s)\n{\n    fclose(s->trace_fp);\n}\n\nvoid\nsim_trace_commit(const SimTrace *s, uint64_t clock_cycle, int cpu_mode,\n                 InstructionLatch *e)\n{\n    fprintf(s->trace_fp, \"cycle=%\" TARGET_ULONG_FMT, clock_cycle);\n    fprintf(s->trace_fp, \" pc=%\" TARGET_ULONG_HEX, e->ins.pc);\n    fprintf(s->trace_fp, \" insn=%\" PRIx32, e->ins.binary);\n    fprintf(s->trace_fp, \" %s\", e->ins.str);\n    fprintf(s->trace_fp, \" mode=%s\", cpu_mode_str[cpu_mode]);\n    fprintf(s->trace_fp, \"\\n\");\n}\n\nvoid\nsim_trace_exception(const SimTrace *s, uint64_t clock_cycle, int cpu_mode,\n                    SimException *e)\n{\n    fprintf(s->trace_fp, \"cycle=%\" TARGET_ULONG_FMT, clock_cycle);\n    fprintf(s->trace_fp, \" pc=%\" TARGET_ULONG_HEX, e->pc);\n    fprintf(s->trace_fp, \" insn=%\" PRIx32, e->insn);\n    fprintf(s->trace_fp, \" %s\", e->insn_str);\n    fprintf(s->trace_fp, \" mode=%s\", cpu_mode_str[cpu_mode]);\n    fprintf(s->trace_fp, \"\\n\");\n}\n\nSimTrace *\nsim_trace_init()\n{\n    SimTrace *s;\n    s = calloc(1, sizeof(SimTrace));\n    assert(s);\n    return s;\n}\n\nvoid\nsim_trace_free(SimTrace **s)\n{\n    free(*s);\n    *s = NULL;\n}"
  },
  {
    "path": "src/riscvsim/utils/sim_trace.h",
    "content": "/**\n * Simulation Trace Generator Utility\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _SIM_TRACE_H_\n#define _SIM_TRACE_H_\n\n#include <inttypes.h>\n#include <stdio.h>\n\n#include \"cpu_latches.h\"\n#include \"sim_exception.h\"\n\ntypedef struct SimTrace\n{\n    FILE *trace_fp;\n} SimTrace;\n\nSimTrace *sim_trace_init();\nvoid sim_trace_start(SimTrace *s, const char *filename);\nvoid sim_trace_stop(SimTrace *s);\nvoid sim_trace_commit(const SimTrace *s, uint64_t clock_cycle, int cpu_mode,\n                      InstructionLatch *e);\nvoid sim_trace_exception(const SimTrace *s, uint64_t clock_cycle, int cpu_mode,\n                         SimException *e);\nvoid sim_trace_free(SimTrace **s);\n#endif\n"
  },
  {
    "path": "src/rtc_timer.c",
    "content": "/*\n * RISCV RTC Timer Device\n *\n * Copyright (c) 2016-2017 Fabrice Bellard\n * Copyright (c) 2020 Gaurav Kothari\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n#include \"rtc_timer.h\"\n\nuint64_t\nrtc_get_host_wall_clock_time(RTC *rtc)\n{\n    struct timespec ts;\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    return (uint64_t)ts.tv_sec * rtc->freq\n           + (ts.tv_nsec / (1000000000 / rtc->freq));\n}\n\n/* This simulates the RISC-V mtime CSR register */\nuint64_t\nrtc_get_elasped_time(RTC *rtc)\n{\n    return rtc_get_host_wall_clock_time(rtc) - rtc->start_time;\n}\n\nRTC *\nrtc_init(uint64_t freq)\n{\n    RTC *rtc = calloc(1, sizeof(RTC));\n    assert(rtc);\n\n    rtc->freq = freq;\n    rtc->start_time = rtc_get_host_wall_clock_time(rtc);\n\n    return rtc;\n}\n\nvoid\nrtc_free(RTC **rtc)\n{\n    free(*rtc);\n}"
  },
  {
    "path": "src/rtc_timer.h",
    "content": "/*\n * RISCV RTC Timer Device\n *\n * Copyright (c) 2016-2017 Fabrice Bellard\n * Copyright (c) 2020 Gaurav Kothari\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef _RTC_H_\n#define _RTC_H_\n\n#include <inttypes.h>\n\ntypedef struct RTC\n{\n    uint64_t freq;\n    uint64_t start_time;\n} RTC;\n\nRTC *rtc_init(uint64_t freq);\nuint64_t rtc_get_host_wall_clock_time(RTC *rtc);\nuint64_t rtc_get_elasped_time(RTC *rtc);\nvoid rtc_free(RTC **rtc);\n#endif"
  },
  {
    "path": "src/sdl.c",
    "content": "/*\n * SDL display driver\n * \n * Copyright (c) 2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <fcntl.h>\n#include <errno.h>\n\n#include <SDL/SDL.h>\n\n#include \"cutils.h\"\n#include \"virtio.h\"\n#include \"machine.h\"\n\n#define KEYCODE_MAX 127\n\nstatic SDL_Surface *screen;\nstatic SDL_Surface *fb_surface;\nstatic int screen_width, screen_height, fb_width, fb_height, fb_stride;\nstatic SDL_Cursor *sdl_cursor_hidden;\nstatic uint8_t key_pressed[KEYCODE_MAX + 1];\n\nstatic void sdl_update_fb_surface(FBDevice *fb_dev)\n{\n    if (!fb_surface)\n        goto force_alloc;\n    if (fb_width != fb_dev->width ||\n        fb_height != fb_dev->height ||\n        fb_stride != fb_dev->stride) {\n    force_alloc:\n        if (fb_surface != NULL)\n            SDL_FreeSurface(fb_surface);\n        fb_width = fb_dev->width;\n        fb_height = fb_dev->height;\n        fb_stride = fb_dev->stride;\n        fb_surface = SDL_CreateRGBSurfaceFrom(fb_dev->fb_data,\n                                              fb_dev->width, fb_dev->height,\n                                              32, fb_dev->stride,\n                                              0x00ff0000,\n                                              0x0000ff00,\n                                              0x000000ff,\n                                              0x00000000);\n        if (!fb_surface) {\n            fprintf(stderr, \"Could not create SDL framebuffer surface\\n\");\n            exit(1);\n        }\n    }\n}\n\nstatic void sdl_update(FBDevice *fb_dev, void *opaque,\n                       int x, int y, int w, int h)\n{\n    SDL_Rect r;\n    //    printf(\"sdl_update: %d %d %d %d\\n\", x, y, w, h);\n    r.x = x;\n    r.y = y;\n    r.w = w;\n    r.h = h;\n    SDL_BlitSurface(fb_surface, &r, screen, &r);\n    SDL_UpdateRect(screen, r.x, r.y, r.w, r.h);\n}\n\n#if defined(_WIN32)\n\nstatic int sdl_get_keycode(const SDL_KeyboardEvent *ev)\n{\n    return ev->keysym.scancode;\n}\n\n#else\n\n/* we assume Xorg is used with a PC keyboard. Return 0 if no keycode found. */\nstatic int sdl_get_keycode(const SDL_KeyboardEvent *ev)\n{\n    int keycode;\n    keycode = ev->keysym.scancode;\n    if (keycode < 9) {\n        keycode = 0;\n    } else if (keycode < 127 + 8) {\n        keycode -= 8;\n    } else {\n        keycode = 0;\n    }\n    return keycode;\n}\n\n#endif\n\n/* release all pressed keys */\nstatic void sdl_reset_keys(VirtMachine *m)\n{\n    int i;\n    \n    for(i = 1; i <= KEYCODE_MAX; i++) {\n        if (key_pressed[i]) {\n            vm_send_key_event(m, FALSE, i);\n            key_pressed[i] = FALSE;\n        }\n    }\n}\n\nstatic void sdl_handle_key_event(const SDL_KeyboardEvent *ev, VirtMachine *m)\n{\n    int keycode, keypress;\n\n    keycode = sdl_get_keycode(ev);\n    if (keycode) {\n        if (keycode == 0x3a || keycode ==0x45) {\n            /* SDL does not generate key up for numlock & caps lock */\n            vm_send_key_event(m, TRUE, keycode);\n            vm_send_key_event(m, FALSE, keycode);\n        } else {\n            keypress = (ev->type == SDL_KEYDOWN);\n            if (keycode <= KEYCODE_MAX)\n                key_pressed[keycode] = keypress;\n            vm_send_key_event(m, keypress, keycode);\n        }\n    } else if (ev->type == SDL_KEYUP) {\n        /* workaround to reset the keyboard state (used when changing\n           desktop with ctrl-alt-x on Linux) */\n        sdl_reset_keys(m);\n    }\n}\n\nstatic void sdl_send_mouse_event(VirtMachine *m, int x1, int y1,\n                                 int dz, int state, BOOL is_absolute)\n{\n    int buttons, x, y;\n\n    buttons = 0;\n    if (state & SDL_BUTTON(SDL_BUTTON_LEFT))\n        buttons |= (1 << 0);\n    if (state & SDL_BUTTON(SDL_BUTTON_RIGHT))\n        buttons |= (1 << 1);\n    if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))\n        buttons |= (1 << 2);\n    if (is_absolute) {\n        x = (x1 * 32768) / screen_width;\n        y = (y1 * 32768) / screen_height;\n    } else {\n        x = x1;\n        y = y1;\n    }\n    vm_send_mouse_event(m, x, y, dz, buttons);\n}\n\nstatic void sdl_handle_mouse_motion_event(const SDL_Event *ev, VirtMachine *m)\n{\n    BOOL is_absolute = vm_mouse_is_absolute(m);\n    int x, y;\n    if (is_absolute) {\n        x = ev->motion.x;\n        y = ev->motion.y;\n    } else {\n        x = ev->motion.xrel;\n        y = ev->motion.yrel;\n    }\n    sdl_send_mouse_event(m, x, y, 0, ev->motion.state, is_absolute);\n}\n\nstatic void sdl_handle_mouse_button_event(const SDL_Event *ev, VirtMachine *m)\n{\n    BOOL is_absolute = vm_mouse_is_absolute(m);\n    int state, dz;\n\n    dz = 0;\n    if (ev->type == SDL_MOUSEBUTTONDOWN) {\n        if (ev->button.button == SDL_BUTTON_WHEELUP) {\n            dz = 1;\n        } else if (ev->button.button == SDL_BUTTON_WHEELDOWN) {\n            dz = -1;\n        }\n    }\n    \n    state = SDL_GetMouseState(NULL, NULL);\n    /* just in case */\n    if (ev->type == SDL_MOUSEBUTTONDOWN)\n        state |= SDL_BUTTON(ev->button.button);\n    else\n        state &= ~SDL_BUTTON(ev->button.button);\n\n    if (is_absolute) {\n        sdl_send_mouse_event(m, ev->button.x, ev->button.y,\n                             dz, state, is_absolute);\n    } else {\n        sdl_send_mouse_event(m, 0, 0, dz, state, is_absolute);\n    }\n}\n\nvoid sdl_refresh(VirtMachine *m)\n{\n    SDL_Event ev_s, *ev = &ev_s;\n\n    if (!m->fb_dev)\n        return;\n    \n    sdl_update_fb_surface(m->fb_dev);\n\n    m->fb_dev->refresh(m->fb_dev, sdl_update, NULL);\n    \n    while (SDL_PollEvent(ev)) {\n        switch (ev->type) {\n        case SDL_KEYDOWN:\n        case SDL_KEYUP:\n            sdl_handle_key_event(&ev->key, m);\n            break;\n        case SDL_MOUSEMOTION:\n            sdl_handle_mouse_motion_event(ev, m);\n            break;\n        case SDL_MOUSEBUTTONDOWN:\n        case SDL_MOUSEBUTTONUP:\n            sdl_handle_mouse_button_event(ev, m);\n            break;\n        case SDL_QUIT:\n            exit(0);\n        }\n    }\n}\n\nstatic void sdl_hide_cursor(void)\n{\n    uint8_t data = 0;\n    sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);\n    SDL_ShowCursor(1);\n    SDL_SetCursor(sdl_cursor_hidden);\n}\n\nvoid sdl_init(int width, int height)\n{\n    int flags;\n    \n    screen_width = width;\n    screen_height = height;\n\n    if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE)) {\n        fprintf(stderr, \"Could not initialize SDL - exiting\\n\");\n        exit(1);\n    }\n\n    flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;\n    screen = SDL_SetVideoMode(width, height, 0, flags);\n    if (!screen || !screen->pixels) {\n        fprintf(stderr, \"Could not open SDL display\\n\");\n        exit(1);\n    }\n\n    SDL_WM_SetCaption(\"TinyEMU\", \"TinyEMU\");\n\n    sdl_hide_cursor();\n}\n\n"
  },
  {
    "path": "src/sha256.c",
    "content": "/* LibTomCrypt, modular cryptographic library -- Tom St Denis\n *\n * LibTomCrypt is a library that provides various cryptographic\n * algorithms in a highly modular and flexible manner.\n *\n * The library is free for all purposes without any express\n * guarantee it works.\n *\n * Tom St Denis, tomstdenis@gmail.com, http://libtom.org\n */\n#include <stdlib.h>\n#include <string.h>\n#include \"cutils.h\"\n#include \"sha256.h\"\n\n#define LOAD32H(a, b) a = get_be32(b)\n#define STORE32H(a, b) put_be32(b, a)\n#define STORE64H(a, b) put_be64(b, a)\n#define RORc(x, y) ( ((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((y)&31)) | ((uint32_t)(x)<<(uint32_t)(32-((y)&31)))) & 0xFFFFFFFFUL)\n\n#if defined(CONFIG_EMBUE)\n#define LTC_SMALL_CODE\n#endif\n\n/**\n  @file sha256.c\n  LTC_SHA256 by Tom St Denis\n*/\n\n#ifdef LTC_SMALL_CODE\n/* the K array */\nstatic const uint32_t K[64] = {\n    0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,\n    0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,\n    0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,\n    0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,\n    0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,\n    0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,\n    0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,\n    0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,\n    0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,\n    0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,\n    0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,\n    0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,\n    0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL\n};\n#endif\n\n/* Various logical functions */\n#define Ch(x,y,z)       (z ^ (x & (y ^ z)))\n#define Maj(x,y,z)      (((x | y) & z) | (x & y))\n#define S(x, n)         RORc((x),(n))\n#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))\n#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))\n#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))\n#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))\n#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))\n\n/* compress 512-bits */\nstatic void sha256_compress(SHA256_CTX *s, unsigned char *buf)\n{\n    uint32_t S[8], W[64], t0, t1;\n#ifdef LTC_SMALL_CODE\n    uint32_t t;\n#endif\n    int i;\n\n    /* copy state into S */\n    for (i = 0; i < 8; i++) {\n        S[i] = s->state[i];\n    }\n\n    /* copy the state into 512-bits into W[0..15] */\n    for (i = 0; i < 16; i++) {\n        LOAD32H(W[i], buf + (4*i));\n    }\n\n    /* fill W[16..63] */\n    for (i = 16; i < 64; i++) {\n        W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];\n    }\n\n    /* Compress */\n#ifdef LTC_SMALL_CODE\n#define RND(a,b,c,d,e,f,g,h,i)                         \\\n     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \\\n     t1 = Sigma0(a) + Maj(a, b, c);                    \\\n     d += t0;                                          \\\n     h  = t0 + t1;\n\n     for (i = 0; i < 64; ++i) {\n         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i);\n         t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];\n         S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;\n     }\n#else\n#define RND(a,b,c,d,e,f,g,h,i,ki)                    \\\n     t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i];   \\\n     t1 = Sigma0(a) + Maj(a, b, c);                  \\\n     d += t0;                                        \\\n     h  = t0 + t1;\n\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);\n    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);\n    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);\n    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);\n    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);\n    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);\n    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);\n    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);\n    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);\n\n#undef RND\n\n#endif\n\n    /* feedback */\n    for (i = 0; i < 8; i++) {\n        s->state[i] = s->state[i] + S[i];\n    }\n}\n\n#ifdef LTC_CLEAN_STACK\nstatic int sha256_compress(hash_state * md, unsigned char *buf)\n{\n    int err;\n    err = _sha256_compress(md, buf);\n    burn_stack(sizeof(uint32_t) * 74);\n    return err;\n}\n#endif\n\n/**\n   Initialize the hash state\n   @param md   The hash state you wish to initialize\n   @return CRYPT_OK if successful\n*/\nvoid SHA256_Init(SHA256_CTX *s)\n{\n    s->curlen = 0;\n    s->length = 0;\n    s->state[0] = 0x6A09E667UL;\n    s->state[1] = 0xBB67AE85UL;\n    s->state[2] = 0x3C6EF372UL;\n    s->state[3] = 0xA54FF53AUL;\n    s->state[4] = 0x510E527FUL;\n    s->state[5] = 0x9B05688CUL;\n    s->state[6] = 0x1F83D9ABUL;\n    s->state[7] = 0x5BE0CD19UL;\n}\n\nvoid SHA256_Update(SHA256_CTX *s, const uint8_t *in, unsigned long inlen)\n{\n    unsigned long n;\n\n    if (s->curlen > sizeof(s->buf)) {\n        abort();\n    }\n    if ((s->length + inlen) < s->length) {\n        abort();\n    }\n    while (inlen > 0) {\n        if (s->curlen == 0 && inlen >= 64) {\n            sha256_compress(s, (unsigned char *)in);\n            s->length += 64 * 8;\n            in             += 64;\n            inlen          -= 64;\n        } else {\n            n = min_int(inlen, 64 - s->curlen);\n            memcpy(s->buf + s->curlen, in, (size_t)n);\n            s->curlen += n;\n            in             += n;\n            inlen          -= n;\n            if (s->curlen == 64) {\n                sha256_compress(s, s->buf);\n                s->length += 8*64;\n                s->curlen = 0;\n            }\n       }\n    }                                                                           }\n\n/**\n   Terminate the hash to get the digest\n   @param md  The hash state\n   @param out [out] The destination of the hash (32 bytes)\n   @return CRYPT_OK if successful\n*/\nvoid SHA256_Final(uint8_t *out, SHA256_CTX *s)\n{\n    int i;\n\n    if (s->curlen >= sizeof(s->buf)) {\n        abort();\n    }\n\n\n    /* increase the length of the message */\n    s->length += s->curlen * 8;\n\n    /* append the '1' bit */\n    s->buf[s->curlen++] = (unsigned char)0x80;\n\n    /* if the length is currently above 56 bytes we append zeros\n     * then compress.  Then we can fall back to padding zeros and length\n     * encoding like normal.\n     */\n    if (s->curlen > 56) {\n        while (s->curlen < 64) {\n            s->buf[s->curlen++] = (unsigned char)0;\n        }\n        sha256_compress(s, s->buf);\n        s->curlen = 0;\n    }\n\n    /* pad upto 56 bytes of zeroes */\n    while (s->curlen < 56) {\n        s->buf[s->curlen++] = (unsigned char)0;\n    }\n\n    /* store length */\n    STORE64H(s->length, s->buf+56);\n    sha256_compress(s, s->buf);\n\n    /* copy output */\n    for (i = 0; i < 8; i++) {\n        STORE32H(s->state[i], out+(4*i));\n    }\n#ifdef LTC_CLEAN_STACK\n    zeromem(md, sizeof(hash_state));\n#endif\n}\n\nvoid SHA256(const uint8_t *buf, int buf_len, uint8_t *out)\n{\n    SHA256_CTX ctx;\n\n    SHA256_Init(&ctx);\n    SHA256_Update(&ctx, buf, buf_len);\n    SHA256_Final(out, &ctx);\n}\n\n#if 0\n/**\n  Self-test the hash\n  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled\n*/\nint  sha256_test(void)\n{\n #ifndef LTC_TEST\n    return CRYPT_NOP;\n #else\n  static const struct {\n      char *msg;\n      unsigned char hash[32];\n  } tests[] = {\n    { \"abc\",\n      { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,\n        0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,\n        0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,\n        0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }\n    },\n    { \"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\",\n      { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,\n        0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,\n        0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,\n        0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }\n    },\n  };\n\n  int i;\n  unsigned char tmp[32];\n  hash_state md;\n\n  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {\n      sha256_init(&md);\n      sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));\n      sha256_done(&md, tmp);\n      if (XMEMCMP(tmp, tests[i].hash, 32) != 0) {\n         return CRYPT_FAIL_TESTVECTOR;\n      }\n  }\n  return CRYPT_OK;\n #endif\n}\n\n#endif\n"
  },
  {
    "path": "src/sha256.h",
    "content": "/*\n * OpenSSL compatible SHA256 header\n * \n * Copyright (c) 2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef SHA256_H\n#define SHA256_H\n\n#define SHA256_DIGEST_LENGTH 32\n\ntypedef struct {\n    uint64_t length;\n    uint32_t state[8], curlen;\n    uint8_t buf[64];\n} SHA256_CTX;\n\nvoid SHA256_Init(SHA256_CTX *s);\nvoid SHA256_Update(SHA256_CTX *s, const uint8_t *in, unsigned long inlen);\nvoid SHA256_Final(uint8_t *out, SHA256_CTX *s);\nvoid SHA256(const uint8_t *buf, int buf_len, uint8_t *out);\n\n#endif /* SHA256_H */\n"
  },
  {
    "path": "src/simplefb.c",
    "content": "/*\n * Simple frame buffer\n * \n * Copyright (c) 2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n\n#include \"cutils.h\"\n#include \"iomem.h\"\n#include \"virtio.h\"\n#include \"machine.h\"\n\n//#define DEBUG_VBE\n\n#define FB_ALLOC_ALIGN 65536\n\nstruct SimpleFBState {\n    FBDevice *fb_dev;\n    int fb_page_count;\n    PhysMemoryRange *mem_range;\n};\n\n#define MAX_MERGE_DISTANCE 3\n\nvoid simplefb_refresh(FBDevice *fb_dev,\n                      SimpleFBDrawFunc *redraw_func, void *opaque,\n                      PhysMemoryRange *mem_range,\n                      int fb_page_count)\n{\n    const uint32_t *dirty_bits;\n    uint32_t dirty_val;\n    int y0, y1, page_y0, page_y1, byte_pos, page_index, bit_pos;\n\n    dirty_bits = phys_mem_get_dirty_bits(mem_range);\n    \n    page_index = 0;\n    y0 = y1 = 0;\n    while (page_index < fb_page_count) {\n        dirty_val = dirty_bits[page_index >> 5];\n        if (dirty_val != 0) {\n            bit_pos = 0;\n            while (dirty_val != 0) {\n                while (((dirty_val >> bit_pos) & 1) == 0)\n                    bit_pos++;\n                dirty_val &= ~(1 << bit_pos);\n\n                byte_pos = (page_index + bit_pos) * DEVRAM_PAGE_SIZE;\n                page_y0 = byte_pos / fb_dev->stride;\n                page_y1 = ((byte_pos + DEVRAM_PAGE_SIZE - 1) / fb_dev->stride) + 1;\n                page_y1 = min_int(page_y1, fb_dev->height);\n                if (y0 == y1) {\n                    y0 = page_y0;\n                    y1 = page_y1;\n                } else if (page_y0 <= (y1 + MAX_MERGE_DISTANCE)) {\n                    /* union with current region */\n                    y1 = page_y1;\n                } else {\n                    /* flush */\n                    redraw_func(fb_dev, opaque,\n                                0, y0, fb_dev->width, y1 - y0);\n                    y0 = page_y0;\n                    y1 = page_y1;\n                }\n            }\n        }\n        page_index += 32;\n    }\n\n    if (y0 != y1) {\n        redraw_func(fb_dev, opaque,\n                    0, y0, fb_dev->width, y1 - y0);\n    }\n}\n\nstatic void simplefb_refresh1(FBDevice *fb_dev,\n                              SimpleFBDrawFunc *redraw_func, void *opaque)\n{\n    SimpleFBState *s = fb_dev->device_opaque;\n    simplefb_refresh(fb_dev, redraw_func, opaque, s->mem_range,\n                     s->fb_page_count);\n}\n\nSimpleFBState *simplefb_init(PhysMemoryMap *map, uint64_t phys_addr,\n                             FBDevice *fb_dev, int width, int height)\n{\n    SimpleFBState *s;\n    \n    s = mallocz(sizeof(*s));\n    s->fb_dev = fb_dev;\n\n    fb_dev->width = width;\n    fb_dev->height = height;\n    fb_dev->stride = width * 4;\n    fb_dev->fb_size = (height * fb_dev->stride + FB_ALLOC_ALIGN - 1) & ~(FB_ALLOC_ALIGN - 1);\n    s->fb_page_count = fb_dev->fb_size >> DEVRAM_PAGE_SIZE_LOG2;\n\n    s->mem_range = cpu_register_ram(map, phys_addr, fb_dev->fb_size,\n                                    DEVRAM_FLAG_DIRTY_BITS);\n    \n    fb_dev->fb_data = s->mem_range->phys_mem;\n    fb_dev->device_opaque = s;\n    fb_dev->refresh = simplefb_refresh1;\n    return s;\n}\n"
  },
  {
    "path": "src/slirp/bootp.c",
    "content": "/*\n * QEMU BOOTP/DHCP server\n *\n * Copyright (c) 2004 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"slirp.h\"\n\n/* XXX: only DHCP is supported */\n\n#define LEASE_TIME (24 * 3600)\n\nstatic const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };\n\n#ifdef DEBUG\n#define DPRINTF(fmt, ...) \\\ndo if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ##  __VA_ARGS__); fflush(dfd); } while (0)\n#else\n#define DPRINTF(fmt, ...) do{}while(0)\n#endif\n\nstatic BOOTPClient *get_new_addr(Slirp *slirp, struct in_addr *paddr,\n                                 const uint8_t *macaddr)\n{\n    BOOTPClient *bc;\n    int i;\n\n    for(i = 0; i < NB_BOOTP_CLIENTS; i++) {\n        bc = &slirp->bootp_clients[i];\n        if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6))\n            goto found;\n    }\n    return NULL;\n found:\n    bc = &slirp->bootp_clients[i];\n    bc->allocated = 1;\n    paddr->s_addr = slirp->vdhcp_startaddr.s_addr + htonl(i);\n    return bc;\n}\n\nstatic BOOTPClient *request_addr(Slirp *slirp, const struct in_addr *paddr,\n                                 const uint8_t *macaddr)\n{\n    uint32_t req_addr = ntohl(paddr->s_addr);\n    uint32_t dhcp_addr = ntohl(slirp->vdhcp_startaddr.s_addr);\n    BOOTPClient *bc;\n\n    if (req_addr >= dhcp_addr &&\n        req_addr < (dhcp_addr + NB_BOOTP_CLIENTS)) {\n        bc = &slirp->bootp_clients[req_addr - dhcp_addr];\n        if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) {\n            bc->allocated = 1;\n            return bc;\n        }\n    }\n    return NULL;\n}\n\nstatic BOOTPClient *find_addr(Slirp *slirp, struct in_addr *paddr,\n                              const uint8_t *macaddr)\n{\n    BOOTPClient *bc;\n    int i;\n\n    for(i = 0; i < NB_BOOTP_CLIENTS; i++) {\n        if (!memcmp(macaddr, slirp->bootp_clients[i].macaddr, 6))\n            goto found;\n    }\n    return NULL;\n found:\n    bc = &slirp->bootp_clients[i];\n    bc->allocated = 1;\n    paddr->s_addr = slirp->vdhcp_startaddr.s_addr + htonl(i);\n    return bc;\n}\n\nstatic void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,\n                        struct in_addr *preq_addr)\n{\n    const uint8_t *p, *p_end;\n    int len, tag;\n\n    *pmsg_type = 0;\n    preq_addr->s_addr = htonl(0L);\n\n    p = bp->bp_vend;\n    p_end = p + DHCP_OPT_LEN;\n    if (memcmp(p, rfc1533_cookie, 4) != 0)\n        return;\n    p += 4;\n    while (p < p_end) {\n        tag = p[0];\n        if (tag == RFC1533_PAD) {\n            p++;\n        } else if (tag == RFC1533_END) {\n            break;\n        } else {\n            p++;\n            if (p >= p_end)\n                break;\n            len = *p++;\n            DPRINTF(\"dhcp: tag=%d len=%d\\n\", tag, len);\n\n            switch(tag) {\n            case RFC2132_MSG_TYPE:\n                if (len >= 1)\n                    *pmsg_type = p[0];\n                break;\n            case RFC2132_REQ_ADDR:\n                if (len >= 4) {\n                    memcpy(&(preq_addr->s_addr), p, 4);\n                }\n                break;\n            default:\n                break;\n            }\n            p += len;\n        }\n    }\n    if (*pmsg_type == DHCPREQUEST && preq_addr->s_addr == htonl(0L) &&\n        bp->bp_ciaddr.s_addr) {\n        memcpy(&(preq_addr->s_addr), &bp->bp_ciaddr, 4);\n    }\n}\n\nstatic void bootp_reply(Slirp *slirp, const struct bootp_t *bp)\n{\n    BOOTPClient *bc = NULL;\n    struct mbuf *m;\n    struct bootp_t *rbp;\n    struct sockaddr_in saddr, daddr;\n    struct in_addr preq_addr;\n    int dhcp_msg_type, val;\n    uint8_t *q;\n\n    /* extract exact DHCP msg type */\n    dhcp_decode(bp, &dhcp_msg_type, &preq_addr);\n    DPRINTF(\"bootp packet op=%d msgtype=%d\", bp->bp_op, dhcp_msg_type);\n    if (preq_addr.s_addr != htonl(0L))\n        DPRINTF(\" req_addr=%08x\\n\", ntohl(preq_addr.s_addr));\n    else\n        DPRINTF(\"\\n\");\n\n    if (dhcp_msg_type == 0)\n        dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */\n\n    if (dhcp_msg_type != DHCPDISCOVER &&\n        dhcp_msg_type != DHCPREQUEST)\n        return;\n    /* XXX: this is a hack to get the client mac address */\n    memcpy(slirp->client_ethaddr, bp->bp_hwaddr, 6);\n\n    m = m_get(slirp);\n    if (!m) {\n        return;\n    }\n    m->m_data += IF_MAXLINKHDR;\n    rbp = (struct bootp_t *)m->m_data;\n    m->m_data += sizeof(struct udpiphdr);\n    memset(rbp, 0, sizeof(struct bootp_t));\n\n    if (dhcp_msg_type == DHCPDISCOVER) {\n        if (preq_addr.s_addr != htonl(0L)) {\n            bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);\n            if (bc) {\n                daddr.sin_addr = preq_addr;\n            }\n        }\n        if (!bc) {\n         new_addr:\n            bc = get_new_addr(slirp, &daddr.sin_addr, slirp->client_ethaddr);\n            if (!bc) {\n                DPRINTF(\"no address left\\n\");\n                return;\n            }\n        }\n        memcpy(bc->macaddr, slirp->client_ethaddr, 6);\n    } else if (preq_addr.s_addr != htonl(0L)) {\n        bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);\n        if (bc) {\n            daddr.sin_addr = preq_addr;\n            memcpy(bc->macaddr, slirp->client_ethaddr, 6);\n        } else {\n            daddr.sin_addr.s_addr = 0;\n        }\n    } else {\n        bc = find_addr(slirp, &daddr.sin_addr, bp->bp_hwaddr);\n        if (!bc) {\n            /* if never assigned, behaves as if it was already\n               assigned (windows fix because it remembers its address) */\n            goto new_addr;\n        }\n    }\n\n    saddr.sin_addr = slirp->vhost_addr;\n    saddr.sin_port = htons(BOOTP_SERVER);\n\n    daddr.sin_port = htons(BOOTP_CLIENT);\n\n    rbp->bp_op = BOOTP_REPLY;\n    rbp->bp_xid = bp->bp_xid;\n    rbp->bp_htype = 1;\n    rbp->bp_hlen = 6;\n    memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6);\n\n    rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */\n    rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */\n\n    q = rbp->bp_vend;\n    memcpy(q, rfc1533_cookie, 4);\n    q += 4;\n\n    if (bc) {\n        DPRINTF(\"%s addr=%08x\\n\",\n                (dhcp_msg_type == DHCPDISCOVER) ? \"offered\" : \"ack'ed\",\n                ntohl(daddr.sin_addr.s_addr));\n\n        if (dhcp_msg_type == DHCPDISCOVER) {\n            *q++ = RFC2132_MSG_TYPE;\n            *q++ = 1;\n            *q++ = DHCPOFFER;\n        } else /* DHCPREQUEST */ {\n            *q++ = RFC2132_MSG_TYPE;\n            *q++ = 1;\n            *q++ = DHCPACK;\n        }\n\n        if (slirp->bootp_filename)\n            snprintf((char *)rbp->bp_file, sizeof(rbp->bp_file), \"%s\",\n                     slirp->bootp_filename);\n\n        *q++ = RFC2132_SRV_ID;\n        *q++ = 4;\n        memcpy(q, &saddr.sin_addr, 4);\n        q += 4;\n\n        *q++ = RFC1533_NETMASK;\n        *q++ = 4;\n        memcpy(q, &slirp->vnetwork_mask, 4);\n        q += 4;\n\n        if (!slirp->restricted) {\n            *q++ = RFC1533_GATEWAY;\n            *q++ = 4;\n            memcpy(q, &saddr.sin_addr, 4);\n            q += 4;\n\n            *q++ = RFC1533_DNS;\n            *q++ = 4;\n            memcpy(q, &slirp->vnameserver_addr, 4);\n            q += 4;\n        }\n\n        *q++ = RFC2132_LEASE_TIME;\n        *q++ = 4;\n        val = htonl(LEASE_TIME);\n        memcpy(q, &val, 4);\n        q += 4;\n\n        if (*slirp->client_hostname) {\n            val = strlen(slirp->client_hostname);\n            *q++ = RFC1533_HOSTNAME;\n            *q++ = val;\n            memcpy(q, slirp->client_hostname, val);\n            q += val;\n        }\n    } else {\n        static const char nak_msg[] = \"requested address not available\";\n\n        DPRINTF(\"nak'ed addr=%08x\\n\", ntohl(preq_addr->s_addr));\n\n        *q++ = RFC2132_MSG_TYPE;\n        *q++ = 1;\n        *q++ = DHCPNAK;\n\n        *q++ = RFC2132_MESSAGE;\n        *q++ = sizeof(nak_msg) - 1;\n        memcpy(q, nak_msg, sizeof(nak_msg) - 1);\n        q += sizeof(nak_msg) - 1;\n    }\n    *q = RFC1533_END;\n\n    daddr.sin_addr.s_addr = 0xffffffffu;\n\n    m->m_len = sizeof(struct bootp_t) -\n        sizeof(struct ip) - sizeof(struct udphdr);\n    udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);\n}\n\nvoid bootp_input(struct mbuf *m)\n{\n    struct bootp_t *bp = mtod(m, struct bootp_t *);\n\n    if (bp->bp_op == BOOTP_REQUEST) {\n        bootp_reply(m->slirp, bp);\n    }\n}\n"
  },
  {
    "path": "src/slirp/bootp.h",
    "content": "/* bootp/dhcp defines */\n\n#define BOOTP_SERVER\t67\n#define BOOTP_CLIENT\t68\n\n#define BOOTP_REQUEST\t1\n#define BOOTP_REPLY\t2\n\n#define RFC1533_COOKIE\t\t99, 130, 83, 99\n#define RFC1533_PAD\t\t0\n#define RFC1533_NETMASK\t\t1\n#define RFC1533_TIMEOFFSET\t2\n#define RFC1533_GATEWAY\t\t3\n#define RFC1533_TIMESERVER\t4\n#define RFC1533_IEN116NS\t5\n#define RFC1533_DNS\t\t6\n#define RFC1533_LOGSERVER\t7\n#define RFC1533_COOKIESERVER\t8\n#define RFC1533_LPRSERVER\t9\n#define RFC1533_IMPRESSSERVER\t10\n#define RFC1533_RESOURCESERVER\t11\n#define RFC1533_HOSTNAME\t12\n#define RFC1533_BOOTFILESIZE\t13\n#define RFC1533_MERITDUMPFILE\t14\n#define RFC1533_DOMAINNAME\t15\n#define RFC1533_SWAPSERVER\t16\n#define RFC1533_ROOTPATH\t17\n#define RFC1533_EXTENSIONPATH\t18\n#define RFC1533_IPFORWARDING\t19\n#define RFC1533_IPSOURCEROUTING\t20\n#define RFC1533_IPPOLICYFILTER\t21\n#define RFC1533_IPMAXREASSEMBLY\t22\n#define RFC1533_IPTTL\t\t23\n#define RFC1533_IPMTU\t\t24\n#define RFC1533_IPMTUPLATEAU\t25\n#define RFC1533_INTMTU\t\t26\n#define RFC1533_INTLOCALSUBNETS\t27\n#define RFC1533_INTBROADCAST\t28\n#define RFC1533_INTICMPDISCOVER\t29\n#define RFC1533_INTICMPRESPOND\t30\n#define RFC1533_INTROUTEDISCOVER 31\n#define RFC1533_INTROUTESOLICIT\t32\n#define RFC1533_INTSTATICROUTES\t33\n#define RFC1533_LLTRAILERENCAP\t34\n#define RFC1533_LLARPCACHETMO\t35\n#define RFC1533_LLETHERNETENCAP\t36\n#define RFC1533_TCPTTL\t\t37\n#define RFC1533_TCPKEEPALIVETMO\t38\n#define RFC1533_TCPKEEPALIVEGB\t39\n#define RFC1533_NISDOMAIN\t40\n#define RFC1533_NISSERVER\t41\n#define RFC1533_NTPSERVER\t42\n#define RFC1533_VENDOR\t\t43\n#define RFC1533_NBNS\t\t44\n#define RFC1533_NBDD\t\t45\n#define RFC1533_NBNT\t\t46\n#define RFC1533_NBSCOPE\t\t47\n#define RFC1533_XFS\t\t48\n#define RFC1533_XDM\t\t49\n\n#define RFC2132_REQ_ADDR\t50\n#define RFC2132_LEASE_TIME      51\n#define RFC2132_MSG_TYPE\t53\n#define RFC2132_SRV_ID\t\t54\n#define RFC2132_PARAM_LIST\t55\n#define RFC2132_MESSAGE\t\t56\n#define RFC2132_MAX_SIZE\t57\n#define RFC2132_RENEWAL_TIME    58\n#define RFC2132_REBIND_TIME     59\n\n#define DHCPDISCOVER\t\t1\n#define DHCPOFFER\t\t2\n#define DHCPREQUEST\t\t3\n#define DHCPACK\t\t\t5\n#define DHCPNAK\t\t\t6\n\n#define RFC1533_VENDOR_MAJOR\t0\n#define RFC1533_VENDOR_MINOR\t0\n\n#define RFC1533_VENDOR_MAGIC\t128\n#define RFC1533_VENDOR_ADDPARM\t129\n#define\tRFC1533_VENDOR_ETHDEV\t130\n#define RFC1533_VENDOR_HOWTO    132\n#define RFC1533_VENDOR_MNUOPTS\t160\n#define RFC1533_VENDOR_SELECTION 176\n#define RFC1533_VENDOR_MOTD\t184\n#define RFC1533_VENDOR_NUMOFMOTD 8\n#define RFC1533_VENDOR_IMG\t192\n#define RFC1533_VENDOR_NUMOFIMG\t16\n\n#define RFC1533_END\t\t255\n#define BOOTP_VENDOR_LEN\t64\n#define DHCP_OPT_LEN\t\t312\n\nstruct bootp_t {\n    struct ip ip;\n    struct udphdr udp;\n    uint8_t bp_op;\n    uint8_t bp_htype;\n    uint8_t bp_hlen;\n    uint8_t bp_hops;\n    uint32_t bp_xid;\n    uint16_t bp_secs;\n    uint16_t unused;\n    struct in_addr bp_ciaddr;\n    struct in_addr bp_yiaddr;\n    struct in_addr bp_siaddr;\n    struct in_addr bp_giaddr;\n    uint8_t bp_hwaddr[16];\n    uint8_t bp_sname[64];\n    uint8_t bp_file[128];\n    uint8_t bp_vend[DHCP_OPT_LEN];\n};\n\ntypedef struct {\n    uint16_t allocated;\n    uint8_t macaddr[6];\n} BOOTPClient;\n\n#define NB_BOOTP_CLIENTS 16\n\nvoid bootp_input(struct mbuf *m);\n"
  },
  {
    "path": "src/slirp/cksum.c",
    "content": "/*\n * Copyright (c) 1988, 1992, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)in_cksum.c\t8.1 (Berkeley) 6/10/93\n * in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp\n */\n\n#include \"slirp.h\"\n\n/*\n * Checksum routine for Internet Protocol family headers (Portable Version).\n *\n * This routine is very heavily used in the network\n * code and should be modified for each CPU to be as fast as possible.\n *\n * XXX Since we will never span more than 1 mbuf, we can optimise this\n */\n\n#define ADDCARRY(x)  (x > 65535 ? x -= 65535 : x)\n#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1];        \\\n        (void)ADDCARRY(sum);}\n\nint cksum(struct mbuf *m, int len)\n{\n\tregister uint16_t *w;\n\tregister int sum = 0;\n\tregister int mlen = 0;\n\tint byte_swapped = 0;\n\n\tunion {\n\t\tuint8_t  c[2];\n\t\tuint16_t s;\n\t} s_util;\n\tunion {\n\t\tuint16_t s[2];\n\t\tuint32_t l;\n\t} l_util;\n\n\tif (m->m_len == 0)\n\t   goto cont;\n\tw = mtod(m, uint16_t *);\n\n\tmlen = m->m_len;\n\n\tif (len < mlen)\n\t   mlen = len;\n#ifdef DEBUG\n\tlen -= mlen;\n#endif\n\t/*\n\t * Force to even boundary.\n\t */\n\tif ((1 & (long) w) && (mlen > 0)) {\n\t\tREDUCE;\n\t\tsum <<= 8;\n\t\ts_util.c[0] = *(uint8_t *)w;\n\t\tw = (uint16_t *)((int8_t *)w + 1);\n\t\tmlen--;\n\t\tbyte_swapped = 1;\n\t}\n\t/*\n\t * Unroll the loop to make overhead from\n\t * branches &c small.\n\t */\n\twhile ((mlen -= 32) >= 0) {\n\t\tsum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];\n\t\tsum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];\n\t\tsum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];\n\t\tsum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];\n\t\tw += 16;\n\t}\n\tmlen += 32;\n\twhile ((mlen -= 8) >= 0) {\n\t\tsum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];\n\t\tw += 4;\n\t}\n\tmlen += 8;\n\tif (mlen == 0 && byte_swapped == 0)\n\t   goto cont;\n\tREDUCE;\n\twhile ((mlen -= 2) >= 0) {\n\t\tsum += *w++;\n\t}\n\n\tif (byte_swapped) {\n\t\tREDUCE;\n\t\tsum <<= 8;\n\t\tif (mlen == -1) {\n\t\t\ts_util.c[1] = *(uint8_t *)w;\n\t\t\tsum += s_util.s;\n\t\t\tmlen = 0;\n\t\t} else\n\n\t\t   mlen = -1;\n\t} else if (mlen == -1)\n\t   s_util.c[0] = *(uint8_t *)w;\n\ncont:\n#ifdef DEBUG\n\tif (len) {\n\t\tDEBUG_ERROR((dfd, \"cksum: out of data\\n\"));\n\t\tDEBUG_ERROR((dfd, \" len = %d\\n\", len));\n\t}\n#endif\n\tif (mlen == -1) {\n\t\t/* The last mbuf has odd # of bytes. Follow the\n\t\t standard (the odd byte may be shifted left by 8 bits\n\t\t\t   or not as determined by endian-ness of the machine) */\n\t\ts_util.c[1] = 0;\n\t\tsum += s_util.s;\n\t}\n\tREDUCE;\n\treturn (~sum & 0xffff);\n}\n"
  },
  {
    "path": "src/slirp/debug.h",
    "content": "/*\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n//#define DEBUG 1\n\n#ifdef DEBUG\n\n#define DBG_CALL 0x1\n#define DBG_MISC 0x2\n#define DBG_ERROR 0x4\n\n#define dfd stderr\n\nextern int slirp_debug;\n\n#define DEBUG_CALL(x) if (slirp_debug & DBG_CALL) { fprintf(dfd, \"%s...\\n\", x); fflush(dfd); }\n#define DEBUG_ARG(x, y) if (slirp_debug & DBG_CALL) { fputc(' ', dfd); fprintf(dfd, x, y); fputc('\\n', dfd); fflush(dfd); }\n#define DEBUG_ARGS(x) if (slirp_debug & DBG_CALL) { fprintf x ; fflush(dfd); }\n#define DEBUG_MISC(x) if (slirp_debug & DBG_MISC) { fprintf x ; fflush(dfd); }\n#define DEBUG_ERROR(x) if (slirp_debug & DBG_ERROR) {fprintf x ; fflush(dfd); }\n\n#else\n\n#define DEBUG_CALL(x)\n#define DEBUG_ARG(x, y)\n#define DEBUG_ARGS(x)\n#define DEBUG_MISC(x)\n#define DEBUG_ERROR(x)\n\n#endif\n"
  },
  {
    "path": "src/slirp/if.c",
    "content": "/*\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#include \"slirp.h\"\n\n#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))\n\nstatic void\nifs_insque(struct mbuf *ifm, struct mbuf *ifmhead)\n{\n\tifm->ifs_next = ifmhead->ifs_next;\n\tifmhead->ifs_next = ifm;\n\tifm->ifs_prev = ifmhead;\n\tifm->ifs_next->ifs_prev = ifm;\n}\n\nstatic void\nifs_remque(struct mbuf *ifm)\n{\n\tifm->ifs_prev->ifs_next = ifm->ifs_next;\n\tifm->ifs_next->ifs_prev = ifm->ifs_prev;\n}\n\nvoid\nif_init(Slirp *slirp)\n{\n    slirp->if_fastq.ifq_next = slirp->if_fastq.ifq_prev = &slirp->if_fastq;\n    slirp->if_batchq.ifq_next = slirp->if_batchq.ifq_prev = &slirp->if_batchq;\n    slirp->next_m = &slirp->if_batchq;\n}\n\n/*\n * if_output: Queue packet into an output queue.\n * There are 2 output queue's, if_fastq and if_batchq.\n * Each output queue is a doubly linked list of double linked lists\n * of mbufs, each list belonging to one \"session\" (socket).  This\n * way, we can output packets fairly by sending one packet from each\n * session, instead of all the packets from one session, then all packets\n * from the next session, etc.  Packets on the if_fastq get absolute\n * priority, but if one session hogs the link, it gets \"downgraded\"\n * to the batchq until it runs out of packets, then it'll return\n * to the fastq (eg. if the user does an ls -alR in a telnet session,\n * it'll temporarily get downgraded to the batchq)\n */\nvoid\nif_output(struct socket *so, struct mbuf *ifm)\n{\n\tSlirp *slirp = ifm->slirp;\n\tstruct mbuf *ifq;\n\tint on_fastq = 1;\n\n\tDEBUG_CALL(\"if_output\");\n\tDEBUG_ARG(\"so = %lx\", (long)so);\n\tDEBUG_ARG(\"ifm = %lx\", (long)ifm);\n\n\t/*\n\t * First remove the mbuf from m_usedlist,\n\t * since we're gonna use m_next and m_prev ourselves\n\t * XXX Shouldn't need this, gotta change dtom() etc.\n\t */\n\tif (ifm->m_flags & M_USEDLIST) {\n\t\tremque(ifm);\n\t\tifm->m_flags &= ~M_USEDLIST;\n\t}\n\n\t/*\n\t * See if there's already a batchq list for this session.\n\t * This can include an interactive session, which should go on fastq,\n\t * but gets too greedy... hence it'll be downgraded from fastq to batchq.\n\t * We mustn't put this packet back on the fastq (or we'll send it out of order)\n\t * XXX add cache here?\n\t */\n\tfor (ifq = slirp->if_batchq.ifq_prev; ifq != &slirp->if_batchq;\n\t     ifq = ifq->ifq_prev) {\n\t\tif (so == ifq->ifq_so) {\n\t\t\t/* A match! */\n\t\t\tifm->ifq_so = so;\n\t\t\tifs_insque(ifm, ifq->ifs_prev);\n\t\t\tgoto diddit;\n\t\t}\n\t}\n\n\t/* No match, check which queue to put it on */\n\tif (so && (so->so_iptos & IPTOS_LOWDELAY)) {\n\t\tifq = slirp->if_fastq.ifq_prev;\n\t\ton_fastq = 1;\n\t\t/*\n\t\t * Check if this packet is a part of the last\n\t\t * packet's session\n\t\t */\n\t\tif (ifq->ifq_so == so) {\n\t\t\tifm->ifq_so = so;\n\t\t\tifs_insque(ifm, ifq->ifs_prev);\n\t\t\tgoto diddit;\n\t\t}\n\t} else\n\t\tifq = slirp->if_batchq.ifq_prev;\n\n\t/* Create a new doubly linked list for this session */\n\tifm->ifq_so = so;\n\tifs_init(ifm);\n\tinsque(ifm, ifq);\n\ndiddit:\n\tslirp->if_queued++;\n\n\tif (so) {\n\t\t/* Update *_queued */\n\t\tso->so_queued++;\n\t\tso->so_nqueued++;\n\t\t/*\n\t\t * Check if the interactive session should be downgraded to\n\t\t * the batchq.  A session is downgraded if it has queued 6\n\t\t * packets without pausing, and at least 3 of those packets\n\t\t * have been sent over the link\n\t\t * (XXX These are arbitrary numbers, probably not optimal..)\n\t\t */\n\t\tif (on_fastq && ((so->so_nqueued >= 6) &&\n\t\t\t\t (so->so_nqueued - so->so_queued) >= 3)) {\n\n\t\t\t/* Remove from current queue... */\n\t\t\tremque(ifm->ifs_next);\n\n\t\t\t/* ...And insert in the new.  That'll teach ya! */\n\t\t\tinsque(ifm->ifs_next, &slirp->if_batchq);\n\t\t}\n\t}\n\n#ifndef FULL_BOLT\n\t/*\n\t * This prevents us from malloc()ing too many mbufs\n\t */\n\tif_start(ifm->slirp);\n#endif\n}\n\n/*\n * Send a packet\n * We choose a packet based on it's position in the output queues;\n * If there are packets on the fastq, they are sent FIFO, before\n * everything else.  Otherwise we choose the first packet from the\n * batchq and send it.  the next packet chosen will be from the session\n * after this one, then the session after that one, and so on..  So,\n * for example, if there are 3 ftp session's fighting for bandwidth,\n * one packet will be sent from the first session, then one packet\n * from the second session, then one packet from the third, then back\n * to the first, etc. etc.\n */\nvoid\nif_start(Slirp *slirp)\n{\n\tstruct mbuf *ifm, *ifqt;\n\n\tDEBUG_CALL(\"if_start\");\n\n\tif (slirp->if_queued == 0)\n\t   return; /* Nothing to do */\n\n again:\n        /* check if we can really output */\n        if (!slirp_can_output(slirp->opaque))\n            return;\n\n\t/*\n\t * See which queue to get next packet from\n\t * If there's something in the fastq, select it immediately\n\t */\n\tif (slirp->if_fastq.ifq_next != &slirp->if_fastq) {\n\t\tifm = slirp->if_fastq.ifq_next;\n\t} else {\n\t\t/* Nothing on fastq, see if next_m is valid */\n\t\tif (slirp->next_m != &slirp->if_batchq)\n\t\t   ifm = slirp->next_m;\n\t\telse\n\t\t   ifm = slirp->if_batchq.ifq_next;\n\n\t\t/* Set which packet to send on next iteration */\n\t\tslirp->next_m = ifm->ifq_next;\n\t}\n\t/* Remove it from the queue */\n\tifqt = ifm->ifq_prev;\n\tremque(ifm);\n\tslirp->if_queued--;\n\n\t/* If there are more packets for this session, re-queue them */\n\tif (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {\n\t\tinsque(ifm->ifs_next, ifqt);\n\t\tifs_remque(ifm);\n\t}\n\n\t/* Update so_queued */\n\tif (ifm->ifq_so) {\n\t\tif (--ifm->ifq_so->so_queued == 0)\n\t\t   /* If there's no more queued, reset nqueued */\n\t\t   ifm->ifq_so->so_nqueued = 0;\n\t}\n\n\t/* Encapsulate the packet for sending */\n        if_encap(slirp, (uint8_t *)ifm->m_data, ifm->m_len);\n\n        m_free(ifm);\n\n\tif (slirp->if_queued)\n\t   goto again;\n}\n"
  },
  {
    "path": "src/slirp/if.h",
    "content": "/*\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#ifndef _IF_H_\n#define _IF_H_\n\n#define IF_COMPRESS\t0x01\t/* We want compression */\n#define IF_NOCOMPRESS\t0x02\t/* Do not do compression */\n#define IF_AUTOCOMP\t0x04\t/* Autodetect (default) */\n#define IF_NOCIDCOMP\t0x08\t/* CID compression */\n\n#define IF_MTU 1500\n#define IF_MRU 1500\n#define\tIF_COMP IF_AUTOCOMP\t/* Flags for compression */\n\n/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */\n#define IF_MAXLINKHDR (2 + 14 + 40)\n\n#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))\n\n#endif\n"
  },
  {
    "path": "src/slirp/ip.h",
    "content": "/*\n * Copyright (c) 1982, 1986, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)ip.h\t8.1 (Berkeley) 6/10/93\n * ip.h,v 1.3 1994/08/21 05:27:30 paul Exp\n */\n\n#ifndef _IP_H_\n#define _IP_H_\n\n#ifdef HOST_WORDS_BIGENDIAN\n# ifndef NTOHL\n#  define NTOHL(d)\n# endif\n# ifndef NTOHS\n#  define NTOHS(d)\n# endif\n# ifndef HTONL\n#  define HTONL(d)\n# endif\n# ifndef HTONS\n#  define HTONS(d)\n# endif\n#else\n# ifndef NTOHL\n#  define NTOHL(d) ((d) = ntohl((d)))\n# endif\n# ifndef NTOHS\n#  define NTOHS(d) ((d) = ntohs((uint16_t)(d)))\n# endif\n# ifndef HTONL\n#  define HTONL(d) ((d) = htonl((d)))\n# endif\n# ifndef HTONS\n#  define HTONS(d) ((d) = htons((uint16_t)(d)))\n# endif\n#endif\n\ntypedef uint32_t n_long;                 /* long as received from the net */\n\n/*\n * Definitions for internet protocol version 4.\n * Per RFC 791, September 1981.\n */\n#define\tIPVERSION\t4\n\n/*\n * Structure of an internet header, naked of options.\n */\nstruct ip {\n#ifdef HOST_WORDS_BIGENDIAN\n\tu_int ip_v:4,\t\t\t/* version */\n\t\tip_hl:4;\t\t/* header length */\n#else\n\tu_int ip_hl:4,\t\t/* header length */\n\t\tip_v:4;\t\t\t/* version */\n#endif\n\tuint8_t\t\tip_tos;\t\t\t/* type of service */\n\tuint16_t\tip_len;\t\t\t/* total length */\n\tuint16_t\tip_id;\t\t\t/* identification */\n\tuint16_t\tip_off;\t\t\t/* fragment offset field */\n#define\tIP_DF 0x4000\t\t\t/* don't fragment flag */\n#define\tIP_MF 0x2000\t\t\t/* more fragments flag */\n#define\tIP_OFFMASK 0x1fff\t\t/* mask for fragmenting bits */\n\tuint8_t ip_ttl;\t\t\t/* time to live */\n\tuint8_t ip_p;\t\t\t/* protocol */\n\tuint16_t\tip_sum;\t\t\t/* checksum */\n\tstruct\tin_addr ip_src,ip_dst;\t/* source and dest address */\n} __attribute__((packed));\n\n#define\tIP_MAXPACKET\t65535\t\t/* maximum packet size */\n\n/*\n * Definitions for IP type of service (ip_tos)\n */\n#define\tIPTOS_LOWDELAY\t\t0x10\n#define\tIPTOS_THROUGHPUT\t0x08\n#define\tIPTOS_RELIABILITY\t0x04\n\n/*\n * Definitions for options.\n */\n#define\tIPOPT_COPIED(o)\t\t((o)&0x80)\n#define\tIPOPT_CLASS(o)\t\t((o)&0x60)\n#define\tIPOPT_NUMBER(o)\t\t((o)&0x1f)\n\n#define\tIPOPT_CONTROL\t\t0x00\n#define\tIPOPT_RESERVED1\t\t0x20\n#define\tIPOPT_DEBMEAS\t\t0x40\n#define\tIPOPT_RESERVED2\t\t0x60\n\n#define\tIPOPT_EOL\t\t0\t\t/* end of option list */\n#define\tIPOPT_NOP\t\t1\t\t/* no operation */\n\n#define\tIPOPT_RR\t\t7\t\t/* record packet route */\n#define\tIPOPT_TS\t\t68\t\t/* timestamp */\n#define\tIPOPT_SECURITY\t\t130\t\t/* provide s,c,h,tcc */\n#define\tIPOPT_LSRR\t\t131\t\t/* loose source route */\n#define\tIPOPT_SATID\t\t136\t\t/* satnet id */\n#define\tIPOPT_SSRR\t\t137\t\t/* strict source route */\n\n/*\n * Offsets to fields in options other than EOL and NOP.\n */\n#define\tIPOPT_OPTVAL\t\t0\t\t/* option ID */\n#define\tIPOPT_OLEN\t\t1\t\t/* option length */\n#define IPOPT_OFFSET\t\t2\t\t/* offset within option */\n#define\tIPOPT_MINOFF\t\t4\t\t/* min value of above */\n\n/*\n * Time stamp option structure.\n */\nstruct\tip_timestamp {\n\tuint8_t\tipt_code;\t\t/* IPOPT_TS */\n\tuint8_t\tipt_len;\t\t/* size of structure (variable) */\n\tuint8_t\tipt_ptr;\t\t/* index of current entry */\n#ifdef HOST_WORDS_BIGENDIAN\n\tu_int\tipt_oflw:4,\t\t/* overflow counter */\n\t\tipt_flg:4;\t\t/* flags, see below */\n#else\n\tu_int\tipt_flg:4,\t\t/* flags, see below */\n\t\tipt_oflw:4;\t\t/* overflow counter */\n#endif\n\tunion ipt_timestamp {\n\t\tn_long\tipt_time[1];\n\t\tstruct\tipt_ta {\n\t\t\tstruct in_addr ipt_addr;\n\t\t\tn_long ipt_time;\n\t\t} ipt_ta[1];\n\t} ipt_timestamp;\n} __attribute__((packed));\n\n/* flag bits for ipt_flg */\n#define\tIPOPT_TS_TSONLY\t\t0\t\t/* timestamps only */\n#define\tIPOPT_TS_TSANDADDR\t1\t\t/* timestamps and addresses */\n#define\tIPOPT_TS_PRESPEC\t3\t\t/* specified modules only */\n\n/* bits for security (not byte swapped) */\n#define\tIPOPT_SECUR_UNCLASS\t0x0000\n#define\tIPOPT_SECUR_CONFID\t0xf135\n#define\tIPOPT_SECUR_EFTO\t0x789a\n#define\tIPOPT_SECUR_MMMM\t0xbc4d\n#define\tIPOPT_SECUR_RESTR\t0xaf13\n#define\tIPOPT_SECUR_SECRET\t0xd788\n#define\tIPOPT_SECUR_TOPSECRET\t0x6bc5\n\n/*\n * Internet implementation parameters.\n */\n#define\tMAXTTL\t\t255\t\t/* maximum time to live (seconds) */\n#define\tIPDEFTTL\t64\t\t/* default ttl, from RFC 1340 */\n#define\tIPFRAGTTL\t60\t\t/* time to live for frags, slowhz */\n#define\tIPTTLDEC\t1\t\t/* subtracted when forwarding */\n\n#define\tIP_MSS\t\t576\t\t/* default maximum segment size */\n\n#if SIZEOF_CHAR_P == 4\nstruct mbuf_ptr {\n\tstruct mbuf *mptr;\n\tuint32_t dummy;\n} __attribute__((packed));\n#else\nstruct mbuf_ptr {\n\tstruct mbuf *mptr;\n} __attribute__((packed));\n#endif\nstruct qlink {\n\tvoid *next, *prev;\n};\n\n/*\n * Overlay for ip header used by other protocols (tcp, udp).\n */\nstruct ipovly {\n\tstruct mbuf_ptr ih_mbuf;\t/* backpointer to mbuf */\n\tuint8_t\tih_x1;\t\t\t/* (unused) */\n\tuint8_t\tih_pr;\t\t\t/* protocol */\n\tuint16_t\tih_len;\t\t\t/* protocol length */\n\tstruct\tin_addr ih_src;\t\t/* source internet address */\n\tstruct\tin_addr ih_dst;\t\t/* destination internet address */\n} __attribute__((packed));\n\n/*\n * Ip reassembly queue structure.  Each fragment\n * being reassembled is attached to one of these structures.\n * They are timed out after ipq_ttl drops to 0, and may also\n * be reclaimed if memory becomes tight.\n * size 28 bytes\n */\nstruct ipq {\n        struct qlink frag_link;\t\t\t/* to ip headers of fragments */\n\tstruct qlink ip_link;\t\t\t\t/* to other reass headers */\n\tuint8_t\tipq_ttl;\t\t/* time for reass q to live */\n\tuint8_t\tipq_p;\t\t\t/* protocol of this fragment */\n\tuint16_t\tipq_id;\t\t\t/* sequence id for reassembly */\n\tstruct\tin_addr ipq_src,ipq_dst;\n} __attribute__((packed));\n\n/*\n * Ip header, when holding a fragment.\n *\n * Note: ipf_link must be at same offset as frag_link above\n */\nstruct\tipasfrag {\n\tstruct qlink ipf_link;\n\tstruct ip ipf_ip;\n} __attribute__((packed));\n\n#define ipf_off      ipf_ip.ip_off\n#define ipf_tos      ipf_ip.ip_tos\n#define ipf_len      ipf_ip.ip_len\n#define ipf_next     ipf_link.next\n#define ipf_prev     ipf_link.prev\n\n/*\n * Structure stored in mbuf in inpcb.ip_options\n * and passed to ip_output when ip options are in use.\n * The actual length of the options (including ipopt_dst)\n * is in m_len.\n */\n#define MAX_IPOPTLEN\t40\n\nstruct ipoption {\n\tstruct\tin_addr ipopt_dst;\t/* first-hop dst if source routed */\n\tint8_t\tipopt_list[MAX_IPOPTLEN];\t/* options proper */\n} __attribute__((packed));\n\n#endif\n"
  },
  {
    "path": "src/slirp/ip_icmp.c",
    "content": "/*\n * Copyright (c) 1982, 1986, 1988, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)ip_icmp.c\t8.2 (Berkeley) 1/4/94\n * ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp\n */\n\n#include \"slirp.h\"\n#include \"ip_icmp.h\"\n\n/* The message sent when emulating PING */\n/* Be nice and tell them it's just a pseudo-ping packet */\nstatic const char icmp_ping_msg[] = \"This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\\n\";\n\n/* list of actions for icmp_error() on RX of an icmp message */\nstatic const int icmp_flush[19] = {\n/*  ECHO REPLY (0)  */   0,\n\t\t         1,\n\t\t         1,\n/* DEST UNREACH (3) */   1,\n/* SOURCE QUENCH (4)*/   1,\n/* REDIRECT (5) */       1,\n\t\t         1,\n\t\t         1,\n/* ECHO (8) */           0,\n/* ROUTERADVERT (9) */   1,\n/* ROUTERSOLICIT (10) */ 1,\n/* TIME EXCEEDED (11) */ 1,\n/* PARAMETER PROBLEM (12) */ 1,\n/* TIMESTAMP (13) */     0,\n/* TIMESTAMP REPLY (14) */ 0,\n/* INFO (15) */          0,\n/* INFO REPLY (16) */    0,\n/* ADDR MASK (17) */     0,\n/* ADDR MASK REPLY (18) */ 0\n};\n\n/*\n * Process a received ICMP message.\n */\nvoid\nicmp_input(struct mbuf *m, int hlen)\n{\n  register struct icmp *icp;\n  register struct ip *ip=mtod(m, struct ip *);\n  int icmplen=ip->ip_len;\n  Slirp *slirp = m->slirp;\n\n  DEBUG_CALL(\"icmp_input\");\n  DEBUG_ARG(\"m = %lx\", (long )m);\n  DEBUG_ARG(\"m_len = %d\", m->m_len);\n\n  /*\n   * Locate icmp structure in mbuf, and check\n   * that its not corrupted and of at least minimum length.\n   */\n  if (icmplen < ICMP_MINLEN) {          /* min 8 bytes payload */\n  freeit:\n    m_freem(m);\n    goto end_error;\n  }\n\n  m->m_len -= hlen;\n  m->m_data += hlen;\n  icp = mtod(m, struct icmp *);\n  if (cksum(m, icmplen)) {\n    goto freeit;\n  }\n  m->m_len += hlen;\n  m->m_data -= hlen;\n\n  DEBUG_ARG(\"icmp_type = %d\", icp->icmp_type);\n  switch (icp->icmp_type) {\n  case ICMP_ECHO:\n    icp->icmp_type = ICMP_ECHOREPLY;\n    ip->ip_len += hlen;\t             /* since ip_input subtracts this */\n    if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {\n      icmp_reflect(m);\n    } else {\n      struct socket *so;\n      struct sockaddr_in addr;\n      if ((so = socreate(slirp)) == NULL) goto freeit;\n      if(udp_attach(so) == -1) {\n\tDEBUG_MISC((dfd,\"icmp_input udp_attach errno = %d-%s\\n\",\n\t\t    errno,strerror(errno)));\n\tsofree(so);\n\tm_free(m);\n\tgoto end_error;\n      }\n      so->so_m = m;\n      so->so_faddr = ip->ip_dst;\n      so->so_fport = htons(7);\n      so->so_laddr = ip->ip_src;\n      so->so_lport = htons(9);\n      so->so_iptos = ip->ip_tos;\n      so->so_type = IPPROTO_ICMP;\n      so->so_state = SS_ISFCONNECTED;\n\n      /* Send the packet */\n      addr.sin_family = AF_INET;\n      if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==\n          slirp->vnetwork_addr.s_addr) {\n\t/* It's an alias */\n\tif (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {\n\t  if (get_dns_addr(&addr.sin_addr) < 0)\n\t    addr.sin_addr = loopback_addr;\n\t} else {\n\t  addr.sin_addr = loopback_addr;\n\t}\n      } else {\n\taddr.sin_addr = so->so_faddr;\n      }\n      addr.sin_port = so->so_fport;\n      if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,\n\t\t(struct sockaddr *)&addr, sizeof(addr)) == -1) {\n\tDEBUG_MISC((dfd,\"icmp_input udp sendto tx errno = %d-%s\\n\",\n\t\t    errno,strerror(errno)));\n\ticmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));\n\tudp_detach(so);\n      }\n    } /* if ip->ip_dst.s_addr == alias_addr.s_addr */\n    break;\n  case ICMP_UNREACH:\n    /* XXX? report error? close socket? */\n  case ICMP_TIMXCEED:\n  case ICMP_PARAMPROB:\n  case ICMP_SOURCEQUENCH:\n  case ICMP_TSTAMP:\n  case ICMP_MASKREQ:\n  case ICMP_REDIRECT:\n    m_freem(m);\n    break;\n\n  default:\n    m_freem(m);\n  } /* swith */\n\nend_error:\n  /* m is m_free()'d xor put in a socket xor or given to ip_send */\n  return;\n}\n\n\n/*\n *\tSend an ICMP message in response to a situation\n *\n *\tRFC 1122: 3.2.2\tMUST send at least the IP header and 8 bytes of header. MAY send more (we do).\n *\t\t\tMUST NOT change this header information.\n *\t\t\tMUST NOT reply to a multicast/broadcast IP address.\n *\t\t\tMUST NOT reply to a multicast/broadcast MAC address.\n *\t\t\tMUST reply to only the first fragment.\n */\n/*\n * Send ICMP_UNREACH back to the source regarding msrc.\n * mbuf *msrc is used as a template, but is NOT m_free()'d.\n * It is reported as the bad ip packet.  The header should\n * be fully correct and in host byte order.\n * ICMP fragmentation is illegal.  All machines must accept 576 bytes in one\n * packet.  The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548\n */\n\n#define ICMP_MAXDATALEN (IP_MSS-28)\nvoid\nicmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,\n           const char *message)\n{\n  unsigned hlen, shlen, s_ip_len;\n  register struct ip *ip;\n  register struct icmp *icp;\n  register struct mbuf *m;\n\n  DEBUG_CALL(\"icmp_error\");\n  DEBUG_ARG(\"msrc = %lx\", (long )msrc);\n  DEBUG_ARG(\"msrc_len = %d\", msrc->m_len);\n\n  if(type!=ICMP_UNREACH && type!=ICMP_TIMXCEED) goto end_error;\n\n  /* check msrc */\n  if(!msrc) goto end_error;\n  ip = mtod(msrc, struct ip *);\n#ifdef DEBUG\n  { char bufa[20], bufb[20];\n    strcpy(bufa, inet_ntoa(ip->ip_src));\n    strcpy(bufb, inet_ntoa(ip->ip_dst));\n    DEBUG_MISC((dfd, \" %.16s to %.16s\\n\", bufa, bufb));\n  }\n#endif\n  if(ip->ip_off & IP_OFFMASK) goto end_error;    /* Only reply to fragment 0 */\n\n  shlen=ip->ip_hl << 2;\n  s_ip_len=ip->ip_len;\n  if(ip->ip_p == IPPROTO_ICMP) {\n    icp = (struct icmp *)((char *)ip + shlen);\n    /*\n     *\tAssume any unknown ICMP type is an error. This isn't\n     *\tspecified by the RFC, but think about it..\n     */\n    if(icp->icmp_type>18 || icmp_flush[icp->icmp_type]) goto end_error;\n  }\n\n  /* make a copy */\n  m = m_get(msrc->slirp);\n  if (!m) {\n      goto end_error;\n  }\n\n  { int new_m_size;\n    new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN;\n    if(new_m_size>m->m_size) m_inc(m, new_m_size);\n  }\n  memcpy(m->m_data, msrc->m_data, msrc->m_len);\n  m->m_len = msrc->m_len;                        /* copy msrc to m */\n\n  /* make the header of the reply packet */\n  ip  = mtod(m, struct ip *);\n  hlen= sizeof(struct ip );     /* no options in reply */\n\n  /* fill in icmp */\n  m->m_data += hlen;\n  m->m_len -= hlen;\n\n  icp = mtod(m, struct icmp *);\n\n  if(minsize) s_ip_len=shlen+ICMP_MINLEN;   /* return header+8b only */\n  else if(s_ip_len>ICMP_MAXDATALEN)         /* maximum size */\n    s_ip_len=ICMP_MAXDATALEN;\n\n  m->m_len=ICMP_MINLEN+s_ip_len;        /* 8 bytes ICMP header */\n\n  /* min. size = 8+sizeof(struct ip)+8 */\n\n  icp->icmp_type = type;\n  icp->icmp_code = code;\n  icp->icmp_id = 0;\n  icp->icmp_seq = 0;\n\n  memcpy(&icp->icmp_ip, msrc->m_data, s_ip_len);   /* report the ip packet */\n  HTONS(icp->icmp_ip.ip_len);\n  HTONS(icp->icmp_ip.ip_id);\n  HTONS(icp->icmp_ip.ip_off);\n\n#ifdef DEBUG\n  if(message) {           /* DEBUG : append message to ICMP packet */\n    int message_len;\n    char *cpnt;\n    message_len=strlen(message);\n    if(message_len>ICMP_MAXDATALEN) message_len=ICMP_MAXDATALEN;\n    cpnt=(char *)m->m_data+m->m_len;\n    memcpy(cpnt, message, message_len);\n    m->m_len+=message_len;\n  }\n#endif\n\n  icp->icmp_cksum = 0;\n  icp->icmp_cksum = cksum(m, m->m_len);\n\n  m->m_data -= hlen;\n  m->m_len += hlen;\n\n  /* fill in ip */\n  ip->ip_hl = hlen >> 2;\n  ip->ip_len = m->m_len;\n\n  ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0);  /* high priority for errors */\n\n  ip->ip_ttl = MAXTTL;\n  ip->ip_p = IPPROTO_ICMP;\n  ip->ip_dst = ip->ip_src;    /* ip adresses */\n  ip->ip_src = m->slirp->vhost_addr;\n\n  (void ) ip_output((struct socket *)NULL, m);\n\nend_error:\n  return;\n}\n#undef ICMP_MAXDATALEN\n\n/*\n * Reflect the ip packet back to the source\n */\nvoid\nicmp_reflect(struct mbuf *m)\n{\n  register struct ip *ip = mtod(m, struct ip *);\n  int hlen = ip->ip_hl << 2;\n  int optlen = hlen - sizeof(struct ip );\n  register struct icmp *icp;\n\n  /*\n   * Send an icmp packet back to the ip level,\n   * after supplying a checksum.\n   */\n  m->m_data += hlen;\n  m->m_len -= hlen;\n  icp = mtod(m, struct icmp *);\n\n  icp->icmp_cksum = 0;\n  icp->icmp_cksum = cksum(m, ip->ip_len - hlen);\n\n  m->m_data -= hlen;\n  m->m_len += hlen;\n\n  /* fill in ip */\n  if (optlen > 0) {\n    /*\n     * Strip out original options by copying rest of first\n     * mbuf's data back, and adjust the IP length.\n     */\n    memmove((caddr_t)(ip + 1), (caddr_t)ip + hlen,\n\t    (unsigned )(m->m_len - hlen));\n    hlen -= optlen;\n    ip->ip_hl = hlen >> 2;\n    ip->ip_len -= optlen;\n    m->m_len -= optlen;\n  }\n\n  ip->ip_ttl = MAXTTL;\n  { /* swap */\n    struct in_addr icmp_dst;\n    icmp_dst = ip->ip_dst;\n    ip->ip_dst = ip->ip_src;\n    ip->ip_src = icmp_dst;\n  }\n\n  (void ) ip_output((struct socket *)NULL, m);\n}\n"
  },
  {
    "path": "src/slirp/ip_icmp.h",
    "content": "/*\n * Copyright (c) 1982, 1986, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)ip_icmp.h\t8.1 (Berkeley) 6/10/93\n * ip_icmp.h,v 1.4 1995/05/30 08:09:43 rgrimes Exp\n */\n\n#ifndef _NETINET_IP_ICMP_H_\n#define _NETINET_IP_ICMP_H_\n\n/*\n * Interface Control Message Protocol Definitions.\n * Per RFC 792, September 1981.\n */\n\ntypedef uint32_t n_time;\n\n/*\n * Structure of an icmp header.\n */\nstruct icmp {\n\tu_char\ticmp_type;\t\t/* type of message, see below */\n\tu_char\ticmp_code;\t\t/* type sub code */\n\tu_short\ticmp_cksum;\t\t/* ones complement cksum of struct */\n\tunion {\n\t\tu_char ih_pptr;\t\t\t/* ICMP_PARAMPROB */\n\t\tstruct in_addr ih_gwaddr;\t/* ICMP_REDIRECT */\n\t\tstruct ih_idseq {\n\t\t\tu_short\ticd_id;\n\t\t\tu_short\ticd_seq;\n\t\t} ih_idseq;\n\t\tint ih_void;\n\n\t\t/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */\n\t\tstruct ih_pmtu {\n\t\t\tu_short ipm_void;\n\t\t\tu_short ipm_nextmtu;\n\t\t} ih_pmtu;\n\t} icmp_hun;\n#define\ticmp_pptr\ticmp_hun.ih_pptr\n#define\ticmp_gwaddr\ticmp_hun.ih_gwaddr\n#define\ticmp_id\t\ticmp_hun.ih_idseq.icd_id\n#define\ticmp_seq\ticmp_hun.ih_idseq.icd_seq\n#define\ticmp_void\ticmp_hun.ih_void\n#define\ticmp_pmvoid\ticmp_hun.ih_pmtu.ipm_void\n#define\ticmp_nextmtu\ticmp_hun.ih_pmtu.ipm_nextmtu\n\tunion {\n\t\tstruct id_ts {\n\t\t\tn_time its_otime;\n\t\t\tn_time its_rtime;\n\t\t\tn_time its_ttime;\n\t\t} id_ts;\n\t\tstruct id_ip  {\n\t\t\tstruct ip idi_ip;\n\t\t\t/* options and then 64 bits of data */\n\t\t} id_ip;\n\t\tuint32_t\tid_mask;\n\t\tchar\t\tid_data[1];\n\t} icmp_dun;\n#define\ticmp_otime\ticmp_dun.id_ts.its_otime\n#define\ticmp_rtime\ticmp_dun.id_ts.its_rtime\n#define\ticmp_ttime\ticmp_dun.id_ts.its_ttime\n#define\ticmp_ip\t\ticmp_dun.id_ip.idi_ip\n#define\ticmp_mask\ticmp_dun.id_mask\n#define\ticmp_data\ticmp_dun.id_data\n};\n\n/*\n * Lower bounds on packet lengths for various types.\n * For the error advice packets must first insure that the\n * packet is large enought to contain the returned ip header.\n * Only then can we do the check to see if 64 bits of packet\n * data have been returned, since we need to check the returned\n * ip header length.\n */\n#define\tICMP_MINLEN\t8\t\t\t\t/* abs minimum */\n#define\tICMP_TSLEN\t(8 + 3 * sizeof (n_time))\t/* timestamp */\n#define\tICMP_MASKLEN\t12\t\t\t\t/* address mask */\n#define\tICMP_ADVLENMIN\t(8 + sizeof (struct ip) + 8)\t/* min */\n#define\tICMP_ADVLEN(p)\t(8 + ((p)->icmp_ip.ip_hl << 2) + 8)\n\t/* N.B.: must separately check that ip_hl >= 5 */\n\n/*\n * Definition of type and code field values.\n */\n#define\tICMP_ECHOREPLY\t\t0\t\t/* echo reply */\n#define\tICMP_UNREACH\t\t3\t\t/* dest unreachable, codes: */\n#define\t\tICMP_UNREACH_NET\t0\t\t/* bad net */\n#define\t\tICMP_UNREACH_HOST\t1\t\t/* bad host */\n#define\t\tICMP_UNREACH_PROTOCOL\t2\t\t/* bad protocol */\n#define\t\tICMP_UNREACH_PORT\t3\t\t/* bad port */\n#define\t\tICMP_UNREACH_NEEDFRAG\t4\t\t/* IP_DF caused drop */\n#define\t\tICMP_UNREACH_SRCFAIL\t5\t\t/* src route failed */\n#define\t\tICMP_UNREACH_NET_UNKNOWN 6\t\t/* unknown net */\n#define\t\tICMP_UNREACH_HOST_UNKNOWN 7\t\t/* unknown host */\n#define\t\tICMP_UNREACH_ISOLATED\t8\t\t/* src host isolated */\n#define\t\tICMP_UNREACH_NET_PROHIB\t9\t\t/* prohibited access */\n#define\t\tICMP_UNREACH_HOST_PROHIB 10\t\t/* ditto */\n#define\t\tICMP_UNREACH_TOSNET\t11\t\t/* bad tos for net */\n#define\t\tICMP_UNREACH_TOSHOST\t12\t\t/* bad tos for host */\n#define\tICMP_SOURCEQUENCH\t4\t\t/* packet lost, slow down */\n#define\tICMP_REDIRECT\t\t5\t\t/* shorter route, codes: */\n#define\t\tICMP_REDIRECT_NET\t0\t\t/* for network */\n#define\t\tICMP_REDIRECT_HOST\t1\t\t/* for host */\n#define\t\tICMP_REDIRECT_TOSNET\t2\t\t/* for tos and net */\n#define\t\tICMP_REDIRECT_TOSHOST\t3\t\t/* for tos and host */\n#define\tICMP_ECHO\t\t8\t\t/* echo service */\n#define\tICMP_ROUTERADVERT\t9\t\t/* router advertisement */\n#define\tICMP_ROUTERSOLICIT\t10\t\t/* router solicitation */\n#define\tICMP_TIMXCEED\t\t11\t\t/* time exceeded, code: */\n#define\t\tICMP_TIMXCEED_INTRANS\t0\t\t/* ttl==0 in transit */\n#define\t\tICMP_TIMXCEED_REASS\t1\t\t/* ttl==0 in reass */\n#define\tICMP_PARAMPROB\t\t12\t\t/* ip header bad */\n#define\t\tICMP_PARAMPROB_OPTABSENT 1\t\t/* req. opt. absent */\n#define\tICMP_TSTAMP\t\t13\t\t/* timestamp request */\n#define\tICMP_TSTAMPREPLY\t14\t\t/* timestamp reply */\n#define\tICMP_IREQ\t\t15\t\t/* information request */\n#define\tICMP_IREQREPLY\t\t16\t\t/* information reply */\n#define\tICMP_MASKREQ\t\t17\t\t/* address mask request */\n#define\tICMP_MASKREPLY\t\t18\t\t/* address mask reply */\n\n#define\tICMP_MAXTYPE\t\t18\n\n#define\tICMP_INFOTYPE(type) \\\n\t((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \\\n\t(type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \\\n\t(type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \\\n\t(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \\\n\t(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)\n\nvoid icmp_input(struct mbuf *, int);\nvoid icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,\n                const char *message);\nvoid icmp_reflect(struct mbuf *);\n\n#endif\n"
  },
  {
    "path": "src/slirp/ip_input.c",
    "content": "/*\n * Copyright (c) 1982, 1986, 1988, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)ip_input.c\t8.2 (Berkeley) 1/4/94\n * ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp\n */\n\n/*\n * Changes and additions relating to SLiRP are\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#include \"slirp.h\"\n#include \"ip_icmp.h\"\n\n#define container_of(ptr, type, member) ({                      \\\n        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \\\n        (type *)( (char *)__mptr - offsetof(type,member) );})\n\nstatic struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp);\nstatic void ip_freef(Slirp *slirp, struct ipq *fp);\nstatic void ip_enq(register struct ipasfrag *p,\n                   register struct ipasfrag *prev);\nstatic void ip_deq(register struct ipasfrag *p);\n\n/*\n * IP initialization: fill in IP protocol switch table.\n * All protocols not implemented in kernel go to raw IP protocol handler.\n */\nvoid\nip_init(Slirp *slirp)\n{\n    slirp->ipq.ip_link.next = slirp->ipq.ip_link.prev = &slirp->ipq.ip_link;\n    udp_init(slirp);\n    tcp_init(slirp);\n}\n\n/*\n * Ip input routine.  Checksum and byte swap header.  If fragmented\n * try to reassemble.  Process options.  Pass to next level.\n */\nvoid\nip_input(struct mbuf *m)\n{\n\tSlirp *slirp = m->slirp;\n\tregister struct ip *ip;\n\tint hlen;\n\n\tDEBUG_CALL(\"ip_input\");\n\tDEBUG_ARG(\"m = %lx\", (long)m);\n\tDEBUG_ARG(\"m_len = %d\", m->m_len);\n\n\tif (m->m_len < sizeof (struct ip)) {\n\t\treturn;\n\t}\n\n\tip = mtod(m, struct ip *);\n\n\tif (ip->ip_v != IPVERSION) {\n\t\tgoto bad;\n\t}\n\n\thlen = ip->ip_hl << 2;\n\tif (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */\n\t  goto bad;                                  /* or packet too short */\n\t}\n\n        /* keep ip header intact for ICMP reply\n\t * ip->ip_sum = cksum(m, hlen);\n\t * if (ip->ip_sum) {\n\t */\n\tif(cksum(m,hlen)) {\n\t  goto bad;\n\t}\n\n\t/*\n\t * Convert fields to host representation.\n\t */\n\tNTOHS(ip->ip_len);\n\tif (ip->ip_len < hlen) {\n\t\tgoto bad;\n\t}\n\tNTOHS(ip->ip_id);\n\tNTOHS(ip->ip_off);\n\n\t/*\n\t * Check that the amount of data in the buffers\n\t * is as at least much as the IP header would have us expect.\n\t * Trim mbufs if longer than we expect.\n\t * Drop packet if shorter than we expect.\n\t */\n\tif (m->m_len < ip->ip_len) {\n\t\tgoto bad;\n\t}\n\n    if (slirp->restricted) {\n        if ((ip->ip_dst.s_addr & slirp->vnetwork_mask.s_addr) ==\n            slirp->vnetwork_addr.s_addr) {\n            if (ip->ip_dst.s_addr == 0xffffffff && ip->ip_p != IPPROTO_UDP)\n                goto bad;\n        } else {\n            uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;\n            struct ex_list *ex_ptr;\n\n            if ((ip->ip_dst.s_addr & inv_mask) == inv_mask) {\n                goto bad;\n            }\n            for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)\n                if (ex_ptr->ex_addr.s_addr == ip->ip_dst.s_addr)\n                    break;\n\n            if (!ex_ptr)\n                goto bad;\n        }\n    }\n\n\t/* Should drop packet if mbuf too long? hmmm... */\n\tif (m->m_len > ip->ip_len)\n\t   m_adj(m, ip->ip_len - m->m_len);\n\n\t/* check ip_ttl for a correct ICMP reply */\n\tif(ip->ip_ttl==0) {\n\t  icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,\"ttl\");\n\t  goto bad;\n\t}\n\n\t/*\n\t * If offset or IP_MF are set, must reassemble.\n\t * Otherwise, nothing need be done.\n\t * (We could look in the reassembly queue to see\n\t * if the packet was previously fragmented,\n\t * but it's not worth the time; just let them time out.)\n\t *\n\t * XXX This should fail, don't fragment yet\n\t */\n\tif (ip->ip_off &~ IP_DF) {\n\t  register struct ipq *fp;\n      struct qlink *l;\n\t\t/*\n\t\t * Look for queue of fragments\n\t\t * of this datagram.\n\t\t */\n\t\tfor (l = slirp->ipq.ip_link.next; l != &slirp->ipq.ip_link;\n\t\t     l = l->next) {\n            fp = container_of(l, struct ipq, ip_link);\n            if (ip->ip_id == fp->ipq_id &&\n                    ip->ip_src.s_addr == fp->ipq_src.s_addr &&\n                    ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&\n                    ip->ip_p == fp->ipq_p)\n\t\t    goto found;\n        }\n        fp = NULL;\n\tfound:\n\n\t\t/*\n\t\t * Adjust ip_len to not reflect header,\n\t\t * set ip_mff if more fragments are expected,\n\t\t * convert offset of this to bytes.\n\t\t */\n\t\tip->ip_len -= hlen;\n\t\tif (ip->ip_off & IP_MF)\n\t\t  ip->ip_tos |= 1;\n\t\telse\n\t\t  ip->ip_tos &= ~1;\n\n\t\tip->ip_off <<= 3;\n\n\t\t/*\n\t\t * If datagram marked as having more fragments\n\t\t * or if this is not the first fragment,\n\t\t * attempt reassembly; if it succeeds, proceed.\n\t\t */\n\t\tif (ip->ip_tos & 1 || ip->ip_off) {\n\t\t\tip = ip_reass(slirp, ip, fp);\n                        if (ip == NULL)\n\t\t\t\treturn;\n\t\t\tm = dtom(slirp, ip);\n\t\t} else\n\t\t\tif (fp)\n\t\t   \t   ip_freef(slirp, fp);\n\n\t} else\n\t\tip->ip_len -= hlen;\n\n\t/*\n\t * Switch out to protocol's input routine.\n\t */\n\tswitch (ip->ip_p) {\n\t case IPPROTO_TCP:\n\t\ttcp_input(m, hlen, (struct socket *)NULL);\n\t\tbreak;\n\t case IPPROTO_UDP:\n\t\tudp_input(m, hlen);\n\t\tbreak;\n\t case IPPROTO_ICMP:\n\t\ticmp_input(m, hlen);\n\t\tbreak;\n\t default:\n\t\tm_free(m);\n\t}\n\treturn;\nbad:\n\tm_freem(m);\n\treturn;\n}\n\n#define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink)))\n#define fragtoip(P) ((struct ip*)(((char*)(P)) + sizeof(struct qlink)))\n/*\n * Take incoming datagram fragment and try to\n * reassemble it into whole datagram.  If a chain for\n * reassembly of this datagram already exists, then it\n * is given as fp; otherwise have to make a chain.\n */\nstatic struct ip *\nip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)\n{\n\tregister struct mbuf *m = dtom(slirp, ip);\n\tregister struct ipasfrag *q;\n\tint hlen = ip->ip_hl << 2;\n\tint i, next;\n\n\tDEBUG_CALL(\"ip_reass\");\n\tDEBUG_ARG(\"ip = %lx\", (long)ip);\n\tDEBUG_ARG(\"fp = %lx\", (long)fp);\n\tDEBUG_ARG(\"m = %lx\", (long)m);\n\n\t/*\n\t * Presence of header sizes in mbufs\n\t * would confuse code below.\n         * Fragment m_data is concatenated.\n\t */\n\tm->m_data += hlen;\n\tm->m_len -= hlen;\n\n\t/*\n\t * If first fragment to arrive, create a reassembly queue.\n\t */\n        if (fp == NULL) {\n\t  struct mbuf *t = m_get(slirp);\n\n\t  if (t == NULL) {\n\t      goto dropfrag;\n\t  }\n\t  fp = mtod(t, struct ipq *);\n\t  insque(&fp->ip_link, &slirp->ipq.ip_link);\n\t  fp->ipq_ttl = IPFRAGTTL;\n\t  fp->ipq_p = ip->ip_p;\n\t  fp->ipq_id = ip->ip_id;\n\t  fp->frag_link.next = fp->frag_link.prev = &fp->frag_link;\n\t  fp->ipq_src = ip->ip_src;\n\t  fp->ipq_dst = ip->ip_dst;\n\t  q = (struct ipasfrag *)fp;\n\t  goto insert;\n\t}\n\n\t/*\n\t * Find a segment which begins after this one does.\n\t */\n\tfor (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;\n            q = q->ipf_next)\n\t\tif (q->ipf_off > ip->ip_off)\n\t\t\tbreak;\n\n\t/*\n\t * If there is a preceding segment, it may provide some of\n\t * our data already.  If so, drop the data from the incoming\n\t * segment.  If it provides all of our data, drop us.\n\t */\n\tif (q->ipf_prev != &fp->frag_link) {\n        struct ipasfrag *pq = q->ipf_prev;\n\t\ti = pq->ipf_off + pq->ipf_len - ip->ip_off;\n\t\tif (i > 0) {\n\t\t\tif (i >= ip->ip_len)\n\t\t\t\tgoto dropfrag;\n\t\t\tm_adj(dtom(slirp, ip), i);\n\t\t\tip->ip_off += i;\n\t\t\tip->ip_len -= i;\n\t\t}\n\t}\n\n\t/*\n\t * While we overlap succeeding segments trim them or,\n\t * if they are completely covered, dequeue them.\n\t */\n\twhile (q != (struct ipasfrag*)&fp->frag_link &&\n            ip->ip_off + ip->ip_len > q->ipf_off) {\n\t\ti = (ip->ip_off + ip->ip_len) - q->ipf_off;\n\t\tif (i < q->ipf_len) {\n\t\t\tq->ipf_len -= i;\n\t\t\tq->ipf_off += i;\n\t\t\tm_adj(dtom(slirp, q), i);\n\t\t\tbreak;\n\t\t}\n\t\tq = q->ipf_next;\n\t\tm_freem(dtom(slirp, q->ipf_prev));\n\t\tip_deq(q->ipf_prev);\n\t}\n\ninsert:\n\t/*\n\t * Stick new segment in its place;\n\t * check for complete reassembly.\n\t */\n\tip_enq(iptofrag(ip), q->ipf_prev);\n\tnext = 0;\n\tfor (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link;\n            q = q->ipf_next) {\n\t\tif (q->ipf_off != next)\n                        return NULL;\n\t\tnext += q->ipf_len;\n\t}\n\tif (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1)\n                return NULL;\n\n\t/*\n\t * Reassembly is complete; concatenate fragments.\n\t */\n    q = fp->frag_link.next;\n\tm = dtom(slirp, q);\n\n\tq = (struct ipasfrag *) q->ipf_next;\n\twhile (q != (struct ipasfrag*)&fp->frag_link) {\n\t  struct mbuf *t = dtom(slirp, q);\n\t  q = (struct ipasfrag *) q->ipf_next;\n\t  m_cat(m, t);\n\t}\n\n\t/*\n\t * Create header for new ip packet by\n\t * modifying header of first packet;\n\t * dequeue and discard fragment reassembly header.\n\t * Make header visible.\n\t */\n\tq = fp->frag_link.next;\n\n\t/*\n\t * If the fragments concatenated to an mbuf that's\n\t * bigger than the total size of the fragment, then and\n\t * m_ext buffer was alloced. But fp->ipq_next points to\n\t * the old buffer (in the mbuf), so we must point ip\n\t * into the new buffer.\n\t */\n\tif (m->m_flags & M_EXT) {\n\t  int delta = (char *)q - m->m_dat;\n\t  q = (struct ipasfrag *)(m->m_ext + delta);\n\t}\n\n    ip = fragtoip(q);\n\tip->ip_len = next;\n\tip->ip_tos &= ~1;\n\tip->ip_src = fp->ipq_src;\n\tip->ip_dst = fp->ipq_dst;\n\tremque(&fp->ip_link);\n\t(void) m_free(dtom(slirp, fp));\n\tm->m_len += (ip->ip_hl << 2);\n\tm->m_data -= (ip->ip_hl << 2);\n\n\treturn ip;\n\ndropfrag:\n\tm_freem(m);\n        return NULL;\n}\n\n/*\n * Free a fragment reassembly header and all\n * associated datagrams.\n */\nstatic void\nip_freef(Slirp *slirp, struct ipq *fp)\n{\n\tregister struct ipasfrag *q, *p;\n\n\tfor (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) {\n\t\tp = q->ipf_next;\n\t\tip_deq(q);\n\t\tm_freem(dtom(slirp, q));\n\t}\n\tremque(&fp->ip_link);\n\t(void) m_free(dtom(slirp, fp));\n}\n\n/*\n * Put an ip fragment on a reassembly chain.\n * Like insque, but pointers in middle of structure.\n */\nstatic void\nip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)\n{\n\tDEBUG_CALL(\"ip_enq\");\n\tDEBUG_ARG(\"prev = %lx\", (long)prev);\n\tp->ipf_prev =  prev;\n\tp->ipf_next = prev->ipf_next;\n\t((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p;\n\tprev->ipf_next = p;\n}\n\n/*\n * To ip_enq as remque is to insque.\n */\nstatic void\nip_deq(register struct ipasfrag *p)\n{\n\t((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;\n\t((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;\n}\n\n/*\n * IP timer processing;\n * if a timer expires on a reassembly\n * queue, discard it.\n */\nvoid\nip_slowtimo(Slirp *slirp)\n{\n    struct qlink *l;\n\n\tDEBUG_CALL(\"ip_slowtimo\");\n\n    l = slirp->ipq.ip_link.next;\n\n        if (l == NULL)\n\t   return;\n\n    while (l != &slirp->ipq.ip_link) {\n        struct ipq *fp = container_of(l, struct ipq, ip_link);\n        l = l->next;\n\t\tif (--fp->ipq_ttl == 0) {\n\t\t\tip_freef(slirp, fp);\n\t\t}\n    }\n}\n\n/*\n * Do option processing on a datagram,\n * possibly discarding it if bad options are encountered,\n * or forwarding it if source-routed.\n * Returns 1 if packet has been forwarded/freed,\n * 0 if the packet should be processed further.\n */\n\n#ifdef notdef\n\nint\nip_dooptions(m)\n\tstruct mbuf *m;\n{\n\tregister struct ip *ip = mtod(m, struct ip *);\n\tregister u_char *cp;\n\tregister struct ip_timestamp *ipt;\n\tregister struct in_ifaddr *ia;\n\tint opt, optlen, cnt, off, code, type, forward = 0;\n\tstruct in_addr *sin, dst;\ntypedef uint32_t n_time;\n\tn_time ntime;\n\n\tdst = ip->ip_dst;\n\tcp = (u_char *)(ip + 1);\n\tcnt = (ip->ip_hl << 2) - sizeof (struct ip);\n\tfor (; cnt > 0; cnt -= optlen, cp += optlen) {\n\t\topt = cp[IPOPT_OPTVAL];\n\t\tif (opt == IPOPT_EOL)\n\t\t\tbreak;\n\t\tif (opt == IPOPT_NOP)\n\t\t\toptlen = 1;\n\t\telse {\n\t\t\toptlen = cp[IPOPT_OLEN];\n\t\t\tif (optlen <= 0 || optlen > cnt) {\n\t\t\t\tcode = &cp[IPOPT_OLEN] - (u_char *)ip;\n\t\t\t\tgoto bad;\n\t\t\t}\n\t\t}\n\t\tswitch (opt) {\n\n\t\tdefault:\n\t\t\tbreak;\n\n\t\t/*\n\t\t * Source routing with record.\n\t\t * Find interface with current destination address.\n\t\t * If none on this machine then drop if strictly routed,\n\t\t * or do nothing if loosely routed.\n\t\t * Record interface address and bring up next address\n\t\t * component.  If strictly routed make sure next\n\t\t * address is on directly accessible net.\n\t\t */\n\t\tcase IPOPT_LSRR:\n\t\tcase IPOPT_SSRR:\n\t\t\tif ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {\n\t\t\t\tcode = &cp[IPOPT_OFFSET] - (u_char *)ip;\n\t\t\t\tgoto bad;\n\t\t\t}\n\t\t\tipaddr.sin_addr = ip->ip_dst;\n\t\t\tia = (struct in_ifaddr *)\n\t\t\t\tifa_ifwithaddr((struct sockaddr *)&ipaddr);\n\t\t\tif (ia == 0) {\n\t\t\t\tif (opt == IPOPT_SSRR) {\n\t\t\t\t\ttype = ICMP_UNREACH;\n\t\t\t\t\tcode = ICMP_UNREACH_SRCFAIL;\n\t\t\t\t\tgoto bad;\n\t\t\t\t}\n\t\t\t\t/*\n\t\t\t\t * Loose routing, and not at next destination\n\t\t\t\t * yet; nothing to do except forward.\n\t\t\t\t */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\toff--;\t\t\t/ * 0 origin *  /\n\t\t\tif (off > optlen - sizeof(struct in_addr)) {\n\t\t\t\t/*\n\t\t\t\t * End of source route.  Should be for us.\n\t\t\t\t */\n\t\t\t\tsave_rte(cp, ip->ip_src);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/*\n\t\t\t * locate outgoing interface\n\t\t\t */\n\t\t\tbcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,\n\t\t\t    sizeof(ipaddr.sin_addr));\n\t\t\tif (opt == IPOPT_SSRR) {\n#define\tINA\tstruct in_ifaddr *\n#define\tSA\tstruct sockaddr *\n \t\t\t    if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)\n\t\t\t\tia = (INA)ifa_ifwithnet((SA)&ipaddr);\n\t\t\t} else\n\t\t\t\tia = ip_rtaddr(ipaddr.sin_addr);\n\t\t\tif (ia == 0) {\n\t\t\t\ttype = ICMP_UNREACH;\n\t\t\t\tcode = ICMP_UNREACH_SRCFAIL;\n\t\t\t\tgoto bad;\n\t\t\t}\n\t\t\tip->ip_dst = ipaddr.sin_addr;\n\t\t\tbcopy((caddr_t)&(IA_SIN(ia)->sin_addr),\n\t\t\t    (caddr_t)(cp + off), sizeof(struct in_addr));\n\t\t\tcp[IPOPT_OFFSET] += sizeof(struct in_addr);\n\t\t\t/*\n\t\t\t * Let ip_intr's mcast routing check handle mcast pkts\n\t\t\t */\n\t\t\tforward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));\n\t\t\tbreak;\n\n\t\tcase IPOPT_RR:\n\t\t\tif ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {\n\t\t\t\tcode = &cp[IPOPT_OFFSET] - (u_char *)ip;\n\t\t\t\tgoto bad;\n\t\t\t}\n\t\t\t/*\n\t\t\t * If no space remains, ignore.\n\t\t\t */\n\t\t\toff--;\t\t\t * 0 origin *\n\t\t\tif (off > optlen - sizeof(struct in_addr))\n\t\t\t\tbreak;\n\t\t\tbcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,\n\t\t\t    sizeof(ipaddr.sin_addr));\n\t\t\t/*\n\t\t\t * locate outgoing interface; if we're the destination,\n\t\t\t * use the incoming interface (should be same).\n\t\t\t */\n\t\t\tif ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&\n\t\t\t    (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {\n\t\t\t\ttype = ICMP_UNREACH;\n\t\t\t\tcode = ICMP_UNREACH_HOST;\n\t\t\t\tgoto bad;\n\t\t\t}\n\t\t\tbcopy((caddr_t)&(IA_SIN(ia)->sin_addr),\n\t\t\t    (caddr_t)(cp + off), sizeof(struct in_addr));\n\t\t\tcp[IPOPT_OFFSET] += sizeof(struct in_addr);\n\t\t\tbreak;\n\n\t\tcase IPOPT_TS:\n\t\t\tcode = cp - (u_char *)ip;\n\t\t\tipt = (struct ip_timestamp *)cp;\n\t\t\tif (ipt->ipt_len < 5)\n\t\t\t\tgoto bad;\n\t\t\tif (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {\n\t\t\t\tif (++ipt->ipt_oflw == 0)\n\t\t\t\t\tgoto bad;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tsin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);\n\t\t\tswitch (ipt->ipt_flg) {\n\n\t\t\tcase IPOPT_TS_TSONLY:\n\t\t\t\tbreak;\n\n\t\t\tcase IPOPT_TS_TSANDADDR:\n\t\t\t\tif (ipt->ipt_ptr + sizeof(n_time) +\n\t\t\t\t    sizeof(struct in_addr) > ipt->ipt_len)\n\t\t\t\t\tgoto bad;\n\t\t\t\tipaddr.sin_addr = dst;\n\t\t\t\tia = (INA)ifaof_ i f p foraddr((SA)&ipaddr,\n\t\t\t\t\t\t\t    m->m_pkthdr.rcvif);\n\t\t\t\tif (ia == 0)\n\t\t\t\t\tcontinue;\n\t\t\t\tbcopy((caddr_t)&IA_SIN(ia)->sin_addr,\n\t\t\t\t    (caddr_t)sin, sizeof(struct in_addr));\n\t\t\t\tipt->ipt_ptr += sizeof(struct in_addr);\n\t\t\t\tbreak;\n\n\t\t\tcase IPOPT_TS_PRESPEC:\n\t\t\t\tif (ipt->ipt_ptr + sizeof(n_time) +\n\t\t\t\t    sizeof(struct in_addr) > ipt->ipt_len)\n\t\t\t\t\tgoto bad;\n\t\t\t\tbcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,\n\t\t\t\t    sizeof(struct in_addr));\n\t\t\t\tif (ifa_ifwithaddr((SA)&ipaddr) == 0)\n\t\t\t\t\tcontinue;\n\t\t\t\tipt->ipt_ptr += sizeof(struct in_addr);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tgoto bad;\n\t\t\t}\n\t\t\tntime = iptime();\n\t\t\tbcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,\n\t\t\t    sizeof(n_time));\n\t\t\tipt->ipt_ptr += sizeof(n_time);\n\t\t}\n\t}\n\tif (forward) {\n\t\tip_forward(m, 1);\n\t\treturn (1);\n\t}\n\treturn (0);\nbad:\n \ticmp_error(m, type, code, 0, 0);\n\n\treturn (1);\n}\n\n#endif /* notdef */\n\n/*\n * Strip out IP options, at higher\n * level protocol in the kernel.\n * Second argument is buffer to which options\n * will be moved, and return value is their length.\n * (XXX) should be deleted; last arg currently ignored.\n */\nvoid\nip_stripoptions(register struct mbuf *m, struct mbuf *mopt)\n{\n\tregister int i;\n\tstruct ip *ip = mtod(m, struct ip *);\n\tregister caddr_t opts;\n\tint olen;\n\n\tolen = (ip->ip_hl<<2) - sizeof (struct ip);\n\topts = (caddr_t)(ip + 1);\n\ti = m->m_len - (sizeof (struct ip) + olen);\n\tmemcpy(opts, opts  + olen, (unsigned)i);\n\tm->m_len -= olen;\n\n\tip->ip_hl = sizeof(struct ip) >> 2;\n}\n"
  },
  {
    "path": "src/slirp/ip_output.c",
    "content": "/*\n * Copyright (c) 1982, 1986, 1988, 1990, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)ip_output.c\t8.3 (Berkeley) 1/21/94\n * ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp\n */\n\n/*\n * Changes and additions relating to SLiRP are\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#include \"slirp.h\"\n\n/* Number of packets queued before we start sending\n * (to prevent allocing too many mbufs) */\n#define IF_THRESH 10\n\n/*\n * IP output.  The packet in mbuf chain m contains a skeletal IP\n * header (with len, off, ttl, proto, tos, src, dst).\n * The mbuf chain containing the packet will be freed.\n * The mbuf opt, if present, will not be freed.\n */\nint\nip_output(struct socket *so, struct mbuf *m0)\n{\n\tSlirp *slirp = m0->slirp;\n\tregister struct ip *ip;\n\tregister struct mbuf *m = m0;\n\tregister int hlen = sizeof(struct ip );\n\tint len, off, error = 0;\n\n\tDEBUG_CALL(\"ip_output\");\n\tDEBUG_ARG(\"so = %lx\", (long)so);\n\tDEBUG_ARG(\"m0 = %lx\", (long)m0);\n\n\tip = mtod(m, struct ip *);\n\t/*\n\t * Fill in IP header.\n\t */\n\tip->ip_v = IPVERSION;\n\tip->ip_off &= IP_DF;\n\tip->ip_id = htons(slirp->ip_id++);\n\tip->ip_hl = hlen >> 2;\n\n\t/*\n\t * If small enough for interface, can just send directly.\n\t */\n\tif ((uint16_t)ip->ip_len <= IF_MTU) {\n\t\tip->ip_len = htons((uint16_t)ip->ip_len);\n\t\tip->ip_off = htons((uint16_t)ip->ip_off);\n\t\tip->ip_sum = 0;\n\t\tip->ip_sum = cksum(m, hlen);\n\n\t\tif_output(so, m);\n\t\tgoto done;\n\t}\n\n\t/*\n\t * Too large for interface; fragment if possible.\n\t * Must be able to put at least 8 bytes per fragment.\n\t */\n\tif (ip->ip_off & IP_DF) {\n\t\terror = -1;\n\t\tgoto bad;\n\t}\n\n\tlen = (IF_MTU - hlen) &~ 7;       /* ip databytes per packet */\n\tif (len < 8) {\n\t\terror = -1;\n\t\tgoto bad;\n\t}\n\n    {\n\tint mhlen, firstlen = len;\n\tstruct mbuf **mnext = &m->m_nextpkt;\n\n\t/*\n\t * Loop through length of segment after first fragment,\n\t * make new header and copy data of each part and link onto chain.\n\t */\n\tm0 = m;\n\tmhlen = sizeof (struct ip);\n\tfor (off = hlen + len; off < (uint16_t)ip->ip_len; off += len) {\n\t  register struct ip *mhip;\n\t  m = m_get(slirp);\n          if (m == NULL) {\n\t    error = -1;\n\t    goto sendorfree;\n\t  }\n\t  m->m_data += IF_MAXLINKHDR;\n\t  mhip = mtod(m, struct ip *);\n\t  *mhip = *ip;\n\n\t  m->m_len = mhlen;\n\t  mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);\n\t  if (ip->ip_off & IP_MF)\n\t    mhip->ip_off |= IP_MF;\n\t  if (off + len >= (uint16_t)ip->ip_len)\n\t    len = (uint16_t)ip->ip_len - off;\n\t  else\n\t    mhip->ip_off |= IP_MF;\n\t  mhip->ip_len = htons((uint16_t)(len + mhlen));\n\n\t  if (m_copy(m, m0, off, len) < 0) {\n\t    error = -1;\n\t    goto sendorfree;\n\t  }\n\n\t  mhip->ip_off = htons((uint16_t)mhip->ip_off);\n\t  mhip->ip_sum = 0;\n\t  mhip->ip_sum = cksum(m, mhlen);\n\t  *mnext = m;\n\t  mnext = &m->m_nextpkt;\n\t}\n\t/*\n\t * Update first fragment by trimming what's been copied out\n\t * and updating header, then send each fragment (in order).\n\t */\n\tm = m0;\n\tm_adj(m, hlen + firstlen - (uint16_t)ip->ip_len);\n\tip->ip_len = htons((uint16_t)m->m_len);\n\tip->ip_off = htons((uint16_t)(ip->ip_off | IP_MF));\n\tip->ip_sum = 0;\n\tip->ip_sum = cksum(m, hlen);\nsendorfree:\n\tfor (m = m0; m; m = m0) {\n\t\tm0 = m->m_nextpkt;\n                m->m_nextpkt = NULL;\n\t\tif (error == 0)\n\t\t\tif_output(so, m);\n\t\telse\n\t\t\tm_freem(m);\n\t}\n    }\n\ndone:\n\treturn (error);\n\nbad:\n\tm_freem(m0);\n\tgoto done;\n}\n"
  },
  {
    "path": "src/slirp/libslirp.h",
    "content": "#ifndef _LIBSLIRP_H\n#define _LIBSLIRP_H\n\n#ifdef CONFIG_SLIRP\n\n#include <netinet/in.h>\n\nstruct Slirp;\ntypedef struct Slirp Slirp;\n\nint get_dns_addr(struct in_addr *pdns_addr);\n\nSlirp *slirp_init(int restricted, struct in_addr vnetwork,\n                  struct in_addr vnetmask, struct in_addr vhost,\n                  const char *vhostname, const char *tftp_path,\n                  const char *bootfile, struct in_addr vdhcp_start,\n                  struct in_addr vnameserver, void *opaque);\nvoid slirp_cleanup(Slirp *slirp);\n\nvoid slirp_select_fill(Slirp *slirp, int *pnfds,\n                       fd_set *readfds, fd_set *writefds, fd_set *xfds);\n\nvoid slirp_select_poll(Slirp *slirp,\n                       fd_set *readfds, fd_set *writefds, fd_set *xfds,\n                       int select_error);\n\nvoid slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);\n\n/* you must provide the following functions: */\nint slirp_can_output(void *opaque);\nvoid slirp_output(void *opaque, const uint8_t *pkt, int pkt_len);\n\nint slirp_add_hostfwd(Slirp *slirp, int is_udp,\n                      struct in_addr host_addr, int host_port,\n                      struct in_addr guest_addr, int guest_port);\nint slirp_remove_hostfwd(Slirp *slirp, int is_udp,\n                         struct in_addr host_addr, int host_port);\nint slirp_add_exec(Slirp *slirp, int do_pty, const void *args,\n                   struct in_addr *guest_addr, int guest_port);\n\nvoid slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr,\n                       int guest_port, const uint8_t *buf, int size);\nsize_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,\n                             int guest_port);\nint slirp_get_time_ms(void);\n\n#else /* !CONFIG_SLIRP */\n\nstatic inline void slirp_select_fill(int *pnfds, fd_set *readfds,\n                                     fd_set *writefds, fd_set *xfds) { }\n\nstatic inline void slirp_select_poll(fd_set *readfds, fd_set *writefds,\n                                     fd_set *xfds, int select_error) { }\n#endif /* !CONFIG_SLIRP */\n\n#endif\n"
  },
  {
    "path": "src/slirp/main.h",
    "content": "/*\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#ifdef HAVE_SYS_SELECT_H\n#include <sys/select.h>\n#endif\n\n#define TOWRITEMAX 512\n\nextern int slirp_socket;\nextern int slirp_socket_unit;\nextern int slirp_socket_port;\nextern uint32_t slirp_socket_addr;\nextern char *slirp_socket_passwd;\nextern int ctty_closed;\n\n/*\n * Get the difference in 2 times from updtim()\n * Allow for wraparound times, \"just in case\"\n * x is the greater of the 2 (current time) and y is\n * what it's being compared against.\n */\n#define TIME_DIFF(x,y) (x)-(y) < 0 ? ~0-(y)+(x) : (x)-(y)\n\nextern char *slirp_tty;\nextern char *exec_shell;\nextern u_int curtime;\nextern fd_set *global_readfds, *global_writefds, *global_xfds;\nextern struct in_addr loopback_addr;\nextern char *username;\nextern char *socket_path;\nextern int towrite_max;\nextern int ppp_exit;\nextern int tcp_keepintvl;\n\n#define PROTO_SLIP 0x1\n#ifdef USE_PPP\n#define PROTO_PPP 0x2\n#endif\n\nvoid if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len);\nssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags);\n"
  },
  {
    "path": "src/slirp/mbuf.c",
    "content": "/*\n * Copyright (c) 1995 Danny Gasparovski\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n/*\n * mbuf's in SLiRP are much simpler than the real mbufs in\n * FreeBSD.  They are fixed size, determined by the MTU,\n * so that one whole packet can fit.  Mbuf's cannot be\n * chained together.  If there's more data than the mbuf\n * could hold, an external malloced buffer is pointed to\n * by m_ext (and the data pointers) and M_EXT is set in\n * the flags\n */\n\n#include \"slirp.h\"\n\n#define MBUF_THRESH 30\n\n/*\n * Find a nice value for msize\n * XXX if_maxlinkhdr already in mtu\n */\n#define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + offsetof(struct mbuf, m_dat) + 6)\n\nvoid\nm_init(Slirp *slirp)\n{\n    slirp->m_freelist.m_next = slirp->m_freelist.m_prev = &slirp->m_freelist;\n    slirp->m_usedlist.m_next = slirp->m_usedlist.m_prev = &slirp->m_usedlist;\n}\n\n/*\n * Get an mbuf from the free list, if there are none\n * malloc one\n *\n * Because fragmentation can occur if we alloc new mbufs and\n * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,\n * which tells m_free to actually free() it\n */\nstruct mbuf *\nm_get(Slirp *slirp)\n{\n\tregister struct mbuf *m;\n\tint flags = 0;\n\n\tDEBUG_CALL(\"m_get\");\n\n\tif (slirp->m_freelist.m_next == &slirp->m_freelist) {\n\t\tm = (struct mbuf *)malloc(SLIRP_MSIZE);\n\t\tif (m == NULL) goto end_error;\n\t\tslirp->mbuf_alloced++;\n\t\tif (slirp->mbuf_alloced > MBUF_THRESH)\n\t\t\tflags = M_DOFREE;\n\t\tm->slirp = slirp;\n\t} else {\n\t\tm = slirp->m_freelist.m_next;\n\t\tremque(m);\n\t}\n\n\t/* Insert it in the used list */\n\tinsque(m,&slirp->m_usedlist);\n\tm->m_flags = (flags | M_USEDLIST);\n\n\t/* Initialise it */\n\tm->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat);\n\tm->m_data = m->m_dat;\n\tm->m_len = 0;\n        m->m_nextpkt = NULL;\n        m->m_prevpkt = NULL;\nend_error:\n\tDEBUG_ARG(\"m = %lx\", (long )m);\n\treturn m;\n}\n\nvoid\nm_free(struct mbuf *m)\n{\n\n  DEBUG_CALL(\"m_free\");\n  DEBUG_ARG(\"m = %lx\", (long )m);\n\n  if(m) {\n\t/* Remove from m_usedlist */\n\tif (m->m_flags & M_USEDLIST)\n\t   remque(m);\n\n\t/* If it's M_EXT, free() it */\n\tif (m->m_flags & M_EXT)\n\t   free(m->m_ext);\n\n\t/*\n\t * Either free() it or put it on the free list\n\t */\n\tif (m->m_flags & M_DOFREE) {\n\t\tm->slirp->mbuf_alloced--;\n\t\tfree(m);\n\t} else if ((m->m_flags & M_FREELIST) == 0) {\n\t\tinsque(m,&m->slirp->m_freelist);\n\t\tm->m_flags = M_FREELIST; /* Clobber other flags */\n\t}\n  } /* if(m) */\n}\n\n/*\n * Copy data from one mbuf to the end of\n * the other.. if result is too big for one mbuf, malloc()\n * an M_EXT data segment\n */\nvoid\nm_cat(struct mbuf *m, struct mbuf *n)\n{\n\t/*\n\t * If there's no room, realloc\n\t */\n\tif (M_FREEROOM(m) < n->m_len)\n\t\tm_inc(m,m->m_size+MINCSIZE);\n\n\tmemcpy(m->m_data+m->m_len, n->m_data, n->m_len);\n\tm->m_len += n->m_len;\n\n\tm_free(n);\n}\n\n\n/* make m size bytes large */\nvoid\nm_inc(struct mbuf *m, int size)\n{\n\tint datasize;\n\n\t/* some compiles throw up on gotos.  This one we can fake. */\n        if(m->m_size>size) return;\n\n        if (m->m_flags & M_EXT) {\n\t  datasize = m->m_data - m->m_ext;\n\t  m->m_ext = (char *)realloc(m->m_ext,size);\n\t  m->m_data = m->m_ext + datasize;\n        } else {\n\t  char *dat;\n\t  datasize = m->m_data - m->m_dat;\n\t  dat = (char *)malloc(size);\n\t  memcpy(dat, m->m_dat, m->m_size);\n\n\t  m->m_ext = dat;\n\t  m->m_data = m->m_ext + datasize;\n\t  m->m_flags |= M_EXT;\n        }\n\n        m->m_size = size;\n\n}\n\n\n\nvoid\nm_adj(struct mbuf *m, int len)\n{\n\tif (m == NULL)\n\t\treturn;\n\tif (len >= 0) {\n\t\t/* Trim from head */\n\t\tm->m_data += len;\n\t\tm->m_len -= len;\n\t} else {\n\t\t/* Trim from tail */\n\t\tlen = -len;\n\t\tm->m_len -= len;\n\t}\n}\n\n\n/*\n * Copy len bytes from m, starting off bytes into n\n */\nint\nm_copy(struct mbuf *n, struct mbuf *m, int off, int len)\n{\n\tif (len > M_FREEROOM(n))\n\t\treturn -1;\n\n\tmemcpy((n->m_data + n->m_len), (m->m_data + off), len);\n\tn->m_len += len;\n\treturn 0;\n}\n\n\n/*\n * Given a pointer into an mbuf, return the mbuf\n * XXX This is a kludge, I should eliminate the need for it\n * Fortunately, it's not used often\n */\nstruct mbuf *\ndtom(Slirp *slirp, void *dat)\n{\n\tstruct mbuf *m;\n\n\tDEBUG_CALL(\"dtom\");\n\tDEBUG_ARG(\"dat = %lx\", (long )dat);\n\n\t/* bug corrected for M_EXT buffers */\n\tfor (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist;\n\t     m = m->m_next) {\n\t  if (m->m_flags & M_EXT) {\n\t    if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )\n\t      return m;\n\t  } else {\n\t    if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )\n\t      return m;\n\t  }\n\t}\n\n\tDEBUG_ERROR((dfd, \"dtom failed\"));\n\n\treturn (struct mbuf *)0;\n}\n"
  },
  {
    "path": "src/slirp/mbuf.h",
    "content": "/*\n * Copyright (c) 1982, 1986, 1988, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)mbuf.h\t8.3 (Berkeley) 1/21/94\n * mbuf.h,v 1.9 1994/11/14 13:54:20 bde Exp\n */\n\n#ifndef _MBUF_H_\n#define _MBUF_H_\n\n#define m_freem m_free\n\n\n#define MINCSIZE 4096\t/* Amount to increase mbuf if too small */\n\n/*\n * Macros for type conversion\n * mtod(m,t) -\tconvert mbuf pointer to data pointer of correct type\n */\n#define mtod(m,t)\t((t)(m)->m_data)\n\n/* XXX About mbufs for slirp:\n * Only one mbuf is ever used in a chain, for each \"cell\" of data.\n * m_nextpkt points to the next packet, if fragmented.\n * If the data is too large, the M_EXT is used, and a larger block\n * is alloced.  Therefore, m_free[m] must check for M_EXT and if set\n * free the m_ext.  This is inefficient memory-wise, but who cares.\n */\n\n/* XXX should union some of these! */\n/* header at beginning of each mbuf: */\nstruct m_hdr {\n\tstruct\tmbuf *mh_next;\t\t/* Linked list of mbufs */\n\tstruct\tmbuf *mh_prev;\n\tstruct\tmbuf *mh_nextpkt;\t/* Next packet in queue/record */\n\tstruct\tmbuf *mh_prevpkt; /* Flags aren't used in the output queue */\n\tint\tmh_flags;\t  /* Misc flags */\n\n\tint\tmh_size;\t\t/* Size of data */\n\tstruct\tsocket *mh_so;\n\n\tcaddr_t\tmh_data;\t\t/* Location of data */\n\tint\tmh_len;\t\t\t/* Amount of data in this mbuf */\n};\n\n/*\n * How much room is in the mbuf, from m_data to the end of the mbuf\n */\n#define M_ROOM(m) ((m->m_flags & M_EXT)? \\\n\t\t\t(((m)->m_ext + (m)->m_size) - (m)->m_data) \\\n\t\t   : \\\n\t\t\t(((m)->m_dat + (m)->m_size) - (m)->m_data))\n\n/*\n * How much free room there is\n */\n#define M_FREEROOM(m) (M_ROOM(m) - (m)->m_len)\n#define M_TRAILINGSPACE M_FREEROOM\n\nstruct mbuf {\n\tstruct\tm_hdr m_hdr;\n\tSlirp *slirp;\n\tunion M_dat {\n\t\tchar\tm_dat_[1]; /* ANSI don't like 0 sized arrays */\n\t\tchar\t*m_ext_;\n\t} M_dat;\n};\n\n#define m_next\t\tm_hdr.mh_next\n#define m_prev\t\tm_hdr.mh_prev\n#define m_nextpkt\tm_hdr.mh_nextpkt\n#define m_prevpkt\tm_hdr.mh_prevpkt\n#define m_flags\t\tm_hdr.mh_flags\n#define\tm_len\t\tm_hdr.mh_len\n#define\tm_data\t\tm_hdr.mh_data\n#define m_size\t\tm_hdr.mh_size\n#define m_dat\t\tM_dat.m_dat_\n#define m_ext\t\tM_dat.m_ext_\n#define m_so\t\tm_hdr.mh_so\n\n#define ifq_prev m_prev\n#define ifq_next m_next\n#define ifs_prev m_prevpkt\n#define ifs_next m_nextpkt\n#define ifq_so m_so\n\n#define M_EXT\t\t\t0x01\t/* m_ext points to more (malloced) data */\n#define M_FREELIST\t\t0x02\t/* mbuf is on free list */\n#define M_USEDLIST\t\t0x04\t/* XXX mbuf is on used list (for dtom()) */\n#define M_DOFREE\t\t0x08\t/* when m_free is called on the mbuf, free()\n\t\t\t\t\t * it rather than putting it on the free list */\n\nvoid m_init(Slirp *);\nstruct mbuf * m_get(Slirp *);\nvoid m_free(struct mbuf *);\nvoid m_cat(register struct mbuf *, register struct mbuf *);\nvoid m_inc(struct mbuf *, int);\nvoid m_adj(struct mbuf *, int);\nint m_copy(struct mbuf *, struct mbuf *, int, int);\nstruct mbuf * dtom(Slirp *, void *);\n\n#endif\n"
  },
  {
    "path": "src/slirp/misc.c",
    "content": "/*\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#include \"slirp.h\"\n\n#ifdef DEBUG\nint slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;\n#endif\n\nstruct quehead {\n\tstruct quehead *qh_link;\n\tstruct quehead *qh_rlink;\n};\n\ninline void\ninsque(void *a, void *b)\n{\n\tregister struct quehead *element = (struct quehead *) a;\n\tregister struct quehead *head = (struct quehead *) b;\n\telement->qh_link = head->qh_link;\n\thead->qh_link = (struct quehead *)element;\n\telement->qh_rlink = (struct quehead *)head;\n\t((struct quehead *)(element->qh_link))->qh_rlink\n\t= (struct quehead *)element;\n}\n\ninline void\nremque(void *a)\n{\n  register struct quehead *element = (struct quehead *) a;\n  ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;\n  ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;\n  element->qh_rlink = NULL;\n}\n\nint add_exec(struct ex_list **ex_ptr, int do_pty, char *exec,\n             struct in_addr addr, int port)\n{\n\tstruct ex_list *tmp_ptr;\n\n\t/* First, check if the port is \"bound\" */\n\tfor (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {\n\t\tif (port == tmp_ptr->ex_fport &&\n\t\t    addr.s_addr == tmp_ptr->ex_addr.s_addr)\n\t\t\treturn -1;\n\t}\n\n\ttmp_ptr = *ex_ptr;\n\t*ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));\n\t(*ex_ptr)->ex_fport = port;\n\t(*ex_ptr)->ex_addr = addr;\n\t(*ex_ptr)->ex_pty = do_pty;\n\t(*ex_ptr)->ex_exec = (do_pty == 3) ? exec : strdup(exec);\n\t(*ex_ptr)->ex_next = tmp_ptr;\n\treturn 0;\n}\n\n#ifndef HAVE_STRERROR\n\n/*\n * For systems with no strerror\n */\n\nextern int sys_nerr;\nextern char *sys_errlist[];\n\nchar *\nstrerror(error)\n\tint error;\n{\n\tif (error < sys_nerr)\n\t   return sys_errlist[error];\n\telse\n\t   return \"Unknown error.\";\n}\n\n#endif\n\nint os_socket(int domain, int type, int protocol)\n{\n    return socket(domain, type, protocol);\n}\n\nuint32_t os_get_time_ms(void)\n{\n    struct timespec ts;\n\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    return ts.tv_sec * 1000 +\n        (ts.tv_nsec / 1000000);\n}\n\n\n#if 1\n\nint\nfork_exec(struct socket *so, const char *ex, int do_pty)\n{\n    /* not implemented */\n    return 0;\n}\n\n#else\n\n/*\n * XXX This is ugly\n * We create and bind a socket, then fork off to another\n * process, which connects to this socket, after which we\n * exec the wanted program.  If something (strange) happens,\n * the accept() call could block us forever.\n *\n * do_pty = 0   Fork/exec inetd style\n * do_pty = 1   Fork/exec using slirp.telnetd\n * do_ptr = 2   Fork/exec using pty\n */\nint\nfork_exec(struct socket *so, const char *ex, int do_pty)\n{\n\tint s;\n\tstruct sockaddr_in addr;\n\tsocklen_t addrlen = sizeof(addr);\n\tint opt;\n        int master = -1;\n\tconst char *argv[256];\n\t/* don't want to clobber the original */\n\tchar *bptr;\n\tconst char *curarg;\n\tint c, i, ret;\n\n\tDEBUG_CALL(\"fork_exec\");\n\tDEBUG_ARG(\"so = %lx\", (long)so);\n\tDEBUG_ARG(\"ex = %lx\", (long)ex);\n\tDEBUG_ARG(\"do_pty = %lx\", (long)do_pty);\n\n\tif (do_pty == 2) {\n                return 0;\n\t} else {\n\t\taddr.sin_family = AF_INET;\n\t\taddr.sin_port = 0;\n\t\taddr.sin_addr.s_addr = INADDR_ANY;\n\n\t\tif ((s = os_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||\n\t\t    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||\n\t\t    listen(s, 1) < 0) {\n\t\t\tlprint(\"Error: inet socket: %s\\n\", strerror(errno));\n\t\t\tclosesocket(s);\n\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tswitch(fork()) {\n\t case -1:\n\t\tlprint(\"Error: fork failed: %s\\n\", strerror(errno));\n\t\tclose(s);\n\t\tif (do_pty == 2)\n\t\t   close(master);\n\t\treturn 0;\n\n\t case 0:\n\t\t/* Set the DISPLAY */\n\t\tif (do_pty == 2) {\n\t\t\t(void) close(master);\n#ifdef TIOCSCTTY /* XXXXX */\n\t\t\t(void) setsid();\n\t\t\tioctl(s, TIOCSCTTY, (char *)NULL);\n#endif\n\t\t} else {\n\t\t\tgetsockname(s, (struct sockaddr *)&addr, &addrlen);\n\t\t\tclose(s);\n\t\t\t/*\n\t\t\t * Connect to the socket\n\t\t\t * XXX If any of these fail, we're in trouble!\n\t \t\t */\n\t\t\ts = os_socket(AF_INET, SOCK_STREAM, 0);\n\t\t\taddr.sin_addr = loopback_addr;\n                        do {\n                            ret = connect(s, (struct sockaddr *)&addr, addrlen);\n                        } while (ret < 0 && errno == EINTR);\n\t\t}\n\n\t\tdup2(s, 0);\n\t\tdup2(s, 1);\n\t\tdup2(s, 2);\n\t\tfor (s = getdtablesize() - 1; s >= 3; s--)\n\t\t   close(s);\n\n\t\ti = 0;\n\t\tbptr = qemu_strdup(ex); /* No need to free() this */\n\t\tif (do_pty == 1) {\n\t\t\t/* Setup \"slirp.telnetd -x\" */\n\t\t\targv[i++] = \"slirp.telnetd\";\n\t\t\targv[i++] = \"-x\";\n\t\t\targv[i++] = bptr;\n\t\t} else\n\t\t   do {\n\t\t\t/* Change the string into argv[] */\n\t\t\tcurarg = bptr;\n\t\t\twhile (*bptr != ' ' && *bptr != (char)0)\n\t\t\t   bptr++;\n\t\t\tc = *bptr;\n\t\t\t*bptr++ = (char)0;\n\t\t\targv[i++] = strdup(curarg);\n\t\t   } while (c);\n\n                argv[i] = NULL;\n\t\texecvp(argv[0], (char **)argv);\n\n\t\t/* Ooops, failed, let's tell the user why */\n        fprintf(stderr, \"Error: execvp of %s failed: %s\\n\",\n                argv[0], strerror(errno));\n\t\tclose(0); close(1); close(2); /* XXX */\n\t\texit(1);\n\n\t default:\n\t\tif (do_pty == 2) {\n\t\t\tclose(s);\n\t\t\tso->s = master;\n\t\t} else {\n\t\t\t/*\n\t\t\t * XXX this could block us...\n\t\t\t * XXX Should set a timer here, and if accept() doesn't\n\t\t \t * return after X seconds, declare it a failure\n\t\t \t * The only reason this will block forever is if socket()\n\t\t \t * of connect() fail in the child process\n\t\t \t */\n                        do {\n                            so->s = accept(s, (struct sockaddr *)&addr, &addrlen);\n                        } while (so->s < 0 && errno == EINTR);\n                        closesocket(s);\n\t\t\topt = 1;\n\t\t\tsetsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));\n\t\t\topt = 1;\n\t\t\tsetsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));\n\t\t}\n\t\tfd_nonblock(so->s);\n\n\t\t/* Append the telnet options now */\n                if (so->so_m != NULL && do_pty == 1)  {\n\t\t\tsbappend(so, so->so_m);\n                        so->so_m = NULL;\n\t\t}\n\n\t\treturn 1;\n\t}\n}\n#endif\n\n#ifndef HAVE_STRDUP\nchar *\nstrdup(str)\n\tconst char *str;\n{\n\tchar *bptr;\n\n\tbptr = (char *)malloc(strlen(str)+1);\n\tstrcpy(bptr, str);\n\n\treturn bptr;\n}\n#endif\n\nvoid lprint(const char *format, ...)\n{\n    va_list args;\n\n    va_start(args, format);\n    vprintf(format, args);\n    va_end(args);\n}\n\n/*\n * Set fd blocking and non-blocking\n */\n\nvoid\nfd_nonblock(int fd)\n{\n#ifdef FIONBIO\n#ifdef _WIN32\n        unsigned long opt = 1;\n#else\n        int opt = 1;\n#endif\n\n\tioctlsocket(fd, FIONBIO, &opt);\n#else\n\tint opt;\n\n\topt = fcntl(fd, F_GETFL, 0);\n\topt |= O_NONBLOCK;\n\tfcntl(fd, F_SETFL, opt);\n#endif\n}\n\nvoid\nfd_block(int fd)\n{\n#ifdef FIONBIO\n#ifdef _WIN32\n        unsigned long opt = 0;\n#else\n\tint opt = 0;\n#endif\n\n\tioctlsocket(fd, FIONBIO, &opt);\n#else\n\tint opt;\n\n\topt = fcntl(fd, F_GETFL, 0);\n\topt &= ~O_NONBLOCK;\n\tfcntl(fd, F_SETFL, opt);\n#endif\n}\n\n#if 0\nvoid slirp_connection_info(Slirp *slirp, Monitor *mon)\n{\n    const char * const tcpstates[] = {\n        [TCPS_CLOSED]       = \"CLOSED\",\n        [TCPS_LISTEN]       = \"LISTEN\",\n        [TCPS_SYN_SENT]     = \"SYN_SENT\",\n        [TCPS_SYN_RECEIVED] = \"SYN_RCVD\",\n        [TCPS_ESTABLISHED]  = \"ESTABLISHED\",\n        [TCPS_CLOSE_WAIT]   = \"CLOSE_WAIT\",\n        [TCPS_FIN_WAIT_1]   = \"FIN_WAIT_1\",\n        [TCPS_CLOSING]      = \"CLOSING\",\n        [TCPS_LAST_ACK]     = \"LAST_ACK\",\n        [TCPS_FIN_WAIT_2]   = \"FIN_WAIT_2\",\n        [TCPS_TIME_WAIT]    = \"TIME_WAIT\",\n    };\n    struct in_addr dst_addr;\n    struct sockaddr_in src;\n    socklen_t src_len;\n    uint16_t dst_port;\n    struct socket *so;\n    const char *state;\n    char buf[20];\n    int n;\n\n    monitor_printf(mon, \"  Protocol[State]    FD  Source Address  Port   \"\n                        \"Dest. Address  Port RecvQ SendQ\\n\");\n\n    for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {\n        if (so->so_state & SS_HOSTFWD) {\n            state = \"HOST_FORWARD\";\n        } else if (so->so_tcpcb) {\n            state = tcpstates[so->so_tcpcb->t_state];\n        } else {\n            state = \"NONE\";\n        }\n        if (so->so_state & (SS_HOSTFWD | SS_INCOMING)) {\n            src_len = sizeof(src);\n            getsockname(so->s, (struct sockaddr *)&src, &src_len);\n            dst_addr = so->so_laddr;\n            dst_port = so->so_lport;\n        } else {\n            src.sin_addr = so->so_laddr;\n            src.sin_port = so->so_lport;\n            dst_addr = so->so_faddr;\n            dst_port = so->so_fport;\n        }\n        n = snprintf(buf, sizeof(buf), \"  TCP[%s]\", state);\n        memset(&buf[n], ' ', 19 - n);\n        buf[19] = 0;\n        monitor_printf(mon, \"%s %3d %15s %5d \", buf, so->s,\n                       src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : \"*\",\n                       ntohs(src.sin_port));\n        monitor_printf(mon, \"%15s %5d %5d %5d\\n\",\n                       inet_ntoa(dst_addr), ntohs(dst_port),\n                       so->so_rcv.sb_cc, so->so_snd.sb_cc);\n    }\n\n    for (so = slirp->udb.so_next; so != &slirp->udb; so = so->so_next) {\n        if (so->so_state & SS_HOSTFWD) {\n            n = snprintf(buf, sizeof(buf), \"  UDP[HOST_FORWARD]\");\n            src_len = sizeof(src);\n            getsockname(so->s, (struct sockaddr *)&src, &src_len);\n            dst_addr = so->so_laddr;\n            dst_port = so->so_lport;\n        } else {\n            n = snprintf(buf, sizeof(buf), \"  UDP[%d sec]\",\n                         (so->so_expire - curtime) / 1000);\n            src.sin_addr = so->so_laddr;\n            src.sin_port = so->so_lport;\n            dst_addr = so->so_faddr;\n            dst_port = so->so_fport;\n        }\n        memset(&buf[n], ' ', 19 - n);\n        buf[19] = 0;\n        monitor_printf(mon, \"%s %3d %15s %5d \", buf, so->s,\n                       src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : \"*\",\n                       ntohs(src.sin_port));\n        monitor_printf(mon, \"%15s %5d %5d %5d\\n\",\n                       inet_ntoa(dst_addr), ntohs(dst_port),\n                       so->so_rcv.sb_cc, so->so_snd.sb_cc);\n    }\n}\n#endif\n"
  },
  {
    "path": "src/slirp/misc.h",
    "content": "/*\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#ifndef _MISC_H_\n#define _MISC_H_\n\nstruct ex_list {\n\tint ex_pty;\t\t\t/* Do we want a pty? */\n\tstruct in_addr ex_addr;\t\t/* Server address */\n\tint ex_fport;                   /* Port to telnet to */\n\tconst char *ex_exec;            /* Command line of what to exec */\n\tstruct ex_list *ex_next;\n};\n\n#ifndef HAVE_STRDUP\nchar *strdup(const char *);\n#endif\n\nvoid do_wait(int);\n\n#define EMU_NONE 0x0\n\n/* TCP emulations */\n#define EMU_CTL 0x1\n#define EMU_FTP 0x2\n#define EMU_KSH 0x3\n#define EMU_IRC 0x4\n#define EMU_REALAUDIO 0x5\n#define EMU_RLOGIN 0x6\n#define EMU_IDENT 0x7\n#define EMU_RSH 0x8\n\n#define EMU_NOCONNECT 0x10\t/* Don't connect */\n\nstruct tos_t {\n    uint16_t lport;\n    uint16_t fport;\n    uint8_t tos;\n    uint8_t emu;\n};\n\nstruct emu_t {\n    uint16_t lport;\n    uint16_t fport;\n    uint8_t tos;\n    uint8_t emu;\n    struct emu_t *next;\n};\n\nextern int x_port, x_server, x_display;\n\nint show_x(char *, struct socket *);\nvoid redir_x(uint32_t, int, int, int);\nvoid slirp_insque(void *, void *);\nvoid slirp_remque(void *);\nint add_exec(struct ex_list **, int, char *, struct in_addr, int);\nint slirp_openpty(int *, int *);\nint fork_exec(struct socket *so, const char *ex, int do_pty);\nvoid snooze_hup(int);\nvoid snooze(void);\nvoid relay(int);\nvoid add_emu(char *);\nvoid fd_nonblock(int);\nvoid fd_block(int);\nint rsh_exec(struct socket *, struct socket *, char *, char *, char *);\nint os_socket(int domain, int type, int protocol);\nuint32_t os_get_time_ms(void);\n\n#endif\n"
  },
  {
    "path": "src/slirp/sbuf.c",
    "content": "/*\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#include \"slirp.h\"\n\nstatic void sbappendsb(struct sbuf *sb, struct mbuf *m);\n\nvoid\nsbfree(struct sbuf *sb)\n{\n\tfree(sb->sb_data);\n}\n\nvoid\nsbdrop(struct sbuf *sb, int num)\n{\n\t/*\n\t * We can only drop how much we have\n\t * This should never succeed\n\t */\n\tif(num > sb->sb_cc)\n\t\tnum = sb->sb_cc;\n\tsb->sb_cc -= num;\n\tsb->sb_rptr += num;\n\tif(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)\n\t\tsb->sb_rptr -= sb->sb_datalen;\n\n}\n\nvoid\nsbreserve(struct sbuf *sb, int size)\n{\n\tif (sb->sb_data) {\n\t\t/* Already alloced, realloc if necessary */\n\t\tif (sb->sb_datalen != size) {\n\t\t\tsb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);\n\t\t\tsb->sb_cc = 0;\n\t\t\tif (sb->sb_wptr)\n\t\t\t   sb->sb_datalen = size;\n\t\t\telse\n\t\t\t   sb->sb_datalen = 0;\n\t\t}\n\t} else {\n\t\tsb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);\n\t\tsb->sb_cc = 0;\n\t\tif (sb->sb_wptr)\n\t\t   sb->sb_datalen = size;\n\t\telse\n\t\t   sb->sb_datalen = 0;\n\t}\n}\n\n/*\n * Try and write() to the socket, whatever doesn't get written\n * append to the buffer... for a host with a fast net connection,\n * this prevents an unnecessary copy of the data\n * (the socket is non-blocking, so we won't hang)\n */\nvoid\nsbappend(struct socket *so, struct mbuf *m)\n{\n\tint ret = 0;\n\n\tDEBUG_CALL(\"sbappend\");\n\tDEBUG_ARG(\"so = %lx\", (long)so);\n\tDEBUG_ARG(\"m = %lx\", (long)m);\n\tDEBUG_ARG(\"m->m_len = %d\", m->m_len);\n\n\t/* Shouldn't happen, but...  e.g. foreign host closes connection */\n\tif (m->m_len <= 0) {\n\t\tm_free(m);\n\t\treturn;\n\t}\n\n\t/*\n\t * If there is urgent data, call sosendoob\n\t * if not all was sent, sowrite will take care of the rest\n\t * (The rest of this function is just an optimisation)\n\t */\n\tif (so->so_urgc) {\n\t\tsbappendsb(&so->so_rcv, m);\n\t\tm_free(m);\n\t\tsosendoob(so);\n\t\treturn;\n\t}\n\n\t/*\n\t * We only write if there's nothing in the buffer,\n\t * ottherwise it'll arrive out of order, and hence corrupt\n\t */\n\tif (!so->so_rcv.sb_cc)\n\t   ret = slirp_send(so, m->m_data, m->m_len, 0);\n\n\tif (ret <= 0) {\n\t\t/*\n\t\t * Nothing was written\n\t\t * It's possible that the socket has closed, but\n\t\t * we don't need to check because if it has closed,\n\t\t * it will be detected in the normal way by soread()\n\t\t */\n\t\tsbappendsb(&so->so_rcv, m);\n\t} else if (ret != m->m_len) {\n\t\t/*\n\t\t * Something was written, but not everything..\n\t\t * sbappendsb the rest\n\t\t */\n\t\tm->m_len -= ret;\n\t\tm->m_data += ret;\n\t\tsbappendsb(&so->so_rcv, m);\n\t} /* else */\n\t/* Whatever happened, we free the mbuf */\n\tm_free(m);\n}\n\n/*\n * Copy the data from m into sb\n * The caller is responsible to make sure there's enough room\n */\nstatic void\nsbappendsb(struct sbuf *sb, struct mbuf *m)\n{\n\tint len, n,  nn;\n\n\tlen = m->m_len;\n\n\tif (sb->sb_wptr < sb->sb_rptr) {\n\t\tn = sb->sb_rptr - sb->sb_wptr;\n\t\tif (n > len) n = len;\n\t\tmemcpy(sb->sb_wptr, m->m_data, n);\n\t} else {\n\t\t/* Do the right edge first */\n\t\tn = sb->sb_data + sb->sb_datalen - sb->sb_wptr;\n\t\tif (n > len) n = len;\n\t\tmemcpy(sb->sb_wptr, m->m_data, n);\n\t\tlen -= n;\n\t\tif (len) {\n\t\t\t/* Now the left edge */\n\t\t\tnn = sb->sb_rptr - sb->sb_data;\n\t\t\tif (nn > len) nn = len;\n\t\t\tmemcpy(sb->sb_data,m->m_data+n,nn);\n\t\t\tn += nn;\n\t\t}\n\t}\n\n\tsb->sb_cc += n;\n\tsb->sb_wptr += n;\n\tif (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)\n\t\tsb->sb_wptr -= sb->sb_datalen;\n}\n\n/*\n * Copy data from sbuf to a normal, straight buffer\n * Don't update the sbuf rptr, this will be\n * done in sbdrop when the data is acked\n */\nvoid\nsbcopy(struct sbuf *sb, int off, int len, char *to)\n{\n\tchar *from;\n\n\tfrom = sb->sb_rptr + off;\n\tif (from >= sb->sb_data + sb->sb_datalen)\n\t\tfrom -= sb->sb_datalen;\n\n\tif (from < sb->sb_wptr) {\n\t\tif (len > sb->sb_cc) len = sb->sb_cc;\n\t\tmemcpy(to,from,len);\n\t} else {\n\t\t/* re-use off */\n\t\toff = (sb->sb_data + sb->sb_datalen) - from;\n\t\tif (off > len) off = len;\n\t\tmemcpy(to,from,off);\n\t\tlen -= off;\n\t\tif (len)\n\t\t   memcpy(to+off,sb->sb_data,len);\n\t}\n}\n"
  },
  {
    "path": "src/slirp/sbuf.h",
    "content": "/*\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#ifndef _SBUF_H_\n#define _SBUF_H_\n\n#define sbflush(sb) sbdrop((sb),(sb)->sb_cc)\n#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)\n\nstruct sbuf {\n\tu_int\tsb_cc;\t\t/* actual chars in buffer */\n\tu_int\tsb_datalen;\t/* Length of data  */\n\tchar\t*sb_wptr;\t/* write pointer. points to where the next\n\t\t\t\t * bytes should be written in the sbuf */\n\tchar\t*sb_rptr;\t/* read pointer. points to where the next\n\t\t\t\t * byte should be read from the sbuf */\n\tchar\t*sb_data;\t/* Actual data */\n};\n\nvoid sbfree(struct sbuf *);\nvoid sbdrop(struct sbuf *, int);\nvoid sbreserve(struct sbuf *, int);\nvoid sbappend(struct socket *, struct mbuf *);\nvoid sbcopy(struct sbuf *, int, int, char *);\n\n#endif\n"
  },
  {
    "path": "src/slirp/slirp.c",
    "content": "/*\n * libslirp glue\n *\n * Copyright (c) 2004-2008 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include \"slirp.h\"\n\n/* host loopback address */\nstruct in_addr loopback_addr;\n\n/* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */\nstatic const uint8_t special_ethaddr[6] = {\n    0x52, 0x55, 0x00, 0x00, 0x00, 0x00\n};\n\nstatic const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };\n\n/* XXX: suppress those select globals */\nfd_set *global_readfds, *global_writefds, *global_xfds;\n\nu_int curtime;\nstatic u_int time_fasttimo, last_slowtimo;\nstatic int do_slowtimo;\n\nstatic struct in_addr dns_addr;\nstatic u_int dns_addr_time;\n\n#ifdef _WIN32\n\nint get_dns_addr(struct in_addr *pdns_addr)\n{\n    FIXED_INFO *FixedInfo=NULL;\n    ULONG    BufLen;\n    DWORD    ret;\n    IP_ADDR_STRING *pIPAddr;\n    struct in_addr tmp_addr;\n\n    if (dns_addr.s_addr != 0 && (curtime - dns_addr_time) < 1000) {\n        *pdns_addr = dns_addr;\n        return 0;\n    }\n\n    FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));\n    BufLen = sizeof(FIXED_INFO);\n\n    if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {\n        if (FixedInfo) {\n            GlobalFree(FixedInfo);\n            FixedInfo = NULL;\n        }\n        FixedInfo = GlobalAlloc(GPTR, BufLen);\n    }\n\n    if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {\n        printf(\"GetNetworkParams failed. ret = %08x\\n\", (u_int)ret );\n        if (FixedInfo) {\n            GlobalFree(FixedInfo);\n            FixedInfo = NULL;\n        }\n        return -1;\n    }\n\n    pIPAddr = &(FixedInfo->DnsServerList);\n    inet_aton(pIPAddr->IpAddress.String, &tmp_addr);\n    *pdns_addr = tmp_addr;\n    dns_addr = tmp_addr;\n    dns_addr_time = curtime;\n    if (FixedInfo) {\n        GlobalFree(FixedInfo);\n        FixedInfo = NULL;\n    }\n    return 0;\n}\n\nstatic void winsock_cleanup(void)\n{\n    WSACleanup();\n}\n\n#else\n\nstatic struct stat dns_addr_stat;\n\nint get_dns_addr(struct in_addr *pdns_addr)\n{\n    char buff[512];\n    char buff2[257];\n    FILE *f;\n    int found = 0;\n    struct in_addr tmp_addr;\n\n    if (dns_addr.s_addr != 0) {\n        struct stat old_stat;\n        if ((curtime - dns_addr_time) < 1000) {\n            *pdns_addr = dns_addr;\n            return 0;\n        }\n        old_stat = dns_addr_stat;\n        if (stat(\"/etc/resolv.conf\", &dns_addr_stat) != 0)\n            return -1;\n        if ((dns_addr_stat.st_dev == old_stat.st_dev)\n            && (dns_addr_stat.st_ino == old_stat.st_ino)\n            && (dns_addr_stat.st_size == old_stat.st_size)\n            && (dns_addr_stat.st_mtime == old_stat.st_mtime)) {\n            *pdns_addr = dns_addr;\n            return 0;\n        }\n    }\n\n    f = fopen(\"/etc/resolv.conf\", \"r\");\n    if (!f)\n        return -1;\n\n#ifdef DEBUG\n    lprint(\"IP address of your DNS(s): \");\n#endif\n    while (fgets(buff, 512, f) != NULL) {\n        if (sscanf(buff, \"nameserver%*[ \\t]%256s\", buff2) == 1) {\n            if (!inet_aton(buff2, &tmp_addr))\n                continue;\n            /* If it's the first one, set it to dns_addr */\n            if (!found) {\n                *pdns_addr = tmp_addr;\n                dns_addr = tmp_addr;\n                dns_addr_time = curtime;\n            }\n#ifdef DEBUG\n            else\n                lprint(\", \");\n#endif\n            if (++found > 3) {\n#ifdef DEBUG\n                lprint(\"(more)\");\n#endif\n                break;\n            }\n#ifdef DEBUG\n            else\n                lprint(\"%s\", inet_ntoa(tmp_addr));\n#endif\n        }\n    }\n    fclose(f);\n    if (!found)\n        return -1;\n    return 0;\n}\n\n#endif\n\nstatic void slirp_init_once(void)\n{\n    static int initialized;\n#ifdef _WIN32\n    WSADATA Data;\n#endif\n\n    if (initialized) {\n        return;\n    }\n    initialized = 1;\n\n#ifdef _WIN32\n    WSAStartup(MAKEWORD(2,0), &Data);\n    atexit(winsock_cleanup);\n#endif\n\n    loopback_addr.s_addr = htonl(INADDR_LOOPBACK);\n}\n\nSlirp *slirp_init(int restricted, struct in_addr vnetwork,\n                  struct in_addr vnetmask, struct in_addr vhost,\n                  const char *vhostname, const char *tftp_path,\n                  const char *bootfile, struct in_addr vdhcp_start,\n                  struct in_addr vnameserver, void *opaque)\n{\n    Slirp *slirp = mallocz(sizeof(Slirp));\n\n    slirp_init_once();\n\n    slirp->restricted = restricted;\n\n    if_init(slirp);\n    ip_init(slirp);\n\n    /* Initialise mbufs *after* setting the MTU */\n    m_init(slirp);\n\n    slirp->vnetwork_addr = vnetwork;\n    slirp->vnetwork_mask = vnetmask;\n    slirp->vhost_addr = vhost;\n    if (vhostname) {\n        pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),\n                vhostname);\n    }\n    if (tftp_path) {\n        slirp->tftp_prefix = strdup(tftp_path);\n    }\n    if (bootfile) {\n        slirp->bootp_filename = strdup(bootfile);\n    }\n    slirp->vdhcp_startaddr = vdhcp_start;\n    slirp->vnameserver_addr = vnameserver;\n\n    slirp->opaque = opaque;\n\n    return slirp;\n}\n\nvoid slirp_cleanup(Slirp *slirp)\n{\n    free(slirp->tftp_prefix);\n    free(slirp->bootp_filename);\n    free(slirp);\n}\n\n#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)\n#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)\n#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)\n\nvoid slirp_select_fill(Slirp *slirp, int *pnfds,\n                       fd_set *readfds, fd_set *writefds, fd_set *xfds)\n{\n    struct socket *so, *so_next;\n    int nfds;\n\n    /* fail safe */\n    global_readfds = NULL;\n    global_writefds = NULL;\n    global_xfds = NULL;\n\n    nfds = *pnfds;\n\t/*\n\t * First, TCP sockets\n\t */\n\tdo_slowtimo = 0;\n\n\t{\n\t\t/*\n\t\t * *_slowtimo needs calling if there are IP fragments\n\t\t * in the fragment queue, or there are TCP connections active\n\t\t */\n\t\tdo_slowtimo |= ((slirp->tcb.so_next != &slirp->tcb) ||\n\t\t    (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));\n\n\t\tfor (so = slirp->tcb.so_next; so != &slirp->tcb;\n\t\t     so = so_next) {\n\t\t\tso_next = so->so_next;\n\n\t\t\t/*\n\t\t\t * See if we need a tcp_fasttimo\n\t\t\t */\n\t\t\tif (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)\n\t\t\t   time_fasttimo = curtime; /* Flag when we want a fasttimo */\n\n\t\t\t/*\n\t\t\t * NOFDREF can include still connecting to local-host,\n\t\t\t * newly socreated() sockets etc. Don't want to select these.\n\t \t\t */\n\t\t\tif (so->so_state & SS_NOFDREF || so->s == -1)\n\t\t\t   continue;\n\n\t\t\t/*\n\t\t\t * Set for reading sockets which are accepting\n\t\t\t */\n\t\t\tif (so->so_state & SS_FACCEPTCONN) {\n                                FD_SET(so->s, readfds);\n\t\t\t\tUPD_NFDS(so->s);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Set for writing sockets which are connecting\n\t\t\t */\n\t\t\tif (so->so_state & SS_ISFCONNECTING) {\n\t\t\t\tFD_SET(so->s, writefds);\n\t\t\t\tUPD_NFDS(so->s);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Set for writing if we are connected, can send more, and\n\t\t\t * we have something to send\n\t\t\t */\n\t\t\tif (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {\n\t\t\t\tFD_SET(so->s, writefds);\n\t\t\t\tUPD_NFDS(so->s);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Set for reading (and urgent data) if we are connected, can\n\t\t\t * receive more, and we have room for it XXX /2 ?\n\t\t\t */\n\t\t\tif (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {\n\t\t\t\tFD_SET(so->s, readfds);\n\t\t\t\tFD_SET(so->s, xfds);\n\t\t\t\tUPD_NFDS(so->s);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * UDP sockets\n\t\t */\n\t\tfor (so = slirp->udb.so_next; so != &slirp->udb;\n\t\t     so = so_next) {\n\t\t\tso_next = so->so_next;\n\n\t\t\t/*\n\t\t\t * See if it's timed out\n\t\t\t */\n\t\t\tif (so->so_expire) {\n\t\t\t\tif (so->so_expire <= curtime) {\n\t\t\t\t\tudp_detach(so);\n\t\t\t\t\tcontinue;\n\t\t\t\t} else\n\t\t\t\t\tdo_slowtimo = 1; /* Let socket expire */\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * When UDP packets are received from over the\n\t\t\t * link, they're sendto()'d straight away, so\n\t\t\t * no need for setting for writing\n\t\t\t * Limit the number of packets queued by this session\n\t\t\t * to 4.  Note that even though we try and limit this\n\t\t\t * to 4 packets, the session could have more queued\n\t\t\t * if the packets needed to be fragmented\n\t\t\t * (XXX <= 4 ?)\n\t\t\t */\n\t\t\tif ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {\n\t\t\t\tFD_SET(so->s, readfds);\n\t\t\t\tUPD_NFDS(so->s);\n\t\t\t}\n\t\t}\n\t}\n\n        *pnfds = nfds;\n}\n\nvoid slirp_select_poll(Slirp *slirp,\n                       fd_set *readfds, fd_set *writefds, fd_set *xfds,\n                       int select_error)\n{\n    struct socket *so, *so_next;\n    int ret;\n\n    global_readfds = readfds;\n    global_writefds = writefds;\n    global_xfds = xfds;\n\n    curtime = os_get_time_ms();\n\n    {\n\t/*\n\t * See if anything has timed out\n\t */\n\t\tif (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {\n\t\t\ttcp_fasttimo(slirp);\n\t\t\ttime_fasttimo = 0;\n\t\t}\n\t\tif (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {\n\t\t\tip_slowtimo(slirp);\n\t\t\ttcp_slowtimo(slirp);\n\t\t\tlast_slowtimo = curtime;\n\t\t}\n\n\t/*\n\t * Check sockets\n\t */\n\tif (!select_error) {\n\t\t/*\n\t\t * Check TCP sockets\n\t\t */\n\t\tfor (so = slirp->tcb.so_next; so != &slirp->tcb;\n\t\t     so = so_next) {\n\t\t\tso_next = so->so_next;\n\n\t\t\t/*\n\t\t\t * FD_ISSET is meaningless on these sockets\n\t\t\t * (and they can crash the program)\n\t\t\t */\n\t\t\tif (so->so_state & SS_NOFDREF || so->s == -1)\n\t\t\t   continue;\n\n\t\t\t/*\n\t\t\t * Check for URG data\n\t\t\t * This will soread as well, so no need to\n\t\t\t * test for readfds below if this succeeds\n\t\t\t */\n\t\t\tif (FD_ISSET(so->s, xfds))\n\t\t\t   sorecvoob(so);\n\t\t\t/*\n\t\t\t * Check sockets for reading\n\t\t\t */\n\t\t\telse if (FD_ISSET(so->s, readfds)) {\n\t\t\t\t/*\n\t\t\t\t * Check for incoming connections\n\t\t\t\t */\n\t\t\t\tif (so->so_state & SS_FACCEPTCONN) {\n\t\t\t\t\ttcp_connect(so);\n\t\t\t\t\tcontinue;\n\t\t\t\t} /* else */\n\t\t\t\tret = soread(so);\n\n\t\t\t\t/* Output it if we read something */\n\t\t\t\tif (ret > 0)\n\t\t\t\t   tcp_output(sototcpcb(so));\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Check sockets for writing\n\t\t\t */\n\t\t\tif (FD_ISSET(so->s, writefds)) {\n\t\t\t  /*\n\t\t\t   * Check for non-blocking, still-connecting sockets\n\t\t\t   */\n\t\t\t  if (so->so_state & SS_ISFCONNECTING) {\n\t\t\t    /* Connected */\n\t\t\t    so->so_state &= ~SS_ISFCONNECTING;\n\n\t\t\t    ret = send(so->s, (const void *) &ret, 0, 0);\n\t\t\t    if (ret < 0) {\n\t\t\t      /* XXXXX Must fix, zero bytes is a NOP */\n\t\t\t      if (errno == EAGAIN || errno == EWOULDBLOCK ||\n\t\t\t\t  errno == EINPROGRESS || errno == ENOTCONN)\n\t\t\t\tcontinue;\n\n\t\t\t      /* else failed */\n\t\t\t      so->so_state &= SS_PERSISTENT_MASK;\n\t\t\t      so->so_state |= SS_NOFDREF;\n\t\t\t    }\n\t\t\t    /* else so->so_state &= ~SS_ISFCONNECTING; */\n\n\t\t\t    /*\n\t\t\t     * Continue tcp_input\n\t\t\t     */\n\t\t\t    tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);\n\t\t\t    /* continue; */\n\t\t\t  } else\n\t\t\t    ret = sowrite(so);\n\t\t\t  /*\n\t\t\t   * XXXXX If we wrote something (a lot), there\n\t\t\t   * could be a need for a window update.\n\t\t\t   * In the worst case, the remote will send\n\t\t\t   * a window probe to get things going again\n\t\t\t   */\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Probe a still-connecting, non-blocking socket\n\t\t\t * to check if it's still alive\n\t \t \t */\n#ifdef PROBE_CONN\n\t\t\tif (so->so_state & SS_ISFCONNECTING) {\n\t\t\t  ret = recv(so->s, (char *)&ret, 0,0);\n\n\t\t\t  if (ret < 0) {\n\t\t\t    /* XXX */\n\t\t\t    if (errno == EAGAIN || errno == EWOULDBLOCK ||\n\t\t\t\terrno == EINPROGRESS || errno == ENOTCONN)\n\t\t\t      continue; /* Still connecting, continue */\n\n\t\t\t    /* else failed */\n\t\t\t    so->so_state &= SS_PERSISTENT_MASK;\n\t\t\t    so->so_state |= SS_NOFDREF;\n\n\t\t\t    /* tcp_input will take care of it */\n\t\t\t  } else {\n\t\t\t    ret = send(so->s, &ret, 0,0);\n\t\t\t    if (ret < 0) {\n\t\t\t      /* XXX */\n\t\t\t      if (errno == EAGAIN || errno == EWOULDBLOCK ||\n\t\t\t\t  errno == EINPROGRESS || errno == ENOTCONN)\n\t\t\t\tcontinue;\n\t\t\t      /* else failed */\n\t\t\t      so->so_state &= SS_PERSISTENT_MASK;\n\t\t\t      so->so_state |= SS_NOFDREF;\n\t\t\t    } else\n\t\t\t      so->so_state &= ~SS_ISFCONNECTING;\n\n\t\t\t  }\n\t\t\t  tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);\n\t\t\t} /* SS_ISFCONNECTING */\n#endif\n\t\t}\n\n\t\t/*\n\t\t * Now UDP sockets.\n\t\t * Incoming packets are sent straight away, they're not buffered.\n\t\t * Incoming UDP data isn't buffered either.\n\t\t */\n\t\tfor (so = slirp->udb.so_next; so != &slirp->udb;\n\t\t     so = so_next) {\n\t\t\tso_next = so->so_next;\n\n\t\t\tif (so->s != -1 && FD_ISSET(so->s, readfds)) {\n                            sorecvfrom(so);\n                        }\n\t\t}\n\t}\n\n\t/*\n\t * See if we can start outputting\n\t */\n\tif (slirp->if_queued) {\n\t    if_start(slirp);\n\t}\n    }\n\n\t/* clear global file descriptor sets.\n\t * these reside on the stack in vl.c\n\t * so they're unusable if we're not in\n\t * slirp_select_fill or slirp_select_poll.\n\t */\n\t global_readfds = NULL;\n\t global_writefds = NULL;\n\t global_xfds = NULL;\n}\n\n#define ETH_ALEN 6\n#define ETH_HLEN 14\n\n#define ETH_P_IP\t0x0800\t\t/* Internet Protocol packet\t*/\n#define ETH_P_ARP\t0x0806\t\t/* Address Resolution packet\t*/\n\n#define\tARPOP_REQUEST\t1\t\t/* ARP request\t\t\t*/\n#define\tARPOP_REPLY\t2\t\t/* ARP reply\t\t\t*/\n\nstruct ethhdr\n{\n\tunsigned char\th_dest[ETH_ALEN];\t/* destination eth addr\t*/\n\tunsigned char\th_source[ETH_ALEN];\t/* source ether addr\t*/\n\tunsigned short\th_proto;\t\t/* packet type ID field\t*/\n};\n\nstruct arphdr\n{\n\tunsigned short\tar_hrd;\t\t/* format of hardware address\t*/\n\tunsigned short\tar_pro;\t\t/* format of protocol address\t*/\n\tunsigned char\tar_hln;\t\t/* length of hardware address\t*/\n\tunsigned char\tar_pln;\t\t/* length of protocol address\t*/\n\tunsigned short\tar_op;\t\t/* ARP opcode (command)\t\t*/\n\n\t /*\n\t  *\t Ethernet looks like this : This bit is variable sized however...\n\t  */\n\tunsigned char\t\tar_sha[ETH_ALEN];\t/* sender hardware address\t*/\n\tuint32_t\t\tar_sip;\t\t\t/* sender IP address\t\t*/\n\tunsigned char\t\tar_tha[ETH_ALEN];\t/* target hardware address\t*/\n\tuint32_t\t\tar_tip\t;\t\t/* target IP address\t\t*/\n} __attribute__((packed));\n\nstatic void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)\n{\n    struct ethhdr *eh = (struct ethhdr *)pkt;\n    struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);\n    uint8_t arp_reply[max(ETH_HLEN + sizeof(struct arphdr), 64)];\n    struct ethhdr *reh = (struct ethhdr *)arp_reply;\n    struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);\n    int ar_op;\n    struct ex_list *ex_ptr;\n\n    ar_op = ntohs(ah->ar_op);\n    switch(ar_op) {\n    case ARPOP_REQUEST:\n        if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==\n            slirp->vnetwork_addr.s_addr) {\n            if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||\n                ah->ar_tip == slirp->vhost_addr.s_addr)\n                goto arp_ok;\n            for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {\n                if (ex_ptr->ex_addr.s_addr == ah->ar_tip)\n                    goto arp_ok;\n            }\n            return;\n        arp_ok:\n            memset(arp_reply, 0, sizeof(arp_reply));\n            /* XXX: make an ARP request to have the client address */\n            memcpy(slirp->client_ethaddr, eh->h_source, ETH_ALEN);\n\n            /* ARP request for alias/dns mac address */\n            memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);\n            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);\n            memcpy(&reh->h_source[2], &ah->ar_tip, 4);\n            reh->h_proto = htons(ETH_P_ARP);\n\n            rah->ar_hrd = htons(1);\n            rah->ar_pro = htons(ETH_P_IP);\n            rah->ar_hln = ETH_ALEN;\n            rah->ar_pln = 4;\n            rah->ar_op = htons(ARPOP_REPLY);\n            memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);\n            rah->ar_sip = ah->ar_tip;\n            memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);\n            rah->ar_tip = ah->ar_sip;\n            slirp_output(slirp->opaque, arp_reply, sizeof(arp_reply));\n        }\n        break;\n    case ARPOP_REPLY:\n        /* reply to request of client mac address ? */\n        if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) &&\n            ah->ar_sip == slirp->client_ipaddr.s_addr) {\n            memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN);\n        }\n        break;\n    default:\n        break;\n    }\n}\n\nvoid slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)\n{\n    struct mbuf *m;\n    int proto;\n\n    if (pkt_len < ETH_HLEN)\n        return;\n\n    proto = ntohs(*(uint16_t *)(pkt + 12));\n    switch(proto) {\n    case ETH_P_ARP:\n        arp_input(slirp, pkt, pkt_len);\n        break;\n    case ETH_P_IP:\n        m = m_get(slirp);\n        if (!m)\n            return;\n        /* Note: we add to align the IP header */\n        if (M_FREEROOM(m) < pkt_len + 2) {\n            m_inc(m, pkt_len + 2);\n        }\n        m->m_len = pkt_len + 2;\n        memcpy(m->m_data + 2, pkt, pkt_len);\n\n        m->m_data += 2 + ETH_HLEN;\n        m->m_len -= 2 + ETH_HLEN;\n\n        ip_input(m);\n        break;\n    default:\n        break;\n    }\n}\n\n/* output the IP packet to the ethernet device */\nvoid if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len)\n{\n    uint8_t buf[1600];\n    struct ethhdr *eh = (struct ethhdr *)buf;\n\n    if (ip_data_len + ETH_HLEN > sizeof(buf))\n        return;\n    \n    if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN)) {\n        uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];\n        struct ethhdr *reh = (struct ethhdr *)arp_req;\n        struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);\n        const struct ip *iph = (const struct ip *)ip_data;\n\n        /* If the client addr is not known, there is no point in\n           sending the packet to it. Normally the sender should have\n           done an ARP request to get its MAC address. Here we do it\n           in place of sending the packet and we hope that the sender\n           will retry sending its packet. */\n        memset(reh->h_dest, 0xff, ETH_ALEN);\n        memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);\n        memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);\n        reh->h_proto = htons(ETH_P_ARP);\n        rah->ar_hrd = htons(1);\n        rah->ar_pro = htons(ETH_P_IP);\n        rah->ar_hln = ETH_ALEN;\n        rah->ar_pln = 4;\n        rah->ar_op = htons(ARPOP_REQUEST);\n        /* source hw addr */\n        memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);\n        memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);\n        /* source IP */\n        rah->ar_sip = slirp->vhost_addr.s_addr;\n        /* target hw addr (none) */\n        memset(rah->ar_tha, 0, ETH_ALEN);\n        /* target IP */\n        rah->ar_tip = iph->ip_dst.s_addr;\n        slirp->client_ipaddr = iph->ip_dst;\n        slirp_output(slirp->opaque, arp_req, sizeof(arp_req));\n    } else {\n        memcpy(eh->h_dest, slirp->client_ethaddr, ETH_ALEN);\n        memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);\n        /* XXX: not correct */\n        memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);\n        eh->h_proto = htons(ETH_P_IP);\n        memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);\n        slirp_output(slirp->opaque, buf, ip_data_len + ETH_HLEN);\n    }\n}\n\n/* Drop host forwarding rule, return 0 if found. */\nint slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,\n                         int host_port)\n{\n    struct socket *so;\n    struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);\n    struct sockaddr_in addr;\n    int port = htons(host_port);\n    socklen_t addr_len;\n\n    for (so = head->so_next; so != head; so = so->so_next) {\n        addr_len = sizeof(addr);\n        if ((so->so_state & SS_HOSTFWD) &&\n            getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&\n            addr.sin_addr.s_addr == host_addr.s_addr &&\n            addr.sin_port == port) {\n            close(so->s);\n            sofree(so);\n            return 0;\n        }\n    }\n\n    return -1;\n}\n\nint slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,\n                      int host_port, struct in_addr guest_addr, int guest_port)\n{\n    if (!guest_addr.s_addr) {\n        guest_addr = slirp->vdhcp_startaddr;\n    }\n    if (is_udp) {\n        if (!udp_listen(slirp, host_addr.s_addr, htons(host_port),\n                        guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))\n            return -1;\n    } else {\n        if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port),\n                        guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))\n            return -1;\n    }\n    return 0;\n}\n\nint slirp_add_exec(Slirp *slirp, int do_pty, const void *args,\n                   struct in_addr *guest_addr, int guest_port)\n{\n    if (!guest_addr->s_addr) {\n        guest_addr->s_addr = slirp->vnetwork_addr.s_addr |\n            (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);\n    }\n    if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) !=\n        slirp->vnetwork_addr.s_addr ||\n        guest_addr->s_addr == slirp->vhost_addr.s_addr ||\n        guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {\n        return -1;\n    }\n    return add_exec(&slirp->exec_list, do_pty, (char *)args, *guest_addr,\n                    htons(guest_port));\n}\n\nssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)\n{\n#if 0\n    if (so->s == -1 && so->extra) {\n\t\tqemu_chr_write(so->extra, buf, len);\n\t\treturn len;\n\t}\n#endif\n\treturn send(so->s, buf, len, flags);\n}\n\nstatic struct socket *\nslirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)\n{\n    struct socket *so;\n\n    for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {\n        if (so->so_faddr.s_addr == guest_addr.s_addr &&\n            htons(so->so_fport) == guest_port) {\n            return so;\n        }\n    }\n    return NULL;\n}\n\nsize_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,\n                             int guest_port)\n{\n\tstruct iovec iov[2];\n\tstruct socket *so;\n\n\tso = slirp_find_ctl_socket(slirp, guest_addr, guest_port);\n\n\tif (!so || so->so_state & SS_NOFDREF)\n\t\treturn 0;\n\n\tif (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))\n\t\treturn 0;\n\n\treturn sopreprbuf(so, iov, NULL);\n}\n\nvoid slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,\n                       const uint8_t *buf, int size)\n{\n    int ret;\n    struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);\n\n    if (!so)\n        return;\n\n    ret = soreadbuf(so, (const char *)buf, size);\n\n    if (ret > 0)\n        tcp_output(sototcpcb(so));\n}\n"
  },
  {
    "path": "src/slirp/slirp.h",
    "content": "#ifndef __COMMON_H__\n#define __COMMON_H__\n\n#include <stdlib.h>\n#include \"../cutils.h\"\n#include \"slirp_config.h\"\n\n#ifdef _WIN32\n# include <inttypes.h>\n\ntypedef char *caddr_t;\n\n# include <windows.h>\n# include <winsock2.h>\n# include <ws2tcpip.h>\n# include <sys/timeb.h>\n# include <iphlpapi.h>\n\n# define EWOULDBLOCK WSAEWOULDBLOCK\n# define EINPROGRESS WSAEINPROGRESS\n# define ENOTCONN WSAENOTCONN\n# define EHOSTUNREACH WSAEHOSTUNREACH\n# define ENETUNREACH WSAENETUNREACH\n# define ECONNREFUSED WSAECONNREFUSED\n#else\n# define ioctlsocket ioctl\n# define closesocket(s) close(s)\n# if !defined(__HAIKU__)\n#  define O_BINARY 0\n# endif\n#endif\n\n#include <sys/types.h>\n#ifdef HAVE_SYS_BITYPES_H\n# include <sys/bitypes.h>\n#endif\n\n#include <sys/time.h>\n\n#ifdef HAVE_UNISTD_H\n# include <unistd.h>\n#endif\n\n#ifdef HAVE_STDLIB_H\n# include <stdlib.h>\n#endif\n\n#include <stdio.h>\n#include <errno.h>\n\n#ifndef HAVE_MEMMOVE\n#define memmove(x, y, z) bcopy(y, x, z)\n#endif\n\n#if TIME_WITH_SYS_TIME\n# include <sys/time.h>\n# include <time.h>\n#else\n# ifdef HAVE_SYS_TIME_H\n#  include <sys/time.h>\n# else\n#  include <time.h>\n# endif\n#endif\n\n#ifdef HAVE_STRING_H\n# include <string.h>\n#else\n# include <strings.h>\n#endif\n\n#ifndef _WIN32\n#include <sys/uio.h>\n#endif\n\n#ifndef _WIN32\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#endif\n\n/* Systems lacking strdup() definition in <string.h>. */\n#if defined(ultrix)\nchar *strdup(const char *);\n#endif\n\n/* Systems lacking malloc() definition in <stdlib.h>. */\n#if defined(ultrix) || defined(hcx)\nvoid *malloc(size_t arg);\nvoid free(void *ptr);\n#endif\n\n#ifndef HAVE_INET_ATON\nint inet_aton(const char *cp, struct in_addr *ia);\n#endif\n\n#include <fcntl.h>\n#ifndef NO_UNIX_SOCKETS\n#include <sys/un.h>\n#endif\n#include <signal.h>\n#ifdef HAVE_SYS_SIGNAL_H\n# include <sys/signal.h>\n#endif\n#ifndef _WIN32\n#include <sys/socket.h>\n#endif\n\n#if defined(HAVE_SYS_IOCTL_H)\n# include <sys/ioctl.h>\n#endif\n\n#ifdef HAVE_SYS_SELECT_H\n# include <sys/select.h>\n#endif\n\n#ifdef HAVE_SYS_WAIT_H\n# include <sys/wait.h>\n#endif\n\n#ifdef HAVE_SYS_FILIO_H\n# include <sys/filio.h>\n#endif\n\n#ifdef USE_PPP\n#include <ppp/slirppp.h>\n#endif\n\n#ifdef __STDC__\n#include <stdarg.h>\n#else\n#include <varargs.h>\n#endif\n\n#include <sys/stat.h>\n\n/* Avoid conflicting with the libc insque() and remque(), which\n   have different prototypes. */\n#define insque slirp_insque\n#define remque slirp_remque\n\n#ifdef HAVE_SYS_STROPTS_H\n#include <sys/stropts.h>\n#endif\n\n#include \"debug.h\"\n\n#include \"libslirp.h\"\n#include \"ip.h\"\n#include \"tcp.h\"\n#include \"tcp_timer.h\"\n#include \"tcp_var.h\"\n#include \"tcpip.h\"\n#include \"udp.h\"\n#include \"mbuf.h\"\n#include \"sbuf.h\"\n#include \"socket.h\"\n#include \"if.h\"\n#include \"main.h\"\n#include \"misc.h\"\n#ifdef USE_PPP\n#include \"ppp/pppd.h\"\n#include \"ppp/ppp.h\"\n#endif\n\n#include \"bootp.h\"\n#include \"tftp.h\"\n\nstruct Slirp {\n    /* virtual network configuration */\n    struct in_addr vnetwork_addr;\n    struct in_addr vnetwork_mask;\n    struct in_addr vhost_addr;\n    struct in_addr vdhcp_startaddr;\n    struct in_addr vnameserver_addr;\n\n    /* ARP cache for the guest IP addresses (XXX: allow many entries) */\n    uint8_t client_ethaddr[6];\n\n    struct in_addr client_ipaddr;\n    char client_hostname[33];\n\n    int restricted;\n    struct timeval tt;\n    struct ex_list *exec_list;\n\n    /* mbuf states */\n    struct mbuf m_freelist, m_usedlist;\n    int mbuf_alloced;\n\n    /* if states */\n    int if_queued;          /* number of packets queued so far */\n    struct mbuf if_fastq;   /* fast queue (for interactive data) */\n    struct mbuf if_batchq;  /* queue for non-interactive data */\n    struct mbuf *next_m;    /* pointer to next mbuf to output */\n\n    /* ip states */\n    struct ipq ipq;         /* ip reass. queue */\n    uint16_t ip_id;         /* ip packet ctr, for ids */\n\n    /* bootp/dhcp states */\n    BOOTPClient bootp_clients[NB_BOOTP_CLIENTS];\n    char *bootp_filename;\n\n    /* tcp states */\n    struct socket tcb;\n    struct socket *tcp_last_so;\n    tcp_seq tcp_iss;        /* tcp initial send seq # */\n    uint32_t tcp_now;       /* for RFC 1323 timestamps */\n\n    /* udp states */\n    struct socket udb;\n    struct socket *udp_last_so;\n\n    /* tftp states */\n    char *tftp_prefix;\n    struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];\n\n    void *opaque;\n};\n\nextern Slirp *slirp_instance;\n\n#ifndef NULL\n#define NULL (void *)0\n#endif\n\n#ifndef FULL_BOLT\nvoid if_start(Slirp *);\n#else\nvoid if_start(struct ttys *);\n#endif\n\n#ifndef HAVE_STRERROR\n char *strerror(int error);\n#endif\n\n#ifndef HAVE_INDEX\n char *index(const char *, int);\n#endif\n\n#ifndef HAVE_GETHOSTID\n long gethostid(void);\n#endif\n\nvoid lprint(const char *, ...) __attribute__((format(printf, 1, 2)));\n\n#ifndef _WIN32\n#include <netdb.h>\n#endif\n\n#define DEFAULT_BAUD 115200\n\n#define SO_OPTIONS DO_KEEPALIVE\n#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL)\n\n/* cksum.c */\nint cksum(struct mbuf *m, int len);\n\n/* if.c */\nvoid if_init(Slirp *);\nvoid if_output(struct socket *, struct mbuf *);\n\n/* ip_input.c */\nvoid ip_init(Slirp *);\nvoid ip_input(struct mbuf *);\nvoid ip_slowtimo(Slirp *);\nvoid ip_stripoptions(register struct mbuf *, struct mbuf *);\n\n/* ip_output.c */\nint ip_output(struct socket *, struct mbuf *);\n\n/* tcp_input.c */\nvoid tcp_input(register struct mbuf *, int, struct socket *);\nint tcp_mss(register struct tcpcb *, u_int);\n\n/* tcp_output.c */\nint tcp_output(register struct tcpcb *);\nvoid tcp_setpersist(register struct tcpcb *);\n\n/* tcp_subr.c */\nvoid tcp_init(Slirp *);\nvoid tcp_template(struct tcpcb *);\nvoid tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int);\nstruct tcpcb * tcp_newtcpcb(struct socket *);\nstruct tcpcb * tcp_close(register struct tcpcb *);\nvoid tcp_sockclosed(struct tcpcb *);\nint tcp_fconnect(struct socket *);\nvoid tcp_connect(struct socket *);\nint tcp_attach(struct socket *);\nuint8_t tcp_tos(struct socket *);\nint tcp_emu(struct socket *, struct mbuf *);\nint tcp_ctl(struct socket *);\nstruct tcpcb *tcp_drop(struct tcpcb *tp, int err);\n\n#ifdef USE_PPP\n#define MIN_MRU MINMRU\n#define MAX_MRU MAXMRU\n#else\n#define MIN_MRU 128\n#define MAX_MRU 16384\n#endif\n\n#ifndef _WIN32\n#define min(x,y) ((x) < (y) ? (x) : (y))\n#define max(x,y) ((x) > (y) ? (x) : (y))\n#endif\n\n#ifdef _WIN32\n#undef errno\n#define errno (WSAGetLastError())\n#endif\n\n#endif\n"
  },
  {
    "path": "src/slirp/slirp_config.h",
    "content": "/*\n * User definable configuration options\n */\n\n/* Define if you want the connection to be probed */\n/* XXX Not working yet, so ignore this for now */\n#undef PROBE_CONN\n\n/* Define to 1 if you want KEEPALIVE timers */\n#define DO_KEEPALIVE 0\n\n/* Define to MAX interfaces you expect to use at once */\n/* MAX_INTERFACES determines the max. TOTAL number of interfaces (SLIP and PPP) */\n/* MAX_PPP_INTERFACES determines max. number of PPP interfaces */\n#define MAX_INTERFACES 1\n#define MAX_PPP_INTERFACES 1\n\n/* Define if you want slirp's socket in /tmp */\n/* XXXXXX Do this in ./configure */\n#undef USE_TMPSOCKET\n\n/* Define if you want slirp to use cfsetXspeed() on the terminal */\n#undef DO_CFSETSPEED\n\n/* Define this if you want slirp to write to the tty as fast as it can */\n/* This should only be set if you are using load-balancing, slirp does a */\n/* pretty good job on single modems already, and seting this will make */\n/* interactive sessions less responsive */\n/* XXXXX Talk about having fast modem as unit 0 */\n#undef FULL_BOLT\n\n/*\n * Define if you want slirp to use less CPU\n * You will notice a small lag in interactive sessions, but it's not that bad\n * Things like Netscape/ftp/etc. are completely unaffected\n * This is mainly for sysadmins who have many slirp users\n */\n#undef USE_LOWCPU\n\n/* Define this if your compiler doesn't like prototypes */\n#ifndef __STDC__\n#define NO_PROTOTYPES\n#endif\n\n/*********************************************************/\n/*\n * Autoconf defined configuration options\n * You shouldn't need to touch any of these\n */\n\n/* Ignore this */\n#undef DUMMY_PPP\n\n/* Define if you have unistd.h */\n#define HAVE_UNISTD_H\n\n/* Define if you have stdlib.h */\n#define HAVE_STDLIB_H\n\n/* Define if you have sys/ioctl.h */\n#undef HAVE_SYS_IOCTL_H\n#ifndef _WIN32\n#define HAVE_SYS_IOCTL_H\n#endif\n\n/* Define if you have sys/filio.h */\n#undef HAVE_SYS_FILIO_H\n#ifdef __APPLE__\n#define HAVE_SYS_FILIO_H\n#endif\n\n/* Define if you have strerror */\n#define HAVE_STRERROR\n\n/* Define if you have strdup() */\n#define HAVE_STRDUP\n\n/* Define according to how time.h should be included */\n#define TIME_WITH_SYS_TIME 0\n#undef HAVE_SYS_TIME_H\n\n/* Define if you have sys/bitypes.h */\n#undef HAVE_SYS_BITYPES_H\n\n/* Define if the machine is big endian */\n//#undef HOST_WORDS_BIGENDIAN\n\n/* Define if you have readv */\n#undef HAVE_READV\n\n/* Define if iovec needs to be declared */\n#undef DECLARE_IOVEC\n#ifdef _WIN32\n#define DECLARE_IOVEC\n#endif\n\n/* Define if you have a POSIX.1 sys/wait.h */\n#undef HAVE_SYS_WAIT_H\n\n/* Define if you have sys/select.h */\n#undef HAVE_SYS_SELECT_H\n#ifndef _WIN32\n#define HAVE_SYS_SELECT_H\n#endif\n\n/* Define if you have strings.h */\n#define HAVE_STRING_H\n\n/* Define if you have arpa/inet.h */\n#undef HAVE_ARPA_INET_H\n#ifndef _WIN32\n#define HAVE_ARPA_INET_H\n#endif\n\n/* Define if you have sys/signal.h */\n#undef HAVE_SYS_SIGNAL_H\n\n/* Define if you have sys/stropts.h */\n#undef HAVE_SYS_STROPTS_H\n\n/* Define to whatever your compiler thinks inline should be */\n//#define inline inline\n\n/* Define to whatever your compiler thinks const should be */\n//#define const const\n\n/* Define if your compiler doesn't like prototypes */\n#undef NO_PROTOTYPES\n\n/* Define to sizeof(char) */\n#define SIZEOF_CHAR 1\n\n/* Define to sizeof(short) */\n#define SIZEOF_SHORT 2\n\n/* Define to sizeof(int) */\n#define SIZEOF_INT 4\n\n/* Define to sizeof(char *) */\n#define SIZEOF_CHAR_P (HOST_LONG_BITS / 8)\n\n/* Define if you have random() */\n#undef HAVE_RANDOM\n\n/* Define if you have srandom() */\n#undef HAVE_SRANDOM\n\n/* Define if you have inet_aton */\n#undef HAVE_INET_ATON\n#ifndef _WIN32\n#define HAVE_INET_ATON\n#endif\n\n/* Define if you have setenv */\n#undef HAVE_SETENV\n\n/* Define if you have index() */\n#define HAVE_INDEX\n\n/* Define if you have bcmp() */\n#undef HAVE_BCMP\n\n/* Define if you have drand48 */\n#undef HAVE_DRAND48\n\n/* Define if you have memmove */\n#define HAVE_MEMMOVE\n\n/* Define if you have gethostid */\n#define HAVE_GETHOSTID\n\n/* Define if you DON'T have unix-domain sockets */\n#undef NO_UNIX_SOCKETS\n#ifdef _WIN32\n#define NO_UNIX_SOCKETS\n#endif\n\n/* Define if you have revoke() */\n#undef HAVE_REVOKE\n\n/* Define if you have the sysv method of opening pty's (/dev/ptmx, etc.) */\n#undef HAVE_GRANTPT\n\n/* Define if you have fchmod */\n#undef HAVE_FCHMOD\n\n/* Define if you have <sys/type32.h> */\n#undef HAVE_SYS_TYPES32_H\n"
  },
  {
    "path": "src/slirp/socket.c",
    "content": "/*\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#include \"slirp.h\"\n#include \"ip_icmp.h\"\n\nstatic void sofcantrcvmore(struct socket *so);\nstatic void sofcantsendmore(struct socket *so);\n\nstruct socket *\nsolookup(struct socket *head, struct in_addr laddr, u_int lport,\n         struct in_addr faddr, u_int fport)\n{\n\tstruct socket *so;\n\n\tfor (so = head->so_next; so != head; so = so->so_next) {\n\t\tif (so->so_lport == lport &&\n\t\t    so->so_laddr.s_addr == laddr.s_addr &&\n\t\t    so->so_faddr.s_addr == faddr.s_addr &&\n\t\t    so->so_fport == fport)\n\t\t   break;\n\t}\n\n\tif (so == head)\n\t   return (struct socket *)NULL;\n\treturn so;\n\n}\n\n/*\n * Create a new socket, initialise the fields\n * It is the responsibility of the caller to\n * insque() it into the correct linked-list\n */\nstruct socket *\nsocreate(Slirp *slirp)\n{\n  struct socket *so;\n\n  so = (struct socket *)malloc(sizeof(struct socket));\n  if(so) {\n    memset(so, 0, sizeof(struct socket));\n    so->so_state = SS_NOFDREF;\n    so->s = -1;\n    so->slirp = slirp;\n  }\n  return(so);\n}\n\n/*\n * remque and free a socket, clobber cache\n */\nvoid\nsofree(struct socket *so)\n{\n  Slirp *slirp = so->slirp;\n\n  if (so->so_emu==EMU_RSH && so->extra) {\n\tsofree(so->extra);\n\tso->extra=NULL;\n  }\n  if (so == slirp->tcp_last_so) {\n      slirp->tcp_last_so = &slirp->tcb;\n  } else if (so == slirp->udp_last_so) {\n      slirp->udp_last_so = &slirp->udb;\n  }\n  m_free(so->so_m);\n\n  if(so->so_next && so->so_prev)\n    remque(so);  /* crashes if so is not in a queue */\n\n  free(so);\n}\n\nsize_t sopreprbuf(struct socket *so, struct iovec *iov, int *np)\n{\n\tint n, lss, total;\n\tstruct sbuf *sb = &so->so_snd;\n\tint len = sb->sb_datalen - sb->sb_cc;\n\tint mss = so->so_tcpcb->t_maxseg;\n\n\tDEBUG_CALL(\"sopreprbuf\");\n\tDEBUG_ARG(\"so = %lx\", (long )so);\n\n\tif (len <= 0)\n\t\treturn 0;\n\n\tiov[0].iov_base = sb->sb_wptr;\n        iov[1].iov_base = NULL;\n        iov[1].iov_len = 0;\n\tif (sb->sb_wptr < sb->sb_rptr) {\n\t\tiov[0].iov_len = sb->sb_rptr - sb->sb_wptr;\n\t\t/* Should never succeed, but... */\n\t\tif (iov[0].iov_len > len)\n\t\t   iov[0].iov_len = len;\n\t\tif (iov[0].iov_len > mss)\n\t\t   iov[0].iov_len -= iov[0].iov_len%mss;\n\t\tn = 1;\n\t} else {\n\t\tiov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;\n\t\t/* Should never succeed, but... */\n\t\tif (iov[0].iov_len > len) iov[0].iov_len = len;\n\t\tlen -= iov[0].iov_len;\n\t\tif (len) {\n\t\t\tiov[1].iov_base = sb->sb_data;\n\t\t\tiov[1].iov_len = sb->sb_rptr - sb->sb_data;\n\t\t\tif(iov[1].iov_len > len)\n\t\t\t   iov[1].iov_len = len;\n\t\t\ttotal = iov[0].iov_len + iov[1].iov_len;\n\t\t\tif (total > mss) {\n\t\t\t\tlss = total%mss;\n\t\t\t\tif (iov[1].iov_len > lss) {\n\t\t\t\t\tiov[1].iov_len -= lss;\n\t\t\t\t\tn = 2;\n\t\t\t\t} else {\n\t\t\t\t\tlss -= iov[1].iov_len;\n\t\t\t\t\tiov[0].iov_len -= lss;\n\t\t\t\t\tn = 1;\n\t\t\t\t}\n\t\t\t} else\n\t\t\t\tn = 2;\n\t\t} else {\n\t\t\tif (iov[0].iov_len > mss)\n\t\t\t   iov[0].iov_len -= iov[0].iov_len%mss;\n\t\t\tn = 1;\n\t\t}\n\t}\n\tif (np)\n\t\t*np = n;\n\n\treturn iov[0].iov_len + (n - 1) * iov[1].iov_len;\n}\n\n/*\n * Read from so's socket into sb_snd, updating all relevant sbuf fields\n * NOTE: This will only be called if it is select()ed for reading, so\n * a read() of 0 (or less) means it's disconnected\n */\nint\nsoread(struct socket *so)\n{\n\tint n, nn;\n\tstruct sbuf *sb = &so->so_snd;\n\tstruct iovec iov[2];\n\n\tDEBUG_CALL(\"soread\");\n\tDEBUG_ARG(\"so = %lx\", (long )so);\n\n\t/*\n\t * No need to check if there's enough room to read.\n\t * soread wouldn't have been called if there weren't\n\t */\n\tsopreprbuf(so, iov, &n);\n\n#ifdef HAVE_READV\n\tnn = readv(so->s, (struct iovec *)iov, n);\n\tDEBUG_MISC((dfd, \" ... read nn = %d bytes\\n\", nn));\n#else\n\tnn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);\n#endif\n\tif (nn <= 0) {\n\t\tif (nn < 0 && (errno == EINTR || errno == EAGAIN))\n\t\t\treturn 0;\n\t\telse {\n\t\t\tDEBUG_MISC((dfd, \" --- soread() disconnected, nn = %d, errno = %d-%s\\n\", nn, errno,strerror(errno)));\n\t\t\tsofcantrcvmore(so);\n\t\t\ttcp_sockclosed(sototcpcb(so));\n\t\t\treturn -1;\n\t\t}\n\t}\n\n#ifndef HAVE_READV\n\t/*\n\t * If there was no error, try and read the second time round\n\t * We read again if n = 2 (ie, there's another part of the buffer)\n\t * and we read as much as we could in the first read\n\t * We don't test for <= 0 this time, because there legitimately\n\t * might not be any more data (since the socket is non-blocking),\n\t * a close will be detected on next iteration.\n\t * A return of -1 wont (shouldn't) happen, since it didn't happen above\n\t */\n\tif (n == 2 && nn == iov[0].iov_len) {\n            int ret;\n            ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0);\n            if (ret > 0)\n                nn += ret;\n        }\n\n\tDEBUG_MISC((dfd, \" ... read nn = %d bytes\\n\", nn));\n#endif\n\n\t/* Update fields */\n\tsb->sb_cc += nn;\n\tsb->sb_wptr += nn;\n\tif (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))\n\t\tsb->sb_wptr -= sb->sb_datalen;\n\treturn nn;\n}\n\nint soreadbuf(struct socket *so, const char *buf, int size)\n{\n    int n, nn, copy = size;\n\tstruct sbuf *sb = &so->so_snd;\n\tstruct iovec iov[2];\n\n\tDEBUG_CALL(\"soreadbuf\");\n\tDEBUG_ARG(\"so = %lx\", (long )so);\n\n\t/*\n\t * No need to check if there's enough room to read.\n\t * soread wouldn't have been called if there weren't\n\t */\n\tif (sopreprbuf(so, iov, &n) < size)\n        goto err;\n\n    nn = min(iov[0].iov_len, copy);\n    memcpy(iov[0].iov_base, buf, nn);\n\n    copy -= nn;\n    buf += nn;\n\n    if (copy == 0)\n        goto done;\n\n    memcpy(iov[1].iov_base, buf, copy);\n\ndone:\n    /* Update fields */\n\tsb->sb_cc += size;\n\tsb->sb_wptr += size;\n\tif (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))\n\t\tsb->sb_wptr -= sb->sb_datalen;\n    return size;\nerr:\n\n    sofcantrcvmore(so);\n    tcp_sockclosed(sototcpcb(so));\n    fprintf(stderr, \"soreadbuf buffer to small\");\n    return -1;\n}\n\n/*\n * Get urgent data\n *\n * When the socket is created, we set it SO_OOBINLINE,\n * so when OOB data arrives, we soread() it and everything\n * in the send buffer is sent as urgent data\n */\nvoid\nsorecvoob(struct socket *so)\n{\n\tstruct tcpcb *tp = sototcpcb(so);\n\n\tDEBUG_CALL(\"sorecvoob\");\n\tDEBUG_ARG(\"so = %lx\", (long)so);\n\n\t/*\n\t * We take a guess at how much urgent data has arrived.\n\t * In most situations, when urgent data arrives, the next\n\t * read() should get all the urgent data.  This guess will\n\t * be wrong however if more data arrives just after the\n\t * urgent data, or the read() doesn't return all the\n\t * urgent data.\n\t */\n\tsoread(so);\n\ttp->snd_up = tp->snd_una + so->so_snd.sb_cc;\n\ttp->t_force = 1;\n\ttcp_output(tp);\n\ttp->t_force = 0;\n}\n\n/*\n * Send urgent data\n * There's a lot duplicated code here, but...\n */\nint\nsosendoob(struct socket *so)\n{\n\tstruct sbuf *sb = &so->so_rcv;\n\tchar buff[2048]; /* XXX Shouldn't be sending more oob data than this */\n\n\tint n, len;\n\n\tDEBUG_CALL(\"sosendoob\");\n\tDEBUG_ARG(\"so = %lx\", (long)so);\n\tDEBUG_ARG(\"sb->sb_cc = %d\", sb->sb_cc);\n\n\tif (so->so_urgc > 2048)\n\t   so->so_urgc = 2048; /* XXXX */\n\n\tif (sb->sb_rptr < sb->sb_wptr) {\n\t\t/* We can send it directly */\n\t\tn = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */\n\t\tso->so_urgc -= n;\n\n\t\tDEBUG_MISC((dfd, \" --- sent %d bytes urgent data, %d urgent bytes left\\n\", n, so->so_urgc));\n\t} else {\n\t\t/*\n\t\t * Since there's no sendv or sendtov like writev,\n\t\t * we must copy all data to a linear buffer then\n\t\t * send it all\n\t\t */\n\t\tlen = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;\n\t\tif (len > so->so_urgc) len = so->so_urgc;\n\t\tmemcpy(buff, sb->sb_rptr, len);\n\t\tso->so_urgc -= len;\n\t\tif (so->so_urgc) {\n\t\t\tn = sb->sb_wptr - sb->sb_data;\n\t\t\tif (n > so->so_urgc) n = so->so_urgc;\n\t\t\tmemcpy((buff + len), sb->sb_data, n);\n\t\t\tso->so_urgc -= n;\n\t\t\tlen += n;\n\t\t}\n\t\tn = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */\n#ifdef DEBUG\n\t\tif (n != len)\n\t\t   DEBUG_ERROR((dfd, \"Didn't send all data urgently XXXXX\\n\"));\n#endif\n\t\tDEBUG_MISC((dfd, \" ---2 sent %d bytes urgent data, %d urgent bytes left\\n\", n, so->so_urgc));\n\t}\n\n\tsb->sb_cc -= n;\n\tsb->sb_rptr += n;\n\tif (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))\n\t\tsb->sb_rptr -= sb->sb_datalen;\n\n\treturn n;\n}\n\n/*\n * Write data from so_rcv to so's socket,\n * updating all sbuf field as necessary\n */\nint\nsowrite(struct socket *so)\n{\n\tint  n,nn;\n\tstruct sbuf *sb = &so->so_rcv;\n\tint len = sb->sb_cc;\n\tstruct iovec iov[2];\n\n\tDEBUG_CALL(\"sowrite\");\n\tDEBUG_ARG(\"so = %lx\", (long)so);\n\n\tif (so->so_urgc) {\n\t\tsosendoob(so);\n\t\tif (sb->sb_cc == 0)\n\t\t\treturn 0;\n\t}\n\n\t/*\n\t * No need to check if there's something to write,\n\t * sowrite wouldn't have been called otherwise\n\t */\n\n\tiov[0].iov_base = sb->sb_rptr;\n        iov[1].iov_base = NULL;\n        iov[1].iov_len = 0;\n\tif (sb->sb_rptr < sb->sb_wptr) {\n\t\tiov[0].iov_len = sb->sb_wptr - sb->sb_rptr;\n\t\t/* Should never succeed, but... */\n\t\tif (iov[0].iov_len > len) iov[0].iov_len = len;\n\t\tn = 1;\n\t} else {\n\t\tiov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;\n\t\tif (iov[0].iov_len > len) iov[0].iov_len = len;\n\t\tlen -= iov[0].iov_len;\n\t\tif (len) {\n\t\t\tiov[1].iov_base = sb->sb_data;\n\t\t\tiov[1].iov_len = sb->sb_wptr - sb->sb_data;\n\t\t\tif (iov[1].iov_len > len) iov[1].iov_len = len;\n\t\t\tn = 2;\n\t\t} else\n\t\t\tn = 1;\n\t}\n\t/* Check if there's urgent data to send, and if so, send it */\n\n#ifdef HAVE_READV\n\tnn = writev(so->s, (const struct iovec *)iov, n);\n\n\tDEBUG_MISC((dfd, \"  ... wrote nn = %d bytes\\n\", nn));\n#else\n\tnn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0);\n#endif\n\t/* This should never happen, but people tell me it does *shrug* */\n\tif (nn < 0 && (errno == EAGAIN || errno == EINTR))\n\t\treturn 0;\n\n\tif (nn <= 0) {\n\t\tDEBUG_MISC((dfd, \" --- sowrite disconnected, so->so_state = %x, errno = %d\\n\",\n\t\t\tso->so_state, errno));\n\t\tsofcantsendmore(so);\n\t\ttcp_sockclosed(sototcpcb(so));\n\t\treturn -1;\n\t}\n\n#ifndef HAVE_READV\n\tif (n == 2 && nn == iov[0].iov_len) {\n            int ret;\n            ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0);\n            if (ret > 0)\n                nn += ret;\n        }\n        DEBUG_MISC((dfd, \"  ... wrote nn = %d bytes\\n\", nn));\n#endif\n\n\t/* Update sbuf */\n\tsb->sb_cc -= nn;\n\tsb->sb_rptr += nn;\n\tif (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))\n\t\tsb->sb_rptr -= sb->sb_datalen;\n\n\t/*\n\t * If in DRAIN mode, and there's no more data, set\n\t * it CANTSENDMORE\n\t */\n\tif ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)\n\t\tsofcantsendmore(so);\n\n\treturn nn;\n}\n\n/*\n * recvfrom() a UDP socket\n */\nvoid\nsorecvfrom(struct socket *so)\n{\n\tstruct sockaddr_in addr;\n\tsocklen_t addrlen = sizeof(struct sockaddr_in);\n\n\tDEBUG_CALL(\"sorecvfrom\");\n\tDEBUG_ARG(\"so = %lx\", (long)so);\n\n\tif (so->so_type == IPPROTO_ICMP) {   /* This is a \"ping\" reply */\n\t  char buff[256];\n\t  int len;\n\n\t  len = recvfrom(so->s, buff, 256, 0,\n\t\t\t (struct sockaddr *)&addr, &addrlen);\n\t  /* XXX Check if reply is \"correct\"? */\n\n\t  if(len == -1 || len == 0) {\n\t    u_char code=ICMP_UNREACH_PORT;\n\n\t    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;\n\t    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;\n\n\t    DEBUG_MISC((dfd,\" udp icmp rx errno = %d-%s\\n\",\n\t\t\terrno,strerror(errno)));\n\t    icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));\n\t  } else {\n\t    icmp_reflect(so->so_m);\n            so->so_m = NULL; /* Don't m_free() it again! */\n\t  }\n\t  /* No need for this socket anymore, udp_detach it */\n\t  udp_detach(so);\n\t} else {                            \t/* A \"normal\" UDP packet */\n\t  struct mbuf *m;\n          int len;\n#ifdef _WIN32\n          unsigned long n;\n#else\n          int n;\n#endif\n\n\t  m = m_get(so->slirp);\n\t  if (!m) {\n\t      return;\n\t  }\n\t  m->m_data += IF_MAXLINKHDR;\n\n\t  /*\n\t   * XXX Shouldn't FIONREAD packets destined for port 53,\n\t   * but I don't know the max packet size for DNS lookups\n\t   */\n\t  len = M_FREEROOM(m);\n\t  /* if (so->so_fport != htons(53)) { */\n\t  ioctlsocket(so->s, FIONREAD, &n);\n\n\t  if (n > len) {\n\t    n = (m->m_data - m->m_dat) + m->m_len + n + 1;\n\t    m_inc(m, n);\n\t    len = M_FREEROOM(m);\n\t  }\n\t  /* } */\n\n\t  m->m_len = recvfrom(so->s, m->m_data, len, 0,\n\t\t\t      (struct sockaddr *)&addr, &addrlen);\n\t  DEBUG_MISC((dfd, \" did recvfrom %d, errno = %d-%s\\n\",\n\t\t      m->m_len, errno,strerror(errno)));\n\t  if(m->m_len<0) {\n\t    u_char code=ICMP_UNREACH_PORT;\n\n\t    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;\n\t    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;\n\n\t    DEBUG_MISC((dfd,\" rx error, tx icmp ICMP_UNREACH:%i\\n\", code));\n\t    icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));\n\t    m_free(m);\n\t  } else {\n\t  /*\n\t   * Hack: domain name lookup will be used the most for UDP,\n\t   * and since they'll only be used once there's no need\n\t   * for the 4 minute (or whatever) timeout... So we time them\n\t   * out much quicker (10 seconds  for now...)\n\t   */\n\t    if (so->so_expire) {\n\t      if (so->so_fport == htons(53))\n\t\tso->so_expire = curtime + SO_EXPIREFAST;\n\t      else\n\t\tso->so_expire = curtime + SO_EXPIRE;\n\t    }\n\n\t    /*\n\t     * If this packet was destined for CTL_ADDR,\n\t     * make it look like that's where it came from, done by udp_output\n\t     */\n\t    udp_output(so, m, &addr);\n\t  } /* rx error */\n\t} /* if ping packet */\n}\n\n/*\n * sendto() a socket\n */\nint\nsosendto(struct socket *so, struct mbuf *m)\n{\n\tSlirp *slirp = so->slirp;\n\tint ret;\n\tstruct sockaddr_in addr;\n\n\tDEBUG_CALL(\"sosendto\");\n\tDEBUG_ARG(\"so = %lx\", (long)so);\n\tDEBUG_ARG(\"m = %lx\", (long)m);\n\n        addr.sin_family = AF_INET;\n\tif ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==\n\t    slirp->vnetwork_addr.s_addr) {\n\t  /* It's an alias */\n\t  if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {\n\t    if (get_dns_addr(&addr.sin_addr) < 0)\n\t      addr.sin_addr = loopback_addr;\n\t  } else {\n\t    addr.sin_addr = loopback_addr;\n\t  }\n\t} else\n\t  addr.sin_addr = so->so_faddr;\n\taddr.sin_port = so->so_fport;\n\n\tDEBUG_MISC((dfd, \" sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\\n\", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));\n\n\t/* Don't care what port we get */\n\tret = sendto(so->s, m->m_data, m->m_len, 0,\n\t\t     (struct sockaddr *)&addr, sizeof (struct sockaddr));\n\tif (ret < 0)\n\t\treturn -1;\n\n\t/*\n\t * Kill the socket if there's no reply in 4 minutes,\n\t * but only if it's an expirable socket\n\t */\n\tif (so->so_expire)\n\t\tso->so_expire = curtime + SO_EXPIRE;\n\tso->so_state &= SS_PERSISTENT_MASK;\n\tso->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */\n\treturn 0;\n}\n\n/*\n * Listen for incoming TCP connections\n */\nstruct socket *\ntcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,\n           u_int lport, int flags)\n{\n\tstruct sockaddr_in addr;\n\tstruct socket *so;\n\tint s, opt = 1;\n\tsocklen_t addrlen = sizeof(addr);\n\tmemset(&addr, 0, addrlen);\n\n\tDEBUG_CALL(\"tcp_listen\");\n\tDEBUG_ARG(\"haddr = %x\", haddr);\n\tDEBUG_ARG(\"hport = %d\", hport);\n\tDEBUG_ARG(\"laddr = %x\", laddr);\n\tDEBUG_ARG(\"lport = %d\", lport);\n\tDEBUG_ARG(\"flags = %x\", flags);\n\n\tso = socreate(slirp);\n\tif (!so) {\n\t  return NULL;\n\t}\n\n\t/* Don't tcp_attach... we don't need so_snd nor so_rcv */\n\tif ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {\n\t\tfree(so);\n\t\treturn NULL;\n\t}\n\tinsque(so, &slirp->tcb);\n\n\t/*\n\t * SS_FACCEPTONCE sockets must time out.\n\t */\n\tif (flags & SS_FACCEPTONCE)\n\t   so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;\n\n\tso->so_state &= SS_PERSISTENT_MASK;\n\tso->so_state |= (SS_FACCEPTCONN | flags);\n\tso->so_lport = lport; /* Kept in network format */\n\tso->so_laddr.s_addr = laddr; /* Ditto */\n\n\taddr.sin_family = AF_INET;\n\taddr.sin_addr.s_addr = haddr;\n\taddr.sin_port = hport;\n\n\tif (((s = os_socket(AF_INET,SOCK_STREAM,0)) < 0) ||\n\t    (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||\n\t    (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||\n\t    (listen(s,1) < 0)) {\n\t\tint tmperrno = errno; /* Don't clobber the real reason we failed */\n\n\t\tclose(s);\n\t\tsofree(so);\n\t\t/* Restore the real errno */\n#ifdef _WIN32\n\t\tWSASetLastError(tmperrno);\n#else\n\t\terrno = tmperrno;\n#endif\n\t\treturn NULL;\n\t}\n\tsetsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));\n\n\tgetsockname(s,(struct sockaddr *)&addr,&addrlen);\n\tso->so_fport = addr.sin_port;\n\tif (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)\n\t   so->so_faddr = slirp->vhost_addr;\n\telse\n\t   so->so_faddr = addr.sin_addr;\n\n\tso->s = s;\n\treturn so;\n}\n\n/*\n * Various session state calls\n * XXX Should be #define's\n * The socket state stuff needs work, these often get call 2 or 3\n * times each when only 1 was needed\n */\nvoid\nsoisfconnecting(struct socket *so)\n{\n\tso->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|\n\t\t\t  SS_FCANTSENDMORE|SS_FWDRAIN);\n\tso->so_state |= SS_ISFCONNECTING; /* Clobber other states */\n}\n\nvoid\nsoisfconnected(struct socket *so)\n{\n\tso->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);\n\tso->so_state |= SS_ISFCONNECTED; /* Clobber other states */\n}\n\nstatic void\nsofcantrcvmore(struct socket *so)\n{\n\tif ((so->so_state & SS_NOFDREF) == 0) {\n\t\tshutdown(so->s,0);\n\t\tif(global_writefds) {\n\t\t  FD_CLR(so->s,global_writefds);\n\t\t}\n\t}\n\tso->so_state &= ~(SS_ISFCONNECTING);\n\tif (so->so_state & SS_FCANTSENDMORE) {\n\t   so->so_state &= SS_PERSISTENT_MASK;\n\t   so->so_state |= SS_NOFDREF; /* Don't select it */\n\t} else {\n\t   so->so_state |= SS_FCANTRCVMORE;\n\t}\n}\n\nstatic void\nsofcantsendmore(struct socket *so)\n{\n\tif ((so->so_state & SS_NOFDREF) == 0) {\n            shutdown(so->s,1);           /* send FIN to fhost */\n            if (global_readfds) {\n                FD_CLR(so->s,global_readfds);\n            }\n            if (global_xfds) {\n                FD_CLR(so->s,global_xfds);\n            }\n\t}\n\tso->so_state &= ~(SS_ISFCONNECTING);\n\tif (so->so_state & SS_FCANTRCVMORE) {\n\t   so->so_state &= SS_PERSISTENT_MASK;\n\t   so->so_state |= SS_NOFDREF; /* as above */\n\t} else {\n\t   so->so_state |= SS_FCANTSENDMORE;\n\t}\n}\n\n/*\n * Set write drain mode\n * Set CANTSENDMORE once all data has been write()n\n */\nvoid\nsofwdrain(struct socket *so)\n{\n\tif (so->so_rcv.sb_cc)\n\t\tso->so_state |= SS_FWDRAIN;\n\telse\n\t\tsofcantsendmore(so);\n}\n"
  },
  {
    "path": "src/slirp/socket.h",
    "content": "/*\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#ifndef _SLIRP_SOCKET_H_\n#define _SLIRP_SOCKET_H_\n\n#define SO_EXPIRE 240000\n#define SO_EXPIREFAST 10000\n\n/*\n * Our socket structure\n */\n\nstruct socket {\n  struct socket *so_next,*so_prev;      /* For a linked list of sockets */\n\n  int s;                           /* The actual socket */\n\n  Slirp *slirp;\t\t\t   /* managing slirp instance */\n\n\t\t\t/* XXX union these with not-yet-used sbuf params */\n  struct mbuf *so_m;\t           /* Pointer to the original SYN packet,\n\t\t\t\t    * for non-blocking connect()'s, and\n\t\t\t\t    * PING reply's */\n  struct tcpiphdr *so_ti;\t   /* Pointer to the original ti within\n\t\t\t\t    * so_mconn, for non-blocking connections */\n  int so_urgc;\n  struct in_addr so_faddr;\t   /* foreign host table entry */\n  struct in_addr so_laddr;\t   /* local host table entry */\n  uint16_t so_fport;\t\t   /* foreign port */\n  uint16_t so_lport;\t\t   /* local port */\n\n  uint8_t\tso_iptos;\t/* Type of service */\n  uint8_t\tso_emu;\t\t/* Is the socket emulated? */\n\n  u_char\tso_type;\t\t/* Type of socket, UDP or TCP */\n  int\tso_state;\t\t/* internal state flags SS_*, below */\n\n  struct \ttcpcb *so_tcpcb;\t/* pointer to TCP protocol control block */\n  u_int\tso_expire;\t\t/* When the socket will expire */\n\n  int\tso_queued;\t\t/* Number of packets queued from this socket */\n  int\tso_nqueued;\t\t/* Number of packets queued in a row\n\t\t\t\t * Used to determine when to \"downgrade\" a session\n\t\t\t\t\t * from fastq to batchq */\n\n  struct sbuf so_rcv;\t\t/* Receive buffer */\n  struct sbuf so_snd;\t\t/* Send buffer */\n  void * extra;\t\t\t/* Extra pointer */\n};\n\n\n/*\n * Socket state bits. (peer means the host on the Internet,\n * local host means the host on the other end of the modem)\n */\n#define SS_NOFDREF\t\t0x001\t/* No fd reference */\n\n#define SS_ISFCONNECTING\t0x002\t/* Socket is connecting to peer (non-blocking connect()'s) */\n#define SS_ISFCONNECTED\t\t0x004\t/* Socket is connected to peer */\n#define SS_FCANTRCVMORE\t\t0x008\t/* Socket can't receive more from peer (for half-closes) */\n#define SS_FCANTSENDMORE\t0x010\t/* Socket can't send more to peer (for half-closes) */\n#define SS_FWDRAIN\t\t0x040\t/* We received a FIN, drain data and set SS_FCANTSENDMORE */\n\n#define SS_CTL\t\t\t0x080\n#define SS_FACCEPTCONN\t\t0x100\t/* Socket is accepting connections from a host on the internet */\n#define SS_FACCEPTONCE\t\t0x200\t/* If set, the SS_FACCEPTCONN socket will die after one accept */\n\n#define SS_PERSISTENT_MASK\t0xf000\t/* Unremovable state bits */\n#define SS_HOSTFWD\t\t0x1000\t/* Socket describes host->guest forwarding */\n#define SS_INCOMING\t\t0x2000\t/* Connection was initiated by a host on the internet */\n\nstruct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int);\nstruct socket * socreate(Slirp *);\nvoid sofree(struct socket *);\nint soread(struct socket *);\nvoid sorecvoob(struct socket *);\nint sosendoob(struct socket *);\nint sowrite(struct socket *);\nvoid sorecvfrom(struct socket *);\nint sosendto(struct socket *, struct mbuf *);\nstruct socket * tcp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,\n                               int);\nvoid soisfconnecting(register struct socket *);\nvoid soisfconnected(register struct socket *);\nvoid sofwdrain(struct socket *);\nstruct iovec; /* For win32 */\nsize_t sopreprbuf(struct socket *so, struct iovec *iov, int *np);\nint soreadbuf(struct socket *so, const char *buf, int size);\n\n#endif /* _SOCKET_H_ */\n"
  },
  {
    "path": "src/slirp/tcp.h",
    "content": "/*\n * Copyright (c) 1982, 1986, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)tcp.h\t8.1 (Berkeley) 6/10/93\n * tcp.h,v 1.3 1994/08/21 05:27:34 paul Exp\n */\n\n#ifndef _TCP_H_\n#define _TCP_H_\n\ntypedef\tuint32_t tcp_seq;\n\n#define      PR_SLOWHZ       2               /* 2 slow timeouts per second (approx) */\n#define      PR_FASTHZ       5               /* 5 fast timeouts per second (not important) */\n\n#define TCP_SNDSPACE 8192\n#define TCP_RCVSPACE 8192\n\n/*\n * TCP header.\n * Per RFC 793, September, 1981.\n */\nstruct tcphdr {\n\tuint16_t th_sport;              /* source port */\n\tuint16_t th_dport;              /* destination port */\n\ttcp_seq\tth_seq;\t\t\t/* sequence number */\n\ttcp_seq\tth_ack;\t\t\t/* acknowledgement number */\n#ifdef HOST_WORDS_BIGENDIAN\n\tu_int\tth_off:4,\t\t/* data offset */\n\t\tth_x2:4;\t\t/* (unused) */\n#else\n\tu_int\tth_x2:4,\t\t/* (unused) */\n\t\tth_off:4;\t\t/* data offset */\n#endif\n\tuint8_t th_flags;\n#define\tTH_FIN\t0x01\n#define\tTH_SYN\t0x02\n#define\tTH_RST\t0x04\n#define\tTH_PUSH\t0x08\n#define\tTH_ACK\t0x10\n#define\tTH_URG\t0x20\n\tuint16_t th_win;                /* window */\n\tuint16_t th_sum;                /* checksum */\n\tuint16_t th_urp;                /* urgent pointer */\n};\n\n#include \"tcp_var.h\"\n\n#define\tTCPOPT_EOL\t\t0\n#define\tTCPOPT_NOP\t\t1\n#define\tTCPOPT_MAXSEG\t\t2\n#define    TCPOLEN_MAXSEG\t\t4\n#define TCPOPT_WINDOW\t\t3\n#define    TCPOLEN_WINDOW\t\t3\n#define TCPOPT_SACK_PERMITTED\t4\t\t/* Experimental */\n#define    TCPOLEN_SACK_PERMITTED\t2\n#define TCPOPT_SACK\t\t5\t\t/* Experimental */\n#define TCPOPT_TIMESTAMP\t8\n#define    TCPOLEN_TIMESTAMP\t\t10\n#define    TCPOLEN_TSTAMP_APPA\t\t(TCPOLEN_TIMESTAMP+2) /* appendix A */\n\n#define TCPOPT_TSTAMP_HDR\t\\\n    (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)\n\n/*\n * Default maximum segment size for TCP.\n * With an IP MSS of 576, this is 536,\n * but 512 is probably more convenient.\n * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)).\n *\n * We make this 1460 because we only care about Ethernet in the qemu context.\n */\n#define\tTCP_MSS\t1460\n\n#define\tTCP_MAXWIN\t65535\t/* largest value for (unscaled) window */\n\n#define TCP_MAX_WINSHIFT\t14\t/* maximum window shift */\n\n/*\n * User-settable options (used with setsockopt).\n *\n * We don't use the system headers on unix because we have conflicting\n * local structures. We can't avoid the system definitions on Windows,\n * so we undefine them.\n */\n#undef TCP_NODELAY\n#define\tTCP_NODELAY\t0x01\t/* don't delay send to coalesce packets */\n#undef TCP_MAXSEG\n\n/*\n * TCP FSM state definitions.\n * Per RFC793, September, 1981.\n */\n\n#define TCP_NSTATES     11\n\n#define TCPS_CLOSED             0       /* closed */\n#define TCPS_LISTEN             1       /* listening for connection */\n#define TCPS_SYN_SENT           2       /* active, have sent syn */\n#define TCPS_SYN_RECEIVED       3       /* have send and received syn */\n/* states < TCPS_ESTABLISHED are those where connections not established */\n#define TCPS_ESTABLISHED        4       /* established */\n#define TCPS_CLOSE_WAIT         5       /* rcvd fin, waiting for close */\n/* states > TCPS_CLOSE_WAIT are those where user has closed */\n#define TCPS_FIN_WAIT_1         6       /* have closed, sent fin */\n#define TCPS_CLOSING            7       /* closed xchd FIN; await FIN ACK */\n#define TCPS_LAST_ACK           8       /* had fin and close; await FIN ACK */\n/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */\n#define TCPS_FIN_WAIT_2         9       /* have closed, fin is acked */\n#define TCPS_TIME_WAIT          10      /* in 2*msl quiet wait after close */\n\n#define TCPS_HAVERCVDSYN(s)     ((s) >= TCPS_SYN_RECEIVED)\n#define TCPS_HAVEESTABLISHED(s) ((s) >= TCPS_ESTABLISHED)\n#define TCPS_HAVERCVDFIN(s)     ((s) >= TCPS_TIME_WAIT)\n\n/*\n * TCP sequence numbers are 32 bit integers operated\n * on with modular arithmetic.  These macros can be\n * used to compare such integers.\n */\n#define SEQ_LT(a,b)     ((int)((a)-(b)) < 0)\n#define SEQ_LEQ(a,b)    ((int)((a)-(b)) <= 0)\n#define SEQ_GT(a,b)     ((int)((a)-(b)) > 0)\n#define SEQ_GEQ(a,b)    ((int)((a)-(b)) >= 0)\n\n/*\n * Macros to initialize tcp sequence numbers for\n * send and receive from initial send and receive\n * sequence numbers.\n */\n#define tcp_rcvseqinit(tp) \\\n     (tp)->rcv_adv = (tp)->rcv_nxt = (tp)->irs + 1\n\n#define tcp_sendseqinit(tp) \\\n    (tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = (tp)->iss\n\n#define TCP_ISSINCR     (125*1024)      /* increment for tcp_iss each second */\n\n#endif\n"
  },
  {
    "path": "src/slirp/tcp_input.c",
    "content": "/*\n * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)tcp_input.c\t8.5 (Berkeley) 4/10/94\n * tcp_input.c,v 1.10 1994/10/13 18:36:32 wollman Exp\n */\n\n/*\n * Changes and additions relating to SLiRP\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#include \"slirp.h\"\n#include \"ip_icmp.h\"\n\n#define\tTCPREXMTTHRESH 3\n\n#define TCP_PAWS_IDLE\t(24 * 24 * 60 * 60 * PR_SLOWHZ)\n\n/* for modulo comparisons of timestamps */\n#define TSTMP_LT(a,b)\t((int)((a)-(b)) < 0)\n#define TSTMP_GEQ(a,b)\t((int)((a)-(b)) >= 0)\n\n/*\n * Insert segment ti into reassembly queue of tcp with\n * control block tp.  Return TH_FIN if reassembly now includes\n * a segment with FIN.  The macro form does the common case inline\n * (segment is the next to be received on an established connection,\n * and the queue is empty), avoiding linkage into and removal\n * from the queue and repetition of various conversions.\n * Set DELACK for segments received in order, but ack immediately\n * when segments are out of order (so fast retransmit can work).\n */\n#ifdef TCP_ACK_HACK\n#define TCP_REASS(tp, ti, m, so, flags) {\\\n       if ((ti)->ti_seq == (tp)->rcv_nxt && \\\n           tcpfrag_list_empty(tp) && \\\n           (tp)->t_state == TCPS_ESTABLISHED) {\\\n               if (ti->ti_flags & TH_PUSH) \\\n                       tp->t_flags |= TF_ACKNOW; \\\n               else \\\n                       tp->t_flags |= TF_DELACK; \\\n               (tp)->rcv_nxt += (ti)->ti_len; \\\n               flags = (ti)->ti_flags & TH_FIN; \\\n               if (so->so_emu) { \\\n\t\t       if (tcp_emu((so),(m))) sbappend((so), (m)); \\\n\t       } else \\\n\t       \t       sbappend((so), (m)); \\\n\t} else {\\\n               (flags) = tcp_reass((tp), (ti), (m)); \\\n               tp->t_flags |= TF_ACKNOW; \\\n       } \\\n}\n#else\n#define\tTCP_REASS(tp, ti, m, so, flags) { \\\n\tif ((ti)->ti_seq == (tp)->rcv_nxt && \\\n        tcpfrag_list_empty(tp) && \\\n\t    (tp)->t_state == TCPS_ESTABLISHED) { \\\n\t\ttp->t_flags |= TF_DELACK; \\\n\t\t(tp)->rcv_nxt += (ti)->ti_len; \\\n\t\tflags = (ti)->ti_flags & TH_FIN; \\\n\t\tif (so->so_emu) { \\\n\t\t\tif (tcp_emu((so),(m))) sbappend(so, (m)); \\\n\t\t} else \\\n\t\t\tsbappend((so), (m)); \\\n\t} else { \\\n\t\t(flags) = tcp_reass((tp), (ti), (m)); \\\n\t\ttp->t_flags |= TF_ACKNOW; \\\n\t} \\\n}\n#endif\nstatic void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt,\n                          struct tcpiphdr *ti);\nstatic void tcp_xmit_timer(register struct tcpcb *tp, int rtt);\n\nstatic int\ntcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,\n          struct mbuf *m)\n{\n\tregister struct tcpiphdr *q;\n\tstruct socket *so = tp->t_socket;\n\tint flags;\n\n\t/*\n\t * Call with ti==NULL after become established to\n\t * force pre-ESTABLISHED data up to user socket.\n\t */\n        if (ti == NULL)\n\t\tgoto present;\n\n\t/*\n\t * Find a segment which begins after this one does.\n\t */\n\tfor (q = tcpfrag_list_first(tp); !tcpfrag_list_end(q, tp);\n            q = tcpiphdr_next(q))\n\t\tif (SEQ_GT(q->ti_seq, ti->ti_seq))\n\t\t\tbreak;\n\n\t/*\n\t * If there is a preceding segment, it may provide some of\n\t * our data already.  If so, drop the data from the incoming\n\t * segment.  If it provides all of our data, drop us.\n\t */\n\tif (!tcpfrag_list_end(tcpiphdr_prev(q), tp)) {\n\t\tregister int i;\n\t\tq = tcpiphdr_prev(q);\n\t\t/* conversion to int (in i) handles seq wraparound */\n\t\ti = q->ti_seq + q->ti_len - ti->ti_seq;\n\t\tif (i > 0) {\n\t\t\tif (i >= ti->ti_len) {\n\t\t\t\tm_freem(m);\n\t\t\t\t/*\n\t\t\t\t * Try to present any queued data\n\t\t\t\t * at the left window edge to the user.\n\t\t\t\t * This is needed after the 3-WHS\n\t\t\t\t * completes.\n\t\t\t\t */\n\t\t\t\tgoto present;   /* ??? */\n\t\t\t}\n\t\t\tm_adj(m, i);\n\t\t\tti->ti_len -= i;\n\t\t\tti->ti_seq += i;\n\t\t}\n\t\tq = tcpiphdr_next(q);\n\t}\n\tti->ti_mbuf = m;\n\n\t/*\n\t * While we overlap succeeding segments trim them or,\n\t * if they are completely covered, dequeue them.\n\t */\n\twhile (!tcpfrag_list_end(q, tp)) {\n\t\tregister int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;\n\t\tif (i <= 0)\n\t\t\tbreak;\n\t\tif (i < q->ti_len) {\n\t\t\tq->ti_seq += i;\n\t\t\tq->ti_len -= i;\n\t\t\tm_adj(q->ti_mbuf, i);\n\t\t\tbreak;\n\t\t}\n\t\tq = tcpiphdr_next(q);\n\t\tm = tcpiphdr_prev(q)->ti_mbuf;\n\t\tremque(tcpiphdr2qlink(tcpiphdr_prev(q)));\n\t\tm_freem(m);\n\t}\n\n\t/*\n\t * Stick new segment in its place.\n\t */\n\tinsque(tcpiphdr2qlink(ti), tcpiphdr2qlink(tcpiphdr_prev(q)));\n\npresent:\n\t/*\n\t * Present data to user, advancing rcv_nxt through\n\t * completed sequence space.\n\t */\n\tif (!TCPS_HAVEESTABLISHED(tp->t_state))\n\t\treturn (0);\n\tti = tcpfrag_list_first(tp);\n\tif (tcpfrag_list_end(ti, tp) || ti->ti_seq != tp->rcv_nxt)\n\t\treturn (0);\n\tif (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len)\n\t\treturn (0);\n\tdo {\n\t\ttp->rcv_nxt += ti->ti_len;\n\t\tflags = ti->ti_flags & TH_FIN;\n\t\tremque(tcpiphdr2qlink(ti));\n\t\tm = ti->ti_mbuf;\n\t\tti = tcpiphdr_next(ti);\n\t\tif (so->so_state & SS_FCANTSENDMORE)\n\t\t\tm_freem(m);\n\t\telse {\n\t\t\tif (so->so_emu) {\n\t\t\t\tif (tcp_emu(so,m)) sbappend(so, m);\n\t\t\t} else\n\t\t\t\tsbappend(so, m);\n\t\t}\n\t} while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);\n\treturn (flags);\n}\n\n/*\n * TCP input routine, follows pages 65-76 of the\n * protocol specification dated September, 1981 very closely.\n */\nvoid\ntcp_input(struct mbuf *m, int iphlen, struct socket *inso)\n{\n  \tstruct ip save_ip, *ip;\n\tregister struct tcpiphdr *ti;\n\tcaddr_t optp = NULL;\n\tint optlen = 0;\n\tint len, tlen, off;\n        register struct tcpcb *tp = NULL;\n\tregister int tiflags;\n        struct socket *so = NULL;\n\tint todrop, acked, ourfinisacked, needoutput = 0;\n\tint iss = 0;\n\tu_long tiwin;\n\tint ret;\n    struct ex_list *ex_ptr;\n    Slirp *slirp;\n\n\tDEBUG_CALL(\"tcp_input\");\n\tDEBUG_ARGS((dfd,\" m = %8lx  iphlen = %2d  inso = %lx\\n\",\n\t\t    (long )m, iphlen, (long )inso ));\n\n\t/*\n\t * If called with m == 0, then we're continuing the connect\n\t */\n\tif (m == NULL) {\n\t\tso = inso;\n\t\tslirp = so->slirp;\n\n\t\t/* Re-set a few variables */\n\t\ttp = sototcpcb(so);\n\t\tm = so->so_m;\n                so->so_m = NULL;\n\t\tti = so->so_ti;\n\t\ttiwin = ti->ti_win;\n\t\ttiflags = ti->ti_flags;\n\n\t\tgoto cont_conn;\n\t}\n\tslirp = m->slirp;\n\n\t/*\n\t * Get IP and TCP header together in first mbuf.\n\t * Note: IP leaves IP header in first mbuf.\n\t */\n\tti = mtod(m, struct tcpiphdr *);\n\tif (iphlen > sizeof(struct ip )) {\n\t  ip_stripoptions(m, (struct mbuf *)0);\n\t  iphlen=sizeof(struct ip );\n\t}\n\t/* XXX Check if too short */\n\n\n\t/*\n\t * Save a copy of the IP header in case we want restore it\n\t * for sending an ICMP error message in response.\n\t */\n\tip=mtod(m, struct ip *);\n\tsave_ip = *ip;\n\tsave_ip.ip_len+= iphlen;\n\n\t/*\n\t * Checksum extended TCP header and data.\n\t */\n\ttlen = ((struct ip *)ti)->ip_len;\n        tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;\n        memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));\n\tti->ti_x1 = 0;\n\tti->ti_len = htons((uint16_t)tlen);\n\tlen = sizeof(struct ip ) + tlen;\n\tif(cksum(m, len)) {\n\t  goto drop;\n\t}\n\n\t/*\n\t * Check that TCP offset makes sense,\n\t * pull out TCP options and adjust length.\t\tXXX\n\t */\n\toff = ti->ti_off << 2;\n\tif (off < sizeof (struct tcphdr) || off > tlen) {\n\t  goto drop;\n\t}\n\ttlen -= off;\n\tti->ti_len = tlen;\n\tif (off > sizeof (struct tcphdr)) {\n\t  optlen = off - sizeof (struct tcphdr);\n\t  optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr);\n\t}\n\ttiflags = ti->ti_flags;\n\n\t/*\n\t * Convert TCP protocol specific fields to host format.\n\t */\n\tNTOHL(ti->ti_seq);\n\tNTOHL(ti->ti_ack);\n\tNTOHS(ti->ti_win);\n\tNTOHS(ti->ti_urp);\n\n\t/*\n\t * Drop TCP, IP headers and TCP options.\n\t */\n\tm->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);\n\tm->m_len  -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);\n\n    if (slirp->restricted) {\n        for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {\n            if (ex_ptr->ex_fport == ti->ti_dport &&\n                ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) {\n                break;\n            }\n        }\n        if (!ex_ptr)\n            goto drop;\n    }\n\t/*\n\t * Locate pcb for segment.\n\t */\nfindso:\n\tso = slirp->tcp_last_so;\n\tif (so->so_fport != ti->ti_dport ||\n\t    so->so_lport != ti->ti_sport ||\n\t    so->so_laddr.s_addr != ti->ti_src.s_addr ||\n\t    so->so_faddr.s_addr != ti->ti_dst.s_addr) {\n\t\tso = solookup(&slirp->tcb, ti->ti_src, ti->ti_sport,\n\t\t\t       ti->ti_dst, ti->ti_dport);\n\t\tif (so)\n\t\t\tslirp->tcp_last_so = so;\n\t}\n\n\t/*\n\t * If the state is CLOSED (i.e., TCB does not exist) then\n\t * all data in the incoming segment is discarded.\n\t * If the TCB exists but is in CLOSED state, it is embryonic,\n\t * but should either do a listen or a connect soon.\n\t *\n\t * state == CLOSED means we've done socreate() but haven't\n\t * attached it to a protocol yet...\n\t *\n\t * XXX If a TCB does not exist, and the TH_SYN flag is\n\t * the only flag set, then create a session, mark it\n\t * as if it was LISTENING, and continue...\n\t */\n        if (so == NULL) {\n\t  if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN)\n\t    goto dropwithreset;\n\n\t  if ((so = socreate(slirp)) == NULL)\n\t    goto dropwithreset;\n\t  if (tcp_attach(so) < 0) {\n\t    free(so); /* Not sofree (if it failed, it's not insqued) */\n\t    goto dropwithreset;\n\t  }\n\n\t  sbreserve(&so->so_snd, TCP_SNDSPACE);\n\t  sbreserve(&so->so_rcv, TCP_RCVSPACE);\n\n\t  so->so_laddr = ti->ti_src;\n\t  so->so_lport = ti->ti_sport;\n\t  so->so_faddr = ti->ti_dst;\n\t  so->so_fport = ti->ti_dport;\n\n\t  if ((so->so_iptos = tcp_tos(so)) == 0)\n\t    so->so_iptos = ((struct ip *)ti)->ip_tos;\n\n\t  tp = sototcpcb(so);\n\t  tp->t_state = TCPS_LISTEN;\n\t}\n\n        /*\n         * If this is a still-connecting socket, this probably\n         * a retransmit of the SYN.  Whether it's a retransmit SYN\n\t * or something else, we nuke it.\n         */\n        if (so->so_state & SS_ISFCONNECTING)\n                goto drop;\n\n\ttp = sototcpcb(so);\n\n\t/* XXX Should never fail */\n        if (tp == NULL)\n\t\tgoto dropwithreset;\n\tif (tp->t_state == TCPS_CLOSED)\n\t\tgoto drop;\n\n\ttiwin = ti->ti_win;\n\n\t/*\n\t * Segment received on connection.\n\t * Reset idle time and keep-alive timer.\n\t */\n\ttp->t_idle = 0;\n\tif (SO_OPTIONS)\n\t   tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;\n\telse\n\t   tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;\n\n\t/*\n\t * Process options if not in LISTEN state,\n\t * else do it below (after getting remote address).\n\t */\n\tif (optp && tp->t_state != TCPS_LISTEN)\n\t\ttcp_dooptions(tp, (u_char *)optp, optlen, ti);\n\n\t/*\n\t * Header prediction: check for the two common cases\n\t * of a uni-directional data xfer.  If the packet has\n\t * no control flags, is in-sequence, the window didn't\n\t * change and we're not retransmitting, it's a\n\t * candidate.  If the length is zero and the ack moved\n\t * forward, we're the sender side of the xfer.  Just\n\t * free the data acked & wake any higher level process\n\t * that was blocked waiting for space.  If the length\n\t * is non-zero and the ack didn't move, we're the\n\t * receiver side.  If we're getting packets in-order\n\t * (the reassembly queue is empty), add the data to\n\t * the socket buffer and note that we need a delayed ack.\n\t *\n\t * XXX Some of these tests are not needed\n\t * eg: the tiwin == tp->snd_wnd prevents many more\n\t * predictions.. with no *real* advantage..\n\t */\n\tif (tp->t_state == TCPS_ESTABLISHED &&\n\t    (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&\n\t    ti->ti_seq == tp->rcv_nxt &&\n\t    tiwin && tiwin == tp->snd_wnd &&\n\t    tp->snd_nxt == tp->snd_max) {\n\t\tif (ti->ti_len == 0) {\n\t\t\tif (SEQ_GT(ti->ti_ack, tp->snd_una) &&\n\t\t\t    SEQ_LEQ(ti->ti_ack, tp->snd_max) &&\n\t\t\t    tp->snd_cwnd >= tp->snd_wnd) {\n\t\t\t\t/*\n\t\t\t\t * this is a pure ack for outstanding data.\n\t\t\t\t */\n\t\t\t\tif (tp->t_rtt &&\n\t\t\t\t    SEQ_GT(ti->ti_ack, tp->t_rtseq))\n\t\t\t\t\ttcp_xmit_timer(tp, tp->t_rtt);\n\t\t\t\tacked = ti->ti_ack - tp->snd_una;\n\t\t\t\tsbdrop(&so->so_snd, acked);\n\t\t\t\ttp->snd_una = ti->ti_ack;\n\t\t\t\tm_freem(m);\n\n\t\t\t\t/*\n\t\t\t\t * If all outstanding data are acked, stop\n\t\t\t\t * retransmit timer, otherwise restart timer\n\t\t\t\t * using current (possibly backed-off) value.\n\t\t\t\t * If process is waiting for space,\n\t\t\t\t * wakeup/selwakeup/signal.  If data\n\t\t\t\t * are ready to send, let tcp_output\n\t\t\t\t * decide between more output or persist.\n\t\t\t\t */\n\t\t\t\tif (tp->snd_una == tp->snd_max)\n\t\t\t\t\ttp->t_timer[TCPT_REXMT] = 0;\n\t\t\t\telse if (tp->t_timer[TCPT_PERSIST] == 0)\n\t\t\t\t\ttp->t_timer[TCPT_REXMT] = tp->t_rxtcur;\n\n\t\t\t\t/*\n\t\t\t\t * This is called because sowwakeup might have\n\t\t\t\t * put data into so_snd.  Since we don't so sowwakeup,\n\t\t\t\t * we don't need this.. XXX???\n\t\t\t\t */\n\t\t\t\tif (so->so_snd.sb_cc)\n\t\t\t\t\t(void) tcp_output(tp);\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else if (ti->ti_ack == tp->snd_una &&\n\t\t    tcpfrag_list_empty(tp) &&\n\t\t    ti->ti_len <= sbspace(&so->so_rcv)) {\n\t\t\t/*\n\t\t\t * this is a pure, in-sequence data packet\n\t\t\t * with nothing on the reassembly queue and\n\t\t\t * we have enough buffer space to take it.\n\t\t\t */\n\t\t\ttp->rcv_nxt += ti->ti_len;\n\t\t\t/*\n\t\t\t * Add data to socket buffer.\n\t\t\t */\n\t\t\tif (so->so_emu) {\n\t\t\t\tif (tcp_emu(so,m)) sbappend(so, m);\n\t\t\t} else\n\t\t\t\tsbappend(so, m);\n\n\t\t\t/*\n\t\t\t * If this is a short packet, then ACK now - with Nagel\n\t\t\t *\tcongestion avoidance sender won't send more until\n\t\t\t *\the gets an ACK.\n\t\t\t *\n\t\t\t * It is better to not delay acks at all to maximize\n\t\t\t * TCP throughput.  See RFC 2581.\n\t\t\t */\n\t\t\ttp->t_flags |= TF_ACKNOW;\n\t\t\ttcp_output(tp);\n\t\t\treturn;\n\t\t}\n\t} /* header prediction */\n\t/*\n\t * Calculate amount of space in receive window,\n\t * and then do TCP input processing.\n\t * Receive window is amount of space in rcv queue,\n\t * but not less than advertised window.\n\t */\n\t{ int win;\n          win = sbspace(&so->so_rcv);\n\t  if (win < 0)\n\t    win = 0;\n\t  tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt));\n\t}\n\n\tswitch (tp->t_state) {\n\n\t/*\n\t * If the state is LISTEN then ignore segment if it contains an RST.\n\t * If the segment contains an ACK then it is bad and send a RST.\n\t * If it does not contain a SYN then it is not interesting; drop it.\n\t * Don't bother responding if the destination was a broadcast.\n\t * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial\n\t * tp->iss, and send a segment:\n\t *     <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK>\n\t * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss.\n\t * Fill in remote peer address fields if not previously specified.\n\t * Enter SYN_RECEIVED state, and process any other fields of this\n\t * segment in this state.\n\t */\n\tcase TCPS_LISTEN: {\n\n\t  if (tiflags & TH_RST)\n\t    goto drop;\n\t  if (tiflags & TH_ACK)\n\t    goto dropwithreset;\n\t  if ((tiflags & TH_SYN) == 0)\n\t    goto drop;\n\n\t  /*\n\t   * This has way too many gotos...\n\t   * But a bit of spaghetti code never hurt anybody :)\n\t   */\n\n\t  /*\n\t   * If this is destined for the control address, then flag to\n\t   * tcp_ctl once connected, otherwise connect\n\t   */\n\t  if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==\n\t      slirp->vnetwork_addr.s_addr) {\n\t    if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&\n\t\tso->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {\n\t\t/* May be an add exec */\n\t\tfor (ex_ptr = slirp->exec_list; ex_ptr;\n\t\t     ex_ptr = ex_ptr->ex_next) {\n\t\t  if(ex_ptr->ex_fport == so->so_fport &&\n\t\t     so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {\n\t\t    so->so_state |= SS_CTL;\n\t\t    break;\n\t\t  }\n\t\t}\n\t\tif (so->so_state & SS_CTL) {\n\t\t    goto cont_input;\n\t\t}\n\t    }\n\t    /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */\n\t  }\n\n\t  if (so->so_emu & EMU_NOCONNECT) {\n\t    so->so_emu &= ~EMU_NOCONNECT;\n\t    goto cont_input;\n\t  }\n\n\t  if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) {\n\t    u_char code=ICMP_UNREACH_NET;\n\t    DEBUG_MISC((dfd,\" tcp fconnect errno = %d-%s\\n\",\n\t\t\terrno,strerror(errno)));\n\t    if(errno == ECONNREFUSED) {\n\t      /* ACK the SYN, send RST to refuse the connection */\n\t      tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0,\n\t\t\t  TH_RST|TH_ACK);\n\t    } else {\n\t      if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;\n\t      HTONL(ti->ti_seq);             /* restore tcp header */\n\t      HTONL(ti->ti_ack);\n\t      HTONS(ti->ti_win);\n\t      HTONS(ti->ti_urp);\n\t      m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);\n\t      m->m_len  += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);\n\t      *ip=save_ip;\n\t      icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno));\n\t    }\n            tcp_close(tp);\n\t    m_free(m);\n\t  } else {\n\t    /*\n\t     * Haven't connected yet, save the current mbuf\n\t     * and ti, and return\n\t     * XXX Some OS's don't tell us whether the connect()\n\t     * succeeded or not.  So we must time it out.\n\t     */\n\t    so->so_m = m;\n\t    so->so_ti = ti;\n\t    tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;\n\t    tp->t_state = TCPS_SYN_RECEIVED;\n\t  }\n\t  return;\n\n\tcont_conn:\n\t  /* m==NULL\n\t   * Check if the connect succeeded\n\t   */\n\t  if (so->so_state & SS_NOFDREF) {\n\t    tp = tcp_close(tp);\n\t    goto dropwithreset;\n\t  }\n\tcont_input:\n\t  tcp_template(tp);\n\n\t  if (optp)\n\t    tcp_dooptions(tp, (u_char *)optp, optlen, ti);\n\n\t  if (iss)\n\t    tp->iss = iss;\n\t  else\n\t    tp->iss = slirp->tcp_iss;\n\t  slirp->tcp_iss += TCP_ISSINCR/2;\n\t  tp->irs = ti->ti_seq;\n\t  tcp_sendseqinit(tp);\n\t  tcp_rcvseqinit(tp);\n\t  tp->t_flags |= TF_ACKNOW;\n\t  tp->t_state = TCPS_SYN_RECEIVED;\n\t  tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;\n\t  goto trimthenstep6;\n\t} /* case TCPS_LISTEN */\n\n\t/*\n\t * If the state is SYN_SENT:\n\t *\tif seg contains an ACK, but not for our SYN, drop the input.\n\t *\tif seg contains a RST, then drop the connection.\n\t *\tif seg does not contain SYN, then drop it.\n\t * Otherwise this is an acceptable SYN segment\n\t *\tinitialize tp->rcv_nxt and tp->irs\n\t *\tif seg contains ack then advance tp->snd_una\n\t *\tif SYN has been acked change to ESTABLISHED else SYN_RCVD state\n\t *\tarrange for segment to be acked (eventually)\n\t *\tcontinue processing rest of data/controls, beginning with URG\n\t */\n\tcase TCPS_SYN_SENT:\n\t\tif ((tiflags & TH_ACK) &&\n\t\t    (SEQ_LEQ(ti->ti_ack, tp->iss) ||\n\t\t     SEQ_GT(ti->ti_ack, tp->snd_max)))\n\t\t\tgoto dropwithreset;\n\n\t\tif (tiflags & TH_RST) {\n                        if (tiflags & TH_ACK) {\n                                tcp_drop(tp, 0); /* XXX Check t_softerror! */\n                        }\n\t\t\tgoto drop;\n\t\t}\n\n\t\tif ((tiflags & TH_SYN) == 0)\n\t\t\tgoto drop;\n\t\tif (tiflags & TH_ACK) {\n\t\t\ttp->snd_una = ti->ti_ack;\n\t\t\tif (SEQ_LT(tp->snd_nxt, tp->snd_una))\n\t\t\t\ttp->snd_nxt = tp->snd_una;\n\t\t}\n\n\t\ttp->t_timer[TCPT_REXMT] = 0;\n\t\ttp->irs = ti->ti_seq;\n\t\ttcp_rcvseqinit(tp);\n\t\ttp->t_flags |= TF_ACKNOW;\n\t\tif (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) {\n\t\t\tsoisfconnected(so);\n\t\t\ttp->t_state = TCPS_ESTABLISHED;\n\n\t\t\t(void) tcp_reass(tp, (struct tcpiphdr *)0,\n\t\t\t\t(struct mbuf *)0);\n\t\t\t/*\n\t\t\t * if we didn't have to retransmit the SYN,\n\t\t\t * use its rtt as our initial srtt & rtt var.\n\t\t\t */\n\t\t\tif (tp->t_rtt)\n\t\t\t\ttcp_xmit_timer(tp, tp->t_rtt);\n\t\t} else\n\t\t\ttp->t_state = TCPS_SYN_RECEIVED;\n\ntrimthenstep6:\n\t\t/*\n\t\t * Advance ti->ti_seq to correspond to first data byte.\n\t\t * If data, trim to stay within window,\n\t\t * dropping FIN if necessary.\n\t\t */\n\t\tti->ti_seq++;\n\t\tif (ti->ti_len > tp->rcv_wnd) {\n\t\t\ttodrop = ti->ti_len - tp->rcv_wnd;\n\t\t\tm_adj(m, -todrop);\n\t\t\tti->ti_len = tp->rcv_wnd;\n\t\t\ttiflags &= ~TH_FIN;\n\t\t}\n\t\ttp->snd_wl1 = ti->ti_seq - 1;\n\t\ttp->rcv_up = ti->ti_seq;\n\t\tgoto step6;\n\t} /* switch tp->t_state */\n\t/*\n\t * States other than LISTEN or SYN_SENT.\n\t * Check that at least some bytes of segment are within\n\t * receive window.  If segment begins before rcv_nxt,\n\t * drop leading data (and SYN); if nothing left, just ack.\n\t */\n\ttodrop = tp->rcv_nxt - ti->ti_seq;\n\tif (todrop > 0) {\n\t\tif (tiflags & TH_SYN) {\n\t\t\ttiflags &= ~TH_SYN;\n\t\t\tti->ti_seq++;\n\t\t\tif (ti->ti_urp > 1)\n\t\t\t\tti->ti_urp--;\n\t\t\telse\n\t\t\t\ttiflags &= ~TH_URG;\n\t\t\ttodrop--;\n\t\t}\n\t\t/*\n\t\t * Following if statement from Stevens, vol. 2, p. 960.\n\t\t */\n\t\tif (todrop > ti->ti_len\n\t\t    || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) {\n\t\t\t/*\n\t\t\t * Any valid FIN must be to the left of the window.\n\t\t\t * At this point the FIN must be a duplicate or out\n\t\t\t * of sequence; drop it.\n\t\t\t */\n\t\t\ttiflags &= ~TH_FIN;\n\n\t\t\t/*\n\t\t\t * Send an ACK to resynchronize and drop any data.\n\t\t\t * But keep on processing for RST or ACK.\n\t\t\t */\n\t\t\ttp->t_flags |= TF_ACKNOW;\n\t\t\ttodrop = ti->ti_len;\n\t\t}\n\t\tm_adj(m, todrop);\n\t\tti->ti_seq += todrop;\n\t\tti->ti_len -= todrop;\n\t\tif (ti->ti_urp > todrop)\n\t\t\tti->ti_urp -= todrop;\n\t\telse {\n\t\t\ttiflags &= ~TH_URG;\n\t\t\tti->ti_urp = 0;\n\t\t}\n\t}\n\t/*\n\t * If new data are received on a connection after the\n\t * user processes are gone, then RST the other end.\n\t */\n\tif ((so->so_state & SS_NOFDREF) &&\n\t    tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {\n\t\ttp = tcp_close(tp);\n\t\tgoto dropwithreset;\n\t}\n\n\t/*\n\t * If segment ends after window, drop trailing data\n\t * (and PUSH and FIN); if nothing left, just ACK.\n\t */\n\ttodrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);\n\tif (todrop > 0) {\n\t\tif (todrop >= ti->ti_len) {\n\t\t\t/*\n\t\t\t * If a new connection request is received\n\t\t\t * while in TIME_WAIT, drop the old connection\n\t\t\t * and start over if the sequence numbers\n\t\t\t * are above the previous ones.\n\t\t\t */\n\t\t\tif (tiflags & TH_SYN &&\n\t\t\t    tp->t_state == TCPS_TIME_WAIT &&\n\t\t\t    SEQ_GT(ti->ti_seq, tp->rcv_nxt)) {\n\t\t\t\tiss = tp->rcv_nxt + TCP_ISSINCR;\n\t\t\t\ttp = tcp_close(tp);\n\t\t\t\tgoto findso;\n\t\t\t}\n\t\t\t/*\n\t\t\t * If window is closed can only take segments at\n\t\t\t * window edge, and have to drop data and PUSH from\n\t\t\t * incoming segments.  Continue processing, but\n\t\t\t * remember to ack.  Otherwise, drop segment\n\t\t\t * and ack.\n\t\t\t */\n\t\t\tif (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {\n\t\t\t\ttp->t_flags |= TF_ACKNOW;\n\t\t\t} else {\n\t\t\t\tgoto dropafterack;\n\t\t\t}\n\t\t}\n\t\tm_adj(m, -todrop);\n\t\tti->ti_len -= todrop;\n\t\ttiflags &= ~(TH_PUSH|TH_FIN);\n\t}\n\n\t/*\n\t * If the RST bit is set examine the state:\n\t *    SYN_RECEIVED STATE:\n\t *\tIf passive open, return to LISTEN state.\n\t *\tIf active open, inform user that connection was refused.\n\t *    ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:\n\t *\tInform user that connection was reset, and close tcb.\n\t *    CLOSING, LAST_ACK, TIME_WAIT STATES\n\t *\tClose the tcb.\n\t */\n\tif (tiflags&TH_RST) switch (tp->t_state) {\n\n\tcase TCPS_SYN_RECEIVED:\n\tcase TCPS_ESTABLISHED:\n\tcase TCPS_FIN_WAIT_1:\n\tcase TCPS_FIN_WAIT_2:\n\tcase TCPS_CLOSE_WAIT:\n\t\ttp->t_state = TCPS_CLOSED;\n                tcp_close(tp);\n\t\tgoto drop;\n\n\tcase TCPS_CLOSING:\n\tcase TCPS_LAST_ACK:\n\tcase TCPS_TIME_WAIT:\n                tcp_close(tp);\n\t\tgoto drop;\n\t}\n\n\t/*\n\t * If a SYN is in the window, then this is an\n\t * error and we send an RST and drop the connection.\n\t */\n\tif (tiflags & TH_SYN) {\n\t\ttp = tcp_drop(tp,0);\n\t\tgoto dropwithreset;\n\t}\n\n\t/*\n\t * If the ACK bit is off we drop the segment and return.\n\t */\n\tif ((tiflags & TH_ACK) == 0) goto drop;\n\n\t/*\n\t * Ack processing.\n\t */\n\tswitch (tp->t_state) {\n\t/*\n\t * In SYN_RECEIVED state if the ack ACKs our SYN then enter\n\t * ESTABLISHED state and continue processing, otherwise\n\t * send an RST.  una<=ack<=max\n\t */\n\tcase TCPS_SYN_RECEIVED:\n\n\t\tif (SEQ_GT(tp->snd_una, ti->ti_ack) ||\n\t\t    SEQ_GT(ti->ti_ack, tp->snd_max))\n\t\t\tgoto dropwithreset;\n\t\ttp->t_state = TCPS_ESTABLISHED;\n\t\t/*\n\t\t * The sent SYN is ack'ed with our sequence number +1\n\t\t * The first data byte already in the buffer will get\n\t\t * lost if no correction is made.  This is only needed for\n\t\t * SS_CTL since the buffer is empty otherwise.\n\t\t * tp->snd_una++; or:\n\t\t */\n\t\ttp->snd_una=ti->ti_ack;\n\t\tif (so->so_state & SS_CTL) {\n\t\t  /* So tcp_ctl reports the right state */\n\t\t  ret = tcp_ctl(so);\n\t\t  if (ret == 1) {\n\t\t    soisfconnected(so);\n\t\t    so->so_state &= ~SS_CTL;   /* success XXX */\n\t\t  } else if (ret == 2) {\n\t\t    so->so_state &= SS_PERSISTENT_MASK;\n\t\t    so->so_state |= SS_NOFDREF; /* CTL_CMD */\n\t\t  } else {\n\t\t    needoutput = 1;\n\t\t    tp->t_state = TCPS_FIN_WAIT_1;\n\t\t  }\n\t\t} else {\n\t\t  soisfconnected(so);\n\t\t}\n\n\t\t(void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0);\n\t\ttp->snd_wl1 = ti->ti_seq - 1;\n\t\t/* Avoid ack processing; snd_una==ti_ack  =>  dup ack */\n\t\tgoto synrx_to_est;\n\t\t/* fall into ... */\n\n\t/*\n\t * In ESTABLISHED state: drop duplicate ACKs; ACK out of range\n\t * ACKs.  If the ack is in the range\n\t *\ttp->snd_una < ti->ti_ack <= tp->snd_max\n\t * then advance tp->snd_una to ti->ti_ack and drop\n\t * data from the retransmission queue.  If this ACK reflects\n\t * more up to date window information we update our window information.\n\t */\n\tcase TCPS_ESTABLISHED:\n\tcase TCPS_FIN_WAIT_1:\n\tcase TCPS_FIN_WAIT_2:\n\tcase TCPS_CLOSE_WAIT:\n\tcase TCPS_CLOSING:\n\tcase TCPS_LAST_ACK:\n\tcase TCPS_TIME_WAIT:\n\n\t\tif (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {\n\t\t\tif (ti->ti_len == 0 && tiwin == tp->snd_wnd) {\n\t\t\t  DEBUG_MISC((dfd,\" dup ack  m = %lx  so = %lx \\n\",\n\t\t\t\t      (long )m, (long )so));\n\t\t\t\t/*\n\t\t\t\t * If we have outstanding data (other than\n\t\t\t\t * a window probe), this is a completely\n\t\t\t\t * duplicate ack (ie, window info didn't\n\t\t\t\t * change), the ack is the biggest we've\n\t\t\t\t * seen and we've seen exactly our rexmt\n\t\t\t\t * threshold of them, assume a packet\n\t\t\t\t * has been dropped and retransmit it.\n\t\t\t\t * Kludge snd_nxt & the congestion\n\t\t\t\t * window so we send only this one\n\t\t\t\t * packet.\n\t\t\t\t *\n\t\t\t\t * We know we're losing at the current\n\t\t\t\t * window size so do congestion avoidance\n\t\t\t\t * (set ssthresh to half the current window\n\t\t\t\t * and pull our congestion window back to\n\t\t\t\t * the new ssthresh).\n\t\t\t\t *\n\t\t\t\t * Dup acks mean that packets have left the\n\t\t\t\t * network (they're now cached at the receiver)\n\t\t\t\t * so bump cwnd by the amount in the receiver\n\t\t\t\t * to keep a constant cwnd packets in the\n\t\t\t\t * network.\n\t\t\t\t */\n\t\t\t\tif (tp->t_timer[TCPT_REXMT] == 0 ||\n\t\t\t\t    ti->ti_ack != tp->snd_una)\n\t\t\t\t\ttp->t_dupacks = 0;\n\t\t\t\telse if (++tp->t_dupacks == TCPREXMTTHRESH) {\n\t\t\t\t\ttcp_seq onxt = tp->snd_nxt;\n\t\t\t\t\tu_int win =\n\t\t\t\t\t    min(tp->snd_wnd, tp->snd_cwnd) / 2 /\n\t\t\t\t\t\ttp->t_maxseg;\n\n\t\t\t\t\tif (win < 2)\n\t\t\t\t\t\twin = 2;\n\t\t\t\t\ttp->snd_ssthresh = win * tp->t_maxseg;\n\t\t\t\t\ttp->t_timer[TCPT_REXMT] = 0;\n\t\t\t\t\ttp->t_rtt = 0;\n\t\t\t\t\ttp->snd_nxt = ti->ti_ack;\n\t\t\t\t\ttp->snd_cwnd = tp->t_maxseg;\n\t\t\t\t\t(void) tcp_output(tp);\n\t\t\t\t\ttp->snd_cwnd = tp->snd_ssthresh +\n\t\t\t\t\t       tp->t_maxseg * tp->t_dupacks;\n\t\t\t\t\tif (SEQ_GT(onxt, tp->snd_nxt))\n\t\t\t\t\t\ttp->snd_nxt = onxt;\n\t\t\t\t\tgoto drop;\n\t\t\t\t} else if (tp->t_dupacks > TCPREXMTTHRESH) {\n\t\t\t\t\ttp->snd_cwnd += tp->t_maxseg;\n\t\t\t\t\t(void) tcp_output(tp);\n\t\t\t\t\tgoto drop;\n\t\t\t\t}\n\t\t\t} else\n\t\t\t\ttp->t_dupacks = 0;\n\t\t\tbreak;\n\t\t}\n\tsynrx_to_est:\n\t\t/*\n\t\t * If the congestion window was inflated to account\n\t\t * for the other side's cached packets, retract it.\n\t\t */\n\t\tif (tp->t_dupacks > TCPREXMTTHRESH &&\n\t\t    tp->snd_cwnd > tp->snd_ssthresh)\n\t\t\ttp->snd_cwnd = tp->snd_ssthresh;\n\t\ttp->t_dupacks = 0;\n\t\tif (SEQ_GT(ti->ti_ack, tp->snd_max)) {\n\t\t\tgoto dropafterack;\n\t\t}\n\t\tacked = ti->ti_ack - tp->snd_una;\n\n\t\t/*\n\t\t * If transmit timer is running and timed sequence\n\t\t * number was acked, update smoothed round trip time.\n\t\t * Since we now have an rtt measurement, cancel the\n\t\t * timer backoff (cf., Phil Karn's retransmit alg.).\n\t\t * Recompute the initial retransmit timer.\n\t\t */\n\t\tif (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))\n\t\t\ttcp_xmit_timer(tp,tp->t_rtt);\n\n\t\t/*\n\t\t * If all outstanding data is acked, stop retransmit\n\t\t * timer and remember to restart (more output or persist).\n\t\t * If there is more data to be acked, restart retransmit\n\t\t * timer, using current (possibly backed-off) value.\n\t\t */\n\t\tif (ti->ti_ack == tp->snd_max) {\n\t\t\ttp->t_timer[TCPT_REXMT] = 0;\n\t\t\tneedoutput = 1;\n\t\t} else if (tp->t_timer[TCPT_PERSIST] == 0)\n\t\t\ttp->t_timer[TCPT_REXMT] = tp->t_rxtcur;\n\t\t/*\n\t\t * When new data is acked, open the congestion window.\n\t\t * If the window gives us less than ssthresh packets\n\t\t * in flight, open exponentially (maxseg per packet).\n\t\t * Otherwise open linearly: maxseg per window\n\t\t * (maxseg^2 / cwnd per packet).\n\t\t */\n\t\t{\n\t\t  register u_int cw = tp->snd_cwnd;\n\t\t  register u_int incr = tp->t_maxseg;\n\n\t\t  if (cw > tp->snd_ssthresh)\n\t\t    incr = incr * incr / cw;\n\t\t  tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale);\n\t\t}\n\t\tif (acked > so->so_snd.sb_cc) {\n\t\t\ttp->snd_wnd -= so->so_snd.sb_cc;\n\t\t\tsbdrop(&so->so_snd, (int )so->so_snd.sb_cc);\n\t\t\tourfinisacked = 1;\n\t\t} else {\n\t\t\tsbdrop(&so->so_snd, acked);\n\t\t\ttp->snd_wnd -= acked;\n\t\t\tourfinisacked = 0;\n\t\t}\n\t\ttp->snd_una = ti->ti_ack;\n\t\tif (SEQ_LT(tp->snd_nxt, tp->snd_una))\n\t\t\ttp->snd_nxt = tp->snd_una;\n\n\t\tswitch (tp->t_state) {\n\n\t\t/*\n\t\t * In FIN_WAIT_1 STATE in addition to the processing\n\t\t * for the ESTABLISHED state if our FIN is now acknowledged\n\t\t * then enter FIN_WAIT_2.\n\t\t */\n\t\tcase TCPS_FIN_WAIT_1:\n\t\t\tif (ourfinisacked) {\n\t\t\t\t/*\n\t\t\t\t * If we can't receive any more\n\t\t\t\t * data, then closing user can proceed.\n\t\t\t\t * Starting the timer is contrary to the\n\t\t\t\t * specification, but if we don't get a FIN\n\t\t\t\t * we'll hang forever.\n\t\t\t\t */\n\t\t\t\tif (so->so_state & SS_FCANTRCVMORE) {\n\t\t\t\t\ttp->t_timer[TCPT_2MSL] = TCP_MAXIDLE;\n\t\t\t\t}\n\t\t\t\ttp->t_state = TCPS_FIN_WAIT_2;\n\t\t\t}\n\t\t\tbreak;\n\n\t \t/*\n\t\t * In CLOSING STATE in addition to the processing for\n\t\t * the ESTABLISHED state if the ACK acknowledges our FIN\n\t\t * then enter the TIME-WAIT state, otherwise ignore\n\t\t * the segment.\n\t\t */\n\t\tcase TCPS_CLOSING:\n\t\t\tif (ourfinisacked) {\n\t\t\t\ttp->t_state = TCPS_TIME_WAIT;\n\t\t\t\ttcp_canceltimers(tp);\n\t\t\t\ttp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t * In LAST_ACK, we may still be waiting for data to drain\n\t\t * and/or to be acked, as well as for the ack of our FIN.\n\t\t * If our FIN is now acknowledged, delete the TCB,\n\t\t * enter the closed state and return.\n\t\t */\n\t\tcase TCPS_LAST_ACK:\n\t\t\tif (ourfinisacked) {\n                                tcp_close(tp);\n\t\t\t\tgoto drop;\n\t\t\t}\n\t\t\tbreak;\n\n\t\t/*\n\t\t * In TIME_WAIT state the only thing that should arrive\n\t\t * is a retransmission of the remote FIN.  Acknowledge\n\t\t * it and restart the finack timer.\n\t\t */\n\t\tcase TCPS_TIME_WAIT:\n\t\t\ttp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;\n\t\t\tgoto dropafterack;\n\t\t}\n\t} /* switch(tp->t_state) */\n\nstep6:\n\t/*\n\t * Update window information.\n\t * Don't look at window if no ACK: TAC's send garbage on first SYN.\n\t */\n\tif ((tiflags & TH_ACK) &&\n\t    (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||\n\t    (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||\n\t    (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) {\n\t\ttp->snd_wnd = tiwin;\n\t\ttp->snd_wl1 = ti->ti_seq;\n\t\ttp->snd_wl2 = ti->ti_ack;\n\t\tif (tp->snd_wnd > tp->max_sndwnd)\n\t\t\ttp->max_sndwnd = tp->snd_wnd;\n\t\tneedoutput = 1;\n\t}\n\n\t/*\n\t * Process segments with URG.\n\t */\n\tif ((tiflags & TH_URG) && ti->ti_urp &&\n\t    TCPS_HAVERCVDFIN(tp->t_state) == 0) {\n\t\t/*\n\t\t * This is a kludge, but if we receive and accept\n\t\t * random urgent pointers, we'll crash in\n\t\t * soreceive.  It's hard to imagine someone\n\t\t * actually wanting to send this much urgent data.\n\t\t */\n\t\tif (ti->ti_urp + so->so_rcv.sb_cc > so->so_rcv.sb_datalen) {\n\t\t\tti->ti_urp = 0;\n\t\t\ttiflags &= ~TH_URG;\n\t\t\tgoto dodata;\n\t\t}\n\t\t/*\n\t\t * If this segment advances the known urgent pointer,\n\t\t * then mark the data stream.  This should not happen\n\t\t * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since\n\t\t * a FIN has been received from the remote side.\n\t\t * In these states we ignore the URG.\n\t\t *\n\t\t * According to RFC961 (Assigned Protocols),\n\t\t * the urgent pointer points to the last octet\n\t\t * of urgent data.  We continue, however,\n\t\t * to consider it to indicate the first octet\n\t\t * of data past the urgent section as the original\n\t\t * spec states (in one of two places).\n\t\t */\n\t\tif (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) {\n\t\t\ttp->rcv_up = ti->ti_seq + ti->ti_urp;\n\t\t\tso->so_urgc =  so->so_rcv.sb_cc +\n\t\t\t\t(tp->rcv_up - tp->rcv_nxt); /* -1; */\n\t\t\ttp->rcv_up = ti->ti_seq + ti->ti_urp;\n\n\t\t}\n\t} else\n\t\t/*\n\t\t * If no out of band data is expected,\n\t\t * pull receive urgent pointer along\n\t\t * with the receive window.\n\t\t */\n\t\tif (SEQ_GT(tp->rcv_nxt, tp->rcv_up))\n\t\t\ttp->rcv_up = tp->rcv_nxt;\ndodata:\n\n\t/*\n\t * Process the segment text, merging it into the TCP sequencing queue,\n\t * and arranging for acknowledgment of receipt if necessary.\n\t * This process logically involves adjusting tp->rcv_wnd as data\n\t * is presented to the user (this happens in tcp_usrreq.c,\n\t * case PRU_RCVD).  If a FIN has already been received on this\n\t * connection then we just ignore the text.\n\t */\n\tif ((ti->ti_len || (tiflags&TH_FIN)) &&\n\t    TCPS_HAVERCVDFIN(tp->t_state) == 0) {\n\t\tTCP_REASS(tp, ti, m, so, tiflags);\n\t} else {\n\t\tm_free(m);\n\t\ttiflags &= ~TH_FIN;\n\t}\n\n\t/*\n\t * If FIN is received ACK the FIN and let the user know\n\t * that the connection is closing.\n\t */\n\tif (tiflags & TH_FIN) {\n\t\tif (TCPS_HAVERCVDFIN(tp->t_state) == 0) {\n\t\t\t/*\n\t\t\t * If we receive a FIN we can't send more data,\n\t\t\t * set it SS_FDRAIN\n                         * Shutdown the socket if there is no rx data in the\n\t\t\t * buffer.\n\t\t\t * soread() is called on completion of shutdown() and\n\t\t\t * will got to TCPS_LAST_ACK, and use tcp_output()\n\t\t\t * to send the FIN.\n\t\t\t */\n\t\t\tsofwdrain(so);\n\n\t\t\ttp->t_flags |= TF_ACKNOW;\n\t\t\ttp->rcv_nxt++;\n\t\t}\n\t\tswitch (tp->t_state) {\n\n\t \t/*\n\t\t * In SYN_RECEIVED and ESTABLISHED STATES\n\t\t * enter the CLOSE_WAIT state.\n\t\t */\n\t\tcase TCPS_SYN_RECEIVED:\n\t\tcase TCPS_ESTABLISHED:\n\t\t  if(so->so_emu == EMU_CTL)        /* no shutdown on socket */\n\t\t    tp->t_state = TCPS_LAST_ACK;\n\t\t  else\n\t\t    tp->t_state = TCPS_CLOSE_WAIT;\n\t\t  break;\n\n\t \t/*\n\t\t * If still in FIN_WAIT_1 STATE FIN has not been acked so\n\t\t * enter the CLOSING state.\n\t\t */\n\t\tcase TCPS_FIN_WAIT_1:\n\t\t\ttp->t_state = TCPS_CLOSING;\n\t\t\tbreak;\n\n\t \t/*\n\t\t * In FIN_WAIT_2 state enter the TIME_WAIT state,\n\t\t * starting the time-wait timer, turning off the other\n\t\t * standard timers.\n\t\t */\n\t\tcase TCPS_FIN_WAIT_2:\n\t\t\ttp->t_state = TCPS_TIME_WAIT;\n\t\t\ttcp_canceltimers(tp);\n\t\t\ttp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;\n\t\t\tbreak;\n\n\t\t/*\n\t\t * In TIME_WAIT state restart the 2 MSL time_wait timer.\n\t\t */\n\t\tcase TCPS_TIME_WAIT:\n\t\t\ttp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t * If this is a small packet, then ACK now - with Nagel\n\t *      congestion avoidance sender won't send more until\n\t *      he gets an ACK.\n\t *\n\t * See above.\n\t */\n\tif (ti->ti_len && (unsigned)ti->ti_len <= 5 &&\n\t    ((struct tcpiphdr_2 *)ti)->first_char == (char)27) {\n\t\ttp->t_flags |= TF_ACKNOW;\n\t}\n\n\t/*\n\t * Return any desired output.\n\t */\n\tif (needoutput || (tp->t_flags & TF_ACKNOW)) {\n\t\t(void) tcp_output(tp);\n\t}\n\treturn;\n\ndropafterack:\n\t/*\n\t * Generate an ACK dropping incoming segment if it occupies\n\t * sequence space, where the ACK reflects our state.\n\t */\n\tif (tiflags & TH_RST)\n\t\tgoto drop;\n\tm_freem(m);\n\ttp->t_flags |= TF_ACKNOW;\n\t(void) tcp_output(tp);\n\treturn;\n\ndropwithreset:\n\t/* reuses m if m!=NULL, m_free() unnecessary */\n\tif (tiflags & TH_ACK)\n\t\ttcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);\n\telse {\n\t\tif (tiflags & TH_SYN) ti->ti_len++;\n\t\ttcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0,\n\t\t    TH_RST|TH_ACK);\n\t}\n\n\treturn;\n\ndrop:\n\t/*\n\t * Drop space held by incoming segment and return.\n\t */\n\tm_free(m);\n\n\treturn;\n}\n\nstatic void\ntcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)\n{\n\tuint16_t mss;\n\tint opt, optlen;\n\n\tDEBUG_CALL(\"tcp_dooptions\");\n\tDEBUG_ARGS((dfd,\" tp = %lx  cnt=%i \\n\", (long )tp, cnt));\n\n\tfor (; cnt > 0; cnt -= optlen, cp += optlen) {\n\t\topt = cp[0];\n\t\tif (opt == TCPOPT_EOL)\n\t\t\tbreak;\n\t\tif (opt == TCPOPT_NOP)\n\t\t\toptlen = 1;\n\t\telse {\n\t\t\toptlen = cp[1];\n\t\t\tif (optlen <= 0)\n\t\t\t\tbreak;\n\t\t}\n\t\tswitch (opt) {\n\n\t\tdefault:\n\t\t\tcontinue;\n\n\t\tcase TCPOPT_MAXSEG:\n\t\t\tif (optlen != TCPOLEN_MAXSEG)\n\t\t\t\tcontinue;\n\t\t\tif (!(ti->ti_flags & TH_SYN))\n\t\t\t\tcontinue;\n\t\t\tmemcpy((char *) &mss, (char *) cp + 2, sizeof(mss));\n\t\t\tNTOHS(mss);\n\t\t\t(void) tcp_mss(tp, mss);\t/* sets t_maxseg */\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\n/*\n * Pull out of band byte out of a segment so\n * it doesn't appear in the user's data queue.\n * It is still reflected in the segment length for\n * sequencing purposes.\n */\n\n#ifdef notdef\n\nvoid\ntcp_pulloutofband(so, ti, m)\n\tstruct socket *so;\n\tstruct tcpiphdr *ti;\n\tregister struct mbuf *m;\n{\n\tint cnt = ti->ti_urp - 1;\n\n\twhile (cnt >= 0) {\n\t\tif (m->m_len > cnt) {\n\t\t\tchar *cp = mtod(m, caddr_t) + cnt;\n\t\t\tstruct tcpcb *tp = sototcpcb(so);\n\n\t\t\ttp->t_iobc = *cp;\n\t\t\ttp->t_oobflags |= TCPOOB_HAVEDATA;\n\t\t\tmemcpy(sp, cp+1, (unsigned)(m->m_len - cnt - 1));\n\t\t\tm->m_len--;\n\t\t\treturn;\n\t\t}\n\t\tcnt -= m->m_len;\n\t\tm = m->m_next; /* XXX WRONG! Fix it! */\n\t\tif (m == 0)\n\t\t\tbreak;\n\t}\n\tpanic(\"tcp_pulloutofband\");\n}\n\n#endif /* notdef */\n\n/*\n * Collect new round-trip time estimate\n * and update averages and current timeout.\n */\n\nstatic void\ntcp_xmit_timer(register struct tcpcb *tp, int rtt)\n{\n\tregister short delta;\n\n\tDEBUG_CALL(\"tcp_xmit_timer\");\n\tDEBUG_ARG(\"tp = %lx\", (long)tp);\n\tDEBUG_ARG(\"rtt = %d\", rtt);\n\n\tif (tp->t_srtt != 0) {\n\t\t/*\n\t\t * srtt is stored as fixed point with 3 bits after the\n\t\t * binary point (i.e., scaled by 8).  The following magic\n\t\t * is equivalent to the smoothing algorithm in rfc793 with\n\t\t * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed\n\t\t * point).  Adjust rtt to origin 0.\n\t\t */\n\t\tdelta = rtt - 1 - (tp->t_srtt >> TCP_RTT_SHIFT);\n\t\tif ((tp->t_srtt += delta) <= 0)\n\t\t\ttp->t_srtt = 1;\n\t\t/*\n\t\t * We accumulate a smoothed rtt variance (actually, a\n\t\t * smoothed mean difference), then set the retransmit\n\t\t * timer to smoothed rtt + 4 times the smoothed variance.\n\t\t * rttvar is stored as fixed point with 2 bits after the\n\t\t * binary point (scaled by 4).  The following is\n\t\t * equivalent to rfc793 smoothing with an alpha of .75\n\t\t * (rttvar = rttvar*3/4 + |delta| / 4).  This replaces\n\t\t * rfc793's wired-in beta.\n\t\t */\n\t\tif (delta < 0)\n\t\t\tdelta = -delta;\n\t\tdelta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT);\n\t\tif ((tp->t_rttvar += delta) <= 0)\n\t\t\ttp->t_rttvar = 1;\n\t} else {\n\t\t/*\n\t\t * No rtt measurement yet - use the unsmoothed rtt.\n\t\t * Set the variance to half the rtt (so our first\n\t\t * retransmit happens at 3*rtt).\n\t\t */\n\t\ttp->t_srtt = rtt << TCP_RTT_SHIFT;\n\t\ttp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1);\n\t}\n\ttp->t_rtt = 0;\n\ttp->t_rxtshift = 0;\n\n\t/*\n\t * the retransmit should happen at rtt + 4 * rttvar.\n\t * Because of the way we do the smoothing, srtt and rttvar\n\t * will each average +1/2 tick of bias.  When we compute\n\t * the retransmit timer, we want 1/2 tick of rounding and\n\t * 1 extra tick because of +-1/2 tick uncertainty in the\n\t * firing of the timer.  The bias will give us exactly the\n\t * 1.5 tick we need.  But, because the bias is\n\t * statistical, we have to test that we don't drop below\n\t * the minimum feasible timer (which is 2 ticks).\n\t */\n\tTCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),\n\t    (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */\n\n\t/*\n\t * We received an ack for a packet that wasn't retransmitted;\n\t * it is probably safe to discard any error indications we've\n\t * received recently.  This isn't quite right, but close enough\n\t * for now (a route might have failed after we sent a segment,\n\t * and the return path might not be symmetrical).\n\t */\n\ttp->t_softerror = 0;\n}\n\n/*\n * Determine a reasonable value for maxseg size.\n * If the route is known, check route for mtu.\n * If none, use an mss that can be handled on the outgoing\n * interface without forcing IP to fragment; if bigger than\n * an mbuf cluster (MCLBYTES), round down to nearest multiple of MCLBYTES\n * to utilize large mbufs.  If no route is found, route has no mtu,\n * or the destination isn't local, use a default, hopefully conservative\n * size (usually 512 or the default IP max size, but no more than the mtu\n * of the interface), as we can't discover anything about intervening\n * gateways or networks.  We also initialize the congestion/slow start\n * window to be a single segment if the destination isn't local.\n * While looking at the routing entry, we also initialize other path-dependent\n * parameters from pre-set or cached values in the routing entry.\n */\n\nint\ntcp_mss(struct tcpcb *tp, u_int offer)\n{\n\tstruct socket *so = tp->t_socket;\n\tint mss;\n\n\tDEBUG_CALL(\"tcp_mss\");\n\tDEBUG_ARG(\"tp = %lx\", (long)tp);\n\tDEBUG_ARG(\"offer = %d\", offer);\n\n\tmss = min(IF_MTU, IF_MRU) - sizeof(struct tcpiphdr);\n\tif (offer)\n\t\tmss = min(mss, offer);\n\tmss = max(mss, 32);\n\tif (mss < tp->t_maxseg || offer != 0)\n\t   tp->t_maxseg = mss;\n\n\ttp->snd_cwnd = mss;\n\n\tsbreserve(&so->so_snd, TCP_SNDSPACE + ((TCP_SNDSPACE % mss) ?\n                                               (mss - (TCP_SNDSPACE % mss)) :\n                                               0));\n\tsbreserve(&so->so_rcv, TCP_RCVSPACE + ((TCP_RCVSPACE % mss) ?\n                                               (mss - (TCP_RCVSPACE % mss)) :\n                                               0));\n\n\tDEBUG_MISC((dfd, \" returning mss = %d\\n\", mss));\n\n\treturn mss;\n}\n"
  },
  {
    "path": "src/slirp/tcp_output.c",
    "content": "/*\n * Copyright (c) 1982, 1986, 1988, 1990, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)tcp_output.c\t8.3 (Berkeley) 12/30/93\n * tcp_output.c,v 1.3 1994/09/15 10:36:55 davidg Exp\n */\n\n/*\n * Changes and additions relating to SLiRP\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#include \"slirp.h\"\n\nstatic const u_char  tcp_outflags[TCP_NSTATES] = {\n\tTH_RST|TH_ACK, 0,      TH_SYN,        TH_SYN|TH_ACK,\n\tTH_ACK,        TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,\n\tTH_FIN|TH_ACK, TH_ACK, TH_ACK,\n};\n\n\n#define MAX_TCPOPTLEN\t32\t/* max # bytes that go in options */\n\n/*\n * Tcp output routine: figure out what should be sent and send it.\n */\nint\ntcp_output(struct tcpcb *tp)\n{\n\tregister struct socket *so = tp->t_socket;\n\tregister long len, win;\n\tint off, flags, error;\n\tregister struct mbuf *m;\n\tregister struct tcpiphdr *ti;\n\tu_char opt[MAX_TCPOPTLEN];\n\tunsigned optlen, hdrlen;\n\tint idle, sendalot;\n\n\tDEBUG_CALL(\"tcp_output\");\n\tDEBUG_ARG(\"tp = %lx\", (long )tp);\n\n\t/*\n\t * Determine length of data that should be transmitted,\n\t * and flags that will be used.\n\t * If there is some data or critical controls (SYN, RST)\n\t * to send, then transmit; otherwise, investigate further.\n\t */\n\tidle = (tp->snd_max == tp->snd_una);\n\tif (idle && tp->t_idle >= tp->t_rxtcur)\n\t\t/*\n\t\t * We have been idle for \"a while\" and no acks are\n\t\t * expected to clock out any data we send --\n\t\t * slow start to get ack \"clock\" running again.\n\t\t */\n\t\ttp->snd_cwnd = tp->t_maxseg;\nagain:\n\tsendalot = 0;\n\toff = tp->snd_nxt - tp->snd_una;\n\twin = min(tp->snd_wnd, tp->snd_cwnd);\n\n\tflags = tcp_outflags[tp->t_state];\n\n\tDEBUG_MISC((dfd, \" --- tcp_output flags = 0x%x\\n\",flags));\n\n\t/*\n\t * If in persist timeout with window of 0, send 1 byte.\n\t * Otherwise, if window is small but nonzero\n\t * and timer expired, we will send what we can\n\t * and go to transmit state.\n\t */\n\tif (tp->t_force) {\n\t\tif (win == 0) {\n\t\t\t/*\n\t\t\t * If we still have some data to send, then\n\t\t\t * clear the FIN bit.  Usually this would\n\t\t\t * happen below when it realizes that we\n\t\t\t * aren't sending all the data.  However,\n\t\t\t * if we have exactly 1 byte of unset data,\n\t\t\t * then it won't clear the FIN bit below,\n\t\t\t * and if we are in persist state, we wind\n\t\t\t * up sending the packet without recording\n\t\t\t * that we sent the FIN bit.\n\t\t\t *\n\t\t\t * We can't just blindly clear the FIN bit,\n\t\t\t * because if we don't have any more data\n\t\t\t * to send then the probe will be the FIN\n\t\t\t * itself.\n\t\t\t */\n\t\t\tif (off < so->so_snd.sb_cc)\n\t\t\t\tflags &= ~TH_FIN;\n\t\t\twin = 1;\n\t\t} else {\n\t\t\ttp->t_timer[TCPT_PERSIST] = 0;\n\t\t\ttp->t_rxtshift = 0;\n\t\t}\n\t}\n\n\tlen = min(so->so_snd.sb_cc, win) - off;\n\n\tif (len < 0) {\n\t\t/*\n\t\t * If FIN has been sent but not acked,\n\t\t * but we haven't been called to retransmit,\n\t\t * len will be -1.  Otherwise, window shrank\n\t\t * after we sent into it.  If window shrank to 0,\n\t\t * cancel pending retransmit and pull snd_nxt\n\t\t * back to (closed) window.  We will enter persist\n\t\t * state below.  If the window didn't close completely,\n\t\t * just wait for an ACK.\n\t\t */\n\t\tlen = 0;\n\t\tif (win == 0) {\n\t\t\ttp->t_timer[TCPT_REXMT] = 0;\n\t\t\ttp->snd_nxt = tp->snd_una;\n\t\t}\n\t}\n\n\tif (len > tp->t_maxseg) {\n\t\tlen = tp->t_maxseg;\n\t\tsendalot = 1;\n\t}\n\tif (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))\n\t\tflags &= ~TH_FIN;\n\n\twin = sbspace(&so->so_rcv);\n\n\t/*\n\t * Sender silly window avoidance.  If connection is idle\n\t * and can send all data, a maximum segment,\n\t * at least a maximum default-size segment do it,\n\t * or are forced, do it; otherwise don't bother.\n\t * If peer's buffer is tiny, then send\n\t * when window is at least half open.\n\t * If retransmitting (possibly after persist timer forced us\n\t * to send into a small window), then must resend.\n\t */\n\tif (len) {\n\t\tif (len == tp->t_maxseg)\n\t\t\tgoto send;\n\t\tif ((1 || idle || tp->t_flags & TF_NODELAY) &&\n\t\t    len + off >= so->so_snd.sb_cc)\n\t\t\tgoto send;\n\t\tif (tp->t_force)\n\t\t\tgoto send;\n\t\tif (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0)\n\t\t\tgoto send;\n\t\tif (SEQ_LT(tp->snd_nxt, tp->snd_max))\n\t\t\tgoto send;\n\t}\n\n\t/*\n\t * Compare available window to amount of window\n\t * known to peer (as advertised window less\n\t * next expected input).  If the difference is at least two\n\t * max size segments, or at least 50% of the maximum possible\n\t * window, then want to send a window update to peer.\n\t */\n\tif (win > 0) {\n\t\t/*\n\t\t * \"adv\" is the amount we can increase the window,\n\t\t * taking into account that we are limited by\n\t\t * TCP_MAXWIN << tp->rcv_scale.\n\t\t */\n\t\tlong adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -\n\t\t\t(tp->rcv_adv - tp->rcv_nxt);\n\n\t\tif (adv >= (long) (2 * tp->t_maxseg))\n\t\t\tgoto send;\n\t\tif (2 * adv >= (long) so->so_rcv.sb_datalen)\n\t\t\tgoto send;\n\t}\n\n\t/*\n\t * Send if we owe peer an ACK.\n\t */\n\tif (tp->t_flags & TF_ACKNOW)\n\t\tgoto send;\n\tif (flags & (TH_SYN|TH_RST))\n\t\tgoto send;\n\tif (SEQ_GT(tp->snd_up, tp->snd_una))\n\t\tgoto send;\n\t/*\n\t * If our state indicates that FIN should be sent\n\t * and we have not yet done so, or we're retransmitting the FIN,\n\t * then we need to send.\n\t */\n\tif (flags & TH_FIN &&\n\t    ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))\n\t\tgoto send;\n\n\t/*\n\t * TCP window updates are not reliable, rather a polling protocol\n\t * using ``persist'' packets is used to insure receipt of window\n\t * updates.  The three ``states'' for the output side are:\n\t *\tidle\t\t\tnot doing retransmits or persists\n\t *\tpersisting\t\tto move a small or zero window\n\t *\t(re)transmitting\tand thereby not persisting\n\t *\n\t * tp->t_timer[TCPT_PERSIST]\n\t *\tis set when we are in persist state.\n\t * tp->t_force\n\t *\tis set when we are called to send a persist packet.\n\t * tp->t_timer[TCPT_REXMT]\n\t *\tis set when we are retransmitting\n\t * The output side is idle when both timers are zero.\n\t *\n\t * If send window is too small, there is data to transmit, and no\n\t * retransmit or persist is pending, then go to persist state.\n\t * If nothing happens soon, send when timer expires:\n\t * if window is nonzero, transmit what we can,\n\t * otherwise force out a byte.\n\t */\n\tif (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 &&\n\t    tp->t_timer[TCPT_PERSIST] == 0) {\n\t\ttp->t_rxtshift = 0;\n\t\ttcp_setpersist(tp);\n\t}\n\n\t/*\n\t * No reason to send a segment, just return.\n\t */\n\treturn (0);\n\nsend:\n\t/*\n\t * Before ESTABLISHED, force sending of initial options\n\t * unless TCP set not to do any options.\n\t * NOTE: we assume that the IP/TCP header plus TCP options\n\t * always fit in a single mbuf, leaving room for a maximum\n\t * link header, i.e.\n\t *\tmax_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN\n\t */\n\toptlen = 0;\n\thdrlen = sizeof (struct tcpiphdr);\n\tif (flags & TH_SYN) {\n\t\ttp->snd_nxt = tp->iss;\n\t\tif ((tp->t_flags & TF_NOOPT) == 0) {\n\t\t\tuint16_t mss;\n\n\t\t\topt[0] = TCPOPT_MAXSEG;\n\t\t\topt[1] = 4;\n\t\t\tmss = htons((uint16_t) tcp_mss(tp, 0));\n\t\t\tmemcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss));\n\t\t\toptlen = 4;\n\t\t}\n \t}\n\n \thdrlen += optlen;\n\n\t/*\n\t * Adjust data length if insertion of options will\n\t * bump the packet length beyond the t_maxseg length.\n\t */\n\t if (len > tp->t_maxseg - optlen) {\n\t\tlen = tp->t_maxseg - optlen;\n\t\tsendalot = 1;\n\t }\n\n\t/*\n\t * Grab a header mbuf, attaching a copy of data to\n\t * be transmitted, and initialize the header from\n\t * the template for sends on this connection.\n\t */\n\tif (len) {\n\t\tm = m_get(so->slirp);\n\t\tif (m == NULL) {\n\t\t\terror = 1;\n\t\t\tgoto out;\n\t\t}\n\t\tm->m_data += IF_MAXLINKHDR;\n\t\tm->m_len = hdrlen;\n\n\t\tsbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);\n\t\tm->m_len += len;\n\n\t\t/*\n\t\t * If we're sending everything we've got, set PUSH.\n\t\t * (This will keep happy those implementations which only\n\t\t * give data to the user when a buffer fills or\n\t\t * a PUSH comes in.)\n\t\t */\n\t\tif (off + len == so->so_snd.sb_cc)\n\t\t\tflags |= TH_PUSH;\n\t} else {\n\t\tm = m_get(so->slirp);\n\t\tif (m == NULL) {\n\t\t\terror = 1;\n\t\t\tgoto out;\n\t\t}\n\t\tm->m_data += IF_MAXLINKHDR;\n\t\tm->m_len = hdrlen;\n\t}\n\n\tti = mtod(m, struct tcpiphdr *);\n\n\tmemcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));\n\n\t/*\n\t * Fill in fields, remembering maximum advertised\n\t * window for use in delaying messages about window sizes.\n\t * If resending a FIN, be sure not to use a new sequence number.\n\t */\n\tif (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&\n\t    tp->snd_nxt == tp->snd_max)\n\t\ttp->snd_nxt--;\n\t/*\n\t * If we are doing retransmissions, then snd_nxt will\n\t * not reflect the first unsent octet.  For ACK only\n\t * packets, we do not want the sequence number of the\n\t * retransmitted packet, we want the sequence number\n\t * of the next unsent octet.  So, if there is no data\n\t * (and no SYN or FIN), use snd_max instead of snd_nxt\n\t * when filling in ti_seq.  But if we are in persist\n\t * state, snd_max might reflect one byte beyond the\n\t * right edge of the window, so use snd_nxt in that\n\t * case, since we know we aren't doing a retransmission.\n\t * (retransmit and persist are mutually exclusive...)\n\t */\n\tif (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])\n\t\tti->ti_seq = htonl(tp->snd_nxt);\n\telse\n\t\tti->ti_seq = htonl(tp->snd_max);\n\tti->ti_ack = htonl(tp->rcv_nxt);\n\tif (optlen) {\n\t\tmemcpy((caddr_t)(ti + 1), (caddr_t)opt, optlen);\n\t\tti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;\n\t}\n\tti->ti_flags = flags;\n\t/*\n\t * Calculate receive window.  Don't shrink window,\n\t * but avoid silly window syndrome.\n\t */\n\tif (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg)\n\t\twin = 0;\n\tif (win > (long)TCP_MAXWIN << tp->rcv_scale)\n\t\twin = (long)TCP_MAXWIN << tp->rcv_scale;\n\tif (win < (long)(tp->rcv_adv - tp->rcv_nxt))\n\t\twin = (long)(tp->rcv_adv - tp->rcv_nxt);\n\tti->ti_win = htons((uint16_t) (win>>tp->rcv_scale));\n\n\tif (SEQ_GT(tp->snd_up, tp->snd_una)) {\n\t\tti->ti_urp = htons((uint16_t)(tp->snd_up - ntohl(ti->ti_seq)));\n\t\tti->ti_flags |= TH_URG;\n\t} else\n\t\t/*\n\t\t * If no urgent pointer to send, then we pull\n\t\t * the urgent pointer to the left edge of the send window\n\t\t * so that it doesn't drift into the send window on sequence\n\t\t * number wraparound.\n\t\t */\n\t\ttp->snd_up = tp->snd_una;\t\t/* drag it along */\n\n\t/*\n\t * Put TCP length in extended header, and then\n\t * checksum extended header and data.\n\t */\n\tif (len + optlen)\n\t\tti->ti_len = htons((uint16_t)(sizeof (struct tcphdr) +\n\t\t    optlen + len));\n\tti->ti_sum = cksum(m, (int)(hdrlen + len));\n\n\t/*\n\t * In transmit state, time the transmission and arrange for\n\t * the retransmit.  In persist state, just set snd_max.\n\t */\n\tif (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) {\n\t\ttcp_seq startseq = tp->snd_nxt;\n\n\t\t/*\n\t\t * Advance snd_nxt over sequence space of this segment.\n\t\t */\n\t\tif (flags & (TH_SYN|TH_FIN)) {\n\t\t\tif (flags & TH_SYN)\n\t\t\t\ttp->snd_nxt++;\n\t\t\tif (flags & TH_FIN) {\n\t\t\t\ttp->snd_nxt++;\n\t\t\t\ttp->t_flags |= TF_SENTFIN;\n\t\t\t}\n\t\t}\n\t\ttp->snd_nxt += len;\n\t\tif (SEQ_GT(tp->snd_nxt, tp->snd_max)) {\n\t\t\ttp->snd_max = tp->snd_nxt;\n\t\t\t/*\n\t\t\t * Time this transmission if not a retransmission and\n\t\t\t * not currently timing anything.\n\t\t\t */\n\t\t\tif (tp->t_rtt == 0) {\n\t\t\t\ttp->t_rtt = 1;\n\t\t\t\ttp->t_rtseq = startseq;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * Set retransmit timer if not currently set,\n\t\t * and not doing an ack or a keep-alive probe.\n\t\t * Initial value for retransmit timer is smoothed\n\t\t * round-trip time + 2 * round-trip time variance.\n\t\t * Initialize shift counter which is used for backoff\n\t\t * of retransmit time.\n\t\t */\n\t\tif (tp->t_timer[TCPT_REXMT] == 0 &&\n\t\t    tp->snd_nxt != tp->snd_una) {\n\t\t\ttp->t_timer[TCPT_REXMT] = tp->t_rxtcur;\n\t\t\tif (tp->t_timer[TCPT_PERSIST]) {\n\t\t\t\ttp->t_timer[TCPT_PERSIST] = 0;\n\t\t\t\ttp->t_rxtshift = 0;\n\t\t\t}\n\t\t}\n\t} else\n\t\tif (SEQ_GT(tp->snd_nxt + len, tp->snd_max))\n\t\t\ttp->snd_max = tp->snd_nxt + len;\n\n\t/*\n\t * Fill in IP length and desired time to live and\n\t * send to IP level.  There should be a better way\n\t * to handle ttl and tos; we could keep them in\n\t * the template, but need a way to checksum without them.\n\t */\n\tm->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */\n\n    {\n\n\t((struct ip *)ti)->ip_len = m->m_len;\n\n\t((struct ip *)ti)->ip_ttl = IPDEFTTL;\n\t((struct ip *)ti)->ip_tos = so->so_iptos;\n\n\terror = ip_output(so, m);\n    }\n\tif (error) {\nout:\n\t\treturn (error);\n\t}\n\n\t/*\n\t * Data sent (as far as we can tell).\n\t * If this advertises a larger window than any other segment,\n\t * then remember the size of the advertised window.\n\t * Any pending ACK has now been sent.\n\t */\n\tif (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))\n\t\ttp->rcv_adv = tp->rcv_nxt + win;\n\ttp->last_ack_sent = tp->rcv_nxt;\n\ttp->t_flags &= ~(TF_ACKNOW|TF_DELACK);\n\tif (sendalot)\n\t\tgoto again;\n\n\treturn (0);\n}\n\nvoid\ntcp_setpersist(struct tcpcb *tp)\n{\n    int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;\n\n\t/*\n\t * Start/restart persistence timer.\n\t */\n\tTCPT_RANGESET(tp->t_timer[TCPT_PERSIST],\n\t    t * tcp_backoff[tp->t_rxtshift],\n\t    TCPTV_PERSMIN, TCPTV_PERSMAX);\n\tif (tp->t_rxtshift < TCP_MAXRXTSHIFT)\n\t\ttp->t_rxtshift++;\n}\n"
  },
  {
    "path": "src/slirp/tcp_subr.c",
    "content": "/*\n * Copyright (c) 1982, 1986, 1988, 1990, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)tcp_subr.c\t8.1 (Berkeley) 6/10/93\n * tcp_subr.c,v 1.5 1994/10/08 22:39:58 phk Exp\n */\n\n/*\n * Changes and additions relating to SLiRP\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#include \"slirp.h\"\n\n/* patchable/settable parameters for tcp */\n/* Don't do rfc1323 performance enhancements */\n#define TCP_DO_RFC1323 0\n\n/*\n * Tcp initialization\n */\nvoid\ntcp_init(Slirp *slirp)\n{\n    slirp->tcp_iss = 1;\t\t/* wrong */\n    slirp->tcb.so_next = slirp->tcb.so_prev = &slirp->tcb;\n    slirp->tcp_last_so = &slirp->tcb;\n}\n\n/*\n * Create template to be used to send tcp packets on a connection.\n * Call after host entry created, fills\n * in a skeletal tcp/ip header, minimizing the amount of work\n * necessary when the connection is used.\n */\nvoid\ntcp_template(struct tcpcb *tp)\n{\n\tstruct socket *so = tp->t_socket;\n\tregister struct tcpiphdr *n = &tp->t_template;\n\n\tn->ti_mbuf = NULL;\n\tn->ti_x1 = 0;\n\tn->ti_pr = IPPROTO_TCP;\n\tn->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));\n\tn->ti_src = so->so_faddr;\n\tn->ti_dst = so->so_laddr;\n\tn->ti_sport = so->so_fport;\n\tn->ti_dport = so->so_lport;\n\n\tn->ti_seq = 0;\n\tn->ti_ack = 0;\n\tn->ti_x2 = 0;\n\tn->ti_off = 5;\n\tn->ti_flags = 0;\n\tn->ti_win = 0;\n\tn->ti_sum = 0;\n\tn->ti_urp = 0;\n}\n\n/*\n * Send a single message to the TCP at address specified by\n * the given TCP/IP header.  If m == 0, then we make a copy\n * of the tcpiphdr at ti and send directly to the addressed host.\n * This is used to force keep alive messages out using the TCP\n * template for a connection tp->t_template.  If flags are given\n * then we send a message back to the TCP which originated the\n * segment ti, and discard the mbuf containing it and any other\n * attached mbufs.\n *\n * In any case the ack and sequence number of the transmitted\n * segment are as specified by the parameters.\n */\nvoid\ntcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,\n            tcp_seq ack, tcp_seq seq, int flags)\n{\n\tregister int tlen;\n\tint win = 0;\n\n\tDEBUG_CALL(\"tcp_respond\");\n\tDEBUG_ARG(\"tp = %lx\", (long)tp);\n\tDEBUG_ARG(\"ti = %lx\", (long)ti);\n\tDEBUG_ARG(\"m = %lx\", (long)m);\n\tDEBUG_ARG(\"ack = %u\", ack);\n\tDEBUG_ARG(\"seq = %u\", seq);\n\tDEBUG_ARG(\"flags = %x\", flags);\n\n\tif (tp)\n\t\twin = sbspace(&tp->t_socket->so_rcv);\n        if (m == NULL) {\n\t\tif ((m = m_get(tp->t_socket->slirp)) == NULL)\n\t\t\treturn;\n\t\ttlen = 0;\n\t\tm->m_data += IF_MAXLINKHDR;\n\t\t*mtod(m, struct tcpiphdr *) = *ti;\n\t\tti = mtod(m, struct tcpiphdr *);\n\t\tflags = TH_ACK;\n\t} else {\n\t\t/*\n\t\t * ti points into m so the next line is just making\n\t\t * the mbuf point to ti\n\t\t */\n\t\tm->m_data = (caddr_t)ti;\n\n\t\tm->m_len = sizeof (struct tcpiphdr);\n\t\ttlen = 0;\n#define xchg(a,b,type) { type t; t=a; a=b; b=t; }\n\t\txchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, uint32_t);\n\t\txchg(ti->ti_dport, ti->ti_sport, uint16_t);\n#undef xchg\n\t}\n\tti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));\n\ttlen += sizeof (struct tcpiphdr);\n\tm->m_len = tlen;\n\n        ti->ti_mbuf = NULL;\n\tti->ti_x1 = 0;\n\tti->ti_seq = htonl(seq);\n\tti->ti_ack = htonl(ack);\n\tti->ti_x2 = 0;\n\tti->ti_off = sizeof (struct tcphdr) >> 2;\n\tti->ti_flags = flags;\n\tif (tp)\n\t\tti->ti_win = htons((uint16_t) (win >> tp->rcv_scale));\n\telse\n\t\tti->ti_win = htons((uint16_t)win);\n\tti->ti_urp = 0;\n\tti->ti_sum = 0;\n\tti->ti_sum = cksum(m, tlen);\n\t((struct ip *)ti)->ip_len = tlen;\n\n\tif(flags & TH_RST)\n\t  ((struct ip *)ti)->ip_ttl = MAXTTL;\n\telse\n\t  ((struct ip *)ti)->ip_ttl = IPDEFTTL;\n\n\t(void) ip_output((struct socket *)0, m);\n}\n\n/*\n * Create a new TCP control block, making an\n * empty reassembly queue and hooking it to the argument\n * protocol control block.\n */\nstruct tcpcb *\ntcp_newtcpcb(struct socket *so)\n{\n\tregister struct tcpcb *tp;\n\n\ttp = (struct tcpcb *)malloc(sizeof(*tp));\n\tif (tp == NULL)\n\t\treturn ((struct tcpcb *)0);\n\n\tmemset((char *) tp, 0, sizeof(struct tcpcb));\n\ttp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp;\n\ttp->t_maxseg = TCP_MSS;\n\n\ttp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;\n\ttp->t_socket = so;\n\n\t/*\n\t * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no\n\t * rtt estimate.  Set rttvar so that srtt + 2 * rttvar gives\n\t * reasonable initial retransmit time.\n\t */\n\ttp->t_srtt = TCPTV_SRTTBASE;\n\ttp->t_rttvar = TCPTV_SRTTDFLT << 2;\n\ttp->t_rttmin = TCPTV_MIN;\n\n\tTCPT_RANGESET(tp->t_rxtcur,\n\t    ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,\n\t    TCPTV_MIN, TCPTV_REXMTMAX);\n\n\ttp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;\n\ttp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;\n\ttp->t_state = TCPS_CLOSED;\n\n\tso->so_tcpcb = tp;\n\n\treturn (tp);\n}\n\n/*\n * Drop a TCP connection, reporting\n * the specified error.  If connection is synchronized,\n * then send a RST to peer.\n */\nstruct tcpcb *tcp_drop(struct tcpcb *tp, int err)\n{\n\tDEBUG_CALL(\"tcp_drop\");\n\tDEBUG_ARG(\"tp = %lx\", (long)tp);\n\tDEBUG_ARG(\"errno = %d\", errno);\n\n\tif (TCPS_HAVERCVDSYN(tp->t_state)) {\n\t\ttp->t_state = TCPS_CLOSED;\n\t\t(void) tcp_output(tp);\n\t}\n\treturn (tcp_close(tp));\n}\n\n/*\n * Close a TCP control block:\n *\tdiscard all space held by the tcp\n *\tdiscard internet protocol block\n *\twake up any sleepers\n */\nstruct tcpcb *\ntcp_close(struct tcpcb *tp)\n{\n\tregister struct tcpiphdr *t;\n\tstruct socket *so = tp->t_socket;\n\tSlirp *slirp = so->slirp;\n\tregister struct mbuf *m;\n\n\tDEBUG_CALL(\"tcp_close\");\n\tDEBUG_ARG(\"tp = %lx\", (long )tp);\n\n\t/* free the reassembly queue, if any */\n\tt = tcpfrag_list_first(tp);\n\twhile (!tcpfrag_list_end(t, tp)) {\n\t\tt = tcpiphdr_next(t);\n\t\tm = tcpiphdr_prev(t)->ti_mbuf;\n\t\tremque(tcpiphdr2qlink(tcpiphdr_prev(t)));\n\t\tm_freem(m);\n\t}\n\tfree(tp);\n        so->so_tcpcb = NULL;\n\t/* clobber input socket cache if we're closing the cached connection */\n\tif (so == slirp->tcp_last_so)\n\t\tslirp->tcp_last_so = &slirp->tcb;\n\tclosesocket(so->s);\n\tsbfree(&so->so_rcv);\n\tsbfree(&so->so_snd);\n\tsofree(so);\n\treturn ((struct tcpcb *)0);\n}\n\n/*\n * TCP protocol interface to socket abstraction.\n */\n\n/*\n * User issued close, and wish to trail through shutdown states:\n * if never received SYN, just forget it.  If got a SYN from peer,\n * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.\n * If already got a FIN from peer, then almost done; go to LAST_ACK\n * state.  In all other cases, have already sent FIN to peer (e.g.\n * after PRU_SHUTDOWN), and just have to play tedious game waiting\n * for peer to send FIN or not respond to keep-alives, etc.\n * We can let the user exit from the close as soon as the FIN is acked.\n */\nvoid\ntcp_sockclosed(struct tcpcb *tp)\n{\n\n\tDEBUG_CALL(\"tcp_sockclosed\");\n\tDEBUG_ARG(\"tp = %lx\", (long)tp);\n\n\tswitch (tp->t_state) {\n\n\tcase TCPS_CLOSED:\n\tcase TCPS_LISTEN:\n\tcase TCPS_SYN_SENT:\n\t\ttp->t_state = TCPS_CLOSED;\n\t\ttp = tcp_close(tp);\n\t\tbreak;\n\n\tcase TCPS_SYN_RECEIVED:\n\tcase TCPS_ESTABLISHED:\n\t\ttp->t_state = TCPS_FIN_WAIT_1;\n\t\tbreak;\n\n\tcase TCPS_CLOSE_WAIT:\n\t\ttp->t_state = TCPS_LAST_ACK;\n\t\tbreak;\n\t}\n\tif (tp)\n\t\ttcp_output(tp);\n}\n\n/*\n * Connect to a host on the Internet\n * Called by tcp_input\n * Only do a connect, the tcp fields will be set in tcp_input\n * return 0 if there's a result of the connect,\n * else return -1 means we're still connecting\n * The return value is almost always -1 since the socket is\n * nonblocking.  Connect returns after the SYN is sent, and does\n * not wait for ACK+SYN.\n */\nint tcp_fconnect(struct socket *so)\n{\n  Slirp *slirp = so->slirp;\n  int ret=0;\n\n  DEBUG_CALL(\"tcp_fconnect\");\n  DEBUG_ARG(\"so = %lx\", (long )so);\n\n  if( (ret = so->s = os_socket(AF_INET,SOCK_STREAM,0)) >= 0) {\n    int opt, s=so->s;\n    struct sockaddr_in addr;\n\n    fd_nonblock(s);\n    opt = 1;\n    setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt ));\n    opt = 1;\n    setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));\n\n    addr.sin_family = AF_INET;\n    if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==\n        slirp->vnetwork_addr.s_addr) {\n      /* It's an alias */\n      if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {\n\tif (get_dns_addr(&addr.sin_addr) < 0)\n\t  addr.sin_addr = loopback_addr;\n      } else {\n\taddr.sin_addr = loopback_addr;\n      }\n    } else\n      addr.sin_addr = so->so_faddr;\n    addr.sin_port = so->so_fport;\n\n    DEBUG_MISC((dfd, \" connect()ing, addr.sin_port=%d, \"\n\t\t\"addr.sin_addr.s_addr=%.16s\\n\",\n\t\tntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));\n    /* We don't care what port we get */\n    ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));\n\n    /*\n     * If it's not in progress, it failed, so we just return 0,\n     * without clearing SS_NOFDREF\n     */\n    soisfconnecting(so);\n  }\n\n  return(ret);\n}\n\n/*\n * Accept the socket and connect to the local-host\n *\n * We have a problem. The correct thing to do would be\n * to first connect to the local-host, and only if the\n * connection is accepted, then do an accept() here.\n * But, a) we need to know who's trying to connect\n * to the socket to be able to SYN the local-host, and\n * b) we are already connected to the foreign host by\n * the time it gets to accept(), so... We simply accept\n * here and SYN the local-host.\n */\nvoid\ntcp_connect(struct socket *inso)\n{\n\tSlirp *slirp = inso->slirp;\n\tstruct socket *so;\n\tstruct sockaddr_in addr;\n\tsocklen_t addrlen = sizeof(struct sockaddr_in);\n\tstruct tcpcb *tp;\n\tint s, opt;\n\n\tDEBUG_CALL(\"tcp_connect\");\n\tDEBUG_ARG(\"inso = %lx\", (long)inso);\n\n\t/*\n\t * If it's an SS_ACCEPTONCE socket, no need to socreate()\n\t * another socket, just use the accept() socket.\n\t */\n\tif (inso->so_state & SS_FACCEPTONCE) {\n\t\t/* FACCEPTONCE already have a tcpcb */\n\t\tso = inso;\n\t} else {\n\t\tif ((so = socreate(slirp)) == NULL) {\n\t\t\t/* If it failed, get rid of the pending connection */\n\t\t\tclosesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));\n\t\t\treturn;\n\t\t}\n\t\tif (tcp_attach(so) < 0) {\n\t\t\tfree(so); /* NOT sofree */\n\t\t\treturn;\n\t\t}\n\t\tso->so_laddr = inso->so_laddr;\n\t\tso->so_lport = inso->so_lport;\n\t}\n\n\t(void) tcp_mss(sototcpcb(so), 0);\n\n\tif ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) {\n\t\ttcp_close(sototcpcb(so)); /* This will sofree() as well */\n\t\treturn;\n\t}\n\tfd_nonblock(s);\n\topt = 1;\n\tsetsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));\n\topt = 1;\n\tsetsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));\n\topt = 1;\n\tsetsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int));\n\n\tso->so_fport = addr.sin_port;\n\tso->so_faddr = addr.sin_addr;\n\t/* Translate connections from localhost to the real hostname */\n\tif (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)\n\t   so->so_faddr = slirp->vhost_addr;\n\n\t/* Close the accept() socket, set right state */\n\tif (inso->so_state & SS_FACCEPTONCE) {\n\t\tclosesocket(so->s); /* If we only accept once, close the accept() socket */\n\t\tso->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */\n\t\t\t\t\t   /* if it's not FACCEPTONCE, it's already NOFDREF */\n\t}\n\tso->s = s;\n\tso->so_state |= SS_INCOMING;\n\n\tso->so_iptos = tcp_tos(so);\n\ttp = sototcpcb(so);\n\n\ttcp_template(tp);\n\n\ttp->t_state = TCPS_SYN_SENT;\n\ttp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;\n\ttp->iss = slirp->tcp_iss;\n\tslirp->tcp_iss += TCP_ISSINCR/2;\n\ttcp_sendseqinit(tp);\n\ttcp_output(tp);\n}\n\n/*\n * Attach a TCPCB to a socket.\n */\nint\ntcp_attach(struct socket *so)\n{\n\tif ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)\n\t   return -1;\n\n\tinsque(so, &so->slirp->tcb);\n\n\treturn 0;\n}\n\n/*\n * Set the socket's type of service field\n */\nstatic const struct tos_t tcptos[] = {\n\t  {0, 20, IPTOS_THROUGHPUT, 0},\t/* ftp data */\n\t  {21, 21, IPTOS_LOWDELAY,  EMU_FTP},\t/* ftp control */\n\t  {0, 23, IPTOS_LOWDELAY, 0},\t/* telnet */\n\t  {0, 80, IPTOS_THROUGHPUT, 0},\t/* WWW */\n\t  {0, 513, IPTOS_LOWDELAY, EMU_RLOGIN|EMU_NOCONNECT},\t/* rlogin */\n\t  {0, 514, IPTOS_LOWDELAY, EMU_RSH|EMU_NOCONNECT},\t/* shell */\n\t  {0, 544, IPTOS_LOWDELAY, EMU_KSH},\t\t/* kshell */\n\t  {0, 543, IPTOS_LOWDELAY, 0},\t/* klogin */\n\t  {0, 6667, IPTOS_THROUGHPUT, EMU_IRC},\t/* IRC */\n\t  {0, 6668, IPTOS_THROUGHPUT, EMU_IRC},\t/* IRC undernet */\n\t  {0, 7070, IPTOS_LOWDELAY, EMU_REALAUDIO }, /* RealAudio control */\n\t  {0, 113, IPTOS_LOWDELAY, EMU_IDENT }, /* identd protocol */\n\t  {0, 0, 0, 0}\n};\n\nstatic struct emu_t *tcpemu = NULL;\n\n/*\n * Return TOS according to the above table\n */\nuint8_t\ntcp_tos(struct socket *so)\n{\n\tint i = 0;\n\tstruct emu_t *emup;\n\n\twhile(tcptos[i].tos) {\n\t\tif ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) ||\n\t\t    (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) {\n\t\t\tso->so_emu = tcptos[i].emu;\n\t\t\treturn tcptos[i].tos;\n\t\t}\n\t\ti++;\n\t}\n\n\t/* Nope, lets see if there's a user-added one */\n\tfor (emup = tcpemu; emup; emup = emup->next) {\n\t\tif ((emup->fport && (ntohs(so->so_fport) == emup->fport)) ||\n\t\t    (emup->lport && (ntohs(so->so_lport) == emup->lport))) {\n\t\t\tso->so_emu = emup->emu;\n\t\t\treturn emup->tos;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\n/*\n * Emulate programs that try and connect to us\n * This includes ftp (the data connection is\n * initiated by the server) and IRC (DCC CHAT and\n * DCC SEND) for now\n *\n * NOTE: It's possible to crash SLiRP by sending it\n * unstandard strings to emulate... if this is a problem,\n * more checks are needed here\n *\n * XXX Assumes the whole command came in one packet\n *\n * XXX Some ftp clients will have their TOS set to\n * LOWDELAY and so Nagel will kick in.  Because of this,\n * we'll get the first letter, followed by the rest, so\n * we simply scan for ORT instead of PORT...\n * DCC doesn't have this problem because there's other stuff\n * in the packet before the DCC command.\n *\n * Return 1 if the mbuf m is still valid and should be\n * sbappend()ed\n *\n * NOTE: if you return 0 you MUST m_free() the mbuf!\n */\nint\ntcp_emu(struct socket *so, struct mbuf *m)\n{\n\tSlirp *slirp = so->slirp;\n\tu_int n1, n2, n3, n4, n5, n6;\n        char buff[257];\n\tuint32_t laddr;\n\tu_int lport;\n\tchar *bptr;\n\n\tDEBUG_CALL(\"tcp_emu\");\n\tDEBUG_ARG(\"so = %lx\", (long)so);\n\tDEBUG_ARG(\"m = %lx\", (long)m);\n\n\tswitch(so->so_emu) {\n\t\tint x, i;\n\n\t case EMU_IDENT:\n\t\t/*\n\t\t * Identification protocol as per rfc-1413\n\t\t */\n\n\t\t{\n\t\t\tstruct socket *tmpso;\n\t\t\tstruct sockaddr_in addr;\n\t\t\tsocklen_t addrlen = sizeof(struct sockaddr_in);\n\t\t\tstruct sbuf *so_rcv = &so->so_rcv;\n\n\t\t\tmemcpy(so_rcv->sb_wptr, m->m_data, m->m_len);\n\t\t\tso_rcv->sb_wptr += m->m_len;\n\t\t\tso_rcv->sb_rptr += m->m_len;\n\t\t\tm->m_data[m->m_len] = 0; /* NULL terminate */\n\t\t\tif (strchr(m->m_data, '\\r') || strchr(m->m_data, '\\n')) {\n\t\t\t\tif (sscanf(so_rcv->sb_data, \"%u%*[ ,]%u\", &n1, &n2) == 2) {\n\t\t\t\t\tHTONS(n1);\n\t\t\t\t\tHTONS(n2);\n\t\t\t\t\t/* n2 is the one on our host */\n\t\t\t\t\tfor (tmpso = slirp->tcb.so_next;\n\t\t\t\t\t     tmpso != &slirp->tcb;\n\t\t\t\t\t     tmpso = tmpso->so_next) {\n\t\t\t\t\t\tif (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&\n\t\t\t\t\t\t    tmpso->so_lport == n2 &&\n\t\t\t\t\t\t    tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&\n\t\t\t\t\t\t    tmpso->so_fport == n1) {\n\t\t\t\t\t\t\tif (getsockname(tmpso->s,\n\t\t\t\t\t\t\t\t(struct sockaddr *)&addr, &addrlen) == 0)\n\t\t\t\t\t\t\t   n2 = ntohs(addr.sin_port);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n                                so_rcv->sb_cc = snprintf(so_rcv->sb_data,\n                                                         so_rcv->sb_datalen,\n                                                         \"%d,%d\\r\\n\", n1, n2);\n\t\t\t\tso_rcv->sb_rptr = so_rcv->sb_data;\n\t\t\t\tso_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;\n\t\t\t}\n\t\t\tm_free(m);\n\t\t\treturn 0;\n\t\t}\n\n        case EMU_FTP: /* ftp */\n                *(m->m_data+m->m_len) = 0; /* NUL terminate for strstr */\n\t\tif ((bptr = (char *)strstr(m->m_data, \"ORT\")) != NULL) {\n\t\t\t/*\n\t\t\t * Need to emulate the PORT command\n\t\t\t */\n\t\t\tx = sscanf(bptr, \"ORT %u,%u,%u,%u,%u,%u\\r\\n%256[^\\177]\",\n\t\t\t\t   &n1, &n2, &n3, &n4, &n5, &n6, buff);\n\t\t\tif (x < 6)\n\t\t\t   return 1;\n\n\t\t\tladdr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));\n\t\t\tlport = htons((n5 << 8) | (n6));\n\n\t\t\tif ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr,\n\t\t\t                     lport, SS_FACCEPTONCE)) == NULL) {\n\t\t\t   return 1;\n\t\t\t}\n\t\t\tn6 = ntohs(so->so_fport);\n\n\t\t\tn5 = (n6 >> 8) & 0xff;\n\t\t\tn6 &= 0xff;\n\n\t\t\tladdr = ntohl(so->so_faddr.s_addr);\n\n\t\t\tn1 = ((laddr >> 24) & 0xff);\n\t\t\tn2 = ((laddr >> 16) & 0xff);\n\t\t\tn3 = ((laddr >> 8)  & 0xff);\n\t\t\tn4 =  (laddr & 0xff);\n\n\t\t\tm->m_len = bptr - m->m_data; /* Adjust length */\n                        m->m_len += snprintf(bptr, m->m_hdr.mh_size - m->m_len,\n                                             \"ORT %d,%d,%d,%d,%d,%d\\r\\n%s\",\n                                             n1, n2, n3, n4, n5, n6, x==7?buff:\"\");\n\t\t\treturn 1;\n\t\t} else if ((bptr = (char *)strstr(m->m_data, \"27 Entering\")) != NULL) {\n\t\t\t/*\n\t\t\t * Need to emulate the PASV response\n\t\t\t */\n\t\t\tx = sscanf(bptr, \"27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\\r\\n%256[^\\177]\",\n\t\t\t\t   &n1, &n2, &n3, &n4, &n5, &n6, buff);\n\t\t\tif (x < 6)\n\t\t\t   return 1;\n\n\t\t\tladdr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));\n\t\t\tlport = htons((n5 << 8) | (n6));\n\n\t\t\tif ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr,\n\t\t\t                     lport, SS_FACCEPTONCE)) == NULL) {\n\t\t\t   return 1;\n\t\t\t}\n\t\t\tn6 = ntohs(so->so_fport);\n\n\t\t\tn5 = (n6 >> 8) & 0xff;\n\t\t\tn6 &= 0xff;\n\n\t\t\tladdr = ntohl(so->so_faddr.s_addr);\n\n\t\t\tn1 = ((laddr >> 24) & 0xff);\n\t\t\tn2 = ((laddr >> 16) & 0xff);\n\t\t\tn3 = ((laddr >> 8)  & 0xff);\n\t\t\tn4 =  (laddr & 0xff);\n\n\t\t\tm->m_len = bptr - m->m_data; /* Adjust length */\n\t\t\tm->m_len += snprintf(bptr, m->m_hdr.mh_size - m->m_len,\n                                             \"27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\\r\\n%s\",\n                                             n1, n2, n3, n4, n5, n6, x==7?buff:\"\");\n\n\t\t\treturn 1;\n\t\t}\n\n\t\treturn 1;\n\n\t case EMU_KSH:\n\t\t/*\n\t\t * The kshell (Kerberos rsh) and shell services both pass\n\t\t * a local port port number to carry signals to the server\n\t\t * and stderr to the client.  It is passed at the beginning\n\t\t * of the connection as a NUL-terminated decimal ASCII string.\n\t\t */\n\t\tso->so_emu = 0;\n\t\tfor (lport = 0, i = 0; i < m->m_len-1; ++i) {\n\t\t\tif (m->m_data[i] < '0' || m->m_data[i] > '9')\n\t\t\t\treturn 1;       /* invalid number */\n\t\t\tlport *= 10;\n\t\t\tlport += m->m_data[i] - '0';\n\t\t}\n\t\tif (m->m_data[m->m_len-1] == '\\0' && lport != 0 &&\n\t\t    (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr,\n\t\t                     htons(lport), SS_FACCEPTONCE)) != NULL)\n                    m->m_len = snprintf(m->m_data, m->m_hdr.mh_size, \"%d\",\n                                        ntohs(so->so_fport)) + 1;\n\t\treturn 1;\n\n\t case EMU_IRC:\n\t\t/*\n\t\t * Need to emulate DCC CHAT, DCC SEND and DCC MOVE\n\t\t */\n\t\t*(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */\n\t\tif ((bptr = (char *)strstr(m->m_data, \"DCC\")) == NULL)\n\t\t\t return 1;\n\n\t\t/* The %256s is for the broken mIRC */\n\t\tif (sscanf(bptr, \"DCC CHAT %256s %u %u\", buff, &laddr, &lport) == 3) {\n\t\t\tif ((so = tcp_listen(slirp, INADDR_ANY, 0,\n\t\t\t                     htonl(laddr), htons(lport),\n\t\t\t                     SS_FACCEPTONCE)) == NULL) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tm->m_len = bptr - m->m_data; /* Adjust length */\n                        m->m_len += snprintf(bptr, m->m_hdr.mh_size,\n                                             \"DCC CHAT chat %lu %u%c\\n\",\n                                             (unsigned long)ntohl(so->so_faddr.s_addr),\n                                             ntohs(so->so_fport), 1);\n\t\t} else if (sscanf(bptr, \"DCC SEND %256s %u %u %u\", buff, &laddr, &lport, &n1) == 4) {\n\t\t\tif ((so = tcp_listen(slirp, INADDR_ANY, 0,\n\t\t\t                     htonl(laddr), htons(lport),\n\t\t\t                     SS_FACCEPTONCE)) == NULL) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tm->m_len = bptr - m->m_data; /* Adjust length */\n                        m->m_len += snprintf(bptr, m->m_hdr.mh_size,\n                                             \"DCC SEND %s %lu %u %u%c\\n\", buff,\n                                             (unsigned long)ntohl(so->so_faddr.s_addr),\n                                             ntohs(so->so_fport), n1, 1);\n\t\t} else if (sscanf(bptr, \"DCC MOVE %256s %u %u %u\", buff, &laddr, &lport, &n1) == 4) {\n\t\t\tif ((so = tcp_listen(slirp, INADDR_ANY, 0,\n\t\t\t                     htonl(laddr), htons(lport),\n\t\t\t                     SS_FACCEPTONCE)) == NULL) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tm->m_len = bptr - m->m_data; /* Adjust length */\n                        m->m_len += snprintf(bptr, m->m_hdr.mh_size,\n                                             \"DCC MOVE %s %lu %u %u%c\\n\", buff,\n                                             (unsigned long)ntohl(so->so_faddr.s_addr),\n                                             ntohs(so->so_fport), n1, 1);\n\t\t}\n\t\treturn 1;\n\n\t case EMU_REALAUDIO:\n                /*\n\t\t * RealAudio emulation - JP. We must try to parse the incoming\n\t\t * data and try to find the two characters that contain the\n\t\t * port number. Then we redirect an udp port and replace the\n\t\t * number with the real port we got.\n\t\t *\n\t\t * The 1.0 beta versions of the player are not supported\n\t\t * any more.\n\t\t *\n\t\t * A typical packet for player version 1.0 (release version):\n\t\t *\n\t\t * 0000:50 4E 41 00 05\n\t\t * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 ........g.l.c..P\n\t\t * 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH\n\t\t * 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v\n\t\t * 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB\n\t\t *\n\t\t * Now the port number 0x1BD7 is found at offset 0x04 of the\n\t\t * Now the port number 0x1BD7 is found at offset 0x04 of the\n\t\t * second packet. This time we received five bytes first and\n\t\t * then the rest. You never know how many bytes you get.\n\t\t *\n\t\t * A typical packet for player version 2.0 (beta):\n\t\t *\n\t\t * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA.............\n\t\t * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .gux.c..Win2.0.0\n\t\t * 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/\n\t\t * 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas\n\t\t * 0040:65 2E 72 61 79 53 00 00 06 36 42                e.rayS...6B\n\t\t *\n\t\t * Port number 0x1BC1 is found at offset 0x0d.\n\t\t *\n\t\t * This is just a horrible switch statement. Variable ra tells\n\t\t * us where we're going.\n\t\t */\n\n\t\tbptr = m->m_data;\n\t\twhile (bptr < m->m_data + m->m_len) {\n\t\t\tu_short p;\n\t\t\tstatic int ra = 0;\n\t\t\tchar ra_tbl[4];\n\n\t\t\tra_tbl[0] = 0x50;\n\t\t\tra_tbl[1] = 0x4e;\n\t\t\tra_tbl[2] = 0x41;\n\t\t\tra_tbl[3] = 0;\n\n\t\t\tswitch (ra) {\n\t\t\t case 0:\n\t\t\t case 2:\n\t\t\t case 3:\n\t\t\t\tif (*bptr++ != ra_tbl[ra]) {\n\t\t\t\t\tra = 0;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t case 1:\n\t\t\t\t/*\n\t\t\t\t * We may get 0x50 several times, ignore them\n\t\t\t\t */\n\t\t\t\tif (*bptr == 0x50) {\n\t\t\t\t\tra = 1;\n\t\t\t\t\tbptr++;\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (*bptr++ != ra_tbl[ra]) {\n\t\t\t\t\tra = 0;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t case 4:\n\t\t\t\t/*\n\t\t\t\t * skip version number\n\t\t\t\t */\n\t\t\t\tbptr++;\n\t\t\t\tbreak;\n\n\t\t\t case 5:\n\t\t\t\t/*\n\t\t\t\t * The difference between versions 1.0 and\n\t\t\t\t * 2.0 is here. For future versions of\n\t\t\t\t * the player this may need to be modified.\n\t\t\t\t */\n\t\t\t\tif (*(bptr + 1) == 0x02)\n\t\t\t\t   bptr += 8;\n\t\t\t\telse\n\t\t\t\t   bptr += 4;\n\t\t\t\tbreak;\n\n\t\t\t case 6:\n\t\t\t\t/* This is the field containing the port\n\t\t\t\t * number that RA-player is listening to.\n\t\t\t\t */\n\t\t\t\tlport = (((u_char*)bptr)[0] << 8)\n\t\t\t\t+ ((u_char *)bptr)[1];\n\t\t\t\tif (lport < 6970)\n\t\t\t\t   lport += 256;   /* don't know why */\n\t\t\t\tif (lport < 6970 || lport > 7170)\n\t\t\t\t   return 1;       /* failed */\n\n\t\t\t\t/* try to get udp port between 6970 - 7170 */\n\t\t\t\tfor (p = 6970; p < 7071; p++) {\n\t\t\t\t\tif (udp_listen(slirp, INADDR_ANY,\n\t\t\t\t\t\t       htons(p),\n\t\t\t\t\t\t       so->so_laddr.s_addr,\n\t\t\t\t\t\t       htons(lport),\n\t\t\t\t\t\t       SS_FACCEPTONCE)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (p == 7071)\n\t\t\t\t   p = 0;\n\t\t\t\t*(u_char *)bptr++ = (p >> 8) & 0xff;\n                                *(u_char *)bptr = p & 0xff;\n\t\t\t\tra = 0;\n\t\t\t\treturn 1;   /* port redirected, we're done */\n\t\t\t\tbreak;\n\n\t\t\t default:\n\t\t\t\tra = 0;\n\t\t\t}\n\t\t\tra++;\n\t\t}\n\t\treturn 1;\n\n\t default:\n\t\t/* Ooops, not emulated, won't call tcp_emu again */\n\t\tso->so_emu = 0;\n\t\treturn 1;\n\t}\n}\n\n/*\n * Do misc. config of SLiRP while its running.\n * Return 0 if this connections is to be closed, 1 otherwise,\n * return 2 if this is a command-line connection\n */\nint tcp_ctl(struct socket *so)\n{\n    Slirp *slirp = so->slirp;\n    struct sbuf *sb = &so->so_snd;\n    struct ex_list *ex_ptr;\n    int do_pty;\n\n    DEBUG_CALL(\"tcp_ctl\");\n    DEBUG_ARG(\"so = %lx\", (long )so);\n\n    if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {\n        /* Check if it's pty_exec */\n        for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {\n            if (ex_ptr->ex_fport == so->so_fport &&\n                so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {\n                if (ex_ptr->ex_pty == 3) {\n                    so->s = -1;\n                    so->extra = (void *)ex_ptr->ex_exec;\n                    return 1;\n                }\n                do_pty = ex_ptr->ex_pty;\n                DEBUG_MISC((dfd, \" executing %s \\n\",ex_ptr->ex_exec));\n                return fork_exec(so, ex_ptr->ex_exec, do_pty);\n            }\n        }\n    }\n    sb->sb_cc =\n        snprintf(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data),\n                 \"Error: No application configured.\\r\\n\");\n    sb->sb_wptr += sb->sb_cc;\n    return 0;\n}\n"
  },
  {
    "path": "src/slirp/tcp_timer.c",
    "content": "/*\n * Copyright (c) 1982, 1986, 1988, 1990, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)tcp_timer.c\t8.1 (Berkeley) 6/10/93\n * tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp\n */\n\n#include \"slirp.h\"\n\nstatic struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer);\n\n/*\n * Fast timeout routine for processing delayed acks\n */\nvoid\ntcp_fasttimo(Slirp *slirp)\n{\n\tregister struct socket *so;\n\tregister struct tcpcb *tp;\n\n\tDEBUG_CALL(\"tcp_fasttimo\");\n\n\tso = slirp->tcb.so_next;\n\tif (so)\n\tfor (; so != &slirp->tcb; so = so->so_next)\n\t\tif ((tp = (struct tcpcb *)so->so_tcpcb) &&\n\t\t    (tp->t_flags & TF_DELACK)) {\n\t\t\ttp->t_flags &= ~TF_DELACK;\n\t\t\ttp->t_flags |= TF_ACKNOW;\n\t\t\t(void) tcp_output(tp);\n\t\t}\n}\n\n/*\n * Tcp protocol timeout routine called every 500 ms.\n * Updates the timers in all active tcb's and\n * causes finite state machine actions if timers expire.\n */\nvoid\ntcp_slowtimo(Slirp *slirp)\n{\n\tregister struct socket *ip, *ipnxt;\n\tregister struct tcpcb *tp;\n\tregister int i;\n\n\tDEBUG_CALL(\"tcp_slowtimo\");\n\n\t/*\n\t * Search through tcb's and update active timers.\n\t */\n\tip = slirp->tcb.so_next;\n        if (ip == NULL) {\n            return;\n        }\n\tfor (; ip != &slirp->tcb; ip = ipnxt) {\n\t\tipnxt = ip->so_next;\n\t\ttp = sototcpcb(ip);\n                if (tp == NULL) {\n                        continue;\n                }\n\t\tfor (i = 0; i < TCPT_NTIMERS; i++) {\n\t\t\tif (tp->t_timer[i] && --tp->t_timer[i] == 0) {\n\t\t\t\ttcp_timers(tp,i);\n\t\t\t\tif (ipnxt->so_prev != ip)\n\t\t\t\t\tgoto tpgone;\n\t\t\t}\n\t\t}\n\t\ttp->t_idle++;\n\t\tif (tp->t_rtt)\n\t\t   tp->t_rtt++;\ntpgone:\n\t\t;\n\t}\n\tslirp->tcp_iss += TCP_ISSINCR/PR_SLOWHZ;\t/* increment iss */\n\tslirp->tcp_now++;\t\t\t\t/* for timestamps */\n}\n\n/*\n * Cancel all timers for TCP tp.\n */\nvoid\ntcp_canceltimers(struct tcpcb *tp)\n{\n\tregister int i;\n\n\tfor (i = 0; i < TCPT_NTIMERS; i++)\n\t\ttp->t_timer[i] = 0;\n}\n\nconst int tcp_backoff[TCP_MAXRXTSHIFT + 1] =\n   { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };\n\n/*\n * TCP timer processing.\n */\nstatic struct tcpcb *\ntcp_timers(register struct tcpcb *tp, int timer)\n{\n\tregister int rexmt;\n\n\tDEBUG_CALL(\"tcp_timers\");\n\n\tswitch (timer) {\n\n\t/*\n\t * 2 MSL timeout in shutdown went off.  If we're closed but\n\t * still waiting for peer to close and connection has been idle\n\t * too long, or if 2MSL time is up from TIME_WAIT, delete connection\n\t * control block.  Otherwise, check again in a bit.\n\t */\n\tcase TCPT_2MSL:\n\t\tif (tp->t_state != TCPS_TIME_WAIT &&\n\t\t    tp->t_idle <= TCP_MAXIDLE)\n\t\t\ttp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL;\n\t\telse\n\t\t\ttp = tcp_close(tp);\n\t\tbreak;\n\n\t/*\n\t * Retransmission timer went off.  Message has not\n\t * been acked within retransmit interval.  Back off\n\t * to a longer retransmit interval and retransmit one segment.\n\t */\n\tcase TCPT_REXMT:\n\n\t\t/*\n\t\t * XXXXX If a packet has timed out, then remove all the queued\n\t\t * packets for that session.\n\t\t */\n\n\t\tif (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {\n\t\t\t/*\n\t\t\t * This is a hack to suit our terminal server here at the uni of canberra\n\t\t\t * since they have trouble with zeroes... It usually lets them through\n\t\t\t * unharmed, but under some conditions, it'll eat the zeros.  If we\n\t\t\t * keep retransmitting it, it'll keep eating the zeroes, so we keep\n\t\t\t * retransmitting, and eventually the connection dies...\n\t\t\t * (this only happens on incoming data)\n\t\t\t *\n\t\t\t * So, if we were gonna drop the connection from too many retransmits,\n\t\t\t * don't... instead halve the t_maxseg, which might break up the NULLs and\n\t\t\t * let them through\n\t\t\t *\n\t\t\t * *sigh*\n\t\t\t */\n\n\t\t\ttp->t_maxseg >>= 1;\n\t\t\tif (tp->t_maxseg < 32) {\n\t\t\t\t/*\n\t\t\t\t * We tried our best, now the connection must die!\n\t\t\t\t */\n\t\t\t\ttp->t_rxtshift = TCP_MAXRXTSHIFT;\n\t\t\t\ttp = tcp_drop(tp, tp->t_softerror);\n\t\t\t\t/* tp->t_softerror : ETIMEDOUT); */ /* XXX */\n\t\t\t\treturn (tp); /* XXX */\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Set rxtshift to 6, which is still at the maximum\n\t\t\t * backoff time\n\t\t\t */\n\t\t\ttp->t_rxtshift = 6;\n\t\t}\n\t\trexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];\n\t\tTCPT_RANGESET(tp->t_rxtcur, rexmt,\n\t\t    (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */\n\t\ttp->t_timer[TCPT_REXMT] = tp->t_rxtcur;\n\t\t/*\n\t\t * If losing, let the lower level know and try for\n\t\t * a better route.  Also, if we backed off this far,\n\t\t * our srtt estimate is probably bogus.  Clobber it\n\t\t * so we'll take the next rtt measurement as our srtt;\n\t\t * move the current srtt into rttvar to keep the current\n\t\t * retransmit times until then.\n\t\t */\n\t\tif (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {\n\t\t\ttp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);\n\t\t\ttp->t_srtt = 0;\n\t\t}\n\t\ttp->snd_nxt = tp->snd_una;\n\t\t/*\n\t\t * If timing a segment in this window, stop the timer.\n\t\t */\n\t\ttp->t_rtt = 0;\n\t\t/*\n\t\t * Close the congestion window down to one segment\n\t\t * (we'll open it by one segment for each ack we get).\n\t\t * Since we probably have a window's worth of unacked\n\t\t * data accumulated, this \"slow start\" keeps us from\n\t\t * dumping all that data as back-to-back packets (which\n\t\t * might overwhelm an intermediate gateway).\n\t\t *\n\t\t * There are two phases to the opening: Initially we\n\t\t * open by one mss on each ack.  This makes the window\n\t\t * size increase exponentially with time.  If the\n\t\t * window is larger than the path can handle, this\n\t\t * exponential growth results in dropped packet(s)\n\t\t * almost immediately.  To get more time between\n\t\t * drops but still \"push\" the network to take advantage\n\t\t * of improving conditions, we switch from exponential\n\t\t * to linear window opening at some threshold size.\n\t\t * For a threshold, we use half the current window\n\t\t * size, truncated to a multiple of the mss.\n\t\t *\n\t\t * (the minimum cwnd that will give us exponential\n\t\t * growth is 2 mss.  We don't allow the threshold\n\t\t * to go below this.)\n\t\t */\n\t\t{\n\t\tu_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;\n\t\tif (win < 2)\n\t\t\twin = 2;\n\t\ttp->snd_cwnd = tp->t_maxseg;\n\t\ttp->snd_ssthresh = win * tp->t_maxseg;\n\t\ttp->t_dupacks = 0;\n\t\t}\n\t\t(void) tcp_output(tp);\n\t\tbreak;\n\n\t/*\n\t * Persistence timer into zero window.\n\t * Force a byte to be output, if possible.\n\t */\n\tcase TCPT_PERSIST:\n\t\ttcp_setpersist(tp);\n\t\ttp->t_force = 1;\n\t\t(void) tcp_output(tp);\n\t\ttp->t_force = 0;\n\t\tbreak;\n\n\t/*\n\t * Keep-alive timer went off; send something\n\t * or drop connection if idle for too long.\n\t */\n\tcase TCPT_KEEP:\n\t\tif (tp->t_state < TCPS_ESTABLISHED)\n\t\t\tgoto dropit;\n\n\t\tif ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) {\n\t\t    \tif (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)\n\t\t\t\tgoto dropit;\n\t\t\t/*\n\t\t\t * Send a packet designed to force a response\n\t\t\t * if the peer is up and reachable:\n\t\t\t * either an ACK if the connection is still alive,\n\t\t\t * or an RST if the peer has closed the connection\n\t\t\t * due to timeout or reboot.\n\t\t\t * Using sequence number tp->snd_una-1\n\t\t\t * causes the transmitted zero-length segment\n\t\t\t * to lie outside the receive window;\n\t\t\t * by the protocol spec, this requires the\n\t\t\t * correspondent TCP to respond.\n\t\t\t */\n\t\t\ttcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,\n\t\t\t    tp->rcv_nxt, tp->snd_una - 1, 0);\n\t\t\ttp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;\n\t\t} else\n\t\t\ttp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;\n\t\tbreak;\n\n\tdropit:\n\t\ttp = tcp_drop(tp, 0);\n\t\tbreak;\n\t}\n\n\treturn (tp);\n}\n"
  },
  {
    "path": "src/slirp/tcp_timer.h",
    "content": "/*\n * Copyright (c) 1982, 1986, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)tcp_timer.h\t8.1 (Berkeley) 6/10/93\n * tcp_timer.h,v 1.4 1994/08/21 05:27:38 paul Exp\n */\n\n#ifndef _TCP_TIMER_H_\n#define _TCP_TIMER_H_\n\n/*\n * Definitions of the TCP timers.  These timers are counted\n * down PR_SLOWHZ times a second.\n */\n#define\tTCPT_NTIMERS\t4\n\n#define\tTCPT_REXMT\t0\t\t/* retransmit */\n#define\tTCPT_PERSIST\t1\t\t/* retransmit persistence */\n#define\tTCPT_KEEP\t2\t\t/* keep alive */\n#define\tTCPT_2MSL\t3\t\t/* 2*msl quiet time timer */\n\n/*\n * The TCPT_REXMT timer is used to force retransmissions.\n * The TCP has the TCPT_REXMT timer set whenever segments\n * have been sent for which ACKs are expected but not yet\n * received.  If an ACK is received which advances tp->snd_una,\n * then the retransmit timer is cleared (if there are no more\n * outstanding segments) or reset to the base value (if there\n * are more ACKs expected).  Whenever the retransmit timer goes off,\n * we retransmit one unacknowledged segment, and do a backoff\n * on the retransmit timer.\n *\n * The TCPT_PERSIST timer is used to keep window size information\n * flowing even if the window goes shut.  If all previous transmissions\n * have been acknowledged (so that there are no retransmissions in progress),\n * and the window is too small to bother sending anything, then we start\n * the TCPT_PERSIST timer.  When it expires, if the window is nonzero,\n * we go to transmit state.  Otherwise, at intervals send a single byte\n * into the peer's window to force him to update our window information.\n * We do this at most as often as TCPT_PERSMIN time intervals,\n * but no more frequently than the current estimate of round-trip\n * packet time.  The TCPT_PERSIST timer is cleared whenever we receive\n * a window update from the peer.\n *\n * The TCPT_KEEP timer is used to keep connections alive.  If an\n * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time,\n * but not yet established, then we drop the connection.  Once the connection\n * is established, if the connection is idle for TCPTV_KEEP_IDLE time\n * (and keepalives have been enabled on the socket), we begin to probe\n * the connection.  We force the peer to send us a segment by sending:\n *\t<SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK>\n * This segment is (deliberately) outside the window, and should elicit\n * an ack segment in response from the peer.  If, despite the TCPT_KEEP\n * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE\n * amount of time probing, then we drop the connection.\n */\n\n/*\n * Time constants.\n */\n#define TCPTV_MSL       ( 5*PR_SLOWHZ)          /* max seg lifetime (hah!) */\n\n#define\tTCPTV_SRTTBASE\t0\t\t\t/* base roundtrip time;\n\t\t\t\t\t\t   if 0, no idea yet */\n#define\tTCPTV_SRTTDFLT\t(  3*PR_SLOWHZ)\t\t/* assumed RTT if no info */\n\n#define\tTCPTV_PERSMIN\t(  5*PR_SLOWHZ)\t\t/* retransmit persistence */\n#define\tTCPTV_PERSMAX\t( 60*PR_SLOWHZ)\t\t/* maximum persist interval */\n\n#define\tTCPTV_KEEP_INIT\t( 75*PR_SLOWHZ)\t\t/* initial connect keep alive */\n#define\tTCPTV_KEEP_IDLE\t(120*60*PR_SLOWHZ)\t/* dflt time before probing */\n#define\tTCPTV_KEEPINTVL\t( 75*PR_SLOWHZ)\t\t/* default probe interval */\n#define\tTCPTV_KEEPCNT\t8\t\t\t/* max probes before drop */\n\n#define\tTCPTV_MIN\t(  1*PR_SLOWHZ)\t\t/* minimum allowable value */\n#define TCPTV_REXMTMAX  ( 12*PR_SLOWHZ)\t\t/* max allowable REXMT value */\n\n#define\tTCP_LINGERTIME\t120\t\t\t/* linger at most 2 minutes */\n\n#define TCP_MAXRXTSHIFT 12                      /* maximum retransmits */\n\n\n/*\n * Force a time value to be in a certain range.\n */\n#define\tTCPT_RANGESET(tv, value, tvmin, tvmax) { \\\n\t(tv) = (value); \\\n\tif ((tv) < (tvmin)) \\\n\t\t(tv) = (tvmin); \\\n\telse if ((tv) > (tvmax)) \\\n\t\t(tv) = (tvmax); \\\n}\n\nextern const int tcp_backoff[];\n\nstruct tcpcb;\n\nvoid tcp_fasttimo(Slirp *);\nvoid tcp_slowtimo(Slirp *);\nvoid tcp_canceltimers(struct tcpcb *);\n\n#endif\n"
  },
  {
    "path": "src/slirp/tcp_var.h",
    "content": "/*\n * Copyright (c) 1982, 1986, 1993, 1994\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)tcp_var.h\t8.3 (Berkeley) 4/10/94\n * tcp_var.h,v 1.3 1994/08/21 05:27:39 paul Exp\n */\n\n#ifndef _TCP_VAR_H_\n#define _TCP_VAR_H_\n\n#include \"tcpip.h\"\n#include \"tcp_timer.h\"\n\n/*\n * Tcp control block, one per tcp; fields:\n */\nstruct tcpcb {\n\tstruct tcpiphdr *seg_next;\t/* sequencing queue */\n\tstruct tcpiphdr *seg_prev;\n\tshort\tt_state;\t\t/* state of this connection */\n\tshort\tt_timer[TCPT_NTIMERS];\t/* tcp timers */\n\tshort\tt_rxtshift;\t\t/* log(2) of rexmt exp. backoff */\n\tshort\tt_rxtcur;\t\t/* current retransmit value */\n\tshort\tt_dupacks;\t\t/* consecutive dup acks recd */\n\tu_short\tt_maxseg;\t\t/* maximum segment size */\n\tchar\tt_force;\t\t/* 1 if forcing out a byte */\n\tu_short\tt_flags;\n#define\tTF_ACKNOW\t0x0001\t\t/* ack peer immediately */\n#define\tTF_DELACK\t0x0002\t\t/* ack, but try to delay it */\n#define\tTF_NODELAY\t0x0004\t\t/* don't delay packets to coalesce */\n#define\tTF_NOOPT\t0x0008\t\t/* don't use tcp options */\n#define\tTF_SENTFIN\t0x0010\t\t/* have sent FIN */\n#define\tTF_REQ_SCALE\t0x0020\t\t/* have/will request window scaling */\n#define\tTF_RCVD_SCALE\t0x0040\t\t/* other side has requested scaling */\n#define\tTF_REQ_TSTMP\t0x0080\t\t/* have/will request timestamps */\n#define\tTF_RCVD_TSTMP\t0x0100\t\t/* a timestamp was received in SYN */\n#define\tTF_SACK_PERMIT\t0x0200\t\t/* other side said I could SACK */\n\n\tstruct\ttcpiphdr t_template;    /* static skeletal packet for xmit */\n\n\tstruct\tsocket *t_socket;\t\t/* back pointer to socket */\n/*\n * The following fields are used as in the protocol specification.\n * See RFC783, Dec. 1981, page 21.\n */\n/* send sequence variables */\n\ttcp_seq\tsnd_una;\t\t/* send unacknowledged */\n\ttcp_seq\tsnd_nxt;\t\t/* send next */\n\ttcp_seq\tsnd_up;\t\t\t/* send urgent pointer */\n\ttcp_seq\tsnd_wl1;\t\t/* window update seg seq number */\n\ttcp_seq\tsnd_wl2;\t\t/* window update seg ack number */\n\ttcp_seq\tiss;\t\t\t/* initial send sequence number */\n\tuint32_t snd_wnd;\t\t/* send window */\n/* receive sequence variables */\n\tuint32_t rcv_wnd;\t\t/* receive window */\n\ttcp_seq\trcv_nxt;\t\t/* receive next */\n\ttcp_seq\trcv_up;\t\t\t/* receive urgent pointer */\n\ttcp_seq\tirs;\t\t\t/* initial receive sequence number */\n/*\n * Additional variables for this implementation.\n */\n/* receive variables */\n\ttcp_seq\trcv_adv;\t\t/* advertised window */\n/* retransmit variables */\n\ttcp_seq\tsnd_max;\t\t/* highest sequence number sent;\n\t\t\t\t\t * used to recognize retransmits\n\t\t\t\t\t */\n/* congestion control (for slow start, source quench, retransmit after loss) */\n\tuint32_t snd_cwnd;\t\t/* congestion-controlled window */\n\tuint32_t snd_ssthresh;\t\t/* snd_cwnd size threshold for\n\t\t\t\t\t * for slow start exponential to\n\t\t\t\t\t * linear switch\n\t\t\t\t\t */\n/*\n * transmit timing stuff.  See below for scale of srtt and rttvar.\n * \"Variance\" is actually smoothed difference.\n */\n\tshort\tt_idle;\t\t\t/* inactivity time */\n\tshort\tt_rtt;\t\t\t/* round trip time */\n\ttcp_seq\tt_rtseq;\t\t/* sequence number being timed */\n\tshort\tt_srtt;\t\t\t/* smoothed round-trip time */\n\tshort\tt_rttvar;\t\t/* variance in round-trip time */\n\tu_short\tt_rttmin;\t\t/* minimum rtt allowed */\n\tuint32_t max_sndwnd;\t\t/* largest window peer has offered */\n\n/* out-of-band data */\n\tchar\tt_oobflags;\t\t/* have some */\n\tchar\tt_iobc;\t\t\t/* input character */\n#define\tTCPOOB_HAVEDATA\t0x01\n#define\tTCPOOB_HADDATA\t0x02\n\tshort\tt_softerror;\t\t/* possible error not yet reported */\n\n/* RFC 1323 variables */\n\tu_char\tsnd_scale;\t\t/* window scaling for send window */\n\tu_char\trcv_scale;\t\t/* window scaling for recv window */\n\tu_char\trequest_r_scale;\t/* pending window scaling */\n\tu_char\trequested_s_scale;\n\tuint32_t\tts_recent;\t\t/* timestamp echo data */\n\tuint32_t\tts_recent_age;\t\t/* when last updated */\n\ttcp_seq\tlast_ack_sent;\n\n};\n\n#define\tsototcpcb(so)\t((so)->so_tcpcb)\n\n/*\n * The smoothed round-trip time and estimated variance\n * are stored as fixed point numbers scaled by the values below.\n * For convenience, these scales are also used in smoothing the average\n * (smoothed = (1/scale)sample + ((scale-1)/scale)smoothed).\n * With these scales, srtt has 3 bits to the right of the binary point,\n * and thus an \"ALPHA\" of 0.875.  rttvar has 2 bits to the right of the\n * binary point, and is smoothed with an ALPHA of 0.75.\n */\n#define\tTCP_RTT_SCALE\t\t8\t/* multiplier for srtt; 3 bits frac. */\n#define\tTCP_RTT_SHIFT\t\t3\t/* shift for srtt; 3 bits frac. */\n#define\tTCP_RTTVAR_SCALE\t4\t/* multiplier for rttvar; 2 bits */\n#define\tTCP_RTTVAR_SHIFT\t2\t/* multiplier for rttvar; 2 bits */\n\n/*\n * The initial retransmission should happen at rtt + 4 * rttvar.\n * Because of the way we do the smoothing, srtt and rttvar\n * will each average +1/2 tick of bias.  When we compute\n * the retransmit timer, we want 1/2 tick of rounding and\n * 1 extra tick because of +-1/2 tick uncertainty in the\n * firing of the timer.  The bias will give us exactly the\n * 1.5 tick we need.  But, because the bias is\n * statistical, we have to test that we don't drop below\n * the minimum feasible timer (which is 2 ticks).\n * This macro assumes that the value of TCP_RTTVAR_SCALE\n * is the same as the multiplier for rttvar.\n */\n#define\tTCP_REXMTVAL(tp) \\\n\t(((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar)\n\n#endif\n"
  },
  {
    "path": "src/slirp/tcpip.h",
    "content": "/*\n * Copyright (c) 1982, 1986, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)tcpip.h\t8.1 (Berkeley) 6/10/93\n * tcpip.h,v 1.3 1994/08/21 05:27:40 paul Exp\n */\n\n#ifndef _TCPIP_H_\n#define _TCPIP_H_\n\n/*\n * Tcp+ip header, after ip options removed.\n */\nstruct tcpiphdr {\n\tstruct \tipovly ti_i;\t\t/* overlaid ip structure */\n\tstruct\ttcphdr ti_t;\t\t/* tcp header */\n};\n#define\tti_mbuf\t\tti_i.ih_mbuf.mptr\n#define\tti_x1\t\tti_i.ih_x1\n#define\tti_pr\t\tti_i.ih_pr\n#define\tti_len\t\tti_i.ih_len\n#define\tti_src\t\tti_i.ih_src\n#define\tti_dst\t\tti_i.ih_dst\n#define\tti_sport\tti_t.th_sport\n#define\tti_dport\tti_t.th_dport\n#define\tti_seq\t\tti_t.th_seq\n#define\tti_ack\t\tti_t.th_ack\n#define\tti_x2\t\tti_t.th_x2\n#define\tti_off\t\tti_t.th_off\n#define\tti_flags\tti_t.th_flags\n#define\tti_win\t\tti_t.th_win\n#define\tti_sum\t\tti_t.th_sum\n#define\tti_urp\t\tti_t.th_urp\n\n#define tcpiphdr2qlink(T) ((struct qlink*)(((char*)(T)) - sizeof(struct qlink)))\n#define qlink2tcpiphdr(Q) ((struct tcpiphdr*)(((char*)(Q)) + sizeof(struct qlink)))\n#define tcpiphdr_next(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->next)\n#define tcpiphdr_prev(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->prev)\n#define tcpfrag_list_first(T) qlink2tcpiphdr((T)->seg_next)\n#define tcpfrag_list_end(F, T) (tcpiphdr2qlink(F) == (struct qlink*)(T))\n#define tcpfrag_list_empty(T) ((T)->seg_next == (struct tcpiphdr*)(T))\n\n/*\n * Just a clean way to get to the first byte\n * of the packet\n */\nstruct tcpiphdr_2 {\n\tstruct tcpiphdr dummy;\n\tchar first_char;\n};\n\n#endif\n"
  },
  {
    "path": "src/slirp/tftp.h",
    "content": "/* tftp defines */\n\n#define TFTP_SESSIONS_MAX 3\n\n#define TFTP_SERVER\t69\n\n#define TFTP_RRQ    1\n#define TFTP_WRQ    2\n#define TFTP_DATA   3\n#define TFTP_ACK    4\n#define TFTP_ERROR  5\n#define TFTP_OACK   6\n\n#define TFTP_FILENAME_MAX 512\n\nstruct tftp_t {\n  struct ip ip;\n  struct udphdr udp;\n  uint16_t tp_op;\n  union {\n    struct {\n      uint16_t tp_block_nr;\n      uint8_t tp_buf[512];\n    } tp_data;\n    struct {\n      uint16_t tp_error_code;\n      uint8_t tp_msg[512];\n    } tp_error;\n    uint8_t tp_buf[512 + 2];\n  } x;\n};\n\nstruct tftp_session {\n    Slirp *slirp;\n    char *filename;\n\n    struct in_addr client_ip;\n    uint16_t client_port;\n\n    int timestamp;\n};\n\nvoid tftp_input(struct mbuf *m);\n"
  },
  {
    "path": "src/slirp/udp.c",
    "content": "/*\n * Copyright (c) 1982, 1986, 1988, 1990, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)udp_usrreq.c\t8.4 (Berkeley) 1/21/94\n * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp\n */\n\n/*\n * Changes and additions relating to SLiRP\n * Copyright (c) 1995 Danny Gasparovski.\n *\n * Please read the file COPYRIGHT for the\n * terms and conditions of the copyright.\n */\n\n#include \"slirp.h\"\n#include \"ip_icmp.h\"\n\nstatic uint8_t udp_tos(struct socket *so);\n\nvoid\nudp_init(Slirp *slirp)\n{\n    slirp->udb.so_next = slirp->udb.so_prev = &slirp->udb;\n    slirp->udp_last_so = &slirp->udb;\n}\n/* m->m_data  points at ip packet header\n * m->m_len   length ip packet\n * ip->ip_len length data (IPDU)\n */\nvoid\nudp_input(register struct mbuf *m, int iphlen)\n{\n\tSlirp *slirp = m->slirp;\n\tregister struct ip *ip;\n\tregister struct udphdr *uh;\n\tint len;\n\tstruct ip save_ip;\n\tstruct socket *so;\n\n\tDEBUG_CALL(\"udp_input\");\n\tDEBUG_ARG(\"m = %lx\", (long)m);\n\tDEBUG_ARG(\"iphlen = %d\", iphlen);\n\n\t/*\n\t * Strip IP options, if any; should skip this,\n\t * make available to user, and use on returned packets,\n\t * but we don't yet have a way to check the checksum\n\t * with options still present.\n\t */\n\tif(iphlen > sizeof(struct ip)) {\n\t\tip_stripoptions(m, (struct mbuf *)0);\n\t\tiphlen = sizeof(struct ip);\n\t}\n\n\t/*\n\t * Get IP and UDP header together in first mbuf.\n\t */\n\tip = mtod(m, struct ip *);\n\tuh = (struct udphdr *)((caddr_t)ip + iphlen);\n\n\t/*\n\t * Make mbuf data length reflect UDP length.\n\t * If not enough data to reflect UDP length, drop.\n\t */\n\tlen = ntohs((uint16_t)uh->uh_ulen);\n\n\tif (ip->ip_len != len) {\n\t\tif (len > ip->ip_len) {\n\t\t\tgoto bad;\n\t\t}\n\t\tm_adj(m, len - ip->ip_len);\n\t\tip->ip_len = len;\n\t}\n\n\t/*\n\t * Save a copy of the IP header in case we want restore it\n\t * for sending an ICMP error message in response.\n\t */\n\tsave_ip = *ip;\n\tsave_ip.ip_len+= iphlen;         /* tcp_input subtracts this */\n\n\t/*\n\t * Checksum extended UDP header and data.\n\t */\n\tif (uh->uh_sum) {\n      memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));\n\t  ((struct ipovly *)ip)->ih_x1 = 0;\n\t  ((struct ipovly *)ip)->ih_len = uh->uh_ulen;\n\t  if(cksum(m, len + sizeof(struct ip))) {\n\t    goto bad;\n\t  }\n\t}\n\n        /*\n         *  handle DHCP/BOOTP\n         */\n        if (ntohs(uh->uh_dport) == BOOTP_SERVER) {\n            bootp_input(m);\n            goto bad;\n        }\n\n        if (slirp->restricted) {\n            goto bad;\n        }\n\n#if 0\n        /*\n         *  handle TFTP\n         */\n        if (ntohs(uh->uh_dport) == TFTP_SERVER) {\n            tftp_input(m);\n            goto bad;\n        }\n#endif\n        \n\t/*\n\t * Locate pcb for datagram.\n\t */\n\tso = slirp->udp_last_so;\n\tif (so->so_lport != uh->uh_sport ||\n\t    so->so_laddr.s_addr != ip->ip_src.s_addr) {\n\t\tstruct socket *tmp;\n\n\t\tfor (tmp = slirp->udb.so_next; tmp != &slirp->udb;\n\t\t     tmp = tmp->so_next) {\n\t\t\tif (tmp->so_lport == uh->uh_sport &&\n\t\t\t    tmp->so_laddr.s_addr == ip->ip_src.s_addr) {\n\t\t\t\tso = tmp;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (tmp == &slirp->udb) {\n\t\t  so = NULL;\n\t\t} else {\n\t\t  slirp->udp_last_so = so;\n\t\t}\n\t}\n\n\tif (so == NULL) {\n\t  /*\n\t   * If there's no socket for this packet,\n\t   * create one\n\t   */\n\t  so = socreate(slirp);\n\t  if (!so) {\n\t      goto bad;\n\t  }\n\t  if(udp_attach(so) == -1) {\n\t    DEBUG_MISC((dfd,\" udp_attach errno = %d-%s\\n\",\n\t\t\terrno,strerror(errno)));\n\t    sofree(so);\n\t    goto bad;\n\t  }\n\n\t  /*\n\t   * Setup fields\n\t   */\n\t  so->so_laddr = ip->ip_src;\n\t  so->so_lport = uh->uh_sport;\n\n\t  if ((so->so_iptos = udp_tos(so)) == 0)\n\t    so->so_iptos = ip->ip_tos;\n\n\t  /*\n\t   * XXXXX Here, check if it's in udpexec_list,\n\t   * and if it is, do the fork_exec() etc.\n\t   */\n\t}\n\n        so->so_faddr = ip->ip_dst; /* XXX */\n        so->so_fport = uh->uh_dport; /* XXX */\n\n\tiphlen += sizeof(struct udphdr);\n\tm->m_len -= iphlen;\n\tm->m_data += iphlen;\n\n\t/*\n\t * Now we sendto() the packet.\n\t */\n\tif(sosendto(so,m) == -1) {\n\t  m->m_len += iphlen;\n\t  m->m_data -= iphlen;\n\t  *ip=save_ip;\n\t  DEBUG_MISC((dfd,\"udp tx errno = %d-%s\\n\",errno,strerror(errno)));\n\t  icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));\n\t}\n\n\tm_free(so->so_m);   /* used for ICMP if error on sorecvfrom */\n\n\t/* restore the orig mbuf packet */\n\tm->m_len += iphlen;\n\tm->m_data -= iphlen;\n\t*ip=save_ip;\n\tso->so_m=m;         /* ICMP backup */\n\n\treturn;\nbad:\n\tm_freem(m);\n\treturn;\n}\n\nint udp_output2(struct socket *so, struct mbuf *m,\n                struct sockaddr_in *saddr, struct sockaddr_in *daddr,\n                int iptos)\n{\n\tregister struct udpiphdr *ui;\n\tint error = 0;\n\n\tDEBUG_CALL(\"udp_output\");\n\tDEBUG_ARG(\"so = %lx\", (long)so);\n\tDEBUG_ARG(\"m = %lx\", (long)m);\n\tDEBUG_ARG(\"saddr = %lx\", (long)saddr->sin_addr.s_addr);\n\tDEBUG_ARG(\"daddr = %lx\", (long)daddr->sin_addr.s_addr);\n\n\t/*\n\t * Adjust for header\n\t */\n\tm->m_data -= sizeof(struct udpiphdr);\n\tm->m_len += sizeof(struct udpiphdr);\n\n\t/*\n\t * Fill in mbuf with extended UDP header\n\t * and addresses and length put into network format.\n\t */\n\tui = mtod(m, struct udpiphdr *);\n    memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));\n\tui->ui_x1 = 0;\n\tui->ui_pr = IPPROTO_UDP;\n\tui->ui_len = htons(m->m_len - sizeof(struct ip));\n\t/* XXXXX Check for from-one-location sockets, or from-any-location sockets */\n        ui->ui_src = saddr->sin_addr;\n\tui->ui_dst = daddr->sin_addr;\n\tui->ui_sport = saddr->sin_port;\n\tui->ui_dport = daddr->sin_port;\n\tui->ui_ulen = ui->ui_len;\n\n\t/*\n\t * Stuff checksum and output datagram.\n\t */\n\tui->ui_sum = 0;\n\tif ((ui->ui_sum = cksum(m, m->m_len)) == 0)\n\t\tui->ui_sum = 0xffff;\n\t((struct ip *)ui)->ip_len = m->m_len;\n\n\t((struct ip *)ui)->ip_ttl = IPDEFTTL;\n\t((struct ip *)ui)->ip_tos = iptos;\n\n\terror = ip_output(so, m);\n\n\treturn (error);\n}\n\nint udp_output(struct socket *so, struct mbuf *m,\n               struct sockaddr_in *addr)\n\n{\n    Slirp *slirp = so->slirp;\n    struct sockaddr_in saddr, daddr;\n\n    saddr = *addr;\n    if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==\n        slirp->vnetwork_addr.s_addr) {\n        uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;\n\n        if ((so->so_faddr.s_addr & inv_mask) == inv_mask) {\n            saddr.sin_addr = slirp->vhost_addr;\n        } else if (addr->sin_addr.s_addr == loopback_addr.s_addr ||\n                   so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {\n            saddr.sin_addr = so->so_faddr;\n        }\n    }\n    daddr.sin_addr = so->so_laddr;\n    daddr.sin_port = so->so_lport;\n\n    return udp_output2(so, m, &saddr, &daddr, so->so_iptos);\n}\n\nint\nudp_attach(struct socket *so)\n{\n  if((so->s = os_socket(AF_INET,SOCK_DGRAM,0)) != -1) {\n    so->so_expire = curtime + SO_EXPIRE;\n    insque(so, &so->slirp->udb);\n  }\n  return(so->s);\n}\n\nvoid\nudp_detach(struct socket *so)\n{\n\tclosesocket(so->s);\n\tsofree(so);\n}\n\nstatic const struct tos_t udptos[] = {\n\t{0, 53, IPTOS_LOWDELAY, 0},\t\t\t/* DNS */\n\t{0, 0, 0, 0}\n};\n\nstatic uint8_t\nudp_tos(struct socket *so)\n{\n\tint i = 0;\n\n\twhile(udptos[i].tos) {\n\t\tif ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||\n\t\t    (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {\n\t\t    \tso->so_emu = udptos[i].emu;\n\t\t\treturn udptos[i].tos;\n\t\t}\n\t\ti++;\n\t}\n\n\treturn 0;\n}\n\nstruct socket *\nudp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,\n           u_int lport, int flags)\n{\n\tstruct sockaddr_in addr;\n\tstruct socket *so;\n\tsocklen_t addrlen = sizeof(struct sockaddr_in), opt = 1;\n\n\tso = socreate(slirp);\n\tif (!so) {\n\t    return NULL;\n\t}\n\tso->s = os_socket(AF_INET,SOCK_DGRAM,0);\n\tso->so_expire = curtime + SO_EXPIRE;\n\tinsque(so, &slirp->udb);\n\n\taddr.sin_family = AF_INET;\n\taddr.sin_addr.s_addr = haddr;\n\taddr.sin_port = hport;\n\n\tif (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {\n\t\tudp_detach(so);\n\t\treturn NULL;\n\t}\n\tsetsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));\n\n\tgetsockname(so->s,(struct sockaddr *)&addr,&addrlen);\n\tso->so_fport = addr.sin_port;\n\tif (addr.sin_addr.s_addr == 0 ||\n\t    addr.sin_addr.s_addr == loopback_addr.s_addr) {\n\t   so->so_faddr = slirp->vhost_addr;\n\t} else {\n\t   so->so_faddr = addr.sin_addr;\n\t}\n\tso->so_lport = lport;\n\tso->so_laddr.s_addr = laddr;\n\tif (flags != SS_FACCEPTONCE)\n\t   so->so_expire = 0;\n\n\tso->so_state &= SS_PERSISTENT_MASK;\n\tso->so_state |= SS_ISFCONNECTED | flags;\n\n\treturn so;\n}\n"
  },
  {
    "path": "src/slirp/udp.h",
    "content": "/*\n * Copyright (c) 1982, 1986, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)udp.h\t8.1 (Berkeley) 6/10/93\n * udp.h,v 1.3 1994/08/21 05:27:41 paul Exp\n */\n\n#ifndef _UDP_H_\n#define _UDP_H_\n\n#define UDP_TTL 0x60\n#define UDP_UDPDATALEN 16192\n\n/*\n * Udp protocol header.\n * Per RFC 768, September, 1981.\n */\nstruct udphdr {\n    uint16_t uh_sport;          /* source port */\n    uint16_t uh_dport;          /* destination port */\n    int16_t  uh_ulen;           /* udp length */\n    uint16_t uh_sum;            /* udp checksum */\n};\n\n/*\n * UDP kernel structures and variables.\n */\nstruct udpiphdr {\n\t        struct  ipovly ui_i;            /* overlaid ip structure */\n\t        struct  udphdr ui_u;            /* udp header */\n};\n#define ui_mbuf         ui_i.ih_mbuf.mptr\n#define ui_x1           ui_i.ih_x1\n#define ui_pr           ui_i.ih_pr\n#define ui_len          ui_i.ih_len\n#define ui_src          ui_i.ih_src\n#define ui_dst          ui_i.ih_dst\n#define ui_sport        ui_u.uh_sport\n#define ui_dport        ui_u.uh_dport\n#define ui_ulen         ui_u.uh_ulen\n#define ui_sum          ui_u.uh_sum\n\n/*\n * Names for UDP sysctl objects\n */\n#define UDPCTL_CHECKSUM         1       /* checksum UDP packets */\n#define UDPCTL_MAXID            2\n\nstruct mbuf;\n\nvoid udp_init(Slirp *);\nvoid udp_input(register struct mbuf *, int);\nint udp_output(struct socket *, struct mbuf *, struct sockaddr_in *);\nint udp_attach(struct socket *);\nvoid udp_detach(struct socket *);\nstruct socket * udp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,\n                           int);\nint udp_output2(struct socket *so, struct mbuf *m,\n                struct sockaddr_in *saddr, struct sockaddr_in *daddr,\n                int iptos);\n#endif\n"
  },
  {
    "path": "src/softfp.c",
    "content": "/*\n * SoftFP Library\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <assert.h>\n#include <string.h>\n\n#include \"cutils.h\"\n#include \"softfp.h\"\n\nstatic inline int clz32(uint32_t a)\n{\n    int r;\n    if (a == 0) {\n        r = 32;\n    } else {\n        r = __builtin_clz(a);\n    }\n    return r;\n}\n\nstatic inline int clz64(uint64_t a)\n{\n    int r;\n    if (a == 0) {\n        r = 64;\n    } else \n    {\n        r = __builtin_clzll(a);\n    }\n    return r;\n}\n\n#ifdef HAVE_INT128\nstatic inline int clz128(uint128_t a)\n{\n    int r;\n    if (a == 0) {\n        r = 128;\n    } else \n    {\n        uint64_t ah, al;\n        ah = a >> 64;\n        al = a;\n        if (ah != 0)\n            r = __builtin_clzll(ah);\n        else\n            r = __builtin_clzll(al) + 64;\n    }\n    return r;\n}\n#endif\n\n#define F_SIZE 32\n#include \"softfp_template.h\"\n\n#define F_SIZE 64\n#include \"softfp_template.h\"\n\n#ifdef HAVE_INT128\n\n#define F_SIZE 128\n#include \"softfp_template.h\"\n\n#endif\n\n"
  },
  {
    "path": "src/softfp.h",
    "content": "/*\n * SoftFP Library\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef SOFTFP_H\n#define SOFTFP_H\n\n#include <inttypes.h>\n#include \"cutils.h\"\n\ntypedef enum {\n    RM_RNE, /* Round to Nearest, ties to Even */\n    RM_RTZ, /* Round towards Zero */\n    RM_RDN, /* Round Down */\n    RM_RUP, /* Round Up */\n    RM_RMM, /* Round to Nearest, ties to Max Magnitude */\n} RoundingModeEnum;\n\n#define FFLAG_INVALID_OP  (1 << 4)\n#define FFLAG_DIVIDE_ZERO (1 << 3)\n#define FFLAG_OVERFLOW    (1 << 2)\n#define FFLAG_UNDERFLOW   (1 << 1)\n#define FFLAG_INEXACT     (1 << 0)\n\n#define FCLASS_NINF       (1 << 0)\n#define FCLASS_NNORMAL    (1 << 1)\n#define FCLASS_NSUBNORMAL (1 << 2)\n#define FCLASS_NZERO      (1 << 3)\n#define FCLASS_PZERO      (1 << 4)\n#define FCLASS_PSUBNORMAL (1 << 5)\n#define FCLASS_PNORMAL    (1 << 6)\n#define FCLASS_PINF       (1 << 7)\n#define FCLASS_SNAN       (1 << 8)\n#define FCLASS_QNAN       (1 << 9)\n\ntypedef enum {\n    FMINMAX_PROP, /* min(1, qNaN/sNaN) -> qNaN */\n    FMINMAX_IEEE754_2008, /* min(1, qNaN) -> 1, min(1, sNaN) -> qNaN */\n    FMINMAX_IEEE754_201X, /* min(1, qNaN/sNaN) -> 1 */\n} SoftFPMinMaxTypeEnum;\n\ntypedef uint32_t sfloat32;\ntypedef uint64_t sfloat64;\n#ifdef HAVE_INT128\ntypedef uint128_t sfloat128;\n#endif\n\n/* 32 bit floats */\n\n#define FSIGN_MASK32 (1 << 31)\n\nsfloat32 add_sf32(sfloat32 a, sfloat32 b, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat32 sub_sf32(sfloat32 a, sfloat32 b, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat32 mul_sf32(sfloat32 a, sfloat32 b, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat32 div_sf32(sfloat32 a, sfloat32 b, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat32 sqrt_sf32(sfloat32 a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat32 fma_sf32(sfloat32 a, sfloat32 b, sfloat32 c, RoundingModeEnum rm, uint32_t *pfflags);\n\nsfloat32 min_sf32(sfloat32 a, sfloat32 b, uint32_t *pfflags, SoftFPMinMaxTypeEnum minmax_type);\nsfloat32 max_sf32(sfloat32 a, sfloat32 b, uint32_t *pfflags, SoftFPMinMaxTypeEnum minmax_type);\nint eq_quiet_sf32(sfloat32 a, sfloat32 b, uint32_t *pfflags);\nint le_sf32(sfloat32 a, sfloat32 b, uint32_t *pfflags);\nint lt_sf32(sfloat32 a, sfloat32 b, uint32_t *pfflags);\nuint32_t fclass_sf32(sfloat32 a);\n\nsfloat64 cvt_sf32_sf64(sfloat32 a, uint32_t *pfflags);\nsfloat32 cvt_sf64_sf32(sfloat64 a, RoundingModeEnum rm, uint32_t *pfflags);\nint32_t cvt_sf32_i32(sfloat32 a, RoundingModeEnum rm, uint32_t *pfflags);\nuint32_t cvt_sf32_u32(sfloat32 a, RoundingModeEnum rm, uint32_t *pfflags);\nint64_t cvt_sf32_i64(sfloat32 a, RoundingModeEnum rm, uint32_t *pfflags);\nuint64_t cvt_sf32_u64(sfloat32 a, RoundingModeEnum rm, uint32_t *pfflags);\n#ifdef HAVE_INT128\nint128_t cvt_sf32_i128(sfloat32 a, RoundingModeEnum rm, uint32_t *pfflags);\nuint128_t cvt_sf32_u128(sfloat32 a, RoundingModeEnum rm, uint32_t *pfflags);\n#endif\nsfloat32 cvt_i32_sf32(int32_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat32 cvt_u32_sf32(uint32_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat32 cvt_i64_sf32(int64_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat32 cvt_u64_sf32(uint64_t a, RoundingModeEnum rm, uint32_t *pfflags);\n#ifdef HAVE_INT128\nsfloat32 cvt_i128_sf32(int128_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat32 cvt_u128_sf32(uint128_t a, RoundingModeEnum rm, uint32_t *pfflags);\n#endif\n\n/* 64 bit floats */\n\n#define FSIGN_MASK64 ((uint64_t)1 << 63)\n\nsfloat64 add_sf64(sfloat64 a, sfloat64 b, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat64 sub_sf64(sfloat64 a, sfloat64 b, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat64 mul_sf64(sfloat64 a, sfloat64 b, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat64 div_sf64(sfloat64 a, sfloat64 b, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat64 sqrt_sf64(sfloat64 a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat64 fma_sf64(sfloat64 a, sfloat64 b, sfloat64 c, RoundingModeEnum rm, uint32_t *pfflags);\n\nsfloat64 min_sf64(sfloat64 a, sfloat64 b, uint32_t *pfflags, SoftFPMinMaxTypeEnum minmax_type);\nsfloat64 max_sf64(sfloat64 a, sfloat64 b, uint32_t *pfflags, SoftFPMinMaxTypeEnum minmax_type);\nint eq_quiet_sf64(sfloat64 a, sfloat64 b, uint32_t *pfflags);\nint le_sf64(sfloat64 a, sfloat64 b, uint32_t *pfflags);\nint lt_sf64(sfloat64 a, sfloat64 b, uint32_t *pfflags);\nuint32_t fclass_sf64(sfloat64 a);\n\nsfloat64 cvt_sf32_sf64(sfloat32 a, uint32_t *pfflags);\nsfloat32 cvt_sf64_sf32(sfloat64 a, RoundingModeEnum rm, uint32_t *pfflags);\nint32_t cvt_sf64_i32(sfloat64 a, RoundingModeEnum rm, uint32_t *pfflags);\nuint32_t cvt_sf64_u32(sfloat64 a, RoundingModeEnum rm, uint32_t *pfflags);\nint64_t cvt_sf64_i64(sfloat64 a, RoundingModeEnum rm, uint32_t *pfflags);\nuint64_t cvt_sf64_u64(sfloat64 a, RoundingModeEnum rm, uint32_t *pfflags);\n#ifdef HAVE_INT128\nint128_t cvt_sf64_i128(sfloat64 a, RoundingModeEnum rm, uint32_t *pfflags);\nuint128_t cvt_sf64_u128(sfloat64 a, RoundingModeEnum rm, uint32_t *pfflags);\n#endif\nsfloat64 cvt_i32_sf64(int32_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat64 cvt_u32_sf64(uint32_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat64 cvt_i64_sf64(int64_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat64 cvt_u64_sf64(uint64_t a, RoundingModeEnum rm, uint32_t *pfflags);\n#ifdef HAVE_INT128\nsfloat64 cvt_i128_sf64(int128_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat64 cvt_u128_sf64(uint128_t a, RoundingModeEnum rm, uint32_t *pfflags);\n#endif\n\n/* 128 bit floats */\n\n#ifdef HAVE_INT128\n\n#define FSIGN_MASK128 ((uint128_t)1 << 127)\n\nsfloat128 add_sf128(sfloat128 a, sfloat128 b, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat128 sub_sf128(sfloat128 a, sfloat128 b, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat128 mul_sf128(sfloat128 a, sfloat128 b, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat128 div_sf128(sfloat128 a, sfloat128 b, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat128 sqrt_sf128(sfloat128 a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat128 fma_sf128(sfloat128 a, sfloat128 b, sfloat128 c, RoundingModeEnum rm, uint32_t *pfflags);\n\nsfloat128 min_sf128(sfloat128 a, sfloat128 b, uint32_t *pfflags, SoftFPMinMaxTypeEnum minmax_type);\nsfloat128 max_sf128(sfloat128 a, sfloat128 b, uint32_t *pfflags, SoftFPMinMaxTypeEnum minmax_type);\nint eq_quiet_sf128(sfloat128 a, sfloat128 b, uint32_t *pfflags);\nint le_sf128(sfloat128 a, sfloat128 b, uint32_t *pfflags);\nint lt_sf128(sfloat128 a, sfloat128 b, uint32_t *pfflags);\nuint32_t fclass_sf128(sfloat128 a);\n\nsfloat128 cvt_sf32_sf128(sfloat32 a, uint32_t *pfflags);\nsfloat32 cvt_sf128_sf32(sfloat128 a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat128 cvt_sf64_sf128(sfloat64 a, uint32_t *pfflags);\nsfloat64 cvt_sf128_sf64(sfloat128 a, RoundingModeEnum rm, uint32_t *pfflags);\n\nint32_t cvt_sf128_i32(sfloat128 a, RoundingModeEnum rm, uint32_t *pfflags);\nuint32_t cvt_sf128_u32(sfloat128 a, RoundingModeEnum rm, uint32_t *pfflags);\nint64_t cvt_sf128_i64(sfloat128 a, RoundingModeEnum rm, uint32_t *pfflags);\nuint64_t cvt_sf128_u64(sfloat128 a, RoundingModeEnum rm, uint32_t *pfflags);\nint128_t cvt_sf128_i128(sfloat128 a, RoundingModeEnum rm, uint32_t *pfflags);\nuint128_t cvt_sf128_u128(sfloat128 a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat128 cvt_i32_sf128(int32_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat128 cvt_u32_sf128(uint32_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat128 cvt_i64_sf128(int64_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat128 cvt_u64_sf128(uint64_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat128 cvt_i128_sf128(int128_t a, RoundingModeEnum rm, uint32_t *pfflags);\nsfloat128 cvt_u128_sf128(uint128_t a, RoundingModeEnum rm, uint32_t *pfflags);\n\n#endif\n\n#endif /* SOFTFP_H */\n"
  },
  {
    "path": "src/softfp_template.h",
    "content": "/*\n * SoftFP Library\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#if F_SIZE == 32\n#define F_UINT uint32_t\n#define F_ULONG uint64_t\n#define MANT_SIZE 23\n#define EXP_SIZE 8\n#elif F_SIZE == 64\n#define F_UHALF uint32_t\n#define F_UINT uint64_t\n#ifdef HAVE_INT128\n#define F_ULONG uint128_t\n#endif\n#define MANT_SIZE 52\n#define EXP_SIZE 11\n#elif F_SIZE == 128\n#define F_UHALF uint64_t\n#define F_UINT uint128_t\n#define MANT_SIZE 112\n#define EXP_SIZE 15\n#else\n#error unsupported F_SIZE\n#endif\n\n#define EXP_MASK ((1 << EXP_SIZE) - 1)\n#define MANT_MASK (((F_UINT)1 << MANT_SIZE) - 1)\n#define SIGN_MASK ((F_UINT)1 << (F_SIZE - 1))\n#define IMANT_SIZE (F_SIZE - 2) /* internal mantissa size */\n#define RND_SIZE (IMANT_SIZE - MANT_SIZE)\n#define QNAN_MASK ((F_UINT)1 << (MANT_SIZE - 1))\n\n/* quiet NaN */\n#define F_QNAN glue(F_QNAN, F_SIZE)\n#define clz glue(clz, F_SIZE)\n#define pack_sf glue(pack_sf, F_SIZE)\n#define unpack_sf glue(unpack_sf, F_SIZE)\n#define rshift_rnd glue(rshift_rnd, F_SIZE)\n#define round_pack_sf glue(roundpack_sf, F_SIZE)\n#define normalize_sf glue(normalize_sf, F_SIZE)\n#define normalize2_sf glue(normalize2_sf, F_SIZE)\n#define issignan_sf glue(issignan_sf, F_SIZE)\n#define isnan_sf glue(isnan_sf, F_SIZE)\n#define add_sf glue(add_sf, F_SIZE)\n#define mul_sf glue(mul_sf, F_SIZE)\n#define fma_sf glue(fma_sf, F_SIZE)\n#define div_sf glue(div_sf, F_SIZE)\n#define sqrt_sf glue(sqrt_sf, F_SIZE)\n#define normalize_subnormal_sf glue(normalize_subnormal_sf, F_SIZE)\n#define divrem_u glue(divrem_u, F_SIZE)\n#define sqrtrem_u glue(sqrtrem_u, F_SIZE)\n#define mul_u glue(mul_u, F_SIZE)\n#define cvt_sf32_sf glue(cvt_sf32_sf, F_SIZE)\n#define cvt_sf64_sf glue(cvt_sf64_sf, F_SIZE)\n\nstatic const F_UINT F_QNAN = (((F_UINT)EXP_MASK << MANT_SIZE) | ((F_UINT)1 << (MANT_SIZE - 1)));\n\nstatic inline F_UINT pack_sf(uint32_t a_sign, uint32_t a_exp, F_UINT a_mant)\n{\n    return ((F_UINT)a_sign << (F_SIZE - 1)) |\n        ((F_UINT)a_exp << MANT_SIZE) | \n        (a_mant & MANT_MASK);\n}\n\nstatic inline F_UINT unpack_sf(uint32_t *pa_sign, int32_t *pa_exp,\n                               F_UINT a)\n{\n    *pa_sign = a >> (F_SIZE - 1);\n    *pa_exp = (a >> MANT_SIZE) & EXP_MASK;\n    return a & MANT_MASK;\n} \n\nstatic F_UINT rshift_rnd(F_UINT a, int d)\n{\n    F_UINT mask;\n    if (d != 0) {\n        if (d >= F_SIZE) {\n            a = (a != 0);\n        } else {\n            mask = ((F_UINT)1 << d) - 1;\n            a = (a >> d) | ((a & mask) != 0);\n        }\n    }\n    return a;\n}\n\n/* a_mant is considered to have its MSB at F_SIZE - 2 bits */\nstatic F_UINT round_pack_sf(uint32_t a_sign, int a_exp, F_UINT a_mant,\n                            RoundingModeEnum rm, uint32_t *pfflags)\n{\n    int diff;\n    uint32_t addend, rnd_bits;\n\n    switch(rm) {\n    case RM_RNE:\n    case RM_RMM:\n        addend = (1 << (RND_SIZE - 1));\n        break;\n    case RM_RTZ:\n        addend = 0;\n        break;\n    default:\n    case RM_RDN:\n    case RM_RUP:\n        //        printf(\"s=%d rm=%d m=%x\\n\", a_sign, rm, a_mant);\n        if (a_sign ^ (rm & 1))\n            addend = (1 << RND_SIZE) - 1;\n        else\n            addend = 0;\n        break;\n    }\n\n    /* potentially subnormal */\n    if (a_exp <= 0) {\n        BOOL is_subnormal;\n        /* Note: we set the underflow flag if the rounded result\n           is subnormal and inexact */\n        is_subnormal = (a_exp < 0 || \n                        (a_mant + addend) < ((F_UINT)1 << (F_SIZE - 1)));\n        diff = 1 - a_exp;\n        a_mant = rshift_rnd(a_mant, diff);\n        rnd_bits = a_mant & ((1 << RND_SIZE ) - 1);\n        if (is_subnormal && rnd_bits != 0) {\n            *pfflags |= FFLAG_UNDERFLOW;\n        }\n        a_exp = 1;\n    } else {\n        rnd_bits = a_mant & ((1 << RND_SIZE ) - 1);\n    }\n    if (rnd_bits != 0)\n        *pfflags |= FFLAG_INEXACT;\n    a_mant = (a_mant + addend) >> RND_SIZE;\n    /* half way: select even result */\n    if (rm == RM_RNE && rnd_bits == (1 << (RND_SIZE - 1)))\n        a_mant &= ~1;\n    /* Note the rounding adds at least 1, so this is the maximum\n       value */\n    a_exp += a_mant >> (MANT_SIZE + 1);\n    if (a_mant <= MANT_MASK) {\n        /* denormalized or zero */\n        a_exp = 0;\n    } else if (a_exp >= EXP_MASK) {\n        /* overflow */\n        if (addend == 0) {\n            a_exp = EXP_MASK - 1;\n            a_mant = MANT_MASK;\n        } else {\n            /* infinity */\n            a_exp = EXP_MASK;\n            a_mant = 0;\n        }\n        *pfflags |= FFLAG_OVERFLOW | FFLAG_INEXACT;\n    }\n    return pack_sf(a_sign, a_exp, a_mant);\n}\n\n/* a_mant is considered to have at most F_SIZE - 1 bits */\nstatic F_UINT normalize_sf(uint32_t a_sign, int a_exp, F_UINT a_mant,\n                           RoundingModeEnum rm, uint32_t *pfflags)\n{\n    int shift;\n    shift = clz(a_mant) - (F_SIZE - 1 - IMANT_SIZE);\n    assert(shift >= 0);\n    a_exp -= shift;\n    a_mant <<= shift;\n    return round_pack_sf(a_sign, a_exp, a_mant, rm, pfflags);\n}\n\n/* same as normalize_sf() but with a double word mantissa. a_mant1 is\n   considered to have at most F_SIZE - 1 bits */\nstatic F_UINT normalize2_sf(uint32_t a_sign, int a_exp, F_UINT a_mant1, F_UINT a_mant0,\n                            RoundingModeEnum rm, uint32_t *pfflags)\n{\n    int l, shift;\n    if (a_mant1 == 0) {\n        l = F_SIZE + clz(a_mant0);\n    } else {\n        l = clz(a_mant1);\n    }\n    shift = l - (F_SIZE - 1 - IMANT_SIZE);\n    assert(shift >= 0);\n    a_exp -= shift;\n    if (shift == 0) {\n        a_mant1 |= (a_mant0 != 0);\n    } else if (shift < F_SIZE) {\n        a_mant1 = (a_mant1 << shift) | (a_mant0 >> (F_SIZE - shift));\n        a_mant0 <<= shift;\n        a_mant1 |= (a_mant0 != 0);\n    } else {\n        a_mant1 = a_mant0 << (shift - F_SIZE);\n    }\n    return round_pack_sf(a_sign, a_exp, a_mant1, rm, pfflags);\n}\n\nBOOL issignan_sf(F_UINT a)\n{\n    uint32_t a_exp1;\n    F_UINT a_mant;\n    a_exp1 = (a >> (MANT_SIZE - 1)) & ((1 << (EXP_SIZE + 1)) - 1);\n    a_mant = a & MANT_MASK;\n    return (a_exp1 == (2 * EXP_MASK) && a_mant != 0);\n}\n\nBOOL isnan_sf(F_UINT a)\n{\n    uint32_t a_exp;\n    F_UINT a_mant;\n    a_exp = (a >> MANT_SIZE) & EXP_MASK;\n    a_mant = a & MANT_MASK;\n    return (a_exp == EXP_MASK && a_mant != 0);\n}\n\n\nF_UINT add_sf(F_UINT a, F_UINT b, RoundingModeEnum rm,\n              uint32_t *pfflags)\n{\n    uint32_t a_sign, b_sign, a_exp, b_exp;\n    F_UINT tmp, a_mant, b_mant;\n\n    /* swap so that  abs(a) >= abs(b) */\n    if ((a & ~SIGN_MASK) < (b & ~SIGN_MASK)) {\n        tmp = a;\n        a = b;\n        b = tmp;\n    }\n    a_sign = a >> (F_SIZE - 1);\n    b_sign = b >> (F_SIZE - 1);\n    a_exp = (a >> MANT_SIZE) & EXP_MASK;\n    b_exp = (b >> MANT_SIZE) & EXP_MASK;\n    a_mant = (a & MANT_MASK) << 3;\n    b_mant = (b & MANT_MASK) << 3;\n    if (unlikely(a_exp == EXP_MASK)) {\n        if (a_mant != 0) {\n            /* NaN result */\n            if (!(a_mant & (QNAN_MASK << 3)) || issignan_sf(b))\n                *pfflags |= FFLAG_INVALID_OP;\n            return F_QNAN;\n        } else if (b_exp == EXP_MASK && a_sign != b_sign) {\n            *pfflags |= FFLAG_INVALID_OP;\n            return F_QNAN;\n        } else {\n            /* infinity */\n            return a;\n        }\n    }\n    if (a_exp == 0) {\n        a_exp = 1;\n    } else {\n        a_mant |= (F_UINT)1 << (MANT_SIZE + 3);\n    }\n    if (b_exp == 0) {\n        b_exp = 1;\n    } else {\n        b_mant |= (F_UINT)1 << (MANT_SIZE + 3);\n    }\n    b_mant = rshift_rnd(b_mant, a_exp - b_exp);\n    if (a_sign == b_sign) {\n        /* same signs : add the absolute values  */\n        a_mant += b_mant;\n    } else {\n        /* different signs : subtract the absolute values  */\n        a_mant -= b_mant;\n        if (a_mant == 0) {\n            /* zero result : the sign needs a specific handling */\n            a_sign = (rm == RM_RDN);\n        }\n    }\n    a_exp += (RND_SIZE - 3);\n    return normalize_sf(a_sign, a_exp, a_mant, rm, pfflags);\n}\n\nF_UINT glue(sub_sf, F_SIZE)(F_UINT a, F_UINT b, RoundingModeEnum rm,\n                            uint32_t *pfflags)\n{\n    return add_sf(a, b ^ SIGN_MASK, rm, pfflags);\n}\n\nstatic inline F_UINT normalize_subnormal_sf(int32_t *pa_exp, F_UINT a_mant)\n{\n    int shift;\n    shift = MANT_SIZE - ((F_SIZE - 1 - clz(a_mant)));\n    *pa_exp = 1 - shift;\n    return a_mant << shift;\n}\n\n#ifdef F_ULONG\n\nstatic F_UINT mul_u(F_UINT *plow, F_UINT a, F_UINT b)\n{\n    F_ULONG r;\n    r = (F_ULONG)a * (F_ULONG)b;\n    *plow = r;\n    return r >> F_SIZE;\n}\n\n#else\n\n#define FH_SIZE (F_SIZE / 2)\n\nstatic F_UINT mul_u(F_UINT *plow, F_UINT a, F_UINT b)\n{\n    F_UHALF a0, a1, b0, b1, r0, r1, r2, r3;\n    F_UINT r00, r01, r10, r11, c;\n    a0 = a;\n    a1 = a >> FH_SIZE;\n    b0 = b;\n    b1 = b >> FH_SIZE;\n\n    r00 = (F_UINT)a0 * (F_UINT)b0;\n    r01 = (F_UINT)a0 * (F_UINT)b1;\n    r10 = (F_UINT)a1 * (F_UINT)b0;\n    r11 = (F_UINT)a1 * (F_UINT)b1;\n    \n    r0 = r00;\n    c = (r00 >> FH_SIZE) + (F_UHALF)r01 + (F_UHALF)r10;\n    r1 = c;\n    c = (c >> FH_SIZE) + (r01 >> FH_SIZE) + (r10 >> FH_SIZE) + (F_UHALF)r11;\n    r2 = c;\n    r3 = (c >> FH_SIZE) + (r11 >> FH_SIZE);\n\n    *plow = ((F_UINT)r1 << FH_SIZE) | r0;\n    return ((F_UINT)r3 << FH_SIZE) | r2;\n}\n\n#undef FH_SIZE\n\n#endif\n\nF_UINT mul_sf(F_UINT a, F_UINT b, RoundingModeEnum rm,\n              uint32_t *pfflags)\n{\n    uint32_t a_sign, b_sign, r_sign;\n    int32_t a_exp, b_exp, r_exp;\n    F_UINT a_mant, b_mant, r_mant, r_mant_low;\n\n    a_sign = a >> (F_SIZE - 1);\n    b_sign = b >> (F_SIZE - 1);\n    r_sign = a_sign ^ b_sign;\n    a_exp = (a >> MANT_SIZE) & EXP_MASK;\n    b_exp = (b >> MANT_SIZE) & EXP_MASK;\n    a_mant = a & MANT_MASK;\n    b_mant = b & MANT_MASK;\n    if (a_exp == EXP_MASK || b_exp == EXP_MASK) {\n        if (isnan_sf(a) || isnan_sf(b)) {\n            if (issignan_sf(a) || issignan_sf(b)) {\n                *pfflags |= FFLAG_INVALID_OP;\n            }\n            return F_QNAN;\n        } else {\n            /* infinity */\n            if ((a_exp == EXP_MASK && (b_exp == 0 && b_mant == 0)) ||\n                (b_exp == EXP_MASK && (a_exp == 0 && a_mant == 0))) {\n                *pfflags |= FFLAG_INVALID_OP;\n                return F_QNAN;\n            } else {\n                return pack_sf(r_sign, EXP_MASK, 0);\n            }\n        }\n    }\n    if (a_exp == 0) {\n        if (a_mant == 0)\n            return pack_sf(r_sign, 0, 0); /* zero */\n        a_mant = normalize_subnormal_sf(&a_exp, a_mant);\n    } else {\n        a_mant |= (F_UINT)1 << MANT_SIZE;\n    }\n    if (b_exp == 0) {\n        if (b_mant == 0)\n            return pack_sf(r_sign, 0, 0); /* zero */\n        b_mant = normalize_subnormal_sf(&b_exp, b_mant);\n    } else {\n        b_mant |= (F_UINT)1 << MANT_SIZE;\n    }\n    r_exp = a_exp + b_exp - (1 << (EXP_SIZE - 1)) + 2;\n    \n    r_mant = mul_u(&r_mant_low,a_mant << RND_SIZE, b_mant << (RND_SIZE + 1));\n    r_mant |= (r_mant_low != 0);\n    return normalize_sf(r_sign, r_exp, r_mant, rm, pfflags);\n}\n\n/* fused multiply and add */\nF_UINT fma_sf(F_UINT a, F_UINT b, F_UINT c, RoundingModeEnum rm,\n              uint32_t *pfflags)\n{\n    uint32_t a_sign, b_sign, c_sign, r_sign;\n    int32_t a_exp, b_exp, c_exp, r_exp, shift;\n    F_UINT a_mant, b_mant, c_mant, r_mant1, r_mant0, c_mant1, c_mant0, mask;\n\n    a_sign = a >> (F_SIZE - 1);\n    b_sign = b >> (F_SIZE - 1);\n    c_sign = c >> (F_SIZE - 1);\n    r_sign = a_sign ^ b_sign;\n    a_exp = (a >> MANT_SIZE) & EXP_MASK;\n    b_exp = (b >> MANT_SIZE) & EXP_MASK;\n    c_exp = (c >> MANT_SIZE) & EXP_MASK;\n    a_mant = a & MANT_MASK;\n    b_mant = b & MANT_MASK;\n    c_mant = c & MANT_MASK;\n    if (a_exp == EXP_MASK || b_exp == EXP_MASK || c_exp == EXP_MASK) {\n        if (isnan_sf(a) || isnan_sf(b) || isnan_sf(c)) {\n            if (issignan_sf(a) || issignan_sf(b) || issignan_sf(c)) {\n                *pfflags |= FFLAG_INVALID_OP;\n            }\n            return F_QNAN;\n        } else {\n            /* infinities */\n            if ((a_exp == EXP_MASK && (b_exp == 0 && b_mant == 0)) ||\n                (b_exp == EXP_MASK && (a_exp == 0 && a_mant == 0)) ||\n                ((a_exp == EXP_MASK || b_exp == EXP_MASK) &&\n                 (c_exp == EXP_MASK && r_sign != c_sign))) {\n                *pfflags |= FFLAG_INVALID_OP;\n                return F_QNAN;\n            } else if (c_exp == EXP_MASK) {\n                return pack_sf(c_sign, EXP_MASK, 0);\n            } else {\n                return pack_sf(r_sign, EXP_MASK, 0);\n            }\n        }\n    }\n    if (a_exp == 0) {\n        if (a_mant == 0)\n            goto mul_zero;\n        a_mant = normalize_subnormal_sf(&a_exp, a_mant);\n    } else {\n        a_mant |= (F_UINT)1 << MANT_SIZE;\n    }\n    if (b_exp == 0) {\n        if (b_mant == 0) {\n        mul_zero:\n            if (c_exp == 0 && c_mant == 0) {\n                if (c_sign != r_sign)\n                    r_sign = (rm == RM_RDN);\n                return pack_sf(r_sign, 0, 0);\n            } else {\n                return c;\n            }\n        }\n        b_mant = normalize_subnormal_sf(&b_exp, b_mant);\n    } else {\n        b_mant |= (F_UINT)1 << MANT_SIZE;\n    }\n    /* multiply */\n    r_exp = a_exp + b_exp - (1 << (EXP_SIZE - 1)) + 3;\n    \n    r_mant1 = mul_u(&r_mant0, a_mant << RND_SIZE, b_mant << RND_SIZE);\n    /* normalize to F_SIZE - 3 */\n    if (r_mant1 < ((F_UINT)1 << (F_SIZE - 3))) {\n        r_mant1 = (r_mant1 << 1) | (r_mant0 >> (F_SIZE - 1));\n        r_mant0 <<= 1;\n        r_exp--;\n    }\n\n    /* add */\n    if (c_exp == 0) {\n        if (c_mant == 0) {\n            /* add zero */\n            r_mant1 |= (r_mant0 != 0);\n            return normalize_sf(r_sign, r_exp, r_mant1, rm, pfflags);\n        }\n        c_mant = normalize_subnormal_sf(&c_exp, c_mant);\n    } else {\n        c_mant |= (F_UINT)1 << MANT_SIZE;\n    }\n    c_exp++;\n    c_mant1 = c_mant << (RND_SIZE - 1);\n    c_mant0 = 0;\n\n    //    printf(\"r_s=%d r_exp=%d r_mant=%08x %08x\\n\", r_sign, r_exp, (uint32_t)r_mant1, (uint32_t)r_mant0);\n    //    printf(\"c_s=%d c_exp=%d c_mant=%08x %08x\\n\", c_sign, c_exp, (uint32_t)c_mant1, (uint32_t)c_mant0);\n\n    /* ensure that abs(r) >= abs(c) */\n    if (!(r_exp > c_exp || (r_exp == c_exp && r_mant1 >= c_mant1))) {\n        F_UINT tmp;\n        int32_t c_tmp;\n        /* swap */\n        tmp = r_mant1; r_mant1 = c_mant1; c_mant1 = tmp;\n        tmp = r_mant0; r_mant0 = c_mant0; c_mant0 = tmp;\n        c_tmp = r_exp; r_exp = c_exp; c_exp = c_tmp;\n        c_tmp = r_sign; r_sign = c_sign; c_sign = c_tmp;\n    }\n    /* right shift c_mant */\n    shift = r_exp - c_exp;\n    if (shift >= 2 * F_SIZE) {\n        c_mant0 = (c_mant0 | c_mant1) != 0;\n        c_mant1 = 0;\n    } else if (shift >= F_SIZE + 1) {\n        c_mant0 = rshift_rnd(c_mant1, shift - F_SIZE);\n        c_mant1 = 0;\n    } else if (shift == F_SIZE) {\n        c_mant0 = c_mant1 | (c_mant0 != 0);\n        c_mant1 = 0;\n    } else if (shift != 0) {\n        mask = ((F_UINT)1 << shift) - 1;\n        c_mant0 = (c_mant1 << (F_SIZE - shift)) | (c_mant0 >> shift) | ((c_mant0 & mask) != 0);\n        c_mant1 = c_mant1 >> shift;\n    }\n    //    printf(\"  r_mant=%08x %08x\\n\", (uint32_t)r_mant1, (uint32_t)r_mant0);\n    //    printf(\"  c_mant=%08x %08x\\n\", (uint32_t)c_mant1, (uint32_t)c_mant0);\n    /* add or subtract */\n    if (r_sign == c_sign) {\n        r_mant0 += c_mant0;\n        r_mant1 += c_mant1 + (r_mant0 < c_mant0);\n    } else {\n        F_UINT tmp;\n        tmp = r_mant0;\n        r_mant0 -= c_mant0;\n        r_mant1 = r_mant1 - c_mant1 - (r_mant0 > tmp);\n        if ((r_mant0 | r_mant1) == 0) {\n            /* zero result : the sign needs a specific handling */\n            r_sign = (rm == RM_RDN);\n        }\n    }\n#if 0\n    //    printf(\"  r1_mant=%08x %08x\\n\", (uint32_t)r_mant1, (uint32_t)r_mant0);\n    /* normalize */\n    if (r_mant1 == 0) {\n        r_mant1 = r_mant0;\n        r_exp -= F_SIZE;\n    } else {\n        shift = clz(r_mant1) - (F_SIZE - 1 - IMANT_SIZE);\n        if (shift != 0) {\n            r_mant1 = (r_mant1 << shift) | (r_mant0 >> (F_SIZE - shift));\n            r_mant0 <<= shift;\n            r_exp -= shift;\n        }\n        r_mant1 |= (r_mant0 != 0);\n    }\n    return normalize_sf(r_sign, r_exp, r_mant1, rm, pfflags);\n#else\n    return normalize2_sf(r_sign, r_exp, r_mant1, r_mant0, rm, pfflags);\n#endif\n}\n\n#ifdef F_ULONG\n\nstatic F_UINT divrem_u(F_UINT *pr, F_UINT ah, F_UINT al, F_UINT b)\n{\n    F_ULONG a;\n    a = ((F_ULONG)ah << F_SIZE) | al;\n    *pr = a % b;\n    return a / b;\n}\n\n#else\n\n/* XXX: optimize */\nstatic F_UINT divrem_u(F_UINT *pr, F_UINT a1, F_UINT a0, F_UINT b)\n{\n    int i, qb, ab;\n\n    assert(a1 < b);\n    for(i = 0; i < F_SIZE; i++) {\n        ab = a1 >> (F_SIZE - 1);\n        a1 = (a1 << 1) | (a0 >> (F_SIZE - 1));\n        if (ab || a1 >= b) {\n            a1 -= b;\n            qb = 1;\n        } else {\n            qb = 0;\n        }\n        a0 = (a0 << 1) | qb;\n    }\n    *pr = a1;\n    return a0;\n}\n\n#endif\n\nF_UINT div_sf(F_UINT a, F_UINT b, RoundingModeEnum rm,\n              uint32_t *pfflags)\n{\n    uint32_t a_sign, b_sign, r_sign;\n    int32_t a_exp, b_exp, r_exp;\n    F_UINT a_mant, b_mant, r_mant, r;\n\n    a_sign = a >> (F_SIZE - 1);\n    b_sign = b >> (F_SIZE - 1);\n    r_sign = a_sign ^ b_sign;\n    a_exp = (a >> MANT_SIZE) & EXP_MASK;\n    b_exp = (b >> MANT_SIZE) & EXP_MASK;\n    a_mant = a & MANT_MASK;\n    b_mant = b & MANT_MASK;\n    if (a_exp == EXP_MASK) {\n        if (a_mant != 0 || isnan_sf(b)) {\n            if (issignan_sf(a) || issignan_sf(b)) {\n                *pfflags |= FFLAG_INVALID_OP;\n            }\n            return F_QNAN;\n        } else if (b_exp == EXP_MASK) {\n            *pfflags |= FFLAG_INVALID_OP;\n            return F_QNAN;\n        } else {\n            return pack_sf(r_sign, EXP_MASK, 0);\n        }\n    } else if (b_exp == EXP_MASK) {\n        if (b_mant != 0) {\n            if (issignan_sf(a) || issignan_sf(b)) {\n                *pfflags |= FFLAG_INVALID_OP;\n            }\n            return F_QNAN;\n        } else {\n            return pack_sf(r_sign, 0, 0);\n        }\n    }\n\n    if (b_exp == 0) {\n        if (b_mant == 0) { \n            /* zero */\n            if (a_exp == 0 && a_mant == 0) {\n                *pfflags |= FFLAG_INVALID_OP;\n                return F_QNAN;\n            } else {\n                *pfflags |= FFLAG_DIVIDE_ZERO;\n                return pack_sf(r_sign, EXP_MASK, 0);\n            }\n        }\n        b_mant = normalize_subnormal_sf(&b_exp, b_mant);\n    } else {\n        b_mant |= (F_UINT)1 << MANT_SIZE;\n    }\n    if (a_exp == 0) {\n        if (a_mant == 0)\n            return pack_sf(r_sign, 0, 0); /* zero */\n        a_mant = normalize_subnormal_sf(&a_exp, a_mant);\n    } else {\n        a_mant |= (F_UINT)1 << MANT_SIZE;\n    }\n    r_exp = a_exp - b_exp + (1 << (EXP_SIZE - 1)) - 1;\n    r_mant = divrem_u(&r, a_mant, 0, b_mant << 2);\n    if (r != 0)\n        r_mant |= 1;\n    return normalize_sf(r_sign, r_exp, r_mant, rm, pfflags);\n}\n\n#ifdef F_ULONG\n\n/* compute sqrt(a) with a = ah*2^F_SIZE+al and a < 2^(F_SIZE - 2)\n   return true if not exact square. */\nstatic int sqrtrem_u(F_UINT *pr, F_UINT ah, F_UINT al)\n{\n    F_ULONG a, u, s;\n    int l, inexact;\n\n    /* 2^l >= a */\n    if (ah != 0) {\n        l = 2 * F_SIZE - clz(ah - 1);\n    } else {\n        if (al == 0) {\n            *pr = 0;\n            return 0;\n        }\n        l = F_SIZE - clz(al - 1);\n    }\n    a = ((F_ULONG)ah << F_SIZE) | al;\n    u = (F_ULONG)1 << ((l + 1) / 2);\n    for(;;) {\n        s = u;\n        u = ((a / s) + s) / 2;\n        if (u >= s)\n            break;\n    }\n    inexact = (a - s * s) != 0;\n    *pr = s;\n    return inexact;\n}\n\n#else\n\nstatic int sqrtrem_u(F_UINT *pr, F_UINT a1, F_UINT a0)\n{\n    int l, inexact;\n    F_UINT u, s, r, q, sq0, sq1;\n\n    /* 2^l >= a */\n    if (a1 != 0) {\n        l = 2 * F_SIZE - clz(a1 - 1);\n    } else {\n        if (a0 == 0) {\n            *pr = 0;\n            return 0;\n        }\n        l = F_SIZE - clz(a0 - 1);\n    }\n    u = (F_UINT)1 << ((l + 1) / 2);\n    for(;;) {\n        s = u;\n        q = divrem_u(&r, a1, a0, s);\n        u = (q + s) / 2;\n        if (u >= s)\n            break;\n    }\n    sq1 = mul_u(&sq0, s, s);\n    inexact = (sq0 != a0 || sq1 != a1);\n    *pr = s;\n    return inexact;\n}\n\n#endif\n\nF_UINT sqrt_sf(F_UINT a, RoundingModeEnum rm,\n               uint32_t *pfflags)\n{\n    uint32_t a_sign;\n    int32_t a_exp;\n    F_UINT a_mant;\n\n    a_sign = a >> (F_SIZE - 1);\n    a_exp = (a >> MANT_SIZE) & EXP_MASK;\n    a_mant = a & MANT_MASK;\n    if (a_exp == EXP_MASK) {\n        if (a_mant != 0) {\n            if (issignan_sf(a)) {\n                *pfflags |= FFLAG_INVALID_OP;\n            }\n            return F_QNAN;\n        } else if (a_sign) {\n            goto neg_error;\n        } else {\n            return a; /* +infinity */\n        }\n    }\n    if (a_sign) {\n        if (a_exp == 0 && a_mant == 0)\n            return a; /* -zero */\n    neg_error:\n        *pfflags |= FFLAG_INVALID_OP;\n        return F_QNAN;\n    }\n    if (a_exp == 0) {\n        if (a_mant == 0)\n            return pack_sf(0, 0, 0); /* zero */\n        a_mant = normalize_subnormal_sf(&a_exp, a_mant);\n    } else {\n        a_mant |= (F_UINT)1 << MANT_SIZE;\n    }\n    a_exp -= EXP_MASK / 2;\n    /* simpler to handle an even exponent */\n    if (a_exp & 1) {\n        a_exp--;\n        a_mant <<= 1;\n    }\n    a_exp = (a_exp >> 1) + EXP_MASK / 2;\n    a_mant <<= (F_SIZE - 4 - MANT_SIZE);\n    if (sqrtrem_u(&a_mant, a_mant, 0))\n        a_mant |= 1;\n    return normalize_sf(a_sign, a_exp, a_mant, rm, pfflags);\n}\n\n/* comparisons */\n\nstatic F_UINT glue(min_max_nan_sf, F_SIZE)(F_UINT a, F_UINT b, uint32_t *pfflags, SoftFPMinMaxTypeEnum minmax_type)\n{\n    if (issignan_sf(a) || issignan_sf(b)) {\n        *pfflags |= FFLAG_INVALID_OP;\n        if (minmax_type == FMINMAX_IEEE754_2008)\n            return F_QNAN;\n    }\n    if (minmax_type == FMINMAX_PROP) {\n        return F_QNAN;\n    } else {\n        if (isnan_sf(a)) {\n            if (isnan_sf(b)) \n                return F_QNAN;\n            else\n                return b;\n        } else {\n            return a;\n        }\n    }\n}\n\nF_UINT glue(min_sf, F_SIZE)(F_UINT a, F_UINT b, uint32_t *pfflags,\n                            SoftFPMinMaxTypeEnum minmax_type)\n{\n    uint32_t a_sign, b_sign;\n\n    if (isnan_sf(a) || isnan_sf(b)) {\n        return glue(min_max_nan_sf, F_SIZE)(a, b, pfflags, minmax_type);\n    }\n    a_sign = a >> (F_SIZE - 1);\n    b_sign = b >> (F_SIZE - 1);\n\n    if (a_sign != b_sign) {\n        if (a_sign)\n            return a;\n        else\n            return b;\n    } else {\n        if ((a < b) ^ a_sign)\n            return a;\n        else\n            return b;\n    }\n}\n\nF_UINT glue(max_sf, F_SIZE)(F_UINT a, F_UINT b, uint32_t *pfflags,\n                            SoftFPMinMaxTypeEnum minmax_type)\n{\n    uint32_t a_sign, b_sign;\n\n    if (isnan_sf(a) || isnan_sf(b)) {\n        return glue(min_max_nan_sf, F_SIZE)(a, b, pfflags, minmax_type);\n    }\n    a_sign = a >> (F_SIZE - 1);\n    b_sign = b >> (F_SIZE - 1);\n\n    if (a_sign != b_sign) {\n        if (a_sign)\n            return b;\n        else\n            return a;\n    } else {\n        if ((a < b) ^ a_sign)\n            return b;\n        else\n            return a;\n    }\n}\n\nint glue(eq_quiet_sf, F_SIZE)(F_UINT a, F_UINT b, uint32_t *pfflags)\n{\n    if (isnan_sf(a) || isnan_sf(b)) {\n        if (issignan_sf(a) || issignan_sf(b)) {\n            *pfflags |= FFLAG_INVALID_OP;\n        }\n        return 0;\n    }\n\n    if ((F_UINT)((a | b) << 1) == 0)\n        return 1; /* zero case */\n    return (a == b);\n}\n\nint glue(le_sf, F_SIZE)(F_UINT a, F_UINT b, uint32_t *pfflags)\n{\n    uint32_t a_sign, b_sign;\n\n    if (isnan_sf(a) || isnan_sf(b)) {\n        *pfflags |= FFLAG_INVALID_OP;\n        return 0;\n    }\n\n    a_sign = a >> (F_SIZE - 1);\n    b_sign = b >> (F_SIZE - 1);\n    if (a_sign != b_sign) {\n        return (a_sign || ((F_UINT)((a | b) << 1) == 0));\n    } else {\n        if (a_sign) {\n            return (a >= b);\n        } else {\n            return (a <= b);\n        }\n    }\n}\n\nint glue(lt_sf, F_SIZE)(F_UINT a, F_UINT b, uint32_t *pfflags)\n{\n    uint32_t a_sign, b_sign;\n\n    if (isnan_sf(a) || isnan_sf(b)) {\n        *pfflags |= FFLAG_INVALID_OP;\n        return 0;\n    }\n\n    a_sign = a >> (F_SIZE - 1);\n    b_sign = b >> (F_SIZE - 1);\n    if (a_sign != b_sign) {\n        return (a_sign && ((F_UINT)((a | b) << 1) != 0));\n    } else {\n        if (a_sign) {\n            return (a > b);\n        } else {\n            return (a < b);\n        }\n    }\n}\n\nuint32_t glue(fclass_sf, F_SIZE)(F_UINT a)\n{\n    uint32_t a_sign;\n    int32_t a_exp;\n    F_UINT a_mant;\n    uint32_t ret;\n\n    a_sign = a >> (F_SIZE - 1);\n    a_exp = (a >> MANT_SIZE) & EXP_MASK;\n    a_mant = a & MANT_MASK;\n    if (a_exp == EXP_MASK) {\n        if (a_mant != 0) {\n            if (a_mant & QNAN_MASK)\n                ret = FCLASS_QNAN;\n            else\n                ret = FCLASS_SNAN;\n        } else {\n            if (a_sign)\n                ret = FCLASS_NINF;\n            else\n                ret = FCLASS_PINF;\n        }\n    } else if (a_exp == 0) {\n        if (a_mant == 0) {\n            if (a_sign)\n                ret = FCLASS_NZERO;\n            else\n                ret = FCLASS_PZERO;\n        } else {\n            if (a_sign)\n                ret = FCLASS_NSUBNORMAL;\n            else\n                ret = FCLASS_PSUBNORMAL;\n        }\n    } else {\n        if (a_sign)\n            ret = FCLASS_NNORMAL;\n        else\n            ret = FCLASS_PNORMAL;\n    }\n    return ret;\n}\n\n/* conversions between floats */\n\n#if F_SIZE >= 64\n\nF_UINT cvt_sf32_sf(uint32_t a, uint32_t *pfflags)\n{\n    uint32_t a_sign;\n    int32_t a_exp;\n    F_UINT a_mant;\n\n    a_mant = unpack_sf32(&a_sign, &a_exp, a);\n    if (a_exp == 0xff) {\n        if (a_mant != 0) {\n            /* NaN */\n            if (issignan_sf32(a)) {\n                *pfflags |= FFLAG_INVALID_OP;\n            }\n            return F_QNAN;\n        } else {\n            /* infinity */\n            return pack_sf(a_sign, EXP_MASK, 0);\n        }\n    }\n    if (a_exp == 0) {\n        if (a_mant == 0)\n            return pack_sf(a_sign, 0, 0); /* zero */\n        a_mant = normalize_subnormal_sf32(&a_exp, a_mant);\n    }\n    /* convert the exponent value */\n    a_exp = a_exp - 0x7f + (EXP_MASK / 2);\n    /* shift the mantissa */\n    a_mant <<= (MANT_SIZE - 23);\n    /* We assume the target float is large enough to that no\n       normalization is necessary */\n    return pack_sf(a_sign, a_exp, a_mant);\n}\n\nuint32_t glue(glue(cvt_sf, F_SIZE), _sf32)(F_UINT a, RoundingModeEnum rm,\n                                           uint32_t *pfflags)\n{\n    uint32_t a_sign;\n    int32_t a_exp;\n    F_UINT a_mant;\n\n    a_mant = unpack_sf(&a_sign, &a_exp, a);\n    if (a_exp == EXP_MASK) {\n        if (a_mant != 0) {\n            /* NaN */\n            if (issignan_sf(a)) {\n                *pfflags |= FFLAG_INVALID_OP;\n            }\n            return F_QNAN32;\n        } else {\n            /* infinity */\n            return pack_sf32(a_sign, 0xff, 0);\n        }\n    }\n    if (a_exp == 0) {\n        if (a_mant == 0)\n            return pack_sf32(a_sign, 0, 0); /* zero */\n        normalize_subnormal_sf(&a_exp, a_mant);\n    } else {\n        a_mant |= (F_UINT)1 << MANT_SIZE;\n    }\n    /* convert the exponent value */\n    a_exp = a_exp - (EXP_MASK / 2) + 0x7f;\n    /* shift the mantissa */\n    a_mant = rshift_rnd(a_mant, MANT_SIZE - (32 - 2));\n    return normalize_sf32(a_sign, a_exp, a_mant, rm, pfflags);\n}\n\n#endif\n\n#if F_SIZE >= 128\n\nF_UINT cvt_sf64_sf(uint64_t a, uint32_t *pfflags)\n{\n    uint32_t a_sign;\n    int32_t a_exp;\n    F_UINT a_mant;\n\n    a_mant = unpack_sf64(&a_sign, &a_exp, a);\n\n    if (a_exp == 0x7ff) {\n        if (a_mant != 0) {\n            /* NaN */\n            if (issignan_sf64(a)) {\n                *pfflags |= FFLAG_INVALID_OP;\n            }\n            return F_QNAN;\n        } else {\n            /* infinity */\n            return pack_sf(a_sign, EXP_MASK, 0);\n        }\n    }\n    if (a_exp == 0) {\n        if (a_mant == 0)\n            return pack_sf(a_sign, 0, 0); /* zero */\n        a_mant = normalize_subnormal_sf64(&a_exp, a_mant);\n    }\n    /* convert the exponent value */\n    a_exp = a_exp - 0x3ff + (EXP_MASK / 2);\n    /* shift the mantissa */\n    a_mant <<= (MANT_SIZE - 52);\n    return pack_sf(a_sign, a_exp, a_mant);\n}\n\nuint64_t glue(glue(cvt_sf, F_SIZE), _sf64)(F_UINT a, RoundingModeEnum rm,\n                                               uint32_t *pfflags)\n{\n    uint32_t a_sign;\n    int32_t a_exp;\n    F_UINT a_mant;\n\n    a_mant = unpack_sf(&a_sign, &a_exp, a);\n    if (a_exp == EXP_MASK) {\n        if (a_mant != 0) {\n            /* NaN */\n            if (issignan_sf(a)) {\n                *pfflags |= FFLAG_INVALID_OP;\n            }\n            return F_QNAN64;\n        } else {\n            /* infinity */\n            return pack_sf64(a_sign, 0x7ff, 0);\n        }\n    }\n    if (a_exp == 0) {\n        if (a_mant == 0)\n            return pack_sf64(a_sign, 0, 0); /* zero */\n        normalize_subnormal_sf(&a_exp, a_mant);\n    } else {\n        a_mant |= (F_UINT)1 << MANT_SIZE;\n    }\n    /* convert the exponent value */\n    a_exp = a_exp - (EXP_MASK / 2) + 0x3ff;\n    /* shift the mantissa */\n    a_mant = rshift_rnd(a_mant, MANT_SIZE - (64 - 2));\n    return normalize_sf64(a_sign, a_exp, a_mant, rm, pfflags);\n}\n\n#endif\n\n#undef clz\n\n#define ICVT_SIZE 32\n#include \"softfp_template_icvt.h\"\n\n#define ICVT_SIZE 64\n#include \"softfp_template_icvt.h\"\n\n#ifdef HAVE_INT128\n#define ICVT_SIZE 128\n#include \"softfp_template_icvt.h\"\n#endif\n\n#undef F_SIZE\n#undef F_UINT\n#undef F_ULONG\n#undef F_UHALF\n#undef MANT_SIZE\n#undef EXP_SIZE\n#undef EXP_MASK\n#undef MANT_MASK\n#undef SIGN_MASK\n#undef IMANT_SIZE\n#undef RND_SIZE\n#undef QNAN_MASK\n#undef F_QNAN\n\n#undef pack_sf\n#undef unpack_sf\n#undef rshift_rnd\n#undef round_pack_sf\n#undef normalize_sf\n#undef normalize2_sf\n#undef issignan_sf\n#undef isnan_sf\n#undef add_sf\n#undef mul_sf\n#undef fma_sf\n#undef div_sf\n#undef sqrt_sf\n#undef normalize_subnormal_sf\n#undef divrem_u\n#undef sqrtrem_u\n#undef mul_u\n#undef cvt_sf32_sf\n#undef cvt_sf64_sf\n"
  },
  {
    "path": "src/softfp_template_icvt.h",
    "content": "/*\n * SoftFP Library\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#if ICVT_SIZE == 32\n#define ICVT_UINT uint32_t\n#define ICVT_INT int32_t\n#elif ICVT_SIZE == 64\n#define ICVT_UINT uint64_t\n#define ICVT_INT int64_t\n#elif ICVT_SIZE == 128\n#define ICVT_UINT uint128_t\n#define ICVT_INT int128_t\n#else\n#error unsupported icvt\n#endif\n\n/* conversions between float and integers */\nstatic ICVT_INT glue(glue(glue(internal_cvt_sf, F_SIZE), _i), ICVT_SIZE)(F_UINT a, RoundingModeEnum rm,\n                                                                         uint32_t *pfflags, BOOL is_unsigned)\n{\n    uint32_t a_sign, addend, rnd_bits;\n    int32_t a_exp;\n    F_UINT a_mant;\n    ICVT_UINT r, r_max;\n\n    a_sign = a >> (F_SIZE - 1);\n    a_exp = (a >> MANT_SIZE) & EXP_MASK;\n    a_mant = a & MANT_MASK;\n    if (a_exp == EXP_MASK && a_mant != 0)\n        a_sign = 0; /* NaN is like +infinity */\n    if (a_exp == 0) {\n        a_exp = 1;\n    } else {\n        a_mant |= (F_UINT)1 << MANT_SIZE;\n    }\n    a_mant <<= RND_SIZE;\n    a_exp = a_exp - (EXP_MASK / 2) - MANT_SIZE;\n\n    if (is_unsigned)\n        r_max = (ICVT_UINT)a_sign - 1;\n    else\n        r_max = ((ICVT_UINT)1 << (ICVT_SIZE - 1)) - (ICVT_UINT)(a_sign ^ 1);\n    if (a_exp >= 0) {\n        if (a_exp <= (ICVT_SIZE - 1 - MANT_SIZE)) {\n            r = (ICVT_UINT)(a_mant >> RND_SIZE) << a_exp;\n            if (r > r_max)\n                goto overflow;\n        } else {\n        overflow:\n            *pfflags |= FFLAG_INVALID_OP;\n            return r_max;\n        }\n    } else {\n        a_mant = rshift_rnd(a_mant, -a_exp);\n\n        switch(rm) {\n        case RM_RNE:\n        case RM_RMM:\n            addend = (1 << (RND_SIZE - 1));\n            break;\n        case RM_RTZ:\n            addend = 0;\n            break;\n        default:\n        case RM_RDN:\n        case RM_RUP:\n            if (a_sign ^ (rm & 1))\n                addend = (1 << RND_SIZE) - 1;\n            else\n                addend = 0;\n            break;\n        }\n        \n        rnd_bits = a_mant & ((1 << RND_SIZE ) - 1);\n        a_mant = (a_mant + addend) >> RND_SIZE;\n        /* half way: select even result */\n        if (rm == RM_RNE && rnd_bits == (1 << (RND_SIZE - 1)))\n            a_mant &= ~1;\n        if (a_mant > r_max)\n            goto overflow;\n        r = a_mant;\n        if (rnd_bits != 0)\n            *pfflags |= FFLAG_INEXACT;\n    }\n    if (a_sign)\n        r = -r;\n    return r;\n}\n\nICVT_INT glue(glue(glue(cvt_sf, F_SIZE), _i), ICVT_SIZE)(F_UINT a, RoundingModeEnum rm,\n                                                          uint32_t *pfflags)\n{\n    return glue(glue(glue(internal_cvt_sf, F_SIZE), _i), ICVT_SIZE)(a, rm, \n                                                                    pfflags, FALSE);\n}\n\nICVT_UINT glue(glue(glue(cvt_sf, F_SIZE), _u), ICVT_SIZE)(F_UINT a, RoundingModeEnum rm,\n                                                          uint32_t *pfflags)\n{\n    return glue(glue(glue(internal_cvt_sf, F_SIZE), _i), ICVT_SIZE) (a, rm, \n                                                                     pfflags, TRUE);\n}\n\n/* conversions between float and integers */\nstatic F_UINT glue(glue(glue(internal_cvt_i, ICVT_SIZE), _sf), F_SIZE)(ICVT_INT a, \n                                                                       RoundingModeEnum rm,\n                                                                       uint32_t *pfflags,\n                                                                       BOOL is_unsigned)\n{\n    uint32_t a_sign;\n    int32_t a_exp;\n    F_UINT a_mant;\n    ICVT_UINT r, mask;\n    int l;\n\n    if (!is_unsigned && a < 0) {\n        a_sign = 1;\n        r = -(ICVT_UINT)a;\n    } else {\n        a_sign = 0;\n        r = a;\n    }\n    a_exp = (EXP_MASK / 2) + F_SIZE - 2;\n    /* need to reduce range before generic float normalization */\n    l = ICVT_SIZE - glue(clz, ICVT_SIZE)(r) - (F_SIZE - 1);\n    if (l > 0) {\n        mask = r & (((ICVT_UINT)1 << l) - 1);\n        r = (r >> l) | ((r & mask) != 0);\n        a_exp += l;\n    }\n    a_mant = r;\n    return normalize_sf(a_sign, a_exp, a_mant, rm, pfflags);\n}\n\nF_UINT glue(glue(glue(cvt_i, ICVT_SIZE), _sf), F_SIZE)(ICVT_INT a, \n                                                       RoundingModeEnum rm,\n                                                       uint32_t *pfflags)\n{\n    return glue(glue(glue(internal_cvt_i, ICVT_SIZE), _sf), F_SIZE)(a, rm, pfflags, FALSE);\n}\n\nF_UINT glue(glue(glue(cvt_u, ICVT_SIZE), _sf), F_SIZE)(ICVT_UINT a, \n                                                       RoundingModeEnum rm,\n                                                       uint32_t *pfflags)\n{\n    return glue(glue(glue(internal_cvt_i, ICVT_SIZE), _sf), F_SIZE)(a, rm, pfflags, TRUE);\n}\n\n#undef ICVT_SIZE\n#undef ICVT_INT\n#undef ICVT_UINT\n"
  },
  {
    "path": "src/splitimg.c",
    "content": "/*\n * Disk image splitter\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <inttypes.h>\n#include <string.h>\n#include <ctype.h>\n#include <getopt.h>\n\nint main(int argc, char **argv)\n{\n    int blocksize, ret, i;\n    const char *infilename, *outpath;\n    FILE *f, *fo;\n    char buf1[1024];\n    uint8_t *buf;\n\n    if ((optind + 1) >= argc) {\n        printf(\"splitimg version \" CONFIG_VERSION \", Copyright (c) 2011-2016 Fabrice Bellard\\n\"\n               \"usage: splitimg infile outpath [blocksize]\\n\"\n               \"Create a multi-file disk image for the RISCVEMU HTTP block device\\n\"\n               \"\\n\"\n               \"outpath must be a directory\\n\"\n               \"blocksize is the block size in KB\\n\");\n        exit(1);\n    }\n\n    infilename = argv[optind++];\n    outpath = argv[optind++];\n    blocksize = 256;\n    if (optind < argc)\n        blocksize = strtol(argv[optind++], NULL, 0);\n\n    blocksize *= 1024;\n    \n    buf = malloc(blocksize);\n\n    f = fopen(infilename, \"rb\");\n    if (!f) {\n        perror(infilename);\n        exit(1);\n    }\n    i = 0;\n    for(;;) {\n        ret = fread(buf, 1, blocksize, f);\n        if (ret < 0) {\n            perror(\"fread\");\n            exit(1);\n        }\n        if (ret == 0)\n            break;\n        if (ret < blocksize) {\n            printf(\"warning: last block is not full\\n\");\n            memset(buf + ret, 0, blocksize - ret);\n        }\n        snprintf(buf1, sizeof(buf1), \"%s/blk%09u.bin\", outpath, i);\n        fo = fopen(buf1, \"wb\");\n        if (!fo) {\n            perror(buf1);\n            exit(1);\n        }\n        fwrite(buf, 1, blocksize, fo);\n        fclose(fo);\n        i++;\n    }\n    fclose(f);\n    printf(\"%d blocks\\n\", i);\n\n    snprintf(buf1, sizeof(buf1), \"%s/blk.txt\", outpath);\n    fo = fopen(buf1, \"wb\");\n    if (!fo) {\n        perror(buf1);\n        exit(1);\n    }\n    fprintf(fo, \"{\\n\");\n    fprintf(fo, \"  block_size: %d,\\n\", blocksize / 1024);\n    fprintf(fo, \"  n_block: %d,\\n\", i);\n    fprintf(fo, \"}\\n\");\n    fclose(fo);\n    return 0;\n}\n"
  },
  {
    "path": "src/stats_display.c",
    "content": "/*\n * Terminal based Simulation Statistics Viewer\n *\n * MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\n *\n * Copyright (c) 2017-2020 Gaurav Kothari {gkothar1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018-2019 Parikshit Sarnaik {psarnai1@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Copyright (c) 2018 Göktürk Yüksek {gokturk@binghamton.edu}\n * State University of New York at Binghamton\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <errno.h>\n#include <fcntl.h>\n#include <inttypes.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <time.h>\n#include <unistd.h>\n\n#include \"riscvsim/utils/sim_params.h\"\n#include \"riscvsim/utils/sim_stats.h\"\n\n#define GET_TOTAL_STAT(attr) (s[0].attr + s[1].attr + s[2].attr + s[3].attr)\n\nstatic int stats_shm_fd;\nstatic SimStats *s;\nstatic const char *stats_shm_name;\n\nstatic void\nsetup_connection()\n{\n    unsigned long nsec_passed = 0;\n    unsigned noent_print = 0;\nretry:\n    stats_shm_fd = shm_open(stats_shm_name, O_RDWR, 0);\n    if (stats_shm_fd < 0)\n    {\n        if (errno == ENOENT)\n        {\n            const unsigned long nsec = 1000000;\n            struct timespec ts = {.tv_sec = 0, .tv_nsec = nsec};\n            if (noent_print == 0)\n            {\n                fprintf(stderr, \"cannot open shm %s,\"\n                                \" retrying every %ld nanoseconds \",\n                        stats_shm_name, nsec);\n                ++noent_print;\n            }\n            else if (nsec_passed > 1000000000)\n            {\n                fprintf(stderr, \".\");\n                ++noent_print;\n                nsec_passed = 0;\n            }\n            nsec_passed += nsec;\n            nanosleep(&ts, NULL);\n            goto retry;\n        }\n        else\n        {\n            perror(\"setup_connection(): \"\n                   \"Unable to establish the shared memory\");\n            exit(errno);\n        }\n    }\n    if (noent_print)\n        fprintf(stderr, \"\\n\");\n    if ((s = (SimStats *)mmap(NULL, NUM_MAX_PRV_LEVELS * sizeof(SimStats),\n                              PROT_READ | PROT_WRITE, MAP_SHARED, stats_shm_fd,\n                              0))\n        == MAP_FAILED)\n    {\n        fprintf(stderr, \"cannot mmap shm %s:\", stats_shm_name);\n    }\n    fprintf(stderr, \"memory attached at %p\\n\", s);\n}\n\nstatic void\nprint_header()\n{\n    printf(\"%s\\n\",\n           \"MARSS-RISCV : Micro-Architectural System Simulator for RISC-V\");\n    printf(\"%s\\n\", \"Terminal based Simulation Statistics Viewer\");\n}\n\nstatic void\nprint_usage(const char *prog_name)\n{\n    printf(\"usage: %s <posix-shared-mem-name>\\n\", prog_name);\n}\n\nstatic void\nprint_ins_stats()\n{\n    uint64_t cycles = GET_TOTAL_STAT(cycles);\n    uint64_t commits = GET_TOTAL_STAT(ins_simulated);\n    uint64_t fetches = GET_TOTAL_STAT(ins_fetch);\n    uint64_t flushed = fetches - commits;\n\n    printf(\"%-22s : %0.2lf\\n\", \"ipc\", ((double)commits / (double)cycles));\n    printf(\"%-22s : %-22\" PRIu64 \"\\n\", \"cycles\", cycles);\n    printf(\"%-22s : %-22\" PRIu64 \"\\n\", \"total-commits\", commits);\n    printf(\"%-22s : %-22\" PRIu64 \"\\n\", \"total-fetches\", fetches);\n    printf(\"%-22s : %-22\" PRIu64 \" (%0.2lf %%)\\n\", \"insn-flushed\", flushed,\n           (((double)flushed / (double)fetches)) * 100);\n    printf(\"\\n\");\n}\n\nstatic void\nprint_bpu_stats()\n{\n    uint64_t btb_probes = GET_TOTAL_STAT(btb_probes);\n    uint64_t btb_hits = GET_TOTAL_STAT(btb_hits);\n    uint64_t correct_pred\n        = GET_TOTAL_STAT(bpu_cond_correct) + GET_TOTAL_STAT(bpu_uncond_correct);\n    uint64_t incorrect_pred = GET_TOTAL_STAT(bpu_cond_incorrect)\n                              + GET_TOTAL_STAT(bpu_uncond_incorrect);\n    uint64_t total_branches = GET_TOTAL_STAT(ins_type[INS_TYPE_COND_BRANCH])\n                              + GET_TOTAL_STAT(ins_type[INS_TYPE_JAL])\n                              + GET_TOTAL_STAT(ins_type[INS_TYPE_JALR]);\n\n    printf(\"%-22s : %-22\" PRIu64 \"\\n\", \"btb-probes\", btb_probes);\n    printf(\"%-22s : %-22\" PRIu64 \" (%0.2lf %%)\\n\", \"btb-hits\", btb_hits,\n           ((double)btb_hits / (double)btb_probes) * 100);\n    printf(\"%-22s : %-22\" PRIu64 \" (%0.2lf %%)\\n\", \"correct-predictions\",\n           correct_pred, ((double)correct_pred / (double)total_branches) * 100);\n    printf(\"%-22s : %-22\" PRIu64 \" (%0.2lf %%)\\n\", \"miss-predictions\",\n           incorrect_pred,\n           ((double)incorrect_pred / (double)total_branches) * 100);\n    printf(\"\\n\");\n}\n\nstatic void\nprint_tlb_stats()\n{\n    uint64_t code_tlb_hits = GET_TOTAL_STAT(code_tlb_hits);\n    uint64_t load_tlb_hits = GET_TOTAL_STAT(load_tlb_hits);\n    uint64_t store_tlb_hits = GET_TOTAL_STAT(store_tlb_hits);\n\n    printf(\"%-22s : %-22\" PRIu64 \" (%0.2lf %%)\\n\", \"itlb-hits\", code_tlb_hits,\n           ((double)code_tlb_hits / (double)GET_TOTAL_STAT(code_tlb_lookups))\n               * 100);\n\n    printf(\"%-22s : %-22\" PRIu64 \" (%0.2lf %%)\\n\", \"load-tlb-hits\",\n           load_tlb_hits,\n           ((double)load_tlb_hits / (double)GET_TOTAL_STAT(load_tlb_lookups))\n               * 100);\n\n    printf(\"%-22s : %-22\" PRIu64 \" (%0.2lf %%)\\n\", \"store-tlb-hits\",\n           store_tlb_hits,\n           ((double)store_tlb_hits / (double)GET_TOTAL_STAT(store_tlb_lookups))\n               * 100);\n\n    printf(\"\\n\");\n}\n\nstatic void\nprint_caches_stats()\n{\n    uint64_t icache_hit\n        = GET_TOTAL_STAT(icache_read) - GET_TOTAL_STAT(icache_read_miss);\n    uint64_t dcache_read_hit\n        = GET_TOTAL_STAT(dcache_read) - GET_TOTAL_STAT(dcache_read_miss);\n    uint64_t dcache_write_hit\n        = GET_TOTAL_STAT(dcache_write) - GET_TOTAL_STAT(dcache_write_miss);\n    uint64_t l2_cache_read_hit\n        = GET_TOTAL_STAT(l2_cache_read) - GET_TOTAL_STAT(l2_cache_read_miss);\n    uint64_t l2_cache_write_hit\n        = GET_TOTAL_STAT(l2_cache_write) - GET_TOTAL_STAT(l2_cache_write_miss);\n\n    printf(\"%-22s : %-22\" PRIu64 \" (%0.2lf %%)\\n\", \"icache-hits\", icache_hit,\n           ((double)icache_hit / (double)GET_TOTAL_STAT(icache_read)) * 100);\n\n    printf(\"%-22s : %-22\" PRIu64 \" (%0.2lf %%)\\n\", \"dcache-read-hits\",\n           dcache_read_hit,\n           ((double)dcache_read_hit / (double)GET_TOTAL_STAT(dcache_read))\n               * 100);\n\n    printf(\"%-22s : %-22\" PRIu64 \" (%0.2lf %%)\\n\", \"dcache-write-hits\",\n           dcache_write_hit,\n           ((double)dcache_write_hit / (double)GET_TOTAL_STAT(dcache_write))\n               * 100);\n\n    printf(\"%-22s : %-22\" PRIu64 \" (%0.2lf %%)\\n\", \"l2-shared-read-hits\",\n           l2_cache_read_hit,\n           ((double)l2_cache_read_hit / (double)GET_TOTAL_STAT(l2_cache_read))\n               * 100);\n\n    printf(\"%-22s : %-22\" PRIu64 \" (%0.2lf %%)\\n\", \"l2-shared-write-hits\",\n           l2_cache_write_hit,\n           ((double)l2_cache_write_hit / (double)GET_TOTAL_STAT(l2_cache_write))\n               * 100);\n\n    printf(\"\\n\");\n}\n\nint\nmain(int argc, char const *argv[])\n{\n\n    if (argc != 2)\n    {\n        print_usage(argv[0]);\n        exit(0);\n    }\n\n    stats_shm_name = argv[1];\n\n    setup_connection();\n    while (1)\n    {\n        /* Clear to the end of screen */\n        printf(\"\\033[H\"\n               \"\\033[J\");\n\n        print_header();\n        print_ins_stats();\n        print_bpu_stats();\n        print_tlb_stats();\n        print_caches_stats();\n        usleep(100000);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "src/temu.c",
    "content": "/*\n * TinyEMU\n * \n * Copyright (c) 2016-2018 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <unistd.h>\n#include <time.h>\n#include <getopt.h>\n#ifndef _WIN32\n#include <termios.h>\n#include <sys/ioctl.h>\n#include <net/if.h>\n#include <linux/if_tun.h>\n#endif\n#include <sys/stat.h>\n#include <signal.h>\n\n#include \"cutils.h\"\n#include \"iomem.h\"\n#include \"virtio.h\"\n#include \"machine.h\"\n#ifdef CONFIG_FS_NET\n#include \"fs_utils.h\"\n#include \"fs_wget.h\"\n#endif\n#ifdef CONFIG_SLIRP\n#include \"slirp/libslirp.h\"\n#endif\n\n#include \"riscvsim/utils/sim_params.h\"\n#include \"riscvsim/utils/sim_log.h\"\n\n#ifndef _WIN32\ntypedef struct {\n    int stdin_fd;\n    int console_esc_state;\n    BOOL resize_pending;\n} STDIODevice;\n\nstatic struct termios oldtty;\nstatic int old_fd0_flags;\nstatic STDIODevice *global_stdio_device;\n\nstatic void term_exit(void)\n{\n    tcsetattr (0, TCSANOW, &oldtty);\n    fcntl(0, F_SETFL, old_fd0_flags);\n}\n\nstatic void term_init(BOOL allow_ctrlc)\n{\n    struct termios tty;\n\n    memset(&tty, 0, sizeof(tty));\n    tcgetattr (0, &tty);\n    oldtty = tty;\n    old_fd0_flags = fcntl(0, F_GETFL);\n\n    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP\n                          |INLCR|IGNCR|ICRNL|IXON);\n    tty.c_oflag |= OPOST;\n    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);\n    if (!allow_ctrlc)\n        tty.c_lflag &= ~ISIG;\n    tty.c_cflag &= ~(CSIZE|PARENB);\n    tty.c_cflag |= CS8;\n    tty.c_cc[VMIN] = 1;\n    tty.c_cc[VTIME] = 0;\n\n    tcsetattr (0, TCSANOW, &tty);\n\n    atexit(term_exit);\n}\n\nstatic void console_write(void *opaque, const uint8_t *buf, int len)\n{\n    fwrite(buf, 1, len, stdout);\n    fflush(stdout);\n}\n\nstatic int console_read(void *opaque, uint8_t *buf, int len)\n{\n    STDIODevice *s = opaque;\n    int ret, i, j;\n    uint8_t ch;\n    \n    if (len <= 0)\n        return 0;\n\n    ret = read(s->stdin_fd, buf, len);\n    if (ret < 0)\n        return 0;\n    if (ret == 0) {\n        /* EOF */\n        exit(1);\n    }\n\n    j = 0;\n    for(i = 0; i < ret; i++) {\n        ch = buf[i];\n        if (s->console_esc_state) {\n            s->console_esc_state = 0;\n            switch(ch) {\n            case 'x':\n                printf(\"Terminated\\n\");\n                exit(0);\n            case 'h':\n                printf(\"\\n\"\n                       \"C-a h   print this help\\n\"\n                       \"C-a x   exit emulator\\n\"\n                       \"C-a C-a send C-a\\n\"\n                       );\n                break;\n            case 1:\n                goto output_char;\n            default:\n                break;\n            }\n        } else {\n            if (ch == 1) {\n                s->console_esc_state = 1;\n            } else {\n            output_char:\n                buf[j++] = ch;\n            }\n        }\n    }\n    return j;\n}\n\nstatic void term_resize_handler(int sig)\n{\n    if (global_stdio_device)\n        global_stdio_device->resize_pending = TRUE;\n}\n\nstatic void console_get_size(STDIODevice *s, int *pw, int *ph)\n{\n    struct winsize ws;\n    int width, height;\n    /* default values */\n    width = 80;\n    height = 25;\n    if (ioctl(s->stdin_fd, TIOCGWINSZ, &ws) == 0 &&\n        ws.ws_col >= 4 && ws.ws_row >= 4) {\n        width = ws.ws_col;\n        height = ws.ws_row;\n    }\n    *pw = width;\n    *ph = height;\n}\n\nCharacterDevice *console_init(BOOL allow_ctrlc)\n{\n    CharacterDevice *dev;\n    STDIODevice *s;\n    struct sigaction sig;\n\n    term_init(allow_ctrlc);\n\n    dev = mallocz(sizeof(*dev));\n    s = mallocz(sizeof(*s));\n    s->stdin_fd = 0;\n    /* Note: the glibc does not properly tests the return value of\n       write() in printf, so some messages on stdout may be lost */\n    fcntl(s->stdin_fd, F_SETFL, O_NONBLOCK);\n\n    s->resize_pending = TRUE;\n    global_stdio_device = s;\n    \n    /* use a signal to get the host terminal resize events */\n    sig.sa_handler = term_resize_handler;\n    sigemptyset(&sig.sa_mask);\n    sig.sa_flags = 0;\n    sigaction(SIGWINCH, &sig, NULL);\n    \n    dev->opaque = s;\n    dev->write_data = console_write;\n    dev->read_data = console_read;\n    return dev;\n}\n\n#endif /* !_WIN32 */\n\ntypedef enum {\n    BF_MODE_RO,\n    BF_MODE_RW,\n    BF_MODE_SNAPSHOT,\n} BlockDeviceModeEnum;\n\n#define SECTOR_SIZE 512\n\ntypedef struct BlockDeviceFile {\n    FILE *f;\n    int64_t nb_sectors;\n    BlockDeviceModeEnum mode;\n    uint8_t **sector_table;\n} BlockDeviceFile;\n\nstatic int64_t bf_get_sector_count(BlockDevice *bs)\n{\n    BlockDeviceFile *bf = bs->opaque;\n    return bf->nb_sectors;\n}\n\n//#define DUMP_BLOCK_READ\n\nstatic int bf_read_async(BlockDevice *bs,\n                         uint64_t sector_num, uint8_t *buf, int n,\n                         BlockDeviceCompletionFunc *cb, void *opaque)\n{\n    BlockDeviceFile *bf = bs->opaque;\n    //    printf(\"bf_read_async: sector_num=%\" PRId64 \" n=%d\\n\", sector_num, n);\n#ifdef DUMP_BLOCK_READ\n    {\n        static FILE *f;\n        if (!f)\n            f = fopen(\"/tmp/read_sect.txt\", \"wb\");\n        fprintf(f, \"%\" PRId64 \" %d\\n\", sector_num, n);\n    }\n#endif\n    if (!bf->f)\n        return -1;\n    if (bf->mode == BF_MODE_SNAPSHOT) {\n        int i;\n        for(i = 0; i < n; i++) {\n            if (!bf->sector_table[sector_num]) {\n                fseek(bf->f, sector_num * SECTOR_SIZE, SEEK_SET);\n                fread(buf, 1, SECTOR_SIZE, bf->f);\n            } else {\n                memcpy(buf, bf->sector_table[sector_num], SECTOR_SIZE);\n            }\n            sector_num++;\n            buf += SECTOR_SIZE;\n        }\n    } else {\n        fseek(bf->f, sector_num * SECTOR_SIZE, SEEK_SET);\n        fread(buf, 1, n * SECTOR_SIZE, bf->f);\n    }\n    /* synchronous read */\n    return 0;\n}\n\nstatic int bf_write_async(BlockDevice *bs,\n                          uint64_t sector_num, const uint8_t *buf, int n,\n                          BlockDeviceCompletionFunc *cb, void *opaque)\n{\n    BlockDeviceFile *bf = bs->opaque;\n    int ret;\n\n    switch(bf->mode) {\n    case BF_MODE_RO:\n        ret = -1; /* error */\n        break;\n    case BF_MODE_RW:\n        fseek(bf->f, sector_num * SECTOR_SIZE, SEEK_SET);\n        fwrite(buf, 1, n * SECTOR_SIZE, bf->f);\n        ret = 0;\n        break;\n    case BF_MODE_SNAPSHOT:\n        {\n            int i;\n            if ((sector_num + n) > bf->nb_sectors)\n                return -1;\n            for(i = 0; i < n; i++) {\n                if (!bf->sector_table[sector_num]) {\n                    bf->sector_table[sector_num] = malloc(SECTOR_SIZE);\n                }\n                memcpy(bf->sector_table[sector_num], buf, SECTOR_SIZE);\n                sector_num++;\n                buf += SECTOR_SIZE;\n            }\n            ret = 0;\n        }\n        break;\n    default:\n        abort();\n    }\n\n    return ret;\n}\n\nstatic BlockDevice *block_device_init(const char *filename,\n                                      BlockDeviceModeEnum mode)\n{\n    BlockDevice *bs;\n    BlockDeviceFile *bf;\n    int64_t file_size;\n    FILE *f;\n    const char *mode_str;\n\n    if (mode == BF_MODE_RW) {\n        mode_str = \"r+b\";\n    } else {\n        mode_str = \"rb\";\n    }\n    \n    f = fopen(filename, mode_str);\n    if (!f) {\n        perror(filename);\n        exit(1);\n    }\n    fseek(f, 0, SEEK_END);\n    file_size = ftello(f);\n\n    bs = mallocz(sizeof(*bs));\n    bf = mallocz(sizeof(*bf));\n\n    bf->mode = mode;\n    bf->nb_sectors = file_size / 512;\n    bf->f = f;\n\n    if (mode == BF_MODE_SNAPSHOT) {\n        bf->sector_table = mallocz(sizeof(bf->sector_table[0]) *\n                                   bf->nb_sectors);\n    }\n    \n    bs->opaque = bf;\n    bs->get_sector_count = bf_get_sector_count;\n    bs->read_async = bf_read_async;\n    bs->write_async = bf_write_async;\n    return bs;\n}\n\n#ifndef _WIN32\n\ntypedef struct {\n    int fd;\n    BOOL select_filled;\n} TunState;\n\nstatic void tun_write_packet(EthernetDevice *net,\n                             const uint8_t *buf, int len)\n{\n    TunState *s = net->opaque;\n    write(s->fd, buf, len);\n}\n\nstatic void tun_select_fill(EthernetDevice *net, int *pfd_max,\n                            fd_set *rfds, fd_set *wfds, fd_set *efds,\n                            int *pdelay)\n{\n    TunState *s = net->opaque;\n    int net_fd = s->fd;\n\n    s->select_filled = net->device_can_write_packet(net);\n    if (s->select_filled) {\n        FD_SET(net_fd, rfds);\n        *pfd_max = max_int(*pfd_max, net_fd);\n    }\n}\n\nstatic void tun_select_poll(EthernetDevice *net, \n                            fd_set *rfds, fd_set *wfds, fd_set *efds,\n                            int select_ret)\n{\n    TunState *s = net->opaque;\n    int net_fd = s->fd;\n    uint8_t buf[2048];\n    int ret;\n    \n    if (select_ret <= 0)\n        return;\n    if (s->select_filled && FD_ISSET(net_fd, rfds)) {\n        ret = read(net_fd, buf, sizeof(buf));\n        if (ret > 0)\n            net->device_write_packet(net, buf, ret);\n    }\n    \n}\n\n/* configure with:\n# bridge configuration (connect tap0 to bridge interface br0)\n   ip link add br0 type bridge\n   ip tuntap add dev tap0 mode tap [user x] [group x]\n   ip link set tap0 master br0\n   ip link set dev br0 up\n   ip link set dev tap0 up\n\n# NAT configuration (eth1 is the interface connected to internet)\n   ifconfig br0 192.168.3.1\n   echo 1 > /proc/sys/net/ipv4/ip_forward\n   iptables -D FORWARD 1\n   iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE\n\n   In the VM:\n   ifconfig eth0 192.168.3.2\n   route add -net 0.0.0.0 netmask 0.0.0.0 gw 192.168.3.1\n*/\nstatic EthernetDevice *tun_open(const char *ifname)\n{\n    struct ifreq ifr;\n    int fd, ret;\n    EthernetDevice *net;\n    TunState *s;\n    \n    fd = open(\"/dev/net/tun\", O_RDWR);\n    if (fd < 0) {\n        fprintf(stderr, \"Error: could not open /dev/net/tun\\n\");\n        return NULL;\n    }\n    memset(&ifr, 0, sizeof(ifr));\n    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;\n    pstrcpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);\n    ret = ioctl(fd, TUNSETIFF, (void *) &ifr);\n    if (ret != 0) {\n        fprintf(stderr, \"Error: could not configure /dev/net/tun\\n\");\n        close(fd);\n        return NULL;\n    }\n    fcntl(fd, F_SETFL, O_NONBLOCK);\n\n    net = mallocz(sizeof(*net));\n    net->mac_addr[0] = 0x02;\n    net->mac_addr[1] = 0x00;\n    net->mac_addr[2] = 0x00;\n    net->mac_addr[3] = 0x00;\n    net->mac_addr[4] = 0x00;\n    net->mac_addr[5] = 0x01;\n    s = mallocz(sizeof(*s));\n    s->fd = fd;\n    net->opaque = s;\n    net->write_packet = tun_write_packet;\n    net->select_fill = tun_select_fill;\n    net->select_poll = tun_select_poll;\n    return net;\n}\n\n#endif /* !_WIN32 */\n\n#ifdef CONFIG_SLIRP\n\n/*******************************************************/\n/* slirp */\n\nstatic Slirp *slirp_state;\n\nstatic void slirp_write_packet(EthernetDevice *net,\n                               const uint8_t *buf, int len)\n{\n    Slirp *slirp_state = net->opaque;\n    slirp_input(slirp_state, buf, len);\n}\n\nint slirp_can_output(void *opaque)\n{\n    EthernetDevice *net = opaque;\n    return net->device_can_write_packet(net);\n}\n\nvoid slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)\n{\n    EthernetDevice *net = opaque;\n    return net->device_write_packet(net, pkt, pkt_len);\n}\n\nstatic void slirp_select_fill1(EthernetDevice *net, int *pfd_max,\n                               fd_set *rfds, fd_set *wfds, fd_set *efds,\n                               int *pdelay)\n{\n    Slirp *slirp_state = net->opaque;\n    slirp_select_fill(slirp_state, pfd_max, rfds, wfds, efds);\n}\n\nstatic void slirp_select_poll1(EthernetDevice *net, \n                               fd_set *rfds, fd_set *wfds, fd_set *efds,\n                               int select_ret)\n{\n    Slirp *slirp_state = net->opaque;\n    slirp_select_poll(slirp_state, rfds, wfds, efds, (select_ret <= 0));\n}\n\nstatic EthernetDevice *slirp_open(void)\n{\n    EthernetDevice *net;\n    struct in_addr net_addr  = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */\n    struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 */\n    struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */\n    struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */\n    struct in_addr dns  = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */\n    const char *bootfile = NULL;\n    const char *vhostname = NULL;\n    int restricted = 0;\n    \n    if (slirp_state) {\n        fprintf(stderr, \"Only a single slirp instance is allowed\\n\");\n        return NULL;\n    }\n    net = mallocz(sizeof(*net));\n\n    slirp_state = slirp_init(restricted, net_addr, mask, host, vhostname,\n                             \"\", bootfile, dhcp, dns, net);\n    \n    net->mac_addr[0] = 0x02;\n    net->mac_addr[1] = 0x00;\n    net->mac_addr[2] = 0x00;\n    net->mac_addr[3] = 0x00;\n    net->mac_addr[4] = 0x00;\n    net->mac_addr[5] = 0x01;\n    net->opaque = slirp_state;\n    net->write_packet = slirp_write_packet;\n    net->select_fill = slirp_select_fill1;\n    net->select_poll = slirp_select_poll1;\n    \n    return net;\n}\n\n#endif /* CONFIG_SLIRP */\n\n#define MAX_EXEC_CYCLE 500000\n#define MAX_SLEEP_TIME 10 /* in ms */\n\nvoid virt_machine_run(VirtMachine *m)\n{\n    fd_set rfds, wfds, efds;\n    int fd_max, ret, delay;\n    struct timeval tv;\n#ifndef _WIN32\n    int stdin_fd;\n#endif\n    \n    delay = virt_machine_get_sleep_duration(m, MAX_SLEEP_TIME);\n    \n    /* wait for an event */\n    FD_ZERO(&rfds);\n    FD_ZERO(&wfds);\n    FD_ZERO(&efds);\n    fd_max = -1;\n#ifndef _WIN32\n    if (m->console_dev && (uart_can_rx(m) || virtio_console_can_write_data(m->console_dev))) {\n        STDIODevice *s = m->console->opaque;\n        stdin_fd = s->stdin_fd;\n        FD_SET(stdin_fd, &rfds);\n        fd_max = stdin_fd;\n\n        if (s->resize_pending && virtio_console_can_write_data(m->console_dev)) {\n            int width, height;\n            console_get_size(s, &width, &height);\n            virtio_console_resize_event(m->console_dev, width, height);\n            s->resize_pending = FALSE;\n        }\n    }\n#endif\n    if (m->net) {\n        m->net->select_fill(m->net, &fd_max, &rfds, &wfds, &efds, &delay);\n    }\n#ifdef CONFIG_FS_NET\n    fs_net_set_fdset(&fd_max, &rfds, &wfds, &efds, &delay);\n#endif\n    tv.tv_sec = delay / 1000;\n    tv.tv_usec = (delay % 1000) * 1000;\n    ret = select(fd_max + 1, &rfds, &wfds, &efds, &tv);\n    if (m->net) {\n        m->net->select_poll(m->net, &rfds, &wfds, &efds, ret);\n    }\n    if (ret > 0) {\n#ifndef _WIN32\n        if (m->console_dev && FD_ISSET(stdin_fd, &rfds)) {\n            uint8_t buf[128];\n            int ret, len = sizeof(buf), ulen = uart_can_rx(m);\n            if (virtio_console_can_write_data(m->console_dev))\n                len = min_int(len, virtio_console_get_write_len(m->console_dev));\n            if (ulen)\n                len = min_int(len, ulen);\n            ret = m->console->read_data(m->console->opaque, buf, len);\n            if (ret > 0) {\n                uart_rx_data(m, buf, ret);\n                if (virtio_console_can_write_data(m->console_dev))\n                    virtio_console_write_data(m->console_dev, buf, ret);\n            }\n        }\n#endif\n    }\n\n#ifdef CONFIG_SDL\n    sdl_refresh(m);\n#endif\n    \n    virt_machine_interp(m, MAX_EXEC_CYCLE);\n}\n\n/*******************************************************/\n\nstatic struct option options[] = {\n    {\"help\", no_argument, NULL, 'h'},\n    {\"ctrlc\", no_argument},\n    {\"rw\", no_argument},\n    {\"ro\", no_argument},\n    {\"append\", required_argument},\n    {\"no-accel\", no_argument},\n    {\"simstart\", no_argument},\n    {\"sim-stats-display\", required_argument},\n    {\"sim-mem-model\", required_argument},\n    {\"build-preload\", required_argument},\n    {\"sim-flush-mem\", no_argument},\n    {\"sim-flush-bpu\", no_argument},\n    {\"sim-trace\", no_argument},\n    {\"sim-file-path\", required_argument},\n    {\"sim-file-prefix\", required_argument},\n    {\"sim-stop-after-icount\", required_argument},\n    {NULL},\n};\n\nvoid help(void)\n{\n    printf(\"marss-riscv version \" CONFIG_VERSION \", Copyright (c) 2017-2020 Gaurav Kothari, Parikshit Sarnaik, Gokturk Yuksek\\n\"\n           \"temu version 2018-09-23, Copyright (c) 2016-2017 Fabrice Bellard\\n\"\n           \"usage: marss-riscv [options] config_file\\n\"\n           \"options are:\\n\"\n           \"-m ram_size                         set the RAM size in MB\\n\"\n           \"-rw                                 allow write access to the disk image (default=snapshot)\\n\"\n           \"-ctrlc                              the C-c key stops the emulator instead of being sent to the\\n\"\n           \"                                    emulated software\\n\"\n           \"-append cmdline                     append cmdline to the kernel command line\\n\"\n           \"-simstart                           start (boot kernel) in simulation mode\\n\"\n           \"-sim-stats-display [posix-shm-name] dump simulation performance stats to a shared memory location <posix-shm-name>, read by sim-stats-display tool\\n\"\n           \"-sim-mem-model [base,\\n\"\n           \"                dramsim3,\\n\"\n           \"                ramulator]          type of simulated memory model\\n\"\n           \"-sim-flush-mem                      flush simulator memory hierarchy on every new simulation run\\n\"\n           \"-sim-flush-bpu                      flush branch prediction unit on every new simulation run\\n\"\n           \"-sim-trace                          generate instruction commit trace in [trace-file-name] during simulation\\n\"\n           \"-sim-file-path [directory path]     path of the directory to store stats, log, and trace file\\n\"\n           \"-sim-file-prefix [prefix]           prefix appended to stats, log, and trace file names\\n\"\n           \"-sim-emulate-after-icount [icount]  switch to emulation mode after simulating icount instructions every time simulation starts\\n\"\n           \"\\n\"\n           \"Console keys:\\n\"\n           \"Press C-a x to exit the emulator, C-a h to get some help.\\n\");\n    exit(1);\n}\n\n#ifdef CONFIG_FS_NET\nstatic BOOL net_completed;\n\nstatic void net_start_cb(void *arg)\n{\n    net_completed = TRUE;\n}\n\nstatic BOOL net_poll_cb(void *arg)\n{\n    return net_completed;\n}\n\n#endif\n\nint main(int argc, char **argv)\n{\n    VirtMachine *s;\n    char sim_log_file_name[1024];\n    const char *path, *cmdline, *build_preload_file;\n    char *sim_file_path = NULL, *sim_file_prefix = NULL, *sim_stats_shm_name = NULL;\n    int c, option_index, i, ram_size, accel_enable;\n    BOOL allow_ctrlc;\n    BlockDeviceModeEnum drive_mode;\n    VirtMachineParams p_s, *p = &p_s;\n    int marss_start_in_sim = FALSE;\n    int marss_stats_display = FALSE;\n    int marss_mem_model = MEM_MODEL_BASE;\n    int marss_flush_sim_mem_on_simstart = FALSE;\n    int marss_do_sim_trace = FALSE;\n    int marss_flush_bpu_on_simstart = FALSE;\n    uint64_t marss_sim_emulate_after_icount = 0;\n\n    ram_size = -1;\n    allow_ctrlc = FALSE;\n    (void)allow_ctrlc;\n    drive_mode = BF_MODE_SNAPSHOT;\n    accel_enable = -1;\n    cmdline = NULL;\n    build_preload_file = NULL;\n    for(;;) {\n        c = getopt_long_only(argc, argv, \"hm:\", options, &option_index);\n        if (c == -1)\n            break;\n        switch(c) {\n        case 0:\n            switch(option_index) {\n            case 1: /* ctrlc */\n                allow_ctrlc = TRUE;\n                break;\n            case 2: /* rw */\n                drive_mode = BF_MODE_RW;\n                break;\n            case 3: /* ro */\n                drive_mode = BF_MODE_RO;\n                break;\n            case 4: /* append */\n                cmdline = optarg;\n                break;\n            case 5: /* no-accel */\n                accel_enable = FALSE;\n                break;\n            case 6: /* simstart */\n                marss_start_in_sim = TRUE;\n                break;\n            case 7: /* sim-stats-display */\n                marss_stats_display = TRUE;\n                sim_stats_shm_name = optarg;\n                break;\n            case 8: /* sim-mem-model */\n                if (strcmp(optarg, \"base\") == 0)\n                {\n                    marss_mem_model = MEM_MODEL_BASE;\n                }\n                else if (strcmp(optarg, \"dramsim3\") == 0)\n                {\n                    marss_mem_model = MEM_MODEL_DRAMSIM;\n                }\n                else if (strcmp(optarg, \"ramulator\") == 0)\n                {\n                    marss_mem_model = MEM_MODEL_RAMULATOR;\n                }\n                else\n                {\n                    fprintf(stderr, \"unknown sim-mem-model type, see help\\n\");\n                    exit(1);\n                }\n                break;\n            case 9: /* build-preload */\n                build_preload_file = optarg;\n                break;\n            case 10: /* sim-flush-mem */\n                marss_flush_sim_mem_on_simstart = TRUE;\n                break;\n            case 11: /* sim-flush-bpu */\n                marss_flush_bpu_on_simstart = TRUE;\n                break;\n            case 12: /* sim-trace */\n                marss_do_sim_trace = TRUE;\n                break;\n            case 13: /* sim-file-path */\n                sim_file_path = optarg;\n                break;\n            case 14: /* sim-file-prefix */\n                sim_file_prefix = optarg;\n                break;\n            case 15: /* sim-stop-after-icount */\n                marss_sim_emulate_after_icount = strtoll(optarg, NULL, 10);\n                break;\n            default:\n                fprintf(stderr, \"unknown option index: %d\\n\", option_index);\n                exit(1);\n            }\n            break;\n        case 'h':\n            help();\n            break;\n        case 'm':\n            ram_size = strtoul(optarg, NULL, 0);\n            break;\n        default:\n            exit(1);\n        }\n    }\n\n    if (optind >= argc) {\n        help();\n    }\n\n    path = argv[optind++];\n\n    /* Setup default TinyEMU and simulation parameters */\n    virt_machine_set_defaults(p);\n\n    /* Override default simulation parameters with latest command-line options */\n    p->sim_params->start_in_sim = marss_start_in_sim;\n    p->sim_params->enable_stats_display = marss_stats_display;\n    p->sim_params->flush_sim_mem_on_simstart = marss_flush_sim_mem_on_simstart;\n    p->sim_params->flush_bpu_on_simstart = marss_flush_bpu_on_simstart;\n    p->sim_params->do_sim_trace = marss_do_sim_trace;\n    p->sim_params->sim_emulate_after_icount = marss_sim_emulate_after_icount;\n    p->sim_params->dram_model_type = marss_mem_model;\n\n    if (sim_file_path) {\n        free(p->sim_params->sim_file_path);\n        p->sim_params->sim_file_path = strdup(sim_file_path);\n    }\n\n    if (sim_file_prefix) {\n        free(p->sim_params->sim_file_prefix);\n        p->sim_params->sim_file_prefix = strdup(sim_file_prefix);\n    }\n\n    if (sim_stats_shm_name) {\n        free(p->sim_params->sim_stats_shm_name);\n        p->sim_params->sim_stats_shm_name = strdup(sim_stats_shm_name);\n    }\n\n    /* Create the log-file full name */\n    strcpy(sim_log_file_name, p->sim_params->sim_file_path);\n    strcat(sim_log_file_name, \"/\");\n    strcat(sim_log_file_name, p->sim_params->sim_file_prefix);\n    strcat(sim_log_file_name, \".log\");\n    free(p->sim_params->sim_log_file);\n    p->sim_params->sim_log_file = strdup(sim_log_file_name);\n\n    /* Initialize simulator logging file */\n    sim_log = sim_log_init(p->sim_params->sim_log_file);\n\n    if (!sim_log->log_fp)\n    {\n        sim_log_event_to_terminal(\"directory %s does not exists\",\n                                  sim_file_path);\n        abort();\n    }\n\n    sim_log_event(sim_log, \"%s\", SIM_PROG_TITLE);\n    sim_log_event(sim_log, \"Created log file: %s\", p->sim_params->sim_log_file);\n\n#ifdef CONFIG_FS_NET\n    fs_wget_init();\n#endif\n    virt_machine_load_config_file(p, path, NULL, NULL);\n#ifdef CONFIG_FS_NET\n    fs_net_event_loop(NULL, NULL);\n#endif\n\n    /* override some config parameters */\n\n    if (ram_size > 0) {\n        p->ram_size = (uint64_t)ram_size << 20;\n    }\n    if (accel_enable != -1)\n        p->accel_enable = accel_enable;\n    if (cmdline) {\n        vm_add_cmdline(p, cmdline);\n    }\n\n\n    /* open the files & devices */\n    for(i = 0; i < p->drive_count; i++) {\n        BlockDevice *drive;\n        char *fname;\n        fname = get_file_path(p->cfg_filename, p->tab_drive[i].filename);\n#ifdef CONFIG_FS_NET\n        if (is_url(fname)) {\n            net_completed = FALSE;\n            drive = block_device_init_http(fname, 128 * 1024,\n                                           net_start_cb, NULL);\n            /* wait until the drive is initialized */\n            fs_net_event_loop(net_poll_cb, NULL);\n        } else\n#endif\n        {\n            drive = block_device_init(fname, drive_mode);\n        }\n        free(fname);\n        p->tab_drive[i].block_dev = drive;\n    }\n\n    for(i = 0; i < p->fs_count; i++) {\n        FSDevice *fs;\n        const char *path;\n        path = p->tab_fs[i].filename;\n#ifdef CONFIG_FS_NET\n        if (is_url(path)) {\n            fs = fs_net_init(path, NULL, NULL);\n            if (!fs)\n                exit(1);\n            if (build_preload_file)\n                fs_dump_cache_load(fs, build_preload_file);\n            fs_net_event_loop(NULL, NULL);\n        } else\n#endif\n        {\n#ifdef _WIN32\n            fprintf(stderr, \"Filesystem access not supported yet\\n\");\n            exit(1);\n#else\n            char *fname;\n            fname = get_file_path(p->cfg_filename, path);\n            fs = fs_disk_init(fname);\n            if (!fs) {\n                fprintf(stderr, \"%s: must be a directory\\n\", fname);\n                exit(1);\n            }\n            free(fname);\n#endif\n        }\n        p->tab_fs[i].fs_dev = fs;\n    }\n\n    for(i = 0; i < p->eth_count; i++) {\n#ifdef CONFIG_SLIRP\n        if (!strcmp(p->tab_eth[i].driver, \"user\")) {\n            p->tab_eth[i].net = slirp_open();\n            if (!p->tab_eth[i].net)\n                exit(1);\n        } else\n#endif\n#ifndef _WIN32\n        if (!strcmp(p->tab_eth[i].driver, \"tap\")) {\n            p->tab_eth[i].net = tun_open(p->tab_eth[i].ifname);\n            if (!p->tab_eth[i].net)\n                exit(1);\n        } else\n#endif\n        {\n            fprintf(stderr, \"Unsupported network driver '%s'\\n\",\n                    p->tab_eth[i].driver);\n            exit(1);\n        }\n    }\n    \n#ifdef CONFIG_SDL\n    if (p->display_device) {\n        sdl_init(p->width, p->height);\n    } else\n#endif\n    {\n#ifdef _WIN32\n        fprintf(stderr, \"Console not supported yet\\n\");\n        exit(1);\n#else\n        p->console = console_init(allow_ctrlc);\n#endif\n    }\n    p->rtc_real_time = TRUE;\n\n    s = virt_machine_init(p);\n    if (!s)\n        exit(1);\n    \n    virt_machine_free_config(p);\n\n    if (s->net) {\n        s->net->device_set_carrier(s->net, TRUE);\n    }\n    \n    for(;;) {\n        virt_machine_run(s);\n    }\n    virt_machine_end(s);\n    sim_log_free(&sim_log);\n    return 0;\n}\n"
  },
  {
    "path": "src/vga.c",
    "content": "/*\n * Dummy VGA device\n * \n * Copyright (c) 2003-2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n\n#include \"cutils.h\"\n#include \"iomem.h\"\n#include \"virtio.h\"\n#include \"machine.h\"\n\n//#define DEBUG_VBE\n\n#define MSR_COLOR_EMULATION 0x01\n#define MSR_PAGE_SELECT     0x20\n\n#define ST01_V_RETRACE      0x08\n#define ST01_DISP_ENABLE    0x01\n\n#define VBE_DISPI_INDEX_ID              0x0\n#define VBE_DISPI_INDEX_XRES            0x1\n#define VBE_DISPI_INDEX_YRES            0x2\n#define VBE_DISPI_INDEX_BPP             0x3\n#define VBE_DISPI_INDEX_ENABLE          0x4\n#define VBE_DISPI_INDEX_BANK            0x5\n#define VBE_DISPI_INDEX_VIRT_WIDTH      0x6\n#define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7\n#define VBE_DISPI_INDEX_X_OFFSET        0x8\n#define VBE_DISPI_INDEX_Y_OFFSET        0x9\n#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa\n#define VBE_DISPI_INDEX_NB              0xb\n\n#define VBE_DISPI_ID0                   0xB0C0\n#define VBE_DISPI_ID1                   0xB0C1\n#define VBE_DISPI_ID2                   0xB0C2\n#define VBE_DISPI_ID3                   0xB0C3\n#define VBE_DISPI_ID4                   0xB0C4\n#define VBE_DISPI_ID5                   0xB0C5\n\n#define VBE_DISPI_DISABLED              0x00\n#define VBE_DISPI_ENABLED               0x01\n#define VBE_DISPI_GETCAPS               0x02\n#define VBE_DISPI_8BIT_DAC              0x20\n#define VBE_DISPI_LFB_ENABLED           0x40\n#define VBE_DISPI_NOCLEARMEM            0x80\n\n#define FB_ALLOC_ALIGN (1 << 20)\n\n#define MAX_TEXT_WIDTH 132\n#define MAX_TEXT_HEIGHT 60\n\nstruct VGAState {\n    FBDevice *fb_dev;\n    int fb_page_count;\n    PhysMemoryRange *mem_range;\n    PhysMemoryRange *mem_range2;\n    PCIDevice *pci_dev;\n    PhysMemoryRange *rom_range;\n\n    uint8_t *vga_ram; /* 128K at 0xa0000 */\n    \n    uint8_t sr_index;\n    uint8_t sr[8];\n    uint8_t gr_index;\n    uint8_t gr[16];\n    uint8_t ar_index;\n    uint8_t ar[21];\n    int ar_flip_flop;\n    uint8_t cr_index;\n    uint8_t cr[256]; /* CRT registers */\n    uint8_t msr; /* Misc Output Register */\n    uint8_t fcr; /* Feature Control Register */\n    uint8_t st00; /* status 0 */\n    uint8_t st01; /* status 1 */\n    uint8_t dac_state;\n    uint8_t dac_sub_index;\n    uint8_t dac_read_index;\n    uint8_t dac_write_index;\n    uint8_t dac_cache[3]; /* used when writing */\n    uint8_t palette[768];\n    \n    /* text mode state */\n    uint32_t last_palette[16];\n    uint16_t last_ch_attr[MAX_TEXT_WIDTH * MAX_TEXT_HEIGHT];\n    uint32_t last_width;\n    uint32_t last_height;\n    uint16_t last_line_offset;\n    uint16_t last_start_addr;\n    uint16_t last_cursor_offset;\n    uint8_t last_cursor_start;\n    uint8_t last_cursor_end;\n    \n    /* VBE extension */\n    uint16_t vbe_index;\n    uint16_t vbe_regs[VBE_DISPI_INDEX_NB];\n};\n\nstatic void vga_draw_glyph8(uint8_t *d, int linesize,\n                            const uint8_t *font_ptr, int h,\n                            uint32_t fgcol, uint32_t bgcol)\n{\n    uint32_t font_data, xorcol;\n\n    xorcol = bgcol ^ fgcol;\n    do {\n        font_data = font_ptr[0];\n        ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;\n        font_ptr++;\n        d += linesize;\n    } while (--h);\n}\n\nstatic void vga_draw_glyph9(uint8_t *d, int linesize,\n                            const uint8_t *font_ptr, int h,\n                            uint32_t fgcol, uint32_t bgcol,\n                            int dup9)\n{\n    uint32_t font_data, xorcol, v;\n\n    xorcol = bgcol ^ fgcol;\n    do {\n        font_data = font_ptr[0];\n        ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;\n        v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;\n        ((uint32_t *)d)[7] = v;\n        if (dup9)\n            ((uint32_t *)d)[8] = v;\n        else\n            ((uint32_t *)d)[8] = bgcol;\n        font_ptr++;\n        d += linesize;\n    } while (--h);\n}\n\nstatic const uint8_t cursor_glyph[32] = {\n    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n};\n\nstatic inline int c6_to_8(int v)\n{\n    int b;\n    v &= 0x3f;\n    b = v & 1;\n    return (v << 2) | (b << 1) | b;\n}\n\nstatic int update_palette16(VGAState *s, uint32_t *palette)\n{\n    int full_update, i;\n    uint32_t v, col;\n\n    full_update = 0;\n    for(i = 0; i < 16; i++) {\n        v = s->ar[i];\n        if (s->ar[0x10] & 0x80)\n            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);\n        else\n            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);\n        v = v * 3;\n        col = (c6_to_8(s->palette[v]) << 16) |\n            (c6_to_8(s->palette[v + 1]) << 8) |\n            c6_to_8(s->palette[v + 2]);\n        if (col != palette[i]) {\n            full_update = 1;\n            palette[i] = col;\n        }\n    }\n    return full_update;\n}\n\n/* the text refresh is just for debugging and initial boot message, so\n   it is very incomplete */\nstatic void vga_text_refresh(VGAState *s,\n                             SimpleFBDrawFunc *redraw_func, void *opaque)\n{\n    FBDevice *fb_dev = s->fb_dev;\n    int width, height, cwidth, cheight, cy, cx, x1, y1, width1, height1;\n    int cx_min, cx_max, dup9;\n    uint32_t ch_attr, line_offset, start_addr, ch_addr, ch_addr1, ch, cattr;\n    uint8_t *vga_ram, *font_ptr, *dst;\n    uint32_t fgcol, bgcol, cursor_offset, cursor_start, cursor_end;\n    BOOL full_update;\n\n    full_update = update_palette16(s, s->last_palette);\n\n    vga_ram = s->vga_ram;\n    \n    line_offset = s->cr[0x13];\n    line_offset <<= 3;\n    line_offset >>= 1;\n\n    start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);\n    \n    cheight = (s->cr[9] & 0x1f) + 1;\n    cwidth = 8;\n    if (!(s->sr[1] & 0x01))\n        cwidth++;\n    \n    width = (s->cr[0x01] + 1);\n    height = s->cr[0x12] |\n        ((s->cr[0x07] & 0x02) << 7) |\n        ((s->cr[0x07] & 0x40) << 3);\n    height = (height + 1) / cheight;\n    \n    width1 = width * cwidth;\n    height1 = height * cheight;\n    if (fb_dev->width < width1 || fb_dev->height < height1 ||\n        width > MAX_TEXT_WIDTH || height > MAX_TEXT_HEIGHT)\n        return; /* not enough space */\n    if (s->last_line_offset != line_offset ||\n        s->last_start_addr != start_addr ||\n        s->last_width != width ||\n        s->last_height != height) {\n        s->last_line_offset = line_offset;\n        s->last_start_addr = start_addr;\n        s->last_width = width;\n        s->last_height = height;\n        full_update = TRUE;\n    }\n       \n    /* update cursor position */\n    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - start_addr;\n    cursor_start = s->cr[0xa];\n    cursor_end = s->cr[0xb];\n    if (cursor_offset != s->last_cursor_offset ||\n        cursor_start != s->last_cursor_start ||\n        cursor_end != s->last_cursor_end) {\n        /* force refresh of characters with the cursor */\n        if (s->last_cursor_offset < MAX_TEXT_WIDTH * MAX_TEXT_HEIGHT)\n            s->last_ch_attr[s->last_cursor_offset] = -1;\n        if (cursor_offset < MAX_TEXT_WIDTH * MAX_TEXT_HEIGHT)\n            s->last_ch_attr[cursor_offset] = -1;\n        s->last_cursor_offset = cursor_offset;\n        s->last_cursor_start = cursor_start;\n        s->last_cursor_end = cursor_end;\n    }\n\n    ch_addr1 = 0x18000 + (start_addr * 2);\n    cursor_offset = 0x18000 + (start_addr + cursor_offset) * 2;\n    \n    x1 = (fb_dev->width - width1) / 2;\n    y1 = (fb_dev->height - height1) / 2;\n#if 0\n    printf(\"text refresh %dx%d font=%dx%d start_addr=0x%x line_offset=0x%x\\n\",\n           width, height, cwidth, cheight, start_addr, line_offset);\n#endif\n    for(cy = 0; cy < height; cy++) {\n        ch_addr = ch_addr1;\n        dst = fb_dev->fb_data + (y1 + cy * cheight) * fb_dev->stride + x1 * 4;\n        cx_min = width;\n        cx_max = -1;\n        for(cx = 0; cx < width; cx++) {\n            ch_attr = *(uint16_t *)(vga_ram + (ch_addr & 0x1fffe));\n            if (full_update || ch_attr != s->last_ch_attr[cy * width + cx]) {\n                s->last_ch_attr[cy * width + cx] = ch_attr;\n                cx_min = min_int(cx_min, cx);\n                cx_max = max_int(cx_max, cx);\n                ch = ch_attr & 0xff;\n                cattr = ch_attr >> 8;\n                font_ptr = vga_ram + 32 * ch;\n                bgcol = s->last_palette[cattr >> 4];\n                fgcol = s->last_palette[cattr & 0x0f];\n                if (cwidth == 8) {\n                    vga_draw_glyph8(dst, fb_dev->stride, font_ptr, cheight,\n                                    fgcol, bgcol);\n                } else {\n                    dup9 = 0;\n                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))\n                        dup9 = 1;\n                    vga_draw_glyph9(dst, fb_dev->stride, font_ptr, cheight,\n                                    fgcol, bgcol, dup9);\n                }\n                /* cursor display */\n                if (cursor_offset == ch_addr && !(cursor_start & 0x20)) {\n                    int line_start, line_last, h;\n                    uint8_t *dst1;\n                    line_start = cursor_start & 0x1f;\n                    line_last = min_int(cursor_end & 0x1f, cheight - 1);\n\n                    if (line_last >= line_start && line_start < cheight) {\n                        h = line_last - line_start + 1;\n                        dst1 = dst + fb_dev->stride * line_start;\n                        if (cwidth == 8) {\n                            vga_draw_glyph8(dst1, fb_dev->stride,\n                                            cursor_glyph,\n                                            h, fgcol, bgcol);\n                        } else {\n                            vga_draw_glyph9(dst1, fb_dev->stride,\n                                            cursor_glyph,\n                                            h, fgcol, bgcol, 1);\n                        }\n                    }\n                }\n            }\n            ch_addr += 2;\n            dst += 4 * cwidth;\n        }\n        if (cx_max >= cx_min) {\n            //            printf(\"redraw %d %d %d\\n\", cy, cx_min, cx_max);\n            redraw_func(fb_dev, opaque,\n                        x1 + cx_min * cwidth, y1 + cy * cheight,\n                        (cx_max - cx_min + 1) * cwidth, cheight);\n        }\n        ch_addr1 += line_offset;\n    }\n}\n\nstatic void vga_refresh(FBDevice *fb_dev,\n                        SimpleFBDrawFunc *redraw_func, void *opaque)\n{\n    VGAState *s = fb_dev->device_opaque;\n\n    if (!(s->ar_index & 0x20)) {\n        /* blank */\n    } else if (s->gr[0x06] & 1) {\n        /* graphic mode (VBE) */\n        simplefb_refresh(fb_dev, redraw_func, opaque, s->mem_range, s->fb_page_count);\n    } else {\n        /* text mode */\n        vga_text_refresh(s, redraw_func, opaque);\n    }\n}\n\n/* force some bits to zero */\nstatic const uint8_t sr_mask[8] = {\n    (uint8_t)~0xfc,\n    (uint8_t)~0xc2,\n    (uint8_t)~0xf0,\n    (uint8_t)~0xc0,\n    (uint8_t)~0xf1,\n    (uint8_t)~0xff,\n    (uint8_t)~0xff,\n    (uint8_t)~0x00,\n};\n\nstatic const uint8_t gr_mask[16] = {\n    (uint8_t)~0xf0, /* 0x00 */\n    (uint8_t)~0xf0, /* 0x01 */\n    (uint8_t)~0xf0, /* 0x02 */\n    (uint8_t)~0xe0, /* 0x03 */\n    (uint8_t)~0xfc, /* 0x04 */\n    (uint8_t)~0x84, /* 0x05 */\n    (uint8_t)~0xf0, /* 0x06 */\n    (uint8_t)~0xf0, /* 0x07 */\n    (uint8_t)~0x00, /* 0x08 */\n    (uint8_t)~0xff, /* 0x09 */\n    (uint8_t)~0xff, /* 0x0a */\n    (uint8_t)~0xff, /* 0x0b */\n    (uint8_t)~0xff, /* 0x0c */\n    (uint8_t)~0xff, /* 0x0d */\n    (uint8_t)~0xff, /* 0x0e */\n    (uint8_t)~0xff, /* 0x0f */\n};\n\nstatic uint32_t vga_ioport_read(VGAState *s, uint32_t addr)\n{\n    int val, index;\n\n    /* check port range access depending on color/monochrome mode */\n    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||\n        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {\n        val = 0xff;\n    } else {\n        switch(addr) {\n        case 0x3c0:\n            if (s->ar_flip_flop == 0) {\n                val = s->ar_index;\n            } else {\n                val = 0;\n            }\n            break;\n        case 0x3c1:\n            index = s->ar_index & 0x1f;\n            if (index < 21)\n                val = s->ar[index];\n            else\n                val = 0;\n            break;\n        case 0x3c2:\n            val = s->st00;\n            break;\n        case 0x3c4:\n            val = s->sr_index;\n            break;\n        case 0x3c5:\n            val = s->sr[s->sr_index];\n#ifdef DEBUG_VGA_REG\n            printf(\"vga: read SR%x = 0x%02x\\n\", s->sr_index, val);\n#endif\n            break;\n        case 0x3c7:\n            val = s->dac_state;\n            break;\n\tcase 0x3c8:\n\t    val = s->dac_write_index;\n\t    break;\n        case 0x3c9:\n            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];\n            if (++s->dac_sub_index == 3) {\n                s->dac_sub_index = 0;\n                s->dac_read_index++;\n            }\n            break;\n        case 0x3ca:\n            val = s->fcr;\n            break;\n        case 0x3cc:\n            val = s->msr;\n            break;\n        case 0x3ce:\n            val = s->gr_index;\n            break;\n        case 0x3cf:\n            val = s->gr[s->gr_index];\n#ifdef DEBUG_VGA_REG\n            printf(\"vga: read GR%x = 0x%02x\\n\", s->gr_index, val);\n#endif\n            break;\n        case 0x3b4:\n        case 0x3d4:\n            val = s->cr_index;\n            break;\n        case 0x3b5:\n        case 0x3d5:\n            val = s->cr[s->cr_index];\n#ifdef DEBUG_VGA_REG\n            printf(\"vga: read CR%x = 0x%02x\\n\", s->cr_index, val);\n#endif\n            break;\n        case 0x3ba:\n        case 0x3da:\n            /* just toggle to fool polling */\n            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;\n            val = s->st01;\n            s->ar_flip_flop = 0;\n            break;\n        default:\n            val = 0x00;\n            break;\n        }\n    }\n#if defined(DEBUG_VGA)\n    printf(\"VGA: read addr=0x%04x data=0x%02x\\n\", addr, val);\n#endif\n    return val;\n}\n\nstatic void vga_ioport_write(VGAState *s, uint32_t addr, uint32_t val)\n{\n    int index;\n\n    /* check port range access depending on color/monochrome mode */\n    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||\n        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))\n        return;\n\n#ifdef DEBUG_VGA\n    printf(\"VGA: write addr=0x%04x data=0x%02x\\n\", addr, val);\n#endif\n\n    switch(addr) {\n    case 0x3c0:\n        if (s->ar_flip_flop == 0) {\n            val &= 0x3f;\n            s->ar_index = val;\n        } else {\n            index = s->ar_index & 0x1f;\n            switch(index) {\n            case 0x00 ... 0x0f:\n                s->ar[index] = val & 0x3f;\n                break;\n            case 0x10:\n                s->ar[index] = val & ~0x10;\n                break;\n            case 0x11:\n                s->ar[index] = val;\n                break;\n            case 0x12:\n                s->ar[index] = val & ~0xc0;\n                break;\n            case 0x13:\n                s->ar[index] = val & ~0xf0;\n                break;\n            case 0x14:\n                s->ar[index] = val & ~0xf0;\n                break;\n            default:\n                break;\n            }\n        }\n        s->ar_flip_flop ^= 1;\n        break;\n    case 0x3c2:\n        s->msr = val & ~0x10;\n        break;\n    case 0x3c4:\n        s->sr_index = val & 7;\n        break;\n    case 0x3c5:\n#ifdef DEBUG_VGA_REG\n        printf(\"vga: write SR%x = 0x%02x\\n\", s->sr_index, val);\n#endif\n        s->sr[s->sr_index] = val & sr_mask[s->sr_index];\n        break;\n    case 0x3c7:\n        s->dac_read_index = val;\n        s->dac_sub_index = 0;\n        s->dac_state = 3;\n        break;\n    case 0x3c8:\n        s->dac_write_index = val;\n        s->dac_sub_index = 0;\n        s->dac_state = 0;\n        break;\n    case 0x3c9:\n        s->dac_cache[s->dac_sub_index] = val;\n        if (++s->dac_sub_index == 3) {\n            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);\n            s->dac_sub_index = 0;\n            s->dac_write_index++;\n        }\n        break;\n    case 0x3ce:\n        s->gr_index = val & 0x0f;\n        break;\n    case 0x3cf:\n#ifdef DEBUG_VGA_REG\n        printf(\"vga: write GR%x = 0x%02x\\n\", s->gr_index, val);\n#endif\n        s->gr[s->gr_index] = val & gr_mask[s->gr_index];\n        break;\n    case 0x3b4:\n    case 0x3d4:\n        s->cr_index = val;\n        break;\n    case 0x3b5:\n    case 0x3d5:\n#ifdef DEBUG_VGA_REG\n        printf(\"vga: write CR%x = 0x%02x\\n\", s->cr_index, val);\n#endif\n        /* handle CR0-7 protection */\n        if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {\n            /* can always write bit 4 of CR7 */\n            if (s->cr_index == 7)\n                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);\n            return;\n        }\n        switch(s->cr_index) {\n        case 0x01: /* horizontal display end */\n        case 0x07:\n        case 0x09:\n        case 0x0c:\n        case 0x0d:\n        case 0x12: /* vertical display end */\n            s->cr[s->cr_index] = val;\n            break;\n        default:\n            s->cr[s->cr_index] = val;\n            break;\n        }\n        break;\n    case 0x3ba:\n    case 0x3da:\n        s->fcr = val & 0x10;\n        break;\n    }\n}\n\n#define VGA_IO(base) \\\nstatic uint32_t vga_read_ ## base(void *opaque, uint32_t addr, int size_log2)\\\n{\\\n    return vga_ioport_read(opaque, base + addr);\\\n}\\\nstatic void vga_write_ ## base(void *opaque, uint32_t addr, uint32_t val, int size_log2)\\\n{\\\n    return vga_ioport_write(opaque, base + addr, val);\\\n}\n\nVGA_IO(0x3c0)\nVGA_IO(0x3b4)\nVGA_IO(0x3d4)\nVGA_IO(0x3ba)\nVGA_IO(0x3da)\n\nstatic void vbe_write(void *opaque, uint32_t offset,\n                      uint32_t val, int size_log2)\n{\n    VGAState *s = opaque;\n    FBDevice *fb_dev = s->fb_dev;\n    \n    if (offset == 0) {\n        s->vbe_index = val;\n    } else {\n#ifdef DEBUG_VBE\n        printf(\"VBE write: index=0x%04x val=0x%04x\\n\", s->vbe_index, val);\n#endif\n        switch(s->vbe_index) {\n        case VBE_DISPI_INDEX_ID:\n            if (val >= VBE_DISPI_ID0 && val <= VBE_DISPI_ID5)\n                s->vbe_regs[s->vbe_index] = val;\n            break;\n        case VBE_DISPI_INDEX_ENABLE:\n            if ((val & VBE_DISPI_ENABLED) &&\n                !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {\n                /* set graphic mode */\n                /* XXX: resolution change not really supported */\n                if (s->vbe_regs[VBE_DISPI_INDEX_XRES] <= 4096 &&\n                    s->vbe_regs[VBE_DISPI_INDEX_YRES] <= 4096 &&\n                    (s->vbe_regs[VBE_DISPI_INDEX_XRES] * 4 *\n                     s->vbe_regs[VBE_DISPI_INDEX_YRES]) <= fb_dev->fb_size) {\n                    fb_dev->width = s->vbe_regs[VBE_DISPI_INDEX_XRES];\n                    fb_dev->height = s->vbe_regs[VBE_DISPI_INDEX_YRES];\n                    fb_dev->stride = fb_dev->width * 4;\n                }\n                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =\n                    s->vbe_regs[VBE_DISPI_INDEX_XRES];\n                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =\n                    s->vbe_regs[VBE_DISPI_INDEX_YRES];\n                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;\n                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;\n            }\n            s->vbe_regs[s->vbe_index] = val;\n            break;\n        case VBE_DISPI_INDEX_XRES:\n        case VBE_DISPI_INDEX_YRES:\n        case VBE_DISPI_INDEX_BPP:\n        case VBE_DISPI_INDEX_BANK:\n        case VBE_DISPI_INDEX_VIRT_WIDTH:\n        case VBE_DISPI_INDEX_VIRT_HEIGHT:\n        case VBE_DISPI_INDEX_X_OFFSET:\n        case VBE_DISPI_INDEX_Y_OFFSET:\n            s->vbe_regs[s->vbe_index] = val;\n            break;\n        }\n    }\n}\n\nstatic uint32_t vbe_read(void *opaque, uint32_t offset, int size_log2)\n{\n    VGAState *s = opaque;\n    uint32_t val;\n\n    if (offset == 0) {\n        val = s->vbe_index;\n    } else {\n        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {\n            switch(s->vbe_index) {\n            case VBE_DISPI_INDEX_XRES:\n                val = s->fb_dev->width;\n                break;\n            case VBE_DISPI_INDEX_YRES:\n                val = s->fb_dev->height;\n                break;\n            case VBE_DISPI_INDEX_BPP:\n                val = 32;\n                break;\n            default:\n                goto read_reg;\n            }\n        } else {\n        read_reg:\n            if (s->vbe_index < VBE_DISPI_INDEX_NB)\n                val = s->vbe_regs[s->vbe_index];\n            else\n                val = 0;\n        }\n#ifdef DEBUG_VBE\n        printf(\"VBE read: index=0x%04x val=0x%04x\\n\", s->vbe_index, val);\n#endif\n    }\n    return val;\n}\n\n\nstatic void simplefb_bar_set(void *opaque, int bar_num,\n                              uint32_t addr, BOOL enabled)\n{\n    VGAState *s = opaque;\n    if (bar_num == 0)\n        phys_mem_set_addr(s->mem_range, addr, enabled);\n    else\n        phys_mem_set_addr(s->rom_range, addr, enabled);\n}\n\nVGAState *pci_vga_init(PCIBus *bus, FBDevice *fb_dev,\n                       int width, int height,\n                       const uint8_t *vga_rom_buf, int vga_rom_size)\n{\n    VGAState *s;\n    PCIDevice *d;\n    uint32_t bar_size;\n    PhysMemoryMap *mem_map, *port_map;\n    \n    d = pci_register_device(bus, \"VGA\", -1, 0x1234, 0x1111, 0x00, 0x0300);\n    \n    mem_map = pci_device_get_mem_map(d);\n    port_map = pci_device_get_port_map(d);\n\n    s = mallocz(sizeof(*s));\n    s->fb_dev = fb_dev;\n    \n    fb_dev->width = width;\n    fb_dev->height = height;\n    fb_dev->stride = width * 4;\n\n    fb_dev->fb_size = (height * fb_dev->stride + FB_ALLOC_ALIGN - 1) & ~(FB_ALLOC_ALIGN - 1);\n    s->fb_page_count = fb_dev->fb_size >> DEVRAM_PAGE_SIZE_LOG2;\n\n    s->mem_range =\n        cpu_register_ram(mem_map, 0, fb_dev->fb_size,\n                         DEVRAM_FLAG_DIRTY_BITS | DEVRAM_FLAG_DISABLED);\n    \n    fb_dev->fb_data = s->mem_range->phys_mem;\n\n    s->pci_dev = d;\n    bar_size = 1;\n    while (bar_size < fb_dev->fb_size)\n        bar_size <<= 1;\n    pci_register_bar(d, 0, bar_size, PCI_ADDRESS_SPACE_MEM, s,\n                     simplefb_bar_set);\n\n    if (vga_rom_size > 0) {\n        int rom_size;\n        /* align to page size */\n        rom_size = (vga_rom_size + DEVRAM_PAGE_SIZE - 1) & ~(DEVRAM_PAGE_SIZE - 1);\n        s->rom_range = cpu_register_ram(mem_map, 0, rom_size,\n                                        DEVRAM_FLAG_ROM | DEVRAM_FLAG_DISABLED);\n        memcpy(s->rom_range->phys_mem, vga_rom_buf, vga_rom_size);\n\n        bar_size = 1;\n        while (bar_size < rom_size)\n            bar_size <<= 1;\n        pci_register_bar(d, PCI_ROM_SLOT, bar_size, PCI_ADDRESS_SPACE_MEM, s,\n                         simplefb_bar_set);\n    }\n\n    /* VGA memory (for simple text mode no need for callbacks) */\n    s->mem_range2 = cpu_register_ram(mem_map, 0xa0000, 0x20000, 0);\n    s->vga_ram = s->mem_range2->phys_mem;\n        \n    /* standard VGA ports */\n    \n    cpu_register_device(port_map, 0x3c0, 16, s, vga_read_0x3c0, vga_write_0x3c0,\n                        DEVIO_SIZE8);\n    cpu_register_device(port_map, 0x3b4, 2, s, vga_read_0x3b4, vga_write_0x3b4,\n                        DEVIO_SIZE8);\n    cpu_register_device(port_map, 0x3d4, 2, s, vga_read_0x3d4, vga_write_0x3d4,\n                        DEVIO_SIZE8);\n    cpu_register_device(port_map, 0x3ba, 1, s, vga_read_0x3ba, vga_write_0x3ba,\n                        DEVIO_SIZE8);\n    cpu_register_device(port_map, 0x3da, 1, s, vga_read_0x3da, vga_write_0x3da,\n                        DEVIO_SIZE8);\n    \n    /* VBE extension */\n    cpu_register_device(port_map, 0x1ce, 2, s, vbe_read, vbe_write, \n                        DEVIO_SIZE16);\n    \n    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;\n    s->vbe_regs[VBE_DISPI_INDEX_VIDEO_MEMORY_64K] = fb_dev->fb_size >> 16;\n\n    fb_dev->device_opaque = s;\n    fb_dev->refresh = vga_refresh;\n    return s;\n}\n"
  },
  {
    "path": "src/virtio.c",
    "content": "/*\n * VIRTIO driver\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n#include <stdarg.h>\n\n#include \"cutils.h\"\n#include \"list.h\"\n#include \"virtio.h\"\n\n//#define DEBUG_VIRTIO\n\n/* MMIO addresses - from the Linux kernel */\n#define VIRTIO_MMIO_MAGIC_VALUE\t\t0x000\n#define VIRTIO_MMIO_VERSION\t\t0x004\n#define VIRTIO_MMIO_DEVICE_ID\t\t0x008\n#define VIRTIO_MMIO_VENDOR_ID\t\t0x00c\n#define VIRTIO_MMIO_DEVICE_FEATURES\t0x010\n#define VIRTIO_MMIO_DEVICE_FEATURES_SEL\t0x014\n#define VIRTIO_MMIO_DRIVER_FEATURES\t0x020\n#define VIRTIO_MMIO_DRIVER_FEATURES_SEL\t0x024\n#define VIRTIO_MMIO_GUEST_PAGE_SIZE\t0x028 /* version 1 only */\n#define VIRTIO_MMIO_QUEUE_SEL\t\t0x030\n#define VIRTIO_MMIO_QUEUE_NUM_MAX\t0x034\n#define VIRTIO_MMIO_QUEUE_NUM\t\t0x038\n#define VIRTIO_MMIO_QUEUE_ALIGN\t\t0x03c /* version 1 only */\n#define VIRTIO_MMIO_QUEUE_PFN\t\t0x040 /* version 1 only */\n#define VIRTIO_MMIO_QUEUE_READY\t\t0x044\n#define VIRTIO_MMIO_QUEUE_NOTIFY\t0x050\n#define VIRTIO_MMIO_INTERRUPT_STATUS\t0x060\n#define VIRTIO_MMIO_INTERRUPT_ACK\t0x064\n#define VIRTIO_MMIO_STATUS\t\t0x070\n#define VIRTIO_MMIO_QUEUE_DESC_LOW\t0x080\n#define VIRTIO_MMIO_QUEUE_DESC_HIGH\t0x084\n#define VIRTIO_MMIO_QUEUE_AVAIL_LOW\t0x090\n#define VIRTIO_MMIO_QUEUE_AVAIL_HIGH\t0x094\n#define VIRTIO_MMIO_QUEUE_USED_LOW\t0x0a0\n#define VIRTIO_MMIO_QUEUE_USED_HIGH\t0x0a4\n#define VIRTIO_MMIO_CONFIG_GENERATION\t0x0fc\n#define VIRTIO_MMIO_CONFIG\t\t0x100\n\n/* PCI registers */\n#define VIRTIO_PCI_DEVICE_FEATURE_SEL\t0x000\n#define VIRTIO_PCI_DEVICE_FEATURE\t0x004\n#define VIRTIO_PCI_GUEST_FEATURE_SEL\t0x008\n#define VIRTIO_PCI_GUEST_FEATURE\t0x00c\n#define VIRTIO_PCI_MSIX_CONFIG          0x010\n#define VIRTIO_PCI_NUM_QUEUES           0x012\n#define VIRTIO_PCI_DEVICE_STATUS        0x014\n#define VIRTIO_PCI_CONFIG_GENERATION    0x015\n#define VIRTIO_PCI_QUEUE_SEL\t\t0x016\n#define VIRTIO_PCI_QUEUE_SIZE\t        0x018\n#define VIRTIO_PCI_QUEUE_MSIX_VECTOR    0x01a\n#define VIRTIO_PCI_QUEUE_ENABLE         0x01c\n#define VIRTIO_PCI_QUEUE_NOTIFY_OFF     0x01e\n#define VIRTIO_PCI_QUEUE_DESC_LOW\t0x020\n#define VIRTIO_PCI_QUEUE_DESC_HIGH\t0x024\n#define VIRTIO_PCI_QUEUE_AVAIL_LOW\t0x028\n#define VIRTIO_PCI_QUEUE_AVAIL_HIGH\t0x02c\n#define VIRTIO_PCI_QUEUE_USED_LOW\t0x030\n#define VIRTIO_PCI_QUEUE_USED_HIGH\t0x034\n\n#define VIRTIO_PCI_CFG_OFFSET          0x0000\n#define VIRTIO_PCI_ISR_OFFSET          0x1000\n#define VIRTIO_PCI_CONFIG_OFFSET       0x2000\n#define VIRTIO_PCI_NOTIFY_OFFSET       0x3000\n\n#define VIRTIO_PCI_CAP_LEN 16\n\n#define MAX_QUEUE 8\n#define MAX_CONFIG_SPACE_SIZE 256\n#define MAX_QUEUE_NUM 16\n\ntypedef struct {\n    uint32_t ready; /* 0 or 1 */\n    uint32_t num;\n    uint16_t last_avail_idx;\n    virtio_phys_addr_t desc_addr;\n    virtio_phys_addr_t avail_addr;\n    virtio_phys_addr_t used_addr;\n    BOOL manual_recv; /* if TRUE, the device_recv() callback is not called */\n} QueueState;\n\n#define VRING_DESC_F_NEXT\t1\n#define VRING_DESC_F_WRITE\t2\n#define VRING_DESC_F_INDIRECT\t4\n\ntypedef struct {\n    uint64_t addr;\n    uint32_t len;\n    uint16_t flags; /* VRING_DESC_F_x */\n    uint16_t next;\n} VIRTIODesc;\n\n/* return < 0 to stop the notification (it must be manually restarted\n   later), 0 if OK */\ntypedef int VIRTIODeviceRecvFunc(VIRTIODevice *s1, int queue_idx,\n                                 int desc_idx, int read_size,\n                                 int write_size);\n\n/* return NULL if no RAM at this address. The mapping is valid for one page */\ntypedef uint8_t *VIRTIOGetRAMPtrFunc(VIRTIODevice *s, virtio_phys_addr_t paddr, BOOL is_rw);\n\nstruct VIRTIODevice {\n    PhysMemoryMap *mem_map;\n    PhysMemoryRange *mem_range;\n    /* PCI only */\n    PCIDevice *pci_dev;\n    /* MMIO only */\n    IRQSignal *irq;\n    VIRTIOGetRAMPtrFunc *get_ram_ptr;\n    int debug;\n\n    uint32_t int_status;\n    uint32_t status;\n    uint32_t device_features_sel;\n    uint32_t queue_sel; /* currently selected queue */\n    QueueState queue[MAX_QUEUE];\n\n    /* device specific */\n    uint32_t device_id;\n    uint32_t vendor_id;\n    uint32_t device_features;\n    VIRTIODeviceRecvFunc *device_recv;\n    void (*config_write)(VIRTIODevice *s); /* called after the config\n                                              is written */\n    uint32_t config_space_size; /* in bytes, must be multiple of 4 */\n    uint8_t config_space[MAX_CONFIG_SPACE_SIZE];\n};\n\nstatic uint32_t virtio_mmio_read(void *opaque, uint32_t offset1, int size_log2);\nstatic void virtio_mmio_write(void *opaque, uint32_t offset,\n                              uint32_t val, int size_log2);\nstatic uint32_t virtio_pci_read(void *opaque, uint32_t offset, int size_log2);\nstatic void virtio_pci_write(void *opaque, uint32_t offset,\n                             uint32_t val, int size_log2);\n\nstatic void virtio_reset(VIRTIODevice *s)\n{\n    int i;\n\n    s->status = 0;\n    s->queue_sel = 0;\n    s->device_features_sel = 0;\n    s->int_status = 0;\n    for(i = 0; i < MAX_QUEUE; i++) {\n        QueueState *qs = &s->queue[i];\n        qs->ready = 0;\n        qs->num = MAX_QUEUE_NUM;\n        qs->desc_addr = 0;\n        qs->avail_addr = 0;\n        qs->used_addr = 0;\n        qs->last_avail_idx = 0;\n    }\n}\n\nstatic uint8_t *virtio_pci_get_ram_ptr(VIRTIODevice *s, virtio_phys_addr_t paddr, BOOL is_rw)\n{\n    return pci_device_get_dma_ptr(s->pci_dev, paddr, is_rw);\n}\n\nstatic uint8_t *virtio_mmio_get_ram_ptr(VIRTIODevice *s, virtio_phys_addr_t paddr, BOOL is_rw)\n{\n    return phys_mem_get_ram_ptr(s->mem_map, paddr, is_rw);\n}\n\nstatic void virtio_add_pci_capability(VIRTIODevice *s, int cfg_type,\n                                      int bar, uint32_t offset, uint32_t len,\n                                      uint32_t mult)\n{\n    uint8_t cap[20];\n    int cap_len;\n    if (cfg_type == 2)\n        cap_len = 20;\n    else\n        cap_len = 16;\n    memset(cap, 0, cap_len);\n    cap[0] = 0x09; /* vendor specific */\n    cap[2] = cap_len; /* set by pci_add_capability() */\n    cap[3] = cfg_type;\n    cap[4] = bar;\n    put_le32(cap + 8, offset);\n    put_le32(cap + 12, len);\n    if (cfg_type == 2)\n        put_le32(cap + 16, mult);\n    pci_add_capability(s->pci_dev, cap, cap_len);\n}\n\nstatic void virtio_pci_bar_set(void *opaque, int bar_num,\n                               uint32_t addr, BOOL enabled)\n{\n    VIRTIODevice *s = opaque;\n    phys_mem_set_addr(s->mem_range, addr, enabled);\n}\n\nstatic void virtio_init(VIRTIODevice *s, VIRTIOBusDef *bus,\n                        uint32_t device_id, int config_space_size,\n                        VIRTIODeviceRecvFunc *device_recv)\n{\n    memset(s, 0, sizeof(*s));\n\n    if (bus->pci_bus) {\n        uint16_t pci_device_id, class_id;\n        char name[32];\n        int bar_num;\n        \n        switch(device_id) {\n        case 1:\n            pci_device_id = 0x1000; /* net */\n            class_id = 0x0200;\n            break;\n        case 2:\n            pci_device_id = 0x1001; /* block */\n            class_id = 0x0100; /* XXX: check it */\n            break;\n        case 3:\n            pci_device_id = 0x1003; /* console */\n            class_id = 0x0780;\n            break;\n        case 9:\n            pci_device_id = 0x1040 + device_id; /* use new device ID */\n            class_id = 0x2;\n            break;\n        case 18:\n            pci_device_id = 0x1040 + device_id; /* use new device ID */\n            class_id = 0x0980;\n            break;\n        default:\n            abort();\n        }\n        snprintf(name, sizeof(name), \"virtio_%04x\", pci_device_id);\n        s->pci_dev = pci_register_device(bus->pci_bus, name, -1,\n                                         0x1af4, pci_device_id, 0x00,\n                                         class_id);\n        pci_device_set_config16(s->pci_dev, 0x2c, 0x1af4);\n        pci_device_set_config16(s->pci_dev, 0x2e, device_id);\n        pci_device_set_config8(s->pci_dev, PCI_INTERRUPT_PIN, 1);\n\n        bar_num = 4;\n        virtio_add_pci_capability(s, 1, bar_num,\n                              VIRTIO_PCI_CFG_OFFSET, 0x1000, 0); /* common */\n        virtio_add_pci_capability(s, 3, bar_num,\n                              VIRTIO_PCI_ISR_OFFSET, 0x1000, 0); /* isr */\n        virtio_add_pci_capability(s, 4, bar_num,\n                              VIRTIO_PCI_CONFIG_OFFSET, 0x1000, 0); /* config */\n        virtio_add_pci_capability(s, 2, bar_num,\n                              VIRTIO_PCI_NOTIFY_OFFSET, 0x1000, 0); /* notify */\n        \n        s->get_ram_ptr = virtio_pci_get_ram_ptr;\n        s->irq = pci_device_get_irq(s->pci_dev, 0);\n        s->mem_map = pci_device_get_mem_map(s->pci_dev);\n        s->mem_range = cpu_register_device(s->mem_map, 0, 0x4000, s,\n                                           virtio_pci_read, virtio_pci_write,\n                                           DEVIO_SIZE8 | DEVIO_SIZE16 | DEVIO_SIZE32 | DEVIO_DISABLED);\n        pci_register_bar(s->pci_dev, bar_num, 0x4000, PCI_ADDRESS_SPACE_MEM,\n                         s, virtio_pci_bar_set);\n    } else {\n        /* MMIO case */\n        s->mem_map = bus->mem_map;\n        s->irq = bus->irq;\n        s->mem_range = cpu_register_device(s->mem_map, bus->addr, VIRTIO_PAGE_SIZE,\n                                           s, virtio_mmio_read, virtio_mmio_write,\n                                           DEVIO_SIZE8 | DEVIO_SIZE16 | DEVIO_SIZE32);\n        s->get_ram_ptr = virtio_mmio_get_ram_ptr;\n    }\n\n    s->device_id = device_id;\n    s->vendor_id = 0xffff;\n    s->config_space_size = config_space_size;\n    s->device_recv = device_recv;\n    virtio_reset(s);\n}\n\nstatic uint16_t virtio_read16(VIRTIODevice *s, virtio_phys_addr_t addr)\n{\n    uint8_t *ptr;\n    if (addr & 1)\n        return 0; /* unaligned access are not supported */\n    ptr = s->get_ram_ptr(s, addr, FALSE);\n    if (!ptr)\n        return 0;\n    return *(uint16_t *)ptr;\n}\n\nstatic void virtio_write16(VIRTIODevice *s, virtio_phys_addr_t addr,\n                           uint16_t val)\n{\n    uint8_t *ptr;\n    if (addr & 1)\n        return; /* unaligned access are not supported */\n    ptr = s->get_ram_ptr(s, addr, TRUE);\n    if (!ptr)\n        return;\n    *(uint16_t *)ptr = val;\n}\n\nstatic void virtio_write32(VIRTIODevice *s, virtio_phys_addr_t addr,\n                           uint32_t val)\n{\n    uint8_t *ptr;\n    if (addr & 3)\n        return; /* unaligned access are not supported */\n    ptr = s->get_ram_ptr(s, addr, TRUE);\n    if (!ptr)\n        return;\n    *(uint32_t *)ptr = val;\n}\n\nstatic int virtio_memcpy_from_ram(VIRTIODevice *s, uint8_t *buf,\n                                  virtio_phys_addr_t addr, int count)\n{\n    uint8_t *ptr;\n    int l;\n\n    while (count > 0) {\n        l = min_int(count, VIRTIO_PAGE_SIZE - (addr & (VIRTIO_PAGE_SIZE - 1)));\n        ptr = s->get_ram_ptr(s, addr, FALSE);\n        if (!ptr)\n            return -1;\n        memcpy(buf, ptr, l);\n        addr += l;\n        buf += l;\n        count -= l;\n    }\n    return 0;\n}\n\nstatic int virtio_memcpy_to_ram(VIRTIODevice *s, virtio_phys_addr_t addr, \n                                const uint8_t *buf, int count)\n{\n    uint8_t *ptr;\n    int l;\n\n    while (count > 0) {\n        l = min_int(count, VIRTIO_PAGE_SIZE - (addr & (VIRTIO_PAGE_SIZE - 1)));\n        ptr = s->get_ram_ptr(s, addr, TRUE);\n        if (!ptr)\n            return -1;\n        memcpy(ptr, buf, l);\n        addr += l;\n        buf += l;\n        count -= l;\n    }\n    return 0;\n}\n\nstatic int get_desc(VIRTIODevice *s, VIRTIODesc *desc,  \n                    int queue_idx, int desc_idx)\n{\n    QueueState *qs = &s->queue[queue_idx];\n    return virtio_memcpy_from_ram(s, (void *)desc, qs->desc_addr +\n                                  desc_idx * sizeof(VIRTIODesc),\n                                  sizeof(VIRTIODesc));\n}\n\nstatic int memcpy_to_from_queue(VIRTIODevice *s, uint8_t *buf,\n                                int queue_idx, int desc_idx,\n                                int offset, int count, BOOL to_queue)\n{\n    VIRTIODesc desc;\n    int l, f_write_flag;\n\n    if (count == 0)\n        return 0;\n\n    get_desc(s, &desc, queue_idx, desc_idx);\n\n    if (to_queue) {\n        f_write_flag = VRING_DESC_F_WRITE;\n        /* find the first write descriptor */\n        for(;;) {\n            if ((desc.flags & VRING_DESC_F_WRITE) == f_write_flag)\n                break;\n            if (!(desc.flags & VRING_DESC_F_NEXT))\n                return -1;\n            desc_idx = desc.next;\n            get_desc(s, &desc, queue_idx, desc_idx);\n        }\n    } else {\n        f_write_flag = 0;\n    }\n\n    /* find the descriptor at offset */\n    for(;;) {\n        if ((desc.flags & VRING_DESC_F_WRITE) != f_write_flag)\n            return -1;\n        if (offset < desc.len)\n            break;\n        if (!(desc.flags & VRING_DESC_F_NEXT))\n            return -1;\n        desc_idx = desc.next;\n        offset -= desc.len;\n        get_desc(s, &desc, queue_idx, desc_idx);\n    }\n\n    for(;;) {\n        l = min_int(count, desc.len - offset);\n        if (to_queue)\n            virtio_memcpy_to_ram(s, desc.addr + offset, buf, l);\n        else\n            virtio_memcpy_from_ram(s, buf, desc.addr + offset, l);\n        count -= l;\n        if (count == 0)\n            break;\n        offset += l;\n        buf += l;\n        if (offset == desc.len) {\n            if (!(desc.flags & VRING_DESC_F_NEXT))\n                return -1;\n            desc_idx = desc.next;\n            get_desc(s, &desc, queue_idx, desc_idx);\n            if ((desc.flags & VRING_DESC_F_WRITE) != f_write_flag)\n                return -1;\n            offset = 0;\n        }\n    }\n    return 0;\n}\n\nstatic int memcpy_from_queue(VIRTIODevice *s, void *buf,\n                             int queue_idx, int desc_idx,\n                             int offset, int count)\n{\n    return memcpy_to_from_queue(s, buf, queue_idx, desc_idx, offset, count,\n                                FALSE);\n}\n\nstatic int memcpy_to_queue(VIRTIODevice *s,\n                           int queue_idx, int desc_idx,\n                           int offset, const void *buf, int count)\n{\n    return memcpy_to_from_queue(s, (void *)buf, queue_idx, desc_idx, offset,\n                                count, TRUE);\n}\n\n/* signal that the descriptor has been consumed */\nstatic void virtio_consume_desc(VIRTIODevice *s,\n                                int queue_idx, int desc_idx, int desc_len)\n{\n    QueueState *qs = &s->queue[queue_idx];\n    virtio_phys_addr_t addr;\n    uint32_t index;\n\n    addr = qs->used_addr + 2;\n    index = virtio_read16(s, addr);\n    virtio_write16(s, addr, index + 1);\n\n    addr = qs->used_addr + 4 + (index & (qs->num - 1)) * 8;\n    virtio_write32(s, addr, desc_idx);\n    virtio_write32(s, addr + 4, desc_len);\n\n    s->int_status |= 1;\n    set_irq(s->irq, 1);\n}\n\nstatic int get_desc_rw_size(VIRTIODevice *s, \n                             int *pread_size, int *pwrite_size,\n                             int queue_idx, int desc_idx)\n{\n    VIRTIODesc desc;\n    int read_size, write_size;\n\n    read_size = 0;\n    write_size = 0;\n    get_desc(s, &desc, queue_idx, desc_idx);\n\n    for(;;) {\n        if (desc.flags & VRING_DESC_F_WRITE)\n            break;\n        read_size += desc.len;\n        if (!(desc.flags & VRING_DESC_F_NEXT))\n            goto done;\n        desc_idx = desc.next;\n        get_desc(s, &desc, queue_idx, desc_idx);\n    }\n    \n    for(;;) {\n        if (!(desc.flags & VRING_DESC_F_WRITE))\n            return -1;\n        write_size += desc.len;\n        if (!(desc.flags & VRING_DESC_F_NEXT))\n            break;\n        desc_idx = desc.next;\n        get_desc(s, &desc, queue_idx, desc_idx);\n    }\n\n done:\n    *pread_size = read_size;\n    *pwrite_size = write_size;\n    return 0;\n}\n\n/* XXX: test if the queue is ready ? */\nstatic void queue_notify(VIRTIODevice *s, int queue_idx)\n{\n    QueueState *qs = &s->queue[queue_idx];\n    uint16_t avail_idx;\n    int desc_idx, read_size, write_size;\n\n    if (qs->manual_recv)\n        return;\n\n    avail_idx = virtio_read16(s, qs->avail_addr + 2);\n    while (qs->last_avail_idx != avail_idx) {\n        desc_idx = virtio_read16(s, qs->avail_addr + 4 + \n                                 (qs->last_avail_idx & (qs->num - 1)) * 2);\n        if (!get_desc_rw_size(s, &read_size, &write_size, queue_idx, desc_idx)) {\n#ifdef DEBUG_VIRTIO\n            if (s->debug & VIRTIO_DEBUG_IO) {\n                printf(\"queue_notify: idx=%d read_size=%d write_size=%d\\n\",\n                       queue_idx, read_size, write_size);\n            }\n#endif\n            if (s->device_recv(s, queue_idx, desc_idx,\n                               read_size, write_size) < 0)\n                break;\n        }\n        qs->last_avail_idx++;\n    }\n}\n\nstatic uint32_t virtio_config_read(VIRTIODevice *s, uint32_t offset,\n                                   int size_log2)\n{\n    uint32_t val;\n    switch(size_log2) {\n    case 0:\n        if (offset < s->config_space_size) {\n            val = s->config_space[offset];\n        } else {\n            val = 0;\n        }\n        break;\n    case 1:\n        if (offset < (s->config_space_size - 1)) {\n            val = get_le16(&s->config_space[offset]);\n        } else {\n            val = 0;\n        }\n        break;\n    case 2:\n        if (offset < (s->config_space_size - 3)) {\n            val = get_le32(s->config_space + offset);\n        } else {\n            val = 0;\n        }\n        break;\n    default:\n        abort();\n    }\n    return val;\n}\n\nstatic void virtio_config_write(VIRTIODevice *s, uint32_t offset,\n                                uint32_t val, int size_log2)\n{\n    switch(size_log2) {\n    case 0:\n        if (offset < s->config_space_size) {\n            s->config_space[offset] = val;\n            if (s->config_write)\n                s->config_write(s);\n        }\n        break;\n    case 1:\n        if (offset < s->config_space_size - 1) {\n            put_le16(s->config_space + offset, val);\n            if (s->config_write)\n                s->config_write(s);\n        }\n        break;\n    case 2:\n        if (offset < s->config_space_size - 3) {\n            put_le32(s->config_space + offset, val);\n            if (s->config_write)\n                s->config_write(s);\n        }\n        break;\n    }\n}\n\nstatic uint32_t virtio_mmio_read(void *opaque, uint32_t offset, int size_log2)\n{\n    VIRTIODevice *s = opaque;\n    uint32_t val;\n\n    if (offset >= VIRTIO_MMIO_CONFIG) {\n        return virtio_config_read(s, offset - VIRTIO_MMIO_CONFIG, size_log2);\n    }\n\n    if (size_log2 == 2) {\n        switch(offset) {\n        case VIRTIO_MMIO_MAGIC_VALUE:\n            val = 0x74726976;\n            break;\n        case VIRTIO_MMIO_VERSION:\n            val = 2;\n            break;\n        case VIRTIO_MMIO_DEVICE_ID:\n            val = s->device_id;\n            break;\n        case VIRTIO_MMIO_VENDOR_ID:\n            val = s->vendor_id;\n            break;\n        case VIRTIO_MMIO_DEVICE_FEATURES:\n            switch(s->device_features_sel) {\n            case 0:\n                val = s->device_features;\n                break;\n            case 1:\n                val = 1; /* version 1 */\n                break;\n            default:\n                val = 0;\n                break;\n            }\n            break;\n        case VIRTIO_MMIO_DEVICE_FEATURES_SEL:\n            val = s->device_features_sel;\n            break;\n        case VIRTIO_MMIO_QUEUE_SEL:\n            val = s->queue_sel;\n            break;\n        case VIRTIO_MMIO_QUEUE_NUM_MAX:\n            val = MAX_QUEUE_NUM;\n            break;\n        case VIRTIO_MMIO_QUEUE_NUM:\n            val = s->queue[s->queue_sel].num;\n            break;\n        case VIRTIO_MMIO_QUEUE_DESC_LOW:\n            val = s->queue[s->queue_sel].desc_addr;\n            break;\n        case VIRTIO_MMIO_QUEUE_AVAIL_LOW:\n            val = s->queue[s->queue_sel].avail_addr;\n            break;\n        case VIRTIO_MMIO_QUEUE_USED_LOW:\n            val = s->queue[s->queue_sel].used_addr;\n            break;\n#if VIRTIO_ADDR_BITS == 64\n        case VIRTIO_MMIO_QUEUE_DESC_HIGH:\n            val = s->queue[s->queue_sel].desc_addr >> 32;\n            break;\n        case VIRTIO_MMIO_QUEUE_AVAIL_HIGH:\n            val = s->queue[s->queue_sel].avail_addr >> 32;\n            break;\n        case VIRTIO_MMIO_QUEUE_USED_HIGH:\n            val = s->queue[s->queue_sel].used_addr >> 32;\n            break;\n#endif\n        case VIRTIO_MMIO_QUEUE_READY:\n            val = s->queue[s->queue_sel].ready;\n            break;\n        case VIRTIO_MMIO_INTERRUPT_STATUS:\n            val = s->int_status;\n            break;\n        case VIRTIO_MMIO_STATUS:\n            val = s->status;\n            break;\n        case VIRTIO_MMIO_CONFIG_GENERATION:\n            val = 0;\n            break;\n        default:\n            val = 0;\n            break;\n        }\n    } else {\n        val = 0;\n    }\n#ifdef DEBUG_VIRTIO\n    if (s->debug & VIRTIO_DEBUG_IO) {\n        printf(\"virto_mmio_read: offset=0x%x val=0x%x size=%d\\n\", \n               offset, val, 1 << size_log2);\n    }\n#endif\n    return val;\n}\n\n#if VIRTIO_ADDR_BITS == 64\nstatic void set_low32(virtio_phys_addr_t *paddr, uint32_t val)\n{\n    *paddr = (*paddr & ~(virtio_phys_addr_t)0xffffffff) | val;\n}\n\nstatic void set_high32(virtio_phys_addr_t *paddr, uint32_t val)\n{\n    *paddr = (*paddr & 0xffffffff) | ((virtio_phys_addr_t)val << 32);\n}\n#else\nstatic void set_low32(virtio_phys_addr_t *paddr, uint32_t val)\n{\n    *paddr = val;\n}\n#endif\n\nstatic void virtio_mmio_write(void *opaque, uint32_t offset,\n                              uint32_t val, int size_log2)\n{\n    VIRTIODevice *s = opaque;\n    \n#ifdef DEBUG_VIRTIO\n    if (s->debug & VIRTIO_DEBUG_IO) {\n        printf(\"virto_mmio_write: offset=0x%x val=0x%x size=%d\\n\",\n               offset, val, 1 << size_log2);\n    }\n#endif\n\n    if (offset >= VIRTIO_MMIO_CONFIG) {\n        virtio_config_write(s, offset - VIRTIO_MMIO_CONFIG, val, size_log2);\n        return;\n    }\n\n    if (size_log2 == 2) {\n        switch(offset) {\n        case VIRTIO_MMIO_DEVICE_FEATURES_SEL:\n            s->device_features_sel = val;\n            break;\n        case VIRTIO_MMIO_QUEUE_SEL:\n            if (val < MAX_QUEUE)\n                s->queue_sel = val;\n            break;\n        case VIRTIO_MMIO_QUEUE_NUM:\n            if ((val & (val - 1)) == 0 && val > 0) {\n                s->queue[s->queue_sel].num = val;\n            }\n            break;\n        case VIRTIO_MMIO_QUEUE_DESC_LOW:\n            set_low32(&s->queue[s->queue_sel].desc_addr, val);\n            break;\n        case VIRTIO_MMIO_QUEUE_AVAIL_LOW:\n            set_low32(&s->queue[s->queue_sel].avail_addr, val);\n            break;\n        case VIRTIO_MMIO_QUEUE_USED_LOW:\n            set_low32(&s->queue[s->queue_sel].used_addr, val);\n            break;\n#if VIRTIO_ADDR_BITS == 64\n        case VIRTIO_MMIO_QUEUE_DESC_HIGH:\n            set_high32(&s->queue[s->queue_sel].desc_addr, val);\n            break;\n        case VIRTIO_MMIO_QUEUE_AVAIL_HIGH:\n            set_high32(&s->queue[s->queue_sel].avail_addr, val);\n            break;\n        case VIRTIO_MMIO_QUEUE_USED_HIGH:\n            set_high32(&s->queue[s->queue_sel].used_addr, val);\n            break;\n#endif\n        case VIRTIO_MMIO_STATUS:\n            s->status = val;\n            if (val == 0) {\n                /* reset */\n                set_irq(s->irq, 0);\n                virtio_reset(s);\n            }\n            break;\n        case VIRTIO_MMIO_QUEUE_READY:\n            s->queue[s->queue_sel].ready = val & 1;\n            break;\n        case VIRTIO_MMIO_QUEUE_NOTIFY:\n            if (val < MAX_QUEUE)\n                queue_notify(s, val);\n            break;\n        case VIRTIO_MMIO_INTERRUPT_ACK:\n            s->int_status &= ~val;\n            if (s->int_status == 0) {\n                set_irq(s->irq, 0);\n            }\n            break;\n        }\n    }\n}\n\nstatic uint32_t virtio_pci_read(void *opaque, uint32_t offset1, int size_log2)\n{\n    VIRTIODevice *s = opaque;\n    uint32_t offset;\n    uint32_t val = 0;\n\n    offset = offset1 & 0xfff;\n    switch(offset1 >> 12) {\n    case VIRTIO_PCI_CFG_OFFSET >> 12:\n        if (size_log2 == 2) {\n            switch(offset) {\n            case VIRTIO_PCI_DEVICE_FEATURE:\n                switch(s->device_features_sel) {\n                case 0:\n                    val = s->device_features;\n                    break;\n                case 1:\n                    val = 1; /* version 1 */\n                    break;\n                default:\n                    val = 0;\n                    break;\n                }\n                break;\n            case VIRTIO_PCI_DEVICE_FEATURE_SEL:\n                val = s->device_features_sel;\n                break;\n            case VIRTIO_PCI_QUEUE_DESC_LOW:\n                val = s->queue[s->queue_sel].desc_addr;\n                break;\n            case VIRTIO_PCI_QUEUE_AVAIL_LOW:\n                val = s->queue[s->queue_sel].avail_addr;\n                break;\n            case VIRTIO_PCI_QUEUE_USED_LOW:\n                val = s->queue[s->queue_sel].used_addr;\n                break;\n#if VIRTIO_ADDR_BITS == 64\n            case VIRTIO_PCI_QUEUE_DESC_HIGH:\n                val = s->queue[s->queue_sel].desc_addr >> 32;\n                break;\n            case VIRTIO_PCI_QUEUE_AVAIL_HIGH:\n                val = s->queue[s->queue_sel].avail_addr >> 32;\n                break;\n            case VIRTIO_PCI_QUEUE_USED_HIGH:\n                val = s->queue[s->queue_sel].used_addr >> 32;\n                break;\n#endif\n            }\n        } else if (size_log2 == 1) {\n            switch(offset) {\n            case VIRTIO_PCI_NUM_QUEUES:\n                val = MAX_QUEUE_NUM;\n                break;\n            case VIRTIO_PCI_QUEUE_SEL:\n                val = s->queue_sel;\n                break;\n            case VIRTIO_PCI_QUEUE_SIZE:\n                val = s->queue[s->queue_sel].num;\n                break;\n            case VIRTIO_PCI_QUEUE_ENABLE:\n                val = s->queue[s->queue_sel].ready;\n                break;\n            case VIRTIO_PCI_QUEUE_NOTIFY_OFF:\n                val = 0;\n                break;\n            }\n        } else if (size_log2 == 0) {\n            switch(offset) {\n            case VIRTIO_PCI_DEVICE_STATUS:\n                val = s->status;\n                break;\n            }\n        }\n        break;\n    case VIRTIO_PCI_ISR_OFFSET >> 12:\n        if (offset == 0 && size_log2 == 0) {\n            val = s->int_status;\n            s->int_status = 0;\n            set_irq(s->irq, 0);\n        }\n        break;\n    case VIRTIO_PCI_CONFIG_OFFSET >> 12:\n        val = virtio_config_read(s, offset, size_log2);\n        break;\n    }\n#ifdef DEBUG_VIRTIO\n    if (s->debug & VIRTIO_DEBUG_IO) {\n        printf(\"virto_pci_read: offset=0x%x val=0x%x size=%d\\n\", \n               offset1, val, 1 << size_log2);\n    }\n#endif\n    return val;\n}\n\nstatic void virtio_pci_write(void *opaque, uint32_t offset1,\n                             uint32_t val, int size_log2)\n{\n    VIRTIODevice *s = opaque;\n    uint32_t offset;\n    \n#ifdef DEBUG_VIRTIO\n    if (s->debug & VIRTIO_DEBUG_IO) {\n        printf(\"virto_pci_write: offset=0x%x val=0x%x size=%d\\n\",\n               offset1, val, 1 << size_log2);\n    }\n#endif\n    offset = offset1 & 0xfff;\n    switch(offset1 >> 12) {\n    case VIRTIO_PCI_CFG_OFFSET >> 12:\n        if (size_log2 == 2) {\n            switch(offset) {\n            case VIRTIO_PCI_DEVICE_FEATURE_SEL:\n                s->device_features_sel = val;\n                break;\n            case VIRTIO_PCI_QUEUE_DESC_LOW:\n                set_low32(&s->queue[s->queue_sel].desc_addr, val);\n                break;\n            case VIRTIO_PCI_QUEUE_AVAIL_LOW:\n                set_low32(&s->queue[s->queue_sel].avail_addr, val);\n                break;\n            case VIRTIO_PCI_QUEUE_USED_LOW:\n                set_low32(&s->queue[s->queue_sel].used_addr, val);\n                break;\n#if VIRTIO_ADDR_BITS == 64\n            case VIRTIO_PCI_QUEUE_DESC_HIGH:\n                set_high32(&s->queue[s->queue_sel].desc_addr, val);\n                break;\n            case VIRTIO_PCI_QUEUE_AVAIL_HIGH:\n                set_high32(&s->queue[s->queue_sel].avail_addr, val);\n                break;\n            case VIRTIO_PCI_QUEUE_USED_HIGH:\n                set_high32(&s->queue[s->queue_sel].used_addr, val);\n                break;\n#endif\n            }\n        } else if (size_log2 == 1) {\n            switch(offset) {\n            case VIRTIO_PCI_QUEUE_SEL:\n                if (val < MAX_QUEUE)\n                    s->queue_sel = val;\n                break;\n            case VIRTIO_PCI_QUEUE_SIZE:\n                if ((val & (val - 1)) == 0 && val > 0) {\n                    s->queue[s->queue_sel].num = val;\n                }\n                break;\n            case VIRTIO_PCI_QUEUE_ENABLE:\n                s->queue[s->queue_sel].ready = val & 1;\n                break;\n            }\n        } else if (size_log2 == 0) {\n            switch(offset) {\n            case VIRTIO_PCI_DEVICE_STATUS:\n                s->status = val;\n                if (val == 0) {\n                    /* reset */\n                    set_irq(s->irq, 0);\n                    virtio_reset(s);\n                }\n                break;\n            }\n        }\n        break;\n    case VIRTIO_PCI_CONFIG_OFFSET >> 12:\n        virtio_config_write(s, offset, val, size_log2);\n        break;\n    case VIRTIO_PCI_NOTIFY_OFFSET >> 12:\n        if (val < MAX_QUEUE)\n            queue_notify(s, val);\n        break;\n    }\n}\n\nvoid virtio_set_debug(VIRTIODevice *s, int debug)\n{\n    s->debug = debug;\n}\n\nstatic void virtio_config_change_notify(VIRTIODevice *s)\n{\n    /* INT_CONFIG interrupt */\n    s->int_status |= 2;\n    set_irq(s->irq, 1);\n}\n\n/*********************************************************************/\n/* block device */\n\ntypedef struct {\n    uint32_t type;\n    uint8_t *buf;\n    int write_size;\n    int queue_idx;\n    int desc_idx;\n} BlockRequest;\n\ntypedef struct VIRTIOBlockDevice {\n    VIRTIODevice common;\n    BlockDevice *bs;\n\n    BOOL req_in_progress;\n    BlockRequest req; /* request in progress */\n} VIRTIOBlockDevice;\n\ntypedef struct {\n    uint32_t type;\n    uint32_t ioprio;\n    uint64_t sector_num;\n} BlockRequestHeader;\n\n#define VIRTIO_BLK_T_IN          0\n#define VIRTIO_BLK_T_OUT         1\n#define VIRTIO_BLK_T_FLUSH       4\n#define VIRTIO_BLK_T_FLUSH_OUT   5\n\n#define VIRTIO_BLK_S_OK     0\n#define VIRTIO_BLK_S_IOERR  1\n#define VIRTIO_BLK_S_UNSUPP 2\n\n#define SECTOR_SIZE 512\n\nstatic void virtio_block_req_end(VIRTIODevice *s, int ret)\n{\n    VIRTIOBlockDevice *s1 = (VIRTIOBlockDevice *)s;\n    int write_size;\n    int queue_idx = s1->req.queue_idx;\n    int desc_idx = s1->req.desc_idx;\n    uint8_t *buf, buf1[1];\n\n    switch(s1->req.type) {\n    case VIRTIO_BLK_T_IN:\n        write_size = s1->req.write_size;\n        buf = s1->req.buf;\n        if (ret < 0) {\n            buf[write_size - 1] = VIRTIO_BLK_S_IOERR;\n        } else {\n            buf[write_size - 1] = VIRTIO_BLK_S_OK;\n        }\n        memcpy_to_queue(s, queue_idx, desc_idx, 0, buf, write_size);\n        free(buf);\n        virtio_consume_desc(s, queue_idx, desc_idx, write_size);\n        break;\n    case VIRTIO_BLK_T_OUT:\n        if (ret < 0)\n            buf1[0] = VIRTIO_BLK_S_IOERR;\n        else\n            buf1[0] = VIRTIO_BLK_S_OK;\n        memcpy_to_queue(s, queue_idx, desc_idx, 0, buf1, sizeof(buf1));\n        virtio_consume_desc(s, queue_idx, desc_idx, 1);\n        break;\n    default:\n        abort();\n    }\n}\n\nstatic void virtio_block_req_cb(void *opaque, int ret)\n{\n    VIRTIODevice *s = opaque;\n    VIRTIOBlockDevice *s1 = (VIRTIOBlockDevice *)s;\n\n    virtio_block_req_end(s, ret);\n    \n    s1->req_in_progress = FALSE;\n\n    /* handle next requests */\n    queue_notify((VIRTIODevice *)s, s1->req.queue_idx);\n}\n\n/* XXX: handle async I/O */\nstatic int virtio_block_recv_request(VIRTIODevice *s, int queue_idx,\n                                     int desc_idx, int read_size,\n                                     int write_size)\n{\n    VIRTIOBlockDevice *s1 = (VIRTIOBlockDevice *)s;\n    BlockDevice *bs = s1->bs;\n    BlockRequestHeader h;\n    uint8_t *buf;\n    int len, ret;\n\n    if (s1->req_in_progress)\n        return -1;\n    \n    if (memcpy_from_queue(s, &h, queue_idx, desc_idx, 0, sizeof(h)) < 0)\n        return 0;\n    s1->req.type = h.type;\n    s1->req.queue_idx = queue_idx;\n    s1->req.desc_idx = desc_idx;\n    switch(h.type) {\n    case VIRTIO_BLK_T_IN:\n        s1->req.buf = malloc(write_size);\n        s1->req.write_size = write_size;\n        ret = bs->read_async(bs, h.sector_num, s1->req.buf, \n                             (write_size - 1) / SECTOR_SIZE,\n                             virtio_block_req_cb, s);\n        if (ret > 0) {\n            /* asyncronous read */\n            s1->req_in_progress = TRUE;\n        } else {\n            virtio_block_req_end(s, ret);\n        }\n        break;\n    case VIRTIO_BLK_T_OUT:\n        assert(write_size >= 1);\n        len = read_size - sizeof(h);\n        buf = malloc(len);\n        memcpy_from_queue(s, buf, queue_idx, desc_idx, sizeof(h), len);\n        ret = bs->write_async(bs, h.sector_num, buf, len / SECTOR_SIZE,\n                              virtio_block_req_cb, s);\n        free(buf);\n        if (ret > 0) {\n            /* asyncronous write */\n            s1->req_in_progress = TRUE;\n        } else {\n            virtio_block_req_end(s, ret);\n        }\n        break;\n    default:\n        break;\n    }\n    return 0;\n}\n\nVIRTIODevice *virtio_block_init(VIRTIOBusDef *bus, BlockDevice *bs)\n{\n    VIRTIOBlockDevice *s;\n    uint64_t nb_sectors;\n\n    s = mallocz(sizeof(*s));\n    virtio_init(&s->common, bus,\n                2, 8, virtio_block_recv_request);\n    s->bs = bs;\n    \n    nb_sectors = bs->get_sector_count(bs);\n    put_le32(s->common.config_space, nb_sectors);\n    put_le32(s->common.config_space + 4, nb_sectors >> 32);\n\n    return (VIRTIODevice *)s;\n}\n\n/*********************************************************************/\n/* network device */\n\ntypedef struct VIRTIONetDevice {\n    VIRTIODevice common;\n    EthernetDevice *es;\n    int header_size;\n} VIRTIONetDevice;\n\ntypedef struct {\n    uint8_t flags;\n    uint8_t gso_type;\n    uint16_t hdr_len;\n    uint16_t gso_size;\n    uint16_t csum_start;\n    uint16_t csum_offset;\n    uint16_t num_buffers;\n} VIRTIONetHeader;\n\nstatic int virtio_net_recv_request(VIRTIODevice *s, int queue_idx,\n                                   int desc_idx, int read_size,\n                                   int write_size)\n{\n    VIRTIONetDevice *s1 = (VIRTIONetDevice *)s;\n    EthernetDevice *es = s1->es;\n    VIRTIONetHeader h;\n    uint8_t *buf;\n    int len;\n\n    if (queue_idx == 1) {\n        /* send to network */\n        if (memcpy_from_queue(s, &h, queue_idx, desc_idx, 0, s1->header_size) < 0)\n            return 0;\n        len = read_size - s1->header_size;\n        buf = malloc(len);\n        memcpy_from_queue(s, buf, queue_idx, desc_idx, s1->header_size, len);\n        es->write_packet(es, buf, len);\n        free(buf);\n        virtio_consume_desc(s, queue_idx, desc_idx, 0);\n    }\n    return 0;\n}\n\nstatic BOOL virtio_net_can_write_packet(EthernetDevice *es)\n{\n    VIRTIODevice *s = es->device_opaque;\n    QueueState *qs = &s->queue[0];\n    uint16_t avail_idx;\n\n    if (!qs->ready)\n        return FALSE;\n    avail_idx = virtio_read16(s, qs->avail_addr + 2);\n    return qs->last_avail_idx != avail_idx;\n}\n\nstatic void virtio_net_write_packet(EthernetDevice *es, const uint8_t *buf, int buf_len)\n{\n    VIRTIODevice *s = es->device_opaque;\n    VIRTIONetDevice *s1 = (VIRTIONetDevice *)s;\n    int queue_idx = 0;\n    QueueState *qs = &s->queue[queue_idx];\n    int desc_idx;\n    VIRTIONetHeader h;\n    int len, read_size, write_size;\n    uint16_t avail_idx;\n\n    if (!qs->ready)\n        return;\n    avail_idx = virtio_read16(s, qs->avail_addr + 2);\n    if (qs->last_avail_idx == avail_idx)\n        return;\n    desc_idx = virtio_read16(s, qs->avail_addr + 4 + \n                             (qs->last_avail_idx & (qs->num - 1)) * 2);\n    if (get_desc_rw_size(s, &read_size, &write_size, queue_idx, desc_idx))\n        return;\n    len = s1->header_size + buf_len; \n    if (len > write_size)\n        return;\n    memset(&h, 0, s1->header_size);\n    memcpy_to_queue(s, queue_idx, desc_idx, 0, &h, s1->header_size);\n    memcpy_to_queue(s, queue_idx, desc_idx, s1->header_size, buf, buf_len);\n    virtio_consume_desc(s, queue_idx, desc_idx, len);\n    qs->last_avail_idx++;\n}\n\nstatic void virtio_net_set_carrier(EthernetDevice *es, BOOL carrier_state)\n{\n#if 0\n    VIRTIODevice *s1 = es->device_opaque;\n    VIRTIONetDevice *s = (VIRTIONetDevice *)s1;\n    int cur_carrier_state;\n\n    //    printf(\"virtio_net_set_carrier: %d\\n\", carrier_state);\n    cur_carrier_state = s->common.config_space[6] & 1;\n    if (cur_carrier_state != carrier_state) {\n        s->common.config_space[6] = (carrier_state << 0);\n        virtio_config_change_notify(s1);\n    }\n#endif\n}\n\nVIRTIODevice *virtio_net_init(VIRTIOBusDef *bus, EthernetDevice *es)\n{\n    VIRTIONetDevice *s;\n\n    s = mallocz(sizeof(*s));\n    virtio_init(&s->common, bus,\n                1, 6 + 2, virtio_net_recv_request);\n    /* VIRTIO_NET_F_MAC, VIRTIO_NET_F_STATUS */\n    s->common.device_features = (1 << 5) /* | (1 << 16) */;\n    s->common.queue[0].manual_recv = TRUE;\n    s->es = es;\n    memcpy(s->common.config_space, es->mac_addr, 6);\n    /* status */\n    s->common.config_space[6] = 0;\n    s->common.config_space[7] = 0;\n\n    s->header_size = sizeof(VIRTIONetHeader);\n    \n    es->device_opaque = s;\n    es->device_can_write_packet = virtio_net_can_write_packet;\n    es->device_write_packet = virtio_net_write_packet;\n    es->device_set_carrier = virtio_net_set_carrier;\n    return (VIRTIODevice *)s;\n}\n\n/*********************************************************************/\n/* console device */\n\ntypedef struct VIRTIOConsoleDevice {\n    VIRTIODevice common;\n    CharacterDevice *cs;\n} VIRTIOConsoleDevice;\n\nstatic int virtio_console_recv_request(VIRTIODevice *s, int queue_idx,\n                                       int desc_idx, int read_size,\n                                       int write_size)\n{\n    VIRTIOConsoleDevice *s1 = (VIRTIOConsoleDevice *)s;\n    CharacterDevice *cs = s1->cs;\n    uint8_t *buf;\n\n    if (queue_idx == 1) {\n        /* send to console */\n        buf = malloc(read_size);\n        memcpy_from_queue(s, buf, queue_idx, desc_idx, 0, read_size);\n        cs->write_data(cs->opaque, buf, read_size);\n        free(buf);\n        virtio_consume_desc(s, queue_idx, desc_idx, 0);\n    }\n    return 0;\n}\n\nBOOL virtio_console_can_write_data(VIRTIODevice *s)\n{\n    QueueState *qs = &s->queue[0];\n    uint16_t avail_idx;\n\n    if (!qs->ready)\n        return FALSE;\n    avail_idx = virtio_read16(s, qs->avail_addr + 2);\n    return qs->last_avail_idx != avail_idx;\n}\n\nint virtio_console_get_write_len(VIRTIODevice *s)\n{\n    int queue_idx = 0;\n    QueueState *qs = &s->queue[queue_idx];\n    int desc_idx;\n    int read_size, write_size;\n    uint16_t avail_idx;\n\n    if (!qs->ready)\n        return 0;\n    avail_idx = virtio_read16(s, qs->avail_addr + 2);\n    if (qs->last_avail_idx == avail_idx)\n        return 0;\n    desc_idx = virtio_read16(s, qs->avail_addr + 4 + \n                             (qs->last_avail_idx & (qs->num - 1)) * 2);\n    if (get_desc_rw_size(s, &read_size, &write_size, queue_idx, desc_idx))\n        return 0;\n    return write_size;\n}\n\nint virtio_console_write_data(VIRTIODevice *s, const uint8_t *buf, int buf_len)\n{\n    int queue_idx = 0;\n    QueueState *qs = &s->queue[queue_idx];\n    int desc_idx;\n    uint16_t avail_idx;\n\n    if (!qs->ready)\n        return 0;\n    avail_idx = virtio_read16(s, qs->avail_addr + 2);\n    if (qs->last_avail_idx == avail_idx)\n        return 0;\n    desc_idx = virtio_read16(s, qs->avail_addr + 4 + \n                             (qs->last_avail_idx & (qs->num - 1)) * 2);\n    memcpy_to_queue(s, queue_idx, desc_idx, 0, buf, buf_len);\n    virtio_consume_desc(s, queue_idx, desc_idx, buf_len);\n    qs->last_avail_idx++;\n    return buf_len;\n}\n\n/* send a resize event */\nvoid virtio_console_resize_event(VIRTIODevice *s, int width, int height)\n{\n    /* indicate the console size */\n    put_le16(s->config_space + 0, width);\n    put_le16(s->config_space + 2, height);\n\n    virtio_config_change_notify(s);\n}\n\nVIRTIODevice *virtio_console_init(VIRTIOBusDef *bus, CharacterDevice *cs)\n{\n    VIRTIOConsoleDevice *s;\n\n    s = mallocz(sizeof(*s));\n    virtio_init(&s->common, bus,\n                3, 4, virtio_console_recv_request);\n    s->common.device_features = (1 << 0); /* VIRTIO_CONSOLE_F_SIZE */\n    s->common.queue[0].manual_recv = TRUE;\n    \n    s->cs = cs;\n    return (VIRTIODevice *)s;\n}\n\n/*********************************************************************/\n/* input device */\n\nenum {\n    VIRTIO_INPUT_CFG_UNSET      = 0x00,\n    VIRTIO_INPUT_CFG_ID_NAME    = 0x01,\n    VIRTIO_INPUT_CFG_ID_SERIAL  = 0x02,\n    VIRTIO_INPUT_CFG_ID_DEVIDS  = 0x03,\n    VIRTIO_INPUT_CFG_PROP_BITS  = 0x10,\n    VIRTIO_INPUT_CFG_EV_BITS    = 0x11,\n    VIRTIO_INPUT_CFG_ABS_INFO   = 0x12,\n};\n\n#define VIRTIO_INPUT_EV_SYN 0x00\n#define VIRTIO_INPUT_EV_KEY 0x01\n#define VIRTIO_INPUT_EV_REL 0x02\n#define VIRTIO_INPUT_EV_ABS 0x03\n#define VIRTIO_INPUT_EV_REP 0x14\n\n#define BTN_LEFT         0x110\n#define BTN_RIGHT        0x111\n#define BTN_MIDDLE       0x112\n#define BTN_GEAR_DOWN    0x150\n#define BTN_GEAR_UP      0x151\n\n#define REL_X 0x00\n#define REL_Y 0x01\n#define REL_Z 0x02\n#define REL_WHEEL 0x08\n\n#define ABS_X 0x00\n#define ABS_Y 0x01\n#define ABS_Z 0x02\n\ntypedef struct VIRTIOInputDevice {\n    VIRTIODevice common;\n    VirtioInputTypeEnum type;\n    uint32_t buttons_state;\n} VIRTIOInputDevice;\n\nstatic const uint16_t buttons_list[] = {\n    BTN_LEFT, BTN_RIGHT, BTN_MIDDLE\n};\n\nstatic int virtio_input_recv_request(VIRTIODevice *s, int queue_idx,\n                                      int desc_idx, int read_size,\n                                      int write_size)\n{\n    if (queue_idx == 1) {\n        /* led & keyboard updates */\n        //        printf(\"%s: write_size=%d\\n\", __func__, write_size);\n        virtio_consume_desc(s, queue_idx, desc_idx, 0);\n    }\n    return 0;\n}\n\n/* return < 0 if could not send key event */\nstatic int virtio_input_queue_event(VIRTIODevice *s,\n                                    uint16_t type, uint16_t code,\n                                    uint32_t value)\n{\n    int queue_idx = 0;\n    QueueState *qs = &s->queue[queue_idx];\n    int desc_idx, buf_len;\n    uint16_t avail_idx;\n    uint8_t buf[8];\n\n    if (!qs->ready)\n        return -1;\n\n    put_le16(buf, type);\n    put_le16(buf + 2, code);\n    put_le32(buf + 4, value);\n    buf_len = 8;\n    \n    avail_idx = virtio_read16(s, qs->avail_addr + 2);\n    if (qs->last_avail_idx == avail_idx)\n        return -1;\n    desc_idx = virtio_read16(s, qs->avail_addr + 4 + \n                             (qs->last_avail_idx & (qs->num - 1)) * 2);\n    //    printf(\"send: queue_idx=%d desc_idx=%d\\n\", queue_idx, desc_idx);\n    memcpy_to_queue(s, queue_idx, desc_idx, 0, buf, buf_len);\n    virtio_consume_desc(s, queue_idx, desc_idx, buf_len);\n    qs->last_avail_idx++;\n    return 0;\n}\n\nint virtio_input_send_key_event(VIRTIODevice *s, BOOL is_down,\n                                uint16_t key_code)\n{\n    VIRTIOInputDevice *s1 = (VIRTIOInputDevice *)s;\n    int ret;\n    \n    if (s1->type != VIRTIO_INPUT_TYPE_KEYBOARD)\n        return -1;\n    ret = virtio_input_queue_event(s, VIRTIO_INPUT_EV_KEY, key_code, is_down);\n    if (ret)\n        return ret;\n    return virtio_input_queue_event(s, VIRTIO_INPUT_EV_SYN, 0, 0);\n}\n\n/* also used for the tablet */\nint virtio_input_send_mouse_event(VIRTIODevice *s, int dx, int dy, int dz,\n                                  unsigned int buttons)\n{\n    VIRTIOInputDevice *s1 = (VIRTIOInputDevice *)s;\n    int ret, i, b, last_b;\n\n    if (s1->type != VIRTIO_INPUT_TYPE_MOUSE &&\n        s1->type != VIRTIO_INPUT_TYPE_TABLET)\n        return -1;\n    if (s1->type == VIRTIO_INPUT_TYPE_MOUSE) {\n        ret = virtio_input_queue_event(s, VIRTIO_INPUT_EV_REL, REL_X, dx);\n        if (ret != 0)\n            return ret;\n        ret = virtio_input_queue_event(s, VIRTIO_INPUT_EV_REL, REL_Y, dy);\n        if (ret != 0)\n            return ret;\n    } else {\n        ret = virtio_input_queue_event(s, VIRTIO_INPUT_EV_ABS, ABS_X, dx);\n        if (ret != 0)\n            return ret;\n        ret = virtio_input_queue_event(s, VIRTIO_INPUT_EV_ABS, ABS_Y, dy);\n        if (ret != 0)\n            return ret;\n    }\n    if (dz != 0) {\n        ret = virtio_input_queue_event(s, VIRTIO_INPUT_EV_REL, REL_WHEEL, dz);\n        if (ret != 0)\n            return ret;\n    }\n\n    if (buttons != s1->buttons_state) {\n        for(i = 0; i < countof(buttons_list); i++) {\n            b = (buttons >> i) & 1;\n            last_b = (s1->buttons_state >> i) & 1;\n            if (b != last_b) {\n                ret = virtio_input_queue_event(s, VIRTIO_INPUT_EV_KEY,\n                                               buttons_list[i], b);\n                if (ret != 0)\n                    return ret;\n            }\n        }\n        s1->buttons_state = buttons;\n    }\n\n    return virtio_input_queue_event(s, VIRTIO_INPUT_EV_SYN, 0, 0);\n}\n\nstatic void set_bit(uint8_t *tab, int k)\n{\n    tab[k >> 3] |= 1 << (k & 7);\n}\n\nstatic void virtio_input_config_write(VIRTIODevice *s)\n{\n    VIRTIOInputDevice *s1 = (VIRTIOInputDevice *)s;\n    uint8_t *config = s->config_space;\n    int i;\n    \n    //    printf(\"config_write: %02x %02x\\n\", config[0], config[1]);\n    switch(config[0]) {\n    case VIRTIO_INPUT_CFG_UNSET:\n        break;\n    case VIRTIO_INPUT_CFG_ID_NAME:\n        {\n            const char *name;\n            int len;\n            switch(s1->type) {\n            case VIRTIO_INPUT_TYPE_KEYBOARD:\n                name = \"virtio_keyboard\";\n                break;\n            case VIRTIO_INPUT_TYPE_MOUSE:\n                name = \"virtio_mouse\";\n                break;\n            case VIRTIO_INPUT_TYPE_TABLET:\n                name = \"virtio_tablet\";\n                break;\n            default:\n                abort();\n            }\n            len = strlen(name);\n            config[2] = len;\n            memcpy(config + 8, name, len);\n        }\n        break;\n    default:\n    case VIRTIO_INPUT_CFG_ID_SERIAL:\n    case VIRTIO_INPUT_CFG_ID_DEVIDS:\n    case VIRTIO_INPUT_CFG_PROP_BITS:\n        config[2] = 0; /* size of reply */\n        break;\n    case VIRTIO_INPUT_CFG_EV_BITS:\n        config[2] = 0;\n        switch(s1->type) {\n        case VIRTIO_INPUT_TYPE_KEYBOARD:\n            switch(config[1]) {\n            case VIRTIO_INPUT_EV_KEY:\n                config[2] = 128 / 8;\n                memset(config + 8, 0xff, 128 / 8); /* bitmap */\n                break;\n            case VIRTIO_INPUT_EV_REP: /* allow key repetition */\n                config[2] = 1;\n                break;\n            default:\n                break;\n            }\n            break;\n        case VIRTIO_INPUT_TYPE_MOUSE:\n            switch(config[1]) {\n            case VIRTIO_INPUT_EV_KEY:\n                config[2] = 512 / 8;\n                memset(config + 8, 0, 512 / 8); /* bitmap */\n                for(i = 0; i < countof(buttons_list); i++)\n                    set_bit(config + 8, buttons_list[i]);\n                break;\n            case VIRTIO_INPUT_EV_REL:\n                config[2] = 2;\n                config[8] = 0;\n                config[9] = 0;\n                set_bit(config + 8, REL_X);\n                set_bit(config + 8, REL_Y);\n                set_bit(config + 8, REL_WHEEL);\n                break;\n            default:\n                break;\n            }\n            break;\n        case VIRTIO_INPUT_TYPE_TABLET:\n            switch(config[1]) {\n            case VIRTIO_INPUT_EV_KEY:\n                config[2] = 512 / 8;\n                memset(config + 8, 0, 512 / 8); /* bitmap */\n                for(i = 0; i < countof(buttons_list); i++)\n                    set_bit(config + 8, buttons_list[i]);\n                break;\n            case VIRTIO_INPUT_EV_REL:\n                config[2] = 2;\n                config[8] = 0;\n                config[9] = 0;\n                set_bit(config + 8, REL_WHEEL);\n                break;\n            case VIRTIO_INPUT_EV_ABS:\n                config[2] = 1;\n                config[8] = 0;\n                set_bit(config + 8, ABS_X);\n                set_bit(config + 8, ABS_Y);\n                break;\n            default:\n                break;\n            }\n            break;\n        default:\n            abort();\n        }\n        break;\n    case VIRTIO_INPUT_CFG_ABS_INFO:\n        if (s1->type == VIRTIO_INPUT_TYPE_TABLET && config[1] <= 1) {\n            /* for ABS_X and ABS_Y */\n            config[2] = 5 * 4;\n            put_le32(config + 8, 0); /* min */\n            put_le32(config + 12, VIRTIO_INPUT_ABS_SCALE - 1) ; /* max */\n            put_le32(config + 16, 0); /* fuzz */\n            put_le32(config + 20, 0); /* flat */\n            put_le32(config + 24, 0); /* res */\n        }\n        break;\n    }\n}\n\nVIRTIODevice *virtio_input_init(VIRTIOBusDef *bus, VirtioInputTypeEnum type)\n{\n    VIRTIOInputDevice *s;\n\n    s = mallocz(sizeof(*s));\n    virtio_init(&s->common, bus,\n                18, 256, virtio_input_recv_request);\n    s->common.queue[0].manual_recv = TRUE;\n    s->common.device_features = 0;\n    s->common.config_write = virtio_input_config_write;\n    s->type = type;\n    return (VIRTIODevice *)s;\n}\n\n/*********************************************************************/\n/* 9p filesystem device */\n\ntypedef struct {\n    struct list_head link;\n    uint32_t fid;\n    FSFile *fd;\n} FIDDesc;\n\ntypedef struct VIRTIO9PDevice {\n    VIRTIODevice common;\n    FSDevice *fs;\n    int msize; /* maximum message size */\n    struct list_head fid_list; /* list of FIDDesc */\n    BOOL req_in_progress;\n} VIRTIO9PDevice;\n\nstatic FIDDesc *fid_find1(VIRTIO9PDevice *s, uint32_t fid)\n{\n    struct list_head *el;\n    FIDDesc *f;\n\n    list_for_each(el, &s->fid_list) {\n        f = list_entry(el, FIDDesc, link);\n        if (f->fid == fid)\n            return f;\n    }\n    return NULL;\n}\n\nstatic FSFile *fid_find(VIRTIO9PDevice *s, uint32_t fid)\n{\n    FIDDesc *f;\n\n    f = fid_find1(s, fid);\n    if (!f)\n        return NULL;\n    return f->fd;\n}\n\nstatic void fid_delete(VIRTIO9PDevice *s, uint32_t fid)\n{\n    FIDDesc *f;\n\n    f = fid_find1(s, fid);\n    if (f) {\n        s->fs->fs_delete(s->fs, f->fd);\n        list_del(&f->link);\n        free(f);\n    }\n}\n\nstatic void fid_set(VIRTIO9PDevice *s, uint32_t fid, FSFile *fd)\n{\n    FIDDesc *f;\n\n    f = fid_find1(s, fid);\n    if (f) {\n        s->fs->fs_delete(s->fs, f->fd);\n        f->fd = fd;\n    } else {\n        f = malloc(sizeof(*f));\n        f->fid = fid;\n        f->fd = fd;\n        list_add(&f->link, &s->fid_list);\n    }\n}\n\n#ifdef DEBUG_VIRTIO\n\ntypedef struct {\n    uint8_t tag;\n    const char *name;\n} Virtio9POPName;\n\nstatic const Virtio9POPName virtio_9p_op_names[] = {\n    { 8, \"statfs\" },\n    { 12, \"lopen\" },\n    { 14, \"lcreate\" },\n    { 16, \"symlink\" },\n    { 18, \"mknod\" },\n    { 22, \"readlink\" },\n    { 24, \"getattr\" },\n    { 26, \"setattr\" },\n    { 30, \"xattrwalk\" },\n    { 40, \"readdir\" },\n    { 50, \"fsync\" },\n    { 52, \"lock\" },\n    { 54, \"getlock\" },\n    { 70, \"link\" },\n    { 72, \"mkdir\" },\n    { 74, \"renameat\" },\n    { 76, \"unlinkat\" },\n    { 100, \"version\" },\n    { 104, \"attach\" },\n    { 108, \"flush\" },\n    { 110, \"walk\" },\n    { 116, \"read\" },\n    { 118, \"write\" },\n    { 120, \"clunk\" },\n    { 0, NULL },\n};\n\nstatic const char *get_9p_op_name(int tag)\n{\n    const Virtio9POPName *p;\n    for(p = virtio_9p_op_names; p->name != NULL; p++) {\n        if (p->tag == tag)\n            return p->name;\n    }\n    return NULL;\n}\n\n#endif /* DEBUG_VIRTIO */\n\nstatic int marshall(VIRTIO9PDevice *s, \n                    uint8_t *buf1, int max_len, const char *fmt, ...)\n{\n    va_list ap;\n    int c;\n    uint32_t val;\n    uint64_t val64;\n    uint8_t *buf, *buf_end;\n\n#ifdef DEBUG_VIRTIO\n    if (s->common.debug & VIRTIO_DEBUG_9P)\n        printf(\" ->\");\n#endif\n    va_start(ap, fmt);\n    buf = buf1;\n    buf_end = buf1 + max_len;\n    for(;;) {\n        c = *fmt++;\n        if (c == '\\0')\n            break;\n        switch(c) {\n        case 'b':\n            assert(buf + 1 <= buf_end);\n            val = va_arg(ap, int);\n#ifdef DEBUG_VIRTIO\n            if (s->common.debug & VIRTIO_DEBUG_9P)\n                printf(\" b=%d\", val);\n#endif\n            buf[0] = val;\n            buf += 1;\n            break;\n        case 'h':\n            assert(buf + 2 <= buf_end);\n            val = va_arg(ap, int);\n#ifdef DEBUG_VIRTIO\n            if (s->common.debug & VIRTIO_DEBUG_9P)\n                printf(\" h=%d\", val);\n#endif\n            put_le16(buf, val);\n            buf += 2;\n            break;\n        case 'w':\n            assert(buf + 4 <= buf_end);\n            val = va_arg(ap, int);\n#ifdef DEBUG_VIRTIO\n            if (s->common.debug & VIRTIO_DEBUG_9P)\n                printf(\" w=%d\", val);\n#endif\n            put_le32(buf, val);\n            buf += 4;\n            break;\n        case 'd':\n            assert(buf + 8 <= buf_end);\n            val64 = va_arg(ap, uint64_t);\n#ifdef DEBUG_VIRTIO\n            if (s->common.debug & VIRTIO_DEBUG_9P)\n                printf(\" d=%\" PRId64, val64);\n#endif\n            put_le64(buf, val64);\n            buf += 8;\n            break;\n        case 's':\n            {\n                char *str;\n                int len;\n                str = va_arg(ap, char *);\n#ifdef DEBUG_VIRTIO\n                if (s->common.debug & VIRTIO_DEBUG_9P)\n                    printf(\" s=\\\"%s\\\"\", str);\n#endif\n                len = strlen(str);\n                assert(len <= 65535);\n                assert(buf + 2 + len <= buf_end);\n                put_le16(buf, len);\n                buf += 2;\n                memcpy(buf, str, len);\n                buf += len;\n            }\n            break;\n        case 'Q':\n            {\n                FSQID *qid;\n                assert(buf + 13 <= buf_end);\n                qid = va_arg(ap, FSQID *);\n#ifdef DEBUG_VIRTIO\n                if (s->common.debug & VIRTIO_DEBUG_9P)\n                    printf(\" Q=%d:%d:%\" PRIu64, qid->type, qid->version, qid->path);\n#endif\n                buf[0] = qid->type;\n                put_le32(buf + 1, qid->version);\n                put_le64(buf + 5, qid->path);\n                buf += 13;\n            }\n            break;\n        default:\n            abort();\n        }\n    }\n    va_end(ap);\n    return buf - buf1;\n}\n\n/* return < 0 if error */\n/* XXX: free allocated strings in case of error */\nstatic int unmarshall(VIRTIO9PDevice *s, int queue_idx,\n                      int desc_idx, int *poffset, const char *fmt, ...)\n{\n    VIRTIODevice *s1 = (VIRTIODevice *)s;\n    va_list ap;\n    int offset, c;\n    uint8_t buf[16];\n\n    offset = *poffset;\n    va_start(ap, fmt);\n    for(;;) {\n        c = *fmt++;\n        if (c == '\\0')\n            break;\n        switch(c) {\n        case 'b':\n            {\n                uint8_t *ptr;\n                if (memcpy_from_queue(s1, buf, queue_idx, desc_idx, offset, 1))\n                    return -1;\n                ptr = va_arg(ap, uint8_t *);\n                *ptr = buf[0];\n                offset += 1;\n#ifdef DEBUG_VIRTIO\n                if (s->common.debug & VIRTIO_DEBUG_9P)\n                    printf(\" b=%d\", *ptr);\n#endif\n            }\n            break;\n        case 'h':\n            {\n                uint16_t *ptr;\n                if (memcpy_from_queue(s1, buf, queue_idx, desc_idx, offset, 2))\n                    return -1;\n                ptr = va_arg(ap, uint16_t *);\n                *ptr = get_le16(buf);\n                offset += 2;\n#ifdef DEBUG_VIRTIO\n                if (s->common.debug & VIRTIO_DEBUG_9P)\n                    printf(\" h=%d\", *ptr);\n#endif\n            }\n            break;\n        case 'w':\n            {\n                uint32_t *ptr;\n                if (memcpy_from_queue(s1, buf, queue_idx, desc_idx, offset, 4))\n                    return -1;\n                ptr = va_arg(ap, uint32_t *);\n                *ptr = get_le32(buf);\n                offset += 4;\n#ifdef DEBUG_VIRTIO\n                if (s->common.debug & VIRTIO_DEBUG_9P)\n                    printf(\" w=%d\", *ptr);\n#endif\n            }\n            break;\n        case 'd':\n            {\n                uint64_t *ptr;\n                if (memcpy_from_queue(s1, buf, queue_idx, desc_idx, offset, 8))\n                    return -1;\n                ptr = va_arg(ap, uint64_t *);\n                *ptr = get_le64(buf);\n                offset += 8;\n#ifdef DEBUG_VIRTIO\n                if (s->common.debug & VIRTIO_DEBUG_9P)\n                    printf(\" d=%\" PRId64, *ptr);\n#endif\n            }\n            break;\n        case 's':\n            {\n                char *str, **ptr;\n                int len;\n\n                if (memcpy_from_queue(s1, buf, queue_idx, desc_idx, offset, 2))\n                    return -1;\n                len = get_le16(buf);\n                offset += 2;\n                str = malloc(len + 1);\n                if (memcpy_from_queue(s1, str, queue_idx, desc_idx, offset, len))\n                    return -1;\n                str[len] = '\\0';\n                offset += len;\n                ptr = va_arg(ap, char **);\n                *ptr = str;\n#ifdef DEBUG_VIRTIO\n                if (s->common.debug & VIRTIO_DEBUG_9P)\n                    printf(\" s=\\\"%s\\\"\", *ptr);\n#endif\n            }\n            break;\n        default:\n            abort();\n        }\n    }\n    va_end(ap);\n    *poffset = offset;\n    return 0;\n}\n\nstatic void virtio_9p_send_reply(VIRTIO9PDevice *s, int queue_idx,\n                                 int desc_idx, uint8_t id, uint16_t tag, \n                                 uint8_t *buf, int buf_len)\n{\n    uint8_t *buf1;\n    int len;\n\n#ifdef DEBUG_VIRTIO\n    if (s->common.debug & VIRTIO_DEBUG_9P) {\n        if (id == 6)\n            printf(\" (error)\");\n        printf(\"\\n\");\n    }\n#endif\n    len = buf_len + 7;\n    buf1 = malloc(len);\n    put_le32(buf1, len);\n    buf1[4] = id + 1;\n    put_le16(buf1 + 5, tag);\n    memcpy(buf1 + 7, buf, buf_len);\n    memcpy_to_queue((VIRTIODevice *)s, queue_idx, desc_idx, 0, buf1, len);\n    virtio_consume_desc((VIRTIODevice *)s, queue_idx, desc_idx, len);\n    free(buf1);\n}\n\nstatic void virtio_9p_send_error(VIRTIO9PDevice *s, int queue_idx,\n                                 int desc_idx, uint16_t tag, uint32_t error)\n{\n    uint8_t buf[4];\n    int buf_len;\n\n    buf_len = marshall(s, buf, sizeof(buf), \"w\", -error);\n    virtio_9p_send_reply(s, queue_idx, desc_idx, 6, tag, buf, buf_len);\n}\n\ntypedef struct {\n    VIRTIO9PDevice *dev;\n    int queue_idx;\n    int desc_idx;\n    uint16_t tag;\n} P9OpenInfo;\n\nstatic void virtio_9p_open_reply(FSDevice *fs, FSQID *qid, int err,\n                                 P9OpenInfo *oi)\n{\n    VIRTIO9PDevice *s = oi->dev;\n    uint8_t buf[32];\n    int buf_len;\n    \n    if (err < 0) {\n        virtio_9p_send_error(s, oi->queue_idx, oi->desc_idx, oi->tag, err);\n    } else {\n        buf_len = marshall(s, buf, sizeof(buf),\n                           \"Qw\", qid, s->msize - 24);\n        virtio_9p_send_reply(s, oi->queue_idx, oi->desc_idx, 12, oi->tag,\n                             buf, buf_len);\n    }\n    free(oi);\n}\n\nstatic void virtio_9p_open_cb(FSDevice *fs, FSQID *qid, int err,\n                              void *opaque)\n{\n    P9OpenInfo *oi = opaque;\n    VIRTIO9PDevice *s = oi->dev;\n    int queue_idx = oi->queue_idx;\n    \n    virtio_9p_open_reply(fs, qid, err, oi);\n\n    s->req_in_progress = FALSE;\n\n    /* handle next requests */\n    queue_notify((VIRTIODevice *)s, queue_idx);\n}\n\nstatic int virtio_9p_recv_request(VIRTIODevice *s1, int queue_idx,\n                                   int desc_idx, int read_size,\n                                   int write_size)\n{\n    VIRTIO9PDevice *s = (VIRTIO9PDevice *)s1;\n    int offset, header_len;\n    uint8_t id;\n    uint16_t tag;\n    uint8_t buf[1024];\n    int buf_len, err;\n    FSDevice *fs = s->fs;\n\n    if (queue_idx != 0)\n        return 0;\n    \n    if (s->req_in_progress)\n        return -1;\n    \n    offset = 0;\n    header_len = 4 + 1 + 2;\n    if (memcpy_from_queue(s1, buf, queue_idx, desc_idx, offset, header_len)) {\n        tag = 0;\n        goto protocol_error;\n    }\n    //size = get_le32(buf);\n    id = buf[4];\n    tag = get_le16(buf + 5);\n    offset += header_len;\n    \n#ifdef DEBUG_VIRTIO\n    if (s1->debug & VIRTIO_DEBUG_9P) {\n        const char *name;\n        name = get_9p_op_name(id);\n        printf(\"9p: op=\");\n        if (name)\n            printf(\"%s\", name);\n        else\n            printf(\"%d\", id);\n    }\n#endif\n    /* Note: same subset as JOR1K */\n    switch(id) {\n    case 8: /* statfs */\n        {\n            FSStatFS st;\n\n            fs->fs_statfs(fs, &st);\n            buf_len = marshall(s, buf, sizeof(buf),\n                               \"wwddddddw\", \n                               0,\n                               st.f_bsize,\n                               st.f_blocks,\n                               st.f_bfree,\n                               st.f_bavail,\n                               st.f_files,\n                               st.f_ffree,\n                               0, /* id */\n                               256 /* max filename length */\n                               );\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 12: /* lopen */\n        {\n            uint32_t fid, flags;\n            FSFile *f;\n            FSQID qid;\n            P9OpenInfo *oi;\n            \n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"ww\", &fid, &flags))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f)\n                goto fid_not_found;\n            oi = malloc(sizeof(*oi));\n            oi->dev = s;\n            oi->queue_idx = queue_idx;\n            oi->desc_idx = desc_idx;\n            oi->tag = tag;\n            err = fs->fs_open(fs, &qid, f, flags, virtio_9p_open_cb, oi);\n            if (err <= 0) {\n                virtio_9p_open_reply(fs, &qid, err, oi);\n            } else {\n                s->req_in_progress = TRUE;\n            }\n        }\n        break;\n    case 14: /* lcreate */\n        {\n            uint32_t fid, flags, mode, gid;\n            char *name;\n            FSFile *f;\n            FSQID qid;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wswww\", &fid, &name, &flags, &mode, &gid))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f) {\n                err = -P9_EPROTO;\n            } else {\n                err = fs->fs_create(fs, &qid, f, name, flags, mode, gid);\n            }\n            free(name);\n            if (err) \n                goto error;\n            buf_len = marshall(s, buf, sizeof(buf),\n                               \"Qw\", &qid, s->msize - 24);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 16: /* symlink */\n        {\n            uint32_t fid, gid;\n            char *name, *symgt;\n            FSFile *f;\n            FSQID qid;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wssw\", &fid, &name, &symgt, &gid))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f) {\n                err = -P9_EPROTO;\n            } else {\n                err = fs->fs_symlink(fs, &qid, f, name, symgt, gid);\n            }\n            free(name);\n            free(symgt);\n            if (err)\n                goto error;\n            buf_len = marshall(s, buf, sizeof(buf),\n                               \"Q\", &qid);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 18: /* mknod */\n        {\n            uint32_t fid, mode, major, minor, gid;\n            char *name;\n            FSFile *f;\n            FSQID qid;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wswwww\", &fid, &name, &mode, &major, &minor, &gid))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f) {\n                err = -P9_EPROTO;\n            } else {\n                err = fs->fs_mknod(fs, &qid, f, name, mode, major, minor, gid);\n            }\n            free(name);\n            if (err)\n                goto error;\n            buf_len = marshall(s, buf, sizeof(buf),\n                               \"Q\", &qid);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 22: /* readlink */\n        {\n            uint32_t fid;\n            char buf1[1024];\n            FSFile *f;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"w\", &fid))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f) {\n                err = -P9_EPROTO;\n            } else {\n                err = fs->fs_readlink(fs, buf1, sizeof(buf1), f);\n            }\n            if (err)\n                goto error;\n            buf_len = marshall(s, buf, sizeof(buf), \"s\", buf1);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 24: /* getattr */\n        {\n            uint32_t fid;\n            uint64_t mask;\n            FSFile *f;\n            FSStat st;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wd\", &fid, &mask))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f)\n                goto fid_not_found;\n            err = fs->fs_stat(fs, f, &st);\n            if (err)\n                goto error;\n\n            buf_len = marshall(s, buf, sizeof(buf),\n                               \"dQwwwddddddddddddddd\", \n                               mask, &st.qid,\n                               st.st_mode, st.st_uid, st.st_gid,\n                               st.st_nlink, st.st_rdev, st.st_size,\n                               st.st_blksize, st.st_blocks,\n                               st.st_atime_sec, (uint64_t)st.st_atime_nsec,\n                               st.st_mtime_sec, (uint64_t)st.st_mtime_nsec,\n                               st.st_ctime_sec, (uint64_t)st.st_ctime_nsec,\n                               (uint64_t)0, (uint64_t)0,\n                               (uint64_t)0, (uint64_t)0);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 26: /* setattr */\n        {\n            uint32_t fid, mask, mode, uid, gid;\n            uint64_t size, atime_sec, atime_nsec, mtime_sec, mtime_nsec;\n            FSFile *f;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wwwwwddddd\", &fid, &mask, &mode, &uid, &gid,\n                           &size, &atime_sec, &atime_nsec, \n                           &mtime_sec, &mtime_nsec))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f)\n                goto fid_not_found;\n            err = fs->fs_setattr(fs, f, mask, mode, uid, gid, size, atime_sec,\n                                 atime_nsec, mtime_sec, mtime_nsec);\n            if (err)\n                goto error;\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, NULL, 0);\n        }\n        break;\n    case 30: /* xattrwalk */\n        {\n            /* not supported yet */\n            err = -P9_ENOTSUP;\n            goto error;\n        }\n        break;\n    case 40: /* readdir */\n        {\n            uint32_t fid, count;\n            uint64_t offs;\n            uint8_t *buf;\n            int n;\n            FSFile *f;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wdw\", &fid, &offs, &count))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f)\n                goto fid_not_found;\n            buf = malloc(count + 4);\n            n = fs->fs_readdir(fs, f, offs, buf + 4, count);\n            if (n < 0) {\n                err = n;\n                goto error;\n            }\n            put_le32(buf, n);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, n + 4);\n            free(buf);\n        }\n        break;\n    case 50: /* fsync */\n        {\n            uint32_t fid;\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"w\", &fid))\n                goto protocol_error;\n            /* ignored */\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, NULL, 0);\n        }\n        break;\n    case 52: /* lock */\n        {\n            uint32_t fid;\n            FSFile *f;\n            FSLock lock;\n            \n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wbwddws\", &fid, &lock.type, &lock.flags,\n                           &lock.start, &lock.length,\n                           &lock.proc_id, &lock.client_id))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f)\n                err = -P9_EPROTO;\n            else\n                err = fs->fs_lock(fs, f, &lock);\n            free(lock.client_id);\n            if (err < 0)\n                goto error;\n            buf_len = marshall(s, buf, sizeof(buf), \"b\", err);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 54: /* getlock */\n        {\n            uint32_t fid;\n            FSFile *f;\n            FSLock lock;\n            \n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wbddws\", &fid, &lock.type,\n                           &lock.start, &lock.length,\n                           &lock.proc_id, &lock.client_id))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f)\n                err = -P9_EPROTO;\n            else\n                err = fs->fs_getlock(fs, f, &lock);\n            if (err < 0) {\n                free(lock.client_id);\n                goto error;\n            }\n            buf_len = marshall(s, buf, sizeof(buf), \"bddws\",\n                               &lock.type,\n                               &lock.start, &lock.length,\n                               &lock.proc_id, &lock.client_id);\n            free(lock.client_id);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 70: /* link */\n        {\n            uint32_t dfid, fid;\n            char *name;\n            FSFile *f, *df;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wws\", &dfid, &fid, &name))\n                goto protocol_error;\n            df = fid_find(s, dfid);\n            f = fid_find(s, fid);\n            if (!df || !f) {\n                err = -P9_EPROTO;\n            } else {\n                err = fs->fs_link(fs, df, f, name);\n            }\n            free(name);\n            if (err)\n                goto error;\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, NULL, 0);\n        }\n        break;\n    case 72: /* mkdir */\n        {\n            uint32_t fid, mode, gid;\n            char *name;\n            FSFile *f;\n            FSQID qid;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wsww\", &fid, &name, &mode, &gid))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f)\n                goto fid_not_found;\n            err = fs->fs_mkdir(fs, &qid, f, name, mode, gid);\n            if (err != 0)\n                goto error;\n            buf_len = marshall(s, buf, sizeof(buf), \"Q\", &qid);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 74: /* renameat */\n        {\n            uint32_t fid, new_fid;\n            char *name, *new_name;\n            FSFile *f, *new_f;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wsws\", &fid, &name, &new_fid, &new_name))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            new_f = fid_find(s, new_fid);\n            if (!f || !new_f) {\n                err = -P9_EPROTO;\n            } else {\n                err = fs->fs_renameat(fs, f, name, new_f, new_name);\n            }\n            free(name);\n            free(new_name);\n            if (err != 0)\n                goto error;\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, NULL, 0);\n        }\n        break;\n    case 76: /* unlinkat */\n        {\n            uint32_t fid, flags;\n            char *name;\n            FSFile *f;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wsw\", &fid, &name, &flags))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f) {\n                err = -P9_EPROTO;\n            } else {\n                err = fs->fs_unlinkat(fs, f, name);\n            }\n            free(name);\n            if (err != 0)\n                goto error;\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, NULL, 0);\n        }\n        break;\n    case 100: /* version */\n        {\n            uint32_t msize;\n            char *version;\n            if (unmarshall(s, queue_idx, desc_idx, &offset, \n                           \"ws\", &msize, &version))\n                goto protocol_error;\n            s->msize = msize;\n            //            printf(\"version: msize=%d version=%s\\n\", msize, version);\n            free(version);\n            buf_len = marshall(s, buf, sizeof(buf), \"ws\", s->msize, \"9P2000.L\");\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 104: /* attach */\n        {\n            uint32_t fid, afid, uid;\n            char *uname, *aname;\n            FSQID qid;\n            FSFile *f;\n            \n            if (unmarshall(s, queue_idx, desc_idx, &offset, \n                           \"wwssw\", &fid, &afid, &uname, &aname, &uid))\n                goto protocol_error;\n            err = fs->fs_attach(fs, &f, &qid, uid, uname, aname);\n            if (err != 0)\n                goto error;\n            fid_set(s, fid, f);\n            free(uname);\n            free(aname);\n            buf_len = marshall(s, buf, sizeof(buf), \"Q\", &qid);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 108: /* flush */\n        {\n            uint16_t oldtag;\n            if (unmarshall(s, queue_idx, desc_idx, &offset, \n                           \"h\", &oldtag))\n                goto protocol_error;\n            /* ignored */\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, NULL, 0);\n        }\n        break;\n    case 110: /* walk */\n        {\n            uint32_t fid, newfid;\n            uint16_t nwname;\n            FSQID *qids;\n            char **names;\n            FSFile *f;\n            int i;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset, \n                           \"wwh\", &fid, &newfid, &nwname))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f)\n                goto fid_not_found;\n            names = mallocz(sizeof(names[0]) * nwname);\n            qids = malloc(sizeof(qids[0]) * nwname);\n            for(i = 0; i < nwname; i++) {\n                if (unmarshall(s, queue_idx, desc_idx, &offset, \n                               \"s\", &names[i])) {\n                    err = -P9_EPROTO;\n                    goto walk_done;\n                }\n            }\n            err = fs->fs_walk(fs, &f, qids, f, nwname, names);\n        walk_done:\n            for(i = 0; i < nwname; i++) {\n                free(names[i]);\n            }\n            free(names);\n            if (err < 0) {\n                free(qids);\n                goto error;\n            }\n            buf_len = marshall(s, buf, sizeof(buf), \"h\", err);\n            for(i = 0; i < err; i++) {\n                buf_len += marshall(s, buf + buf_len, sizeof(buf) - buf_len,\n                                    \"Q\", &qids[i]);\n            }\n            free(qids);\n            fid_set(s, newfid, f);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 116: /* read */\n        {\n            uint32_t fid, count;\n            uint64_t offs;\n            uint8_t *buf;\n            int n;\n            FSFile *f;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wdw\", &fid, &offs, &count))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f)\n                goto fid_not_found;\n            buf = malloc(count + 4);\n            n = fs->fs_read(fs, f, offs, buf + 4, count);\n            if (n < 0) {\n                err = n;\n                free(buf);\n                goto error;\n            }\n            put_le32(buf, n);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, n + 4);\n            free(buf);\n        }\n        break;\n    case 118: /* write */\n        {\n            uint32_t fid, count;\n            uint64_t offs;\n            uint8_t *buf1;\n            int n;\n            FSFile *f;\n\n            if (unmarshall(s, queue_idx, desc_idx, &offset,\n                           \"wdw\", &fid, &offs, &count))\n                goto protocol_error;\n            f = fid_find(s, fid);\n            if (!f)\n                goto fid_not_found;\n            buf1 = malloc(count);\n            if (memcpy_from_queue(s1, buf1, queue_idx, desc_idx, offset,\n                                  count)) {\n                free(buf1);\n                goto protocol_error;\n            }\n            n = fs->fs_write(fs, f, offs, buf1, count);\n            free(buf1);\n            if (n < 0) {\n                err = n;\n                goto error;\n            }\n            buf_len = marshall(s, buf, sizeof(buf), \"w\", n);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, buf, buf_len);\n        }\n        break;\n    case 120: /* clunk */\n        {\n            uint32_t fid;\n            \n            if (unmarshall(s, queue_idx, desc_idx, &offset, \n                           \"w\", &fid))\n                goto protocol_error;\n            fid_delete(s, fid);\n            virtio_9p_send_reply(s, queue_idx, desc_idx, id, tag, NULL, 0);\n        }\n        break;\n    default:\n        printf(\"9p: unsupported operation id=%d\\n\", id);\n        goto protocol_error;\n    }\n    return 0;\n error:\n    virtio_9p_send_error(s, queue_idx, desc_idx, tag, err);\n    return 0;\n protocol_error:\n fid_not_found:\n    err = -P9_EPROTO;\n    goto error;\n}\n\nVIRTIODevice *virtio_9p_init(VIRTIOBusDef *bus, FSDevice *fs,\n                             const char *mount_tag)\n\n{\n    VIRTIO9PDevice *s;\n    int len;\n    uint8_t *cfg;\n\n    len = strlen(mount_tag);\n    s = mallocz(sizeof(*s));\n    virtio_init(&s->common, bus,\n                9, 2 + len, virtio_9p_recv_request);\n    s->common.device_features = 1 << 0;\n\n    /* set the mount tag */\n    cfg = s->common.config_space;\n    cfg[0] = len;\n    cfg[1] = len >> 8;\n    memcpy(cfg + 2, mount_tag, len);\n\n    s->fs = fs;\n    s->msize = 8192;\n    init_list_head(&s->fid_list);\n    \n    return (VIRTIODevice *)s;\n}\n\n"
  },
  {
    "path": "src/virtio.h",
    "content": "/*\n * VIRTIO driver\n * \n * Copyright (c) 2016 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#ifndef VIRTIO_H\n#define VIRTIO_H\n\n#include <sys/select.h>\n\n#include \"iomem.h\"\n#include \"pci.h\"\n\n#define VIRTIO_PAGE_SIZE 4096\n\n#if defined(EMSCRIPTEN)\n#define VIRTIO_ADDR_BITS 32\n#else\n#define VIRTIO_ADDR_BITS 64\n#endif\n\n#if VIRTIO_ADDR_BITS == 64\ntypedef uint64_t virtio_phys_addr_t;\n#else\ntypedef uint32_t virtio_phys_addr_t;\n#endif\n\ntypedef struct {\n    /* PCI only: */\n    PCIBus *pci_bus;\n    /* MMIO only: */\n    PhysMemoryMap *mem_map;\n    uint64_t addr;\n    IRQSignal *irq;\n} VIRTIOBusDef;\n\ntypedef struct VIRTIODevice VIRTIODevice; \n\n#define VIRTIO_DEBUG_IO (1 << 0)\n#define VIRTIO_DEBUG_9P (1 << 1)\n\nvoid virtio_set_debug(VIRTIODevice *s, int debug_flags);\n\n/* block device */\n\ntypedef void BlockDeviceCompletionFunc(void *opaque, int ret);\n\ntypedef struct BlockDevice BlockDevice;\n\nstruct BlockDevice {\n    int64_t (*get_sector_count)(BlockDevice *bs);\n    int (*read_async)(BlockDevice *bs,\n                      uint64_t sector_num, uint8_t *buf, int n,\n                      BlockDeviceCompletionFunc *cb, void *opaque);\n    int (*write_async)(BlockDevice *bs,\n                       uint64_t sector_num, const uint8_t *buf, int n,\n                       BlockDeviceCompletionFunc *cb, void *opaque);\n    void *opaque;\n};\n\nVIRTIODevice *virtio_block_init(VIRTIOBusDef *bus, BlockDevice *bs);\n\n/* network device */\n\ntypedef struct EthernetDevice EthernetDevice; \n\nstruct EthernetDevice {\n    uint8_t mac_addr[6]; /* mac address of the interface */\n    void (*write_packet)(EthernetDevice *net,\n                         const uint8_t *buf, int len);\n    void *opaque;\n#if !defined(EMSCRIPTEN)\n    void (*select_fill)(EthernetDevice *net, int *pfd_max,\n                        fd_set *rfds, fd_set *wfds, fd_set *efds,\n                        int *pdelay);\n    void (*select_poll)(EthernetDevice *net, \n                        fd_set *rfds, fd_set *wfds, fd_set *efds,\n                        int select_ret);\n#endif\n    /* the following is set by the device */\n    void *device_opaque;\n    BOOL (*device_can_write_packet)(EthernetDevice *net);\n    void (*device_write_packet)(EthernetDevice *net,\n                                const uint8_t *buf, int len);\n    void (*device_set_carrier)(EthernetDevice *net, BOOL carrier_state);\n};\n\nVIRTIODevice *virtio_net_init(VIRTIOBusDef *bus, EthernetDevice *es);\n\n/* console device */\n\ntypedef struct {\n    void *opaque;\n    void (*write_data)(void *opaque, const uint8_t *buf, int len);\n    int (*read_data)(void *opaque, uint8_t *buf, int len);\n} CharacterDevice;\n\nVIRTIODevice *virtio_console_init(VIRTIOBusDef *bus, CharacterDevice *cs);\nBOOL virtio_console_can_write_data(VIRTIODevice *s);\nint virtio_console_get_write_len(VIRTIODevice *s);\nint virtio_console_write_data(VIRTIODevice *s, const uint8_t *buf, int buf_len);\nvoid virtio_console_resize_event(VIRTIODevice *s, int width, int height);\n\n/* input device */\n\ntypedef enum {\n    VIRTIO_INPUT_TYPE_KEYBOARD,\n    VIRTIO_INPUT_TYPE_MOUSE,\n    VIRTIO_INPUT_TYPE_TABLET,\n} VirtioInputTypeEnum;\n\n#define VIRTIO_INPUT_ABS_SCALE 32768\n\nint virtio_input_send_key_event(VIRTIODevice *s, BOOL is_down,\n                                uint16_t key_code);\nint virtio_input_send_mouse_event(VIRTIODevice *s, int dx, int dy, int dz,\n                                  unsigned int buttons);\n\nVIRTIODevice *virtio_input_init(VIRTIOBusDef *bus, VirtioInputTypeEnum type);\n\n/* 9p filesystem device */\n\n#include \"fs.h\"\n\nVIRTIODevice *virtio_9p_init(VIRTIOBusDef *bus, FSDevice *fs,\n                             const char *mount_tag);\n\n#endif /* VIRTIO_H */\n"
  },
  {
    "path": "src/vmmouse.c",
    "content": "/*\n * VM mouse emulation\n * \n * Copyright (c) 2017 Fabrice Bellard\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include <assert.h>\n\n#include \"cutils.h\"\n#include \"iomem.h\"\n#include \"ps2.h\"\n\n#define VMPORT_MAGIC   0x564D5868\n\n#define REG_EAX 0\n#define REG_EBX 1\n#define REG_ECX 2\n#define REG_EDX 3\n#define REG_ESI 4\n#define REG_EDI 5\n\n#define FIFO_SIZE (4 * 16)\n\nstruct VMMouseState {\n    PS2MouseState *ps2_mouse;\n    int fifo_count, fifo_rindex, fifo_windex;\n    BOOL enabled;\n    BOOL absolute;\n    uint32_t fifo_buf[FIFO_SIZE];\n};\n\nstatic void put_queue(VMMouseState *s, uint32_t val)\n{\n    if (s->fifo_count >= FIFO_SIZE)\n        return;\n    s->fifo_buf[s->fifo_windex] = val;\n    if (++s->fifo_windex == FIFO_SIZE)\n        s->fifo_windex = 0;\n    s->fifo_count++;\n}\n\nstatic void read_data(VMMouseState *s, uint32_t *regs, int size)\n{\n    int i;\n    if (size > 6 || size > s->fifo_count) {\n        //        printf(\"vmmouse: read error req=%d count=%d\\n\", size, s->fifo_count);\n        s->enabled = FALSE;\n        return;\n    }\n    for(i = 0; i < size; i++) {\n        regs[i] = s->fifo_buf[s->fifo_rindex];\n        if (++s->fifo_rindex == FIFO_SIZE)\n            s->fifo_rindex = 0;\n    }\n    s->fifo_count -= size;\n}\n\nvoid vmmouse_send_mouse_event(VMMouseState *s, int x, int y, int dz,\n                              int buttons)\n{\n    int state;\n\n    if (!s->enabled) {\n        ps2_mouse_event(s->ps2_mouse, x, y, dz, buttons);\n        return;\n    }\n\n    if ((s->fifo_count + 4) > FIFO_SIZE)\n        return;\n\n    state = 0;\n    if (buttons & 1)\n        state |= 0x20;\n    if (buttons & 2)\n        state |= 0x10;\n    if (buttons & 4)\n        state |= 0x08;\n    if (s->absolute) {\n        /* range = 0 ... 65535 */\n        x *= 2; \n        y *= 2;\n    }\n\n    put_queue(s, state);\n    put_queue(s, x);\n    put_queue(s, y);\n    put_queue(s, -dz);\n\n    /* send PS/2 mouse event */\n    ps2_mouse_event(s->ps2_mouse, 1, 0, 0, 0);\n}\n\nvoid vmmouse_handler(VMMouseState *s, uint32_t *regs)\n{\n    uint32_t cmd;\n    \n    cmd = regs[REG_ECX] & 0xff;\n    switch(cmd) {\n    case 10: /* get version */\n        regs[REG_EBX] = VMPORT_MAGIC;\n        break;\n    case 39: /* VMMOUSE_DATA */\n        read_data(s, regs, regs[REG_EBX]);\n        break;\n    case 40: /* VMMOUSE_STATUS */\n        regs[REG_EAX] = ((s->enabled ? 0 : 0xffff) << 16) | s->fifo_count;\n        break;\n    case 41: /* VMMOUSE_COMMAND */\n        switch(regs[REG_EBX]) {\n        case 0x45414552: /* read id */\n            if (s->fifo_count < FIFO_SIZE) {\n                put_queue(s, 0x3442554a);\n                s->enabled = TRUE;\n            }\n            break;\n        case 0x000000f5: /* disable */\n            s->enabled = FALSE;\n            break;\n        case 0x4c455252: /* set relative */\n            s->absolute = 0;\n            break;\n        case 0x53424152: /* set absolute */\n            s->absolute = 1;\n            break;\n        }\n        break;\n    }\n}\n\nBOOL vmmouse_is_absolute(VMMouseState *s)\n{\n    return s->absolute;\n}\n\nVMMouseState *vmmouse_init(PS2MouseState *ps2_mouse)\n{\n    VMMouseState *s;\n    s = mallocz(sizeof(*s));\n    s->ps2_mouse = ps2_mouse;\n    return s;\n}\n"
  }
]